Chromium Code Reviews| Index: extensions/browser/extension_web_contents_observer.cc |
| diff --git a/extensions/browser/extension_web_contents_observer.cc b/extensions/browser/extension_web_contents_observer.cc |
| index 665fc0809cca1b3ebcfa428ae79d762d9c8c5caa..e3b5653b963e306022200533dcfc51eeb1e09204 100644 |
| --- a/extensions/browser/extension_web_contents_observer.cc |
| +++ b/extensions/browser/extension_web_contents_observer.cc |
| @@ -4,7 +4,9 @@ |
| #include "extensions/browser/extension_web_contents_observer.h" |
| +#include "components/guest_view/browser/guest_view_base.h" |
| #include "content/public/browser/child_process_security_policy.h" |
| +#include "content/public/browser/navigation_details.h" |
| #include "content/public/browser/render_frame_host.h" |
| #include "content/public/browser/render_process_host.h" |
| #include "content/public/browser/render_view_host.h" |
| @@ -24,6 +26,14 @@ |
| namespace extensions { |
| +namespace { |
| + |
| +bool IsExtensionURL(const GURL& url) { |
| + return url.SchemeIs(kExtensionScheme) || url.SchemeIs(content::kGuestScheme); |
|
Devlin
2015/12/01 00:58:20
nit: comment why we include guest scheme.
robwu
2015/12/01 17:19:57
The only reason for putting kGuestScheme here is b
|
| +} |
| + |
| +} // namespace |
| + |
| // static |
| ExtensionWebContentsObserver* ExtensionWebContentsObserver::GetForWebContents( |
| content::WebContents* web_contents) { |
| @@ -50,18 +60,34 @@ void ExtensionWebContentsObserver::InitializeRenderFrame( |
| DCHECK(render_frame_host); |
| DCHECK(render_frame_host->IsRenderFrameLive()); |
| + ViewType view_type = GetViewType(web_contents()); |
| + if (view_type == VIEW_TYPE_INVALID) { |
| + // This is expected to happen only for non-extension pages (e.g. devtools) |
| + // and GuestViews. |
| + DCHECK(guest_view::GuestViewBase::FromWebContents(web_contents()) || |
| + !IsExtensionURL(render_frame_host->GetSiteInstance()->GetSiteURL())); |
| + return; |
| + } |
| + |
| + // At the initialization of the render frame, the last committed URL is not |
| + // reliable, so do not take it into account in determining whether it is an |
| + // extension frame. |
| + const Extension* frame_extension = |
| + GetExtensionFromFrame(render_frame_host, false); |
| + // TODO(robwu): Add DCHECK that verifies that |frame_extension| always exists |
| + // if OOP frames is enabled. |
| + if (!frame_extension) |
| + return; |
| + |
| // Notify the render frame of the view type. |
| render_frame_host->Send(new ExtensionMsg_NotifyRenderViewType( |
| - render_frame_host->GetRoutingID(), GetViewType(web_contents()))); |
| - |
| - const Extension* frame_extension = GetExtensionFromFrame(render_frame_host); |
| - if (frame_extension) { |
| - ExtensionsBrowserClient::Get()->RegisterMojoServices(render_frame_host, |
| - frame_extension); |
| - ProcessManager::Get(browser_context_) |
| - ->RegisterRenderFrameHost(web_contents(), render_frame_host, |
| - frame_extension); |
| - } |
| + render_frame_host->GetRoutingID(), view_type)); |
| + |
| + ExtensionsBrowserClient::Get()->RegisterMojoServices(render_frame_host, |
| + frame_extension); |
| + ProcessManager::Get(browser_context_) |
| + ->RegisterRenderFrameHost(web_contents(), render_frame_host, |
| + frame_extension); |
| } |
| content::WebContents* ExtensionWebContentsObserver::GetAssociatedWebContents() |
| @@ -110,6 +136,49 @@ void ExtensionWebContentsObserver::RenderFrameDeleted( |
| ->UnregisterRenderFrameHost(render_frame_host); |
| } |
| +void ExtensionWebContentsObserver::DidCommitProvisionalLoadForFrame( |
| + content::RenderFrameHost* render_frame_host, |
| + const GURL& url, |
| + ui::PageTransition transition_type) { |
| + ProcessManager* pm = ProcessManager::Get(browser_context_); |
| + |
| + if (pm->IsRenderFrameHostRegistered(render_frame_host)) { |
| + const Extension* frame_extension = |
| + GetExtensionFromFrame(render_frame_host, true); |
| + |
| + if (!frame_extension) |
| + pm->UnregisterRenderFrameHost(render_frame_host); |
| + } |
| +} |
| + |
| +void ExtensionWebContentsObserver::DidNavigateAnyFrame( |
| + content::RenderFrameHost* render_frame_host, |
| + const content::LoadCommittedDetails& details, |
| + const content::FrameNavigateParams& params) { |
| + if (details.is_in_page) |
| + return; |
| + |
| + const Extension* frame_extension = |
| + GetExtensionFromFrame(render_frame_host, true); |
| + ProcessManager* pm = ProcessManager::Get(browser_context_); |
| + |
| + if (!frame_extension) { |
| + // Should have been unregistered by DidCommitProvisionalLoadForFrame. |
| + DCHECK(!pm->IsRenderFrameHostRegistered(render_frame_host)); |
| + return; |
| + } |
| + |
| + if (pm->IsRenderFrameHostRegistered(render_frame_host)) { |
| + // Notify ProcessManager, because some clients do not just want to know |
| + // whether the frame is in an extension process, but also whether the frame |
| + // was navigated. |
| + pm->DidNavigateRenderFrameHost(render_frame_host); |
| + } else { |
| + pm->RegisterRenderFrameHost(web_contents(), render_frame_host, |
| + frame_extension); |
| + } |
| +} |
| + |
| bool ExtensionWebContentsObserver::OnMessageReceived( |
| const IPC::Message& message, |
| content::RenderFrameHost* render_frame_host) { |
| @@ -146,24 +215,47 @@ void ExtensionWebContentsObserver::PepperInstanceDeleted() { |
| std::string ExtensionWebContentsObserver::GetExtensionIdFromFrame( |
| content::RenderFrameHost* render_frame_host) const { |
| - content::SiteInstance* site_instance = render_frame_host->GetSiteInstance(); |
| - GURL url = render_frame_host->GetLastCommittedURL(); |
| - if (!url.is_empty()) { |
| - if (site_instance->GetSiteURL().GetOrigin() != url.GetOrigin()) |
| - return std::string(); |
| - } else { |
| - url = site_instance->GetSiteURL(); |
| - } |
| - |
| - return url.SchemeIs(kExtensionScheme) ? url.host() : std::string(); |
| + const Extension* extension = GetExtensionFromFrame(render_frame_host, true); |
| + return extension ? extension->id() : std::string(); |
| } |
| const Extension* ExtensionWebContentsObserver::GetExtensionFromFrame( |
| - content::RenderFrameHost* render_frame_host) const { |
| - return ExtensionRegistry::Get( |
| - render_frame_host->GetProcess()->GetBrowserContext()) |
| - ->enabled_extensions() |
| - .GetByID(GetExtensionIdFromFrame(render_frame_host)); |
| + content::RenderFrameHost* render_frame_host, |
| + bool verify_url) const { |
| + const GURL site_url(render_frame_host->GetSiteInstance()->GetSiteURL()); |
| + if (!IsExtensionURL(site_url)) |
| + return nullptr; |
| + |
| + const std::string& extension_id = site_url.host(); |
| + const Extension* extension = |
| + ExtensionRegistry::Get( |
| + render_frame_host->GetProcess()->GetBrowserContext()) |
| + ->enabled_extensions() |
| + .GetByID(extension_id); |
| + if (!extension) |
| + return nullptr; |
| + |
| + // This verify_url logic can completely be removed once site isolation is |
| + // fully enabled. |
| + if (verify_url) { |
| + GURL url(render_frame_host->GetLastCommittedURL()); |
|
Devlin
2015/12/01 00:58:20
const&?
|
| + if (extension->is_hosted_app() && extension->web_extent().MatchesURL(url)) |
| + return extension; |
| + |
| + if (!IsExtensionURL(url)) { |
| + // Any about:* frame (in particular about:blank and about:srcdoc) runs in |
| + // the security context of the parent page that created it. Treat such |
| + // frames as extension pages iff the parent frame is registered. |
| + if (url.SchemeIs(url::kAboutScheme) && render_frame_host->GetParent()) |
| + return GetExtensionFromFrame(render_frame_host->GetParent(), true); |
| + return nullptr; |
| + } |
| + if (url.host() != extension_id) { |
|
Devlin
2015/12/01 00:58:20
nit: try to be consistent with wrapping {} in sing
|
| + return nullptr; |
| + } |
| + } |
| + |
| + return extension; |
| } |
| const Extension* ExtensionWebContentsObserver::GetExtension( |