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.*
This commit is contained in:
Marshall Greenblatt
2019-04-24 02:50:25 +00:00
parent 019611c764
commit 8f240861e3
141 changed files with 12733 additions and 3927 deletions

View File

@@ -65,6 +65,19 @@ index be77d0e074e9..949873b9bb22 100644
false, nullptr, &plugin, nullptr));
}
diff --git content/browser/devtools/devtools_http_handler.cc content/browser/devtools/devtools_http_handler.cc
index 94892dd57d36..1d4036fdedf8 100644
--- content/browser/devtools/devtools_http_handler.cc
+++ content/browser/devtools/devtools_http_handler.cc
@@ -572,7 +572,7 @@ void DevToolsHttpHandler::OnJsonRequest(
version.SetString("Protocol-Version",
DevToolsAgentHost::GetProtocolVersion());
version.SetString("WebKit-Version", GetWebKitVersion());
- version.SetString("Browser", GetContentClient()->browser()->GetProduct());
+ version.SetString("Browser", GetContentClient()->browser()->GetChromeProduct());
version.SetString("User-Agent",
GetContentClient()->browser()->GetUserAgent());
version.SetString("V8-Version", V8_VERSION_STRING);
diff --git content/browser/frame_host/navigation_handle_impl.cc content/browser/frame_host/navigation_handle_impl.cc
index 8191262c3815..0fc558a96b1b 100644
--- content/browser/frame_host/navigation_handle_impl.cc
@@ -133,10 +146,23 @@ index 31aa4bc38442..0314343499d3 100644
if (stale) {
// Refresh the plugins asynchronously.
diff --git content/browser/loader/navigation_url_loader_impl.cc content/browser/loader/navigation_url_loader_impl.cc
index f9d3104fa375..729b6886e9df 100644
index f9d3104fa375..719b84b88615 100644
--- content/browser/loader/navigation_url_loader_impl.cc
+++ content/browser/loader/navigation_url_loader_impl.cc
@@ -1156,7 +1156,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
@@ -927,6 +927,12 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
resource_request_->has_user_gesture, resource_request_->method,
resource_request_->headers, &proxied_factory_request_,
external_protocol_factory);
+ if (!handled) {
+ handled = GetContentClient()->browser()->HandleExternalProtocol(
+ web_contents_getter_, frame_tree_node_id_,
+ navigation_ui_data_.get(), *resource_request_,
+ &proxied_factory_request_, external_protocol_factory);
+ }
if (external_protocol_factory) {
factory =
@@ -1156,7 +1162,7 @@ class NavigationURLLoaderImpl::URLLoaderRequestController
// path does as well for navigations.
bool has_plugin = PluginService::GetInstance()->GetPluginInfo(
-1 /* render_process_id */, -1 /* render_frame_id */, resource_context_,
@@ -268,6 +294,37 @@ index 5ea18183cc12..a40b09f2e0e4 100644
url::Origin /* main_frame_origin */,
std::string /* mime_type */,
bool /* found */,
diff --git content/public/browser/content_browser_client.h content/public/browser/content_browser_client.h
index b89c08735e10..4a319326afb9 100644
--- content/public/browser/content_browser_client.h
+++ content/public/browser/content_browser_client.h
@@ -1439,6 +1439,15 @@ class CONTENT_EXPORT ContentBrowserClient {
network::mojom::URLLoaderFactoryRequest* factory_request,
network::mojom::URLLoaderFactory*& out_factory);
+ // Same as above, but exposing the whole ResourceRequest object.
+ virtual bool HandleExternalProtocol(
+ ResourceRequestInfo::WebContentsGetter web_contents_getter,
+ int frame_tree_node_id,
+ NavigationUIData* navigation_data,
+ const network::ResourceRequest& request,
+ network::mojom::URLLoaderFactoryRequest* factory_request,
+ network::mojom::URLLoaderFactory*& out_factory) { return false; }
+
// Creates an OverlayWindow to be used for Picture-in-Picture. This window
// will house the content shown when in Picture-in-Picture mode. This will
// return a new OverlayWindow.
@@ -1506,6 +1515,10 @@ class CONTENT_EXPORT ContentBrowserClient {
// Used as part of the user agent string.
virtual std::string GetProduct() const;
+ // Returns the Chrome-specific product string. This is used for compatibility
+ // purposes with external tools like Selenium.
+ virtual std::string GetChromeProduct() const { return GetProduct(); }
+
// Returns the user agent. Content may cache this value.
virtual std::string GetUserAgent() const;
diff --git content/public/browser/plugin_service.h content/public/browser/plugin_service.h
index aed3085c7794..3b31542094d4 100644
--- content/public/browser/plugin_service.h

View File

@@ -1,13 +0,0 @@
diff --git content/browser/devtools/devtools_http_handler.cc content/browser/devtools/devtools_http_handler.cc
index 94892dd57d36..1d4036fdedf8 100644
--- content/browser/devtools/devtools_http_handler.cc
+++ content/browser/devtools/devtools_http_handler.cc
@@ -572,7 +572,7 @@ void DevToolsHttpHandler::OnJsonRequest(
version.SetString("Protocol-Version",
DevToolsAgentHost::GetProtocolVersion());
version.SetString("WebKit-Version", GetWebKitVersion());
- version.SetString("Browser", GetContentClient()->browser()->GetProduct());
+ version.SetString("Browser", GetContentClient()->browser()->GetChromeProduct());
version.SetString("User-Agent",
GetContentClient()->browser()->GetUserAgent());
version.SetString("V8-Version", V8_VERSION_STRING);

View File

@@ -26,21 +26,6 @@ index 9e81f0a33ede..b796e79ae7ef 100644
auto* browser_context = web_contents->GetBrowserContext();
diff --git content/public/browser/content_browser_client.h content/public/browser/content_browser_client.h
index b89c08735e10..8a63d21d6771 100644
--- content/public/browser/content_browser_client.h
+++ content/public/browser/content_browser_client.h
@@ -1506,6 +1506,10 @@ class CONTENT_EXPORT ContentBrowserClient {
// Used as part of the user agent string.
virtual std::string GetProduct() const;
+ // Returns the Chrome-specific product string. This is used for compatibility
+ // purposes with external tools like Selenium.
+ virtual std::string GetChromeProduct() const { return GetProduct(); }
+
// Returns the user agent. Content may cache this value.
virtual std::string GetUserAgent() const;
diff --git extensions/browser/extension_host.cc extensions/browser/extension_host.cc
index 8cc9503fc131..b74c385b40a2 100644
--- extensions/browser/extension_host.cc

View File

@@ -0,0 +1,86 @@
diff --git chrome/browser/net/profile_network_context_service.cc chrome/browser/net/profile_network_context_service.cc
index 2b24d1ac1b5b..f2d97cd93fb1 100644
--- chrome/browser/net/profile_network_context_service.cc
+++ chrome/browser/net/profile_network_context_service.cc
@@ -411,6 +411,8 @@ ProfileNetworkContextService::CreateNetworkContextParams(
CONTENT_SETTINGS_TYPE_COOKIES, std::string(), &settings);
network_context_params->cookie_manager_params->settings = std::move(settings);
+ network_context_params->cookieable_schemes = profile_->GetCookieableSchemes();
+
// Configure on-disk storage for non-OTR profiles. OTR profiles just use
// default behavior (in memory storage, default sizes).
PrefService* prefs = profile_->GetPrefs();
diff --git chrome/browser/profiles/profile.h chrome/browser/profiles/profile.h
index c70a4c0f48ac..8aaadf324a0e 100644
--- chrome/browser/profiles/profile.h
+++ chrome/browser/profiles/profile.h
@@ -310,6 +310,11 @@ class Profile : public content::BrowserContext {
virtual bool ShouldRestoreOldSessionCookies();
virtual bool ShouldPersistSessionCookies();
+ // Returns schemes that should be cookieable, if other than the defaults.
+ virtual std::vector<std::string> GetCookieableSchemes() {
+ return std::vector<std::string>();
+ }
+
// Creates NetworkContext for the specified isolated app (or for the profile
// itself, if |relative_path| is empty).
virtual network::mojom::NetworkContextPtr CreateNetworkContext(
diff --git services/network/network_context.cc services/network/network_context.cc
index b882aa825923..f1921814e1d8 100644
--- services/network/network_context.cc
+++ services/network/network_context.cc
@@ -1733,6 +1733,7 @@ URLRequestContextOwner NetworkContext::ApplyContextParamsToBuilder(
}
scoped_refptr<SessionCleanupCookieStore> session_cleanup_cookie_store;
+ std::unique_ptr<net::CookieMonster> cookie_store;
if (params_->cookie_path) {
scoped_refptr<base::SequencedTaskRunner> client_task_runner =
base::MessageLoopCurrent::Get()->task_runner();
@@ -1760,18 +1761,27 @@ URLRequestContextOwner NetworkContext::ApplyContextParamsToBuilder(
session_cleanup_cookie_store =
base::MakeRefCounted<SessionCleanupCookieStore>(sqlite_store);
- std::unique_ptr<net::CookieMonster> cookie_store =
+ cookie_store =
std::make_unique<net::CookieMonster>(session_cleanup_cookie_store.get(),
net_log);
if (params_->persist_session_cookies)
cookie_store->SetPersistSessionCookies(true);
-
- builder->SetCookieStore(std::move(cookie_store));
} else {
DCHECK(!params_->restore_old_session_cookies);
DCHECK(!params_->persist_session_cookies);
+
+ cookie_store =
+ std::make_unique<net::CookieMonster>(nullptr /* store */, net_log);
}
+ if (!params_->cookieable_schemes.empty()) {
+ cookie_store->SetCookieableSchemes(
+ params_->cookieable_schemes,
+ net::CookieStore::SetCookieableSchemesCallback());
+ }
+
+ builder->SetCookieStore(std::move(cookie_store));
+
std::unique_ptr<net::StaticHttpUserAgentSettings> user_agent_settings =
std::make_unique<net::StaticHttpUserAgentSettings>(
params_->accept_language, params_->user_agent);
diff --git services/network/public/mojom/network_context.mojom services/network/public/mojom/network_context.mojom
index 864e55731cdf..9fea7361d730 100644
--- services/network/public/mojom/network_context.mojom
+++ services/network/public/mojom/network_context.mojom
@@ -189,6 +189,9 @@ struct NetworkContextParams {
// cookies. Otherwise it should be false.
bool persist_session_cookies = false;
+ // Schemes that will be passed to CookieMonster::SetCookieableSchemes.
+ array<string> cookieable_schemes;
+
// True if an HTTP cache should be used.
bool http_cache_enabled = true;
// Maximum size of the HTTP cache. 0 means to use the default size.