Chromium Code Reviews| Index: content/browser/frame_host/render_frame_host_impl.cc |
| diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc |
| index 488fad6ac2f16a5c604f863a188a6f637b7552a6..235e3f9cc9ffdbbf1c0a94c36a7ad89916fcf9e4 100644 |
| --- a/content/browser/frame_host/render_frame_host_impl.cc |
| +++ b/content/browser/frame_host/render_frame_host_impl.cc |
| @@ -41,6 +41,7 @@ |
| #include "content/browser/renderer_host/render_view_host_impl.h" |
| #include "content/browser/renderer_host/render_widget_host_impl.h" |
| #include "content/browser/renderer_host/render_widget_host_view_base.h" |
| +#include "content/browser/webui/web_ui_controller_factory_registry.h" |
| #include "content/common/accessibility_messages.h" |
| #include "content/common/frame_messages.h" |
| #include "content/common/input_messages.h" |
| @@ -170,7 +171,9 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance, |
| FrameTreeNode* frame_tree_node, |
| int32 routing_id, |
| int32 widget_routing_id, |
| - int flags) |
| + int flags, |
| + const GURL& dest_url, |
| + int entry_bindings) |
| : render_view_host_(render_view_host), |
| delegate_(delegate), |
| site_instance_(static_cast<SiteInstanceImpl*>(site_instance)), |
| @@ -190,6 +193,9 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance, |
| accessibility_reset_token_(0), |
| accessibility_reset_count_(0), |
| no_create_browser_accessibility_manager_for_testing_(false), |
| + web_ui_type_(WebUI::kNoWebUI), |
| + pending_web_ui_type_(WebUI::kNoWebUI), |
| + should_reuse_web_ui_(false), |
| weak_ptr_factory_(this) { |
| bool is_swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT); |
| bool hidden = !!(flags & CREATE_RF_HIDDEN); |
| @@ -215,9 +221,23 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance, |
| widget_routing_id, hidden); |
| render_widget_host_->set_owned_by_render_frame_host(true); |
| } |
| + |
| + web_ui_ = CreateWebUI(dest_url, entry_bindings, &web_ui_type_); |
| + // If a WebUI is created and this RenderFrameHost is for the main frame, it is |
|
nasko
2015/10/07 23:49:33
nit: Empty line between code and comment lines.
carlosk
2015/10/09 17:29:10
Done here and a few more places.
|
| + // assumed that the associated RenderViewHost has also just been created and |
| + // notify the WebUI the RenderView was created. |
| + if (web_ui_ && frame_tree_node_->IsMainFrame()) |
| + web_ui_->RenderViewCreated(render_view_host_); |
| } |
| RenderFrameHostImpl::~RenderFrameHostImpl() { |
| + // Release the WebUI before all else as the WebUI accesses the RenderFrameHost |
| + // during cleanup. |
| + web_ui_type_ = WebUI::kNoWebUI; |
| + web_ui_.reset(); |
| + pending_web_ui_type_ = WebUI::kNoWebUI; |
| + pending_web_ui_.reset(); |
| + |
| GetProcess()->RemoveRoute(routing_id_); |
| g_routing_id_frame_map.Get().erase( |
| RenderFrameHostID(GetProcess()->GetID(), routing_id_)); |
| @@ -1020,6 +1040,9 @@ void RenderFrameHostImpl::SwapOut( |
| swapout_event_monitor_timeout_->Start( |
| base::TimeDelta::FromMilliseconds(RenderViewHostImpl::kUnloadTimeoutMS)); |
| + web_ui_.reset(); |
| + web_ui_type_ = WebUI::kNoWebUI; |
| + |
| // There may be no proxy if there are no active views in the process. |
| int proxy_routing_id = MSG_ROUTING_NONE; |
| FrameReplicationState replication_state; |
| @@ -1959,6 +1982,54 @@ bool RenderFrameHostImpl::IsFocused() { |
| frame_tree_->GetFocusedFrame()->IsDescendantOf(frame_tree_node())); |
| } |
| +void RenderFrameHostImpl::UpdatePendingWebUI(const GURL& dest_url, |
| + int entry_bindings) { |
| + WebUI::TypeID new_web_ui_type = |
| + WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType( |
| + GetSiteInstance()->GetBrowserContext(), dest_url); |
| + // The current WebUI should be reused when dest_url requires a WebUI and its |
| + // type matches the current. |
| + should_reuse_web_ui_ = false; |
| + if (new_web_ui_type != WebUI::kNoWebUI && web_ui_type_ == new_web_ui_type) { |
| + DCHECK(web_ui_); |
| + should_reuse_web_ui_ = true; |
| + // Reset the pending WebUI as the current one will be reused. |
| + pending_web_ui_.reset(); |
| + pending_web_ui_type_ = WebUI::kNoWebUI; |
| + } else if (pending_web_ui_type_ != new_web_ui_type) { |
| + // Otherwise create, update or reset the pending one if its type doesn't |
| + // match the new type (if new type is kNoWebUI then it will be reset). |
| + pending_web_ui_ = |
| + CreateWebUI(dest_url, entry_bindings, &pending_web_ui_type_); |
| + } |
| + // If a pending WebUI is set (be it an actual pending one or the reused |
| + // current one) and the associated RenderFrame is live, notify the WebUI about |
| + // the reusing of the RenderView. |
| + if (pending_web_ui() && IsRenderFrameLive()) { |
| + pending_web_ui()->RenderViewReused(render_view_host_, |
| + frame_tree_node_->IsMainFrame()); |
| + } |
| + CHECK_IMPLIES(pending_web_ui_, pending_web_ui_type_ != WebUI::kNoWebUI); |
| + CHECK_IMPLIES(!pending_web_ui_, pending_web_ui_type_ == WebUI::kNoWebUI); |
| +} |
| + |
| +void RenderFrameHostImpl::CommitPendingWebUI() { |
| + if (should_reuse_web_ui_) { |
| + CHECK(!pending_web_ui_ && pending_web_ui_type_ == WebUI::kNoWebUI); |
| + should_reuse_web_ui_ = false; |
| + } else { |
| + web_ui_ = pending_web_ui_.Pass(); |
| + web_ui_type_ = pending_web_ui_type_; |
| + pending_web_ui_type_ = WebUI::kNoWebUI; |
| + } |
| +} |
| + |
| +void RenderFrameHostImpl::DiscardPendingWebUI() { |
| + pending_web_ui_.reset(); |
| + pending_web_ui_type_ = WebUI::kNoWebUI; |
| + should_reuse_web_ui_ = false; |
| +} |
| + |
| const image_downloader::ImageDownloaderPtr& |
| RenderFrameHostImpl::GetMojoImageDownloader() { |
| if (!mojo_image_downloader_.get() && GetServiceRegistry()) { |
| @@ -2254,4 +2325,42 @@ void RenderFrameHostImpl::AXContentNodeDataToAXNodeData( |
| } |
| } |
| +scoped_ptr<WebUIImpl> RenderFrameHostImpl::CreateWebUI( |
| + const GURL& dest_url, |
| + int entry_bindings, |
| + WebUI::TypeID* web_ui_type) { |
| + scoped_ptr<WebUIImpl> web_ui; |
| + *web_ui_type = WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType( |
| + GetSiteInstance()->GetBrowserContext(), dest_url); |
| + if (*web_ui_type != WebUI::kNoWebUI) { |
| + web_ui = delegate_->CreateWebUIForRenderFrameHost(dest_url); |
| + CHECK(web_ui); |
| + // If we have assigned (zero or more) bindings to the NavigationEntry in the |
| + // past, make sure we're not granting it different bindings than it had |
| + // before. If so, note it and don't give it any bindings, to avoid a |
| + // potential privilege escalation. |
| + if (web_ui && entry_bindings != NavigationEntryImpl::kInvalidBindings && |
| + web_ui->GetBindings() != entry_bindings) { |
| + RecordAction(base::UserMetricsAction("ProcessSwapBindingsMismatch_RVHM")); |
| + web_ui.reset(); |
| + *web_ui_type = WebUI::kNoWebUI; |
| + } |
| + } |
| + |
| + // Check RenderViewHost for proper bindings. |
| + if (web_ui && !render_view_host_->GetProcess()->IsForGuestsOnly()) { |
| + // If a WebUI was created for the URL and the RenderView is not in a guest |
| + // process, then enable missing bindings with the RenderViewHost. |
| + int new_bindings = web_ui->GetBindings(); |
| + if ((render_view_host_->GetEnabledBindings() & new_bindings) != |
| + new_bindings) { |
| + render_view_host_->AllowBindings(new_bindings); |
| + } |
| + } |
| + |
| + CHECK_IMPLIES(web_ui, *web_ui_type != WebUI::kNoWebUI); |
| + CHECK_IMPLIES(!web_ui, *web_ui_type == WebUI::kNoWebUI); |
| + return web_ui.Pass(); |
| +} |
| + |
| } // namespace content |