shell_content_browser_client.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
15f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// Copyright 2014 The Chromium Authors. All rights reserved.
25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// Use of this source code is governed by a BSD-style license that can be
35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// found in the LICENSE file.
45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner#include "extensions/shell/browser/shell_content_browser_client.h"
60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner
75f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "base/command_line.h"
85f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "content/public/browser/browser_thread.h"
95f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "content/public/browser/render_process_host.h"
105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "content/public/browser/site_instance.h"
115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "content/public/common/content_switches.h"
125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "content/public/common/url_constants.h"
135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "content/shell/browser/shell_browser_context.h"
145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "extensions/browser/extension_message_filter.h"
155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "extensions/browser/extension_protocols.h"
165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "extensions/browser/extension_registry.h"
17af8fa25c0d4e0540952a50bbd06dc1558954ccd9Ted Kremenek#include "extensions/browser/info_map.h"
185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "extensions/browser/process_map.h"
199c1b750c59d510e6c9eccb1f37bccc46ccfe6844Ted Kremenek#include "extensions/common/constants.h"
20eb50ed88c2aa040fac08bf2a50bde4dd3da6eb19Chris Lattner#include "extensions/common/extension.h"
215d75de0f821023f4ed4815825bf3aea8a0b5e40dChris Lattner#include "extensions/common/switches.h"
226137dc99ef0c2b14050631367057758b0d596cb3Ted Kremenek#include "extensions/shell/browser/shell_browser_context.h"
231b63e4f732dbc73d90abf886b4d21f8e3a165f6dChris Lattner#include "extensions/shell/browser/shell_browser_main_parts.h"
24d7a3e2c5f61cd4893f95b69a424fe4def3aa0f69Benjamin Kramer#include "extensions/shell/browser/shell_extension_system.h"
25c7229c338c21ef26b01ef3ecf9eec4fd373fa9ecChris Lattner#include "url/gurl.h"
265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
27cc1a875f94630e58d24a55577ffbf0e89b7da8c7Chris Lattnerusing content::BrowserThread;
284f32786ac45210143654390177105eb749b614e9Ted Kremenek
290827408865e32789e0ec4b8113a302ccdc531423Argyrios Kyrtzidisnamespace extensions {
30caaa7df2c78bbd40197823034c0275f3dcbd63e7Ted Kremeneknamespace {
31f4d5eb4866a27d497f0bb75b12c2ffd48ad4d9c0Benjamin Kramer
325b3284a9275a27f5c4410e25eb8933be540601d6Argyrios KyrtzidisShellContentBrowserClient* g_instance = NULL;
330ea76727ae91bca918a8414ed85b530eddcfedebTed Kremenek
342e22253e03e175144aeb9d13350a12fd83f858beDouglas Gregor}  // namespace
355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
368fe83e1df954d72c0f4ffc15d20a5222ec151c21Benjamin KramerShellContentBrowserClient::ShellContentBrowserClient(
378fe83e1df954d72c0f4ffc15d20a5222ec151c21Benjamin Kramer    ShellBrowserMainDelegate* browser_main_delegate)
388fe83e1df954d72c0f4ffc15d20a5222ec151c21Benjamin Kramer    : browser_main_parts_(NULL), browser_main_delegate_(browser_main_delegate) {
398fe83e1df954d72c0f4ffc15d20a5222ec151c21Benjamin Kramer  DCHECK(!g_instance);
405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  g_instance = this;
411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}
425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
4388a35862fbe473f2a4f0c19f24dbe536937e1dc6Douglas GregorShellContentBrowserClient::~ShellContentBrowserClient() {
445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  g_instance = NULL;
455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// static
485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerShellContentBrowserClient* ShellContentBrowserClient::Get() {
492e22253e03e175144aeb9d13350a12fd83f858beDouglas Gregor  return g_instance;
505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencercontent::BrowserContext* ShellContentBrowserClient::GetBrowserContext() {
53f44e854ed1e3aa86d2ed6d615ccd109d50ddcff9Douglas Gregor  return browser_main_parts_->browser_context();
545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
5594dc8f640ebea52241412512ed48601626edbc58Douglas Gregor
566aa52ec6b969faabf3764baf79d89810b8249a7eDouglas Gregorcontent::BrowserMainParts* ShellContentBrowserClient::CreateBrowserMainParts(
57ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie    const content::MainFunctionParams& parameters) {
58e5956bd2730c051835f9acd9e957c5d79f99e7c3Chris Lattner  browser_main_parts_ =
595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      new ShellBrowserMainParts(parameters, browser_main_delegate_);
605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  return browser_main_parts_;
615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
63c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmithvoid ShellContentBrowserClient::RenderProcessWillLaunch(
64d7a3e2c5f61cd4893f95b69a424fe4def3aa0f69Benjamin Kramer    content::RenderProcessHost* host) {
654e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  int render_process_id = host->GetID();
66998b3d3e8528ebd9d2c5d78d3a82edd90a8953a4Douglas Gregor  host->AddFilter(new ExtensionMessageFilter(
675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      render_process_id, browser_main_parts_->browser_context()));
685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerbool ShellContentBrowserClient::ShouldUseProcessPerSite(
716aa52ec6b969faabf3764baf79d89810b8249a7eDouglas Gregor    content::BrowserContext* browser_context,
721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    const GURL& effective_url) {
7388a35862fbe473f2a4f0c19f24dbe536937e1dc6Douglas Gregor  // This ensures that all render views created for a single app will use the
7488a35862fbe473f2a4f0c19f24dbe536937e1dc6Douglas Gregor  // same render process (see content::SiteInstance::GetProcess). Otherwise the
75a5d10c4df435964600e104ebef6a96b106e416b7Kovarththanan Rajaratnam  // default behavior of ContentBrowserClient will lead to separate render
76ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie  // processes for the background page and each app window view.
776137dc99ef0c2b14050631367057758b0d596cb3Ted Kremenek  return true;
786137dc99ef0c2b14050631367057758b0d596cb3Ted Kremenek}
796f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith
801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpnet::URLRequestContextGetter* ShellContentBrowserClient::CreateRequestContext(
810ea76727ae91bca918a8414ed85b530eddcfedebTed Kremenek    content::BrowserContext* content_browser_context,
820ea76727ae91bca918a8414ed85b530eddcfedebTed Kremenek    content::ProtocolHandlerMap* protocol_handlers,
830ea76727ae91bca918a8414ed85b530eddcfedebTed Kremenek    content::URLRequestInterceptorScopedVector request_interceptors) {
841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Handle only chrome-extension:// requests. app_shell does not support
855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // chrome-extension-resource:// requests (it does not store shared extension
865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // data in its installation directory).
875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  InfoMap* extension_info_map =
885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      browser_main_parts_->extension_system()->info_map();
895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  (*protocol_handlers)[kExtensionScheme] =
905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      linked_ptr<net::URLRequestJobFactory::ProtocolHandler>(
91c1f9d828c733ec1eba06d01070735d1f36fda733Chris Lattner          CreateExtensionProtocolHandler(false /* is_incognito */,
921ef8a2e7675f3d8b6e8d9963b00378086e1dcdc7John McCall                                         extension_info_map));
931ef8a2e7675f3d8b6e8d9963b00378086e1dcdc7John McCall  // Let content::ShellBrowserContext handle the rest of the setup.
94148772a841cae6f32db16d890e788b92a763bb3fChris Lattner  return browser_main_parts_->browser_context()->CreateRequestContext(
95c1b5fa41f09512c74030b9a2a0d1564535e22a76Peter Collingbourne      protocol_handlers, request_interceptors.Pass());
96148772a841cae6f32db16d890e788b92a763bb3fChris Lattner}
97cae5095c116c29a4e52c91fa0ad88df09dd2b45fAnders Carlsson
9892bd8c70a6837b647a6c55964f8d0a50bf561dbcJohn Thompsonbool ShellContentBrowserClient::IsHandledURL(const GURL& url) {
9992bd8c70a6837b647a6c55964f8d0a50bf561dbcJohn Thompson  if (!url.is_valid())
100d768150ef57f617c8d9fef48f3c92e8f21698024Ted Kremenek    return false;
1011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Keep in sync with ProtocolHandlers added in CreateRequestContext() and in
1025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // content::ShellURLRequestContextGetter::GetURLRequestContext().
103c1f9d828c733ec1eba06d01070735d1f36fda733Chris Lattner  static const char* const kProtocolList[] = {
1045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      url::kBlobScheme,
1055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      content::kChromeDevToolsScheme,
1065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      content::kChromeUIScheme,
1075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      url::kDataScheme,
1085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      url::kFileScheme,
1095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      url::kFileSystemScheme,
1105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      kExtensionScheme,
1115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      kExtensionResourceScheme,
1125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  };
113f84139a1331c63c998e8b7d54148c75ac0b48ccdEli Friedman  for (size_t i = 0; i < arraysize(kProtocolList); ++i) {
114ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie    if (url.scheme() == kProtocolList[i])
1155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      return true;
1165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
1175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  return false;
1185814e657c9ad9ef6049a2a4af0d2aad248a8a15cDaniel Dunbar}
1195814e657c9ad9ef6049a2a4af0d2aad248a8a15cDaniel Dunbar
1205814e657c9ad9ef6049a2a4af0d2aad248a8a15cDaniel Dunbarvoid ShellContentBrowserClient::SiteInstanceGotProcess(
1211d9c54df56391ac4740db27d551782e81189cb51Chris Lattner    content::SiteInstance* site_instance) {
1221d9c54df56391ac4740db27d551782e81189cb51Chris Lattner  // If this isn't an extension renderer there's nothing to do.
1231d9c54df56391ac4740db27d551782e81189cb51Chris Lattner  const Extension* extension = GetExtension(site_instance);
1248c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  if (!extension)
1258c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie    return;
1268c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie
1278c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie  ProcessMap::Get(browser_main_parts_->browser_context())
1288c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie      ->Insert(extension->id(),
1298c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie               site_instance->GetProcess()->GetID(),
1308c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie               site_instance->GetId());
13188a35862fbe473f2a4f0c19f24dbe536937e1dc6Douglas Gregor
13288a35862fbe473f2a4f0c19f24dbe536937e1dc6Douglas Gregor  BrowserThread::PostTask(
133a5d10c4df435964600e104ebef6a96b106e416b7Kovarththanan Rajaratnam      BrowserThread::IO,
13414e645557ae91c6770d62beb00a1c522e0bfd5d6Argyrios Kyrtzidis      FROM_HERE,
13514e645557ae91c6770d62beb00a1c522e0bfd5d6Argyrios Kyrtzidis      base::Bind(&InfoMap::RegisterExtensionProcess,
13614e645557ae91c6770d62beb00a1c522e0bfd5d6Argyrios Kyrtzidis                 browser_main_parts_->extension_system()->info_map(),
1375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                 extension->id(),
1385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                 site_instance->GetProcess()->GetID(),
139c3222091e1ffa35d0264ca6b680a88c9dc84ede2Daniel Dunbar                 site_instance->GetId()));
1401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}
14168d331a78e655d97294e94fcfa63f92cc1f40578Steve Naroff
14268d331a78e655d97294e94fcfa63f92cc1f40578Steve Naroffvoid ShellContentBrowserClient::SiteInstanceDeleting(
1439e5bb85ac899eeab7c21b5ff9030c3da6ff4837bChandler Carruth    content::SiteInstance* site_instance) {
14468d331a78e655d97294e94fcfa63f92cc1f40578Steve Naroff  // If this isn't an extension renderer there's nothing to do.
1451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  const Extension* extension = GetExtension(site_instance);
14668d331a78e655d97294e94fcfa63f92cc1f40578Steve Naroff  if (!extension)
147083abdf67f157e9d2ab5a8c9d5e71240479d3c99Sebastian Redl    return;
14829238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff
1492e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor  ProcessMap::Get(browser_main_parts_->browser_context())
1501b63e4f732dbc73d90abf886b4d21f8e3a165f6dChris Lattner      ->Remove(extension->id(),
1511b63e4f732dbc73d90abf886b4d21f8e3a165f6dChris Lattner               site_instance->GetProcess()->GetID(),
1521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump               site_instance->GetId());
1535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  BrowserThread::PostTask(
1555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      BrowserThread::IO,
1561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      FROM_HERE,
1571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      base::Bind(&InfoMap::UnregisterExtensionProcess,
1582e22253e03e175144aeb9d13350a12fd83f858beDouglas Gregor                 browser_main_parts_->extension_system()->info_map(),
1592e22253e03e175144aeb9d13350a12fd83f858beDouglas Gregor                 extension->id(),
1601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                 site_instance->GetProcess()->GetID(),
161e55329d6834647ba0e06f8a319e5d84c77310035Axel Naumann                 site_instance->GetId()));
162e55329d6834647ba0e06f8a319e5d84c77310035Axel Naumann}
163e55329d6834647ba0e06f8a319e5d84c77310035Axel Naumann
164e55329d6834647ba0e06f8a319e5d84c77310035Axel Naumannvoid ShellContentBrowserClient::AppendExtraCommandLineSwitches(
165f44e854ed1e3aa86d2ed6d615ccd109d50ddcff9Douglas Gregor    CommandLine* command_line,
166f44e854ed1e3aa86d2ed6d615ccd109d50ddcff9Douglas Gregor    int child_process_id) {
167ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie  std::string process_type =
1682968442603b029949246467253eeac8139a5b6d8Douglas Gregor      command_line->GetSwitchValueASCII(::switches::kProcessType);
1692968442603b029949246467253eeac8139a5b6d8Douglas Gregor  if (process_type == ::switches::kRendererProcess) {
1702968442603b029949246467253eeac8139a5b6d8Douglas Gregor    // TODO(jamescook): Should we check here if the process is in the extension
1717d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis    // service process map, or can we assume all renderers are extension
1727d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis    // renderers?
1737d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis    command_line->AppendSwitch(switches::kExtensionProcess);
1747d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis  }
1757d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis}
1767d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis
1777d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidisvoid ShellContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
1787d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis    std::vector<std::string>* additional_allowed_schemes) {
1797d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis  ContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
1807d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis      additional_allowed_schemes);
1817d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis  additional_allowed_schemes->push_back(kExtensionScheme);
1827d100872341f233c81e1d7b72b40457e62c36862Argyrios Kyrtzidis}
183c13a34b690d2dc2a03c2fea75a0a1438636c19ceDouglas Gregor
184c13a34b690d2dc2a03c2fea75a0a1438636c19ceDouglas Gregorconst Extension* ShellContentBrowserClient::GetExtension(
185b8db7cd9ac05c522855631670ec2e97255384f5aDouglas Gregor    content::SiteInstance* site_instance) {
1868dfac0baaf0f81d3945bcb306480e358ba8d1f08John McCall  ExtensionRegistry* registry =
187b514c792821a8f053027d88444e13bfaa8efef76Douglas Gregor      ExtensionRegistry::Get(site_instance->GetBrowserContext());
188b514c792821a8f053027d88444e13bfaa8efef76Douglas Gregor  return registry->enabled_extensions().GetExtensionOrAppByURL(
189b514c792821a8f053027d88444e13bfaa8efef76Douglas Gregor      site_instance->GetSiteURL());
190b514c792821a8f053027d88444e13bfaa8efef76Douglas Gregor}
191b514c792821a8f053027d88444e13bfaa8efef76Douglas Gregor
192b514c792821a8f053027d88444e13bfaa8efef76Douglas Gregor}  // namespace extensions
193b514c792821a8f053027d88444e13bfaa8efef76Douglas Gregor