Reland: Split the WebContentsDelegate::ShouldCreateWebContents API.
Orignal CL in:
https://chromium-review.googlesource.com/c/chromium/src/+/1824321
Prior CL blew up because:
https://bugs.chromium.org/p/chromium/issues/detail?id=1011283
Original Description:
Currently ShouldCreateWebContents() does 3 separate things
(1) Tells WebContentsImpl::CreateNewWindow() to suppress default
popup creation logic.
(2) Signals to the embedder that a window creation has been attempted
(3) Allows the embedder to signal back, via use of the global routing_id
maps, that a new WebContents has been created and needs partial
initialization inside the content layer.
This is super complex, especially since only one delegate uses (3).
The new API creates 2 functions:
bool IsWebContentsCreationOverridden()
WebContents* CreateCustomWebContents()
Breaking up the API makes it cleaner. If the WebContents initialization
logic can get changed to absorb the single odd use case in (3) then
CreateCustomWebContents() could be changed to have a void return type
making the API even simpler.
Bug: 545684
Change-Id: I894ae320b55fa410d6469ff07350f4a953952f6f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1846477
Auto-Submit: Albert J. Wong <[email protected]>
Commit-Queue: John Abd-El-Malek <[email protected]>
Reviewed-by: John Abd-El-Malek <[email protected]>
Cr-Commit-Position: refs/heads/master@{#703624}
diff --git a/content/browser/content_service_delegate_impl.cc b/content/browser/content_service_delegate_impl.cc
index f792a5e..37692e762 100644
--- a/content/browser/content_service_delegate_impl.cc
+++ b/content/browser/content_service_delegate_impl.cc
@@ -104,25 +104,18 @@
}
// WebContentsDelegate:
- bool ShouldCreateWebContents(
- content::WebContents* web_contents,
- content::RenderFrameHost* opener,
+ bool IsWebContentsCreationOverridden(
content::SiteInstance* source_site_instance,
- int32_t route_id,
- int32_t main_frame_route_id,
- int32_t main_frame_widget_route_id,
content::mojom::WindowContainerType window_container_type,
const GURL& opener_url,
const std::string& frame_name,
- const GURL& target_url,
- const std::string& partition_id,
- content::SessionStorageNamespace* session_storage_namespace) override {
+ const GURL& target_url) override {
// This method is invoked when attempting to open links in a new tab, e.g.:
// <a href="https://www.google.com/" target="_blank">Link</a>
client_->DidSuppressNavigation(target_url,
WindowOpenDisposition::NEW_FOREGROUND_TAB,
/*from_user_gesture=*/true);
- return false;
+ return true;
}
WebContents* OpenURLFromTab(WebContents* source,
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 680edc97..9e0df57 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -4203,8 +4203,9 @@
cloned_namespace.get());
if (is_new_browsing_instance || !new_window) {
- // Opener suppressed or Javascript access disabled. Never tell the renderer
- // about the new window.
+ // Opener suppressed, Javascript access disabled, or delegate did not
+ // provide a handle to any windows it created. In these cases, never tell
+ // the renderer about the new window.
std::move(callback).Run(mojom::CreateNewWindowStatus::kIgnore, nullptr);
return;
}
@@ -4223,8 +4224,8 @@
if (main_frame->waiting_for_init_) {
// Need to check |waiting_for_init_| as some paths inside CreateNewWindow
- // call above (namely, if WebContentsDelegate::ShouldCreateWebContents
- // returns false) will resume requests by calling RenderFrameHostImpl::Init.
+ // call above (eg if WebContentsDelegate::IsWebContentsCreationOverridden()
+ // returns true) will resume requests by calling RenderFrameHostImpl::Init.
main_frame->frame_->BlockRequests();
}
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 3d447fd..91c9a1c 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -2824,39 +2824,14 @@
static_cast<SessionStorageNamespaceImpl*>(session_storage_namespace);
CHECK(session_storage_namespace_impl->IsFromContext(dom_storage_context));
- // TODO(crbug.com/545684): Move these closer to usage after cleaning up the
- // ShouldCreateWebContents() interface to not need the raw ID numbers.
- int render_view_route_id = MSG_ROUTING_NONE;
- int main_frame_route_id = MSG_ROUTING_NONE;
- int main_frame_widget_route_id = MSG_ROUTING_NONE;
- if (!is_new_browsing_instance) {
- render_view_route_id = opener->GetProcess()->GetNextRoutingID();
- main_frame_route_id = opener->GetProcess()->GetNextRoutingID();
- main_frame_widget_route_id = opener->GetProcess()->GetNextRoutingID();
- }
-
- if (delegate_ &&
- !delegate_->ShouldCreateWebContents(
- this, opener, source_site_instance, render_view_route_id,
- main_frame_route_id, main_frame_widget_route_id,
- params.window_container_type, opener->GetLastCommittedURL(),
- params.frame_name, params.target_url, partition_id,
- session_storage_namespace)) {
- // Note: even though we're not creating a WebContents here, it could have
- // been created by the embedder so ensure that the RenderFrameHost is
- // properly initialized.
- // It's safe to only target the frame because the render process will not
- // have a chance to create more frames at this point.
- RenderFrameHostImpl* rfh =
- RenderFrameHostImpl::FromID(render_process_id, main_frame_route_id);
- if (rfh) {
- // TODO(crbug.com/545684): It's super surprising that
- // ShouldCreateWebContents() is actually a way to allow
- // BackgroundWebContents to intercede and provide a completely different
- // webcontents. Fix that API.
- return rfh->delegate();
- }
- return nullptr;
+ if (delegate_ && delegate_->IsWebContentsCreationOverridden(
+ source_site_instance, params.window_container_type,
+ opener->GetLastCommittedURL(), params.frame_name,
+ params.target_url)) {
+ return static_cast<WebContentsImpl*>(delegate_->CreateCustomWebContents(
+ opener, source_site_instance, is_new_browsing_instance,
+ opener->GetLastCommittedURL(), params.frame_name, params.target_url,
+ partition_id, session_storage_namespace));
}
bool renderer_started_hidden =
@@ -2878,9 +2853,22 @@
// the opener's process will not given the routing IDs for the new
// objects.
create_params.renderer_initiated_creation = !is_new_browsing_instance;
- create_params.routing_id = render_view_route_id;
- create_params.main_frame_routing_id = main_frame_route_id;
- create_params.main_frame_widget_routing_id = main_frame_widget_route_id;
+
+ // If |is_new_browsing_instance| is true, defer routing_id allocation
+ // to the WebContentsImpl::Create() call. This is required because with
+ // a new browsing instance, WebContentsImpl::Create() may elect a different
+ // SiteInstance from |site_instance| (which happens if |site_instance| is
+ // nullptr for example).
+ //
+ // TODO(ajwong): This routing id allocation should be pushed down further
+ // into WebContentsImpl::Create().
+ if (!is_new_browsing_instance) {
+ create_params.routing_id = opener->GetProcess()->GetNextRoutingID();
+ create_params.main_frame_routing_id =
+ opener->GetProcess()->GetNextRoutingID();
+ create_params.main_frame_widget_routing_id =
+ opener->GetProcess()->GetNextRoutingID();
+ }
std::unique_ptr<WebContentsImpl> new_contents;
if (!is_guest) {
@@ -2924,8 +2912,9 @@
// TODO(ajwong): This should be keyed off the RenderFrame routing id or the
// FrameTreeNode id instead of the routing id of the Widget for the main
// frame. https://crbug.com/545684
- DCHECK_NE(MSG_ROUTING_NONE, main_frame_widget_route_id);
- GlobalRoutingID id(render_process_id, main_frame_widget_route_id);
+ DCHECK_NE(MSG_ROUTING_NONE, create_params.main_frame_routing_id);
+ GlobalRoutingID id(render_process_id,
+ create_params.main_frame_widget_routing_id);
pending_contents_[id] = std::move(new_contents);
AddDestructionObserver(new_contents_impl);
}
diff --git a/content/public/browser/web_contents_delegate.cc b/content/public/browser/web_contents_delegate.cc
index d868e5cc..1f046dd 100644
--- a/content/public/browser/web_contents_delegate.cc
+++ b/content/public/browser/web_contents_delegate.cc
@@ -119,20 +119,25 @@
return true;
}
-bool WebContentsDelegate::ShouldCreateWebContents(
- WebContents* web_contents,
+bool WebContentsDelegate::IsWebContentsCreationOverridden(
+ SiteInstance* source_site_instance,
+ content::mojom::WindowContainerType window_container_type,
+ const GURL& opener_url,
+ const std::string& frame_name,
+ const GURL& target_url) {
+ return false;
+}
+
+WebContents* WebContentsDelegate::CreateCustomWebContents(
RenderFrameHost* opener,
SiteInstance* source_site_instance,
- int32_t route_id,
- int32_t main_frame_route_id,
- int32_t main_frame_widget_route_id,
- content::mojom::WindowContainerType window_container_type,
+ bool is_new_browsing_instance,
const GURL& opener_url,
const std::string& frame_name,
const GURL& target_url,
const std::string& partition_id,
SessionStorageNamespace* session_storage_namespace) {
- return true;
+ return nullptr;
}
JavaScriptDialogManager* WebContentsDelegate::GetJavaScriptDialogManager(
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h
index b0f8fe9..dd9fcc8 100644
--- a/content/public/browser/web_contents_delegate.h
+++ b/content/public/browser/web_contents_delegate.h
@@ -57,7 +57,6 @@
class FileSelectListener;
class JavaScriptDialogManager;
class RenderFrameHost;
-class RenderProcessHost;
class RenderWidgetHost;
class SessionStorageNamespace;
class SiteInstance;
@@ -298,35 +297,30 @@
virtual bool OnGoToEntryOffset(int offset);
// Allows delegate to control whether a new WebContents can be created by
- // |web_contents|.
+ // the WebContents itself.
//
- // The route ID parameters passed to this method are associated with the
- // |source_site_instance|'s RenderProcessHost. They may also be
- // MSG_ROUTING_NONE. If they are valid, they correspond to a trio of
- // RenderView, RenderFrame, and RenderWidget objects that have been created in
- // the renderer, but not yet assigned a WebContents, RenderViewHost,
- // RenderFrameHost, or RenderWidgetHost.
+ // If an delegate returns true, it can optionally also override
+ // CreateCustomWebContents() below to provide their own WebContents.
+ virtual bool IsWebContentsCreationOverridden(
+ SiteInstance* source_site_instance,
+ content::mojom::WindowContainerType window_container_type,
+ const GURL& opener_url,
+ const std::string& frame_name,
+ const GURL& target_url);
+
+ // Allow delegate to creates a custom WebContents when
+ // WebContents::CreateNewWindow() is called. This function is only called
+ // when IsWebContentsCreationOverridden() returns true.
//
- // The return value is interpreted as follows:
- //
- // Return true: |web_contents| should create a WebContents.
- // Return false: |web_contents| should not create a WebContents. The
- // provisionally-created RenderView (if it exists) in the renderer
- // process will be destroyed, UNLESS the delegate, during this method,
- // itself creates a WebContents using |source_site_instance|,
- // |route_id|, |main_frame_route_id|, and |main_frame_widget_route_id|
- // as creation parameters. If this happens, the delegate assumes
- // ownership of the corresponding RenderView, etc. |web_contents| will
- // detect that this has happened by looking for the existence of a
- // RenderViewHost in |source_site_instance| with |route_id|.
- virtual bool ShouldCreateWebContents(
- WebContents* web_contents,
+ // In general, a delegate should return a pointer to a created WebContents
+ // so that the opener can be given a references to it as appropriate.
+ // Returning nullptr also makes sense if the delegate wishes to suppress
+ // all window creation, or if the delegate wants to ensure the opener
+ // cannot get a reference effectively creating a new browsing instance.
+ virtual WebContents* CreateCustomWebContents(
RenderFrameHost* opener,
SiteInstance* source_site_instance,
- int32_t route_id,
- int32_t main_frame_route_id,
- int32_t main_frame_widget_route_id,
- content::mojom::WindowContainerType window_container_type,
+ bool is_new_browsing_instance,
const GURL& opener_url,
const std::string& frame_name,
const GURL& target_url,