With the introduction of prerendering in Chromium it is now possible for
RenderFrameHosts (RFH) to move between FrameTrees. As a consequence we can no
longer rely on FrameTreeNode IDs to uniquely identify a RFH over its lifespan.
We must now switch to using GlobalRenderFrameHostId (child_id, frame_routing_id)
instead for that purpose. Additionally, we simplify existing code by using the
GlobalRenderFrameHostId struct in all places that previously used a
(render_process_id, render_frame_id) pair, since these concepts are equivalent.
See https://crbug.com/1179502#c8 for additional background.
This change adds support for CEF settings configuration of accept_language_list.
If specified, this value will take precedence over the "intl.accept_languages"
preference which is controlled by chrome://settings/languages.
With the Chrome runtime, Profile initialization may be asynchronous. Code that
waited on CefBrowserContext creation now needs to wait on CefBrowserContext
initialization instead.
The policy->CanAccessDataForOrigin CHECK in NavigationRequest::
GetOriginForURLLoaderFactory was failing because unregistered schemes
(which are already considered non-standard schemes) didn't trigger the
registered non-standard scheme allowance that we previously added in
ChildProcessSecurityPolicyImpl::CanAccessDataForOrigin. This change
modifies GetOriginForURLLoaderFactory to always return an opaque/unique
origin for non-standard schemes resulting in unregistered and non-standard
schemes receiving the same treatment.
New test coverage has been added for this condition, and can be run with:
ceftests --gtest_filter=CorsTest.*CustomUnregistered*
The Chrome runtime requires that cookieable scheme information be available
at Profile initialization time because it also triggers NetworkContext creation
at the same time. To make this possible, and to avoid various race conditions
when setting state, the cookieable scheme configuration has been added as
|cookieable_schemes_list| and |cookieable_schemes_exclude_defaults| in
CefSettings and CefBrowserContextSettings. The CefCookieManager::
SetSupportedSchemes and CefBrowserProcessHandler::GetCookieableSchemes methods
are no longer required and have been removed.
This change also modifies chrome to delay OffTheRecordProfileImpl initialization
so that |ChromeBrowserContext::profile_| can be set before
ChromeContentBrowserClientCef::ConfigureNetworkContextParams calls
CefBrowserContext::FromBrowserContext to retrieve the ChromeBrowserContext
and associated cookieable scheme information. Otherwise, the
ChromeBrowserContext will not be matched and the NetworkContext will not be
configured correctly.
The CookieTest suite now passes with the Chrome runtime enabled.
- Only install network intercepts for Profiles that have an associated
CefBrowserContext. For incognito windows the CefBrowserContext is
associated with the OffTheRecordProfileImpl's original Profile.
- cefsimple: Return the default CefClient instance for browser windows
created via the Chrome UI, and allow Chrome to show error pages.
This change adds support for:
- Protocol and request handling.
- Loading and navigation events.
- Display and focus events.
- Mouse/keyboard events.
- Popup browsers.
- Callbacks in the renderer process.
- Misc. functionality required for ceftests.
This change also adds a new CefBrowserProcessHandler::GetCookieableSchemes
callback for configuring global state that will be applied to all
CefCookieManagers by default. This global callback is currently required by the
chrome runtime because the primary ProfileImpl is created via
ChromeBrowserMainParts::PreMainMessageLoopRun (CreatePrimaryProfile) before
OnContextCreated can be called.
ProfileImpl will use the "C:\Users\[user]\AppData\Local\CEF\User Data\Default"
directory by default (on Windows). Cookies may persist in this directory when
running ceftests and may need to be manually deleted if those tests fail.
Remaining work includes:
- Support for client-created request contexts.
- Embedding the browser in a Views hierarchy (cefclient support).
- TryCloseBrowser and DoClose support.
- Most of the CefSettings configuration.
- DevTools protocol and window control (ShowDevTools, ExecuteDevToolsMethod).
- CEF-specific WebUI pages (about, license, webui-hosts).
- Context menu customization (CefContextMenuHandler).
- Auto resize (SetAutoResizeEnabled).
- Zoom settings (SetZoomLevel).
- File dialog runner (RunFileDialog).
- File and JS dialog handlers (CefDialogHandler, CefJSDialogHandler).
- Extension loading (LoadExtension, etc).
- Plugin loading (OnBeforePluginLoad).
- Widevine loading (CefRegisterWidevineCdm).
- PDF and print preview does not display.
- Crash reporting is untested.
- Mac: Web content loads but does not display.
The following ceftests are now passing when run with the
"--enable-chrome-runtime" command-line flag:
CorsTest.*
DisplayTest.*:-DisplayTest.AutoResize
DOMTest.*
DraggableRegionsTest.*
ImageTest.*
MessageRouterTest.*
NavigationTest.*
ParserTest.*
RequestContextTest.*Global*
RequestTest.*
ResourceManagerTest.*
ResourceRequestHandlerTest.*
ResponseTest.*
SchemeHandlerTest.*
ServerTest.*
StreamResourceHandlerTest.*
StreamTest.*
StringTest.*
TaskTest.*
TestServerTest.*
ThreadTest.*
URLRequestTest.*Global*
V8Test.*:-V8Test.OnUncaughtExceptionDevTools
ValuesTest.*
WaitableEventTest.*
XmlReaderTest.*
ZipReaderTest.*
The Browser object represents the top-level Chrome browser window. One or more
tabs (WebContents) are then owned by the Browser object via TabStripModel. A
new Browser object can be created programmatically using "new Browser" or
Browser::Create, or as a result of user action such as dragging a tab out of an
existing window. New or existing tabs can also be added to an already existing
Browser object.
The Browser object acts as the WebContentsDelegate for all attached tabs. CEF
integration requires WebContentsDelegate callbacks and notification of tab
attach/detach. To support this integration we add a cef::BrowserDelegate
(ChromeBrowserDelegate) member that is created in the Browser constructor and
receives delegation for the Browser callbacks. ChromeBrowserDelegate creates a
new ChromeBrowserHostImpl when a tab is added to a Browser for the first time,
and that ChromeBrowserHostImpl continues to exist until the tab's WebContents
is destroyed. The associated WebContents object does not change, but the
Browser object will change when the tab is dragged between windows.
CEF callback logic is shared between the chrome and alloy runtimes where
possible. This shared logic has been extracted from CefBrowserHostImpl to
create new CefBrowserHostBase and CefBrowserContentsDelegate classes. The
CefBrowserHostImpl class is now only used with the alloy runtime and will be
renamed to AlloyBrowserHostImpl in a future commit.
A CORS preflight request is an "OPTIONS" request sent to a server prior to a
cross-origin XMLHttpRequest or Fetch request. The server's response determines
which HTTP request methods are allowed and supported, and whether credentials
such as Cookies and HTTP Authentication should be sent with requests.
A CORS preflight request will only be sent if certain conditions are met. For
example, it will be sent for requests that have potentially unsafe HTTP
methods [1] or request headers [2]. See the NeedsPreflight function in
services/network/cors/cors_url_loader.cc for full details.
CORS preflight functionality is implemented in the network service and will not
be triggered if the client handles the request instead of allowing it to proceed
over the network. Since the preflight request itself also runs in the network
service it cannot be intercepted by the client.
[1] https://fetch.spec.whatwg.org/#cors-safelisted-method
[2] https://fetch.spec.whatwg.org/#cors-safelisted-request-header
The request.trusted_params.isolation_info.site_for_cookies value must
match request.site_for_cookies.
This change also adds unit test coverage for cross-origin GET redirects.
This fixes an IsCanonical() DCHECK failure triggered by calling
CanonicalCookie::Create for a non-cookieable URL.
This change also adds unit test coverage for cross-origin cookie
behavior with sub-resource requests (iframe, XHR, Fetch).
- CefURLRequest::Create is no longer supported in the renderer process
(see https://crbug.com/891872). Use CefFrame::CreateURLRequest instead.
- Mac platform definitions have been changed from `MACOSX` to `MAC`
(see https://crbug.com/1105907) and related CMake macro names have
been updated. The old `OS_MACOSX` define is still set in code and CMake
for backwards compatibility.
- Linux ARM build is currently broken (see https://crbug.com/1123214).
- Windows: 10.0.19041 SDK is now required.
- macOS: 10.15.1 SDK (at least Xcode 11.2) is now required.
- Remove CefMediaSource::IsValid and CefMediaSink::IsValid which would
always return true.
Existing CefBrowserContext functionality is now split between
CefBrowserContext and AlloyBrowserContext. Runtime implementations of
CefBrowserContext will provide access to the content::BrowserContext and
Profile types via different inheritance paths. For example, the Alloy
runtime uses ChromeProfileAlloy and the Chrome runtime uses ProfileImpl.
This change also renames CefResourceContext to CefIOThreadState to more
accurately represent its purpose as it no longer needs to extend
content::ResourceContext.
This is the first pass in removing direct dependencies on the Alloy
runtime from code that can potentially be shared between runtimes.
CefBrowserHost and CefRequestContext APIs (including CefCookieManager,
CefURLRequest, etc.) are not yet implemented for the Chrome runtime.
Assert early if these API methods are called while the Chrome runtime
is enabled.
As part of introducing the Chrome runtime we now need to distinguish
between the classes that implement the current CEF runtime and the
classes the implement the shared CEF library/runtime structure and
public API. We choose the name Alloy for the current CEF runtime
because it describes a combination of Chrome and other elements.
Shared CEF library/runtime classes will continue to use the Cef
prefix. Classes that implement the Alloy or Chrome runtime will use
the Alloy or Chrome prefixes respectively. Classes that extend an
existing Chrome-prefixed class will add the Cef or Alloy suffix,
thereby following the existing naming pattern of Chrome-derived
classes.
This change applies the new naming pattern to an initial set of
runtime-related classes. Additional classes/files will be renamed
and moved as the Chrome runtime implementation progresses.
This change also restores the Chromium default values for the
SameSiteByDefaultCookies and CookiesWithoutSameSiteMustBeSecure features. See
https://www.chromium.org/updates/same-site for feature details and rollout
timeline.
With this change CefCookieManagerImpl no longer keeps a reference to the
originating CefRequestContextImpl. This means that the CefRequestContextImpl
can be destroyed if all other references are released while the
CefCookieManagerImpl exists. If CefRequestContextImpl destruction results in
the underlying CefBrowserContext being destroyed then the CefCookieManagerImpl's
reference to that CefBrowserContext will be invalidated.
This is the same ownership model introduced with CefMediaRouterImpl in the
previous commit.
Requests from the PDF viewer are not associated with a CefBrowser. Consequently,
the InterceptedRequestHandler for those requests will register as an observer of
CefContext destruction. When the browser is closed the InterceptedRequestHandler
is destroyed and an async task is posted to remove/delete the observer on the UI
thread. If CefShutdown is then called the task may execute after shutdown has
started, in which case CONTEXT_STATE_VALID() will return false. We still need to
remove the observer in this case to avoid a use-after-free in
FinishShutdownOnUIThread.
Modifying the URL in OnBeforeResourceLoad causes an internal redirect response.
In cases where the request is cross-origin and credentials mode is 'include'
the redirect response must include the "Access-Control-Allow-Credentials"
header, otherwise the request will be blocked.
When NetworkService is enabled requests created using CefFrame::CreateURLRequest
will call CefRequestHandler::GetAuthCredentials for the associated browser after
calling CefURLRequestClient::GetAuthCredentials if that call returns false.
For 303 redirects all request methods except HEAD are converted to GET as per
the latest http draft. For historical reasons the draft also allows POST
requests to be converted to GETs when following 301/302 redirects. Most major
browsers do this and so shall we. When a request is converted to GET any POST
data should also be removed.
Use 307 redirects instead if you want the request to be repeated using the same
method and POST data.
Modifying the URL in OnBeforeResourceLoad causes an internal redirect response.
In cases where the request is cross-origin (containing a non-null "Origin"
header) the redirect response must include the "Access-Control-Allow-Origin"
header, otherwise the request will be blocked.
This change also fixes a problem where existing request headers would be
discarded if the request was modified in OnBeforeResourceLoad.
Initialization of request objects requires asynchronous hops between the UI and
IO threads. In some cases the browser may be destroyed, the mojo connection may
be aborted, or the ProxyURLLoaderFactory object may be deleted while
initialization is still in progress. This change fixes crashes and adds unit
tests that try to reproduce these conditions.
To test: Run `ceftests --gtest_repeat=50
--gtest_filter=ResourceRequestHandlerTest.Basic*Abort*`
This is a speculative fix for a crash where |on_disconnect_| appears to be null
in ProxyURLLoaderFactory::MaybeDestroySelf. The hypothesis here is that
OnURLLoaderClientError is being called while the proxy object is still in-flight
to ResourceContextData::AddProxy (e.g. before SetDisconnectCallback has been
called for the proxy object). Additonally, this change protects against
MaybeDestroySelf attempting to execute |on_disconnect_| multiple times.
The behavior has changed as follows with NetworkService enabled:
- All pending and in-progress requests will now be aborted when the CEF context
or associated browser is destroyed. The OnResourceLoadComplete callback will
now also be called in this case for in-progress requests that have a handler.
- The CefResourceHandler::Cancel method will now always be called when resource
handling is complete, irrespective of whether handling completed successfully.
- Request callbacks that arrive after the OnBeforeClose callback for the
associated browser (which may happen for in-progress requests that are aborted
on browser destruction) will now always have a non-nullptr CefBrowser
parameter.
- Allow empty parameters to CefRequest and CefResponse methods where it makes
sense (e.g. resetting default response state, or clearing a referrer value).
- Fixed a reference loop that was keeping CefResourceHandler objects from being
destroyed if they were holding a callback reference (from ProcessRequest,
ReadResponse, etc.) during CEF context or associated browser destruction.
- Fixed an issue where the main frame was not detached on browser destruction
which could cause a crash due to RFH use-after-free (see issue #2498).
To test: All unit tests pass as expected.
This change fixes an issue where the cancel_callback for a pending request
might already have been executed when the OnBrowserDestroyed notification is
received.
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.
Always return ERR_NONE and the response body if a CefURLRequest completes
successfully, including for non-2xx status codes. This matches the behavior of
the old network stack.
To test: ServerTest.* tests pass with NetworkService enabled.
Pending requests that are associated with a browser will be canceled when that
browser is destroyed. Pending requests that are not associated with a browser
(e.g. created using CefURLRequest::Create), and that use the global context, may
still be pending when CefShutdown is called. For this reason the
no_debugct_check attribute has been added for CefResourceRequestHandler and
CefCookieAccessFilter interfaces.
To test: Load a YouTube video or other long-loading content in cefclient and
close the application. No assertions trigger for leaked CefFrame objects.
Requests created using CefURLRequest::Create are not associated with a
browser/frame. When originating from the render process these requests cannot be
intercepted and consequently only http(s) and blob requests are supported. To
work around this limitation a new CefFrame::CreateURLRequest method has been
added that allows the request to be associated with that browser/frame for
interception purposes.
This change also fixes an issue with the NetworkService implementation where
redirected requests could result in two parallel requests being sent to the
target server.
To test: URLRequestTest.* tests pass with NetworkService enabled.
With this change the CefCookieManager::SetSupportedSchemes method can be used
to disable all loading and saving of cookies for the associated request context.
This matches functionality that was previously available via GetBlockingManager.
This change also fixes a bug where Set-Cookie headers returned for a request
handled via CefSchemeHandlerFactory would be ignored if there was not also a
CefResourceRequestHandler returned for the request.
To test: All CookieTest.* tests pass.
To test:
- All tests pass with NetworkService disabled. DownloadTest.*, ExtensionTest.*
and PluginTest.* tests pass with NetworkService enabled.
- The PDF extension displays a file, and the download and print buttons work.
This change fixes a load hang when no custom handlers (CefResourceRequestHandler
or registered scheme handler) are found for a request.
To test: Run `cefsimple --enable-network-service` and all requests load. Test
expectations are unchanged.
This change allows the NetworkService to handle cookie load/save in cases where
cookies will not be filtered (CefResourceRequestHandler::GetCookieAccessFilter
returns null) and the request will be handled by the default network loader.
This represents a minor performance improvement by reducing the volume of cross-
process messaging in the default (no filtering or custom handing) case. Cookie
load/save still needs to be routed through the browser process if a filter is
returned, or if a CefResourceHandler is used for the request.
To test: Test expectations are unchanged.
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.*
The Chromium content layer (which also exposes the NetworkService interface)
generally runs on the UI thread. Previous use of the IO thread for CookieManager
callbacks is an implementation detail of the old network stack that shouldn't be
exposed to clients.
To test: Run ceftests. They should pass as expected.
To test: Run `ceftests --gtest_filter=CookieTest.*:-CookieTest.GetCookieManager*
--enable-network-service`
There should be no functional change when running without the NetworkService
enabled.
Known issues:
- CefCookieManager::SetSupportedSchemes is not yet implemented.