// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.

#include <map>

#include "include/base/cef_bind.h"
#include "include/cef_request.h"
#include "include/wrapper/cef_closure_task.h"
#include "tests/ceftests/test_handler.h"
#include "tests/ceftests/test_util.h"
#include "tests/gtest/include/gtest/gtest.h"
#include "tests/shared/renderer/client_app_renderer.h"

using client::ClientAppRenderer;

// Verify Set/Get methods for CefRequest, CefPostData and CefPostDataElement.
TEST(RequestTest, SetGet) {
  // CefRequest CreateRequest
  CefRefPtr<CefRequest> request(CefRequest::Create());
  EXPECT_TRUE(request.get() != nullptr);
  EXPECT_EQ(0U, request->GetIdentifier());

  CefString url = "http://tests.com/run.html";
  CefString method = "POST";
  CefRequest::HeaderMap setHeaders, getHeaders;
  setHeaders.insert(std::make_pair("HeaderA", "ValueA"));
  setHeaders.insert(std::make_pair("HeaderB", "ValueB"));

  // CefPostData CreatePostData
  CefRefPtr<CefPostData> postData(CefPostData::Create());
  EXPECT_TRUE(postData.get() != nullptr);

  // CefPostDataElement CreatePostDataElement
  CefRefPtr<CefPostDataElement> element1(CefPostDataElement::Create());
  EXPECT_TRUE(element1.get() != nullptr);
  CefRefPtr<CefPostDataElement> element2(CefPostDataElement::Create());
  EXPECT_TRUE(element2.get() != nullptr);

  // CefPostDataElement SetToFile
  CefString file = "c:\\path\\to\\file.ext";
  element1->SetToFile(file);
  EXPECT_EQ(PDE_TYPE_FILE, element1->GetType());
  EXPECT_EQ(file, element1->GetFile());

  // CefPostDataElement SetToBytes
  char bytes[] = "Test Bytes";
  element2->SetToBytes(sizeof(bytes), bytes);
  EXPECT_EQ(PDE_TYPE_BYTES, element2->GetType());
  EXPECT_EQ(sizeof(bytes), element2->GetBytesCount());
  char bytesOut[sizeof(bytes)];
  element2->GetBytes(sizeof(bytes), bytesOut);
  EXPECT_TRUE(!memcmp(bytes, bytesOut, sizeof(bytes)));

  // CefPostData AddElement
  postData->AddElement(element1);
  postData->AddElement(element2);
  EXPECT_EQ((size_t)2, postData->GetElementCount());

  // CefPostData RemoveElement
  postData->RemoveElement(element1);
  EXPECT_EQ((size_t)1, postData->GetElementCount());

  // CefPostData RemoveElements
  postData->RemoveElements();
  EXPECT_EQ((size_t)0, postData->GetElementCount());

  postData->AddElement(element1);
  postData->AddElement(element2);
  EXPECT_EQ((size_t)2, postData->GetElementCount());
  CefPostData::ElementVector elements;
  postData->GetElements(elements);
  CefPostData::ElementVector::const_iterator it = elements.begin();
  for (size_t i = 0; it != elements.end(); ++it, ++i) {
    if (i == 0)
      TestPostDataElementEqual(element1, (*it).get());
    else if (i == 1)
      TestPostDataElementEqual(element2, (*it).get());
  }

  // CefRequest SetURL
  request->SetURL(url);
  EXPECT_EQ(url, request->GetURL());

  // CefRequest SetMethod
  request->SetMethod(method);
  EXPECT_EQ(method, request->GetMethod());

  // CefRequest SetReferrer
  CefString referrer = "http://tests.com/referrer.html";
  CefRequest::ReferrerPolicy policy = REFERRER_POLICY_ORIGIN;
  request->SetReferrer(referrer, policy);
  EXPECT_STREQ("http://tests.com/",
               request->GetReferrerURL().ToString().c_str());
  EXPECT_EQ(policy, request->GetReferrerPolicy());

  // CefRequest SetHeaderMap
  request->SetHeaderMap(setHeaders);
  request->GetHeaderMap(getHeaders);
  TestMapEqual(setHeaders, getHeaders, false);
  getHeaders.clear();

  // CefRequest SetPostData
  request->SetPostData(postData);
  TestPostDataEqual(postData, request->GetPostData());

  EXPECT_EQ(0U, request->GetIdentifier());

  request = CefRequest::Create();
  EXPECT_TRUE(request.get() != nullptr);
  EXPECT_EQ(0U, request->GetIdentifier());

  // CefRequest Set
  request->Set(url, method, postData, setHeaders);
  EXPECT_EQ(0U, request->GetIdentifier());
  EXPECT_EQ(url, request->GetURL());
  EXPECT_EQ(method, request->GetMethod());
  request->GetHeaderMap(getHeaders);
  TestMapEqual(setHeaders, getHeaders, false);
  getHeaders.clear();
  TestPostDataEqual(postData, request->GetPostData());
}

TEST(RequestTest, SetGetHeaderByName) {
  CefRefPtr<CefRequest> request(CefRequest::Create());
  EXPECT_TRUE(request.get() != nullptr);

  CefRequest::HeaderMap headers, expectedHeaders;

  request->SetHeaderByName("HeaderA", "ValueA", false);
  request->SetHeaderByName("HeaderB", "ValueB", false);

  expectedHeaders.insert(std::make_pair("HeaderA", "ValueA"));
  expectedHeaders.insert(std::make_pair("HeaderB", "ValueB"));

  // Case insensitive retrieval.
  EXPECT_STREQ("ValueA",
               request->GetHeaderByName("headera").ToString().c_str());
  EXPECT_STREQ("ValueB",
               request->GetHeaderByName("headerb").ToString().c_str());
  EXPECT_STREQ("", request->GetHeaderByName("noexist").ToString().c_str());

  request->GetHeaderMap(headers);
  TestMapEqual(expectedHeaders, headers, false);

  // Replace an existing value.
  request->SetHeaderByName("HeaderA", "ValueANew", true);

  expectedHeaders.clear();
  expectedHeaders.insert(std::make_pair("HeaderA", "ValueANew"));
  expectedHeaders.insert(std::make_pair("HeaderB", "ValueB"));

  // Case insensitive retrieval.
  EXPECT_STREQ("ValueANew",
               request->GetHeaderByName("headerA").ToString().c_str());

  request->GetHeaderMap(headers);
  TestMapEqual(expectedHeaders, headers, false);

  // Header with multiple values.
  expectedHeaders.clear();
  expectedHeaders.insert(std::make_pair("HeaderA", "ValueA1"));
  expectedHeaders.insert(std::make_pair("HeaderA", "ValueA2"));
  expectedHeaders.insert(std::make_pair("HeaderB", "ValueB"));
  request->SetHeaderMap(expectedHeaders);

  // When there are multiple values only the first is returned.
  EXPECT_STREQ("ValueA1",
               request->GetHeaderByName("headera").ToString().c_str());

  // Don't overwrite the value.
  request->SetHeaderByName("HeaderA", "ValueANew", false);

  request->GetHeaderMap(headers);
  TestMapEqual(expectedHeaders, headers, false);

  // Overwrite the value (remove the duplicates).
  request->SetHeaderByName("HeaderA", "ValueANew", true);

  expectedHeaders.clear();
  expectedHeaders.insert(std::make_pair("HeaderA", "ValueANew"));
  expectedHeaders.insert(std::make_pair("HeaderB", "ValueB"));

  request->GetHeaderMap(headers);
  TestMapEqual(expectedHeaders, headers, false);
}

namespace {

const char kTestUrl[] = "http://tests.com/run.html";

void CreateRequest(CefRefPtr<CefRequest>& request) {
  request = CefRequest::Create();
  EXPECT_TRUE(request.get() != nullptr);

  request->SetURL(kTestUrl);
  request->SetMethod("POST");

  request->SetReferrer("http://tests.com/main.html", REFERRER_POLICY_DEFAULT);

  CefRequest::HeaderMap headers;
  headers.insert(std::make_pair("HeaderA", "ValueA"));
  headers.insert(std::make_pair("HeaderB", "ValueB"));
  request->SetHeaderMap(headers);

  CefRefPtr<CefPostData> postData(CefPostData::Create());
  EXPECT_TRUE(postData.get() != nullptr);

  CefRefPtr<CefPostDataElement> element1(CefPostDataElement::Create());
  EXPECT_TRUE(element1.get() != nullptr);
  char bytes[] = "Test Bytes";
  element1->SetToBytes(sizeof(bytes), bytes);
  postData->AddElement(element1);

  request->SetPostData(postData);
}

class RequestSendRecvTestHandler : public TestHandler {
 public:
  RequestSendRecvTestHandler() : response_length_(0), request_id_(0U) {}

  void RunTest() override {
    // Create the test request.
    CreateRequest(request_);

    const std::string& resource = "<html><body>SendRecv Test</body></html>";
    response_length_ = static_cast<int64>(resource.size());
    AddResource(kTestUrl, resource, "text/html");

    // Create the browser.
    CreateBrowser("about:blank");

    // Time out the test after a reasonable period of time.
    SetTestTimeout();
  }

  void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
    TestHandler::OnAfterCreated(browser);

    // Load the test request.
    browser->GetMainFrame()->LoadRequest(request_);
  }

  cef_return_value_t OnBeforeResourceLoad(
      CefRefPtr<CefBrowser> browser,
      CefRefPtr<CefFrame> frame,
      CefRefPtr<CefRequest> request,
      CefRefPtr<CefRequestCallback> callback) override {
    EXPECT_IO_THREAD();

    request_id_ = request->GetIdentifier();
    DCHECK_GT(request_id_, 0U);

    TestRequest(request);
    EXPECT_FALSE(request->IsReadOnly());

    got_before_resource_load_.yes();

    return RV_CONTINUE;
  }

  CefRefPtr<CefResourceHandler> GetResourceHandler(
      CefRefPtr<CefBrowser> browser,
      CefRefPtr<CefFrame> frame,
      CefRefPtr<CefRequest> request) override {
    EXPECT_IO_THREAD();

    TestRequest(request);
    EXPECT_TRUE(request->IsReadOnly());

    got_resource_handler_.yes();

    return TestHandler::GetResourceHandler(browser, frame, request);
  }

  bool OnResourceResponse(CefRefPtr<CefBrowser> browser,
                          CefRefPtr<CefFrame> frame,
                          CefRefPtr<CefRequest> request,
                          CefRefPtr<CefResponse> response) override {
    EXPECT_IO_THREAD();

    TestRequest(request);
    EXPECT_FALSE(request->IsReadOnly());
    TestResponse(response);
    EXPECT_TRUE(response->IsReadOnly());

    got_resource_response_.yes();

    return false;
  }

  CefRefPtr<CefResponseFilter> GetResourceResponseFilter(
      CefRefPtr<CefBrowser> browser,
      CefRefPtr<CefFrame> frame,
      CefRefPtr<CefRequest> request,
      CefRefPtr<CefResponse> response) override {
    EXPECT_IO_THREAD();

    TestRequest(request);
    EXPECT_TRUE(request->IsReadOnly());
    TestResponse(response);
    EXPECT_TRUE(response->IsReadOnly());

    got_resource_response_filter_.yes();
    return nullptr;
  }

  void OnResourceLoadComplete(CefRefPtr<CefBrowser> browser,
                              CefRefPtr<CefFrame> frame,
                              CefRefPtr<CefRequest> request,
                              CefRefPtr<CefResponse> response,
                              URLRequestStatus status,
                              int64 received_content_length) override {
    EXPECT_IO_THREAD();

    TestRequest(request);
    EXPECT_TRUE(request->IsReadOnly());
    TestResponse(response);
    EXPECT_TRUE(response->IsReadOnly());
    EXPECT_EQ(UR_SUCCESS, status);
    EXPECT_EQ(response_length_, received_content_length);

    got_resource_load_complete_.yes();

    DestroyTest();
  }

 private:
  void TestRequest(CefRefPtr<CefRequest> request) {
    TestRequestEqual(request_, request, true);
    EXPECT_EQ(request_id_, request->GetIdentifier());
    EXPECT_EQ(RT_MAIN_FRAME, request->GetResourceType());
    EXPECT_EQ(TT_FORM_SUBMIT, request->GetTransitionType());
  }

  void TestResponse(CefRefPtr<CefResponse> response) {
    EXPECT_EQ(200, response->GetStatus());
    EXPECT_STREQ("OK", response->GetStatusText().ToString().c_str());
    EXPECT_STREQ("text/html", response->GetMimeType().ToString().c_str());
  }

  void DestroyTest() override {
    EXPECT_TRUE(got_before_resource_load_);
    EXPECT_TRUE(got_resource_handler_);
    EXPECT_TRUE(got_resource_response_);
    EXPECT_TRUE(got_resource_response_filter_);
    EXPECT_TRUE(got_resource_load_complete_);

    TestHandler::DestroyTest();
  }

  CefRefPtr<CefRequest> request_;
  int64 response_length_;
  uint64 request_id_;

  TrackCallback got_before_resource_load_;
  TrackCallback got_resource_handler_;
  TrackCallback got_resource_response_;
  TrackCallback got_resource_response_filter_;
  TrackCallback got_resource_load_complete_;

  IMPLEMENT_REFCOUNTING(RequestSendRecvTestHandler);
};

}  // namespace

// Verify send and recieve
TEST(RequestTest, SendRecv) {
  CefRefPtr<RequestSendRecvTestHandler> handler =
      new RequestSendRecvTestHandler();
  handler->ExecuteTest();
  ReleaseAndWaitForDestructor(handler);
}

namespace {

const char kTypeTestOrigin[] = "http://tests-requesttt.com/";
const cef_transition_type_t kTransitionExplicitLoad =
    static_cast<cef_transition_type_t>(TT_EXPLICIT | TT_DIRECT_LOAD_FLAG);

static struct TypeExpected {
  const char* file;
  bool navigation;  // True if this expectation represents a navigation.
  cef_transition_type_t transition_type;
  cef_resource_type_t resource_type;
  int expected_count;
} g_type_expected[] = {
    // Initial main frame load due to browser creation.
    {"main.html", true, kTransitionExplicitLoad, RT_MAIN_FRAME, 1},

    // Sub frame load.
    {"sub.html", true, TT_AUTO_SUBFRAME, RT_SUB_FRAME, 1},

    // Stylesheet load.
    {"style.css", false, TT_LINK, RT_STYLESHEET, 1},

    // Script load.
    {"script.js", false, TT_LINK, RT_SCRIPT, 1},

    // Image load.
    {"image.png", false, TT_LINK, RT_IMAGE, 1},

    // Font load.
    {"font.ttf", false, TT_LINK, RT_FONT_RESOURCE, 1},

    // XHR load.
    {"xhr.html", false, TT_LINK, RT_XHR, 1},
};

class TypeExpectations {
 public:
  explicit TypeExpectations(bool navigation) : navigation_(navigation) {
    // Build the map of relevant requests.
    for (int i = 0;
         i < static_cast<int>(sizeof(g_type_expected) / sizeof(TypeExpected));
         ++i) {
      if (navigation_ && g_type_expected[i].navigation != navigation_)
        continue;

      request_count_.insert(std::make_pair(i, 0));
    }
  }

  // Notify that a request has been received. Returns true if the request is
  // something we care about.
  bool GotRequest(CefRefPtr<CefRequest> request) {
    const std::string& url = request->GetURL();
    if (url.find(kTypeTestOrigin) != 0)
      return false;

    const std::string& file = url.substr(sizeof(kTypeTestOrigin) - 1);
    cef_transition_type_t transition_type = request->GetTransitionType();
    cef_resource_type_t resource_type = request->GetResourceType();

    const int index = GetExpectedIndex(file, transition_type, resource_type);
    EXPECT_GE(index, 0) << "File: " << file.c_str()
                        << "; Navigation: " << navigation_
                        << "; Transition Type: " << transition_type
                        << "; Resource Type: " << resource_type;

    RequestCount::iterator it = request_count_.find(index);
    EXPECT_TRUE(it != request_count_.end());

    const int actual_count = ++it->second;
    const int expected_count = g_type_expected[index].expected_count;
    EXPECT_LE(actual_count, expected_count)
        << "File: " << file.c_str() << "; Navigation: " << navigation_
        << "; Transition Type: " << transition_type
        << "; Resource Type: " << resource_type;

    return true;
  }

  // Test if all expectations have been met.
  bool IsDone(bool assert) {
    for (int i = 0;
         i < static_cast<int>(sizeof(g_type_expected) / sizeof(TypeExpected));
         ++i) {
      if (navigation_ && g_type_expected[i].navigation != navigation_)
        continue;

      RequestCount::const_iterator it = request_count_.find(i);
      EXPECT_TRUE(it != request_count_.end());
      if (it->second != g_type_expected[i].expected_count) {
        if (assert) {
          EXPECT_EQ(g_type_expected[i].expected_count, it->second)
              << "File: " << g_type_expected[i].file
              << "; Navigation: " << navigation_
              << "; Transition Type: " << g_type_expected[i].transition_type
              << "; Resource Type: " << g_type_expected[i].resource_type;
        }
        return false;
      }
    }
    return true;
  }

 private:
  // Returns the index for the specified navigation.
  int GetExpectedIndex(const std::string& file,
                       cef_transition_type_t transition_type,
                       cef_resource_type_t resource_type) {
    for (int i = 0;
         i < static_cast<int>(sizeof(g_type_expected) / sizeof(TypeExpected));
         ++i) {
      if (g_type_expected[i].file == file &&
          (!navigation_ || g_type_expected[i].navigation == navigation_) &&
          g_type_expected[i].transition_type == transition_type &&
          g_type_expected[i].resource_type == resource_type) {
        return i;
      }
    }
    return -1;
  }

  bool navigation_;

  // Map of TypeExpected index to actual request count.
  typedef std::map<int, int> RequestCount;
  RequestCount request_count_;
};

// Browser side.
class TypeTestHandler : public TestHandler {
 public:
  TypeTestHandler()
      : browse_expectations_(true),
        load_expectations_(false),
        get_expectations_(false),
        completed_browser_side_(false),
        destroyed_(false) {}

  void RunTest() override {
    AddResource(std::string(kTypeTestOrigin) + "main.html",
                "<html>"
                "<head>"
                "<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">"
                "<script type=\"text/javascript\" src=\"script.js\"></script>"
                "</head>"
                "<body><p>Main</p>"
                "<script>xhr = new XMLHttpRequest();"
                "xhr.open('GET', 'xhr.html', false);"
                "xhr.send();</script>"
                "<iframe src=\"sub.html\"></iframe>"
                "<img src=\"image.png\">"
                "</body></html>",
                "text/html");
    AddResource(std::string(kTypeTestOrigin) + "sub.html", "<html>Sub</html>",
                "text/html");
    AddResource(std::string(kTypeTestOrigin) + "style.css",
                "@font-face {"
                "  font-family: custom_font;"
                "  src: url('font.ttf');"
                "}"
                "p {"
                "  font-family: custom_font;"
                "}",
                "text/css");
    AddResource(std::string(kTypeTestOrigin) + "script.js", "<!-- -->",
                "text/javascript");
    AddResource(std::string(kTypeTestOrigin) + "image.png", "<!-- -->",
                "image/png");
    AddResource(std::string(kTypeTestOrigin) + "font.ttf", "<!-- -->",
                "font/ttf");
    AddResource(std::string(kTypeTestOrigin) + "xhr.html", "<html>XHR</html>",
                "text/html");
    AddResource(std::string(kTypeTestOrigin) + "fetch.html",
                "<html>Fetch</html>", "text/html");

    CreateBrowser(std::string(kTypeTestOrigin) + "main.html");

    // Time out the test after a reasonable period of time.
    SetTestTimeout();
  }

  bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
                      CefRefPtr<CefFrame> frame,
                      CefRefPtr<CefRequest> request,
                      bool user_gesture,
                      bool is_redirect) override {
    browse_expectations_.GotRequest(request);

    return false;
  }

  cef_return_value_t OnBeforeResourceLoad(
      CefRefPtr<CefBrowser> browser,
      CefRefPtr<CefFrame> frame,
      CefRefPtr<CefRequest> request,
      CefRefPtr<CefRequestCallback> callback) override {
    load_expectations_.GotRequest(request);

    return RV_CONTINUE;
  }

  CefRefPtr<CefResourceHandler> GetResourceHandler(
      CefRefPtr<CefBrowser> browser,
      CefRefPtr<CefFrame> frame,
      CefRefPtr<CefRequest> request) override {
    if (get_expectations_.GotRequest(request) &&
        get_expectations_.IsDone(false)) {
      completed_browser_side_ = true;
      // Destroy the test on the UI thread.
      CefPostTask(TID_UI, base::Bind(&TypeTestHandler::DestroyTest, this));
    }

    return TestHandler::GetResourceHandler(browser, frame, request);
  }

 private:
  void DestroyTest() override {
    if (destroyed_)
      return;
    destroyed_ = true;

    // Verify test expectations.
    EXPECT_TRUE(completed_browser_side_);
    EXPECT_TRUE(browse_expectations_.IsDone(true));
    EXPECT_TRUE(load_expectations_.IsDone(true));
    EXPECT_TRUE(get_expectations_.IsDone(true));

    TestHandler::DestroyTest();
  }

  TypeExpectations browse_expectations_;
  TypeExpectations load_expectations_;
  TypeExpectations get_expectations_;

  bool completed_browser_side_;
  bool destroyed_;

  IMPLEMENT_REFCOUNTING(TypeTestHandler);
};

}  // namespace

// Verify the order of navigation-related callbacks.
TEST(RequestTest, ResourceAndTransitionType) {
  CefRefPtr<TypeTestHandler> handler = new TypeTestHandler();
  handler->ExecuteTest();
  ReleaseAndWaitForDestructor(handler);
}
