123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// found in the LICENSE file. 423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "extensions/browser/extension_web_contents_observer.h" 623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "content/public/browser/child_process_security_policy.h" 823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "content/public/browser/render_process_host.h" 923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "content/public/browser/render_view_host.h" 1023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "content/public/browser/site_instance.h" 1123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "content/public/browser/web_contents.h" 1223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "content/public/common/url_constants.h" 1323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "extensions/browser/extension_prefs.h" 1423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "extensions/browser/extension_registry.h" 1523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "extensions/browser/view_type_utils.h" 1623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "extensions/common/constants.h" 1723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "extensions/common/extension_messages.h" 1823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 1923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)namespace extensions { 2023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 2123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)ExtensionWebContentsObserver::ExtensionWebContentsObserver( 2223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) content::WebContents* web_contents) 2323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) : content::WebContentsObserver(web_contents), 24effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch browser_context_(web_contents->GetBrowserContext()) { 25effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NotifyRenderViewType(web_contents->GetRenderViewHost()); 26effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 2723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 2823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)ExtensionWebContentsObserver::~ExtensionWebContentsObserver() {} 2923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 3023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void ExtensionWebContentsObserver::RenderViewCreated( 3123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) content::RenderViewHost* render_view_host) { 32effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NotifyRenderViewType(render_view_host); 3323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 3423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const Extension* extension = GetExtension(render_view_host); 3523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!extension) 3623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return; 3723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 3823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) content::RenderProcessHost* process = render_view_host->GetProcess(); 3923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 4023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Some extensions use chrome:// URLs. 4123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // This is a temporary solution. Replace it with access to chrome-static:// 4223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // once it is implemented. See: crbug.com/226927. 4323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) Manifest::Type type = extension->GetType(); 4423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (type == Manifest::TYPE_EXTENSION || 4523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) type == Manifest::TYPE_LEGACY_PACKAGED_APP || 4623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) (type == Manifest::TYPE_PLATFORM_APP && 4723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) extension->location() == Manifest::COMPONENT)) { 4823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) content::ChildProcessSecurityPolicy::GetInstance()->GrantScheme( 4923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) process->GetID(), content::kChromeUIScheme); 5023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 5123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 5223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Some extensions use file:// URLs. 5323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (type == Manifest::TYPE_EXTENSION || 5423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) type == Manifest::TYPE_LEGACY_PACKAGED_APP) { 5523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context_); 5623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (prefs->AllowFileAccess(extension->id())) { 5723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) content::ChildProcessSecurityPolicy::GetInstance()->GrantScheme( 58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) process->GetID(), url::kFileScheme); 5923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 6023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 6123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 6223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) switch (type) { 6323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) case Manifest::TYPE_EXTENSION: 6423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) case Manifest::TYPE_USER_SCRIPT: 6523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) case Manifest::TYPE_HOSTED_APP: 6623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) case Manifest::TYPE_LEGACY_PACKAGED_APP: 6723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) case Manifest::TYPE_PLATFORM_APP: 6823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Always send a Loaded message before ActivateExtension so that 6923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // ExtensionDispatcher knows what Extension is active, not just its ID. 7023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // This is important for classifying the Extension's JavaScript context 7123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // correctly (see ExtensionDispatcher::ClassifyJavaScriptContext). 7223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) render_view_host->Send( 7323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) new ExtensionMsg_Loaded(std::vector<ExtensionMsg_Loaded_Params>( 7423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 1, ExtensionMsg_Loaded_Params(extension)))); 7523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) render_view_host->Send( 7623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) new ExtensionMsg_ActivateExtension(extension->id())); 7723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) break; 7823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 7923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) case Manifest::TYPE_UNKNOWN: 8023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) case Manifest::TYPE_THEME: 8123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) case Manifest::TYPE_SHARED_MODULE: 8223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) break; 83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case Manifest::NUM_LOAD_TYPES: 85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NOTREACHED(); 8623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 8723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 8823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 89effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ExtensionWebContentsObserver::NotifyRenderViewType( 90effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch content::RenderViewHost* render_view_host) { 91effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (render_view_host) { 92effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch render_view_host->Send(new ExtensionMsg_NotifyRenderViewType( 93effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch render_view_host->GetRoutingID(), GetViewType(web_contents()))); 94effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 95effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 96effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 9723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)const Extension* ExtensionWebContentsObserver::GetExtension( 9823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) content::RenderViewHost* render_view_host) { 9923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) std::string extension_id = GetExtensionId(render_view_host); 10023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (extension_id.empty()) 10123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return NULL; 10223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 10323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // May be null if the extension doesn't exist, for example if somebody typos 10423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // a chrome-extension:// URL. 10523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return ExtensionRegistry::Get(browser_context_) 10623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ->GetExtensionById(extension_id, ExtensionRegistry::ENABLED); 10723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 10823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 10923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// static 11023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)std::string ExtensionWebContentsObserver::GetExtensionId( 11123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) content::RenderViewHost* render_view_host) { 11223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Note that due to ChromeContentBrowserClient::GetEffectiveURL(), hosted apps 11323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // (excluding bookmark apps) will have a chrome-extension:// URL for their 11423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // site, so we can ignore that wrinkle here. 11523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const GURL& site = render_view_host->GetSiteInstance()->GetSiteURL(); 11623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 11723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (!site.SchemeIs(kExtensionScheme)) 11823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return std::string(); 11923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 12023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return site.host(); 12123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 12223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 12323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} // namespace extensions 124