diff options
author | jamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-16 21:23:47 +0000 |
---|---|---|
committer | jamescook@chromium.org <jamescook@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-01-16 21:23:47 +0000 |
commit | b32c76fc04ba5e17ae394f026542883cf8037a57 (patch) | |
tree | 1e06fec564ea11d33b8f38717366e45e6f0a3ced /apps | |
parent | a208843d74b70f8d728c3b9e73de9e990393852d (diff) | |
download | chromium_src-b32c76fc04ba5e17ae394f026542883cf8037a57.zip chromium_src-b32c76fc04ba5e17ae394f026542883cf8037a57.tar.gz chromium_src-b32c76fc04ba5e17ae394f026542883cf8037a57.tar.bz2 |
app_shell: Make renderer run background page JavaScript
* Install URL protocol handler for chrome-extension:// and chrome-extension-resource://
* Allow extension urls to be handled.
* Register extensions with IO thread extension InfoMap.
* Bonus: app_shell no longer crashes on startup.
With this change an extension background page can print "Hello world" using console.log().
BUG=288226,332982
TEST=browser_tests. Also run app_shell --app=/path/to/extension with an extension with background.js. The JavaScript executes and console.log() works.
Review URL: https://codereview.chromium.org/136453005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@245325 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'apps')
-rw-r--r-- | apps/shell/DEPS | 2 | ||||
-rw-r--r-- | apps/shell/shell_browser_main_parts.h | 4 | ||||
-rw-r--r-- | apps/shell/shell_content_browser_client.cc | 110 | ||||
-rw-r--r-- | apps/shell/shell_content_browser_client.h | 17 | ||||
-rw-r--r-- | apps/shell/shell_extension_system.cc | 26 | ||||
-rw-r--r-- | apps/shell/shell_extension_system.h | 4 |
6 files changed, 155 insertions, 8 deletions
diff --git a/apps/shell/DEPS b/apps/shell/DEPS index 2ac93a1..4a90c8f 100644 --- a/apps/shell/DEPS +++ b/apps/shell/DEPS @@ -6,6 +6,8 @@ include_rules = [ # TODO(jamescook): Remove these. http://crbug.com/305404 # Chrome pieces for bring-up. + "+chrome/browser/extensions/extension_protocols.h", + "+chrome/browser/extensions/extension_resource_protocols.h", "+chrome/common/chrome_paths.h", "+chrome/common/extensions/extension_file_util.h", "+chrome/common/extensions/features/base_feature_provider.h", diff --git a/apps/shell/shell_browser_main_parts.h b/apps/shell/shell_browser_main_parts.h index 21a11c4..62ff772 100644 --- a/apps/shell/shell_browser_main_parts.h +++ b/apps/shell/shell_browser_main_parts.h @@ -46,6 +46,10 @@ class ShellBrowserMainParts : public content::BrowserMainParts, return browser_context_.get(); } + extensions::ShellExtensionSystem* extension_system() { + return extension_system_; + } + // BrowserMainParts overrides. virtual void PreEarlyInitialization() OVERRIDE; virtual void PreMainMessageLoopStart() OVERRIDE; diff --git a/apps/shell/shell_content_browser_client.cc b/apps/shell/shell_content_browser_client.cc index d269965..589028c 100644 --- a/apps/shell/shell_content_browser_client.cc +++ b/apps/shell/shell_content_browser_client.cc @@ -6,7 +6,25 @@ #include "apps/shell/shell_browser_context.h" #include "apps/shell/shell_browser_main_parts.h" +#include "apps/shell/shell_extension_system.h" +#include "base/command_line.h" +#include "chrome/browser/extensions/extension_protocols.h" +#include "chrome/browser/extensions/extension_resource_protocols.h" +#include "chrome/common/chrome_switches.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/site_instance.h" +#include "content/public/common/content_switches.h" +#include "content/public/common/url_constants.h" #include "content/shell/browser/shell_browser_context.h" +#include "extensions/browser/extension_registry.h" +#include "extensions/browser/info_map.h" +#include "extensions/common/constants.h" +#include "extensions/common/extension.h" +#include "url/gurl.h" + +using content::BrowserThread; +using extensions::ExtensionRegistry; namespace apps { @@ -27,9 +45,99 @@ net::URLRequestContextGetter* ShellContentBrowserClient::CreateRequestContext( content::BrowserContext* content_browser_context, content::ProtocolHandlerMap* protocol_handlers) { - // TODO(jamescook): Should this be an off-the-record context? + // Handle chrome-extension: and chrome-extension-resource: requests. + extensions::InfoMap* extension_info_map = + browser_main_parts_->extension_system()->info_map(); + (*protocol_handlers)[extensions::kExtensionScheme] = + linked_ptr<net::URLRequestJobFactory::ProtocolHandler>( + CreateExtensionProtocolHandler(false /*is_incognito*/, + extension_info_map)); + (*protocol_handlers)[extensions::kExtensionResourceScheme] = + linked_ptr<net::URLRequestJobFactory::ProtocolHandler>( + CreateExtensionResourceProtocolHandler()); + // Let content::ShellBrowserContext handle the rest of the setup. return browser_main_parts_->browser_context()->CreateRequestContext( protocol_handlers); } +bool ShellContentBrowserClient::IsHandledURL(const GURL& url) { + if (!url.is_valid()) + return false; + // Keep in sync with ProtocolHandlers added in CreateRequestContext() and in + // content::ShellURLRequestContextGetter::GetURLRequestContext(). + static const char* const kProtocolList[] = { + chrome::kBlobScheme, + chrome::kChromeUIScheme, + chrome::kChromeDevToolsScheme, + chrome::kDataScheme, + content::kFileScheme, + content::kFileSystemScheme, + extensions::kExtensionScheme, + extensions::kExtensionResourceScheme, + }; + for (size_t i = 0; i < arraysize(kProtocolList); ++i) { + if (url.scheme() == kProtocolList[i]) + return true; + } + return false; +} + +void ShellContentBrowserClient::SiteInstanceGotProcess( + content::SiteInstance* site_instance) { + // If this isn't an extension renderer there's nothing to do. + const extensions::Extension* extension = GetExtension(site_instance); + if (!extension) + return; + + // TODO(jamescook): Add to extension service process_map(). + + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(&extensions::InfoMap::RegisterExtensionProcess, + browser_main_parts_->extension_system()->info_map(), + extension->id(), + site_instance->GetProcess()->GetID(), + site_instance->GetId())); +} + +void ShellContentBrowserClient::SiteInstanceDeleting( + content::SiteInstance* site_instance) { + // If this isn't an extension renderer there's nothing to do. + const extensions::Extension* extension = GetExtension(site_instance); + if (!extension) + return; + + // TODO(jamescook): Remove from extension service process_map(). + + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(&extensions::InfoMap::UnregisterExtensionProcess, + browser_main_parts_->extension_system()->info_map(), + extension->id(), + site_instance->GetProcess()->GetID(), + site_instance->GetId())); +} + +void ShellContentBrowserClient::AppendExtraCommandLineSwitches( + CommandLine* command_line, int child_process_id) { + std::string process_type = + command_line->GetSwitchValueASCII(switches::kProcessType); + if (process_type == switches::kRendererProcess) { + // TODO(jamescook): Should we check here if the process is in the extension + // service process map, or can we assume all renderers are extension + // renderers? + command_line->AppendSwitch(switches::kExtensionProcess); + } +} + +const extensions::Extension* ShellContentBrowserClient::GetExtension( + content::SiteInstance* site_instance) { + ExtensionRegistry* registry = + ExtensionRegistry::Get(site_instance->GetBrowserContext()); + return registry->enabled_extensions().GetExtensionOrAppByURL( + site_instance->GetSiteURL()); +} + } // namespace apps diff --git a/apps/shell/shell_content_browser_client.h b/apps/shell/shell_content_browser_client.h index e72ab2ed..db0f5a8 100644 --- a/apps/shell/shell_content_browser_client.h +++ b/apps/shell/shell_content_browser_client.h @@ -8,6 +8,12 @@ #include "base/compiler_specific.h" #include "content/public/browser/content_browser_client.h" +class GURL; + +namespace extensions { +class Extension; +} + namespace apps { class ShellBrowserMainParts; @@ -24,8 +30,19 @@ class ShellContentBrowserClient : public content::ContentBrowserClient { content::ProtocolHandlerMap* protocol_handlers) OVERRIDE; // TODO(jamescook): Quota management? // TODO(jamescook): Speech recognition? + virtual bool IsHandledURL(const GURL& url) OVERRIDE; + virtual void SiteInstanceGotProcess(content::SiteInstance* site_instance) + OVERRIDE; + virtual void SiteInstanceDeleting(content::SiteInstance* site_instance) + OVERRIDE; + virtual void AppendExtraCommandLineSwitches(CommandLine* command_line, + int child_process_id) OVERRIDE; private: + // Returns the extension or app associated with |site_instance| or NULL. + const extensions::Extension* GetExtension( + content::SiteInstance* site_instance); + // Owned by content::BrowserMainLoop. ShellBrowserMainParts* browser_main_parts_; diff --git a/apps/shell/shell_extension_system.cc b/apps/shell/shell_extension_system.cc index f3ba941..dfb9fec 100644 --- a/apps/shell/shell_extension_system.cc +++ b/apps/shell/shell_extension_system.cc @@ -12,15 +12,18 @@ #include "chrome/browser/extensions/extension_prefs.h" #include "chrome/common/extensions/extension_file_util.h" #include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_source.h" #include "extensions/browser/event_router.h" #include "extensions/browser/extension_registry.h" +#include "extensions/browser/info_map.h" #include "extensions/browser/lazy_background_task_queue.h" #include "extensions/browser/process_manager.h" using content::BrowserContext; +using content::BrowserThread; namespace extensions { @@ -44,10 +47,16 @@ bool ShellExtensionSystem::LoadAndLaunchApp(const base::FilePath& app_dir) { return false; } + // TODO(jamescook): We may want to do some of these things here: + // * Create a PermissionsUpdater. + // * Call PermissionsUpdater::GrantActivePermissions(). + // * Call ExtensionService::SatisfyImports(). + // * Call ExtensionPrefs::OnExtensionInstalled(). + // * Send NOTIFICATION_EXTENSION_INSTALLED. + ExtensionRegistry::Get(browser_context_)->AddEnabled(extension); - // TODO(jamescook): If RegisterExtensionWithRequestContexts() did something, - // this would be the place to call it. + RegisterExtensionWithRequestContexts(extension); content::NotificationService::current()->Notify( chrome::NOTIFICATION_EXTENSION_LOADED, @@ -56,9 +65,6 @@ bool ShellExtensionSystem::LoadAndLaunchApp(const base::FilePath& app_dir) { // Inform the rest of the extensions system to start. ready_.Signal(); - LOG(WARNING) << "-----------------------------------"; - LOG(WARNING) << "app_shell is expected to crash now."; - LOG(WARNING) << "-----------------------------------"; content::NotificationService::current()->Notify( chrome::NOTIFICATION_EXTENSIONS_READY, content::Source<BrowserContext>(browser_context_), @@ -79,7 +85,6 @@ void ShellExtensionSystem::InitForRegularProfile(bool extensions_enabled) { } ExtensionService* ShellExtensionSystem::extension_service() { - NOTREACHED(); return NULL; } @@ -104,7 +109,9 @@ StateStore* ShellExtensionSystem::rules_store() { } InfoMap* ShellExtensionSystem::info_map() { - return NULL; + if (!info_map_.get()) + info_map_ = new InfoMap; + return info_map_; } LazyBackgroundTaskQueue* ShellExtensionSystem::lazy_background_task_queue() { @@ -133,6 +140,11 @@ InstallVerifier* ShellExtensionSystem::install_verifier() { void ShellExtensionSystem::RegisterExtensionWithRequestContexts( const Extension* extension) { + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&InfoMap::AddExtension, info_map(), + make_scoped_refptr(extension), base::Time::Now(), + false, false)); } void ShellExtensionSystem::UnregisterExtensionWithRequestContexts( diff --git a/apps/shell/shell_extension_system.h b/apps/shell/shell_extension_system.h index acc34f0..a72e089 100644 --- a/apps/shell/shell_extension_system.h +++ b/apps/shell/shell_extension_system.h @@ -20,6 +20,7 @@ class BrowserContext; namespace extensions { class EventRouter; +class InfoMap; class LazyBackgroundTaskQueue; class ProcessManager; @@ -63,6 +64,9 @@ class ShellExtensionSystem : public ExtensionSystem { private: content::BrowserContext* browser_context_; // Not owned. + // Data to be accessed on the IO thread. Must outlive process_manager_. + scoped_refptr<InfoMap> info_map_; + scoped_ptr<LazyBackgroundTaskQueue> lazy_background_task_queue_; scoped_ptr<EventRouter> event_router_; scoped_ptr<ProcessManager> process_manager_; |