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 66e303c7014acdd52679293465db1cf9609912df..4def7346d2285a59ab48dcf6b5b6c8d6e52b9c8c 100644 |
| --- a/content/browser/frame_host/render_frame_host_impl.cc |
| +++ b/content/browser/frame_host/render_frame_host_impl.cc |
| @@ -17,6 +17,7 @@ |
| #include "content/browser/accessibility/browser_accessibility_state_impl.h" |
| #include "content/browser/bad_message.h" |
| #include "content/browser/child_process_security_policy_impl.h" |
| +#include "content/browser/child_process_security_policy_impl.h" |
| #include "content/browser/devtools/render_frame_devtools_agent_host.h" |
| #include "content/browser/frame_host/cross_process_frame_connector.h" |
| #include "content/browser/frame_host/cross_site_transferring_request.h" |
| @@ -43,6 +44,7 @@ |
| #include "content/browser/renderer_host/render_widget_host_impl.h" |
| #include "content/browser/renderer_host/render_widget_host_view_base.h" |
| #include "content/browser/wake_lock/wake_lock_service_context.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" |
| @@ -194,6 +196,7 @@ 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), |
| weak_ptr_factory_(this) { |
| bool is_swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT); |
| bool hidden = !!(flags & CREATE_RF_HIDDEN); |
| @@ -233,6 +236,10 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance, |
| } |
| RenderFrameHostImpl::~RenderFrameHostImpl() { |
| + // Release the WebUI before all else as the WebUI accesses the RenderFrameHost |
| + // during cleanup. |
| + ResetWebUI(); |
| + |
| GetProcess()->RemoveRoute(routing_id_); |
| g_routing_id_frame_map.Get().erase( |
| RenderFrameHostID(GetProcess()->GetID(), routing_id_)); |
| @@ -1035,6 +1042,8 @@ void RenderFrameHostImpl::SwapOut( |
| swapout_event_monitor_timeout_->Start( |
| base::TimeDelta::FromMilliseconds(RenderViewHostImpl::kUnloadTimeoutMS)); |
| + ResetWebUI(); |
| + |
| // There may be no proxy if there are no active views in the process. |
| int proxy_routing_id = MSG_ROUTING_NONE; |
| FrameReplicationState replication_state; |
| @@ -2003,6 +2012,65 @@ bool RenderFrameHostImpl::IsFocused() { |
| frame_tree_->GetFocusedFrame()->IsDescendantOf(frame_tree_node())); |
| } |
| +bool RenderFrameHostImpl::UpdateWebUI(const GURL& dest_url, |
| + int entry_bindings) { |
| + WebUI::TypeID new_web_ui_type = WebUI::kNoWebUI; |
| + if (dest_url.is_valid()) { |
| + new_web_ui_type = |
| + WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType( |
| + GetSiteInstance()->GetBrowserContext(), dest_url); |
| + } |
| + |
| + WebUIImpl* prev_web_ui = web_ui_.get(); |
| + if (new_web_ui_type == WebUI::kNoWebUI) { |
| + ResetWebUI(); |
|
nasko
2015/11/02 17:00:36
Can't we early return from here? It will make also
carlosk
2015/11/03 09:50:30
No because of the bindings checks further below. U
nasko
2015/11/04 17:16:10
No, let's keep it all in one place, as bindings ch
carlosk
2015/11/04 21:43:59
Acknowledged.
|
| + } else { |
| + // The current WebUI should be reused when dest_url requires a WebUI and its |
| + // type matches the current. Otherwise replace it with a new one. |
| + if (web_ui_type_ != new_web_ui_type) { |
| + web_ui_ = delegate_->CreateWebUIForRenderFrameHost(dest_url); |
| + DCHECK(web_ui_); |
| + web_ui_type_ = new_web_ui_type; |
| + |
| + // 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 (entry_bindings != NavigationEntryImpl::kInvalidBindings && |
| + web_ui_->GetBindings() != entry_bindings) { |
| + RecordAction( |
| + base::UserMetricsAction("ProcessSwapBindingsMismatch_RVHM")); |
| + ResetWebUI(); |
| + return !!prev_web_ui; |
| + } |
| + } |
| + } |
| + DCHECK_EQ(!web_ui_, 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); |
| + } |
| + } else if (render_view_host_->is_active()) { |
| + // If the ongoing navigation is not to a WebUI or the RenderView is in a |
| + // guest process, ensure that we don't create an unprivileged RenderView in |
| + // a WebUI-enabled process unless it's swapped out. |
| + bool url_acceptable_for_webui = |
| + WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI( |
| + GetSiteInstance()->GetBrowserContext(), dest_url); |
| + if (!url_acceptable_for_webui) { |
| + CHECK(!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( |
| + GetProcess()->GetID())); |
| + } |
| + } |
| + return prev_web_ui != web_ui_.get(); |
| +} |
| + |
| const image_downloader::ImageDownloaderPtr& |
| RenderFrameHostImpl::GetMojoImageDownloader() { |
| if (!mojo_image_downloader_.get() && GetServiceRegistry()) { |
| @@ -2312,4 +2380,9 @@ void RenderFrameHostImpl::AXContentTreeDataToAXTreeData( |
| dst->parent_tree_id = RoutingIDToAXTreeID(src.parent_routing_id); |
| } |
| +void RenderFrameHostImpl::ResetWebUI() { |
| + web_ui_type_ = WebUI::kNoWebUI; |
| + web_ui_.reset(); |
| +} |
| + |
| } // namespace content |