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..bd69dfaa23164c47cae7aa33978a0018d5cabe81 100644 |
| --- a/extensions/browser/extension_web_contents_observer.cc |
| +++ b/extensions/browser/extension_web_contents_observer.cc |
| @@ -4,12 +4,16 @@ |
| #include "extensions/browser/extension_web_contents_observer.h" |
| +#include "base/command_line.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" |
| #include "content/public/browser/site_instance.h" |
| #include "content/public/browser/web_contents.h" |
| +#include "content/public/common/content_switches.h" |
| #include "content/public/common/url_constants.h" |
| #include "extensions/browser/extension_prefs.h" |
| #include "extensions/browser/extension_registry.h" |
| @@ -50,18 +54,38 @@ 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()) || |
| + !render_frame_host->GetSiteInstance()->GetSiteURL().SchemeIs( |
| + kExtensionScheme)); |
| + 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); |
| + // Only extension frames should be reported if site isolation is enabled, so |
| + // |frame_extension| should exist at this point. |
| + DCHECK(!base::CommandLine::ForCurrentProcess()->HasSwitch( |
| + switches::kSitePerProcess) || |
| + frame_extension); |
| + 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 +134,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 +213,39 @@ 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 (!site_url.SchemeIs(kExtensionScheme)) |
| + 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; |
| + |
| + if (verify_url) { |
| + // Without site isolation, this check is needed to eliminate non-extension |
| + // schemes. With site isolation, this is still needed to exclude sandboxed |
| + // extension frames with a unique origin. |
| + if (!render_frame_host->GetLastCommittedOrigin().IsSameOriginWith( |
| + url::Origin(site_url)) && |
|
ncarter (slow)
2015/12/01 17:51:42
I think this works only because extension urls don
robwu
2015/12/01 23:19:58
Done.
|
| + (!extension->is_hosted_app() || |
| + !extension->web_extent().MatchesURL( |
| + render_frame_host->GetLastCommittedURL()))) |
|
ncarter (slow)
2015/12/01 17:51:42
Does this MatchesURL logic work properly for the a
robwu
2015/12/01 23:19:58
No.
|
| + return nullptr; |
| + } |
| + |
| + return extension; |
| } |
| const Extension* ExtensionWebContentsObserver::GetExtension( |