mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
@@ -186,6 +186,8 @@
|
|||||||
'tests/shared/common/client_app_other.h',
|
'tests/shared/common/client_app_other.h',
|
||||||
'tests/shared/common/client_switches.cc',
|
'tests/shared/common/client_switches.cc',
|
||||||
'tests/shared/common/client_switches.h',
|
'tests/shared/common/client_switches.h',
|
||||||
|
'tests/shared/common/string_util.cc',
|
||||||
|
'tests/shared/common/string_util.h',
|
||||||
],
|
],
|
||||||
'shared_sources_renderer': [
|
'shared_sources_renderer': [
|
||||||
'tests/shared/renderer/client_app_renderer.cc',
|
'tests/shared/renderer/client_app_renderer.cc',
|
||||||
@@ -476,6 +478,7 @@
|
|||||||
'tests/ceftests/file_util_unittest.cc',
|
'tests/ceftests/file_util_unittest.cc',
|
||||||
'tests/ceftests/frame_handler_unittest.cc',
|
'tests/ceftests/frame_handler_unittest.cc',
|
||||||
'tests/ceftests/frame_unittest.cc',
|
'tests/ceftests/frame_unittest.cc',
|
||||||
|
'tests/ceftests/hsts_redirect_unittest.cc',
|
||||||
'tests/ceftests/image_unittest.cc',
|
'tests/ceftests/image_unittest.cc',
|
||||||
'tests/ceftests/image_util.cc',
|
'tests/ceftests/image_util.cc',
|
||||||
'tests/ceftests/image_util.h',
|
'tests/ceftests/image_util.h',
|
||||||
|
@@ -184,6 +184,13 @@ class CefTestServerImpl::Context {
|
|||||||
test_server_->RegisterRequestHandler(
|
test_server_->RegisterRequestHandler(
|
||||||
base::BindRepeating(&Context::HandleRequest, base::Unretained(this)));
|
base::BindRepeating(&Context::HandleRequest, base::Unretained(this)));
|
||||||
|
|
||||||
|
if (https_server) {
|
||||||
|
// Use a "localhost" domain certificate instead of IP address. This is
|
||||||
|
// required for HSTS tests (see https://crbug.com/456712).
|
||||||
|
test_server_->SetSSLConfig(
|
||||||
|
EmbeddedTestServer::CERT_COMMON_NAME_IS_DOMAIN);
|
||||||
|
}
|
||||||
|
|
||||||
test_server_handle_ =
|
test_server_handle_ =
|
||||||
test_server_->StartAndReturnHandle(static_cast<int>(port));
|
test_server_->StartAndReturnHandle(static_cast<int>(port));
|
||||||
if (!test_server_handle_) {
|
if (!test_server_handle_) {
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
#include "tests/shared/browser/resource_util.h"
|
#include "tests/shared/browser/resource_util.h"
|
||||||
#include "tests/shared/common/binary_value_utils.h"
|
#include "tests/shared/common/binary_value_utils.h"
|
||||||
#include "tests/shared/common/client_switches.h"
|
#include "tests/shared/common/client_switches.h"
|
||||||
|
#include "tests/shared/common/string_util.h"
|
||||||
|
|
||||||
namespace client {
|
namespace client {
|
||||||
|
|
||||||
@@ -1047,12 +1048,9 @@ void ClientHandler::OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
|
|||||||
if (url.empty())
|
if (url.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::string start_url = startup_url_;
|
|
||||||
|
|
||||||
// Convert URLs to lowercase for easier comparison.
|
// Convert URLs to lowercase for easier comparison.
|
||||||
std::transform(url.begin(), url.end(), url.begin(), tolower);
|
url = AsciiStrToLower(url);
|
||||||
std::transform(start_url.begin(), start_url.end(), start_url.begin(),
|
const std::string& start_url = AsciiStrToLower(startup_url_);
|
||||||
tolower);
|
|
||||||
|
|
||||||
// Don't reload the URL that just resulted in termination.
|
// Don't reload the URL that just resulted in termination.
|
||||||
if (url.find(start_url) == 0)
|
if (url.find(start_url) == 0)
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "tests/shared/browser/file_util.h"
|
#include "tests/shared/browser/file_util.h"
|
||||||
#include "tests/shared/browser/resource_util.h"
|
#include "tests/shared/browser/resource_util.h"
|
||||||
|
#include "tests/shared/common/string_util.h"
|
||||||
|
|
||||||
namespace client {
|
namespace client {
|
||||||
|
|
||||||
@@ -158,7 +159,7 @@ ImageCache::ImageType ImageCache::GetImageType(const std::string& path) {
|
|||||||
if (ext.empty())
|
if (ext.empty())
|
||||||
return TYPE_NONE;
|
return TYPE_NONE;
|
||||||
|
|
||||||
std::transform(ext.begin(), ext.end(), ext.begin(), tolower);
|
ext = AsciiStrToLower(ext);
|
||||||
if (ext == "png")
|
if (ext == "png")
|
||||||
return TYPE_PNG;
|
return TYPE_PNG;
|
||||||
if (ext == "jpg" || ext == "jpeg")
|
if (ext == "jpg" || ext == "jpeg")
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
#include "include/cef_parser.h"
|
#include "include/cef_parser.h"
|
||||||
#include "tests/shared/browser/client_app_browser.h"
|
#include "tests/shared/browser/client_app_browser.h"
|
||||||
#include "tests/shared/common/client_switches.h"
|
#include "tests/shared/common/client_switches.h"
|
||||||
|
#include "tests/shared/common/string_util.h"
|
||||||
|
|
||||||
namespace client {
|
namespace client {
|
||||||
|
|
||||||
@@ -19,10 +20,7 @@ const char kDefaultUrl[] = "http://www.google.com";
|
|||||||
|
|
||||||
// Returns the ARGB value for |color|.
|
// Returns the ARGB value for |color|.
|
||||||
cef_color_t ParseColor(const std::string& color) {
|
cef_color_t ParseColor(const std::string& color) {
|
||||||
std::string colorToLower;
|
const std::string& colorToLower = AsciiStrToLower(color);
|
||||||
colorToLower.resize(color.size());
|
|
||||||
std::transform(color.begin(), color.end(), colorToLower.begin(), ::tolower);
|
|
||||||
|
|
||||||
if (colorToLower == "black")
|
if (colorToLower == "black")
|
||||||
return CefColorSetARGB(255, 0, 0, 0);
|
return CefColorSetARGB(255, 0, 0, 0);
|
||||||
else if (colorToLower == "blue")
|
else if (colorToLower == "blue")
|
||||||
|
@@ -29,6 +29,7 @@
|
|||||||
#include "tests/cefclient/browser/urlrequest_test.h"
|
#include "tests/cefclient/browser/urlrequest_test.h"
|
||||||
#include "tests/cefclient/browser/window_test.h"
|
#include "tests/cefclient/browser/window_test.h"
|
||||||
#include "tests/shared/browser/resource_util.h"
|
#include "tests/shared/browser/resource_util.h"
|
||||||
|
#include "tests/shared/common/string_util.h"
|
||||||
|
|
||||||
namespace client {
|
namespace client {
|
||||||
namespace test_runner {
|
namespace test_runner {
|
||||||
@@ -54,31 +55,13 @@ void LoadStringResourcePage(CefRefPtr<CefBrowser> browser,
|
|||||||
browser->GetMainFrame()->LoadURL(kTestOrigin + page);
|
browser->GetMainFrame()->LoadURL(kTestOrigin + page);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace all instances of |from| with |to| in |str|.
|
|
||||||
std::string StringReplace(const std::string& str,
|
|
||||||
const std::string& from,
|
|
||||||
const std::string& to) {
|
|
||||||
std::string result = str;
|
|
||||||
std::string::size_type pos = 0;
|
|
||||||
std::string::size_type from_len = from.length();
|
|
||||||
std::string::size_type to_len = to.length();
|
|
||||||
do {
|
|
||||||
pos = result.find(from, pos);
|
|
||||||
if (pos != std::string::npos) {
|
|
||||||
result.replace(pos, from_len, to);
|
|
||||||
pos += to_len;
|
|
||||||
}
|
|
||||||
} while (pos != std::string::npos);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RunGetSourceTest(CefRefPtr<CefBrowser> browser) {
|
void RunGetSourceTest(CefRefPtr<CefBrowser> browser) {
|
||||||
class Visitor : public CefStringVisitor {
|
class Visitor : public CefStringVisitor {
|
||||||
public:
|
public:
|
||||||
explicit Visitor(CefRefPtr<CefBrowser> browser) : browser_(browser) {}
|
explicit Visitor(CefRefPtr<CefBrowser> browser) : browser_(browser) {}
|
||||||
virtual void Visit(const CefString& string) override {
|
virtual void Visit(const CefString& string) override {
|
||||||
std::string source = StringReplace(string, "<", "<");
|
std::string source = AsciiStrReplace(string, "<", "<");
|
||||||
source = StringReplace(source, ">", ">");
|
source = AsciiStrReplace(source, ">", ">");
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "<html><body bgcolor=\"white\">Source:<pre>" << source
|
ss << "<html><body bgcolor=\"white\">Source:<pre>" << source
|
||||||
<< "</pre></body></html>";
|
<< "</pre></body></html>";
|
||||||
@@ -98,8 +81,8 @@ void RunGetTextTest(CefRefPtr<CefBrowser> browser) {
|
|||||||
public:
|
public:
|
||||||
explicit Visitor(CefRefPtr<CefBrowser> browser) : browser_(browser) {}
|
explicit Visitor(CefRefPtr<CefBrowser> browser) : browser_(browser) {}
|
||||||
virtual void Visit(const CefString& string) override {
|
virtual void Visit(const CefString& string) override {
|
||||||
std::string text = StringReplace(string, "<", "<");
|
std::string text = AsciiStrReplace(string, "<", "<");
|
||||||
text = StringReplace(text, ">", ">");
|
text = AsciiStrReplace(text, ">", ">");
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "<html><body bgcolor=\"white\">Text:<pre>" << text
|
ss << "<html><body bgcolor=\"white\">Text:<pre>" << text
|
||||||
<< "</pre></body></html>";
|
<< "</pre></body></html>";
|
||||||
@@ -649,8 +632,7 @@ CefRefPtr<CefStreamReader> GetDumpResponse(
|
|||||||
|
|
||||||
CefRequest::HeaderMap::const_iterator it = requestMap.begin();
|
CefRequest::HeaderMap::const_iterator it = requestMap.begin();
|
||||||
for (; it != requestMap.end(); ++it) {
|
for (; it != requestMap.end(); ++it) {
|
||||||
std::string key = it->first;
|
const std::string& key = AsciiStrToLower(it->first);
|
||||||
std::transform(key.begin(), key.end(), key.begin(), ::tolower);
|
|
||||||
if (key == "origin") {
|
if (key == "origin") {
|
||||||
origin = it->second;
|
origin = it->second;
|
||||||
break;
|
break;
|
||||||
@@ -801,8 +783,8 @@ void Alert(CefRefPtr<CefBrowser> browser, const std::string& message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Escape special characters in the message.
|
// Escape special characters in the message.
|
||||||
std::string msg = StringReplace(message, "\\", "\\\\");
|
std::string msg = AsciiStrReplace(message, "\\", "\\\\");
|
||||||
msg = StringReplace(msg, "'", "\\'");
|
msg = AsciiStrReplace(msg, "'", "\\'");
|
||||||
|
|
||||||
// Execute a JavaScript alert().
|
// Execute a JavaScript alert().
|
||||||
CefRefPtr<CefFrame> frame = browser->GetMainFrame();
|
CefRefPtr<CefFrame> frame = browser->GetMainFrame();
|
||||||
|
@@ -21,6 +21,7 @@
|
|||||||
#include "tests/ceftests/test_suite.h"
|
#include "tests/ceftests/test_suite.h"
|
||||||
#include "tests/ceftests/test_util.h"
|
#include "tests/ceftests/test_util.h"
|
||||||
#include "tests/gtest/include/gtest/gtest.h"
|
#include "tests/gtest/include/gtest/gtest.h"
|
||||||
|
#include "tests/shared/common/string_util.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@@ -1113,7 +1114,7 @@ class CookieAccessResponseHandler {
|
|||||||
std::string GetHeaderValue(const CefServer::HeaderMap& header_map,
|
std::string GetHeaderValue(const CefServer::HeaderMap& header_map,
|
||||||
const std::string& header_name_lower) {
|
const std::string& header_name_lower) {
|
||||||
for (const auto& [name, value] : header_map) {
|
for (const auto& [name, value] : header_map) {
|
||||||
if (AsciiStrToLower(name) == header_name_lower) {
|
if (client::AsciiStrToLower(name) == header_name_lower) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
312
tests/ceftests/hsts_redirect_unittest.cc
Normal file
312
tests/ceftests/hsts_redirect_unittest.cc
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
// Copyright (c) 2022 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 "include/base/cef_callback.h"
|
||||||
|
#include "include/wrapper/cef_closure_task.h"
|
||||||
|
#include "tests/ceftests/test_handler.h"
|
||||||
|
#include "tests/ceftests/test_server.h"
|
||||||
|
#include "tests/ceftests/test_server_observer.h"
|
||||||
|
#include "tests/gtest/include/gtest/gtest.h"
|
||||||
|
#include "tests/shared/common/string_util.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Set the "Strict-Transport-Security" header on an HTTPS response to enable
|
||||||
|
// HSTS redirects for follow-up HTTP requests to the same origin. See
|
||||||
|
// https://www.chromium.org/hsts/.
|
||||||
|
//
|
||||||
|
// HSTS is implemented in the network service so real servers are required to
|
||||||
|
// test the redirect behavior. It also requires a "localhost" domain certificate
|
||||||
|
// instead of IP address (see https://crbug.com/456712). See additional comments
|
||||||
|
// in OnResourceRedirect about redirect behavior with non-standard port numbers.
|
||||||
|
//
|
||||||
|
// The test works as follows:
|
||||||
|
// 1. Start HTTP and HTTPS servers.
|
||||||
|
// 2. Load an HTTP URL that redirects to an HTTPS URL.
|
||||||
|
// 3. Set the "Strict-Transport-Security" header in response to the first HTTPS
|
||||||
|
// request.
|
||||||
|
// 4. Load the same HTTP URL additional times to trigger the internal HTTP to
|
||||||
|
// HTTPS redirect.
|
||||||
|
|
||||||
|
// Number of times to load the same HTTP URL. Must be > 1.
|
||||||
|
constexpr size_t kHSTSLoadCount = 3;
|
||||||
|
|
||||||
|
constexpr char kHSTSURLPath[] = "/index.html";
|
||||||
|
|
||||||
|
// Used to observe HTTP and HTTPS server requests.
|
||||||
|
class HSTSTestServerObserver : public test_server::ObserverHelper {
|
||||||
|
public:
|
||||||
|
using ReadyCallback = base::OnceCallback<void(const std::string& url)>;
|
||||||
|
|
||||||
|
HSTSTestServerObserver(bool https_server,
|
||||||
|
size_t& nav_ct,
|
||||||
|
TrackCallback (&got_request)[kHSTSLoadCount],
|
||||||
|
ReadyCallback ready_callback,
|
||||||
|
base::OnceClosure done_callback)
|
||||||
|
: https_server_(https_server),
|
||||||
|
nav_ct_(nav_ct),
|
||||||
|
got_request_(got_request),
|
||||||
|
ready_callback_(std::move(ready_callback)),
|
||||||
|
done_callback_(std::move(done_callback)) {
|
||||||
|
Initialize(https_server);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnInitialized(const std::string& server_origin) override {
|
||||||
|
EXPECT_UI_THREAD();
|
||||||
|
|
||||||
|
origin_ = ToLocalhostOrigin(server_origin);
|
||||||
|
url_ = origin_ + kHSTSURLPath;
|
||||||
|
|
||||||
|
std::move(ready_callback_).Run(url_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnShutdown() override {
|
||||||
|
EXPECT_UI_THREAD();
|
||||||
|
std::move(done_callback_).Run();
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OnTestServerRequest(CefRefPtr<CefRequest> request,
|
||||||
|
const ResponseCallback& response_callback) override {
|
||||||
|
EXPECT_UI_THREAD();
|
||||||
|
|
||||||
|
// At most 1 request per load.
|
||||||
|
EXPECT_FALSE(got_request_[nav_ct_]) << nav_ct_;
|
||||||
|
got_request_[nav_ct_].yes();
|
||||||
|
|
||||||
|
const std::string& url = ToLocalhostOrigin(request->GetURL());
|
||||||
|
|
||||||
|
auto response = CefResponse::Create();
|
||||||
|
response->SetMimeType("text/html");
|
||||||
|
std::string response_body;
|
||||||
|
|
||||||
|
if (!https_server_) {
|
||||||
|
// Redirect to the HTTPS URL.
|
||||||
|
EXPECT_STREQ(url_.c_str(), url.c_str()) << nav_ct_;
|
||||||
|
response->SetStatus(301); // Permanent Redirect
|
||||||
|
response->SetHeaderByName("Location",
|
||||||
|
GetLocalhostURL(/*https_server=*/true),
|
||||||
|
/*overwrite=*/true);
|
||||||
|
} else {
|
||||||
|
// Normal response after an HTTP to HTTPS redirect.
|
||||||
|
EXPECT_STREQ(url_.c_str(), url.c_str()) << nav_ct_;
|
||||||
|
response->SetStatus(200);
|
||||||
|
|
||||||
|
if (nav_ct_ == 0) {
|
||||||
|
// Set the "Strict-Transport-Security" header in response to the first
|
||||||
|
// HTTPS request.
|
||||||
|
response->SetHeaderByName("Strict-Transport-Security",
|
||||||
|
"max-age=16070400",
|
||||||
|
/*overwrite=*/true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't cache the HTTPS response (so we see all the requests).
|
||||||
|
response->SetHeaderByName("Cache-Control", "no-cache",
|
||||||
|
/*overwrite=*/true);
|
||||||
|
|
||||||
|
response_body = "<html><body>Test1</body></html>";
|
||||||
|
}
|
||||||
|
|
||||||
|
response_callback.Run(response, response_body);
|
||||||
|
|
||||||
|
// Stop propagating the callback.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static std::string ToLocalhostOrigin(const std::string& origin) {
|
||||||
|
// Need to explicitly use the "localhost" domain instead of the IP address.
|
||||||
|
// HTTPS URLs will already be using "localhost".
|
||||||
|
return client::AsciiStrReplace(origin, "127.0.0.1", "localhost");
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string GetLocalhostOrigin(bool https_server) {
|
||||||
|
return ToLocalhostOrigin(test_server::GetOrigin(https_server));
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string GetLocalhostURL(bool https_server) {
|
||||||
|
return GetLocalhostOrigin(/*https_server=*/true) + kHSTSURLPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool https_server_;
|
||||||
|
|
||||||
|
size_t& nav_ct_;
|
||||||
|
TrackCallback (&got_request_)[kHSTSLoadCount];
|
||||||
|
ReadyCallback ready_callback_;
|
||||||
|
base::OnceClosure done_callback_;
|
||||||
|
|
||||||
|
std::string origin_;
|
||||||
|
std::string url_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(HSTSTestServerObserver);
|
||||||
|
};
|
||||||
|
|
||||||
|
class HSTSRedirectTest : public TestHandler {
|
||||||
|
public:
|
||||||
|
HSTSRedirectTest() = default;
|
||||||
|
|
||||||
|
void RunTest() override {
|
||||||
|
SetTestTimeout();
|
||||||
|
CefPostTask(TID_UI,
|
||||||
|
base::BindOnce(&HSTSRedirectTest::StartHttpServer, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnResourceRedirect(CefRefPtr<CefBrowser> browser,
|
||||||
|
CefRefPtr<CefFrame> frame,
|
||||||
|
CefRefPtr<CefRequest> request,
|
||||||
|
CefRefPtr<CefResponse> response,
|
||||||
|
CefString& new_url) override {
|
||||||
|
EXPECT_IO_THREAD();
|
||||||
|
|
||||||
|
EXPECT_FALSE(got_redirect_[nav_ct_]) << nav_ct_;
|
||||||
|
got_redirect_[nav_ct_].yes();
|
||||||
|
|
||||||
|
EXPECT_STREQ(http_url_.c_str(), request->GetURL().ToString().c_str())
|
||||||
|
<< nav_ct_;
|
||||||
|
|
||||||
|
if (nav_ct_ == 0) {
|
||||||
|
// Initial HTTP to HTTPS redirect.
|
||||||
|
EXPECT_STREQ(https_url_.c_str(), new_url.ToString().c_str()) << nav_ct_;
|
||||||
|
} else {
|
||||||
|
// HSTS HTTP to HTTPS redirect. This will use the wrong "localhost" port
|
||||||
|
// number, per spec. From RFC 6797:
|
||||||
|
// The UA MUST replace the URI scheme with "https" [RFC2818], and if the
|
||||||
|
// URI contains an explicit port component of "80", then the UA MUST
|
||||||
|
// convert the port component to be "443", or if the URI contains an
|
||||||
|
// explicit port component that is not equal to "80", the port component
|
||||||
|
// value MUST be preserved; otherwise, if the URI does not contain an
|
||||||
|
// explicit port component, the UA MUST NOT add one.
|
||||||
|
const std::string& expected_https_url =
|
||||||
|
client::AsciiStrReplace(http_url_, "http:", "https:");
|
||||||
|
EXPECT_STREQ(expected_https_url.c_str(), new_url.ToString().c_str())
|
||||||
|
<< nav_ct_;
|
||||||
|
|
||||||
|
// Redirect to the correct HTTPS URL instead.
|
||||||
|
new_url = https_url_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnLoadEnd(CefRefPtr<CefBrowser> browser,
|
||||||
|
CefRefPtr<CefFrame> frame,
|
||||||
|
int httpStatusCode) override {
|
||||||
|
EXPECT_UI_THREAD();
|
||||||
|
|
||||||
|
TestHandler::OnLoadEnd(browser, frame, httpStatusCode);
|
||||||
|
|
||||||
|
EXPECT_FALSE(got_load_end_[nav_ct_]) << nav_ct_;
|
||||||
|
got_load_end_[nav_ct_].yes();
|
||||||
|
|
||||||
|
// Expect only the HTTPS URL to load.
|
||||||
|
EXPECT_STREQ(https_url_.c_str(), frame->GetURL().ToString().c_str())
|
||||||
|
<< nav_ct_;
|
||||||
|
|
||||||
|
if (++nav_ct_ == kHSTSLoadCount) {
|
||||||
|
StopHttpServer();
|
||||||
|
} else {
|
||||||
|
// Load the same HTTP URL again.
|
||||||
|
browser->GetMainFrame()->LoadURL(http_url_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DestroyTest() override {
|
||||||
|
EXPECT_FALSE(http_server_);
|
||||||
|
EXPECT_FALSE(https_server_);
|
||||||
|
|
||||||
|
EXPECT_EQ(kHSTSLoadCount, nav_ct_);
|
||||||
|
for (size_t i = 0; i < kHSTSLoadCount; ++i) {
|
||||||
|
EXPECT_TRUE(got_redirect_[i]) << i;
|
||||||
|
EXPECT_TRUE(got_load_end_[i]) << i;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < kHSTSLoadCount; ++i) {
|
||||||
|
// Should only see the 1st HTTP request due to the internal HSTS redirect
|
||||||
|
// for the 2nd+ requests.
|
||||||
|
EXPECT_EQ(i == 0, got_http_request_[i]) << i;
|
||||||
|
|
||||||
|
// Should see all HTTPS requests.
|
||||||
|
EXPECT_TRUE(got_https_request_[i]) << i;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestHandler::DestroyTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void StartHttpServer() {
|
||||||
|
EXPECT_UI_THREAD();
|
||||||
|
|
||||||
|
// Will delete itself after the server stops.
|
||||||
|
http_server_ = new HSTSTestServerObserver(
|
||||||
|
/*https_server=*/false, nav_ct_, got_http_request_,
|
||||||
|
base::BindOnce(&HSTSRedirectTest::StartedHttpServer, this),
|
||||||
|
base::BindOnce(&HSTSRedirectTest::StoppedHttpServer, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartedHttpServer(const std::string& url) {
|
||||||
|
EXPECT_UI_THREAD();
|
||||||
|
|
||||||
|
http_url_ = url;
|
||||||
|
EXPECT_TRUE(http_url_.find("http://localhost:") == 0);
|
||||||
|
|
||||||
|
// Start the HTTPS server. Will delete itself after the server stops.
|
||||||
|
https_server_ = new HSTSTestServerObserver(
|
||||||
|
/*https_server=*/true, nav_ct_, got_https_request_,
|
||||||
|
base::BindOnce(&HSTSRedirectTest::StartedHttpsServer, this),
|
||||||
|
base::BindOnce(&HSTSRedirectTest::StoppedHttpsServer, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartedHttpsServer(const std::string& url) {
|
||||||
|
EXPECT_UI_THREAD();
|
||||||
|
|
||||||
|
https_url_ = url;
|
||||||
|
EXPECT_TRUE(https_url_.find("https://localhost:") == 0);
|
||||||
|
|
||||||
|
CreateBrowser(http_url_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StopHttpServer() {
|
||||||
|
EXPECT_UI_THREAD();
|
||||||
|
|
||||||
|
// Results in a call to StoppedHttpServer().
|
||||||
|
http_server_->Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StoppedHttpServer() {
|
||||||
|
EXPECT_UI_THREAD();
|
||||||
|
|
||||||
|
http_server_ = nullptr;
|
||||||
|
|
||||||
|
// Stop the HTTPS server. Results in a call to StoppedHttpsServer().
|
||||||
|
https_server_->Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StoppedHttpsServer() {
|
||||||
|
EXPECT_UI_THREAD();
|
||||||
|
|
||||||
|
https_server_ = nullptr;
|
||||||
|
|
||||||
|
DestroyTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
HSTSTestServerObserver* http_server_ = nullptr;
|
||||||
|
std::string http_url_;
|
||||||
|
|
||||||
|
HSTSTestServerObserver* https_server_ = nullptr;
|
||||||
|
std::string https_url_;
|
||||||
|
|
||||||
|
size_t nav_ct_ = 0U;
|
||||||
|
TrackCallback got_http_request_[kHSTSLoadCount];
|
||||||
|
TrackCallback got_https_request_[kHSTSLoadCount];
|
||||||
|
TrackCallback got_load_end_[kHSTSLoadCount];
|
||||||
|
TrackCallback got_redirect_[kHSTSLoadCount];
|
||||||
|
|
||||||
|
IMPLEMENT_REFCOUNTING(HSTSRedirectTest);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST(HSTSRedirectTest, Redirect) {
|
||||||
|
CefRefPtr<HSTSRedirectTest> handler = new HSTSRedirectTest();
|
||||||
|
handler->ExecuteTest();
|
||||||
|
ReleaseAndWaitForDestructor(handler);
|
||||||
|
}
|
@@ -10,12 +10,7 @@
|
|||||||
#include "include/cef_command_line.h"
|
#include "include/cef_command_line.h"
|
||||||
#include "include/cef_request_context_handler.h"
|
#include "include/cef_request_context_handler.h"
|
||||||
#include "tests/gtest/include/gtest/gtest.h"
|
#include "tests/gtest/include/gtest/gtest.h"
|
||||||
|
#include "tests/shared/common/string_util.h"
|
||||||
std::string AsciiStrToLower(const std::string& str) {
|
|
||||||
std::string lowerStr = str;
|
|
||||||
std::transform(lowerStr.begin(), lowerStr.end(), lowerStr.begin(), ::tolower);
|
|
||||||
return lowerStr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestMapEqual(const CefRequest::HeaderMap& map1,
|
void TestMapEqual(const CefRequest::HeaderMap& map1,
|
||||||
const CefRequest::HeaderMap& map2,
|
const CefRequest::HeaderMap& map2,
|
||||||
@@ -31,9 +26,9 @@ void TestMapEqual(const CefRequest::HeaderMap& map1,
|
|||||||
|
|
||||||
for (it1 = map1.begin(); it1 != map1.end(); ++it1) {
|
for (it1 = map1.begin(); it1 != map1.end(); ++it1) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
std::string name1 = AsciiStrToLower(it1->first);
|
std::string name1 = client::AsciiStrToLower(it1->first);
|
||||||
for (it2 = map2.begin(); it2 != map2.end(); ++it2) {
|
for (it2 = map2.begin(); it2 != map2.end(); ++it2) {
|
||||||
std::string name2 = AsciiStrToLower(it2->first);
|
std::string name2 = client::AsciiStrToLower(it2->first);
|
||||||
if (name1 == name2 && it1->second == it2->second) {
|
if (name1 == name2 && it1->second == it2->second) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
|
@@ -16,8 +16,6 @@
|
|||||||
CefTime CefTimeFrom(CefBaseTime value);
|
CefTime CefTimeFrom(CefBaseTime value);
|
||||||
CefBaseTime CefBaseTimeFrom(const CefTime& value);
|
CefBaseTime CefBaseTimeFrom(const CefTime& value);
|
||||||
|
|
||||||
std::string AsciiStrToLower(const std::string& str);
|
|
||||||
|
|
||||||
// Test that CefRequest::HeaderMap objects are equal. Multiple values with the
|
// Test that CefRequest::HeaderMap objects are equal. Multiple values with the
|
||||||
// same key are allowed, but not duplicate entries with the same key/value. If
|
// same key are allowed, but not duplicate entries with the same key/value. If
|
||||||
// |allowExtras| is true then additional header fields will be allowed in
|
// |allowExtras| is true then additional header fields will be allowed in
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
#include "tests/gtest/include/gtest/gtest.h"
|
#include "tests/gtest/include/gtest/gtest.h"
|
||||||
#include "tests/shared/browser/client_app_browser.h"
|
#include "tests/shared/browser/client_app_browser.h"
|
||||||
#include "tests/shared/browser/file_util.h"
|
#include "tests/shared/browser/file_util.h"
|
||||||
|
#include "tests/shared/common/string_util.h"
|
||||||
#include "tests/shared/renderer/client_app_renderer.h"
|
#include "tests/shared/renderer/client_app_renderer.h"
|
||||||
|
|
||||||
using client::ClientAppRenderer;
|
using client::ClientAppRenderer;
|
||||||
@@ -453,7 +454,7 @@ std::string GetHeaderValue(const CefRequest::HeaderMap& header_map,
|
|||||||
const std::string& header_name_lower) {
|
const std::string& header_name_lower) {
|
||||||
CefRequest::HeaderMap::const_iterator it = header_map.begin();
|
CefRequest::HeaderMap::const_iterator it = header_map.begin();
|
||||||
for (; it != header_map.end(); ++it) {
|
for (; it != header_map.end(); ++it) {
|
||||||
std::string name = AsciiStrToLower(it->first);
|
std::string name = client::AsciiStrToLower(it->first);
|
||||||
if (name == header_name_lower)
|
if (name == header_name_lower)
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
#include "include/wrapper/cef_closure_task.h"
|
#include "include/wrapper/cef_closure_task.h"
|
||||||
#include "tests/shared/browser/file_util.h"
|
#include "tests/shared/browser/file_util.h"
|
||||||
#include "tests/shared/browser/resource_util.h"
|
#include "tests/shared/browser/resource_util.h"
|
||||||
|
#include "tests/shared/common/string_util.h"
|
||||||
|
|
||||||
namespace client {
|
namespace client {
|
||||||
namespace extension_util {
|
namespace extension_util {
|
||||||
@@ -36,10 +37,8 @@ std::string GetInternalPath(const std::string& extension_path) {
|
|||||||
|
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
// Convert to lower-case, since Windows paths are case-insensitive.
|
// Convert to lower-case, since Windows paths are case-insensitive.
|
||||||
std::transform(resources_path_lower.begin(), resources_path_lower.end(),
|
resources_path_lower = AsciiStrToLower(resources_path_lower);
|
||||||
resources_path_lower.begin(), ::tolower);
|
extension_path_lower = AsciiStrToLower(extension_path_lower);
|
||||||
std::transform(extension_path_lower.begin(), extension_path_lower.end(),
|
|
||||||
extension_path_lower.begin(), ::tolower);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::string internal_path;
|
std::string internal_path;
|
||||||
|
34
tests/shared/common/string_util.cc
Normal file
34
tests/shared/common/string_util.cc
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
// Copyright (c) 2022 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 "tests/shared/common/string_util.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace client {
|
||||||
|
|
||||||
|
std::string AsciiStrToLower(const std::string& str) {
|
||||||
|
std::string lowerStr = str;
|
||||||
|
std::transform(lowerStr.begin(), lowerStr.end(), lowerStr.begin(), ::tolower);
|
||||||
|
return lowerStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AsciiStrReplace(const std::string& str,
|
||||||
|
const std::string& from,
|
||||||
|
const std::string& to) {
|
||||||
|
std::string result = str;
|
||||||
|
std::string::size_type pos = 0;
|
||||||
|
std::string::size_type from_len = from.length();
|
||||||
|
std::string::size_type to_len = to.length();
|
||||||
|
do {
|
||||||
|
pos = result.find(from, pos);
|
||||||
|
if (pos != std::string::npos) {
|
||||||
|
result.replace(pos, from_len, to);
|
||||||
|
pos += to_len;
|
||||||
|
}
|
||||||
|
} while (pos != std::string::npos);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace client
|
23
tests/shared/common/string_util.h
Normal file
23
tests/shared/common/string_util.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// Copyright (c) 2022 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.
|
||||||
|
|
||||||
|
#ifndef CEF_TESTS_SHARED_COMMON_STRING_UTIL_H_
|
||||||
|
#define CEF_TESTS_SHARED_COMMON_STRING_UTIL_H_
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace client {
|
||||||
|
|
||||||
|
// Convert |str| to lowercase.
|
||||||
|
std::string AsciiStrToLower(const std::string& str);
|
||||||
|
|
||||||
|
// Replace all instances of |from| with |to| in |str|.
|
||||||
|
std::string AsciiStrReplace(const std::string& str,
|
||||||
|
const std::string& from,
|
||||||
|
const std::string& to);
|
||||||
|
|
||||||
|
} // namespace client
|
||||||
|
|
||||||
|
#endif // CEF_TESTS_SHARED_COMMON_STRING_UTIL_H_
|
Reference in New Issue
Block a user