cef/tests/ceftests/request_handler_unittest.cc

522 lines
18 KiB
C++
Raw Normal View History

// Copyright (c) 2013 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 <algorithm>
#include <cmath>
#include <sstream>
#include <string>
Move message routing from CefBrowser to CefFrame (see issue #2498). This change moves the SendProcessMessage method from CefBrowser to CefFrame and adds CefBrowser parameters to OnProcessMessageReceived and OnDraggableRegionsChanged. The internal implementation has changed as follows: - Frame IDs are now a 64-bit combination of the 32-bit render_process_id and render_routing_id values that uniquely identify a RenderFrameHost (RFH). - CefFrameHostImpl objects are now managed by CefBrowserInfo with life span tied to RFH expectations. Specifically, a CefFrameHostImpl object representing a sub-frame will be created when a RenderFrame is created in the renderer process and detached when the associated RenderFrame is deleted or the renderer process in which it runs has died. - The CefFrameHostImpl object representing the main frame will always be valid but the underlying RFH (and associated frame ID) may change over time as a result of cross-origin navigations. Despite these changes calling LoadURL on the main frame object in the browser process will always navigate as expected. - Speculative RFHs, which may be created as a result of a cross-origin navigation and discarded if that navigation is not committed, are now handled correctly (e.g. ignored in most cases until they're committed). - It is less likely, but still possible, to receive a CefFrame object with an invalid frame ID (ID < 0). This can happen in cases where a RFH has not yet been created for a sub-frame. For example, when OnBeforeBrowse is called before initiating navigation in a previously nonexisting sub-frame. To test: All tests pass with NetworkService enabled and disabled.
2019-05-24 22:23:43 +02:00
#include <vector>
#include "include/base/cef_bind.h"
#include "include/base/cef_scoped_ptr.h"
#include "include/cef_cookie.h"
Implement NetworkService request interception/handling (see issue #2622). Implementation notes: - Chromium change: CookieMonster::SetCookieableSchemes needs to be called immediately after the CookieMonster is created in NetworkContext:: ApplyContextParamsToBuilder. Add a Profile::GetCookieableSchemes method and NetworkContextParams.cookieable_schemes member (set from ProfileNetworkContextService::CreateNetworkContextParams) to support that. - Chromium change: Add a ContentBrowserClient::HandleExternalProtocol variant that exposes additional NetworkService request information. - GetResourceResponseFilter is not yet implemented. API changes: - Resource-related callbacks have been moved from CefRequestHandler to a new CefResourceRequestHandler interface which is returned via the GetResourceRequestHandler method. If the CefRequestHandler declines to handle a resource it can optionally be handled by the CefRequestContextHandler, if any, associated with the loading context. - The OnProtocolExecution callback has been moved from CefRequestHandler to CefResourceRequestHandler and will be called if a custom scheme request is unhandled. - Cookie send/save permission callbacks have been moved from CefRequestHandler and CefResourceHandler to CefResourceRequestHandler. - New methods added to CefResourceHandler that better match NetworkService execution sequence expectations. The old methods are now deprecated. - New methods added to CefRequest and CefResponse. Known behavior changes with the NetworkService implementation: - Modifying the |new_url| parameter in OnResourceRedirect will no longer result in the method being called an additional time (likely a bug in the old implementation). - Modifying the request URL in OnResourceResponse would previously cause a redirect. This behavior is now deprecated because the NetworkService does not support this functionality when using default network loaders. Temporary support has been added in combination with CefResourceHandler usage only. - Other changes to the request object in OnResourceResponse will now cause the request to be restarted. This means that OnBeforeResourceLoad, etc, will be called an additional time with the new request information. - CefResponse::GetMimeType will now be empty for non-200 responses. - Requests using custom schemes can now be handled via CefResourceRequestHandler with the same callback behavior as builtin schemes. - Redirects of custom scheme requests will now be followed as expected. - Default handling of builtin schemes can now be disabled by setting |disable_default_handling| to true in GetResourceRequestHandler. - Unhandled requests (custom scheme or builtin scheme with default handling disabled) will fail with an CefResponse::GetError value of ERR_UNKNOWN_URL_SCHEME. - The CefSchemeHandlerFactory::Create callback will now include cookie headers. To test: - Run `cefclient --enable-network-service`. All resources should load successfully (this tests the transparent proxy capability). - All tests pass with NetworkService disabled. - The following tests pass with NetworkService enabled: - CookieTest.* - FrameTest.* (excluding .*Nav) - NavigationTest.* (excluding .Redirect*) - RequestHandlerTest.* - RequestContextTest.Basic* - RequestContextTest.Popup* - RequestTest.* - ResourceManagerTest.* - ResourceRequestHandlerTest.* (excluding .Filter*) - SchemeHandlerTest.* - StreamResourceHandlerTest.*
2019-04-24 04:50:25 +02:00
#include "include/cef_request_context_handler.h"
#include "include/wrapper/cef_closure_task.h"
#include "include/wrapper/cef_stream_resource_handler.h"
#include "tests/ceftests/test_handler.h"
#include "tests/ceftests/test_util.h"
#include "tests/gtest/include/gtest/gtest.h"
#include "tests/shared/browser/client_app_browser.h"
#include "tests/shared/renderer/client_app_renderer.h"
using client::ClientAppBrowser;
using client::ClientAppRenderer;
namespace {
enum NetNotifyTestType {
NNTT_NONE = 0,
NNTT_NORMAL,
NNTT_DELAYED_RENDERER,
NNTT_DELAYED_BROWSER,
};
const char kNetNotifyOrigin1[] = "http://tests-netnotify1/";
const char kNetNotifyOrigin2[] = "http://tests-netnotify2/";
const char kNetNotifyMsg[] = "RequestHandlerTest.NetNotify";
Enable strict site isolation by default (see issue #2498) This restores the default site isolation mode for Chromium on desktop platforms. Unit tests have been updated to reflect the new behavior expectations. Known behavior changes in CEF are as follows: - A spare renderer process may be created on initial browser creation or cross- origin navigation. This spare process may be used with a future cross-origin navigation or discarded on application shutdown. As a result CefRenderProcessHandler::OnRenderThreadCreated, which is called shortly after renderer process creation, can no longer be used to reliably transfer state for the currently in-progress navigation. Unit tests have been updated to use the CreateBrowser/OnBeforePopup |extra_info| value for transferring test state to CefRenderProcessHandler::OnBrowserCreated which will be called in the correct/expected renderer process. - Cross-origin navigations will again receive a new renderer process, as expected. This behavior had briefly regressed in M78 due to the ProcessSharingWithDefaultSiteInstances feature becoming enabled by default. - Cross-origin navigations initiated by calling LoadURL in the renderer process will now crash that process with "bad IPC message" reason INVALID_INITIATOR_ORIGIN (213). This is a security feature implemented in Chromium. - A DevTools browser created using CefBrowserHost::ShowDevTools will receive the same CefRenderProcessHandler::OnBrowserCreated |extra_info| value that was set via CreateBrowser/OnBeforePopup for the parent browser.
2019-10-03 16:17:58 +02:00
const char kNetNotifyTestCmdKey[] = "rh-net-notify-test";
// Browser side.
class NetNotifyTestHandler : public TestHandler {
public:
NetNotifyTestHandler(CompletionState* completion_state,
NetNotifyTestType test_type,
bool same_origin)
: TestHandler(completion_state),
test_type_(test_type),
same_origin_(same_origin) {}
void SetupTest() override {
std::stringstream ss;
ss << kNetNotifyOrigin1 << "nav1.html?t=" << test_type_;
url1_ = ss.str();
ss.str("");
ss << (same_origin_ ? kNetNotifyOrigin1 : kNetNotifyOrigin2)
<< "nav2.html?t=" << test_type_;
url2_ = ss.str();
const std::string& resource1 =
"<html>"
"<head><script>document.cookie='name1=value1';</script></head>"
"<body>Nav1</body>"
"</html>";
response_length1_ = static_cast<int64>(resource1.size());
AddResource(url1_, resource1, "text/html");
const std::string& resource2 =
"<html>"
"<head><script>document.cookie='name2=value2';</script></head>"
"<body>Nav2</body>"
"</html>";
response_length2_ = static_cast<int64>(resource2.size());
AddResource(url2_, resource2, "text/html");
Add support for complete isolation of storage and permissions (cache, cookies, localStorage, access grants, etc) on a per-request-context basis (issue #1044). - CefRequestContext instances can be configured using a new CefRequestContextSettings structure passed to CefRequestContext::CreateContext. - Scheme registration is now per-request-context using new CefRequestContext::RegisterSchemeHandlerFactory and ClearSchemeHandlerFactories methods. - Cookie managers are now per-request-context by default and can be retrieved using a new CefRequestContext::GetDefaultCookieManager method. - CefURLRequest::Create now accepts an optional CefRequestContext argument for associating a URL request with a context (browser process only). - The CefRequestContextHandler associated with a CefRequestContext will not be released until all objects related to that context have been destroyed. - When the cache path is empty an in-memory cache ("incognito mode") will be used for storage and no data will be persisted to disk. - Add CefSettings.user_data_path which specifies the location where user data such as spell checking dictionary files will be stored on disk. - Add asynchronous callbacks for all CefCookieManager methods. - Add PK_LOCAL_APP_DATA and PK_USER_DATA path keys for retrieving user directories via CefGetPath. - cefclient: Add "New Window" test that creates a new window unrelated to existing windows. When used in combination with `--request-context-per-browser` the new window will be given a new and isolated request context. git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@2040 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
2015-03-02 21:25:14 +01:00
// Create the request context that will use an in-memory cache.
CefRequestContextSettings settings;
CefRefPtr<CefRequestContext> request_context =
CefRequestContext::CreateContext(settings, nullptr);
cookie_manager_ = request_context->GetCookieManager(nullptr);
Add support for complete isolation of storage and permissions (cache, cookies, localStorage, access grants, etc) on a per-request-context basis (issue #1044). - CefRequestContext instances can be configured using a new CefRequestContextSettings structure passed to CefRequestContext::CreateContext. - Scheme registration is now per-request-context using new CefRequestContext::RegisterSchemeHandlerFactory and ClearSchemeHandlerFactories methods. - Cookie managers are now per-request-context by default and can be retrieved using a new CefRequestContext::GetDefaultCookieManager method. - CefURLRequest::Create now accepts an optional CefRequestContext argument for associating a URL request with a context (browser process only). - The CefRequestContextHandler associated with a CefRequestContext will not be released until all objects related to that context have been destroyed. - When the cache path is empty an in-memory cache ("incognito mode") will be used for storage and no data will be persisted to disk. - Add CefSettings.user_data_path which specifies the location where user data such as spell checking dictionary files will be stored on disk. - Add asynchronous callbacks for all CefCookieManager methods. - Add PK_LOCAL_APP_DATA and PK_USER_DATA path keys for retrieving user directories via CefGetPath. - cefclient: Add "New Window" test that creates a new window unrelated to existing windows. When used in combination with `--request-context-per-browser` the new window will be given a new and isolated request context. git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@2040 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
2015-03-02 21:25:14 +01:00
Enable strict site isolation by default (see issue #2498) This restores the default site isolation mode for Chromium on desktop platforms. Unit tests have been updated to reflect the new behavior expectations. Known behavior changes in CEF are as follows: - A spare renderer process may be created on initial browser creation or cross- origin navigation. This spare process may be used with a future cross-origin navigation or discarded on application shutdown. As a result CefRenderProcessHandler::OnRenderThreadCreated, which is called shortly after renderer process creation, can no longer be used to reliably transfer state for the currently in-progress navigation. Unit tests have been updated to use the CreateBrowser/OnBeforePopup |extra_info| value for transferring test state to CefRenderProcessHandler::OnBrowserCreated which will be called in the correct/expected renderer process. - Cross-origin navigations will again receive a new renderer process, as expected. This behavior had briefly regressed in M78 due to the ProcessSharingWithDefaultSiteInstances feature becoming enabled by default. - Cross-origin navigations initiated by calling LoadURL in the renderer process will now crash that process with "bad IPC message" reason INVALID_INITIATOR_ORIGIN (213). This is a security feature implemented in Chromium. - A DevTools browser created using CefBrowserHost::ShowDevTools will receive the same CefRenderProcessHandler::OnBrowserCreated |extra_info| value that was set via CreateBrowser/OnBeforePopup for the parent browser.
2019-10-03 16:17:58 +02:00
CefRefPtr<CefDictionaryValue> extra_info = CefDictionaryValue::Create();
extra_info->SetBool(kNetNotifyTestCmdKey, true);
// Create browser that loads the 1st URL.
Enable strict site isolation by default (see issue #2498) This restores the default site isolation mode for Chromium on desktop platforms. Unit tests have been updated to reflect the new behavior expectations. Known behavior changes in CEF are as follows: - A spare renderer process may be created on initial browser creation or cross- origin navigation. This spare process may be used with a future cross-origin navigation or discarded on application shutdown. As a result CefRenderProcessHandler::OnRenderThreadCreated, which is called shortly after renderer process creation, can no longer be used to reliably transfer state for the currently in-progress navigation. Unit tests have been updated to use the CreateBrowser/OnBeforePopup |extra_info| value for transferring test state to CefRenderProcessHandler::OnBrowserCreated which will be called in the correct/expected renderer process. - Cross-origin navigations will again receive a new renderer process, as expected. This behavior had briefly regressed in M78 due to the ProcessSharingWithDefaultSiteInstances feature becoming enabled by default. - Cross-origin navigations initiated by calling LoadURL in the renderer process will now crash that process with "bad IPC message" reason INVALID_INITIATOR_ORIGIN (213). This is a security feature implemented in Chromium. - A DevTools browser created using CefBrowserHost::ShowDevTools will receive the same CefRenderProcessHandler::OnBrowserCreated |extra_info| value that was set via CreateBrowser/OnBeforePopup for the parent browser.
2019-10-03 16:17:58 +02:00
CreateBrowser(url1_, request_context, extra_info);
}
void RunTest() override {
// Navigate to the 2nd URL.
GetBrowser()->GetMainFrame()->LoadURL(url2_);
// Time out the test after a reasonable period of time.
SetTestTimeout();
}
cef_return_value_t OnBeforeResourceLoad(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefRequestCallback> callback) override {
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
const std::string& url = request->GetURL();
if (url.find(url1_) == 0)
got_before_resource_load1_.yes();
else if (url.find(url2_) == 0)
got_before_resource_load2_.yes();
else
EXPECT_TRUE(false); // Not reached
return RV_CONTINUE;
}
CefRefPtr<CefResourceHandler> GetResourceHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request) override {
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
const std::string& url = request->GetURL();
if (url.find(url1_) == 0)
got_get_resource_handler1_.yes();
else if (url.find(url2_) == 0)
got_get_resource_handler2_.yes();
else
EXPECT_TRUE(false); // Not reached
return TestHandler::GetResourceHandler(browser, frame, request);
}
void OnResourceLoadComplete(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response,
URLRequestStatus status,
int64 received_content_length) override {
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
EXPECT_EQ(UR_SUCCESS, status);
const std::string& url = request->GetURL();
if (url.find(url1_) == 0) {
got_resource_load_complete1_.yes();
EXPECT_EQ(response_length1_, received_content_length);
} else if (url.find(url2_) == 0) {
got_resource_load_complete2_.yes();
EXPECT_EQ(response_length2_, received_content_length);
} else {
EXPECT_TRUE(false); // Not reached
}
}
bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
bool user_gesture,
bool is_redirect) override {
std::string url = request->GetURL();
// Check if the load has already been delayed.
bool delay_loaded = (url.find("delayed=true") != std::string::npos);
if (url.find(url1_) == 0) {
got_before_browse1_.yes();
EXPECT_FALSE(delay_loaded);
} else if (url.find(url2_) == 0) {
got_before_browse2_.yes();
if (delay_loaded) {
got_before_browse2_delayed_.yes();
} else if (test_type_ == NNTT_DELAYED_RENDERER ||
test_type_ == NNTT_DELAYED_BROWSER) {
got_before_browse2_will_delay_.yes();
// Navigating cross-origin from the browser process will cause a new
// render process to be created. We therefore need some information in
// the request itself to tell us that the navigation has already been
// delayed.
Enable strict site isolation by default (see issue #2498) This restores the default site isolation mode for Chromium on desktop platforms. Unit tests have been updated to reflect the new behavior expectations. Known behavior changes in CEF are as follows: - A spare renderer process may be created on initial browser creation or cross- origin navigation. This spare process may be used with a future cross-origin navigation or discarded on application shutdown. As a result CefRenderProcessHandler::OnRenderThreadCreated, which is called shortly after renderer process creation, can no longer be used to reliably transfer state for the currently in-progress navigation. Unit tests have been updated to use the CreateBrowser/OnBeforePopup |extra_info| value for transferring test state to CefRenderProcessHandler::OnBrowserCreated which will be called in the correct/expected renderer process. - Cross-origin navigations will again receive a new renderer process, as expected. This behavior had briefly regressed in M78 due to the ProcessSharingWithDefaultSiteInstances feature becoming enabled by default. - Cross-origin navigations initiated by calling LoadURL in the renderer process will now crash that process with "bad IPC message" reason INVALID_INITIATOR_ORIGIN (213). This is a security feature implemented in Chromium. - A DevTools browser created using CefBrowserHost::ShowDevTools will receive the same CefRenderProcessHandler::OnBrowserCreated |extra_info| value that was set via CreateBrowser/OnBeforePopup for the parent browser.
2019-10-03 16:17:58 +02:00
// Navigating cross-origin from the renderer process will cause the
// process to be terminated with "bad IPC message" reason
// INVALID_INITIATOR_ORIGIN (213).
url += "&delayed=true";
if (test_type_ == NNTT_DELAYED_RENDERER) {
// Load the URL from the render process.
CefRefPtr<CefProcessMessage> message =
CefProcessMessage::Create(kNetNotifyMsg);
CefRefPtr<CefListValue> args = message->GetArgumentList();
args->SetInt(0, test_type_);
args->SetString(1, url);
Move message routing from CefBrowser to CefFrame (see issue #2498). This change moves the SendProcessMessage method from CefBrowser to CefFrame and adds CefBrowser parameters to OnProcessMessageReceived and OnDraggableRegionsChanged. The internal implementation has changed as follows: - Frame IDs are now a 64-bit combination of the 32-bit render_process_id and render_routing_id values that uniquely identify a RenderFrameHost (RFH). - CefFrameHostImpl objects are now managed by CefBrowserInfo with life span tied to RFH expectations. Specifically, a CefFrameHostImpl object representing a sub-frame will be created when a RenderFrame is created in the renderer process and detached when the associated RenderFrame is deleted or the renderer process in which it runs has died. - The CefFrameHostImpl object representing the main frame will always be valid but the underlying RFH (and associated frame ID) may change over time as a result of cross-origin navigations. Despite these changes calling LoadURL on the main frame object in the browser process will always navigate as expected. - Speculative RFHs, which may be created as a result of a cross-origin navigation and discarded if that navigation is not committed, are now handled correctly (e.g. ignored in most cases until they're committed). - It is less likely, but still possible, to receive a CefFrame object with an invalid frame ID (ID < 0). This can happen in cases where a RFH has not yet been created for a sub-frame. For example, when OnBeforeBrowse is called before initiating navigation in a previously nonexisting sub-frame. To test: All tests pass with NetworkService enabled and disabled.
2019-05-24 22:23:43 +02:00
frame->SendProcessMessage(PID_RENDERER, message);
} else {
// Load the URL from the browser process.
Move message routing from CefBrowser to CefFrame (see issue #2498). This change moves the SendProcessMessage method from CefBrowser to CefFrame and adds CefBrowser parameters to OnProcessMessageReceived and OnDraggableRegionsChanged. The internal implementation has changed as follows: - Frame IDs are now a 64-bit combination of the 32-bit render_process_id and render_routing_id values that uniquely identify a RenderFrameHost (RFH). - CefFrameHostImpl objects are now managed by CefBrowserInfo with life span tied to RFH expectations. Specifically, a CefFrameHostImpl object representing a sub-frame will be created when a RenderFrame is created in the renderer process and detached when the associated RenderFrame is deleted or the renderer process in which it runs has died. - The CefFrameHostImpl object representing the main frame will always be valid but the underlying RFH (and associated frame ID) may change over time as a result of cross-origin navigations. Despite these changes calling LoadURL on the main frame object in the browser process will always navigate as expected. - Speculative RFHs, which may be created as a result of a cross-origin navigation and discarded if that navigation is not committed, are now handled correctly (e.g. ignored in most cases until they're committed). - It is less likely, but still possible, to receive a CefFrame object with an invalid frame ID (ID < 0). This can happen in cases where a RFH has not yet been created for a sub-frame. For example, when OnBeforeBrowse is called before initiating navigation in a previously nonexisting sub-frame. To test: All tests pass with NetworkService enabled and disabled.
2019-05-24 22:23:43 +02:00
frame->LoadURL(url);
}
// Cancel the load.
return true;
}
} else {
EXPECT_TRUE(false); // Not reached
}
// Allow the load to continue.
return false;
}
void OnLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int httpStatusCode) override {
const std::string& url = frame->GetURL();
if (url.find(url1_) == 0) {
got_load_end1_.yes();
SetupCompleteIfDone();
} else if (url.find(url2_) == 0) {
got_load_end2_.yes();
FinishTestIfDone();
} else {
EXPECT_TRUE(false); // Not reached
}
}
bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
Move message routing from CefBrowser to CefFrame (see issue #2498). This change moves the SendProcessMessage method from CefBrowser to CefFrame and adds CefBrowser parameters to OnProcessMessageReceived and OnDraggableRegionsChanged. The internal implementation has changed as follows: - Frame IDs are now a 64-bit combination of the 32-bit render_process_id and render_routing_id values that uniquely identify a RenderFrameHost (RFH). - CefFrameHostImpl objects are now managed by CefBrowserInfo with life span tied to RFH expectations. Specifically, a CefFrameHostImpl object representing a sub-frame will be created when a RenderFrame is created in the renderer process and detached when the associated RenderFrame is deleted or the renderer process in which it runs has died. - The CefFrameHostImpl object representing the main frame will always be valid but the underlying RFH (and associated frame ID) may change over time as a result of cross-origin navigations. Despite these changes calling LoadURL on the main frame object in the browser process will always navigate as expected. - Speculative RFHs, which may be created as a result of a cross-origin navigation and discarded if that navigation is not committed, are now handled correctly (e.g. ignored in most cases until they're committed). - It is less likely, but still possible, to receive a CefFrame object with an invalid frame ID (ID < 0). This can happen in cases where a RFH has not yet been created for a sub-frame. For example, when OnBeforeBrowse is called before initiating navigation in a previously nonexisting sub-frame. To test: All tests pass with NetworkService enabled and disabled.
2019-05-24 22:23:43 +02:00
CefRefPtr<CefFrame> frame,
CefProcessId source_process,
CefRefPtr<CefProcessMessage> message) override {
if (message->GetName().ToString() == kNetNotifyMsg) {
CefRefPtr<CefListValue> args = message->GetArgumentList();
EXPECT_TRUE(args.get());
std::string url = args->GetString(0);
if (url.find(url1_) == 0) {
got_process_message1_.yes();
SetupCompleteIfDone();
} else if (url.find(url2_) == 0) {
got_process_message2_.yes();
FinishTestIfDone();
} else {
EXPECT_TRUE(false); // Not reached
}
return true;
}
// Message not handled.
return false;
}
Enable strict site isolation by default (see issue #2498) This restores the default site isolation mode for Chromium on desktop platforms. Unit tests have been updated to reflect the new behavior expectations. Known behavior changes in CEF are as follows: - A spare renderer process may be created on initial browser creation or cross- origin navigation. This spare process may be used with a future cross-origin navigation or discarded on application shutdown. As a result CefRenderProcessHandler::OnRenderThreadCreated, which is called shortly after renderer process creation, can no longer be used to reliably transfer state for the currently in-progress navigation. Unit tests have been updated to use the CreateBrowser/OnBeforePopup |extra_info| value for transferring test state to CefRenderProcessHandler::OnBrowserCreated which will be called in the correct/expected renderer process. - Cross-origin navigations will again receive a new renderer process, as expected. This behavior had briefly regressed in M78 due to the ProcessSharingWithDefaultSiteInstances feature becoming enabled by default. - Cross-origin navigations initiated by calling LoadURL in the renderer process will now crash that process with "bad IPC message" reason INVALID_INITIATOR_ORIGIN (213). This is a security feature implemented in Chromium. - A DevTools browser created using CefBrowserHost::ShowDevTools will receive the same CefRenderProcessHandler::OnBrowserCreated |extra_info| value that was set via CreateBrowser/OnBeforePopup for the parent browser.
2019-10-03 16:17:58 +02:00
void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
TerminationStatus status) override {
got_process_terminated_ct_++;
// Termination is expected for cross-origin requests initiated from the
// renderer process.
if (!(test_type_ == NNTT_DELAYED_RENDERER && !same_origin_)) {
TestHandler::OnRenderProcessTerminated(browser, status);
}
FinishTest();
}
protected:
void SetupCompleteIfDone() {
if (got_load_end1_ && got_process_message1_)
SetupComplete();
}
void FinishTestIfDone() {
if (got_load_end2_ && got_process_message2_)
FinishTest();
}
void FinishTest() {
// Verify that cookies were set correctly.
class TestVisitor : public CefCookieVisitor {
public:
explicit TestVisitor(NetNotifyTestHandler* handler) : handler_(handler) {}
~TestVisitor() override {
// Destroy the test.
CefPostTask(TID_UI,
base::Bind(&NetNotifyTestHandler::DestroyTest, handler_));
}
bool Visit(const CefCookie& cookie,
int count,
int total,
bool& deleteCookie) override {
const std::string& name = CefString(&cookie.name);
const std::string& value = CefString(&cookie.value);
if (name == "name1" && value == "value1") {
handler_->got_cookie1_.yes();
deleteCookie = true;
} else if (name == "name2" && value == "value2") {
handler_->got_cookie2_.yes();
deleteCookie = true;
}
return true;
}
private:
NetNotifyTestHandler* handler_;
IMPLEMENT_REFCOUNTING(TestVisitor);
};
cookie_manager_->VisitAllCookies(new TestVisitor(this));
}
void DestroyTest() override {
int browser_id = GetBrowser()->GetIdentifier();
// Verify test expectations.
EXPECT_TRUE(got_before_browse1_) << " browser " << browser_id;
EXPECT_TRUE(got_load_end1_) << " browser " << browser_id;
EXPECT_TRUE(got_before_resource_load1_) << " browser " << browser_id;
EXPECT_TRUE(got_get_resource_handler1_) << " browser " << browser_id;
EXPECT_TRUE(got_resource_load_complete1_) << " browser " << browser_id;
EXPECT_TRUE(got_cookie1_) << " browser " << browser_id;
EXPECT_TRUE(got_process_message1_) << " browser " << browser_id;
EXPECT_TRUE(got_before_browse2_) << " browser " << browser_id;
Enable strict site isolation by default (see issue #2498) This restores the default site isolation mode for Chromium on desktop platforms. Unit tests have been updated to reflect the new behavior expectations. Known behavior changes in CEF are as follows: - A spare renderer process may be created on initial browser creation or cross- origin navigation. This spare process may be used with a future cross-origin navigation or discarded on application shutdown. As a result CefRenderProcessHandler::OnRenderThreadCreated, which is called shortly after renderer process creation, can no longer be used to reliably transfer state for the currently in-progress navigation. Unit tests have been updated to use the CreateBrowser/OnBeforePopup |extra_info| value for transferring test state to CefRenderProcessHandler::OnBrowserCreated which will be called in the correct/expected renderer process. - Cross-origin navigations will again receive a new renderer process, as expected. This behavior had briefly regressed in M78 due to the ProcessSharingWithDefaultSiteInstances feature becoming enabled by default. - Cross-origin navigations initiated by calling LoadURL in the renderer process will now crash that process with "bad IPC message" reason INVALID_INITIATOR_ORIGIN (213). This is a security feature implemented in Chromium. - A DevTools browser created using CefBrowserHost::ShowDevTools will receive the same CefRenderProcessHandler::OnBrowserCreated |extra_info| value that was set via CreateBrowser/OnBeforePopup for the parent browser.
2019-10-03 16:17:58 +02:00
if (test_type_ == NNTT_DELAYED_RENDERER && !same_origin_) {
EXPECT_EQ(1, got_process_terminated_ct_) << " browser " << browser_id;
EXPECT_FALSE(got_load_end2_) << " browser " << browser_id;
EXPECT_FALSE(got_before_resource_load2_) << " browser " << browser_id;
EXPECT_FALSE(got_get_resource_handler2_) << " browser " << browser_id;
EXPECT_FALSE(got_resource_load_complete2_) << " browser " << browser_id;
EXPECT_FALSE(got_cookie2_) << " browser " << browser_id;
EXPECT_FALSE(got_process_message2_) << " browser " << browser_id;
} else {
EXPECT_EQ(0, got_process_terminated_ct_) << " browser " << browser_id;
EXPECT_TRUE(got_load_end2_) << " browser " << browser_id;
EXPECT_TRUE(got_before_resource_load2_) << " browser " << browser_id;
EXPECT_TRUE(got_get_resource_handler2_) << " browser " << browser_id;
EXPECT_TRUE(got_resource_load_complete2_) << " browser " << browser_id;
EXPECT_TRUE(got_cookie2_) << " browser " << browser_id;
EXPECT_TRUE(got_process_message2_) << " browser " << browser_id;
}
if (test_type_ == NNTT_DELAYED_RENDERER ||
test_type_ == NNTT_DELAYED_BROWSER) {
EXPECT_TRUE(got_before_browse2_will_delay_) << " browser " << browser_id;
Enable strict site isolation by default (see issue #2498) This restores the default site isolation mode for Chromium on desktop platforms. Unit tests have been updated to reflect the new behavior expectations. Known behavior changes in CEF are as follows: - A spare renderer process may be created on initial browser creation or cross- origin navigation. This spare process may be used with a future cross-origin navigation or discarded on application shutdown. As a result CefRenderProcessHandler::OnRenderThreadCreated, which is called shortly after renderer process creation, can no longer be used to reliably transfer state for the currently in-progress navigation. Unit tests have been updated to use the CreateBrowser/OnBeforePopup |extra_info| value for transferring test state to CefRenderProcessHandler::OnBrowserCreated which will be called in the correct/expected renderer process. - Cross-origin navigations will again receive a new renderer process, as expected. This behavior had briefly regressed in M78 due to the ProcessSharingWithDefaultSiteInstances feature becoming enabled by default. - Cross-origin navigations initiated by calling LoadURL in the renderer process will now crash that process with "bad IPC message" reason INVALID_INITIATOR_ORIGIN (213). This is a security feature implemented in Chromium. - A DevTools browser created using CefBrowserHost::ShowDevTools will receive the same CefRenderProcessHandler::OnBrowserCreated |extra_info| value that was set via CreateBrowser/OnBeforePopup for the parent browser.
2019-10-03 16:17:58 +02:00
if (test_type_ == NNTT_DELAYED_RENDERER && !same_origin_) {
EXPECT_FALSE(got_before_browse2_delayed_) << " browser " << browser_id;
} else {
EXPECT_TRUE(got_before_browse2_delayed_) << " browser " << browser_id;
}
} else {
EXPECT_FALSE(got_before_browse2_will_delay_) << " browser " << browser_id;
EXPECT_FALSE(got_before_browse2_delayed_) << " browser " << browser_id;
}
cookie_manager_ = nullptr;
TestHandler::DestroyTest();
}
NetNotifyTestType test_type_;
bool same_origin_;
std::string url1_;
std::string url2_;
CefRefPtr<CefCookieManager> cookie_manager_;
TrackCallback got_before_browse1_;
TrackCallback got_load_end1_;
TrackCallback got_before_resource_load1_;
TrackCallback got_get_resource_handler1_;
TrackCallback got_resource_load_complete1_;
TrackCallback got_cookie1_;
TrackCallback got_process_message1_;
TrackCallback got_before_browse2_;
TrackCallback got_load_end2_;
TrackCallback got_before_resource_load2_;
TrackCallback got_get_resource_handler2_;
TrackCallback got_resource_load_complete2_;
TrackCallback got_cookie2_;
TrackCallback got_process_message2_;
TrackCallback got_before_browse2_will_delay_;
TrackCallback got_before_browse2_delayed_;
Enable strict site isolation by default (see issue #2498) This restores the default site isolation mode for Chromium on desktop platforms. Unit tests have been updated to reflect the new behavior expectations. Known behavior changes in CEF are as follows: - A spare renderer process may be created on initial browser creation or cross- origin navigation. This spare process may be used with a future cross-origin navigation or discarded on application shutdown. As a result CefRenderProcessHandler::OnRenderThreadCreated, which is called shortly after renderer process creation, can no longer be used to reliably transfer state for the currently in-progress navigation. Unit tests have been updated to use the CreateBrowser/OnBeforePopup |extra_info| value for transferring test state to CefRenderProcessHandler::OnBrowserCreated which will be called in the correct/expected renderer process. - Cross-origin navigations will again receive a new renderer process, as expected. This behavior had briefly regressed in M78 due to the ProcessSharingWithDefaultSiteInstances feature becoming enabled by default. - Cross-origin navigations initiated by calling LoadURL in the renderer process will now crash that process with "bad IPC message" reason INVALID_INITIATOR_ORIGIN (213). This is a security feature implemented in Chromium. - A DevTools browser created using CefBrowserHost::ShowDevTools will receive the same CefRenderProcessHandler::OnBrowserCreated |extra_info| value that was set via CreateBrowser/OnBeforePopup for the parent browser.
2019-10-03 16:17:58 +02:00
int got_process_terminated_ct_ = 0;
int64 response_length1_;
int64 response_length2_;
IMPLEMENT_REFCOUNTING(NetNotifyTestHandler);
};
// Renderer side.
class NetNotifyRendererTest : public ClientAppRenderer::Delegate,
public CefLoadHandler {
public:
NetNotifyRendererTest() : run_test_(false) {}
Enable strict site isolation by default (see issue #2498) This restores the default site isolation mode for Chromium on desktop platforms. Unit tests have been updated to reflect the new behavior expectations. Known behavior changes in CEF are as follows: - A spare renderer process may be created on initial browser creation or cross- origin navigation. This spare process may be used with a future cross-origin navigation or discarded on application shutdown. As a result CefRenderProcessHandler::OnRenderThreadCreated, which is called shortly after renderer process creation, can no longer be used to reliably transfer state for the currently in-progress navigation. Unit tests have been updated to use the CreateBrowser/OnBeforePopup |extra_info| value for transferring test state to CefRenderProcessHandler::OnBrowserCreated which will be called in the correct/expected renderer process. - Cross-origin navigations will again receive a new renderer process, as expected. This behavior had briefly regressed in M78 due to the ProcessSharingWithDefaultSiteInstances feature becoming enabled by default. - Cross-origin navigations initiated by calling LoadURL in the renderer process will now crash that process with "bad IPC message" reason INVALID_INITIATOR_ORIGIN (213). This is a security feature implemented in Chromium. - A DevTools browser created using CefBrowserHost::ShowDevTools will receive the same CefRenderProcessHandler::OnBrowserCreated |extra_info| value that was set via CreateBrowser/OnBeforePopup for the parent browser.
2019-10-03 16:17:58 +02:00
void OnBrowserCreated(CefRefPtr<ClientAppRenderer> app,
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDictionaryValue> extra_info) override {
run_test_ = extra_info->HasKey(kNetNotifyTestCmdKey);
}
CefRefPtr<CefLoadHandler> GetLoadHandler(
CefRefPtr<ClientAppRenderer> app) override {
if (run_test_)
return this;
return nullptr;
}
void OnLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int httpStatusCode) override {
if (!run_test_)
return;
const std::string& url = frame->GetURL();
// Continue in the browser process.
CefRefPtr<CefProcessMessage> message =
CefProcessMessage::Create(kNetNotifyMsg);
CefRefPtr<CefListValue> args = message->GetArgumentList();
args->SetString(0, url);
Move message routing from CefBrowser to CefFrame (see issue #2498). This change moves the SendProcessMessage method from CefBrowser to CefFrame and adds CefBrowser parameters to OnProcessMessageReceived and OnDraggableRegionsChanged. The internal implementation has changed as follows: - Frame IDs are now a 64-bit combination of the 32-bit render_process_id and render_routing_id values that uniquely identify a RenderFrameHost (RFH). - CefFrameHostImpl objects are now managed by CefBrowserInfo with life span tied to RFH expectations. Specifically, a CefFrameHostImpl object representing a sub-frame will be created when a RenderFrame is created in the renderer process and detached when the associated RenderFrame is deleted or the renderer process in which it runs has died. - The CefFrameHostImpl object representing the main frame will always be valid but the underlying RFH (and associated frame ID) may change over time as a result of cross-origin navigations. Despite these changes calling LoadURL on the main frame object in the browser process will always navigate as expected. - Speculative RFHs, which may be created as a result of a cross-origin navigation and discarded if that navigation is not committed, are now handled correctly (e.g. ignored in most cases until they're committed). - It is less likely, but still possible, to receive a CefFrame object with an invalid frame ID (ID < 0). This can happen in cases where a RFH has not yet been created for a sub-frame. For example, when OnBeforeBrowse is called before initiating navigation in a previously nonexisting sub-frame. To test: All tests pass with NetworkService enabled and disabled.
2019-05-24 22:23:43 +02:00
frame->SendProcessMessage(PID_BROWSER, message);
}
bool OnProcessMessageReceived(CefRefPtr<ClientAppRenderer> app,
CefRefPtr<CefBrowser> browser,
Move message routing from CefBrowser to CefFrame (see issue #2498). This change moves the SendProcessMessage method from CefBrowser to CefFrame and adds CefBrowser parameters to OnProcessMessageReceived and OnDraggableRegionsChanged. The internal implementation has changed as follows: - Frame IDs are now a 64-bit combination of the 32-bit render_process_id and render_routing_id values that uniquely identify a RenderFrameHost (RFH). - CefFrameHostImpl objects are now managed by CefBrowserInfo with life span tied to RFH expectations. Specifically, a CefFrameHostImpl object representing a sub-frame will be created when a RenderFrame is created in the renderer process and detached when the associated RenderFrame is deleted or the renderer process in which it runs has died. - The CefFrameHostImpl object representing the main frame will always be valid but the underlying RFH (and associated frame ID) may change over time as a result of cross-origin navigations. Despite these changes calling LoadURL on the main frame object in the browser process will always navigate as expected. - Speculative RFHs, which may be created as a result of a cross-origin navigation and discarded if that navigation is not committed, are now handled correctly (e.g. ignored in most cases until they're committed). - It is less likely, but still possible, to receive a CefFrame object with an invalid frame ID (ID < 0). This can happen in cases where a RFH has not yet been created for a sub-frame. For example, when OnBeforeBrowse is called before initiating navigation in a previously nonexisting sub-frame. To test: All tests pass with NetworkService enabled and disabled.
2019-05-24 22:23:43 +02:00
CefRefPtr<CefFrame> frame,
CefProcessId source_process,
CefRefPtr<CefProcessMessage> message) override {
if (message->GetName().ToString() == kNetNotifyMsg) {
CefRefPtr<CefListValue> args = message->GetArgumentList();
EXPECT_TRUE(args.get());
NetNotifyTestType test_type =
static_cast<NetNotifyTestType>(args->GetInt(0));
EXPECT_EQ(test_type, NNTT_DELAYED_RENDERER);
const std::string& url = args->GetString(1);
// Load the URL from the render process.
Move message routing from CefBrowser to CefFrame (see issue #2498). This change moves the SendProcessMessage method from CefBrowser to CefFrame and adds CefBrowser parameters to OnProcessMessageReceived and OnDraggableRegionsChanged. The internal implementation has changed as follows: - Frame IDs are now a 64-bit combination of the 32-bit render_process_id and render_routing_id values that uniquely identify a RenderFrameHost (RFH). - CefFrameHostImpl objects are now managed by CefBrowserInfo with life span tied to RFH expectations. Specifically, a CefFrameHostImpl object representing a sub-frame will be created when a RenderFrame is created in the renderer process and detached when the associated RenderFrame is deleted or the renderer process in which it runs has died. - The CefFrameHostImpl object representing the main frame will always be valid but the underlying RFH (and associated frame ID) may change over time as a result of cross-origin navigations. Despite these changes calling LoadURL on the main frame object in the browser process will always navigate as expected. - Speculative RFHs, which may be created as a result of a cross-origin navigation and discarded if that navigation is not committed, are now handled correctly (e.g. ignored in most cases until they're committed). - It is less likely, but still possible, to receive a CefFrame object with an invalid frame ID (ID < 0). This can happen in cases where a RFH has not yet been created for a sub-frame. For example, when OnBeforeBrowse is called before initiating navigation in a previously nonexisting sub-frame. To test: All tests pass with NetworkService enabled and disabled.
2019-05-24 22:23:43 +02:00
frame->LoadURL(url);
return true;
}
// Message not handled.
return false;
}
private:
bool run_test_;
IMPLEMENT_REFCOUNTING(NetNotifyRendererTest);
};
Move message routing from CefBrowser to CefFrame (see issue #2498). This change moves the SendProcessMessage method from CefBrowser to CefFrame and adds CefBrowser parameters to OnProcessMessageReceived and OnDraggableRegionsChanged. The internal implementation has changed as follows: - Frame IDs are now a 64-bit combination of the 32-bit render_process_id and render_routing_id values that uniquely identify a RenderFrameHost (RFH). - CefFrameHostImpl objects are now managed by CefBrowserInfo with life span tied to RFH expectations. Specifically, a CefFrameHostImpl object representing a sub-frame will be created when a RenderFrame is created in the renderer process and detached when the associated RenderFrame is deleted or the renderer process in which it runs has died. - The CefFrameHostImpl object representing the main frame will always be valid but the underlying RFH (and associated frame ID) may change over time as a result of cross-origin navigations. Despite these changes calling LoadURL on the main frame object in the browser process will always navigate as expected. - Speculative RFHs, which may be created as a result of a cross-origin navigation and discarded if that navigation is not committed, are now handled correctly (e.g. ignored in most cases until they're committed). - It is less likely, but still possible, to receive a CefFrame object with an invalid frame ID (ID < 0). This can happen in cases where a RFH has not yet been created for a sub-frame. For example, when OnBeforeBrowse is called before initiating navigation in a previously nonexisting sub-frame. To test: All tests pass with NetworkService enabled and disabled.
2019-05-24 22:23:43 +02:00
void RunNetNotifyTest(NetNotifyTestType test_type,
bool same_origin,
size_t count = 3U) {
TestHandler::CompletionState completion_state(static_cast<int>(count));
TestHandler::Collection collection(&completion_state);
Move message routing from CefBrowser to CefFrame (see issue #2498). This change moves the SendProcessMessage method from CefBrowser to CefFrame and adds CefBrowser parameters to OnProcessMessageReceived and OnDraggableRegionsChanged. The internal implementation has changed as follows: - Frame IDs are now a 64-bit combination of the 32-bit render_process_id and render_routing_id values that uniquely identify a RenderFrameHost (RFH). - CefFrameHostImpl objects are now managed by CefBrowserInfo with life span tied to RFH expectations. Specifically, a CefFrameHostImpl object representing a sub-frame will be created when a RenderFrame is created in the renderer process and detached when the associated RenderFrame is deleted or the renderer process in which it runs has died. - The CefFrameHostImpl object representing the main frame will always be valid but the underlying RFH (and associated frame ID) may change over time as a result of cross-origin navigations. Despite these changes calling LoadURL on the main frame object in the browser process will always navigate as expected. - Speculative RFHs, which may be created as a result of a cross-origin navigation and discarded if that navigation is not committed, are now handled correctly (e.g. ignored in most cases until they're committed). - It is less likely, but still possible, to receive a CefFrame object with an invalid frame ID (ID < 0). This can happen in cases where a RFH has not yet been created for a sub-frame. For example, when OnBeforeBrowse is called before initiating navigation in a previously nonexisting sub-frame. To test: All tests pass with NetworkService enabled and disabled.
2019-05-24 22:23:43 +02:00
std::vector<CefRefPtr<NetNotifyTestHandler>> handlers;
for (size_t i = 0U; i < count; ++i) {
CefRefPtr<NetNotifyTestHandler> handler =
new NetNotifyTestHandler(&completion_state, test_type, same_origin);
collection.AddTestHandler(handler);
handlers.push_back(handler);
}
collection.ExecuteTests();
Move message routing from CefBrowser to CefFrame (see issue #2498). This change moves the SendProcessMessage method from CefBrowser to CefFrame and adds CefBrowser parameters to OnProcessMessageReceived and OnDraggableRegionsChanged. The internal implementation has changed as follows: - Frame IDs are now a 64-bit combination of the 32-bit render_process_id and render_routing_id values that uniquely identify a RenderFrameHost (RFH). - CefFrameHostImpl objects are now managed by CefBrowserInfo with life span tied to RFH expectations. Specifically, a CefFrameHostImpl object representing a sub-frame will be created when a RenderFrame is created in the renderer process and detached when the associated RenderFrame is deleted or the renderer process in which it runs has died. - The CefFrameHostImpl object representing the main frame will always be valid but the underlying RFH (and associated frame ID) may change over time as a result of cross-origin navigations. Despite these changes calling LoadURL on the main frame object in the browser process will always navigate as expected. - Speculative RFHs, which may be created as a result of a cross-origin navigation and discarded if that navigation is not committed, are now handled correctly (e.g. ignored in most cases until they're committed). - It is less likely, but still possible, to receive a CefFrame object with an invalid frame ID (ID < 0). This can happen in cases where a RFH has not yet been created for a sub-frame. For example, when OnBeforeBrowse is called before initiating navigation in a previously nonexisting sub-frame. To test: All tests pass with NetworkService enabled and disabled.
2019-05-24 22:23:43 +02:00
while (!handlers.empty()) {
auto handler = handlers.front();
handlers.erase(handlers.begin());
ReleaseAndWaitForDestructor(handler);
}
}
} // namespace
// Verify network notifications for multiple browsers existing simultaniously.
// URL loading is from the same origin and is not delayed.
TEST(RequestHandlerTest, NotificationsSameOriginDirect) {
RunNetNotifyTest(NNTT_NORMAL, true);
}
// Verify network notifications for multiple browsers existing simultaniously.
// URL loading is from the same origin and is continued asynchronously from the
// render process.
TEST(RequestHandlerTest, NotificationsSameOriginDelayedRenderer) {
RunNetNotifyTest(NNTT_DELAYED_RENDERER, true);
}
// Verify network notifications for multiple browsers existing simultaniously.
// URL loading is from the same origin and is continued asynchronously from the
// browser process.
TEST(RequestHandlerTest, NotificationsSameOriginDelayedBrowser) {
RunNetNotifyTest(NNTT_DELAYED_BROWSER, true);
}
// Verify network notifications for multiple browsers existing simultaniously.
// URL loading is from a different origin and is not delayed.
TEST(RequestHandlerTest, NotificationsCrossOriginDirect) {
RunNetNotifyTest(NNTT_NORMAL, false);
}
// Verify network notifications for multiple browsers existing simultaniously.
// URL loading is from a different origin and is continued asynchronously from
// the render process.
TEST(RequestHandlerTest, NotificationsCrossOriginDelayedRenderer) {
RunNetNotifyTest(NNTT_DELAYED_RENDERER, false);
}
// Verify network notifications for multiple browsers existing simultaniously.
// URL loading is from a different origin and is continued asynchronously from
// the browser process.
TEST(RequestHandlerTest, NotificationsCrossOriginDelayedBrowser) {
RunNetNotifyTest(NNTT_DELAYED_BROWSER, false);
}
// Entry point for creating request handler renderer test objects.
// Called from client_app_delegates.cc.
void CreateRequestHandlerRendererTests(
ClientAppRenderer::DelegateSet& delegates) {
delegates.insert(new NetNotifyRendererTest);
}