Give the main frame a RenderWidget.
Currently, RenderView is a subclass of RenderWidget, and the RenderWidget
portion is effectively treated as the the widget for the main frame as
well. For a number of reasons, this is a problematic model:
- A remote frame doesn't need a widget; however, a RenderView with a remote
main frame still has a vestigal RenderWidget.
- Code that needs to affect both RenderWidget / RenderView is awkwardly
split between them, in both content and blink.
- RenderView itself is often seen as an easy entry point to perform
page-level work in the renderer. With OOPI, this is no longer a valid
assumption.
In order to incrementally de-widgetize RenderView, the main frame will
have also have a RenderWidget, to make it consistent with the local frame
roots for subframes, which already have a RenderWidget. However, instead of
giving main frames their own RenderWidget, the main frame re-uses the
RenderView as its RenderWidget.
The rationale for taking this approach is to minimize the breakage: today,
Chrome simply doesn't expect to have two "widgets" for a frame.
Instantiating a distinct RenderWidget for the main frame can confuse code
that iterates or counts the active widgets: an example of this is the
security check for injecting WebUI bindings.
In the future, when RenderViewHost has-a RenderWidgetHost (and similarly,
when RenderViewImpl has-a RenderWidget) instead of today's is-a relation,
then it be conceptually much more straightforward to transition completely
to the new model.
BUG=419087
Review URL: https://codereview.chromium.org/1303773002
Cr-Commit-Position: refs/heads/master@{#356176}
diff --git a/content/browser/frame_host/frame_tree_node.cc b/content/browser/frame_host/frame_tree_node.cc
index c44c19c..876be33 100644
--- a/content/browser/frame_host/frame_tree_node.cc
+++ b/content/browser/frame_host/frame_tree_node.cc
@@ -131,7 +131,6 @@
// frames in the same SiteInstance as the current frame, and they can swap to
// a different one if they navigate away.
child->render_manager()->Init(
- render_manager_.current_host()->GetSiteInstance()->GetBrowserContext(),
render_manager_.current_host()->GetSiteInstance(),
render_manager_.current_host()->GetRoutingID(), frame_routing_id,
MSG_ROUTING_NONE);
diff --git a/content/browser/frame_host/frame_tree_unittest.cc b/content/browser/frame_host/frame_tree_unittest.cc
index b40628b..6804994 100644
--- a/content/browser/frame_host/frame_tree_unittest.cc
+++ b/content/browser/frame_host/frame_tree_unittest.cc
@@ -136,7 +136,7 @@
// itself. Instead, leave them in "not live" state, which is indicated by the
// * after the frame id, since this test cares about the shape, not the
// frame liveliness.
- EXPECT_EQ("1*: []", GetTreeState(frame_tree));
+ EXPECT_EQ("2*: []", GetTreeState(frame_tree));
// Simulate attaching a series of frames to build the frame tree.
frame_tree->AddFrame(root, process_id, 14, blink::WebTreeScopeType::Document,
@@ -156,10 +156,11 @@
blink::WebTreeScopeType::Document, std::string(),
blink::WebSandboxFlags::None);
- EXPECT_EQ("1*: [14*: [244*: [], 245*: []], "
- "15*: [255* 'no children node': []], "
- "16*: []]",
- GetTreeState(frame_tree));
+ EXPECT_EQ(
+ "2*: [14*: [244*: [], 245*: []], "
+ "15*: [255* 'no children node': []], "
+ "16*: []]",
+ GetTreeState(frame_tree));
FrameTreeNode* child_16 = root->child_at(2);
frame_tree->AddFrame(child_16, process_id, 264,
@@ -193,36 +194,40 @@
std::string(), blink::WebSandboxFlags::None);
// Now that's it's fully built, verify the tree structure is as expected.
- EXPECT_EQ("1*: [14*: [244*: [], 245*: []], "
- "15*: [255* 'no children node': []], "
- "16*: [264*: [], 265*: [], 266*: [], "
- "267* 'node with deep subtree': "
- "[365*: [455*: [555*: [655*: []]]]], 268*: []]]",
- GetTreeState(frame_tree));
+ EXPECT_EQ(
+ "2*: [14*: [244*: [], 245*: []], "
+ "15*: [255* 'no children node': []], "
+ "16*: [264*: [], 265*: [], 266*: [], "
+ "267* 'node with deep subtree': "
+ "[365*: [455*: [555*: [655*: []]]]], 268*: []]]",
+ GetTreeState(frame_tree));
FrameTreeNode* child_555 = child_267->child_at(0)->child_at(0)->child_at(0);
frame_tree->RemoveFrame(child_555);
- EXPECT_EQ("1*: [14*: [244*: [], 245*: []], "
- "15*: [255* 'no children node': []], "
- "16*: [264*: [], 265*: [], 266*: [], "
- "267* 'node with deep subtree': "
- "[365*: [455*: []]], 268*: []]]",
- GetTreeState(frame_tree));
+ EXPECT_EQ(
+ "2*: [14*: [244*: [], 245*: []], "
+ "15*: [255* 'no children node': []], "
+ "16*: [264*: [], 265*: [], 266*: [], "
+ "267* 'node with deep subtree': "
+ "[365*: [455*: []]], 268*: []]]",
+ GetTreeState(frame_tree));
frame_tree->RemoveFrame(child_16->child_at(1));
- EXPECT_EQ("1*: [14*: [244*: [], 245*: []], "
- "15*: [255* 'no children node': []], "
- "16*: [264*: [], 266*: [], "
- "267* 'node with deep subtree': "
- "[365*: [455*: []]], 268*: []]]",
- GetTreeState(frame_tree));
+ EXPECT_EQ(
+ "2*: [14*: [244*: [], 245*: []], "
+ "15*: [255* 'no children node': []], "
+ "16*: [264*: [], 266*: [], "
+ "267* 'node with deep subtree': "
+ "[365*: [455*: []]], 268*: []]]",
+ GetTreeState(frame_tree));
frame_tree->RemoveFrame(root->child_at(1));
- EXPECT_EQ("1*: [14*: [244*: [], 245*: []], "
- "16*: [264*: [], 266*: [], "
- "267* 'node with deep subtree': "
- "[365*: [455*: []]], 268*: []]]",
- GetTreeState(frame_tree));
+ EXPECT_EQ(
+ "2*: [14*: [244*: [], 245*: []], "
+ "16*: [264*: [], 266*: [], "
+ "267* 'node with deep subtree': "
+ "[365*: [455*: []]], 268*: []]]",
+ GetTreeState(frame_tree));
}
// Ensure frames can be found by frame_tree_node_id, routing ID, or name.
@@ -312,7 +317,7 @@
TEST_F(FrameTreeTest, ObserverWalksTreeDuringFrameCreation) {
TreeWalkingWebContentsLogger activity(contents());
contents()->NavigateAndCommit(GURL("http://www.google.com"));
- EXPECT_EQ("RenderFrameCreated(1) -> 1: []", activity.GetLog());
+ EXPECT_EQ("RenderFrameCreated(2) -> 2: []", activity.GetLog());
FrameTree* frame_tree = contents()->GetFrameTree();
FrameTreeNode* root = frame_tree->root();
@@ -322,20 +327,20 @@
std::string(),
blink::WebSandboxFlags::None);
EXPECT_EQ(
- "RenderFrameHostChanged(new)(14) -> 1: []\n"
- "RenderFrameCreated(14) -> 1: [14: []]",
+ "RenderFrameHostChanged(new)(14) -> 2: []\n"
+ "RenderFrameCreated(14) -> 2: [14: []]",
activity.GetLog());
main_test_rfh()->OnCreateChildFrame(18, blink::WebTreeScopeType::Document,
std::string(),
blink::WebSandboxFlags::None);
EXPECT_EQ(
- "RenderFrameHostChanged(new)(18) -> 1: [14: []]\n"
- "RenderFrameCreated(18) -> 1: [14: [], 18: []]",
+ "RenderFrameHostChanged(new)(18) -> 2: [14: []]\n"
+ "RenderFrameCreated(18) -> 2: [14: [], 18: []]",
activity.GetLog());
frame_tree->RemoveFrame(root->child_at(0));
- EXPECT_EQ("RenderFrameDeleted(14) -> 1: [18: []]", activity.GetLog());
+ EXPECT_EQ("RenderFrameDeleted(14) -> 2: [18: []]", activity.GetLog());
frame_tree->RemoveFrame(root->child_at(0));
- EXPECT_EQ("RenderFrameDeleted(18) -> 1: []", activity.GetLog());
+ EXPECT_EQ("RenderFrameDeleted(18) -> 2: []", activity.GetLog());
}
// Make sure that WebContentsObservers see a consistent view of the tree after
@@ -343,30 +348,30 @@
TEST_F(FrameTreeTest, ObserverWalksTreeAfterCrash) {
TreeWalkingWebContentsLogger activity(contents());
contents()->NavigateAndCommit(GURL("http://www.google.com"));
- EXPECT_EQ("RenderFrameCreated(1) -> 1: []", activity.GetLog());
+ EXPECT_EQ("RenderFrameCreated(2) -> 2: []", activity.GetLog());
main_test_rfh()->OnCreateChildFrame(22, blink::WebTreeScopeType::Document,
std::string(),
blink::WebSandboxFlags::None);
EXPECT_EQ(
- "RenderFrameHostChanged(new)(22) -> 1: []\n"
- "RenderFrameCreated(22) -> 1: [22: []]",
+ "RenderFrameHostChanged(new)(22) -> 2: []\n"
+ "RenderFrameCreated(22) -> 2: [22: []]",
activity.GetLog());
main_test_rfh()->OnCreateChildFrame(23, blink::WebTreeScopeType::Document,
std::string(),
blink::WebSandboxFlags::None);
EXPECT_EQ(
- "RenderFrameHostChanged(new)(23) -> 1: [22: []]\n"
- "RenderFrameCreated(23) -> 1: [22: [], 23: []]",
+ "RenderFrameHostChanged(new)(23) -> 2: [22: []]\n"
+ "RenderFrameCreated(23) -> 2: [22: [], 23: []]",
activity.GetLog());
// Crash the renderer
main_test_rfh()->GetProcess()->SimulateCrash();
EXPECT_EQ(
- "RenderProcessGone -> 1*: [22*: [], 23*: []]\n"
- "RenderFrameDeleted(23) -> 1*: [22*: [], 23*: []]\n"
- "RenderFrameDeleted(22) -> 1*: [22*: [], 23*: []]\n"
- "RenderFrameDeleted(1) -> 1*: []",
+ "RenderProcessGone -> 2*: [22*: [], 23*: []]\n"
+ "RenderFrameDeleted(23) -> 2*: [22*: [], 23*: []]\n"
+ "RenderFrameDeleted(22) -> 2*: [22*: [], 23*: []]\n"
+ "RenderFrameDeleted(2) -> 2*: []",
activity.GetLog());
}
@@ -378,13 +383,13 @@
FrameTreeNode* root = frame_tree->root();
int process_id = root->current_frame_host()->GetProcess()->GetID();
- ASSERT_EQ("1: []", GetTreeState(frame_tree));
+ ASSERT_EQ("2: []", GetTreeState(frame_tree));
// Simulate attaching a frame from mismatched process id.
ASSERT_FALSE(frame_tree->AddFrame(
root, process_id + 1, 1, blink::WebTreeScopeType::Document, std::string(),
blink::WebSandboxFlags::None));
- ASSERT_EQ("1: []", GetTreeState(frame_tree));
+ ASSERT_EQ("2: []", GetTreeState(frame_tree));
}
// Ensure that frames removed while a process has crashed are not preserved in
diff --git a/content/browser/frame_host/interstitial_page_impl.cc b/content/browser/frame_host/interstitial_page_impl.cc
index 810647124..c3e6fa1d 100644
--- a/content/browser/frame_host/interstitial_page_impl.cc
+++ b/content/browser/frame_host/interstitial_page_impl.cc
@@ -595,9 +595,12 @@
new SessionStorageNamespaceImpl(dom_storage_context);
// Use the RenderViewHost from our FrameTree.
+ // TODO(avi): The view routing ID can be restored to MSG_ROUTING_NONE once
+ // RenderViewHostImpl has-a RenderWidgetHostImpl. https://crbug.com/545684
+ int32_t widget_routing_id = site_instance->GetProcess()->GetNextRoutingID();
frame_tree_.root()->render_manager()->Init(
- browser_context, site_instance.get(), MSG_ROUTING_NONE, MSG_ROUTING_NONE,
- MSG_ROUTING_NONE);
+ site_instance.get(), widget_routing_id, MSG_ROUTING_NONE,
+ widget_routing_id);
return frame_tree_.root()->current_frame_host()->render_view_host();
}
@@ -761,8 +764,9 @@
void InterstitialPageImpl::CreateNewWindow(
SiteInstance* source_site_instance,
- int route_id,
- int main_frame_route_id,
+ int32_t route_id,
+ int32_t main_frame_route_id,
+ int32_t main_frame_widget_route_id,
const ViewHostMsg_CreateWindow_Params& params,
SessionStorageNamespace* session_storage_namespace) {
NOTREACHED() << "InterstitialPage does not support showing popups yet.";
diff --git a/content/browser/frame_host/interstitial_page_impl.h b/content/browser/frame_host/interstitial_page_impl.h
index 1dd685d..cd15e8d 100644
--- a/content/browser/frame_host/interstitial_page_impl.h
+++ b/content/browser/frame_host/interstitial_page_impl.h
@@ -122,8 +122,9 @@
gfx::Rect GetRootWindowResizerRect() const override;
void CreateNewWindow(
SiteInstance* source_site_instance,
- int route_id,
- int main_frame_route_id,
+ int32_t route_id,
+ int32_t main_frame_route_id,
+ int32_t main_frame_widget_route_id,
const ViewHostMsg_CreateWindow_Params& params,
SessionStorageNamespace* session_storage_namespace) override;
void CreateNewWidget(int32 render_process_id,
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 7868121..06a15f8 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -214,9 +214,20 @@
&RenderFrameHostImpl::OnSwappedOut, weak_ptr_factory_.GetWeakPtr())));
if (widget_routing_id != MSG_ROUTING_NONE) {
- render_widget_host_ = new RenderWidgetHostImpl(rwh_delegate, GetProcess(),
- widget_routing_id, hidden);
- render_widget_host_->set_owned_by_render_frame_host(true);
+ // TODO(avi): Once RenderViewHostImpl has-a RenderWidgetHostImpl, the main
+ // render frame should probably start owning the RenderWidgetHostImpl,
+ // so this logic checking for an already existing RWHI should be removed.
+ // https://crbug.com/545684
+ render_widget_host_ =
+ RenderWidgetHostImpl::FromID(GetProcess()->GetID(), widget_routing_id);
+ if (!render_widget_host_) {
+ DCHECK(frame_tree_node->parent());
+ render_widget_host_ = new RenderWidgetHostImpl(rwh_delegate, GetProcess(),
+ widget_routing_id, hidden);
+ render_widget_host_->set_owned_by_render_frame_host(true);
+ } else {
+ DCHECK(!render_widget_host_->owned_by_render_frame_host());
+ }
}
}
@@ -233,10 +244,6 @@
if (IsRFHStateActive(rfh_state_))
GetSiteInstance()->decrement_active_frame_count();
- // Notify the FrameTree that this RFH is going away, allowing it to shut down
- // the corresponding RenderViewHost if it is no longer needed.
- frame_tree_->ReleaseRenderViewHostRef(render_view_host_);
-
// NULL out the swapout timer; in crash dumps this member will be null only if
// the dtor has run.
swapout_event_monitor_timeout_.reset();
@@ -245,10 +252,15 @@
iter.second.Run(false);
}
- if (render_widget_host_) {
+ if (render_widget_host_ &&
+ render_widget_host_->owned_by_render_frame_host()) {
// Shutdown causes the RenderWidgetHost to delete itself.
render_widget_host_->Shutdown();
}
+
+ // Notify the FrameTree that this RFH is going away, allowing it to shut down
+ // the corresponding RenderViewHost if it is no longer needed.
+ frame_tree_->ReleaseRenderViewHostRef(render_view_host_);
}
int RenderFrameHostImpl::GetRoutingID() {
@@ -652,7 +664,10 @@
// The RenderWidgetHost takes ownership of its view. It is tied to the
// lifetime of the current RenderProcessHost for this RenderFrameHost.
- if (render_widget_host_) {
+ // TODO(avi): This will need to change to initialize a
+ // RenderWidgetHostViewAura for the main frame once RenderViewHostImpl has-a
+ // RenderWidgetHostImpl. https://crbug.com/545684
+ if (parent_routing_id != MSG_ROUTING_NONE && render_widget_host_) {
RenderWidgetHostView* rwhv =
new RenderWidgetHostViewChildFrame(render_widget_host_);
rwhv->Hide();
@@ -954,15 +969,7 @@
}
RenderWidgetHostImpl* RenderFrameHostImpl::GetRenderWidgetHost() {
- if (render_widget_host_)
- return render_widget_host_;
-
- // TODO(kenrb): Remove this fallback and have the top-level frame have a
- // widget host just like all the other frames.
- if (!GetParent())
- return render_view_host_->GetWidget();
-
- return nullptr;
+ return render_widget_host_;
}
RenderWidgetHostView* RenderFrameHostImpl::GetView() {
@@ -973,7 +980,8 @@
frame = static_cast<RenderFrameHostImpl*>(frame->GetParent());
}
- return render_view_host_->GetWidget()->GetView();
+ NOTREACHED();
+ return nullptr;
}
int RenderFrameHostImpl::GetEnabledBindings() {
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc
index 059e2b9..b38cc536 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -253,17 +253,16 @@
SetRenderFrameHost(scoped_ptr<RenderFrameHostImpl>());
}
-void RenderFrameHostManager::Init(BrowserContext* browser_context,
- SiteInstance* site_instance,
+void RenderFrameHostManager::Init(SiteInstance* site_instance,
int32 view_routing_id,
int32 frame_routing_id,
int32 widget_routing_id) {
- // Create a RenderViewHost and RenderFrameHost, once we have an instance. It
- // is important to immediately give this SiteInstance to a RenderViewHost so
- // that the SiteInstance is ref counted.
- if (!site_instance)
- site_instance = SiteInstance::Create(browser_context);
-
+ DCHECK(site_instance);
+ // TODO(avi): While RenderViewHostImpl is-a RenderWidgetHostImpl, this must
+ // hold true to avoid having two RenderWidgetHosts for the top-level frame.
+ // https://crbug.com/545684
+ DCHECK_IMPLIES(frame_tree_node_->IsMainFrame(),
+ view_routing_id == widget_routing_id);
int flags = delegate_->IsHidden() ? CREATE_RF_HIDDEN : 0;
SetRenderFrameHost(CreateRenderFrameHost(site_instance, view_routing_id,
frame_routing_id, widget_routing_id,
@@ -1711,6 +1710,20 @@
if (frame_tree_node_->IsMainFrame()) {
render_view_host = frame_tree->CreateRenderViewHost(
site_instance, view_routing_id, frame_routing_id, swapped_out, hidden);
+ // TODO(avi): It's a bit bizarre that this logic lives here instead of in
+ // CreateRenderFrame(). It turns out that FrameTree::CreateRenderViewHost
+ // doesn't /always/ create a new RenderViewHost. It first tries to find an
+ // already existing one to reuse by a SiteInstance lookup. If it finds one,
+ // then the supplied routing IDs are completely ignored.
+ // CreateRenderFrame() could do this lookup too, but it seems redundant to
+ // do this lookup in two places. This is a good yak shave to clean up, or,
+ // if just ignored, should be an easy cleanup once RenderViewHostImpl has-a
+ // RenderWidgetHostImpl. https://crbug.com/545684
+ if (view_routing_id == MSG_ROUTING_NONE) {
+ widget_routing_id = render_view_host->GetRoutingID();
+ } else {
+ DCHECK_EQ(view_routing_id, render_view_host->GetRoutingID());
+ }
} else {
render_view_host = frame_tree->GetRenderViewHost(site_instance);
CHECK(render_view_host);
diff --git a/content/browser/frame_host/render_frame_host_manager.h b/content/browser/frame_host/render_frame_host_manager.h
index 3cf8ea5..e490e88 100644
--- a/content/browser/frame_host/render_frame_host_manager.h
+++ b/content/browser/frame_host/render_frame_host_manager.h
@@ -201,8 +201,7 @@
~RenderFrameHostManager();
// For arguments, see WebContentsImpl constructor.
- void Init(BrowserContext* browser_context,
- SiteInstance* site_instance,
+ void Init(SiteInstance* site_instance,
int32 view_routing_id,
int32 frame_routing_id,
int32 widget_routing_id);
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc
index 91e81fa5..8861e37 100644
--- a/content/browser/renderer_host/render_message_filter.cc
+++ b/content/browser/renderer_host/render_message_filter.cc
@@ -235,9 +235,7 @@
void RenderMessageFilter::OnCreateWindow(
const ViewHostMsg_CreateWindow_Params& params,
- int* route_id,
- int* main_frame_route_id,
- int64* cloned_session_storage_namespace_id) {
+ ViewHostMsg_CreateWindow_Reply* reply) {
bool no_javascript_access;
bool can_create_window =
@@ -259,9 +257,10 @@
&no_javascript_access);
if (!can_create_window) {
- *route_id = MSG_ROUTING_NONE;
- *main_frame_route_id = MSG_ROUTING_NONE;
- *cloned_session_storage_namespace_id = 0;
+ reply->route_id = MSG_ROUTING_NONE;
+ reply->main_frame_route_id = MSG_ROUTING_NONE;
+ reply->main_frame_widget_route_id = MSG_ROUTING_NONE;
+ reply->cloned_session_storage_namespace_id = 0;
return;
}
@@ -269,14 +268,12 @@
scoped_refptr<SessionStorageNamespaceImpl> cloned_namespace =
new SessionStorageNamespaceImpl(dom_storage_context_.get(),
params.session_storage_namespace_id);
- *cloned_session_storage_namespace_id = cloned_namespace->id();
+ reply->cloned_session_storage_namespace_id = cloned_namespace->id();
- render_widget_helper_->CreateNewWindow(params,
- no_javascript_access,
- PeerHandle(),
- route_id,
- main_frame_route_id,
- cloned_namespace.get());
+ render_widget_helper_->CreateNewWindow(
+ params, no_javascript_access, PeerHandle(), &reply->route_id,
+ &reply->main_frame_route_id, &reply->main_frame_widget_route_id,
+ cloned_namespace.get());
}
void RenderMessageFilter::OnCreateWidget(int opener_id,
diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h
index 4889e32..2fdf7f6 100644
--- a/content/browser/renderer_host/render_message_filter.h
+++ b/content/browser/renderer_host/render_message_filter.h
@@ -43,6 +43,7 @@
class GURL;
struct FontDescriptor;
struct ViewHostMsg_CreateWindow_Params;
+struct ViewHostMsg_CreateWindow_Reply;
namespace blink {
struct WebScreenInfo;
@@ -118,9 +119,7 @@
void OnGetProcessMemorySizes(size_t* private_bytes, size_t* shared_bytes);
void OnCreateWindow(const ViewHostMsg_CreateWindow_Params& params,
- int* route_id,
- int* main_frame_route_id,
- int64* cloned_session_storage_namespace_id);
+ ViewHostMsg_CreateWindow_Reply* reply);
void OnCreateWidget(int opener_id,
blink::WebPopupType popup_type,
int* route_id);
diff --git a/content/browser/renderer_host/render_view_host_delegate.h b/content/browser/renderer_host/render_view_host_delegate.h
index 8805892..37bb5421 100644
--- a/content/browser/renderer_host/render_view_host_delegate.h
+++ b/content/browser/renderer_host/render_view_host_delegate.h
@@ -213,8 +213,9 @@
// new window.
virtual void CreateNewWindow(
SiteInstance* source_site_instance,
- int route_id,
- int main_frame_route_id,
+ int32_t route_id,
+ int32_t main_frame_route_id,
+ int32_t main_frame_widget_route_id,
const ViewHostMsg_CreateWindow_Params& params,
SessionStorageNamespace* session_storage_namespace) {}
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index 328f40b..877062c6 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -315,6 +315,13 @@
params.web_preferences = GetWebkitPreferences();
params.view_id = GetRoutingID();
params.main_frame_routing_id = main_frame_routing_id_;
+ if (main_frame_routing_id_ != MSG_ROUTING_NONE) {
+ RenderFrameHostImpl* main_rfh = RenderFrameHostImpl::FromID(
+ GetProcess()->GetID(), main_frame_routing_id_);
+ DCHECK(main_rfh);
+ RenderWidgetHostImpl* main_rwh = main_rfh->GetRenderWidgetHost();
+ params.main_frame_widget_routing_id = main_rwh->GetRoutingID();
+ }
params.session_storage_namespace_id =
delegate_->GetSessionStorageNamespace(instance_.get())->id();
// Ensure the RenderView sets its opener correctly.
@@ -1009,8 +1016,9 @@
}
void RenderViewHostImpl::CreateNewWindow(
- int route_id,
- int main_frame_route_id,
+ int32_t route_id,
+ int32_t main_frame_route_id,
+ int32_t main_frame_widget_route_id,
const ViewHostMsg_CreateWindow_Params& params,
SessionStorageNamespace* session_storage_namespace) {
ViewHostMsg_CreateWindow_Params validated_params(params);
@@ -1019,7 +1027,8 @@
GetProcess()->FilterURL(true, &validated_params.opener_security_origin);
delegate_->CreateNewWindow(GetSiteInstance(), route_id, main_frame_route_id,
- validated_params, session_storage_namespace);
+ main_frame_widget_route_id, validated_params,
+ session_storage_namespace);
}
void RenderViewHostImpl::CreateNewWidget(int32 route_id,
diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h
index 5889857..83211f1b 100644
--- a/content/browser/renderer_host/render_view_host_impl.h
+++ b/content/browser/renderer_host/render_view_host_impl.h
@@ -291,11 +291,11 @@
gfx::Rect GetRootWindowResizerRect() const override;
// Creates a new RenderView with the given route id.
- void CreateNewWindow(
- int route_id,
- int main_frame_route_id,
- const ViewHostMsg_CreateWindow_Params& params,
- SessionStorageNamespace* session_storage_namespace);
+ void CreateNewWindow(int32_t route_id,
+ int32_t main_frame_route_id,
+ int32_t main_frame_widget_route_id,
+ const ViewHostMsg_CreateWindow_Params& params,
+ SessionStorageNamespace* session_storage_namespace);
// Creates a new RenderWidget with the given route id. |popup_type| indicates
// if this widget is a popup and what kind of popup it is (select, autofill).
diff --git a/content/browser/renderer_host/render_widget_helper.cc b/content/browser/renderer_host/render_widget_helper.cc
index 0aad52a6d..72b2d55 100644
--- a/content/browser/renderer_host/render_widget_helper.cc
+++ b/content/browser/renderer_host/render_widget_helper.cc
@@ -102,8 +102,9 @@
const ViewHostMsg_CreateWindow_Params& params,
bool no_javascript_access,
base::ProcessHandle render_process,
- int* route_id,
- int* main_frame_route_id,
+ int32_t* route_id,
+ int32_t* main_frame_route_id,
+ int32_t* main_frame_widget_route_id,
SessionStorageNamespace* session_storage_namespace) {
if (params.opener_suppressed || no_javascript_access) {
// If the opener is supppressed or script access is disallowed, we should
@@ -113,9 +114,14 @@
// in OnCreateWindowOnUI, using the params provided here.
*route_id = MSG_ROUTING_NONE;
*main_frame_route_id = MSG_ROUTING_NONE;
+ *main_frame_widget_route_id = MSG_ROUTING_NONE;
} else {
*route_id = GetNextRoutingID();
*main_frame_route_id = GetNextRoutingID();
+ // TODO(avi): When RenderViewHostImpl has-a RenderWidgetHostImpl, this
+ // should be updated to give the widget a distinct routing ID.
+ // https://crbug.com/545684
+ *main_frame_widget_route_id = *route_id;
// Block resource requests until the view is created, since the HWND might
// be needed if a response ends up creating a plugin.
resource_dispatcher_host_->BlockRequestsForRoute(
@@ -126,21 +132,23 @@
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&RenderWidgetHelper::OnCreateWindowOnUI,
- this, params, *route_id, *main_frame_route_id,
+ base::Bind(&RenderWidgetHelper::OnCreateWindowOnUI, this, params,
+ *route_id, *main_frame_route_id, *main_frame_widget_route_id,
make_scoped_refptr(session_storage_namespace)));
}
void RenderWidgetHelper::OnCreateWindowOnUI(
const ViewHostMsg_CreateWindow_Params& params,
- int route_id,
- int main_frame_route_id,
+ int32_t route_id,
+ int32_t main_frame_route_id,
+ int32_t main_frame_widget_route_id,
SessionStorageNamespace* session_storage_namespace) {
RenderViewHostImpl* host =
RenderViewHostImpl::FromID(render_process_id_, params.opener_id);
if (host)
- host->CreateNewWindow(route_id, main_frame_route_id, params,
- session_storage_namespace);
+ host->CreateNewWindow(route_id, main_frame_route_id,
+ main_frame_widget_route_id, params,
+ session_storage_namespace);
}
void RenderWidgetHelper::OnResumeRequestsForView(int route_id) {
diff --git a/content/browser/renderer_host/render_widget_helper.h b/content/browser/renderer_host/render_widget_helper.h
index 18576a41..881dd50 100644
--- a/content/browser/renderer_host/render_widget_helper.h
+++ b/content/browser/renderer_host/render_widget_helper.h
@@ -99,13 +99,13 @@
// IO THREAD ONLY -----------------------------------------------------------
- void CreateNewWindow(
- const ViewHostMsg_CreateWindow_Params& params,
- bool no_javascript_access,
- base::ProcessHandle render_process,
- int* route_id,
- int* main_frame_route_id,
- SessionStorageNamespace* session_storage_namespace);
+ void CreateNewWindow(const ViewHostMsg_CreateWindow_Params& params,
+ bool no_javascript_access,
+ base::ProcessHandle render_process,
+ int32_t* route_id,
+ int32_t* main_frame_route_id,
+ int32_t* main_frame_widget_route_id,
+ SessionStorageNamespace* session_storage_namespace);
void CreateNewWidget(int opener_id,
blink::WebPopupType popup_type,
int* route_id);
@@ -119,11 +119,11 @@
~RenderWidgetHelper();
// Called on the UI thread to finish creating a window.
- void OnCreateWindowOnUI(
- const ViewHostMsg_CreateWindow_Params& params,
- int route_id,
- int main_frame_route_id,
- SessionStorageNamespace* session_storage_namespace);
+ void OnCreateWindowOnUI(const ViewHostMsg_CreateWindow_Params& params,
+ int32_t route_id,
+ int32_t main_frame_route_id,
+ int32_t main_frame_widget_route_id,
+ SessionStorageNamespace* session_storage_namespace);
// Called on the IO thread after a window was created on the UI thread.
void OnResumeRequestsForView(int route_id);
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index bd6bc76..240eec1 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -187,6 +187,9 @@
void set_owned_by_render_frame_host(bool owned_by_rfh) {
owned_by_render_frame_host_ = owned_by_rfh;
}
+ bool owned_by_render_frame_host() const {
+ return owned_by_render_frame_host_;
+ }
// Tells the renderer to die and then calls Destroy().
virtual void Shutdown();
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
index 2c5acc4..1358af2 100644
--- a/content/browser/security_exploit_browsertest.cc
+++ b/content/browser/security_exploit_browsertest.cc
@@ -196,7 +196,7 @@
// process.
IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest,
AttemptDuplicateRenderViewHost) {
- int duplicate_routing_id = MSG_ROUTING_NONE;
+ int32_t duplicate_routing_id = MSG_ROUTING_NONE;
RenderViewHostImpl* pending_rvh =
PrepareToDuplicateHosts(shell(), &duplicate_routing_id);
EXPECT_NE(MSG_ROUTING_NONE, duplicate_routing_id);
@@ -213,10 +213,12 @@
scoped_refptr<SessionStorageNamespaceImpl> session_storage(
new SessionStorageNamespaceImpl(dom_storage_context));
// Cause a deliberate collision in routing ids.
- int main_frame_routing_id = duplicate_routing_id + 1;
- pending_rvh->CreateNewWindow(duplicate_routing_id,
- main_frame_routing_id,
- params,
+ int32_t main_frame_routing_id = duplicate_routing_id + 1;
+ // TODO(avi): This should be made unique from the view routing ID once
+ // RenderViewHostImpl has-a RenderWidgetHostImpl. https://crbug.com/545684
+ int32_t main_frame_widget_routing_id = duplicate_routing_id;
+ pending_rvh->CreateNewWindow(duplicate_routing_id, main_frame_routing_id,
+ main_frame_widget_routing_id, params,
session_storage.get());
// If the above operation doesn't cause a crash, the test has succeeded!
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 6b1407b7..5dce2b39 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -1343,14 +1343,33 @@
// it should be hidden.
should_normally_be_visible_ = !params.initially_hidden;
- // Either both routing ids can be given, or neither can be.
+ // The routing ids must either all be set or all be unset.
DCHECK((params.routing_id == MSG_ROUTING_NONE &&
- params.main_frame_routing_id == MSG_ROUTING_NONE) ||
+ params.main_frame_routing_id == MSG_ROUTING_NONE &&
+ params.main_frame_widget_routing_id == MSG_ROUTING_NONE) ||
(params.routing_id != MSG_ROUTING_NONE &&
- params.main_frame_routing_id != MSG_ROUTING_NONE));
- GetRenderManager()->Init(params.browser_context, params.site_instance,
- params.routing_id, params.main_frame_routing_id,
- MSG_ROUTING_NONE);
+ params.main_frame_routing_id != MSG_ROUTING_NONE &&
+ params.main_frame_widget_routing_id != MSG_ROUTING_NONE));
+
+ scoped_refptr<SiteInstance> site_instance = params.site_instance;
+ if (!site_instance)
+ site_instance = SiteInstance::Create(params.browser_context);
+
+ // A main RenderFrameHost always has a RenderWidgetHost, since it is always a
+ // local root by definition.
+ // TODO(avi): Once RenderViewHostImpl has-a RenderWidgetHostImpl, it will no
+ // longer be necessary to eagerly grab a routing ID for the view.
+ // https://crbug.com/545684
+ int32_t view_routing_id = params.routing_id;
+ int32_t main_frame_widget_routing_id = params.main_frame_widget_routing_id;
+ if (main_frame_widget_routing_id == MSG_ROUTING_NONE) {
+ view_routing_id = main_frame_widget_routing_id =
+ site_instance->GetProcess()->GetNextRoutingID();
+ }
+
+ GetRenderManager()->Init(site_instance.get(), view_routing_id,
+ params.main_frame_routing_id,
+ main_frame_widget_routing_id);
frame_tree_.root()->SetFrameName(params.main_frame_name);
WebContentsViewDelegate* delegate =
@@ -1661,8 +1680,9 @@
void WebContentsImpl::CreateNewWindow(
SiteInstance* source_site_instance,
- int route_id,
- int main_frame_route_id,
+ int32_t route_id,
+ int32_t main_frame_route_id,
+ int32_t main_frame_widget_route_id,
const ViewHostMsg_CreateWindow_Params& params,
SessionStorageNamespace* session_storage_namespace) {
// We usually create the new window in the same BrowsingInstance (group of
@@ -1721,14 +1741,10 @@
CHECK(session_storage_namespace_impl->IsFromContext(dom_storage_context));
if (delegate_ &&
- !delegate_->ShouldCreateWebContents(this,
- route_id,
- main_frame_route_id,
- params.window_container_type,
- params.frame_name,
- params.target_url,
- partition_id,
- session_storage_namespace)) {
+ !delegate_->ShouldCreateWebContents(
+ this, route_id, main_frame_route_id, main_frame_widget_route_id,
+ params.window_container_type, params.frame_name, params.target_url,
+ partition_id, session_storage_namespace)) {
if (route_id != MSG_ROUTING_NONE &&
!RenderViewHost::FromID(render_process_id, route_id)) {
// If the embedder didn't create a WebContents for this route, we need to
@@ -1738,6 +1754,8 @@
GetRenderViewHost()->GetProcess()->ResumeRequestsForView(route_id);
GetRenderViewHost()->GetProcess()->ResumeRequestsForView(
main_frame_route_id);
+ GetRenderViewHost()->GetProcess()->ResumeRequestsForView(
+ main_frame_widget_route_id);
return;
}
@@ -1746,6 +1764,7 @@
CreateParams create_params(GetBrowserContext(), site_instance.get());
create_params.routing_id = route_id;
create_params.main_frame_routing_id = main_frame_route_id;
+ create_params.main_frame_widget_routing_id = main_frame_widget_route_id;
create_params.main_frame_name = params.frame_name;
create_params.opener_render_process_id = render_process_id;
create_params.opener_render_frame_id = params.opener_render_frame_id;
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 35da9b59..d9d9d20 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -491,8 +491,9 @@
void LostMouseLock() override;
void CreateNewWindow(
SiteInstance* source_site_instance,
- int route_id,
- int main_frame_route_id,
+ int32_t route_id,
+ int32_t main_frame_route_id,
+ int32_t main_frame_widget_route_id,
const ViewHostMsg_CreateWindow_Params& params,
SessionStorageNamespace* session_storage_namespace) override;
void CreateNewWidget(int32 render_process_id,
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index cec3302..748c676 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -341,6 +341,21 @@
IPC_STRUCT_MEMBER(std::vector<base::string16>, additional_features)
IPC_STRUCT_END()
+IPC_STRUCT_BEGIN(ViewHostMsg_CreateWindow_Reply)
+ // The ID of the view to be created. If the ID is MSG_ROUTING_NONE, then the
+ // view couldn't be created.
+ IPC_STRUCT_MEMBER(int32_t, route_id, MSG_ROUTING_NONE)
+
+ // The ID of the main frame hosted in the view.
+ IPC_STRUCT_MEMBER(int32_t, main_frame_route_id, MSG_ROUTING_NONE)
+
+ // The ID of the widget for the main frame.
+ IPC_STRUCT_MEMBER(int32_t, main_frame_widget_route_id, MSG_ROUTING_NONE)
+
+ // TODO(dcheng): No clue. This is kind of duplicated from ViewMsg_New_Params.
+ IPC_STRUCT_MEMBER(int64, cloned_session_storage_namespace_id)
+IPC_STRUCT_END()
+
IPC_STRUCT_BEGIN(ViewHostMsg_CreateWorker_Params)
// URL for the worker script.
IPC_STRUCT_MEMBER(GURL, url)
@@ -480,17 +495,20 @@
IPC_STRUCT_MEMBER(content::WebPreferences, web_preferences)
// The ID of the view to be created.
- IPC_STRUCT_MEMBER(int32, view_id)
+ IPC_STRUCT_MEMBER(int32_t, view_id, MSG_ROUTING_NONE)
// The ID of the main frame hosted in the view.
- IPC_STRUCT_MEMBER(int32, main_frame_routing_id)
+ IPC_STRUCT_MEMBER(int32_t, main_frame_routing_id, MSG_ROUTING_NONE)
+
+ // The ID of the widget for the main frame.
+ IPC_STRUCT_MEMBER(int32_t, main_frame_widget_routing_id, MSG_ROUTING_NONE)
// The session storage namespace ID this view should use.
IPC_STRUCT_MEMBER(int64, session_storage_namespace_id)
// The route ID of the opener RenderFrame or RenderFrameProxy, if we need to
// set one (MSG_ROUTING_NONE otherwise).
- IPC_STRUCT_MEMBER(int, opener_frame_route_id)
+ IPC_STRUCT_MEMBER(int, opener_frame_route_id, MSG_ROUTING_NONE)
// Whether the RenderView should initially be swapped out.
IPC_STRUCT_MEMBER(bool, swapped_out)
@@ -503,7 +521,7 @@
// The ID of the proxy object for the main frame in this view. It is only
// used if |swapped_out| is true.
- IPC_STRUCT_MEMBER(int32, proxy_routing_id)
+ IPC_STRUCT_MEMBER(int32_t, proxy_routing_id, MSG_ROUTING_NONE)
// Whether the RenderView should initially be hidden.
IPC_STRUCT_MEMBER(bool, hidden)
@@ -967,12 +985,11 @@
bool /* enabled */)
// Sent by the renderer when it is creating a new window. The browser creates a
-// tab for it. If route_id is MSG_ROUTING_NONE, the view couldn't be created.
-IPC_SYNC_MESSAGE_CONTROL1_3(ViewHostMsg_CreateWindow,
+// tab for it. If |reply.route_id| is MSG_ROUTING_NONE, the view couldn't be
+// created.
+IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_CreateWindow,
ViewHostMsg_CreateWindow_Params,
- int /* route_id */,
- int /* main_frame_route_id */,
- int64 /* cloned_session_storage_namespace_id */)
+ ViewHostMsg_CreateWindow_Reply)
// Similar to ViewHostMsg_CreateWindow, except used for sub-widgets, like
// <select> dropdowns. This message is sent to the WebContentsImpl that
diff --git a/content/public/browser/web_contents.cc b/content/public/browser/web_contents.cc
index 887f242f..1b6d8a68 100644
--- a/content/public/browser/web_contents.cc
+++ b/content/public/browser/web_contents.cc
@@ -10,21 +10,10 @@
namespace content {
WebContents::CreateParams::CreateParams(BrowserContext* context)
- : browser_context(context),
- site_instance(nullptr),
- opener_render_process_id(content::ChildProcessHost::kInvalidUniqueID),
- opener_render_frame_id(MSG_ROUTING_NONE),
- opener_suppressed(false),
- created_with_opener(false),
- routing_id(MSG_ROUTING_NONE),
- main_frame_routing_id(MSG_ROUTING_NONE),
- initially_hidden(false),
- guest_delegate(nullptr),
- context(nullptr),
- renderer_initiated_creation(false) {}
+ : CreateParams(context, nullptr) {}
-WebContents::CreateParams::CreateParams(
- BrowserContext* context, SiteInstance* site)
+WebContents::CreateParams::CreateParams(BrowserContext* context,
+ SiteInstance* site)
: browser_context(context),
site_instance(site),
opener_render_process_id(content::ChildProcessHost::kInvalidUniqueID),
@@ -33,6 +22,7 @@
created_with_opener(false),
routing_id(MSG_ROUTING_NONE),
main_frame_routing_id(MSG_ROUTING_NONE),
+ main_frame_widget_routing_id(MSG_ROUTING_NONE),
initially_hidden(false),
guest_delegate(nullptr),
context(nullptr),
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index 795bec5..46918e5 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -113,11 +113,13 @@
// (e.g., for blocked popups).
bool created_with_opener;
- // The routing ids of the RenderView and of the main RenderFrame. Either
- // both must be provided, or both must be MSG_ROUTING_NONE to have the
- // WebContents make the assignment.
- int routing_id;
- int main_frame_routing_id;
+ // The routing ids of the RenderView, main RenderFrame, and the widget for
+ // the main RenderFrame. Either all routing IDs must be provided or all must
+ // be MSG_ROUTING_NONE to have WebContents make the assignment. If provided,
+ // these routing IDs are associated with |site_instance->GetProcess()|.
+ int32_t routing_id;
+ int32_t main_frame_routing_id;
+ int32_t main_frame_widget_routing_id;
// The name of the top-level frame of the new window. It is non-empty
// when creating a named window (e.g. <a target="foo"> or
diff --git a/content/public/browser/web_contents_delegate.cc b/content/public/browser/web_contents_delegate.cc
index 3d18cee..b39436d 100644
--- a/content/public/browser/web_contents_delegate.cc
+++ b/content/public/browser/web_contents_delegate.cc
@@ -132,8 +132,9 @@
bool WebContentsDelegate::ShouldCreateWebContents(
WebContents* web_contents,
- int route_id,
- int main_frame_route_id,
+ int32_t route_id,
+ int32_t main_frame_route_id,
+ int32_t main_frame_widget_route_id,
WindowContainerType window_container_type,
const std::string& frame_name,
const GURL& target_url,
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h
index eb5f480..40a49049a 100644
--- a/content/public/browser/web_contents_delegate.h
+++ b/content/public/browser/web_contents_delegate.h
@@ -289,8 +289,9 @@
// be destroyed.
virtual bool ShouldCreateWebContents(
WebContents* web_contents,
- int route_id,
- int main_frame_route_id,
+ int32_t route_id,
+ int32_t main_frame_route_id,
+ int32_t main_frame_widget_route_id,
WindowContainerType window_container_type,
const std::string& frame_name,
const GURL& target_url,
diff --git a/content/public/test/mock_render_thread.cc b/content/public/test/mock_render_thread.cc
index a3edec4..687d7b8 100644
--- a/content/public/test/mock_render_thread.cc
+++ b/content/public/test/mock_render_thread.cc
@@ -23,8 +23,8 @@
opener_id_(0),
new_window_routing_id_(0),
new_window_main_frame_routing_id_(0),
- new_frame_routing_id_(0) {
-}
+ new_window_main_frame_widget_routing_id_(0),
+ new_frame_routing_id_(0) {}
MockRenderThread::~MockRenderThread() {
while (!filters_.empty()) {
@@ -208,12 +208,11 @@
// The View expects to be returned a valid route_id different from its own.
void MockRenderThread::OnCreateWindow(
const ViewHostMsg_CreateWindow_Params& params,
- int* route_id,
- int* main_frame_route_id,
- int64* cloned_session_storage_namespace_id) {
- *route_id = new_window_routing_id_;
- *main_frame_route_id = new_window_main_frame_routing_id_;
- *cloned_session_storage_namespace_id = 0;
+ ViewHostMsg_CreateWindow_Reply* reply) {
+ reply->route_id = new_window_routing_id_;
+ reply->main_frame_route_id = new_window_main_frame_routing_id_;
+ reply->main_frame_widget_route_id = new_window_main_frame_widget_routing_id_;
+ reply->cloned_session_storage_namespace_id = 0;
}
// The Frame expects to be returned a valid route_id different from its own.
diff --git a/content/public/test/mock_render_thread.h b/content/public/test/mock_render_thread.h
index 945dc673..17d44831 100644
--- a/content/public/test/mock_render_thread.h
+++ b/content/public/test/mock_render_thread.h
@@ -15,6 +15,7 @@
#include "third_party/WebKit/public/web/WebPopupType.h"
struct ViewHostMsg_CreateWindow_Params;
+struct ViewHostMsg_CreateWindow_Reply;
namespace IPC {
class MessageFilter;
@@ -93,6 +94,10 @@
new_window_routing_id_ = id;
}
+ void set_new_window_main_frame_widget_routing_id(int32_t id) {
+ new_window_main_frame_widget_routing_id_ = id;
+ }
+
void set_new_frame_routing_id(int32 id) {
new_frame_routing_id_ = id;
}
@@ -117,14 +122,11 @@
blink::WebPopupType popup_type,
int* route_id);
- // The View expects to be returned a valid route_id different from its own.
- // We do not keep track of the newly created widget in MockRenderThread,
+ // The View expects to be returned a valid |reply.route_id| different from its
+ // own. We do not keep track of the newly created widget in MockRenderThread,
// so it must be cleaned up on its own.
- void OnCreateWindow(
- const ViewHostMsg_CreateWindow_Params& params,
- int* route_id,
- int* main_frame_route_id,
- int64* cloned_session_storage_namespace_id);
+ void OnCreateWindow(const ViewHostMsg_CreateWindow_Params& params,
+ ViewHostMsg_CreateWindow_Reply* reply);
// The Frame expects to be returned a valid route_id different from its own.
void OnCreateChildFrame(int new_frame_routing_id,
@@ -149,6 +151,7 @@
// Routing id that will be assigned to a CreateWindow Widget.
int32 new_window_routing_id_;
int32 new_window_main_frame_routing_id_;
+ int32_t new_window_main_frame_widget_routing_id_;
int32 new_frame_routing_id_;
// The last known good deserializer for sync messages.
diff --git a/content/public/test/render_view_test.cc b/content/public/test/render_view_test.cc
index 39ccf86f..7810e3a7 100644
--- a/content/public/test/render_view_test.cc
+++ b/content/public/test/render_view_test.cc
@@ -61,8 +61,13 @@
const int32 kRouteId = 5;
const int32 kMainFrameRouteId = 6;
+// TODO(avi): Widget routing IDs should be distinct from the view routing IDs,
+// once RenderWidgetHost is distilled from RenderViewHostImpl.
+// https://crbug.com/545684
+const int32_t kMainFrameWidgetRouteId = 5;
const int32 kNewWindowRouteId = 7;
const int32 kNewFrameRouteId = 10;
+const int32_t kNewFrameWidgetRouteId = 7;
// Converts |ascii_character| into |key_code| and returns true on success.
// Handles only the characters needed by tests.
@@ -205,6 +210,8 @@
render_thread_.reset(new MockRenderThread());
render_thread_->set_routing_id(kRouteId);
render_thread_->set_new_window_routing_id(kNewWindowRouteId);
+ render_thread_->set_new_window_main_frame_widget_routing_id(
+ kNewFrameWidgetRouteId);
render_thread_->set_new_frame_routing_id(kNewFrameRouteId);
#if defined(OS_MACOSX)
@@ -242,6 +249,7 @@
view_params.web_preferences = WebPreferences();
view_params.view_id = kRouteId;
view_params.main_frame_routing_id = kMainFrameRouteId;
+ view_params.main_frame_widget_routing_id = kMainFrameWidgetRouteId;
view_params.session_storage_namespace_id = kInvalidSessionStorageNamespaceId;
view_params.swapped_out = false;
view_params.replicated_frame_state = FrameReplicationState();
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 8fff086bd9..76ae73c 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -570,14 +570,31 @@
}
// static
-RenderFrameImpl* RenderFrameImpl::CreateMainFrame(RenderViewImpl* render_view,
- int32 routing_id) {
+RenderFrameImpl* RenderFrameImpl::CreateMainFrame(
+ RenderViewImpl* render_view,
+ int32_t routing_id,
+ int32_t widget_routing_id,
+ bool hidden,
+ const blink::WebScreenInfo& screen_info,
+ CompositorDependencies* compositor_deps) {
+ // A main frame RenderFrame must have a RenderWidget.
+ DCHECK_NE(MSG_ROUTING_NONE, widget_routing_id);
+
RenderFrameImpl* render_frame =
RenderFrameImpl::Create(render_view, routing_id);
WebLocalFrame* web_frame =
WebLocalFrame::create(blink::WebTreeScopeType::Document, render_frame);
render_frame->SetWebFrame(web_frame);
render_view->webview()->setMainFrame(web_frame);
+ render_frame->render_widget_ = RenderWidget::CreateForFrame(
+ widget_routing_id, hidden, screen_info, compositor_deps, web_frame);
+ // TODO(kenrb): Observing shouldn't be necessary when we sort out
+ // WasShown and WasHidden, separating page-level visibility from
+ // frame-level visibility.
+ // TODO(avi): This DCHECK is to track cleanup for https://crbug.com/545684
+ DCHECK_EQ(render_view, render_frame->render_widget_)
+ << "Main frame is no longer reusing the RenderView as its widget! "
+ << "Does the RenderFrame need to register itself with the RenderWidget?";
return render_frame;
}
@@ -633,14 +650,20 @@
web_frame->setOpener(opener);
if (widget_params.routing_id != MSG_ROUTING_NONE) {
- CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible());
+ CHECK_IMPLIES(web_frame->parent(),
+ SiteIsolationPolicy::AreCrossProcessFramesPossible());
render_frame->render_widget_ = RenderWidget::CreateForFrame(
widget_params.routing_id, widget_params.hidden,
render_frame->render_view_->screen_info(), compositor_deps, web_frame);
- // TODO(kenrb): Observing shouldn't be necessary when we sort out
- // WasShown and WasHidden, separating page-level visibility from
- // frame-level visibility.
- render_frame->render_widget_->RegisterRenderFrame(render_frame);
+ // TODO(avi): The main frame re-uses the RenderViewImpl as its widget, so
+ // avoid double-registering the frame as an observer.
+ // https://crbug.com/545684
+ if (web_frame->parent()) {
+ // TODO(kenrb): Observing shouldn't be necessary when we sort out
+ // WasShown and WasHidden, separating page-level visibility from
+ // frame-level visibility.
+ render_frame->render_widget_->RegisterRenderFrame(render_frame);
+ }
}
render_frame->Initialize();
@@ -3987,7 +4010,11 @@
// TODO(kenrb): Need to figure out how to do this better. Should
// VisibilityState remain a page-level concept or move to frames?
// The semantics of 'Show' might have to change here.
- if (render_widget_) {
+ // TODO(avi): This DCHECK is to track cleanup for https://crbug.com/545684
+ DCHECK_IMPLIES(IsMainFrame(), render_widget_.get() == render_view_.get())
+ << "The main render frame is no longer reusing the RenderView as its "
+ << "RenderWidget!";
+ if (render_widget_ && render_view_.get() != render_widget_.get()) {
static_cast<blink::WebFrameWidget*>(render_widget_->webwidget())->
setVisibilityState(blink::WebPageVisibilityStateVisible, false);
}
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index b5bbaa5..945c61d 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -68,6 +68,7 @@
struct WebCompositionUnderline;
struct WebContextMenuData;
struct WebCursorInfo;
+struct WebScreenInfo;
}
namespace gfx {
@@ -137,8 +138,13 @@
NON_EXPORTED_BASE(public blink::WebPageSerializerClient) {
public:
// Creates a new RenderFrame as the main frame of |render_view|.
- static RenderFrameImpl* CreateMainFrame(RenderViewImpl* render_view,
- int32 routing_id);
+ static RenderFrameImpl* CreateMainFrame(
+ RenderViewImpl* render_view,
+ int32_t routing_id,
+ int32_t widget_routing_id,
+ bool hidden,
+ const blink::WebScreenInfo& screen_info,
+ CompositorDependencies* compositor_deps);
// Creates a new RenderFrame with |routing_id|. If |proxy_routing_id| is
// MSG_ROUTING_NONE, it creates the Blink WebLocalFrame and inserts it into
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 489aef6..584854c 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -644,6 +644,7 @@
has_focus_(false),
has_scrolled_focused_editable_node_into_rect_(false),
main_render_frame_(nullptr),
+ frame_widget_(nullptr),
speech_recognition_dispatcher_(NULL),
mouse_lock_dispatcher_(NULL),
#if defined(OS_ANDROID)
@@ -690,8 +691,9 @@
stats_collection_observer_.reset(new StatsCollectionObserver(this));
if (params.main_frame_routing_id != MSG_ROUTING_NONE) {
- main_render_frame_ =
- RenderFrameImpl::CreateMainFrame(this, params.main_frame_routing_id);
+ main_render_frame_ = RenderFrameImpl::CreateMainFrame(
+ this, params.main_frame_routing_id, params.main_frame_widget_routing_id,
+ params.hidden, screen_info(), compositor_deps_);
}
if (params.proxy_routing_id != MSG_ROUTING_NONE) {
@@ -822,6 +824,8 @@
}
RenderViewImpl::~RenderViewImpl() {
+ DCHECK(!frame_widget_);
+
for (BitmapMap::iterator it = disambiguation_bitmaps_.begin();
it != disambiguation_bitmaps_.end();
++it)
@@ -1575,14 +1579,9 @@
for (size_t i = 0; i < features.additionalFeatures.size(); ++i)
params.additional_features.push_back(features.additionalFeatures[i]);
- int32 routing_id = MSG_ROUTING_NONE;
- int32 main_frame_routing_id = MSG_ROUTING_NONE;
- int64 cloned_session_storage_namespace_id = 0;
-
- RenderThread::Get()->Send(
- new ViewHostMsg_CreateWindow(params, &routing_id, &main_frame_routing_id,
- &cloned_session_storage_namespace_id));
- if (routing_id == MSG_ROUTING_NONE)
+ ViewHostMsg_CreateWindow_Reply reply;
+ RenderThread::Get()->Send(new ViewHostMsg_CreateWindow(params, &reply));
+ if (reply.route_id == MSG_ROUTING_NONE)
return NULL;
WebUserGestureIndicator::consumeUserGesture();
@@ -1610,14 +1609,14 @@
view_params.window_was_created_with_opener = true;
view_params.renderer_preferences = renderer_preferences_;
view_params.web_preferences = webkit_preferences_;
- view_params.view_id = routing_id;
- view_params.main_frame_routing_id = main_frame_routing_id;
+ view_params.view_id = reply.route_id;
+ view_params.main_frame_routing_id = reply.main_frame_route_id;
+ view_params.main_frame_widget_routing_id = reply.main_frame_widget_route_id;
view_params.session_storage_namespace_id =
- cloned_session_storage_namespace_id;
+ reply.cloned_session_storage_namespace_id;
view_params.swapped_out = false;
// WebCore will take care of setting the correct name.
view_params.replicated_frame_state = FrameReplicationState();
- view_params.proxy_routing_id = MSG_ROUTING_NONE;
view_params.hidden = (params.disposition == NEW_BACKGROUND_TAB);
view_params.never_visible = never_visible;
view_params.next_page_id = 1;
@@ -1696,6 +1695,12 @@
}
}
+void RenderViewImpl::AttachWebFrameWidget(blink::WebWidget* frame_widget) {
+ // The previous WebFrameWidget must already be detached by CloseForFrame().
+ DCHECK(!frame_widget_);
+ frame_widget_ = frame_widget;
+}
+
void RenderViewImpl::SetZoomLevel(double zoom_level) {
webview()->setZoomLevel(zoom_level);
FOR_EACH_OBSERVER(RenderViewObserver, observers_, OnZoomLevelChanged());
@@ -2946,6 +2951,12 @@
}
#endif // OS_MACOSX
+void RenderViewImpl::CloseForFrame() {
+ DCHECK(frame_widget_);
+ frame_widget_->close();
+ frame_widget_ = nullptr;
+}
+
void RenderViewImpl::Close() {
// We need to grab a pointer to the doomed WebView before we destroy it.
WebView* doomed = webview();
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 7f7dca4..591cd6b4 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -48,6 +48,7 @@
#include "third_party/WebKit/public/web/WebConsoleMessage.h"
#include "third_party/WebKit/public/web/WebDataSource.h"
#include "third_party/WebKit/public/web/WebElement.h"
+#include "third_party/WebKit/public/web/WebFrameWidget.h"
#include "third_party/WebKit/public/web/WebHistoryItem.h"
#include "third_party/WebKit/public/web/WebIconURL.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
@@ -239,6 +240,8 @@
// FocusController.
void SetFocus(bool enable);
+ void AttachWebFrameWidget(blink::WebWidget* frame_widget);
+
// Plugin-related functions --------------------------------------------------
#if defined(ENABLE_PLUGINS)
@@ -449,6 +452,7 @@
protected:
// RenderWidget overrides:
+ void CloseForFrame() override;
void Close() override;
void OnResize(const ViewMsg_Resize_Params& params) override;
void DidInitiatePaint() override;
@@ -901,6 +905,10 @@
RenderFrameImpl* main_render_frame_;
+ // Note: RenderViewImpl is pulling double duty: it's the RenderWidget for the
+ // "view", but it's also the RenderWidget for the main frame.
+ blink::WebWidget* frame_widget_;
+
// The next group of objects all implement RenderViewObserver, so are deleted
// along with the RenderView automatically. This is why we just store
// weak references.
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 2ece707..44b971f 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -50,6 +50,7 @@
#include "content/renderer/render_frame_proxy.h"
#include "content/renderer/render_process.h"
#include "content/renderer/render_thread_impl.h"
+#include "content/renderer/render_view_impl.h"
#include "content/renderer/renderer_blink_platform_impl.h"
#include "content/renderer/resizing_mode_selector.h"
#include "ipc/ipc_sync_message.h"
@@ -571,6 +572,14 @@
CompositorDependencies* compositor_deps,
blink::WebLocalFrame* frame) {
CHECK_NE(routing_id, MSG_ROUTING_NONE);
+ // TODO(avi): Before RenderViewImpl has-a RenderWidget, the browser passes the
+ // same routing ID for both the view routing ID and the main frame widget
+ // routing ID. https://crbug.com/545684
+ RenderViewImpl* view = RenderViewImpl::FromRoutingID(routing_id);
+ if (view) {
+ view->AttachWebFrameWidget(RenderWidget::CreateWebFrameWidget(view, frame));
+ return view;
+ }
scoped_refptr<RenderWidget> widget(
new RenderWidget(compositor_deps, blink::WebPopupTypeNone, screen_info,
false, hidden, false));
@@ -590,6 +599,11 @@
blink::WebWidget* RenderWidget::CreateWebFrameWidget(
RenderWidget* render_widget,
blink::WebLocalFrame* frame) {
+ if (!frame->parent()) {
+ // TODO(dcheng): The main frame widget currently has a special case.
+ // Eliminate this once WebView is no longer a WebWidget.
+ return blink::WebFrameWidget::create(render_widget, frame->view(), frame);
+ }
return blink::WebFrameWidget::create(render_widget, frame);
}
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index bb917e53..804ec98 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -122,7 +122,9 @@
blink::WebLocalFrame* frame);
// Closes a RenderWidget that was created by |CreateForFrame|.
- void CloseForFrame();
+ // TODO(avi): De-virtualize this once RenderViewImpl has-a RenderWidget.
+ // https://crbug.com/545684
+ virtual void CloseForFrame();
int32 routing_id() const { return routing_id_; }
CompositorDependencies* compositor_deps() const { return compositor_deps_; }
diff --git a/content/test/test_web_contents.cc b/content/test/test_web_contents.cc
index b8d0092b..e69d806f 100644
--- a/content/test/test_web_contents.cc
+++ b/content/test/test_web_contents.cc
@@ -301,11 +301,11 @@
void TestWebContents::CreateNewWindow(
SiteInstance* source_site_instance,
- int route_id,
- int main_frame_route_id,
+ int32_t route_id,
+ int32_t main_frame_route_id,
+ int32_t main_frame_widget_route_id,
const ViewHostMsg_CreateWindow_Params& params,
- SessionStorageNamespace* session_storage_namespace) {
-}
+ SessionStorageNamespace* session_storage_namespace) {}
void TestWebContents::CreateNewWidget(int32 render_process_id,
int32 route_id,
diff --git a/content/test/test_web_contents.h b/content/test/test_web_contents.h
index 62910198..f46d0f9 100644
--- a/content/test/test_web_contents.h
+++ b/content/test/test_web_contents.h
@@ -117,8 +117,9 @@
// WebContentsImpl overrides
void CreateNewWindow(
SiteInstance* source_site_instance,
- int route_id,
- int main_frame_route_id,
+ int32_t route_id,
+ int32_t main_frame_route_id,
+ int32_t main_frame_widget_route_id,
const ViewHostMsg_CreateWindow_Params& params,
SessionStorageNamespace* session_storage_namespace) override;
void CreateNewWidget(int32 render_process_id,