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.
This commit is contained in:
Marshall Greenblatt
2019-05-24 23:23:43 +03:00
parent 35295d2e27
commit 241941a44a
80 changed files with 2382 additions and 2378 deletions

View File

@@ -125,6 +125,64 @@ bool IsInternalRequest(const net::URLRequest* request) {
return false;
}
CefRefPtr<CefBrowserHostImpl> GetBrowserForRequest(
const net::URLRequest* request) {
DCHECK(request);
CEF_REQUIRE_IOT();
// When navigating the main frame a new (pre-commit) URLRequest will be
// created before the RenderFrameHost. Consequently we can't rely on
// ResourceRequestInfo::GetRenderFrameForRequest returning a valid frame
// ID. See https://crbug.com/776884 for background.
int render_process_id = -1;
int render_frame_id = MSG_ROUTING_NONE;
if (content::ResourceRequestInfo::GetRenderFrameForRequest(
request, &render_process_id, &render_frame_id) &&
render_process_id >= 0 && render_frame_id >= 0) {
return CefBrowserHostImpl::GetBrowserForFrameRoute(render_process_id,
render_frame_id);
}
content::ResourceRequestInfo* request_info =
content::ResourceRequestInfo::ForRequest(request);
if (request_info) {
return CefBrowserHostImpl::GetBrowserForFrameTreeNode(
request_info->GetFrameTreeNodeId());
}
return nullptr;
}
CefRefPtr<CefFrame> GetFrameForRequest(
scoped_refptr<CefBrowserInfo> browser_info,
const net::URLRequest* request) {
CEF_REQUIRE_IOT();
content::ResourceRequestInfo* info =
content::ResourceRequestInfo::ForRequest(request);
if (!info)
return nullptr;
// Try to locate the most reasonable match by ID.
auto frame =
browser_info->GetFrameForFrameTreeNode(info->GetFrameTreeNodeId());
if (!frame) {
frame = browser_info->GetFrameForRoute(info->GetRouteID(),
info->GetRenderFrameID());
}
if (frame)
return frame;
// The IsMainFrame() flag isn't completely reliable, so do this after
// searching by ID.
if (info->IsMainFrame())
return browser_info->GetMainFrame();
// Create a temporary frame object for requests referencing sub-frames that
// don't yet exist. Use the main frame as the parent because we don't know
// the real parent.
return browser_info->CreateTempSubFrame(CefFrameHostImpl::kInvalidFrameId);
}
CefRefPtr<CefResourceRequestHandler> GetResourceRequestHandler(
const net::URLRequest* request,
CefRefPtr<CefRequestImpl>& cef_request,
@@ -153,15 +211,14 @@ CefRefPtr<CefResourceRequestHandler> GetResourceRequestHandler(
CefRefPtr<CefResourceRequestHandler> resource_request_handler;
CefRefPtr<CefBrowserHostImpl> browser =
CefBrowserHostImpl::GetBrowserForRequest(request);
CefRefPtr<CefBrowserHostImpl> browser = GetBrowserForRequest(request);
CefRefPtr<CefFrame> frame;
CefRefPtr<CefRequestImpl> requestPtr;
// Give the browser handler a chance first.
if (browser) {
// A frame should always exist, or be created.
frame = browser->GetFrameForRequest(request);
frame = GetFrameForRequest(browser->browser_info(), request);
DCHECK(frame);
CefRefPtr<CefClient> client = browser->GetClient();