diff options
author | jamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-07 06:29:21 +0000 |
---|---|---|
committer | jamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-07 06:29:21 +0000 |
commit | 94de8cb973ca8c3c0635c84c426004df3ba728ee (patch) | |
tree | c70aeec5b7f252c1561a4362ebbf52ed68cee2e4 /chrome/browser/extensions | |
parent | 4285d5d3425caa530fcbe92450a167a8e4c8556a (diff) | |
download | chromium_src-94de8cb973ca8c3c0635c84c426004df3ba728ee.zip chromium_src-94de8cb973ca8c3c0635c84c426004df3ba728ee.tar.gz chromium_src-94de8cb973ca8c3c0635c84c426004df3ba728ee.tar.bz2 |
Move ExtensionProcessManager to src/extensions, part 3 - remove Browser
Introduce ExtensionHostFactory to hold Browser-specific ExtensionHost
creation.
BUG=313481
TEST=browser_tests, unit_tests
Review URL: https://codereview.chromium.org/57923009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@233504 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/extensions')
6 files changed, 288 insertions, 157 deletions
diff --git a/chrome/browser/extensions/extension_host_factory.cc b/chrome/browser/extensions/extension_host_factory.cc new file mode 100644 index 0000000..96c86f3 --- /dev/null +++ b/chrome/browser/extensions/extension_host_factory.cc @@ -0,0 +1,144 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/extension_host_factory.h" + +#include "chrome/browser/extensions/extension_host.h" +#include "chrome/browser/extensions/extension_process_manager.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/extension_system.h" +#include "chrome/browser/extensions/extension_util.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/common/url_constants.h" +#include "extensions/common/manifest_handlers/incognito_info.h" +#include "extensions/common/view_type.h" + +#if defined(OS_MACOSX) +#include "chrome/browser/extensions/extension_host_mac.h" +#endif + +namespace extensions { + +namespace { + +// Creates a new ExtensionHost with its associated view, grouping it in the +// appropriate SiteInstance (and therefore process) based on the URL and +// profile. +ExtensionHost* CreateViewHostForExtension(const Extension* extension, + const GURL& url, + Profile* profile, + Browser* browser, + ViewType view_type) { + DCHECK(profile); + // A NULL browser may only be given for dialogs. + DCHECK(browser || view_type == VIEW_TYPE_EXTENSION_DIALOG); + ExtensionProcessManager* pm = + ExtensionSystem::Get(profile)->process_manager(); + content::SiteInstance* site_instance = pm->GetSiteInstanceForURL(url); + ExtensionHost* host = +#if defined(OS_MACOSX) + new ExtensionHostMac(extension, site_instance, url, view_type); +#else + new ExtensionHost(extension, site_instance, url, view_type); +#endif + host->CreateView(browser); + return host; +} + +// Return true if this extension can run in an incognito window. +bool IsIncognitoEnabled(Profile* profile, const Extension* extension) { + ExtensionService* service = + ExtensionSystem::Get(profile)->extension_service(); + return extension_util::IsIncognitoEnabled(extension->id(), service); +} + +// Creates a view host for an extension in an incognito window. Returns NULL +// if the extension is not allowed to run in incognito. +ExtensionHost* CreateViewHostForIncognito(const Extension* extension, + const GURL& url, + Profile* profile, + Browser* browser, + ViewType view_type) { + DCHECK(extension); + DCHECK(profile->IsOffTheRecord()); + + if (!IncognitoInfo::IsSplitMode(extension)) { + // If it's not split-mode the host is associated with the original profile. + Profile* original_profile = profile->GetOriginalProfile(); + return CreateViewHostForExtension( + extension, url, original_profile, browser, view_type); + } + + // Create the host if the extension can run in incognito. + if (IsIncognitoEnabled(profile, extension)) { + return CreateViewHostForExtension( + extension, url, profile, browser, view_type); + } + NOTREACHED() << + "We shouldn't be trying to create an incognito extension view unless " + "it has been enabled for incognito."; + return NULL; +} + +// Returns the extension associated with |url| in |profile|. Returns NULL if +// the extension does not exist. +const Extension* GetExtensionForUrl(Profile* profile, const GURL& url) { + ExtensionService* service = + ExtensionSystem::Get(profile)->extension_service(); + if (!service) + return NULL; + std::string extension_id = url.host(); + if (url.SchemeIs(chrome::kChromeUIScheme) && + url.host() == chrome::kChromeUIExtensionInfoHost) + extension_id = url.path().substr(1); + return service->extensions()->GetByID(extension_id); +} + +// Creates and initializes an ExtensionHost for the extension with |url|. +ExtensionHost* CreateViewHost(const GURL& url, + Profile* profile, + Browser* browser, + extensions::ViewType view_type) { + DCHECK(profile); + // A NULL browser may only be given for dialogs. + DCHECK(browser || view_type == VIEW_TYPE_EXTENSION_DIALOG); + + const Extension* extension = GetExtensionForUrl(profile, url); + if (!extension) + return NULL; + if (profile->IsOffTheRecord()) { + return CreateViewHostForIncognito( + extension, url, profile, browser, view_type); + } + return CreateViewHostForExtension( + extension, url, profile, browser, view_type); +} + +} // namespace + +// static +ExtensionHost* ExtensionHostFactory::CreatePopupHost(const GURL& url, + Browser* browser) { + DCHECK(browser); + return CreateViewHost( + url, browser->profile(), browser, VIEW_TYPE_EXTENSION_POPUP); +} + +// static +ExtensionHost* ExtensionHostFactory::CreateInfobarHost(const GURL& url, + Browser* browser) { + DCHECK(browser); + return CreateViewHost( + url, browser->profile(), browser, VIEW_TYPE_EXTENSION_INFOBAR); +} + +// static +ExtensionHost* ExtensionHostFactory::CreateDialogHost(const GURL& url, + Profile* profile) { + DCHECK(profile); + return CreateViewHost(url, profile, NULL, VIEW_TYPE_EXTENSION_DIALOG); +} + +} // namespace extensions diff --git a/chrome/browser/extensions/extension_host_factory.h b/chrome/browser/extensions/extension_host_factory.h new file mode 100644 index 0000000..b910490 --- /dev/null +++ b/chrome/browser/extensions/extension_host_factory.h @@ -0,0 +1,38 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_HOST_FACTORY_H_ +#define CHROME_BROWSER_EXTENSIONS_EXTENSION_HOST_FACTORY_H_ + +#include "base/basictypes.h" + +class Browser; +class GURL; +class Profile; + +namespace extensions { + +class ExtensionHost; + +// A utility class to make ExtensionHosts, specifically those with browser- +// specific needs. +class ExtensionHostFactory { + public: + // Creates a new ExtensionHost with its associated view, grouping it in the + // appropriate SiteInstance (and therefore process) based on the URL and + // profile. + static ExtensionHost* CreatePopupHost(const GURL& url, Browser* browser); + static ExtensionHost* CreateInfobarHost(const GURL& url, Browser* browser); + + // Some dialogs may not be associated with a particular browser window and + // hence only require a |profile|. + static ExtensionHost* CreateDialogHost(const GURL& url, Profile* profile); + + private: + DISALLOW_COPY_AND_ASSIGN(ExtensionHostFactory); +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_HOST_FACTORY_H_ diff --git a/chrome/browser/extensions/extension_host_factory_browsertest.cc b/chrome/browser/extensions/extension_host_factory_browsertest.cc new file mode 100644 index 0000000..5fb5bcc --- /dev/null +++ b/chrome/browser/extensions/extension_host_factory_browsertest.cc @@ -0,0 +1,88 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/extension_host_factory.h" + +#include "chrome/browser/extensions/extension_browsertest.h" +#include "chrome/test/base/ui_test_utils.h" +#include "extensions/common/view_type.h" + +namespace extensions { + +typedef ExtensionBrowserTest ExtensionHostFactoryTest; + +// Tests that ExtensionHosts are created with the correct type and profiles. +IN_PROC_BROWSER_TEST_F(ExtensionHostFactoryTest, CreateExtensionHosts) { + // Load a very simple extension with just a background page. + scoped_refptr<const Extension> extension = + LoadExtension(test_data_dir_.AppendASCII("api_test") + .AppendASCII("browser_action") + .AppendASCII("none")); + ASSERT_TRUE(extension.get()); + + { + // Popup hosts are created with the correct type and profile. + scoped_ptr<ExtensionHost> host( + ExtensionHostFactory::CreatePopupHost(extension->url(), browser())); + EXPECT_EQ(extension.get(), host->extension()); + EXPECT_EQ(browser()->profile(), host->profile()); + EXPECT_EQ(VIEW_TYPE_EXTENSION_POPUP, host->extension_host_type()); + } + + { + // Infobar hosts are created with the correct type and profile. + scoped_ptr<ExtensionHost> host( + ExtensionHostFactory::CreateInfobarHost(extension->url(), browser())); + EXPECT_EQ(extension.get(), host->extension()); + EXPECT_EQ(browser()->profile(), host->profile()); + EXPECT_EQ(VIEW_TYPE_EXTENSION_INFOBAR, host->extension_host_type()); + } + + { + // Dialog hosts are created with the correct type and profile. + scoped_ptr<ExtensionHost> host(ExtensionHostFactory::CreateDialogHost( + extension->url(), browser()->profile())); + EXPECT_EQ(extension.get(), host->extension()); + EXPECT_EQ(browser()->profile(), host->profile()); + EXPECT_EQ(VIEW_TYPE_EXTENSION_DIALOG, host->extension_host_type()); + } +} + +// Tests that extensions loaded in incognito mode have the correct profiles +// for split-mode and non-split-mode. +IN_PROC_BROWSER_TEST_F(ExtensionHostFactoryTest, IncognitoExtensionHosts) { + // Open an incognito browser. + Browser* incognito_browser = ui_test_utils::OpenURLOffTheRecord( + browser()->profile(), GURL("about:blank")); + + // Load a non-split-mode extension, enabled in incognito. + scoped_refptr<const Extension> regular_extension = + LoadExtensionIncognito(test_data_dir_.AppendASCII("api_test") + .AppendASCII("browser_action") + .AppendASCII("none")); + ASSERT_TRUE(regular_extension.get()); + + // The ExtensionHost for a regular extension in an incognito window is + // associated with the original window's profile. + scoped_ptr<ExtensionHost> regular_host( + ExtensionHostFactory::CreatePopupHost( + regular_extension->url(), incognito_browser)); + EXPECT_EQ(browser()->profile(), regular_host->profile()); + + // Load a split-mode incognito extension. + scoped_refptr<const Extension> split_mode_extension = + LoadExtensionIncognito(test_data_dir_.AppendASCII("api_test") + .AppendASCII("browser_action") + .AppendASCII("split_mode")); + ASSERT_TRUE(split_mode_extension.get()); + + // The ExtensionHost for a split-mode extension is associated with the + // incognito profile. + scoped_ptr<ExtensionHost> split_mode_host( + ExtensionHostFactory::CreatePopupHost( + split_mode_extension->url(), incognito_browser)); + EXPECT_EQ(incognito_browser->profile(), split_mode_host->profile()); +} + +} // namespace extensions diff --git a/chrome/browser/extensions/extension_infobar_delegate.cc b/chrome/browser/extensions/extension_infobar_delegate.cc index a752583..66e3f09 100644 --- a/chrome/browser/extensions/extension_infobar_delegate.cc +++ b/chrome/browser/extensions/extension_infobar_delegate.cc @@ -6,8 +6,7 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/extension_host.h" -#include "chrome/browser/extensions/extension_process_manager.h" -#include "chrome/browser/extensions/extension_system.h" +#include "chrome/browser/extensions/extension_host_factory.h" #include "chrome/browser/infobars/infobar.h" #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/profiles/profile.h" @@ -16,7 +15,6 @@ #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_source.h" - ExtensionInfoBarDelegate::~ExtensionInfoBarDelegate() { if (observer_) observer_->OnDelegateDeleted(); @@ -47,9 +45,8 @@ ExtensionInfoBarDelegate::ExtensionInfoBarDelegate( observer_(NULL), extension_(extension), closing_(false) { - ExtensionProcessManager* manager = - extensions::ExtensionSystem::Get(browser->profile())->process_manager(); - extension_host_.reset(manager->CreateInfobarHost(url, browser)); + extension_host_.reset( + extensions::ExtensionHostFactory::CreateInfobarHost(url, browser)); extension_host_->SetAssociatedWebContents(web_contents); registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_VIEW_SHOULD_CLOSE, diff --git a/chrome/browser/extensions/extension_process_manager.cc b/chrome/browser/extensions/extension_process_manager.cc index 1dc79da..b11eecf 100644 --- a/chrome/browser/extensions/extension_process_manager.cc +++ b/chrome/browser/extensions/extension_process_manager.cc @@ -16,16 +16,13 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/api/runtime/runtime_api.h" #include "chrome/browser/extensions/extension_host.h" -#include "chrome/browser/extensions/extension_info_map.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_system.h" #include "chrome/browser/extensions/extension_util.h" -#include "chrome/browser/ui/browser.h" #include "chrome/common/extensions/background_info.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_messages.h" -#include "chrome/common/extensions/manifest_url_handler.h" -#include "chrome/common/url_constants.h" +#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/devtools_manager.h" @@ -88,11 +85,6 @@ class IncognitoExtensionProcessManager : public ExtensionProcessManager { IncognitoExtensionProcessManager(BrowserContext* incognito_context, BrowserContext* original_context); virtual ~IncognitoExtensionProcessManager(); - virtual ExtensionHost* CreateViewHost( - const Extension* extension, - const GURL& url, - Browser* browser, - extensions::ViewType view_type) OVERRIDE; virtual ExtensionHost* CreateBackgroundHost(const Extension* extension, const GURL& url) OVERRIDE; virtual SiteInstance* GetSiteInstanceForURL(const GURL& url) OVERRIDE; @@ -248,80 +240,6 @@ ExtensionProcessManager::GetAllViews() const { return result; } -void ExtensionProcessManager::EnsureBrowserWhenRequired( - Browser* browser, - extensions::ViewType view_type) { - if (!browser) { - // A NULL browser may only be given for pop-up views and dialogs. - DCHECK(view_type == extensions::VIEW_TYPE_EXTENSION_POPUP || - view_type == extensions::VIEW_TYPE_EXTENSION_DIALOG); - } -} - -ExtensionHost* ExtensionProcessManager::CreateViewHost( - const Extension* extension, - const GURL& url, - Browser* browser, - extensions::ViewType view_type) { - DVLOG(1) << "CreateViewHost"; - DCHECK(extension); - EnsureBrowserWhenRequired(browser, view_type); - ExtensionHost* host = -#if defined(OS_MACOSX) - new extensions::ExtensionHostMac( - extension, GetSiteInstanceForURL(url), url, view_type); -#else - new ExtensionHost(extension, GetSiteInstanceForURL(url), url, view_type); -#endif - host->CreateView(browser); - OnExtensionHostCreated(host, false); - return host; -} - -ExtensionHost* ExtensionProcessManager::CreateViewHost( - const GURL& url, Browser* browser, extensions::ViewType view_type) { - EnsureBrowserWhenRequired(browser, view_type); - ExtensionService* service = ExtensionSystem::GetForBrowserContext( - GetBrowserContext())->extension_service(); - if (service) { - std::string extension_id = url.host(); - if (url.SchemeIs(chrome::kChromeUIScheme) && - url.host() == chrome::kChromeUIExtensionInfoHost) - extension_id = url.path().substr(1); - const Extension* extension = - service->extensions()->GetByID(extension_id); - if (extension) - return CreateViewHost(extension, url, browser, view_type); - } - return NULL; -} - -ExtensionHost* ExtensionProcessManager::CreatePopupHost( - const Extension* extension, const GURL& url, Browser* browser) { - return CreateViewHost( - extension, url, browser, extensions::VIEW_TYPE_EXTENSION_POPUP); -} - -ExtensionHost* ExtensionProcessManager::CreatePopupHost( - const GURL& url, Browser* browser) { - return CreateViewHost(url, browser, extensions::VIEW_TYPE_EXTENSION_POPUP); -} - -ExtensionHost* ExtensionProcessManager::CreateDialogHost(const GURL& url) { - return CreateViewHost(url, NULL, extensions::VIEW_TYPE_EXTENSION_DIALOG); -} - -ExtensionHost* ExtensionProcessManager::CreateInfobarHost( - const Extension* extension, const GURL& url, Browser* browser) { - return CreateViewHost( - extension, url, browser, extensions::VIEW_TYPE_EXTENSION_INFOBAR); -} - -ExtensionHost* ExtensionProcessManager::CreateInfobarHost( - const GURL& url, Browser* browser) { - return CreateViewHost(url, browser, extensions::VIEW_TYPE_EXTENSION_INFOBAR); -} - ExtensionHost* ExtensionProcessManager::CreateBackgroundHost( const Extension* extension, const GURL& url) { DVLOG(1) << "CreateBackgroundHost " << url.spec(); @@ -345,7 +263,7 @@ ExtensionHost* ExtensionProcessManager::CreateBackgroundHost( #endif host->CreateRenderViewSoon(); - OnExtensionHostCreated(host, true); + OnBackgroundHostCreated(host); return host; } @@ -792,20 +710,17 @@ void ExtensionProcessManager::CreateBackgroundHostsForProfileStartup() { } } -void ExtensionProcessManager::OnExtensionHostCreated(ExtensionHost* host, - bool is_background) { - DCHECK_EQ(site_instance_->GetBrowserContext(), host->browser_context()); - if (is_background) { - background_hosts_.insert(host); +void ExtensionProcessManager::OnBackgroundHostCreated(ExtensionHost* host) { + DCHECK_EQ(GetBrowserContext(), host->browser_context()); + background_hosts_.insert(host); - if (BackgroundInfo::HasLazyBackgroundPage(host->extension())) { - linked_ptr<base::ElapsedTimer> since_suspended( - background_page_data_[host->extension()->id()]. - since_suspended.release()); - if (since_suspended.get()) { - UMA_HISTOGRAM_LONG_TIMES("Extensions.EventPageIdleTime", - since_suspended->Elapsed()); - } + if (BackgroundInfo::HasLazyBackgroundPage(host->extension())) { + linked_ptr<base::ElapsedTimer> since_suspended( + background_page_data_[host->extension()->id()]. + since_suspended.release()); + if (since_suspended.get()) { + UMA_HISTOGRAM_LONG_TIMES("Extensions.EventPageIdleTime", + since_suspended->Elapsed()); } } } @@ -902,27 +817,6 @@ IncognitoExtensionProcessManager::~IncognitoExtensionProcessManager() { service->menu_manager()->RemoveAllIncognitoContextItems(); } -ExtensionHost* IncognitoExtensionProcessManager::CreateViewHost( - const Extension* extension, - const GURL& url, - Browser* browser, - extensions::ViewType view_type) { - if (extensions::IncognitoInfo::IsSplitMode(extension)) { - if (IsIncognitoEnabled(extension)) { - return ExtensionProcessManager::CreateViewHost(extension, url, - browser, view_type); - } else { - NOTREACHED() << - "We shouldn't be trying to create an incognito extension view unless " - "it has been enabled for incognito."; - return NULL; - } - } else { - return original_manager_->CreateViewHost(extension, url, - browser, view_type); - } -} - ExtensionHost* IncognitoExtensionProcessManager::CreateBackgroundHost( const Extension* extension, const GURL& url) { if (extensions::IncognitoInfo::IsSplitMode(extension)) { diff --git a/chrome/browser/extensions/extension_process_manager.h b/chrome/browser/extensions/extension_process_manager.h index 2b7273f..a2fefb1 100644 --- a/chrome/browser/extensions/extension_process_manager.h +++ b/chrome/browser/extensions/extension_process_manager.h @@ -18,7 +18,6 @@ #include "content/public/browser/notification_registrar.h" #include "extensions/common/view_type.h" -class Browser; class GURL; namespace content { @@ -51,30 +50,6 @@ class ExtensionProcessManager : public content::NotificationObserver { typedef std::set<content::RenderViewHost*> ViewSet; const ViewSet GetAllViews() const; - // Creates a new ExtensionHost with its associated view, grouping it in the - // appropriate SiteInstance (and therefore process) based on the URL and - // profile. - virtual extensions::ExtensionHost* CreateViewHost( - const extensions::Extension* extension, - const GURL& url, - Browser* browser, - extensions::ViewType view_type); - extensions::ExtensionHost* CreateViewHost(const GURL& url, - Browser* browser, - extensions::ViewType view_type); - extensions::ExtensionHost* CreatePopupHost( - const extensions::Extension* extension, - const GURL& url, - Browser* browser); - extensions::ExtensionHost* CreatePopupHost(const GURL& url, Browser* browser); - extensions::ExtensionHost* CreateDialogHost(const GURL& url); - extensions::ExtensionHost* CreateInfobarHost( - const extensions::Extension* extension, - const GURL& url, - Browser* browser); - extensions::ExtensionHost* CreateInfobarHost(const GURL& url, - Browser* browser); - // Creates a new UI-less extension instance. Like CreateViewHost, but not // displayed anywhere. virtual extensions::ExtensionHost* CreateBackgroundHost( @@ -153,10 +128,6 @@ class ExtensionProcessManager : public content::NotificationObserver { ExtensionProcessManager(content::BrowserContext* context, content::BrowserContext* original_context); - // Called just after |host| is created so it can be registered in our lists. - void OnExtensionHostCreated(extensions::ExtensionHost* host, - bool is_background); - // Called on browser shutdown to close our extension hosts. void CloseBackgroundHosts(); @@ -189,13 +160,12 @@ class ExtensionProcessManager : public content::NotificationObserver { typedef std::map<content::RenderViewHost*, extensions::ViewType> ExtensionRenderViews; + // Called just after |host| is created so it can be registered in our lists. + void OnBackgroundHostCreated(extensions::ExtensionHost* host); + // Close the given |host| iff it's a background page. void CloseBackgroundHost(extensions::ExtensionHost* host); - // Ensure browser object is not null except for certain situations. - void EnsureBrowserWhenRequired(Browser* browser, - extensions::ViewType view_type); - // These are called when the extension transitions between idle and active. // They control the process of closing the background page when idle. void OnLazyBackgroundPageIdle(const std::string& extension_id, |