electron_browser_client.cc 61 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685
  1. // Copyright (c) 2013 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include "shell/browser/electron_browser_client.h"
  5. #if defined(OS_WIN)
  6. #include <shlobj.h>
  7. #endif
  8. #include <memory>
  9. #include <utility>
  10. #include "base/base_switches.h"
  11. #include "base/command_line.h"
  12. #include "base/environment.h"
  13. #include "base/files/file_util.h"
  14. #include "base/json/json_reader.h"
  15. #include "base/lazy_instance.h"
  16. #include "base/no_destructor.h"
  17. #include "base/path_service.h"
  18. #include "base/stl_util.h"
  19. #include "base/strings/string_number_conversions.h"
  20. #include "base/strings/string_util.h"
  21. #include "base/strings/utf_string_conversions.h"
  22. #include "base/task/post_task.h"
  23. #include "chrome/browser/browser_process.h"
  24. #include "chrome/common/chrome_paths.h"
  25. #include "chrome/common/chrome_version.h"
  26. #include "components/net_log/chrome_net_log.h"
  27. #include "components/network_hints/common/network_hints.mojom.h"
  28. #include "content/public/browser/browser_main_runner.h"
  29. #include "content/public/browser/browser_ppapi_host.h"
  30. #include "content/public/browser/browser_task_traits.h"
  31. #include "content/public/browser/client_certificate_delegate.h"
  32. #include "content/public/browser/login_delegate.h"
  33. #include "content/public/browser/overlay_window.h"
  34. #include "content/public/browser/render_frame_host.h"
  35. #include "content/public/browser/render_process_host.h"
  36. #include "content/public/browser/render_view_host.h"
  37. #include "content/public/browser/site_instance.h"
  38. #include "content/public/browser/tts_controller.h"
  39. #include "content/public/browser/tts_platform.h"
  40. #include "content/public/common/content_descriptors.h"
  41. #include "content/public/common/content_paths.h"
  42. #include "content/public/common/content_switches.h"
  43. #include "content/public/common/service_names.mojom.h"
  44. #include "content/public/common/url_constants.h"
  45. #include "content/public/common/web_preferences.h"
  46. #include "electron/buildflags/buildflags.h"
  47. #include "electron/grit/electron_resources.h"
  48. #include "extensions/browser/extension_navigation_ui_data.h"
  49. #include "extensions/browser/extension_protocols.h"
  50. #include "extensions/common/constants.h"
  51. #include "extensions/common/switches.h"
  52. #include "mojo/public/cpp/bindings/binder_map.h"
  53. #include "net/base/escape.h"
  54. #include "net/ssl/ssl_cert_request_info.h"
  55. #include "ppapi/buildflags/buildflags.h"
  56. #include "ppapi/host/ppapi_host.h"
  57. #include "printing/buildflags/buildflags.h"
  58. #include "services/device/public/cpp/geolocation/location_provider.h"
  59. #include "services/network/public/cpp/features.h"
  60. #include "services/network/public/cpp/resource_request_body.h"
  61. #include "shell/app/manifests.h"
  62. #include "shell/browser/api/electron_api_app.h"
  63. #include "shell/browser/api/electron_api_crash_reporter.h"
  64. #include "shell/browser/api/electron_api_protocol.h"
  65. #include "shell/browser/api/electron_api_session.h"
  66. #include "shell/browser/api/electron_api_web_contents.h"
  67. #include "shell/browser/api/electron_api_web_request.h"
  68. #include "shell/browser/child_web_contents_tracker.h"
  69. #include "shell/browser/electron_autofill_driver_factory.h"
  70. #include "shell/browser/electron_browser_context.h"
  71. #include "shell/browser/electron_browser_main_parts.h"
  72. #include "shell/browser/electron_navigation_throttle.h"
  73. #include "shell/browser/electron_quota_permission_context.h"
  74. #include "shell/browser/electron_speech_recognition_manager_delegate.h"
  75. #include "shell/browser/font_defaults.h"
  76. #include "shell/browser/javascript_environment.h"
  77. #include "shell/browser/media/media_capture_devices_dispatcher.h"
  78. #include "shell/browser/native_window.h"
  79. #include "shell/browser/net/network_context_service.h"
  80. #include "shell/browser/net/network_context_service_factory.h"
  81. #include "shell/browser/net/proxying_url_loader_factory.h"
  82. #include "shell/browser/net/proxying_websocket.h"
  83. #include "shell/browser/net/system_network_context_manager.h"
  84. #include "shell/browser/network_hints_handler_impl.h"
  85. #include "shell/browser/notifications/notification_presenter.h"
  86. #include "shell/browser/notifications/platform_notification_service.h"
  87. #include "shell/browser/protocol_registry.h"
  88. #include "shell/browser/session_preferences.h"
  89. #include "shell/browser/ui/devtools_manager_delegate.h"
  90. #include "shell/browser/web_contents_permission_helper.h"
  91. #include "shell/browser/web_contents_preferences.h"
  92. #include "shell/browser/window_list.h"
  93. #include "shell/common/api/api.mojom.h"
  94. #include "shell/common/application_info.h"
  95. #include "shell/common/electron_paths.h"
  96. #include "shell/common/options_switches.h"
  97. #include "shell/common/platform_util.h"
  98. #include "third_party/blink/public/common/loader/url_loader_throttle.h"
  99. #include "ui/base/resource/resource_bundle.h"
  100. #include "ui/native_theme/native_theme.h"
  101. #include "v8/include/v8.h"
  102. #if defined(OS_WIN)
  103. #include "sandbox/win/src/sandbox_policy.h"
  104. #endif
  105. #if defined(USE_NSS_CERTS)
  106. #include "net/ssl/client_cert_store_nss.h"
  107. #elif defined(OS_WIN)
  108. #include "net/ssl/client_cert_store_win.h"
  109. #elif defined(OS_MACOSX)
  110. #include "net/ssl/client_cert_store_mac.h"
  111. #elif defined(USE_OPENSSL)
  112. #include "net/ssl/client_cert_store.h"
  113. #endif
  114. #if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
  115. #include "chrome/browser/spellchecker/spell_check_host_chrome_impl.h" // nogncheck
  116. #include "components/spellcheck/common/spellcheck.mojom.h" // nogncheck
  117. #endif
  118. #if BUILDFLAG(ENABLE_PEPPER_FLASH)
  119. #include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h" // nogncheck
  120. #endif // BUILDFLAG(ENABLE_PEPPER_FLASH)
  121. #if BUILDFLAG(OVERRIDE_LOCATION_PROVIDER)
  122. #include "shell/browser/fake_location_provider.h"
  123. #endif // BUILDFLAG(OVERRIDE_LOCATION_PROVIDER)
  124. #if BUILDFLAG(ENABLE_PRINTING)
  125. #include "chrome/browser/printing/printing_message_filter.h"
  126. #endif // BUILDFLAG(ENABLE_PRINTING)
  127. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  128. #include "chrome/common/webui_url_constants.h"
  129. #include "content/public/browser/child_process_security_policy.h"
  130. #include "content/public/browser/file_url_loader.h"
  131. #include "content/public/browser/web_ui_url_loader_factory.h"
  132. #include "extensions/browser/api/mime_handler_private/mime_handler_private.h"
  133. #include "extensions/browser/extension_host.h"
  134. #include "extensions/browser/extension_message_filter.h"
  135. #include "extensions/browser/extension_navigation_throttle.h"
  136. #include "extensions/browser/extension_registry.h"
  137. #include "extensions/browser/extensions_browser_client.h"
  138. #include "extensions/browser/guest_view/extensions_guest_view_message_filter.h"
  139. #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
  140. #include "extensions/browser/info_map.h"
  141. #include "extensions/browser/process_manager.h"
  142. #include "extensions/browser/process_map.h"
  143. #include "extensions/common/api/mime_handler.mojom.h"
  144. #include "extensions/common/extension.h"
  145. #include "shell/browser/extensions/electron_extension_message_filter.h"
  146. #include "shell/browser/extensions/electron_extension_system.h"
  147. #include "shell/browser/extensions/electron_extension_web_contents_observer.h"
  148. #endif
  149. #if BUILDFLAG(ENABLE_PLUGINS)
  150. #include "chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.h" // nogncheck
  151. #include "shell/browser/plugins/plugin_utils.h"
  152. #endif
  153. #if defined(OS_MACOSX)
  154. #include "content/common/mac_helpers.h"
  155. #include "content/public/common/child_process_host.h"
  156. #endif
  157. #if defined(OS_LINUX) && !defined(MAS_BUILD)
  158. #include "base/debug/leak_annotations.h"
  159. #include "components/crash/content/browser/crash_handler_host_linux.h"
  160. #include "components/crash/core/app/breakpad_linux.h" // nogncheck
  161. #include "components/crash/core/app/crash_switches.h" // nogncheck
  162. #include "components/crash/core/app/crashpad.h" // nogncheck
  163. #endif
  164. using content::BrowserThread;
  165. namespace electron {
  166. namespace {
  167. // Next navigation should not restart renderer process.
  168. bool g_suppress_renderer_process_restart = false;
  169. bool IsSameWebSite(content::BrowserContext* browser_context,
  170. content::SiteInstance* site_instance,
  171. const GURL& dest_url) {
  172. return site_instance->IsSameSiteWithURL(dest_url) ||
  173. // `IsSameSiteWithURL` doesn't seem to work for some URIs such as
  174. // `file:`, handle these scenarios by comparing only the site as
  175. // defined by `GetSiteForURL`.
  176. (content::SiteInstance::GetSiteForURL(browser_context, dest_url) ==
  177. site_instance->GetSiteURL());
  178. }
  179. ElectronBrowserClient* g_browser_client = nullptr;
  180. base::LazyInstance<std::string>::DestructorAtExit
  181. g_io_thread_application_locale = LAZY_INSTANCE_INITIALIZER;
  182. base::NoDestructor<std::string> g_application_locale;
  183. void SetApplicationLocaleOnIOThread(const std::string& locale) {
  184. DCHECK_CURRENTLY_ON(BrowserThread::IO);
  185. g_io_thread_application_locale.Get() = locale;
  186. }
  187. void BindNetworkHintsHandler(
  188. content::RenderFrameHost* frame_host,
  189. mojo::PendingReceiver<network_hints::mojom::NetworkHintsHandler> receiver) {
  190. NetworkHintsHandlerImpl::Create(frame_host, std::move(receiver));
  191. }
  192. #if defined(OS_WIN)
  193. const base::FilePath::StringPieceType kPathDelimiter = FILE_PATH_LITERAL(";");
  194. #else
  195. const base::FilePath::StringPieceType kPathDelimiter = FILE_PATH_LITERAL(":");
  196. #endif
  197. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  198. // Used by the GetPrivilegeRequiredByUrl() and GetProcessPrivilege() functions
  199. // below. Extension, and isolated apps require different privileges to be
  200. // granted to their RenderProcessHosts. This classification allows us to make
  201. // sure URLs are served by hosts with the right set of privileges.
  202. enum RenderProcessHostPrivilege {
  203. PRIV_NORMAL,
  204. PRIV_HOSTED,
  205. PRIV_ISOLATED,
  206. PRIV_EXTENSION,
  207. };
  208. RenderProcessHostPrivilege GetPrivilegeRequiredByUrl(
  209. const GURL& url,
  210. extensions::ExtensionRegistry* registry) {
  211. // Default to a normal renderer cause it is lower privileged. This should only
  212. // occur if the URL on a site instance is either malformed, or uninitialized.
  213. // If it is malformed, then there is no need for better privileges anyways.
  214. // If it is uninitialized, but eventually settles on being an a scheme other
  215. // than normal webrenderer, the navigation logic will correct us out of band
  216. // anyways.
  217. if (!url.is_valid())
  218. return PRIV_NORMAL;
  219. if (!url.SchemeIs(extensions::kExtensionScheme))
  220. return PRIV_NORMAL;
  221. return PRIV_EXTENSION;
  222. }
  223. RenderProcessHostPrivilege GetProcessPrivilege(
  224. content::RenderProcessHost* process_host,
  225. extensions::ProcessMap* process_map,
  226. extensions::ExtensionRegistry* registry) {
  227. std::set<std::string> extension_ids =
  228. process_map->GetExtensionsInProcess(process_host->GetID());
  229. if (extension_ids.empty())
  230. return PRIV_NORMAL;
  231. return PRIV_EXTENSION;
  232. }
  233. const extensions::Extension* GetEnabledExtensionFromEffectiveURL(
  234. content::BrowserContext* context,
  235. const GURL& effective_url) {
  236. if (!effective_url.SchemeIs(extensions::kExtensionScheme))
  237. return nullptr;
  238. extensions::ExtensionRegistry* registry =
  239. extensions::ExtensionRegistry::Get(context);
  240. if (!registry)
  241. return nullptr;
  242. return registry->enabled_extensions().GetByID(effective_url.host());
  243. }
  244. #endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  245. #if defined(OS_LINUX)
  246. breakpad::CrashHandlerHostLinux* CreateCrashHandlerHost(
  247. const std::string& process_type) {
  248. base::FilePath dumps_path;
  249. base::PathService::Get(electron::DIR_CRASH_DUMPS, &dumps_path);
  250. {
  251. ANNOTATE_SCOPED_MEMORY_LEAK;
  252. breakpad::CrashHandlerHostLinux* crash_handler =
  253. new breakpad::CrashHandlerHostLinux(process_type, dumps_path, true);
  254. crash_handler->StartUploaderThread();
  255. return crash_handler;
  256. }
  257. }
  258. int GetCrashSignalFD(const base::CommandLine& command_line) {
  259. // Extensions have the same process type as renderers.
  260. if (command_line.HasSwitch(extensions::switches::kExtensionProcess)) {
  261. static breakpad::CrashHandlerHostLinux* crash_handler = nullptr;
  262. if (!crash_handler)
  263. crash_handler = CreateCrashHandlerHost("extension");
  264. return crash_handler->GetDeathSignalSocket();
  265. }
  266. std::string process_type =
  267. command_line.GetSwitchValueASCII(::switches::kProcessType);
  268. if (process_type == ::switches::kRendererProcess) {
  269. static breakpad::CrashHandlerHostLinux* crash_handler = nullptr;
  270. if (!crash_handler)
  271. crash_handler = CreateCrashHandlerHost(process_type);
  272. return crash_handler->GetDeathSignalSocket();
  273. }
  274. if (process_type == ::switches::kPpapiPluginProcess) {
  275. static breakpad::CrashHandlerHostLinux* crash_handler = nullptr;
  276. if (!crash_handler)
  277. crash_handler = CreateCrashHandlerHost(process_type);
  278. return crash_handler->GetDeathSignalSocket();
  279. }
  280. if (process_type == ::switches::kGpuProcess) {
  281. static breakpad::CrashHandlerHostLinux* crash_handler = nullptr;
  282. if (!crash_handler)
  283. crash_handler = CreateCrashHandlerHost(process_type);
  284. return crash_handler->GetDeathSignalSocket();
  285. }
  286. if (process_type == ::switches::kUtilityProcess) {
  287. static breakpad::CrashHandlerHostLinux* crash_handler = nullptr;
  288. if (!crash_handler)
  289. crash_handler = CreateCrashHandlerHost(process_type);
  290. return crash_handler->GetDeathSignalSocket();
  291. }
  292. return -1;
  293. }
  294. #endif // defined(OS_LINUX)
  295. } // namespace
  296. // static
  297. void ElectronBrowserClient::SuppressRendererProcessRestartForOnce() {
  298. g_suppress_renderer_process_restart = true;
  299. }
  300. ElectronBrowserClient* ElectronBrowserClient::Get() {
  301. return g_browser_client;
  302. }
  303. // static
  304. void ElectronBrowserClient::SetApplicationLocale(const std::string& locale) {
  305. if (!BrowserThread::IsThreadInitialized(BrowserThread::IO) ||
  306. !base::PostTask(
  307. FROM_HERE, {BrowserThread::IO},
  308. base::BindOnce(&SetApplicationLocaleOnIOThread, locale))) {
  309. g_io_thread_application_locale.Get() = locale;
  310. }
  311. *g_application_locale = locale;
  312. }
  313. ElectronBrowserClient::ElectronBrowserClient() {
  314. DCHECK(!g_browser_client);
  315. g_browser_client = this;
  316. }
  317. ElectronBrowserClient::~ElectronBrowserClient() {
  318. DCHECK(g_browser_client);
  319. g_browser_client = nullptr;
  320. }
  321. content::WebContents* ElectronBrowserClient::GetWebContentsFromProcessID(
  322. int process_id) {
  323. // If the process is a pending process, we should use the web contents
  324. // for the frame host passed into RegisterPendingProcess.
  325. const auto iter = pending_processes_.find(process_id);
  326. if (iter != std::end(pending_processes_))
  327. return iter->second;
  328. // Certain render process will be created with no associated render view,
  329. // for example: ServiceWorker.
  330. return WebContentsPreferences::GetWebContentsFromProcessID(process_id);
  331. }
  332. bool ElectronBrowserClient::ShouldForceNewSiteInstance(
  333. content::RenderFrameHost* current_rfh,
  334. content::RenderFrameHost* speculative_rfh,
  335. content::BrowserContext* browser_context,
  336. const GURL& url,
  337. bool has_response_started) const {
  338. if (url.SchemeIs(url::kJavaScriptScheme))
  339. // "javacript:" scheme should always use same SiteInstance
  340. return false;
  341. if (url.SchemeIs(extensions::kExtensionScheme))
  342. return false;
  343. content::SiteInstance* current_instance = current_rfh->GetSiteInstance();
  344. content::SiteInstance* speculative_instance =
  345. speculative_rfh ? speculative_rfh->GetSiteInstance() : nullptr;
  346. int process_id = current_instance->GetProcess()->GetID();
  347. if (NavigationWasRedirectedCrossSite(browser_context, current_instance,
  348. speculative_instance, url,
  349. has_response_started)) {
  350. // Navigation was redirected. We can't force the current, speculative or a
  351. // new unrelated site instance to be used. Delegate to the content layer.
  352. return false;
  353. } else if (IsRendererSandboxed(process_id)) {
  354. // Renderer is sandboxed, delegate the decision to the content layer for all
  355. // origins.
  356. return false;
  357. } else if (!RendererUsesNativeWindowOpen(process_id)) {
  358. // non-sandboxed renderers without native window.open should always create
  359. // a new SiteInstance
  360. return true;
  361. } else {
  362. auto* web_contents = content::WebContents::FromRenderFrameHost(current_rfh);
  363. if (!ChildWebContentsTracker::FromWebContents(web_contents)) {
  364. // Root WebContents should always create new process to make sure
  365. // native addons are loaded correctly after reload / navigation.
  366. // (Non-root WebContents opened by window.open() should try to
  367. // reuse process to allow synchronous cross-window scripting.)
  368. return true;
  369. }
  370. }
  371. // Create new a SiteInstance if navigating to a different site.
  372. return !IsSameWebSite(browser_context, current_instance, url);
  373. }
  374. bool ElectronBrowserClient::NavigationWasRedirectedCrossSite(
  375. content::BrowserContext* browser_context,
  376. content::SiteInstance* current_instance,
  377. content::SiteInstance* speculative_instance,
  378. const GURL& dest_url,
  379. bool has_response_started) const {
  380. bool navigation_was_redirected = false;
  381. if (has_response_started) {
  382. navigation_was_redirected =
  383. !IsSameWebSite(browser_context, current_instance, dest_url);
  384. } else {
  385. navigation_was_redirected =
  386. speculative_instance &&
  387. !IsSameWebSite(browser_context, speculative_instance, dest_url);
  388. }
  389. return navigation_was_redirected;
  390. }
  391. void ElectronBrowserClient::AddProcessPreferences(
  392. int process_id,
  393. ElectronBrowserClient::ProcessPreferences prefs) {
  394. process_preferences_[process_id] = prefs;
  395. }
  396. void ElectronBrowserClient::RemoveProcessPreferences(int process_id) {
  397. process_preferences_.erase(process_id);
  398. }
  399. bool ElectronBrowserClient::IsProcessObserved(int process_id) const {
  400. return process_preferences_.find(process_id) != process_preferences_.end();
  401. }
  402. bool ElectronBrowserClient::IsRendererSandboxed(int process_id) const {
  403. auto it = process_preferences_.find(process_id);
  404. return it != process_preferences_.end() && it->second.sandbox;
  405. }
  406. bool ElectronBrowserClient::RendererUsesNativeWindowOpen(int process_id) const {
  407. auto it = process_preferences_.find(process_id);
  408. return it != process_preferences_.end() && it->second.native_window_open;
  409. }
  410. bool ElectronBrowserClient::RendererDisablesPopups(int process_id) const {
  411. auto it = process_preferences_.find(process_id);
  412. return it != process_preferences_.end() && it->second.disable_popups;
  413. }
  414. std::string ElectronBrowserClient::GetAffinityPreference(
  415. content::RenderFrameHost* rfh) const {
  416. auto* web_contents = content::WebContents::FromRenderFrameHost(rfh);
  417. auto* web_preferences = WebContentsPreferences::From(web_contents);
  418. std::string affinity;
  419. if (web_preferences &&
  420. web_preferences->GetPreference("affinity", &affinity) &&
  421. !affinity.empty()) {
  422. affinity = base::ToLowerASCII(affinity);
  423. }
  424. return affinity;
  425. }
  426. content::SiteInstance* ElectronBrowserClient::GetSiteInstanceFromAffinity(
  427. content::BrowserContext* browser_context,
  428. const GURL& url,
  429. content::RenderFrameHost* rfh) const {
  430. std::string affinity = GetAffinityPreference(rfh);
  431. if (!affinity.empty()) {
  432. auto iter = site_per_affinities_.find(affinity);
  433. GURL dest_site = content::SiteInstance::GetSiteForURL(browser_context, url);
  434. if (iter != site_per_affinities_.end() &&
  435. IsSameWebSite(browser_context, iter->second, dest_site)) {
  436. return iter->second;
  437. }
  438. }
  439. return nullptr;
  440. }
  441. void ElectronBrowserClient::ConsiderSiteInstanceForAffinity(
  442. content::RenderFrameHost* rfh,
  443. content::SiteInstance* site_instance) {
  444. std::string affinity = GetAffinityPreference(rfh);
  445. if (!affinity.empty()) {
  446. site_per_affinities_[affinity] = site_instance;
  447. }
  448. }
  449. bool ElectronBrowserClient::IsRendererSubFrame(int process_id) const {
  450. return base::Contains(renderer_is_subframe_, process_id);
  451. }
  452. void ElectronBrowserClient::RenderProcessWillLaunch(
  453. content::RenderProcessHost* host) {
  454. // When a render process is crashed, it might be reused.
  455. int process_id = host->GetID();
  456. if (IsProcessObserved(process_id))
  457. return;
  458. auto* browser_context = host->GetBrowserContext();
  459. ALLOW_UNUSED_LOCAL(browser_context);
  460. #if BUILDFLAG(ENABLE_PRINTING)
  461. host->AddFilter(
  462. new printing::PrintingMessageFilter(process_id, browser_context));
  463. #endif
  464. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  465. host->AddFilter(
  466. new extensions::ExtensionMessageFilter(process_id, browser_context));
  467. host->AddFilter(new extensions::ExtensionsGuestViewMessageFilter(
  468. process_id, browser_context));
  469. host->AddFilter(
  470. new ElectronExtensionMessageFilter(process_id, browser_context));
  471. #endif
  472. ProcessPreferences prefs;
  473. auto* web_preferences =
  474. WebContentsPreferences::From(GetWebContentsFromProcessID(process_id));
  475. if (web_preferences) {
  476. prefs.sandbox = web_preferences->IsEnabled(options::kSandbox);
  477. prefs.native_window_open =
  478. web_preferences->IsEnabled(options::kNativeWindowOpen);
  479. prefs.disable_popups = web_preferences->IsEnabled("disablePopups");
  480. prefs.web_security = web_preferences->IsEnabled(options::kWebSecurity,
  481. true /* default value */);
  482. prefs.browser_context = host->GetBrowserContext();
  483. }
  484. AddProcessPreferences(host->GetID(), prefs);
  485. // ensure the ProcessPreferences is removed later
  486. host->AddObserver(this);
  487. }
  488. content::SpeechRecognitionManagerDelegate*
  489. ElectronBrowserClient::CreateSpeechRecognitionManagerDelegate() {
  490. return new ElectronSpeechRecognitionManagerDelegate;
  491. }
  492. content::TtsPlatform* ElectronBrowserClient::GetTtsPlatform() {
  493. return nullptr;
  494. }
  495. void ElectronBrowserClient::OverrideWebkitPrefs(
  496. content::RenderViewHost* host,
  497. content::WebPreferences* prefs) {
  498. prefs->javascript_enabled = true;
  499. prefs->web_security_enabled = true;
  500. prefs->plugins_enabled = true;
  501. prefs->dom_paste_enabled = true;
  502. prefs->allow_scripts_to_close_windows = true;
  503. prefs->javascript_can_access_clipboard = true;
  504. prefs->local_storage_enabled = true;
  505. prefs->databases_enabled = true;
  506. prefs->application_cache_enabled = true;
  507. prefs->allow_universal_access_from_file_urls = true;
  508. prefs->allow_file_access_from_file_urls = true;
  509. prefs->webgl1_enabled = true;
  510. prefs->webgl2_enabled = true;
  511. prefs->allow_running_insecure_content = false;
  512. prefs->default_minimum_page_scale_factor = 1.f;
  513. prefs->default_maximum_page_scale_factor = 1.f;
  514. prefs->navigate_on_drag_drop = false;
  515. #if !BUILDFLAG(ENABLE_PICTURE_IN_PICTURE)
  516. prefs->picture_in_picture_enabled = false;
  517. #endif
  518. ui::NativeTheme* native_theme = ui::NativeTheme::GetInstanceForNativeUi();
  519. prefs->preferred_color_scheme = native_theme->ShouldUseDarkColors()
  520. ? blink::PreferredColorScheme::kDark
  521. : blink::PreferredColorScheme::kLight;
  522. SetFontDefaults(prefs);
  523. // Custom preferences of guest page.
  524. auto* web_contents = content::WebContents::FromRenderViewHost(host);
  525. auto* web_preferences = WebContentsPreferences::From(web_contents);
  526. if (web_preferences)
  527. web_preferences->OverrideWebkitPrefs(prefs);
  528. }
  529. void ElectronBrowserClient::SetCanUseCustomSiteInstance(bool should_disable) {
  530. disable_process_restart_tricks_ = should_disable;
  531. }
  532. bool ElectronBrowserClient::CanUseCustomSiteInstance() {
  533. return disable_process_restart_tricks_;
  534. }
  535. content::ContentBrowserClient::SiteInstanceForNavigationType
  536. ElectronBrowserClient::ShouldOverrideSiteInstanceForNavigation(
  537. content::RenderFrameHost* current_rfh,
  538. content::RenderFrameHost* speculative_rfh,
  539. content::BrowserContext* browser_context,
  540. const GURL& url,
  541. bool has_navigation_started,
  542. bool has_response_started,
  543. content::SiteInstance** affinity_site_instance) const {
  544. if (g_suppress_renderer_process_restart) {
  545. g_suppress_renderer_process_restart = false;
  546. return SiteInstanceForNavigationType::ASK_CHROMIUM;
  547. }
  548. // Do we have an affinity site to manage ?
  549. content::SiteInstance* site_instance_from_affinity =
  550. GetSiteInstanceFromAffinity(browser_context, url, current_rfh);
  551. if (site_instance_from_affinity) {
  552. *affinity_site_instance = site_instance_from_affinity;
  553. return SiteInstanceForNavigationType::FORCE_AFFINITY;
  554. }
  555. if (!ShouldForceNewSiteInstance(current_rfh, speculative_rfh, browser_context,
  556. url, has_response_started)) {
  557. return SiteInstanceForNavigationType::ASK_CHROMIUM;
  558. }
  559. // ShouldOverrideSiteInstanceForNavigation will be called more than once
  560. // during a navigation (currently twice, on request and when it's about
  561. // to commit in the renderer), look at
  562. // RenderFrameHostManager::GetFrameHostForNavigation.
  563. // In the default mode we should reuse the same site instance until the
  564. // request commits otherwise it will get destroyed. Currently there is no
  565. // unique lifetime tracker for a navigation request during site instance
  566. // creation. We check for the state of the request, which should be one of
  567. // (WAITING_FOR_RENDERER_RESPONSE, STARTED, RESPONSE_STARTED, FAILED) along
  568. // with the availability of a speculative render frame host.
  569. if (has_response_started) {
  570. return SiteInstanceForNavigationType::FORCE_CURRENT;
  571. }
  572. if (!has_navigation_started) {
  573. // If the navigation didn't start yet, ignore any candidate site instance.
  574. // If such instance exists, it belongs to a previous navigation still
  575. // taking place. Fixes https://github.com/electron/electron/issues/17576.
  576. return SiteInstanceForNavigationType::FORCE_NEW;
  577. }
  578. return SiteInstanceForNavigationType::FORCE_CANDIDATE_OR_NEW;
  579. }
  580. void ElectronBrowserClient::RegisterPendingSiteInstance(
  581. content::RenderFrameHost* rfh,
  582. content::SiteInstance* pending_site_instance) {
  583. // Do we have an affinity site to manage?
  584. ConsiderSiteInstanceForAffinity(rfh, pending_site_instance);
  585. // Remember the original web contents for the pending renderer process.
  586. auto* web_contents = content::WebContents::FromRenderFrameHost(rfh);
  587. auto* pending_process = pending_site_instance->GetProcess();
  588. pending_processes_[pending_process->GetID()] = web_contents;
  589. if (rfh->GetParent())
  590. renderer_is_subframe_.insert(pending_process->GetID());
  591. else
  592. renderer_is_subframe_.erase(pending_process->GetID());
  593. }
  594. void ElectronBrowserClient::AppendExtraCommandLineSwitches(
  595. base::CommandLine* command_line,
  596. int process_id) {
  597. // Make sure we're about to launch a known executable
  598. {
  599. base::ThreadRestrictions::ScopedAllowIO allow_io;
  600. base::FilePath child_path;
  601. base::FilePath program =
  602. base::MakeAbsoluteFilePath(command_line->GetProgram());
  603. #if defined(OS_MACOSX)
  604. auto renderer_child_path = content::ChildProcessHost::GetChildPath(
  605. content::ChildProcessHost::CHILD_RENDERER);
  606. auto gpu_child_path = content::ChildProcessHost::GetChildPath(
  607. content::ChildProcessHost::CHILD_GPU);
  608. auto plugin_child_path = content::ChildProcessHost::GetChildPath(
  609. content::ChildProcessHost::CHILD_PLUGIN);
  610. if (program != renderer_child_path && program != gpu_child_path &&
  611. program != plugin_child_path) {
  612. child_path = content::ChildProcessHost::GetChildPath(
  613. content::ChildProcessHost::CHILD_NORMAL);
  614. CHECK_EQ(program, child_path)
  615. << "Aborted from launching unexpected helper executable";
  616. }
  617. #else
  618. base::PathService::Get(content::CHILD_PROCESS_EXE, &child_path);
  619. CHECK_EQ(program, child_path);
  620. #endif
  621. }
  622. std::string process_type =
  623. command_line->GetSwitchValueASCII(::switches::kProcessType);
  624. #if defined(OS_LINUX)
  625. bool enable_crash_reporter = false;
  626. enable_crash_reporter = breakpad::IsCrashReporterEnabled();
  627. if (enable_crash_reporter) {
  628. command_line->AppendSwitch(::switches::kEnableCrashReporter);
  629. std::string switch_value;
  630. for (const auto& pair : api::crash_reporter::GetGlobalCrashKeys()) {
  631. if (!switch_value.empty())
  632. switch_value += ",";
  633. switch_value += pair.first;
  634. switch_value += "=";
  635. switch_value += pair.second;
  636. }
  637. command_line->AppendSwitchASCII(switches::kGlobalCrashKeys, switch_value);
  638. }
  639. #endif
  640. if (process_type == ::switches::kUtilityProcess ||
  641. process_type == ::switches::kRendererProcess) {
  642. // Copy following switches to child process.
  643. static const char* const kCommonSwitchNames[] = {
  644. switches::kStandardSchemes, switches::kEnableSandbox,
  645. switches::kSecureSchemes, switches::kBypassCSPSchemes,
  646. switches::kCORSSchemes, switches::kFetchSchemes,
  647. switches::kServiceWorkerSchemes, switches::kEnableApiFilteringLogging,
  648. switches::kStreamingSchemes};
  649. command_line->CopySwitchesFrom(*base::CommandLine::ForCurrentProcess(),
  650. kCommonSwitchNames,
  651. base::size(kCommonSwitchNames));
  652. }
  653. if (process_type == ::switches::kRendererProcess) {
  654. #if defined(OS_WIN)
  655. // Append --app-user-model-id.
  656. PWSTR current_app_id;
  657. if (SUCCEEDED(GetCurrentProcessExplicitAppUserModelID(&current_app_id))) {
  658. command_line->AppendSwitchNative(switches::kAppUserModelId,
  659. current_app_id);
  660. CoTaskMemFree(current_app_id);
  661. }
  662. #endif
  663. if (delegate_) {
  664. auto app_path = static_cast<api::App*>(delegate_)->GetAppPath();
  665. command_line->AppendSwitchPath(switches::kAppPath, app_path);
  666. }
  667. std::unique_ptr<base::Environment> env(base::Environment::Create());
  668. if (env->HasVar("ELECTRON_PROFILE_INIT_SCRIPTS")) {
  669. command_line->AppendSwitch("profile-electron-init");
  670. }
  671. content::WebContents* web_contents =
  672. GetWebContentsFromProcessID(process_id);
  673. if (web_contents) {
  674. auto* web_preferences = WebContentsPreferences::From(web_contents);
  675. if (web_preferences)
  676. web_preferences->AppendCommandLineSwitches(
  677. command_line, IsRendererSubFrame(process_id));
  678. auto preloads = SessionPreferences::GetValidPreloads(
  679. web_contents->GetBrowserContext());
  680. if (!preloads.empty())
  681. command_line->AppendSwitchNative(
  682. switches::kPreloadScripts,
  683. base::JoinString(preloads, kPathDelimiter));
  684. if (CanUseCustomSiteInstance()) {
  685. command_line->AppendSwitch(
  686. switches::kDisableElectronSiteInstanceOverrides);
  687. }
  688. }
  689. }
  690. }
  691. void ElectronBrowserClient::DidCreatePpapiPlugin(
  692. content::BrowserPpapiHost* host) {
  693. #if BUILDFLAG(ENABLE_PEPPER_FLASH)
  694. host->GetPpapiHost()->AddHostFactoryFilter(
  695. base::WrapUnique(new ChromeBrowserPepperHostFactory(host)));
  696. #endif
  697. }
  698. // attempt to get api key from env
  699. std::string ElectronBrowserClient::GetGeolocationApiKey() {
  700. std::unique_ptr<base::Environment> env(base::Environment::Create());
  701. std::string api_key;
  702. env->GetVar("GOOGLE_API_KEY", &api_key);
  703. return api_key;
  704. }
  705. scoped_refptr<content::QuotaPermissionContext>
  706. ElectronBrowserClient::CreateQuotaPermissionContext() {
  707. return new ElectronQuotaPermissionContext;
  708. }
  709. content::GeneratedCodeCacheSettings
  710. ElectronBrowserClient::GetGeneratedCodeCacheSettings(
  711. content::BrowserContext* context) {
  712. // TODO(deepak1556): Use platform cache directory.
  713. base::FilePath cache_path = context->GetPath();
  714. // If we pass 0 for size, disk_cache will pick a default size using the
  715. // heuristics based on available disk size. These are implemented in
  716. // disk_cache::PreferredCacheSize in net/disk_cache/cache_util.cc.
  717. return content::GeneratedCodeCacheSettings(true, 0, cache_path);
  718. }
  719. void ElectronBrowserClient::AllowCertificateError(
  720. content::WebContents* web_contents,
  721. int cert_error,
  722. const net::SSLInfo& ssl_info,
  723. const GURL& request_url,
  724. bool is_main_frame_request,
  725. bool strict_enforcement,
  726. base::OnceCallback<void(content::CertificateRequestResultType)> callback) {
  727. if (delegate_) {
  728. delegate_->AllowCertificateError(web_contents, cert_error, ssl_info,
  729. request_url, is_main_frame_request,
  730. strict_enforcement, std::move(callback));
  731. }
  732. }
  733. base::OnceClosure ElectronBrowserClient::SelectClientCertificate(
  734. content::WebContents* web_contents,
  735. net::SSLCertRequestInfo* cert_request_info,
  736. net::ClientCertIdentityList client_certs,
  737. std::unique_ptr<content::ClientCertificateDelegate> delegate) {
  738. if (!client_certs.empty() && delegate_) {
  739. delegate_->SelectClientCertificate(web_contents, cert_request_info,
  740. std::move(client_certs),
  741. std::move(delegate));
  742. }
  743. return base::OnceClosure();
  744. }
  745. bool ElectronBrowserClient::CanCreateWindow(
  746. content::RenderFrameHost* opener,
  747. const GURL& opener_url,
  748. const GURL& opener_top_level_frame_url,
  749. const url::Origin& source_origin,
  750. content::mojom::WindowContainerType container_type,
  751. const GURL& target_url,
  752. const content::Referrer& referrer,
  753. const std::string& frame_name,
  754. WindowOpenDisposition disposition,
  755. const blink::mojom::WindowFeatures& features,
  756. const std::string& raw_features,
  757. const scoped_refptr<network::ResourceRequestBody>& body,
  758. bool user_gesture,
  759. bool opener_suppressed,
  760. bool* no_javascript_access) {
  761. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  762. int opener_render_process_id = opener->GetProcess()->GetID();
  763. if (RendererUsesNativeWindowOpen(opener_render_process_id)) {
  764. if (RendererDisablesPopups(opener_render_process_id)) {
  765. // <webview> without allowpopups attribute should return
  766. // null from window.open calls
  767. return false;
  768. } else {
  769. *no_javascript_access = false;
  770. return true;
  771. }
  772. }
  773. if (delegate_) {
  774. return delegate_->CanCreateWindow(
  775. opener, opener_url, opener_top_level_frame_url, source_origin,
  776. container_type, target_url, referrer, frame_name, disposition, features,
  777. raw_features, body, user_gesture, opener_suppressed,
  778. no_javascript_access);
  779. }
  780. return false;
  781. }
  782. #if BUILDFLAG(ENABLE_PICTURE_IN_PICTURE)
  783. std::unique_ptr<content::OverlayWindow>
  784. ElectronBrowserClient::CreateWindowForPictureInPicture(
  785. content::PictureInPictureWindowController* controller) {
  786. return content::OverlayWindow::Create(controller);
  787. }
  788. #endif
  789. void ElectronBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
  790. std::vector<std::string>* additional_schemes) {
  791. auto schemes_list = api::GetStandardSchemes();
  792. if (!schemes_list.empty())
  793. additional_schemes->insert(additional_schemes->end(), schemes_list.begin(),
  794. schemes_list.end());
  795. additional_schemes->push_back(content::kChromeDevToolsScheme);
  796. additional_schemes->push_back(content::kChromeUIScheme);
  797. }
  798. void ElectronBrowserClient::GetAdditionalWebUISchemes(
  799. std::vector<std::string>* additional_schemes) {
  800. additional_schemes->push_back(content::kChromeDevToolsScheme);
  801. }
  802. void ElectronBrowserClient::SiteInstanceGotProcess(
  803. content::SiteInstance* site_instance) {
  804. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  805. auto* browser_context =
  806. static_cast<ElectronBrowserContext*>(site_instance->GetBrowserContext());
  807. if (!browser_context->IsOffTheRecord()) {
  808. extensions::ExtensionRegistry* registry =
  809. extensions::ExtensionRegistry::Get(browser_context);
  810. const extensions::Extension* extension =
  811. registry->enabled_extensions().GetExtensionOrAppByURL(
  812. site_instance->GetSiteURL());
  813. if (!extension)
  814. return;
  815. extensions::ProcessMap::Get(browser_context)
  816. ->Insert(extension->id(), site_instance->GetProcess()->GetID(),
  817. site_instance->GetId());
  818. base::PostTask(
  819. FROM_HERE, {BrowserThread::IO},
  820. base::BindOnce(&extensions::InfoMap::RegisterExtensionProcess,
  821. browser_context->extension_system()->info_map(),
  822. extension->id(), site_instance->GetProcess()->GetID(),
  823. site_instance->GetId()));
  824. }
  825. #endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  826. }
  827. bool ElectronBrowserClient::IsSuitableHost(
  828. content::RenderProcessHost* process_host,
  829. const GURL& site_url) {
  830. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  831. auto* browser_context = process_host->GetBrowserContext();
  832. extensions::ExtensionRegistry* registry =
  833. extensions::ExtensionRegistry::Get(browser_context);
  834. extensions::ProcessMap* process_map =
  835. extensions::ProcessMap::Get(browser_context);
  836. // Otherwise, just make sure the process privilege matches the privilege
  837. // required by the site.
  838. RenderProcessHostPrivilege privilege_required =
  839. GetPrivilegeRequiredByUrl(site_url, registry);
  840. return GetProcessPrivilege(process_host, process_map, registry) ==
  841. privilege_required;
  842. #else
  843. return content::ContentBrowserClient::IsSuitableHost(process_host, site_url);
  844. #endif
  845. }
  846. bool ElectronBrowserClient::ShouldUseProcessPerSite(
  847. content::BrowserContext* browser_context,
  848. const GURL& effective_url) {
  849. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  850. const extensions::Extension* extension =
  851. GetEnabledExtensionFromEffectiveURL(browser_context, effective_url);
  852. return extension != nullptr;
  853. #else
  854. return content::ContentBrowserClient::ShouldUseProcessPerSite(browser_context,
  855. effective_url);
  856. #endif
  857. }
  858. bool ElectronBrowserClient::ArePersistentMediaDeviceIDsAllowed(
  859. content::BrowserContext* browser_context,
  860. const GURL& scope,
  861. const GURL& site_for_cookies,
  862. const base::Optional<url::Origin>& top_frame_origin) {
  863. return true;
  864. }
  865. void ElectronBrowserClient::SiteInstanceDeleting(
  866. content::SiteInstance* site_instance) {
  867. // We are storing weak_ptr, is it fundamental to maintain the map up-to-date
  868. // when an instance is destroyed.
  869. for (auto iter = site_per_affinities_.begin();
  870. iter != site_per_affinities_.end(); ++iter) {
  871. if (iter->second == site_instance) {
  872. site_per_affinities_.erase(iter);
  873. break;
  874. }
  875. }
  876. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  877. // Don't do anything if we're shutting down.
  878. if (content::BrowserMainRunner::ExitedMainMessageLoop())
  879. return;
  880. auto* browser_context =
  881. static_cast<ElectronBrowserContext*>(site_instance->GetBrowserContext());
  882. if (!browser_context->IsOffTheRecord()) {
  883. // If this isn't an extension renderer there's nothing to do.
  884. extensions::ExtensionRegistry* registry =
  885. extensions::ExtensionRegistry::Get(browser_context);
  886. const extensions::Extension* extension =
  887. registry->enabled_extensions().GetExtensionOrAppByURL(
  888. site_instance->GetSiteURL());
  889. if (!extension)
  890. return;
  891. extensions::ProcessMap::Get(browser_context)
  892. ->Remove(extension->id(), site_instance->GetProcess()->GetID(),
  893. site_instance->GetId());
  894. base::PostTask(
  895. FROM_HERE, {BrowserThread::IO},
  896. base::BindOnce(&extensions::InfoMap::UnregisterExtensionProcess,
  897. browser_context->extension_system()->info_map(),
  898. extension->id(), site_instance->GetProcess()->GetID(),
  899. site_instance->GetId()));
  900. }
  901. #endif
  902. }
  903. std::unique_ptr<net::ClientCertStore>
  904. ElectronBrowserClient::CreateClientCertStore(
  905. content::BrowserContext* browser_context) {
  906. #if defined(USE_NSS_CERTS)
  907. return std::make_unique<net::ClientCertStoreNSS>(
  908. net::ClientCertStoreNSS::PasswordDelegateFactory());
  909. #elif defined(OS_WIN)
  910. return std::make_unique<net::ClientCertStoreWin>();
  911. #elif defined(OS_MACOSX)
  912. return std::make_unique<net::ClientCertStoreMac>();
  913. #elif defined(USE_OPENSSL)
  914. return std::unique_ptr<net::ClientCertStore>();
  915. #endif
  916. }
  917. std::unique_ptr<device::LocationProvider>
  918. ElectronBrowserClient::OverrideSystemLocationProvider() {
  919. #if BUILDFLAG(OVERRIDE_LOCATION_PROVIDER)
  920. return std::make_unique<FakeLocationProvider>();
  921. #else
  922. return nullptr;
  923. #endif
  924. }
  925. void ElectronBrowserClient::ConfigureNetworkContextParams(
  926. content::BrowserContext* browser_context,
  927. bool in_memory,
  928. const base::FilePath& relative_partition_path,
  929. network::mojom::NetworkContextParams* network_context_params,
  930. network::mojom::CertVerifierCreationParams* cert_verifier_creation_params) {
  931. DCHECK(browser_context);
  932. return NetworkContextServiceFactory::GetForContext(browser_context)
  933. ->ConfigureNetworkContextParams(network_context_params,
  934. cert_verifier_creation_params);
  935. }
  936. network::mojom::NetworkContext*
  937. ElectronBrowserClient::GetSystemNetworkContext() {
  938. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  939. DCHECK(g_browser_process->system_network_context_manager());
  940. return g_browser_process->system_network_context_manager()->GetContext();
  941. }
  942. base::Optional<service_manager::Manifest>
  943. ElectronBrowserClient::GetServiceManifestOverlay(base::StringPiece name) {
  944. if (name == content::mojom::kBrowserServiceName)
  945. return GetElectronContentBrowserOverlayManifest();
  946. return base::nullopt;
  947. }
  948. std::unique_ptr<content::BrowserMainParts>
  949. ElectronBrowserClient::CreateBrowserMainParts(
  950. const content::MainFunctionParams& params) {
  951. return std::make_unique<ElectronBrowserMainParts>(params);
  952. }
  953. void ElectronBrowserClient::WebNotificationAllowed(
  954. int render_process_id,
  955. base::OnceCallback<void(bool, bool)> callback) {
  956. content::WebContents* web_contents =
  957. WebContentsPreferences::GetWebContentsFromProcessID(render_process_id);
  958. if (!web_contents) {
  959. std::move(callback).Run(false, false);
  960. return;
  961. }
  962. auto* permission_helper =
  963. WebContentsPermissionHelper::FromWebContents(web_contents);
  964. if (!permission_helper) {
  965. std::move(callback).Run(false, false);
  966. return;
  967. }
  968. permission_helper->RequestWebNotificationPermission(
  969. base::BindOnce(std::move(callback), web_contents->IsAudioMuted()));
  970. }
  971. void ElectronBrowserClient::RenderProcessHostDestroyed(
  972. content::RenderProcessHost* host) {
  973. int process_id = host->GetID();
  974. pending_processes_.erase(process_id);
  975. renderer_is_subframe_.erase(process_id);
  976. RemoveProcessPreferences(process_id);
  977. }
  978. void ElectronBrowserClient::RenderProcessReady(
  979. content::RenderProcessHost* host) {
  980. render_process_host_pids_[host->GetID()] =
  981. base::GetProcId(host->GetProcess().Handle());
  982. if (delegate_) {
  983. static_cast<api::App*>(delegate_)->RenderProcessReady(host);
  984. }
  985. }
  986. void ElectronBrowserClient::RenderProcessExited(
  987. content::RenderProcessHost* host,
  988. const content::ChildProcessTerminationInfo& info) {
  989. auto host_pid = render_process_host_pids_.find(host->GetID());
  990. if (host_pid != render_process_host_pids_.end()) {
  991. if (delegate_) {
  992. static_cast<api::App*>(delegate_)->RenderProcessDisconnected(
  993. host_pid->second);
  994. }
  995. render_process_host_pids_.erase(host_pid);
  996. }
  997. }
  998. void OnOpenExternal(const GURL& escaped_url, bool allowed) {
  999. if (allowed) {
  1000. platform_util::OpenExternal(
  1001. escaped_url, platform_util::OpenExternalOptions(), base::DoNothing());
  1002. }
  1003. }
  1004. void HandleExternalProtocolInUI(
  1005. const GURL& url,
  1006. content::WebContents::OnceGetter web_contents_getter,
  1007. bool has_user_gesture) {
  1008. content::WebContents* web_contents = std::move(web_contents_getter).Run();
  1009. if (!web_contents)
  1010. return;
  1011. auto* permission_helper =
  1012. WebContentsPermissionHelper::FromWebContents(web_contents);
  1013. if (!permission_helper)
  1014. return;
  1015. GURL escaped_url(net::EscapeExternalHandlerValue(url.spec()));
  1016. auto callback = base::BindOnce(&OnOpenExternal, escaped_url);
  1017. permission_helper->RequestOpenExternalPermission(std::move(callback),
  1018. has_user_gesture, url);
  1019. }
  1020. bool ElectronBrowserClient::HandleExternalProtocol(
  1021. const GURL& url,
  1022. content::WebContents::OnceGetter web_contents_getter,
  1023. int child_id,
  1024. content::NavigationUIData* navigation_data,
  1025. bool is_main_frame,
  1026. ui::PageTransition page_transition,
  1027. bool has_user_gesture,
  1028. const base::Optional<url::Origin>& initiating_origin,
  1029. mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory) {
  1030. base::PostTask(
  1031. FROM_HERE, {BrowserThread::UI},
  1032. base::BindOnce(&HandleExternalProtocolInUI, url,
  1033. std::move(web_contents_getter), has_user_gesture));
  1034. return true;
  1035. }
  1036. std::vector<std::unique_ptr<content::NavigationThrottle>>
  1037. ElectronBrowserClient::CreateThrottlesForNavigation(
  1038. content::NavigationHandle* handle) {
  1039. std::vector<std::unique_ptr<content::NavigationThrottle>> throttles;
  1040. throttles.push_back(std::make_unique<ElectronNavigationThrottle>(handle));
  1041. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1042. throttles.push_back(
  1043. std::make_unique<extensions::ExtensionNavigationThrottle>(handle));
  1044. #endif
  1045. return throttles;
  1046. }
  1047. content::MediaObserver* ElectronBrowserClient::GetMediaObserver() {
  1048. return MediaCaptureDevicesDispatcher::GetInstance();
  1049. }
  1050. content::DevToolsManagerDelegate*
  1051. ElectronBrowserClient::GetDevToolsManagerDelegate() {
  1052. return new DevToolsManagerDelegate;
  1053. }
  1054. NotificationPresenter* ElectronBrowserClient::GetNotificationPresenter() {
  1055. if (!notification_presenter_) {
  1056. notification_presenter_.reset(NotificationPresenter::Create());
  1057. }
  1058. return notification_presenter_.get();
  1059. }
  1060. content::PlatformNotificationService*
  1061. ElectronBrowserClient::GetPlatformNotificationService(
  1062. content::BrowserContext* browser_context) {
  1063. if (!notification_service_) {
  1064. notification_service_ = std::make_unique<PlatformNotificationService>(this);
  1065. }
  1066. return notification_service_.get();
  1067. }
  1068. base::FilePath ElectronBrowserClient::GetDefaultDownloadDirectory() {
  1069. // ~/Downloads
  1070. base::FilePath path;
  1071. if (base::PathService::Get(base::DIR_HOME, &path))
  1072. path = path.Append(FILE_PATH_LITERAL("Downloads"));
  1073. return path;
  1074. }
  1075. scoped_refptr<network::SharedURLLoaderFactory>
  1076. ElectronBrowserClient::GetSystemSharedURLLoaderFactory() {
  1077. if (!g_browser_process)
  1078. return nullptr;
  1079. return g_browser_process->shared_url_loader_factory();
  1080. }
  1081. void ElectronBrowserClient::OnNetworkServiceCreated(
  1082. network::mojom::NetworkService* network_service) {
  1083. if (!g_browser_process)
  1084. return;
  1085. g_browser_process->system_network_context_manager()->OnNetworkServiceCreated(
  1086. network_service);
  1087. }
  1088. std::vector<base::FilePath>
  1089. ElectronBrowserClient::GetNetworkContextsParentDirectory() {
  1090. base::FilePath user_data_dir;
  1091. base::PathService::Get(DIR_USER_DATA, &user_data_dir);
  1092. DCHECK(!user_data_dir.empty());
  1093. return {user_data_dir};
  1094. }
  1095. std::string ElectronBrowserClient::GetProduct() {
  1096. return "Chrome/" CHROME_VERSION_STRING;
  1097. }
  1098. std::string ElectronBrowserClient::GetUserAgent() {
  1099. if (user_agent_override_.empty())
  1100. return GetApplicationUserAgent();
  1101. return user_agent_override_;
  1102. }
  1103. void ElectronBrowserClient::SetUserAgent(const std::string& user_agent) {
  1104. user_agent_override_ = user_agent;
  1105. }
  1106. void ElectronBrowserClient::RegisterNonNetworkNavigationURLLoaderFactories(
  1107. int frame_tree_node_id,
  1108. NonNetworkURLLoaderFactoryMap* factories) {
  1109. content::WebContents* web_contents =
  1110. content::WebContents::FromFrameTreeNodeId(frame_tree_node_id);
  1111. content::BrowserContext* context = web_contents->GetBrowserContext();
  1112. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1113. factories->emplace(
  1114. extensions::kExtensionScheme,
  1115. extensions::CreateExtensionNavigationURLLoaderFactory(
  1116. context, false /* we don't support extensions::WebViewGuest */));
  1117. #endif
  1118. auto* protocol_registry = ProtocolRegistry::FromBrowserContext(context);
  1119. protocol_registry->RegisterURLLoaderFactories(
  1120. URLLoaderFactoryType::kNavigation, factories);
  1121. }
  1122. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1123. namespace {
  1124. // The FileURLLoaderFactory provided to the extension background pages.
  1125. // Checks with the ChildProcessSecurityPolicy to validate the file access.
  1126. class FileURLLoaderFactory : public network::mojom::URLLoaderFactory {
  1127. public:
  1128. explicit FileURLLoaderFactory(int child_id) : child_id_(child_id) {}
  1129. private:
  1130. // network::mojom::URLLoaderFactory:
  1131. void CreateLoaderAndStart(
  1132. mojo::PendingReceiver<network::mojom::URLLoader> loader,
  1133. int32_t routing_id,
  1134. int32_t request_id,
  1135. uint32_t options,
  1136. const network::ResourceRequest& request,
  1137. mojo::PendingRemote<network::mojom::URLLoaderClient> client,
  1138. const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
  1139. override {
  1140. if (!content::ChildProcessSecurityPolicy::GetInstance()->CanRequestURL(
  1141. child_id_, request.url)) {
  1142. mojo::Remote<network::mojom::URLLoaderClient>(std::move(client))
  1143. ->OnComplete(
  1144. network::URLLoaderCompletionStatus(net::ERR_ACCESS_DENIED));
  1145. return;
  1146. }
  1147. content::CreateFileURLLoaderBypassingSecurityChecks(
  1148. request, std::move(loader), std::move(client),
  1149. /*observer=*/nullptr,
  1150. /* allow_directory_listing */ true);
  1151. }
  1152. void Clone(
  1153. mojo::PendingReceiver<network::mojom::URLLoaderFactory> loader) override {
  1154. receivers_.Add(this, std::move(loader));
  1155. }
  1156. int child_id_;
  1157. mojo::ReceiverSet<network::mojom::URLLoaderFactory> receivers_;
  1158. DISALLOW_COPY_AND_ASSIGN(FileURLLoaderFactory);
  1159. };
  1160. } // namespace
  1161. #endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1162. void ElectronBrowserClient::RegisterNonNetworkSubresourceURLLoaderFactories(
  1163. int render_process_id,
  1164. int render_frame_id,
  1165. NonNetworkURLLoaderFactoryMap* factories) {
  1166. content::RenderFrameHost* frame_host =
  1167. content::RenderFrameHost::FromID(render_process_id, render_frame_id);
  1168. content::WebContents* web_contents =
  1169. content::WebContents::FromRenderFrameHost(frame_host);
  1170. if (web_contents) {
  1171. ProtocolRegistry::FromBrowserContext(web_contents->GetBrowserContext())
  1172. ->RegisterURLLoaderFactories(URLLoaderFactoryType::kDocumentSubResource,
  1173. factories);
  1174. }
  1175. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1176. auto factory = extensions::CreateExtensionURLLoaderFactory(render_process_id,
  1177. render_frame_id);
  1178. if (factory)
  1179. factories->emplace(extensions::kExtensionScheme, std::move(factory));
  1180. if (!web_contents)
  1181. return;
  1182. extensions::ElectronExtensionWebContentsObserver* web_observer =
  1183. extensions::ElectronExtensionWebContentsObserver::FromWebContents(
  1184. web_contents);
  1185. // There is nothing to do if no ElectronExtensionWebContentsObserver is
  1186. // attached to the |web_contents|.
  1187. if (!web_observer)
  1188. return;
  1189. const extensions::Extension* extension =
  1190. web_observer->GetExtensionFromFrame(frame_host, false);
  1191. if (!extension)
  1192. return;
  1193. // Support for chrome:// scheme if appropriate.
  1194. if (extension->is_extension() &&
  1195. extensions::Manifest::IsComponentLocation(extension->location())) {
  1196. // Components of chrome that are implemented as extensions or platform apps
  1197. // are allowed to use chrome://resources/ and chrome://theme/ URLs.
  1198. factories->emplace(
  1199. content::kChromeUIScheme,
  1200. content::CreateWebUIURLLoader(frame_host, content::kChromeUIScheme,
  1201. {content::kChromeUIResourcesHost}));
  1202. }
  1203. // Extension with a background page get file access that gets approval from
  1204. // ChildProcessSecurityPolicy.
  1205. extensions::ExtensionHost* host =
  1206. extensions::ProcessManager::Get(web_contents->GetBrowserContext())
  1207. ->GetBackgroundHostForExtension(extension->id());
  1208. if (host) {
  1209. factories->emplace(url::kFileScheme, std::make_unique<FileURLLoaderFactory>(
  1210. render_process_id));
  1211. }
  1212. #endif
  1213. }
  1214. bool ElectronBrowserClient::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
  1215. base::StringPiece scheme,
  1216. bool is_embedded_origin_secure) {
  1217. if (is_embedded_origin_secure && scheme == content::kChromeUIScheme)
  1218. return true;
  1219. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1220. return scheme == extensions::kExtensionScheme;
  1221. #else
  1222. return false;
  1223. #endif
  1224. }
  1225. bool ElectronBrowserClient::WillInterceptWebSocket(
  1226. content::RenderFrameHost* frame) {
  1227. if (!frame)
  1228. return false;
  1229. v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
  1230. v8::HandleScope scope(isolate);
  1231. auto* browser_context = frame->GetProcess()->GetBrowserContext();
  1232. auto web_request = api::WebRequest::FromOrCreate(isolate, browser_context);
  1233. // NOTE: Some unit test environments do not initialize
  1234. // BrowserContextKeyedAPI factories for e.g. WebRequest.
  1235. if (!web_request.get())
  1236. return false;
  1237. return web_request->HasListener();
  1238. }
  1239. void ElectronBrowserClient::CreateWebSocket(
  1240. content::RenderFrameHost* frame,
  1241. WebSocketFactory factory,
  1242. const GURL& url,
  1243. const net::SiteForCookies& site_for_cookies,
  1244. const base::Optional<std::string>& user_agent,
  1245. mojo::PendingRemote<network::mojom::WebSocketHandshakeClient>
  1246. handshake_client) {
  1247. v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
  1248. v8::HandleScope scope(isolate);
  1249. auto* browser_context = frame->GetProcess()->GetBrowserContext();
  1250. auto web_request = api::WebRequest::FromOrCreate(isolate, browser_context);
  1251. DCHECK(web_request.get());
  1252. ProxyingWebSocket::StartProxying(
  1253. web_request.get(), std::move(factory), url,
  1254. site_for_cookies.RepresentativeUrl(), user_agent,
  1255. std::move(handshake_client), true, frame->GetProcess()->GetID(),
  1256. frame->GetRoutingID(), frame->GetLastCommittedOrigin(), browser_context,
  1257. &next_id_);
  1258. }
  1259. bool ElectronBrowserClient::WillCreateURLLoaderFactory(
  1260. content::BrowserContext* browser_context,
  1261. content::RenderFrameHost* frame_host,
  1262. int render_process_id,
  1263. URLLoaderFactoryType type,
  1264. const url::Origin& request_initiator,
  1265. base::Optional<int64_t> navigation_id,
  1266. mojo::PendingReceiver<network::mojom::URLLoaderFactory>* factory_receiver,
  1267. mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>*
  1268. header_client,
  1269. bool* bypass_redirect_checks,
  1270. bool* disable_secure_dns,
  1271. network::mojom::URLLoaderFactoryOverridePtr* factory_override) {
  1272. v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
  1273. v8::HandleScope scope(isolate);
  1274. auto web_request = api::WebRequest::FromOrCreate(isolate, browser_context);
  1275. DCHECK(web_request.get());
  1276. auto proxied_receiver = std::move(*factory_receiver);
  1277. mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory_remote;
  1278. *factory_receiver = target_factory_remote.InitWithNewPipeAndPassReceiver();
  1279. // Required by WebRequestInfoInitParams.
  1280. //
  1281. // Note that in Electron we allow webRequest to capture requests sent from
  1282. // browser process, so creation of |navigation_ui_data| is different from
  1283. // Chromium which only does for renderer-initialized navigations.
  1284. std::unique_ptr<extensions::ExtensionNavigationUIData> navigation_ui_data;
  1285. if (navigation_id.has_value()) {
  1286. navigation_ui_data =
  1287. std::make_unique<extensions::ExtensionNavigationUIData>();
  1288. }
  1289. mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient>
  1290. header_client_receiver;
  1291. if (header_client)
  1292. header_client_receiver = header_client->InitWithNewPipeAndPassReceiver();
  1293. auto* protocol_registry =
  1294. ProtocolRegistry::FromBrowserContext(browser_context);
  1295. new ProxyingURLLoaderFactory(
  1296. web_request.get(), protocol_registry->intercept_handlers(),
  1297. browser_context, render_process_id, &next_id_,
  1298. std::move(navigation_ui_data), std::move(navigation_id),
  1299. std::move(proxied_receiver), std::move(target_factory_remote),
  1300. std::move(header_client_receiver), type);
  1301. if (bypass_redirect_checks)
  1302. *bypass_redirect_checks = true;
  1303. return true;
  1304. }
  1305. void ElectronBrowserClient::OverrideURLLoaderFactoryParams(
  1306. content::BrowserContext* browser_context,
  1307. const url::Origin& origin,
  1308. bool is_for_isolated_world,
  1309. network::mojom::URLLoaderFactoryParams* factory_params) {
  1310. for (const auto& iter : process_preferences_) {
  1311. if (iter.second.browser_context != browser_context)
  1312. continue;
  1313. if (!iter.second.web_security) {
  1314. // bypass CORB
  1315. factory_params->process_id = iter.first;
  1316. factory_params->is_corb_enabled = false;
  1317. }
  1318. }
  1319. }
  1320. #if defined(OS_WIN)
  1321. bool ElectronBrowserClient::PreSpawnRenderer(sandbox::TargetPolicy* policy,
  1322. RendererSpawnFlags flags) {
  1323. // Allow crashpad to communicate via named pipe.
  1324. sandbox::ResultCode result = policy->AddRule(
  1325. sandbox::TargetPolicy::SUBSYS_FILES,
  1326. sandbox::TargetPolicy::FILES_ALLOW_ANY, L"\\??\\pipe\\crashpad_*");
  1327. if (result != sandbox::SBOX_ALL_OK)
  1328. return false;
  1329. return true;
  1330. }
  1331. #endif // defined(OS_WIN)
  1332. bool ElectronBrowserClient::BindAssociatedReceiverFromFrame(
  1333. content::RenderFrameHost* render_frame_host,
  1334. const std::string& interface_name,
  1335. mojo::ScopedInterfaceEndpointHandle* handle) {
  1336. if (interface_name == mojom::ElectronAutofillDriver::Name_) {
  1337. AutofillDriverFactory::BindAutofillDriver(
  1338. mojom::ElectronAutofillDriverAssociatedRequest(std::move(*handle)),
  1339. render_frame_host);
  1340. return true;
  1341. }
  1342. return false;
  1343. }
  1344. std::string ElectronBrowserClient::GetApplicationLocale() {
  1345. if (BrowserThread::CurrentlyOn(BrowserThread::IO))
  1346. return g_io_thread_application_locale.Get();
  1347. return *g_application_locale;
  1348. }
  1349. base::FilePath ElectronBrowserClient::GetFontLookupTableCacheDir() {
  1350. base::FilePath user_data_dir;
  1351. base::PathService::Get(DIR_USER_DATA, &user_data_dir);
  1352. DCHECK(!user_data_dir.empty());
  1353. return user_data_dir.Append(FILE_PATH_LITERAL("FontLookupTableCache"));
  1354. }
  1355. bool ElectronBrowserClient::ShouldEnableStrictSiteIsolation() {
  1356. // Enable site isolation. It is off by default in Chromium <= 69.
  1357. return true;
  1358. }
  1359. void ElectronBrowserClient::BindHostReceiverForRenderer(
  1360. content::RenderProcessHost* render_process_host,
  1361. mojo::GenericPendingReceiver receiver) {
  1362. #if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
  1363. if (auto host_receiver = receiver.As<spellcheck::mojom::SpellCheckHost>()) {
  1364. SpellCheckHostChromeImpl::Create(render_process_host->GetID(),
  1365. std::move(host_receiver));
  1366. return;
  1367. }
  1368. #endif
  1369. }
  1370. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1371. void BindMimeHandlerService(
  1372. content::RenderFrameHost* frame_host,
  1373. mojo::PendingReceiver<extensions::mime_handler::MimeHandlerService>
  1374. receiver) {
  1375. content::WebContents* contents =
  1376. content::WebContents::FromRenderFrameHost(frame_host);
  1377. auto* guest_view =
  1378. extensions::MimeHandlerViewGuest::FromWebContents(contents);
  1379. if (!guest_view)
  1380. return;
  1381. extensions::MimeHandlerServiceImpl::Create(guest_view->GetStreamWeakPtr(),
  1382. std::move(receiver));
  1383. }
  1384. void BindBeforeUnloadControl(
  1385. content::RenderFrameHost* frame_host,
  1386. mojo::PendingReceiver<extensions::mime_handler::BeforeUnloadControl>
  1387. receiver) {
  1388. auto* web_contents = content::WebContents::FromRenderFrameHost(frame_host);
  1389. if (!web_contents)
  1390. return;
  1391. auto* guest_view =
  1392. extensions::MimeHandlerViewGuest::FromWebContents(web_contents);
  1393. if (!guest_view)
  1394. return;
  1395. guest_view->FuseBeforeUnloadControl(std::move(receiver));
  1396. }
  1397. #endif
  1398. void ElectronBrowserClient::RegisterBrowserInterfaceBindersForFrame(
  1399. content::RenderFrameHost* render_frame_host,
  1400. mojo::BinderMapWithContext<content::RenderFrameHost*>* map) {
  1401. map->Add<network_hints::mojom::NetworkHintsHandler>(
  1402. base::BindRepeating(&BindNetworkHintsHandler));
  1403. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1404. map->Add<extensions::mime_handler::MimeHandlerService>(
  1405. base::BindRepeating(&BindMimeHandlerService));
  1406. map->Add<extensions::mime_handler::BeforeUnloadControl>(
  1407. base::BindRepeating(&BindBeforeUnloadControl));
  1408. content::WebContents* web_contents =
  1409. content::WebContents::FromRenderFrameHost(render_frame_host);
  1410. if (!web_contents)
  1411. return;
  1412. const GURL& site = render_frame_host->GetSiteInstance()->GetSiteURL();
  1413. if (!site.SchemeIs(extensions::kExtensionScheme))
  1414. return;
  1415. content::BrowserContext* browser_context =
  1416. render_frame_host->GetProcess()->GetBrowserContext();
  1417. auto* extension = extensions::ExtensionRegistry::Get(browser_context)
  1418. ->enabled_extensions()
  1419. .GetByID(site.host());
  1420. if (!extension)
  1421. return;
  1422. extensions::ExtensionsBrowserClient::Get()
  1423. ->RegisterBrowserInterfaceBindersForFrame(map, render_frame_host,
  1424. extension);
  1425. #endif
  1426. }
  1427. #if defined(OS_LINUX)
  1428. void ElectronBrowserClient::GetAdditionalMappedFilesForChildProcess(
  1429. const base::CommandLine& command_line,
  1430. int child_process_id,
  1431. content::PosixFileDescriptorInfo* mappings) {
  1432. int crash_signal_fd = GetCrashSignalFD(command_line);
  1433. if (crash_signal_fd >= 0) {
  1434. mappings->Share(service_manager::kCrashDumpSignal, crash_signal_fd);
  1435. }
  1436. }
  1437. #endif
  1438. std::unique_ptr<content::LoginDelegate>
  1439. ElectronBrowserClient::CreateLoginDelegate(
  1440. const net::AuthChallengeInfo& auth_info,
  1441. content::WebContents* web_contents,
  1442. const content::GlobalRequestID& request_id,
  1443. bool is_main_frame,
  1444. const GURL& url,
  1445. scoped_refptr<net::HttpResponseHeaders> response_headers,
  1446. bool first_auth_attempt,
  1447. LoginAuthRequiredCallback auth_required_callback) {
  1448. return std::make_unique<LoginHandler>(
  1449. auth_info, web_contents, is_main_frame, url, response_headers,
  1450. first_auth_attempt, std::move(auth_required_callback));
  1451. }
  1452. std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
  1453. ElectronBrowserClient::CreateURLLoaderThrottles(
  1454. const network::ResourceRequest& request,
  1455. content::BrowserContext* browser_context,
  1456. const base::RepeatingCallback<content::WebContents*()>& wc_getter,
  1457. content::NavigationUIData* navigation_ui_data,
  1458. int frame_tree_node_id) {
  1459. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  1460. std::vector<std::unique_ptr<blink::URLLoaderThrottle>> result;
  1461. #if BUILDFLAG(ENABLE_PLUGINS) && BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1462. result.push_back(std::make_unique<PluginResponseInterceptorURLLoaderThrottle>(
  1463. request.resource_type, frame_tree_node_id));
  1464. #endif
  1465. return result;
  1466. }
  1467. base::flat_set<std::string>
  1468. ElectronBrowserClient::GetPluginMimeTypesWithExternalHandlers(
  1469. content::BrowserContext* browser_context) {
  1470. base::flat_set<std::string> mime_types;
  1471. #if BUILDFLAG(ENABLE_PLUGINS) && BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1472. auto map = PluginUtils::GetMimeTypeToExtensionIdMap(browser_context);
  1473. for (const auto& pair : map)
  1474. mime_types.insert(pair.first);
  1475. #endif
  1476. return mime_types;
  1477. }
  1478. } // namespace electron