shell_content_browser_client.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "extensions/shell/browser/shell_content_browser_client.h"
  5. #include <stddef.h>
  6. #include <utility>
  7. #include "base/command_line.h"
  8. #include "components/nacl/common/buildflags.h"
  9. #include "content/public/browser/browser_main_runner.h"
  10. #include "content/public/browser/browser_task_traits.h"
  11. #include "content/public/browser/browser_thread.h"
  12. #include "content/public/browser/render_frame_host.h"
  13. #include "content/public/browser/render_process_host.h"
  14. #include "content/public/browser/site_instance.h"
  15. #include "content/public/browser/storage_partition.h"
  16. #include "content/public/browser/web_contents.h"
  17. #include "content/public/common/content_descriptors.h"
  18. #include "content/public/common/content_switches.h"
  19. #include "content/public/common/url_constants.h"
  20. #include "content/public/common/user_agent.h"
  21. #include "content/shell/browser/shell_browser_context.h"
  22. #include "content/shell/browser/shell_devtools_manager_delegate.h"
  23. #include "extensions/browser/api/messaging/messaging_api_message_filter.h"
  24. #include "extensions/browser/api/web_request/web_request_api.h"
  25. #include "extensions/browser/event_router.h"
  26. #include "extensions/browser/extension_message_filter.h"
  27. #include "extensions/browser/extension_navigation_throttle.h"
  28. #include "extensions/browser/extension_navigation_ui_data.h"
  29. #include "extensions/browser/extension_protocols.h"
  30. #include "extensions/browser/extension_registry.h"
  31. #include "extensions/browser/extension_web_contents_observer.h"
  32. #include "extensions/browser/guest_view/extensions_guest_view.h"
  33. #include "extensions/browser/guest_view/web_view/web_view_guest.h"
  34. #include "extensions/browser/process_map.h"
  35. #include "extensions/browser/url_loader_factory_manager.h"
  36. #include "extensions/common/constants.h"
  37. #include "extensions/common/extension.h"
  38. #include "extensions/common/switches.h"
  39. #include "extensions/shell/browser/shell_browser_context.h"
  40. #include "extensions/shell/browser/shell_browser_main_parts.h"
  41. #include "extensions/shell/browser/shell_extension_system.h"
  42. #include "extensions/shell/browser/shell_navigation_ui_data.h"
  43. #include "extensions/shell/browser/shell_speech_recognition_manager_delegate.h"
  44. #include "extensions/shell/common/version.h" // Generated file.
  45. #include "services/metrics/public/cpp/ukm_source_id.h"
  46. #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
  47. #include "url/gurl.h"
  48. #if BUILDFLAG(ENABLE_NACL)
  49. #include "components/nacl/browser/nacl_browser.h"
  50. #include "components/nacl/browser/nacl_host_message_filter.h"
  51. #include "components/nacl/browser/nacl_process_host.h"
  52. #include "components/nacl/common/nacl_process_type.h" // nogncheck
  53. #include "components/nacl/common/nacl_switches.h" // nogncheck
  54. #include "content/public/browser/browser_child_process_host.h"
  55. #include "content/public/browser/child_process_data.h"
  56. #endif
  57. using base::CommandLine;
  58. using content::BrowserContext;
  59. namespace extensions {
  60. namespace {
  61. ShellContentBrowserClient* g_instance = nullptr;
  62. } // namespace
  63. ShellContentBrowserClient::ShellContentBrowserClient(
  64. ShellBrowserMainDelegate* browser_main_delegate)
  65. : browser_main_parts_(nullptr),
  66. browser_main_delegate_(browser_main_delegate) {
  67. DCHECK(!g_instance);
  68. g_instance = this;
  69. }
  70. ShellContentBrowserClient::~ShellContentBrowserClient() {
  71. g_instance = nullptr;
  72. }
  73. // static
  74. ShellContentBrowserClient* ShellContentBrowserClient::Get() {
  75. return g_instance;
  76. }
  77. content::BrowserContext* ShellContentBrowserClient::GetBrowserContext() {
  78. return browser_main_parts_->browser_context();
  79. }
  80. std::unique_ptr<content::BrowserMainParts>
  81. ShellContentBrowserClient::CreateBrowserMainParts(bool is_integration_test) {
  82. auto browser_main_parts =
  83. CreateShellBrowserMainParts(browser_main_delegate_, is_integration_test);
  84. browser_main_parts_ = browser_main_parts.get();
  85. return browser_main_parts;
  86. }
  87. void ShellContentBrowserClient::RenderProcessWillLaunch(
  88. content::RenderProcessHost* host) {
  89. int render_process_id = host->GetID();
  90. BrowserContext* browser_context = browser_main_parts_->browser_context();
  91. host->AddFilter(
  92. new ExtensionMessageFilter(render_process_id, browser_context));
  93. host->AddFilter(
  94. new MessagingAPIMessageFilter(render_process_id, browser_context));
  95. // PluginInfoMessageFilter is not required because app_shell does not have
  96. // the concept of disabled plugins.
  97. #if BUILDFLAG(ENABLE_NACL)
  98. host->AddFilter(new nacl::NaClHostMessageFilter(
  99. render_process_id, browser_context->IsOffTheRecord(),
  100. browser_context->GetPath()));
  101. #endif
  102. }
  103. bool ShellContentBrowserClient::ShouldUseProcessPerSite(
  104. content::BrowserContext* browser_context,
  105. const GURL& site_url) {
  106. // This ensures that all render views created for a single app will use the
  107. // same render process (see content::SiteInstance::GetProcess). Otherwise the
  108. // default behavior of ContentBrowserClient will lead to separate render
  109. // processes for the background page and each app window view.
  110. return true;
  111. }
  112. bool ShellContentBrowserClient::IsHandledURL(const GURL& url) {
  113. if (!url.is_valid())
  114. return false;
  115. // Keep in sync with ProtocolHandlers added in
  116. // ShellBrowserContext::CreateRequestContext() and in
  117. // content::ShellURLRequestContextGetter::GetURLRequestContext().
  118. static const char* const kProtocolList[] = {
  119. url::kBlobScheme,
  120. content::kChromeDevToolsScheme,
  121. content::kChromeUIScheme,
  122. url::kDataScheme,
  123. url::kFileScheme,
  124. url::kFileSystemScheme,
  125. kExtensionScheme,
  126. };
  127. for (const char* scheme : kProtocolList) {
  128. if (url.SchemeIs(scheme))
  129. return true;
  130. }
  131. return false;
  132. }
  133. void ShellContentBrowserClient::SiteInstanceGotProcess(
  134. content::SiteInstance* site_instance) {
  135. // If this isn't an extension renderer there's nothing to do.
  136. const Extension* extension = GetExtension(site_instance);
  137. if (!extension)
  138. return;
  139. ProcessMap::Get(browser_main_parts_->browser_context())
  140. ->Insert(extension->id(),
  141. site_instance->GetProcess()->GetID(),
  142. site_instance->GetId());
  143. }
  144. void ShellContentBrowserClient::SiteInstanceDeleting(
  145. content::SiteInstance* site_instance) {
  146. // Don't do anything if we're shutting down.
  147. if (content::BrowserMainRunner::ExitedMainMessageLoop())
  148. return;
  149. // If this isn't an extension renderer there's nothing to do.
  150. const Extension* extension = GetExtension(site_instance);
  151. if (!extension)
  152. return;
  153. ProcessMap::Get(browser_main_parts_->browser_context())
  154. ->Remove(extension->id(),
  155. site_instance->GetProcess()->GetID(),
  156. site_instance->GetId());
  157. }
  158. void ShellContentBrowserClient::AppendExtraCommandLineSwitches(
  159. base::CommandLine* command_line,
  160. int child_process_id) {
  161. std::string process_type =
  162. command_line->GetSwitchValueASCII(::switches::kProcessType);
  163. if (process_type == ::switches::kRendererProcess)
  164. AppendRendererSwitches(command_line);
  165. }
  166. content::SpeechRecognitionManagerDelegate*
  167. ShellContentBrowserClient::CreateSpeechRecognitionManagerDelegate() {
  168. return new speech::ShellSpeechRecognitionManagerDelegate();
  169. }
  170. content::BrowserPpapiHost*
  171. ShellContentBrowserClient::GetExternalBrowserPpapiHost(int plugin_process_id) {
  172. #if BUILDFLAG(ENABLE_NACL)
  173. content::BrowserChildProcessHostIterator iter(PROCESS_TYPE_NACL_LOADER);
  174. while (!iter.Done()) {
  175. nacl::NaClProcessHost* host = static_cast<nacl::NaClProcessHost*>(
  176. iter.GetDelegate());
  177. if (host->process() &&
  178. host->process()->GetData().id == plugin_process_id) {
  179. // Found the plugin.
  180. return host->browser_ppapi_host();
  181. }
  182. ++iter;
  183. }
  184. #endif
  185. return nullptr;
  186. }
  187. void ShellContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
  188. std::vector<std::string>* additional_allowed_schemes) {
  189. ContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
  190. additional_allowed_schemes);
  191. additional_allowed_schemes->push_back(kExtensionScheme);
  192. }
  193. std::unique_ptr<content::DevToolsManagerDelegate>
  194. ShellContentBrowserClient::CreateDevToolsManagerDelegate() {
  195. return std::make_unique<content::ShellDevToolsManagerDelegate>(
  196. GetBrowserContext());
  197. }
  198. void ShellContentBrowserClient::ExposeInterfacesToRenderer(
  199. service_manager::BinderRegistry* registry,
  200. blink::AssociatedInterfaceRegistry* associated_registry,
  201. content::RenderProcessHost* render_process_host) {
  202. associated_registry->AddInterface<mojom::EventRouter>(base::BindRepeating(
  203. &EventRouter::BindForRenderer, render_process_host->GetID()));
  204. associated_registry->AddInterface<guest_view::mojom::GuestViewHost>(
  205. base::BindRepeating(&ExtensionsGuestView::CreateForComponents,
  206. render_process_host->GetID()));
  207. associated_registry->AddInterface<extensions::mojom::GuestView>(
  208. base::BindRepeating(&ExtensionsGuestView::CreateForExtensions,
  209. render_process_host->GetID()));
  210. }
  211. void ShellContentBrowserClient::
  212. RegisterAssociatedInterfaceBindersForRenderFrameHost(
  213. content::RenderFrameHost& render_frame_host,
  214. blink::AssociatedInterfaceRegistry& associated_registry) {
  215. associated_registry.AddInterface<extensions::mojom::LocalFrameHost>(
  216. base::BindRepeating(
  217. [](content::RenderFrameHost* render_frame_host,
  218. mojo::PendingAssociatedReceiver<extensions::mojom::LocalFrameHost>
  219. receiver) {
  220. ExtensionWebContentsObserver::BindLocalFrameHost(
  221. std::move(receiver), render_frame_host);
  222. },
  223. &render_frame_host));
  224. }
  225. std::vector<std::unique_ptr<content::NavigationThrottle>>
  226. ShellContentBrowserClient::CreateThrottlesForNavigation(
  227. content::NavigationHandle* navigation_handle) {
  228. std::vector<std::unique_ptr<content::NavigationThrottle>> throttles;
  229. throttles.push_back(
  230. std::make_unique<ExtensionNavigationThrottle>(navigation_handle));
  231. return throttles;
  232. }
  233. std::unique_ptr<content::NavigationUIData>
  234. ShellContentBrowserClient::GetNavigationUIData(
  235. content::NavigationHandle* navigation_handle) {
  236. return std::make_unique<ShellNavigationUIData>(navigation_handle);
  237. }
  238. void ShellContentBrowserClient::RegisterNonNetworkNavigationURLLoaderFactories(
  239. int frame_tree_node_id,
  240. ukm::SourceIdObj ukm_source_id,
  241. NonNetworkURLLoaderFactoryMap* factories) {
  242. DCHECK(factories);
  243. content::WebContents* web_contents =
  244. content::WebContents::FromFrameTreeNodeId(frame_tree_node_id);
  245. factories->emplace(
  246. extensions::kExtensionScheme,
  247. extensions::CreateExtensionNavigationURLLoaderFactory(
  248. web_contents->GetBrowserContext(), ukm_source_id,
  249. !!extensions::WebViewGuest::FromWebContents(web_contents)));
  250. }
  251. void ShellContentBrowserClient::
  252. RegisterNonNetworkWorkerMainResourceURLLoaderFactories(
  253. content::BrowserContext* browser_context,
  254. NonNetworkURLLoaderFactoryMap* factories) {
  255. DCHECK(browser_context);
  256. DCHECK(factories);
  257. factories->emplace(
  258. extensions::kExtensionScheme,
  259. extensions::CreateExtensionWorkerMainResourceURLLoaderFactory(
  260. browser_context));
  261. }
  262. void ShellContentBrowserClient::
  263. RegisterNonNetworkServiceWorkerUpdateURLLoaderFactories(
  264. content::BrowserContext* browser_context,
  265. NonNetworkURLLoaderFactoryMap* factories) {
  266. DCHECK(browser_context);
  267. DCHECK(factories);
  268. factories->emplace(
  269. extensions::kExtensionScheme,
  270. extensions::CreateExtensionServiceWorkerScriptURLLoaderFactory(
  271. browser_context));
  272. }
  273. void ShellContentBrowserClient::RegisterNonNetworkSubresourceURLLoaderFactories(
  274. int render_process_id,
  275. int render_frame_id,
  276. const absl::optional<url::Origin>& request_initiator_origin,
  277. NonNetworkURLLoaderFactoryMap* factories) {
  278. DCHECK(factories);
  279. factories->emplace(extensions::kExtensionScheme,
  280. extensions::CreateExtensionURLLoaderFactory(
  281. render_process_id, render_frame_id));
  282. }
  283. bool ShellContentBrowserClient::WillCreateURLLoaderFactory(
  284. content::BrowserContext* browser_context,
  285. content::RenderFrameHost* frame,
  286. int render_process_id,
  287. URLLoaderFactoryType type,
  288. const url::Origin& request_initiator,
  289. absl::optional<int64_t> navigation_id,
  290. ukm::SourceIdObj ukm_source_id,
  291. mojo::PendingReceiver<network::mojom::URLLoaderFactory>* factory_receiver,
  292. mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>*
  293. header_client,
  294. bool* bypass_redirect_checks,
  295. bool* disable_secure_dns,
  296. network::mojom::URLLoaderFactoryOverridePtr* factory_override) {
  297. auto* web_request_api =
  298. extensions::BrowserContextKeyedAPIFactory<extensions::WebRequestAPI>::Get(
  299. browser_context);
  300. bool use_proxy = web_request_api->MaybeProxyURLLoaderFactory(
  301. browser_context, frame, render_process_id, type, std::move(navigation_id),
  302. ukm_source_id, factory_receiver, header_client);
  303. if (bypass_redirect_checks)
  304. *bypass_redirect_checks = use_proxy;
  305. return use_proxy;
  306. }
  307. bool ShellContentBrowserClient::HandleExternalProtocol(
  308. const GURL& url,
  309. content::WebContents::Getter web_contents_getter,
  310. int frame_tree_node_id,
  311. content::NavigationUIData* navigation_data,
  312. bool is_primary_main_frame,
  313. bool is_in_fenced_frame_tree,
  314. network::mojom::WebSandboxFlags sandbox_flags,
  315. ui::PageTransition page_transition,
  316. bool has_user_gesture,
  317. const absl::optional<url::Origin>& initiating_origin,
  318. content::RenderFrameHost* initiator_document,
  319. mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory) {
  320. return false;
  321. }
  322. void ShellContentBrowserClient::OverrideURLLoaderFactoryParams(
  323. content::BrowserContext* browser_context,
  324. const url::Origin& origin,
  325. bool is_for_isolated_world,
  326. network::mojom::URLLoaderFactoryParams* factory_params) {
  327. URLLoaderFactoryManager::OverrideURLLoaderFactoryParams(
  328. browser_context, origin, is_for_isolated_world, factory_params);
  329. }
  330. base::FilePath
  331. ShellContentBrowserClient::GetSandboxedStorageServiceDataDirectory() {
  332. return GetBrowserContext()->GetPath();
  333. }
  334. std::string ShellContentBrowserClient::GetUserAgent() {
  335. // Must contain a user agent string for version sniffing. For example,
  336. // pluginless WebRTC Hangouts checks the Chrome version number.
  337. return content::BuildUserAgentFromProduct("Chrome/" PRODUCT_VERSION);
  338. }
  339. std::unique_ptr<ShellBrowserMainParts>
  340. ShellContentBrowserClient::CreateShellBrowserMainParts(
  341. ShellBrowserMainDelegate* browser_main_delegate,
  342. bool is_integration_test) {
  343. return std::make_unique<ShellBrowserMainParts>(browser_main_delegate,
  344. is_integration_test);
  345. }
  346. void ShellContentBrowserClient::AppendRendererSwitches(
  347. base::CommandLine* command_line) {
  348. static const char* const kSwitchNames[] = {
  349. switches::kAllowlistedExtensionID,
  350. switches::kDEPRECATED_AllowlistedExtensionID,
  351. // TODO(jamescook): Should we check here if the process is in the
  352. // extension service process map, or can we assume all renderers are
  353. // extension renderers?
  354. switches::kExtensionProcess,
  355. };
  356. command_line->CopySwitchesFrom(*base::CommandLine::ForCurrentProcess(),
  357. kSwitchNames, std::size(kSwitchNames));
  358. #if BUILDFLAG(ENABLE_NACL)
  359. static const char* const kNaclSwitchNames[] = {
  360. ::switches::kEnableNaClDebug,
  361. };
  362. command_line->CopySwitchesFrom(*base::CommandLine::ForCurrentProcess(),
  363. kNaclSwitchNames, std::size(kNaclSwitchNames));
  364. #endif // BUILDFLAG(ENABLE_NACL)
  365. }
  366. const Extension* ShellContentBrowserClient::GetExtension(
  367. content::SiteInstance* site_instance) {
  368. ExtensionRegistry* registry =
  369. ExtensionRegistry::Get(site_instance->GetBrowserContext());
  370. return registry->enabled_extensions().GetExtensionOrAppByURL(
  371. site_instance->GetSiteURL());
  372. }
  373. } // namespace extensions