electron_browser_client.cc 69 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864
  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 BUILDFLAG(IS_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/debug/crash_logging.h"
  13. #include "base/environment.h"
  14. #include "base/files/file_util.h"
  15. #include "base/json/json_reader.h"
  16. #include "base/lazy_instance.h"
  17. #include "base/no_destructor.h"
  18. #include "base/path_service.h"
  19. #include "base/stl_util.h"
  20. #include "base/strings/strcat.h"
  21. #include "base/strings/string_number_conversions.h"
  22. #include "base/strings/string_util.h"
  23. #include "base/strings/utf_string_conversions.h"
  24. #include "base/task/post_task.h"
  25. #include "chrome/browser/browser_process.h"
  26. #include "chrome/common/chrome_paths.h"
  27. #include "chrome/common/chrome_switches.h"
  28. #include "chrome/common/chrome_version.h"
  29. #include "components/embedder_support/user_agent_utils.h"
  30. #include "components/net_log/chrome_net_log.h"
  31. #include "components/network_hints/common/network_hints.mojom.h"
  32. #include "content/browser/keyboard_lock/keyboard_lock_service_impl.h" // nogncheck
  33. #include "content/browser/site_instance_impl.h" // nogncheck
  34. #include "content/public/browser/browser_main_runner.h"
  35. #include "content/public/browser/browser_ppapi_host.h"
  36. #include "content/public/browser/browser_task_traits.h"
  37. #include "content/public/browser/client_certificate_delegate.h"
  38. #include "content/public/browser/login_delegate.h"
  39. #include "content/public/browser/overlay_window.h"
  40. #include "content/public/browser/render_frame_host.h"
  41. #include "content/public/browser/render_process_host.h"
  42. #include "content/public/browser/render_view_host.h"
  43. #include "content/public/browser/service_worker_version_base_info.h"
  44. #include "content/public/browser/site_instance.h"
  45. #include "content/public/browser/tts_controller.h"
  46. #include "content/public/browser/tts_platform.h"
  47. #include "content/public/browser/url_loader_request_interceptor.h"
  48. #include "content/public/browser/weak_document_ptr.h"
  49. #include "content/public/common/content_descriptors.h"
  50. #include "content/public/common/content_paths.h"
  51. #include "content/public/common/content_switches.h"
  52. #include "content/public/common/url_constants.h"
  53. #include "crypto/crypto_buildflags.h"
  54. #include "electron/buildflags/buildflags.h"
  55. #include "electron/grit/electron_resources.h"
  56. #include "electron/shell/common/api/api.mojom.h"
  57. #include "extensions/browser/api/messaging/messaging_api_message_filter.h"
  58. #include "mojo/public/cpp/bindings/binder_map.h"
  59. #include "net/base/escape.h"
  60. #include "net/ssl/ssl_cert_request_info.h"
  61. #include "ppapi/buildflags/buildflags.h"
  62. #include "ppapi/host/ppapi_host.h"
  63. #include "printing/buildflags/buildflags.h"
  64. #include "services/device/public/cpp/geolocation/location_provider.h"
  65. #include "services/network/public/cpp/features.h"
  66. #include "services/network/public/cpp/is_potentially_trustworthy.h"
  67. #include "services/network/public/cpp/network_switches.h"
  68. #include "services/network/public/cpp/resource_request_body.h"
  69. #include "services/network/public/cpp/self_deleting_url_loader_factory.h"
  70. #include "shell/app/electron_crash_reporter_client.h"
  71. #include "shell/browser/api/electron_api_app.h"
  72. #include "shell/browser/api/electron_api_crash_reporter.h"
  73. #include "shell/browser/api/electron_api_protocol.h"
  74. #include "shell/browser/api/electron_api_session.h"
  75. #include "shell/browser/api/electron_api_web_contents.h"
  76. #include "shell/browser/api/electron_api_web_request.h"
  77. #include "shell/browser/badging/badge_manager.h"
  78. #include "shell/browser/child_web_contents_tracker.h"
  79. #include "shell/browser/electron_api_ipc_handler_impl.h"
  80. #include "shell/browser/electron_autofill_driver_factory.h"
  81. #include "shell/browser/electron_browser_context.h"
  82. #include "shell/browser/electron_browser_main_parts.h"
  83. #include "shell/browser/electron_navigation_throttle.h"
  84. #include "shell/browser/electron_quota_permission_context.h"
  85. #include "shell/browser/electron_speech_recognition_manager_delegate.h"
  86. #include "shell/browser/electron_web_contents_utility_handler_impl.h"
  87. #include "shell/browser/font_defaults.h"
  88. #include "shell/browser/javascript_environment.h"
  89. #include "shell/browser/media/media_capture_devices_dispatcher.h"
  90. #include "shell/browser/native_window.h"
  91. #include "shell/browser/net/network_context_service.h"
  92. #include "shell/browser/net/network_context_service_factory.h"
  93. #include "shell/browser/net/proxying_url_loader_factory.h"
  94. #include "shell/browser/net/proxying_websocket.h"
  95. #include "shell/browser/net/system_network_context_manager.h"
  96. #include "shell/browser/network_hints_handler_impl.h"
  97. #include "shell/browser/notifications/notification_presenter.h"
  98. #include "shell/browser/notifications/platform_notification_service.h"
  99. #include "shell/browser/protocol_registry.h"
  100. #include "shell/browser/serial/electron_serial_delegate.h"
  101. #include "shell/browser/session_preferences.h"
  102. #include "shell/browser/ui/devtools_manager_delegate.h"
  103. #include "shell/browser/web_contents_permission_helper.h"
  104. #include "shell/browser/web_contents_preferences.h"
  105. #include "shell/browser/window_list.h"
  106. #include "shell/common/api/api.mojom.h"
  107. #include "shell/common/application_info.h"
  108. #include "shell/common/electron_paths.h"
  109. #include "shell/common/logging.h"
  110. #include "shell/common/options_switches.h"
  111. #include "shell/common/platform_util.h"
  112. #include "third_party/blink/public/common/loader/url_loader_throttle.h"
  113. #include "third_party/blink/public/common/tokens/tokens.h"
  114. #include "third_party/blink/public/common/web_preferences/web_preferences.h"
  115. #include "third_party/blink/public/mojom/badging/badging.mojom.h"
  116. #include "ui/base/resource/resource_bundle.h"
  117. #include "ui/native_theme/native_theme.h"
  118. #include "v8/include/v8.h"
  119. #if BUILDFLAG(IS_WIN)
  120. #include "sandbox/win/src/sandbox_policy.h"
  121. #endif
  122. #if BUILDFLAG(USE_NSS_CERTS)
  123. #include "net/ssl/client_cert_store_nss.h"
  124. #elif BUILDFLAG(IS_WIN)
  125. #include "net/ssl/client_cert_store_win.h"
  126. #elif BUILDFLAG(IS_MAC)
  127. #include "net/ssl/client_cert_store_mac.h"
  128. #elif defined(USE_OPENSSL)
  129. #include "net/ssl/client_cert_store.h"
  130. #endif
  131. #if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
  132. #include "chrome/browser/spellchecker/spell_check_host_chrome_impl.h" // nogncheck
  133. #include "components/spellcheck/common/spellcheck.mojom.h" // nogncheck
  134. #endif
  135. #if BUILDFLAG(OVERRIDE_LOCATION_PROVIDER)
  136. #include "shell/browser/fake_location_provider.h"
  137. #endif // BUILDFLAG(OVERRIDE_LOCATION_PROVIDER)
  138. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  139. #include "chrome/common/webui_url_constants.h"
  140. #include "content/public/browser/child_process_security_policy.h"
  141. #include "content/public/browser/file_url_loader.h"
  142. #include "content/public/browser/web_ui_url_loader_factory.h"
  143. #include "extensions/browser/api/mime_handler_private/mime_handler_private.h"
  144. #include "extensions/browser/api/web_request/web_request_api.h"
  145. #include "extensions/browser/browser_context_keyed_api_factory.h"
  146. #include "extensions/browser/event_router.h"
  147. #include "extensions/browser/extension_host.h"
  148. #include "extensions/browser/extension_message_filter.h"
  149. #include "extensions/browser/extension_navigation_throttle.h"
  150. #include "extensions/browser/extension_navigation_ui_data.h"
  151. #include "extensions/browser/extension_prefs.h"
  152. #include "extensions/browser/extension_protocols.h"
  153. #include "extensions/browser/extension_registry.h"
  154. #include "extensions/browser/extensions_browser_client.h"
  155. #include "extensions/browser/guest_view/extensions_guest_view.h"
  156. #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
  157. #include "extensions/browser/info_map.h"
  158. #include "extensions/browser/process_manager.h"
  159. #include "extensions/browser/process_map.h"
  160. #include "extensions/browser/url_loader_factory_manager.h"
  161. #include "extensions/common/api/mime_handler.mojom.h"
  162. #include "extensions/common/constants.h"
  163. #include "extensions/common/extension.h"
  164. #include "extensions/common/switches.h"
  165. #include "shell/browser/extensions/electron_extension_message_filter.h"
  166. #include "shell/browser/extensions/electron_extension_system.h"
  167. #include "shell/browser/extensions/electron_extension_web_contents_observer.h"
  168. #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
  169. #endif
  170. #if BUILDFLAG(ENABLE_PLUGINS)
  171. #include "chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.h" // nogncheck
  172. #include "shell/browser/plugins/plugin_utils.h"
  173. #endif
  174. #if BUILDFLAG(IS_MAC)
  175. #include "content/common/mac_helpers.h"
  176. #include "content/public/common/child_process_host.h"
  177. #endif
  178. #if BUILDFLAG(IS_LINUX) && !defined(MAS_BUILD)
  179. #include "base/debug/leak_annotations.h"
  180. #include "components/crash/content/browser/crash_handler_host_linux.h"
  181. #include "components/crash/core/app/breakpad_linux.h" // nogncheck
  182. #include "components/crash/core/app/crash_switches.h" // nogncheck
  183. #include "components/crash/core/app/crashpad.h" // nogncheck
  184. #endif
  185. #if BUILDFLAG(ENABLE_PICTURE_IN_PICTURE) && BUILDFLAG(IS_WIN)
  186. #include "chrome/browser/ui/views/overlay/document_overlay_window_views.h"
  187. #include "chrome/browser/ui/views/overlay/video_overlay_window_views.h"
  188. #include "shell/browser/browser.h"
  189. #include "ui/aura/window.h"
  190. #include "ui/aura/window_tree_host.h"
  191. #include "ui/base/win/shell.h"
  192. #include "ui/views/widget/widget.h"
  193. #endif
  194. #if BUILDFLAG(ENABLE_PRINTING)
  195. #include "shell/browser/printing/print_view_manager_electron.h"
  196. #endif
  197. #if BUILDFLAG(ENABLE_PDF_VIEWER)
  198. #include "chrome/browser/pdf/chrome_pdf_stream_delegate.h"
  199. #include "chrome/browser/plugins/pdf_iframe_navigation_throttle.h" // nogncheck
  200. #include "components/pdf/browser/pdf_navigation_throttle.h"
  201. #include "components/pdf/browser/pdf_url_loader_request_interceptor.h"
  202. #include "components/pdf/browser/pdf_web_contents_helper.h" // nogncheck
  203. #include "components/pdf/common/internal_plugin_helpers.h"
  204. #endif
  205. using content::BrowserThread;
  206. namespace electron {
  207. namespace {
  208. ElectronBrowserClient* g_browser_client = nullptr;
  209. base::LazyInstance<std::string>::DestructorAtExit
  210. g_io_thread_application_locale = LAZY_INSTANCE_INITIALIZER;
  211. base::NoDestructor<std::string> g_application_locale;
  212. void SetApplicationLocaleOnIOThread(const std::string& locale) {
  213. DCHECK_CURRENTLY_ON(BrowserThread::IO);
  214. g_io_thread_application_locale.Get() = locale;
  215. }
  216. void BindNetworkHintsHandler(
  217. content::RenderFrameHost* frame_host,
  218. mojo::PendingReceiver<network_hints::mojom::NetworkHintsHandler> receiver) {
  219. NetworkHintsHandlerImpl::Create(frame_host, std::move(receiver));
  220. }
  221. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  222. // Used by the GetPrivilegeRequiredByUrl() and GetProcessPrivilege() functions
  223. // below. Extension, and isolated apps require different privileges to be
  224. // granted to their RenderProcessHosts. This classification allows us to make
  225. // sure URLs are served by hosts with the right set of privileges.
  226. enum class RenderProcessHostPrivilege {
  227. kNormal,
  228. kHosted,
  229. kIsolated,
  230. kExtension,
  231. };
  232. // Copied from chrome/browser/extensions/extension_util.cc.
  233. bool AllowFileAccess(const std::string& extension_id,
  234. content::BrowserContext* context) {
  235. return base::CommandLine::ForCurrentProcess()->HasSwitch(
  236. ::switches::kDisableExtensionsFileAccessCheck) ||
  237. extensions::ExtensionPrefs::Get(context)->AllowFileAccess(
  238. extension_id);
  239. }
  240. RenderProcessHostPrivilege GetPrivilegeRequiredByUrl(
  241. const GURL& url,
  242. extensions::ExtensionRegistry* registry) {
  243. // Default to a normal renderer cause it is lower privileged. This should only
  244. // occur if the URL on a site instance is either malformed, or uninitialized.
  245. // If it is malformed, then there is no need for better privileges anyways.
  246. // If it is uninitialized, but eventually settles on being an a scheme other
  247. // than normal webrenderer, the navigation logic will correct us out of band
  248. // anyways.
  249. if (!url.is_valid())
  250. return RenderProcessHostPrivilege::kNormal;
  251. if (!url.SchemeIs(extensions::kExtensionScheme))
  252. return RenderProcessHostPrivilege::kNormal;
  253. return RenderProcessHostPrivilege::kExtension;
  254. }
  255. RenderProcessHostPrivilege GetProcessPrivilege(
  256. content::RenderProcessHost* process_host,
  257. extensions::ProcessMap* process_map,
  258. extensions::ExtensionRegistry* registry) {
  259. std::set<std::string> extension_ids =
  260. process_map->GetExtensionsInProcess(process_host->GetID());
  261. if (extension_ids.empty())
  262. return RenderProcessHostPrivilege::kNormal;
  263. return RenderProcessHostPrivilege::kExtension;
  264. }
  265. const extensions::Extension* GetEnabledExtensionFromEffectiveURL(
  266. content::BrowserContext* context,
  267. const GURL& effective_url) {
  268. if (!effective_url.SchemeIs(extensions::kExtensionScheme))
  269. return nullptr;
  270. extensions::ExtensionRegistry* registry =
  271. extensions::ExtensionRegistry::Get(context);
  272. if (!registry)
  273. return nullptr;
  274. return registry->enabled_extensions().GetByID(effective_url.host());
  275. }
  276. #endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  277. #if BUILDFLAG(IS_LINUX)
  278. breakpad::CrashHandlerHostLinux* CreateCrashHandlerHost(
  279. const std::string& process_type) {
  280. base::FilePath dumps_path;
  281. base::PathService::Get(electron::DIR_CRASH_DUMPS, &dumps_path);
  282. {
  283. ANNOTATE_SCOPED_MEMORY_LEAK;
  284. bool upload = ElectronCrashReporterClient::Get()->GetCollectStatsConsent();
  285. breakpad::CrashHandlerHostLinux* crash_handler =
  286. new breakpad::CrashHandlerHostLinux(process_type, dumps_path, upload);
  287. crash_handler->StartUploaderThread();
  288. return crash_handler;
  289. }
  290. }
  291. int GetCrashSignalFD(const base::CommandLine& command_line) {
  292. if (crash_reporter::IsCrashpadEnabled()) {
  293. int fd;
  294. pid_t pid;
  295. return crash_reporter::GetHandlerSocket(&fd, &pid) ? fd : -1;
  296. }
  297. // Extensions have the same process type as renderers.
  298. if (command_line.HasSwitch(extensions::switches::kExtensionProcess)) {
  299. static breakpad::CrashHandlerHostLinux* crash_handler = nullptr;
  300. if (!crash_handler)
  301. crash_handler = CreateCrashHandlerHost("extension");
  302. return crash_handler->GetDeathSignalSocket();
  303. }
  304. std::string process_type =
  305. command_line.GetSwitchValueASCII(::switches::kProcessType);
  306. if (process_type == ::switches::kRendererProcess) {
  307. static breakpad::CrashHandlerHostLinux* crash_handler = nullptr;
  308. if (!crash_handler)
  309. crash_handler = CreateCrashHandlerHost(process_type);
  310. return crash_handler->GetDeathSignalSocket();
  311. }
  312. if (process_type == ::switches::kPpapiPluginProcess) {
  313. static breakpad::CrashHandlerHostLinux* crash_handler = nullptr;
  314. if (!crash_handler)
  315. crash_handler = CreateCrashHandlerHost(process_type);
  316. return crash_handler->GetDeathSignalSocket();
  317. }
  318. if (process_type == ::switches::kGpuProcess) {
  319. static breakpad::CrashHandlerHostLinux* crash_handler = nullptr;
  320. if (!crash_handler)
  321. crash_handler = CreateCrashHandlerHost(process_type);
  322. return crash_handler->GetDeathSignalSocket();
  323. }
  324. if (process_type == ::switches::kUtilityProcess) {
  325. static breakpad::CrashHandlerHostLinux* crash_handler = nullptr;
  326. if (!crash_handler)
  327. crash_handler = CreateCrashHandlerHost(process_type);
  328. return crash_handler->GetDeathSignalSocket();
  329. }
  330. return -1;
  331. }
  332. #endif // BUILDFLAG(IS_LINUX)
  333. void MaybeAppendSecureOriginsAllowlistSwitch(base::CommandLine* cmdline) {
  334. // |allowlist| combines pref/policy + cmdline switch in the browser process.
  335. // For renderer and utility (e.g. NetworkService) processes the switch is the
  336. // only available source, so below the combined (pref/policy + cmdline)
  337. // allowlist of secure origins is injected into |cmdline| for these other
  338. // processes.
  339. std::vector<std::string> allowlist =
  340. network::SecureOriginAllowlist::GetInstance().GetCurrentAllowlist();
  341. if (!allowlist.empty()) {
  342. cmdline->AppendSwitchASCII(
  343. network::switches::kUnsafelyTreatInsecureOriginAsSecure,
  344. base::JoinString(allowlist, ","));
  345. }
  346. }
  347. } // namespace
  348. // static
  349. ElectronBrowserClient* ElectronBrowserClient::Get() {
  350. return g_browser_client;
  351. }
  352. // static
  353. void ElectronBrowserClient::SetApplicationLocale(const std::string& locale) {
  354. if (!BrowserThread::IsThreadInitialized(BrowserThread::IO) ||
  355. !base::PostTask(
  356. FROM_HERE, {BrowserThread::IO},
  357. base::BindOnce(&SetApplicationLocaleOnIOThread, locale))) {
  358. g_io_thread_application_locale.Get() = locale;
  359. }
  360. *g_application_locale = locale;
  361. }
  362. ElectronBrowserClient::ElectronBrowserClient() {
  363. DCHECK(!g_browser_client);
  364. g_browser_client = this;
  365. }
  366. ElectronBrowserClient::~ElectronBrowserClient() {
  367. DCHECK(g_browser_client);
  368. g_browser_client = nullptr;
  369. }
  370. content::WebContents* ElectronBrowserClient::GetWebContentsFromProcessID(
  371. int process_id) {
  372. // If the process is a pending process, we should use the web contents
  373. // for the frame host passed into RegisterPendingProcess.
  374. const auto iter = pending_processes_.find(process_id);
  375. if (iter != std::end(pending_processes_))
  376. return iter->second;
  377. // Certain render process will be created with no associated render view,
  378. // for example: ServiceWorker.
  379. return WebContentsPreferences::GetWebContentsFromProcessID(process_id);
  380. }
  381. content::SiteInstance* ElectronBrowserClient::GetSiteInstanceFromAffinity(
  382. content::BrowserContext* browser_context,
  383. const GURL& url,
  384. content::RenderFrameHost* rfh) const {
  385. return nullptr;
  386. }
  387. bool ElectronBrowserClient::IsRendererSubFrame(int process_id) const {
  388. return base::Contains(renderer_is_subframe_, process_id);
  389. }
  390. void ElectronBrowserClient::RenderProcessWillLaunch(
  391. content::RenderProcessHost* host) {
  392. // When a render process is crashed, it might be reused.
  393. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  394. int process_id = host->GetID();
  395. auto* browser_context = host->GetBrowserContext();
  396. host->AddFilter(
  397. new extensions::ExtensionMessageFilter(process_id, browser_context));
  398. host->AddFilter(
  399. new ElectronExtensionMessageFilter(process_id, browser_context));
  400. host->AddFilter(
  401. new extensions::MessagingAPIMessageFilter(process_id, browser_context));
  402. #endif
  403. // Remove in case the host is reused after a crash, otherwise noop.
  404. host->RemoveObserver(this);
  405. // ensure the ProcessPreferences is removed later
  406. host->AddObserver(this);
  407. }
  408. content::SpeechRecognitionManagerDelegate*
  409. ElectronBrowserClient::CreateSpeechRecognitionManagerDelegate() {
  410. return new ElectronSpeechRecognitionManagerDelegate;
  411. }
  412. content::TtsPlatform* ElectronBrowserClient::GetTtsPlatform() {
  413. return nullptr;
  414. }
  415. void ElectronBrowserClient::OverrideWebkitPrefs(
  416. content::WebContents* web_contents,
  417. blink::web_pref::WebPreferences* prefs) {
  418. prefs->javascript_enabled = true;
  419. prefs->web_security_enabled = true;
  420. prefs->plugins_enabled = true;
  421. prefs->dom_paste_enabled = true;
  422. prefs->allow_scripts_to_close_windows = true;
  423. prefs->javascript_can_access_clipboard = true;
  424. prefs->local_storage_enabled = true;
  425. prefs->databases_enabled = true;
  426. prefs->allow_universal_access_from_file_urls = true;
  427. prefs->allow_file_access_from_file_urls = true;
  428. prefs->webgl1_enabled = true;
  429. prefs->webgl2_enabled = true;
  430. prefs->allow_running_insecure_content = false;
  431. prefs->default_minimum_page_scale_factor = 1.f;
  432. prefs->default_maximum_page_scale_factor = 1.f;
  433. prefs->navigate_on_drag_drop = false;
  434. #if !BUILDFLAG(ENABLE_PICTURE_IN_PICTURE)
  435. prefs->picture_in_picture_enabled = false;
  436. #endif
  437. ui::NativeTheme* native_theme = ui::NativeTheme::GetInstanceForNativeUi();
  438. prefs->preferred_color_scheme =
  439. native_theme->ShouldUseDarkColors()
  440. ? blink::mojom::PreferredColorScheme::kDark
  441. : blink::mojom::PreferredColorScheme::kLight;
  442. auto preloads =
  443. SessionPreferences::GetValidPreloads(web_contents->GetBrowserContext());
  444. if (!preloads.empty())
  445. prefs->preloads = preloads;
  446. SetFontDefaults(prefs);
  447. // Custom preferences of guest page.
  448. auto* web_preferences = WebContentsPreferences::From(web_contents);
  449. if (web_preferences) {
  450. web_preferences->OverrideWebkitPrefs(prefs);
  451. }
  452. }
  453. void ElectronBrowserClient::RegisterPendingSiteInstance(
  454. content::RenderFrameHost* rfh,
  455. content::SiteInstance* pending_site_instance) {
  456. // Remember the original web contents for the pending renderer process.
  457. auto* web_contents = content::WebContents::FromRenderFrameHost(rfh);
  458. auto* pending_process = pending_site_instance->GetProcess();
  459. pending_processes_[pending_process->GetID()] = web_contents;
  460. if (rfh->GetParent())
  461. renderer_is_subframe_.insert(pending_process->GetID());
  462. else
  463. renderer_is_subframe_.erase(pending_process->GetID());
  464. }
  465. void ElectronBrowserClient::AppendExtraCommandLineSwitches(
  466. base::CommandLine* command_line,
  467. int process_id) {
  468. // Make sure we're about to launch a known executable
  469. {
  470. base::ThreadRestrictions::ScopedAllowIO allow_io;
  471. base::FilePath child_path;
  472. base::FilePath program =
  473. base::MakeAbsoluteFilePath(command_line->GetProgram());
  474. #if BUILDFLAG(IS_MAC)
  475. auto renderer_child_path = content::ChildProcessHost::GetChildPath(
  476. content::ChildProcessHost::CHILD_RENDERER);
  477. auto gpu_child_path = content::ChildProcessHost::GetChildPath(
  478. content::ChildProcessHost::CHILD_GPU);
  479. #if BUILDFLAG(ENABLE_PLUGINS)
  480. auto plugin_child_path = content::ChildProcessHost::GetChildPath(
  481. content::ChildProcessHost::CHILD_PLUGIN);
  482. #endif
  483. if (program != renderer_child_path && program != gpu_child_path
  484. #if BUILDFLAG(ENABLE_PLUGINS)
  485. && program != plugin_child_path
  486. #endif
  487. ) {
  488. child_path = content::ChildProcessHost::GetChildPath(
  489. content::ChildProcessHost::CHILD_NORMAL);
  490. CHECK_EQ(program, child_path)
  491. << "Aborted from launching unexpected helper executable";
  492. }
  493. #else
  494. if (!base::PathService::Get(content::CHILD_PROCESS_EXE, &child_path)) {
  495. CHECK(false) << "Unable to get child process binary name.";
  496. }
  497. SCOPED_CRASH_KEY_STRING256("ChildProcess", "child_process_exe",
  498. child_path.AsUTF8Unsafe());
  499. SCOPED_CRASH_KEY_STRING256("ChildProcess", "program",
  500. program.AsUTF8Unsafe());
  501. CHECK_EQ(program, child_path);
  502. #endif
  503. }
  504. std::string process_type =
  505. command_line->GetSwitchValueASCII(::switches::kProcessType);
  506. #if BUILDFLAG(IS_LINUX)
  507. bool enable_crash_reporter = false;
  508. if (crash_reporter::IsCrashpadEnabled()) {
  509. command_line->AppendSwitch(::switches::kEnableCrashpad);
  510. enable_crash_reporter = true;
  511. int fd;
  512. pid_t pid;
  513. if (crash_reporter::GetHandlerSocket(&fd, &pid)) {
  514. command_line->AppendSwitchASCII(
  515. crash_reporter::switches::kCrashpadHandlerPid,
  516. base::NumberToString(pid));
  517. }
  518. } else {
  519. enable_crash_reporter = breakpad::IsCrashReporterEnabled();
  520. }
  521. // Zygote Process gets booted before any JS runs, accessing GetClientId
  522. // will end up touching DIR_USER_DATA path provider and this will
  523. // configure default value because app.name from browser_init has
  524. // not run yet.
  525. if (enable_crash_reporter && process_type != ::switches::kZygoteProcess) {
  526. std::string switch_value =
  527. api::crash_reporter::GetClientId() + ",no_channel";
  528. command_line->AppendSwitchASCII(::switches::kEnableCrashReporter,
  529. switch_value);
  530. if (!crash_reporter::IsCrashpadEnabled()) {
  531. for (const auto& pair : api::crash_reporter::GetGlobalCrashKeys()) {
  532. if (!switch_value.empty())
  533. switch_value += ",";
  534. switch_value += pair.first;
  535. switch_value += "=";
  536. switch_value += pair.second;
  537. }
  538. command_line->AppendSwitchASCII(switches::kGlobalCrashKeys, switch_value);
  539. }
  540. }
  541. #endif
  542. // The zygote process is booted before JS runs, so DIR_USER_DATA isn't usable
  543. // at that time. It doesn't need --user-data-dir to be correct anyway, since
  544. // the zygote itself doesn't access anything in that directory.
  545. if (process_type != ::switches::kZygoteProcess) {
  546. base::FilePath user_data_dir;
  547. if (base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
  548. command_line->AppendSwitchPath(::switches::kUserDataDir, user_data_dir);
  549. }
  550. if (process_type == ::switches::kUtilityProcess ||
  551. process_type == ::switches::kRendererProcess) {
  552. // Copy following switches to child process.
  553. static const char* const kCommonSwitchNames[] = {
  554. switches::kStandardSchemes, switches::kEnableSandbox,
  555. switches::kSecureSchemes, switches::kBypassCSPSchemes,
  556. switches::kCORSSchemes, switches::kFetchSchemes,
  557. switches::kServiceWorkerSchemes, switches::kStreamingSchemes};
  558. command_line->CopySwitchesFrom(*base::CommandLine::ForCurrentProcess(),
  559. kCommonSwitchNames,
  560. std::size(kCommonSwitchNames));
  561. if (process_type == ::switches::kUtilityProcess ||
  562. content::RenderProcessHost::FromID(process_id)) {
  563. MaybeAppendSecureOriginsAllowlistSwitch(command_line);
  564. }
  565. }
  566. if (process_type == ::switches::kRendererProcess) {
  567. #if BUILDFLAG(IS_WIN)
  568. // Append --app-user-model-id.
  569. PWSTR current_app_id;
  570. if (SUCCEEDED(GetCurrentProcessExplicitAppUserModelID(&current_app_id))) {
  571. command_line->AppendSwitchNative(switches::kAppUserModelId,
  572. current_app_id);
  573. CoTaskMemFree(current_app_id);
  574. }
  575. #endif
  576. if (delegate_) {
  577. auto app_path = static_cast<api::App*>(delegate_)->GetAppPath();
  578. command_line->AppendSwitchPath(switches::kAppPath, app_path);
  579. }
  580. auto env = base::Environment::Create();
  581. if (env->HasVar("ELECTRON_PROFILE_INIT_SCRIPTS")) {
  582. command_line->AppendSwitch("profile-electron-init");
  583. }
  584. // Extension background pages don't have WebContentsPreferences, but they
  585. // support WebSQL by default.
  586. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  587. content::RenderProcessHost* process =
  588. content::RenderProcessHost::FromID(process_id);
  589. if (extensions::ProcessMap::Get(process->GetBrowserContext())
  590. ->Contains(process_id))
  591. command_line->AppendSwitch(switches::kEnableWebSQL);
  592. #endif
  593. content::WebContents* web_contents =
  594. GetWebContentsFromProcessID(process_id);
  595. if (web_contents) {
  596. auto* web_preferences = WebContentsPreferences::From(web_contents);
  597. if (web_preferences)
  598. web_preferences->AppendCommandLineSwitches(
  599. command_line, IsRendererSubFrame(process_id));
  600. }
  601. }
  602. }
  603. void ElectronBrowserClient::DidCreatePpapiPlugin(
  604. content::BrowserPpapiHost* host) {}
  605. // attempt to get api key from env
  606. std::string ElectronBrowserClient::GetGeolocationApiKey() {
  607. auto env = base::Environment::Create();
  608. std::string api_key;
  609. env->GetVar("GOOGLE_API_KEY", &api_key);
  610. return api_key;
  611. }
  612. scoped_refptr<content::QuotaPermissionContext>
  613. ElectronBrowserClient::CreateQuotaPermissionContext() {
  614. return base::MakeRefCounted<ElectronQuotaPermissionContext>();
  615. }
  616. content::GeneratedCodeCacheSettings
  617. ElectronBrowserClient::GetGeneratedCodeCacheSettings(
  618. content::BrowserContext* context) {
  619. // TODO(deepak1556): Use platform cache directory.
  620. base::FilePath cache_path = context->GetPath();
  621. // If we pass 0 for size, disk_cache will pick a default size using the
  622. // heuristics based on available disk size. These are implemented in
  623. // disk_cache::PreferredCacheSize in net/disk_cache/cache_util.cc.
  624. return content::GeneratedCodeCacheSettings(true, 0, cache_path);
  625. }
  626. void ElectronBrowserClient::AllowCertificateError(
  627. content::WebContents* web_contents,
  628. int cert_error,
  629. const net::SSLInfo& ssl_info,
  630. const GURL& request_url,
  631. bool is_main_frame_request,
  632. bool strict_enforcement,
  633. base::OnceCallback<void(content::CertificateRequestResultType)> callback) {
  634. if (delegate_) {
  635. delegate_->AllowCertificateError(web_contents, cert_error, ssl_info,
  636. request_url, is_main_frame_request,
  637. strict_enforcement, std::move(callback));
  638. }
  639. }
  640. base::OnceClosure ElectronBrowserClient::SelectClientCertificate(
  641. content::WebContents* web_contents,
  642. net::SSLCertRequestInfo* cert_request_info,
  643. net::ClientCertIdentityList client_certs,
  644. std::unique_ptr<content::ClientCertificateDelegate> delegate) {
  645. if (!client_certs.empty() && delegate_) {
  646. delegate_->SelectClientCertificate(web_contents, cert_request_info,
  647. std::move(client_certs),
  648. std::move(delegate));
  649. }
  650. return base::OnceClosure();
  651. }
  652. bool ElectronBrowserClient::CanCreateWindow(
  653. content::RenderFrameHost* opener,
  654. const GURL& opener_url,
  655. const GURL& opener_top_level_frame_url,
  656. const url::Origin& source_origin,
  657. content::mojom::WindowContainerType container_type,
  658. const GURL& target_url,
  659. const content::Referrer& referrer,
  660. const std::string& frame_name,
  661. WindowOpenDisposition disposition,
  662. const blink::mojom::WindowFeatures& features,
  663. const std::string& raw_features,
  664. const scoped_refptr<network::ResourceRequestBody>& body,
  665. bool user_gesture,
  666. bool opener_suppressed,
  667. bool* no_javascript_access) {
  668. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  669. content::WebContents* web_contents =
  670. content::WebContents::FromRenderFrameHost(opener);
  671. WebContentsPreferences* prefs = WebContentsPreferences::From(web_contents);
  672. if (prefs) {
  673. if (prefs->ShouldDisablePopups()) {
  674. // <webview> without allowpopups attribute should return
  675. // null from window.open calls
  676. return false;
  677. } else {
  678. *no_javascript_access = false;
  679. return true;
  680. }
  681. }
  682. if (delegate_) {
  683. return delegate_->CanCreateWindow(
  684. opener, opener_url, opener_top_level_frame_url, source_origin,
  685. container_type, target_url, referrer, frame_name, disposition, features,
  686. raw_features, body, user_gesture, opener_suppressed,
  687. no_javascript_access);
  688. }
  689. return false;
  690. }
  691. #if BUILDFLAG(ENABLE_PICTURE_IN_PICTURE)
  692. std::unique_ptr<content::VideoOverlayWindow>
  693. ElectronBrowserClient::CreateWindowForVideoPictureInPicture(
  694. content::VideoPictureInPictureWindowController* controller) {
  695. auto overlay_window = content::VideoOverlayWindow::Create(controller);
  696. #if BUILDFLAG(IS_WIN)
  697. std::wstring app_user_model_id = Browser::Get()->GetAppUserModelID();
  698. if (!app_user_model_id.empty()) {
  699. auto* overlay_window_view =
  700. static_cast<VideoOverlayWindowViews*>(overlay_window.get());
  701. ui::win::SetAppIdForWindow(app_user_model_id,
  702. overlay_window_view->GetNativeWindow()
  703. ->GetHost()
  704. ->GetAcceleratedWidget());
  705. }
  706. #endif
  707. return overlay_window;
  708. }
  709. std::unique_ptr<content::DocumentOverlayWindow>
  710. ElectronBrowserClient::CreateWindowForDocumentPictureInPicture(
  711. content::DocumentPictureInPictureWindowController* controller) {
  712. auto overlay_window = content::DocumentOverlayWindow::Create(controller);
  713. #if BUILDFLAG(IS_WIN)
  714. std::wstring app_user_model_id = Browser::Get()->GetAppUserModelID();
  715. if (!app_user_model_id.empty()) {
  716. auto* overlay_window_view =
  717. static_cast<DocumentOverlayWindowViews*>(overlay_window.get());
  718. ui::win::SetAppIdForWindow(app_user_model_id,
  719. overlay_window_view->GetNativeWindow()
  720. ->GetHost()
  721. ->GetAcceleratedWidget());
  722. }
  723. #endif
  724. return overlay_window;
  725. }
  726. #endif
  727. void ElectronBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
  728. std::vector<std::string>* additional_schemes) {
  729. auto schemes_list = api::GetStandardSchemes();
  730. if (!schemes_list.empty())
  731. additional_schemes->insert(additional_schemes->end(), schemes_list.begin(),
  732. schemes_list.end());
  733. additional_schemes->push_back(content::kChromeDevToolsScheme);
  734. additional_schemes->push_back(content::kChromeUIScheme);
  735. }
  736. void ElectronBrowserClient::GetAdditionalWebUISchemes(
  737. std::vector<std::string>* additional_schemes) {
  738. additional_schemes->push_back(content::kChromeDevToolsScheme);
  739. }
  740. void ElectronBrowserClient::SiteInstanceGotProcess(
  741. content::SiteInstance* site_instance) {
  742. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  743. auto* browser_context =
  744. static_cast<ElectronBrowserContext*>(site_instance->GetBrowserContext());
  745. if (!browser_context->IsOffTheRecord()) {
  746. extensions::ExtensionRegistry* registry =
  747. extensions::ExtensionRegistry::Get(browser_context);
  748. const extensions::Extension* extension =
  749. registry->enabled_extensions().GetExtensionOrAppByURL(
  750. site_instance->GetSiteURL());
  751. if (!extension)
  752. return;
  753. extensions::ProcessMap::Get(browser_context)
  754. ->Insert(extension->id(), site_instance->GetProcess()->GetID(),
  755. site_instance->GetId());
  756. }
  757. #endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  758. }
  759. bool ElectronBrowserClient::IsSuitableHost(
  760. content::RenderProcessHost* process_host,
  761. const GURL& site_url) {
  762. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  763. auto* browser_context = process_host->GetBrowserContext();
  764. extensions::ExtensionRegistry* registry =
  765. extensions::ExtensionRegistry::Get(browser_context);
  766. extensions::ProcessMap* process_map =
  767. extensions::ProcessMap::Get(browser_context);
  768. // Otherwise, just make sure the process privilege matches the privilege
  769. // required by the site.
  770. RenderProcessHostPrivilege privilege_required =
  771. GetPrivilegeRequiredByUrl(site_url, registry);
  772. return GetProcessPrivilege(process_host, process_map, registry) ==
  773. privilege_required;
  774. #else
  775. return content::ContentBrowserClient::IsSuitableHost(process_host, site_url);
  776. #endif
  777. }
  778. bool ElectronBrowserClient::ShouldUseProcessPerSite(
  779. content::BrowserContext* browser_context,
  780. const GURL& effective_url) {
  781. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  782. const extensions::Extension* extension =
  783. GetEnabledExtensionFromEffectiveURL(browser_context, effective_url);
  784. return extension != nullptr;
  785. #else
  786. return content::ContentBrowserClient::ShouldUseProcessPerSite(browser_context,
  787. effective_url);
  788. #endif
  789. }
  790. bool ElectronBrowserClient::ArePersistentMediaDeviceIDsAllowed(
  791. content::BrowserContext* browser_context,
  792. const GURL& scope,
  793. const net::SiteForCookies& site_for_cookies,
  794. const absl::optional<url::Origin>& top_frame_origin) {
  795. return true;
  796. }
  797. base::FilePath ElectronBrowserClient::GetLoggingFileName(
  798. const base::CommandLine& cmd_line) {
  799. return logging::GetLogFileName(cmd_line);
  800. }
  801. void ElectronBrowserClient::SiteInstanceDeleting(
  802. content::SiteInstance* site_instance) {
  803. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  804. // Don't do anything if we're shutting down.
  805. if (content::BrowserMainRunner::ExitedMainMessageLoop())
  806. return;
  807. auto* browser_context =
  808. static_cast<ElectronBrowserContext*>(site_instance->GetBrowserContext());
  809. if (!browser_context->IsOffTheRecord()) {
  810. // If this isn't an extension renderer there's nothing to do.
  811. extensions::ExtensionRegistry* registry =
  812. extensions::ExtensionRegistry::Get(browser_context);
  813. const extensions::Extension* extension =
  814. registry->enabled_extensions().GetExtensionOrAppByURL(
  815. site_instance->GetSiteURL());
  816. if (!extension)
  817. return;
  818. extensions::ProcessMap::Get(browser_context)
  819. ->Remove(extension->id(), site_instance->GetProcess()->GetID(),
  820. site_instance->GetId());
  821. }
  822. #endif
  823. }
  824. std::unique_ptr<net::ClientCertStore>
  825. ElectronBrowserClient::CreateClientCertStore(
  826. content::BrowserContext* browser_context) {
  827. #if BUILDFLAG(USE_NSS_CERTS)
  828. return std::make_unique<net::ClientCertStoreNSS>(
  829. net::ClientCertStoreNSS::PasswordDelegateFactory());
  830. #elif BUILDFLAG(IS_WIN)
  831. return std::make_unique<net::ClientCertStoreWin>();
  832. #elif BUILDFLAG(IS_MAC)
  833. return std::make_unique<net::ClientCertStoreMac>();
  834. #elif defined(USE_OPENSSL)
  835. return std::unique_ptr<net::ClientCertStore>();
  836. #endif
  837. }
  838. std::unique_ptr<device::LocationProvider>
  839. ElectronBrowserClient::OverrideSystemLocationProvider() {
  840. #if BUILDFLAG(OVERRIDE_LOCATION_PROVIDER)
  841. return std::make_unique<FakeLocationProvider>();
  842. #else
  843. return nullptr;
  844. #endif
  845. }
  846. void ElectronBrowserClient::ConfigureNetworkContextParams(
  847. content::BrowserContext* browser_context,
  848. bool in_memory,
  849. const base::FilePath& relative_partition_path,
  850. network::mojom::NetworkContextParams* network_context_params,
  851. cert_verifier::mojom::CertVerifierCreationParams*
  852. cert_verifier_creation_params) {
  853. DCHECK(browser_context);
  854. return NetworkContextServiceFactory::GetForContext(browser_context)
  855. ->ConfigureNetworkContextParams(network_context_params,
  856. cert_verifier_creation_params);
  857. }
  858. network::mojom::NetworkContext*
  859. ElectronBrowserClient::GetSystemNetworkContext() {
  860. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  861. DCHECK(g_browser_process->system_network_context_manager());
  862. return g_browser_process->system_network_context_manager()->GetContext();
  863. }
  864. std::unique_ptr<content::BrowserMainParts>
  865. ElectronBrowserClient::CreateBrowserMainParts(
  866. content::MainFunctionParams params) {
  867. auto browser_main_parts =
  868. std::make_unique<ElectronBrowserMainParts>(std::move(params));
  869. #if BUILDFLAG(IS_MAC)
  870. browser_main_parts_ = browser_main_parts.get();
  871. #endif
  872. return browser_main_parts;
  873. }
  874. void ElectronBrowserClient::WebNotificationAllowed(
  875. content::RenderFrameHost* rfh,
  876. base::OnceCallback<void(bool, bool)> callback) {
  877. content::WebContents* web_contents =
  878. content::WebContents::FromRenderFrameHost(rfh);
  879. if (!web_contents) {
  880. std::move(callback).Run(false, false);
  881. return;
  882. }
  883. auto* permission_helper =
  884. WebContentsPermissionHelper::FromWebContents(web_contents);
  885. if (!permission_helper) {
  886. std::move(callback).Run(false, false);
  887. return;
  888. }
  889. permission_helper->RequestWebNotificationPermission(
  890. rfh, base::BindOnce(std::move(callback), web_contents->IsAudioMuted()));
  891. }
  892. void ElectronBrowserClient::RenderProcessHostDestroyed(
  893. content::RenderProcessHost* host) {
  894. int process_id = host->GetID();
  895. pending_processes_.erase(process_id);
  896. renderer_is_subframe_.erase(process_id);
  897. host->RemoveObserver(this);
  898. }
  899. void ElectronBrowserClient::RenderProcessReady(
  900. content::RenderProcessHost* host) {
  901. if (delegate_) {
  902. static_cast<api::App*>(delegate_)->RenderProcessReady(host);
  903. }
  904. }
  905. void ElectronBrowserClient::RenderProcessExited(
  906. content::RenderProcessHost* host,
  907. const content::ChildProcessTerminationInfo& info) {
  908. if (delegate_) {
  909. static_cast<api::App*>(delegate_)->RenderProcessExited(host);
  910. }
  911. }
  912. void OnOpenExternal(const GURL& escaped_url, bool allowed) {
  913. if (allowed) {
  914. platform_util::OpenExternal(
  915. escaped_url, platform_util::OpenExternalOptions(), base::DoNothing());
  916. }
  917. }
  918. void HandleExternalProtocolInUI(
  919. const GURL& url,
  920. content::WeakDocumentPtr document_ptr,
  921. content::WebContents::OnceGetter web_contents_getter,
  922. bool has_user_gesture) {
  923. content::WebContents* web_contents = std::move(web_contents_getter).Run();
  924. if (!web_contents)
  925. return;
  926. auto* permission_helper =
  927. WebContentsPermissionHelper::FromWebContents(web_contents);
  928. if (!permission_helper)
  929. return;
  930. content::RenderFrameHost* rfh = document_ptr.AsRenderFrameHostIfValid();
  931. if (!rfh) {
  932. // If the render frame host is not valid it means it was a top level
  933. // navigation and the frame has already been disposed of. In this case we
  934. // take the current main frame and declare it responsible for the
  935. // transition.
  936. rfh = web_contents->GetMainFrame();
  937. }
  938. GURL escaped_url(net::EscapeExternalHandlerValue(url.spec()));
  939. auto callback = base::BindOnce(&OnOpenExternal, escaped_url);
  940. permission_helper->RequestOpenExternalPermission(rfh, std::move(callback),
  941. has_user_gesture, url);
  942. }
  943. bool ElectronBrowserClient::HandleExternalProtocol(
  944. const GURL& url,
  945. content::WebContents::Getter web_contents_getter,
  946. int frame_tree_node_id,
  947. content::NavigationUIData* navigation_data,
  948. bool is_primary_main_frame,
  949. bool is_in_fenced_frame_tree,
  950. network::mojom::WebSandboxFlags sandbox_flags,
  951. ui::PageTransition page_transition,
  952. bool has_user_gesture,
  953. const absl::optional<url::Origin>& initiating_origin,
  954. content::RenderFrameHost* initiator_document,
  955. mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory) {
  956. base::PostTask(
  957. FROM_HERE, {BrowserThread::UI},
  958. base::BindOnce(&HandleExternalProtocolInUI, url,
  959. initiator_document
  960. ? initiator_document->GetWeakDocumentPtr()
  961. : content::WeakDocumentPtr(),
  962. std::move(web_contents_getter), has_user_gesture));
  963. return true;
  964. }
  965. std::vector<std::unique_ptr<content::NavigationThrottle>>
  966. ElectronBrowserClient::CreateThrottlesForNavigation(
  967. content::NavigationHandle* handle) {
  968. std::vector<std::unique_ptr<content::NavigationThrottle>> throttles;
  969. throttles.push_back(std::make_unique<ElectronNavigationThrottle>(handle));
  970. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  971. throttles.push_back(
  972. std::make_unique<extensions::ExtensionNavigationThrottle>(handle));
  973. #endif
  974. #if BUILDFLAG(ENABLE_PDF_VIEWER)
  975. std::unique_ptr<content::NavigationThrottle> pdf_iframe_throttle =
  976. PDFIFrameNavigationThrottle::MaybeCreateThrottleFor(handle);
  977. if (pdf_iframe_throttle)
  978. throttles.push_back(std::move(pdf_iframe_throttle));
  979. std::unique_ptr<content::NavigationThrottle> pdf_throttle =
  980. pdf::PdfNavigationThrottle::MaybeCreateThrottleFor(
  981. handle, std::make_unique<ChromePdfStreamDelegate>());
  982. if (pdf_throttle)
  983. throttles.push_back(std::move(pdf_throttle));
  984. #endif
  985. return throttles;
  986. }
  987. content::MediaObserver* ElectronBrowserClient::GetMediaObserver() {
  988. return MediaCaptureDevicesDispatcher::GetInstance();
  989. }
  990. std::unique_ptr<content::DevToolsManagerDelegate>
  991. ElectronBrowserClient::CreateDevToolsManagerDelegate() {
  992. return std::make_unique<DevToolsManagerDelegate>();
  993. }
  994. NotificationPresenter* ElectronBrowserClient::GetNotificationPresenter() {
  995. if (!notification_presenter_) {
  996. notification_presenter_.reset(NotificationPresenter::Create());
  997. }
  998. return notification_presenter_.get();
  999. }
  1000. content::PlatformNotificationService*
  1001. ElectronBrowserClient::GetPlatformNotificationService() {
  1002. if (!notification_service_) {
  1003. notification_service_ = std::make_unique<PlatformNotificationService>(this);
  1004. }
  1005. return notification_service_.get();
  1006. }
  1007. base::FilePath ElectronBrowserClient::GetDefaultDownloadDirectory() {
  1008. base::FilePath download_path;
  1009. if (base::PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &download_path))
  1010. return download_path;
  1011. return base::FilePath();
  1012. }
  1013. scoped_refptr<network::SharedURLLoaderFactory>
  1014. ElectronBrowserClient::GetSystemSharedURLLoaderFactory() {
  1015. if (!g_browser_process)
  1016. return nullptr;
  1017. return g_browser_process->shared_url_loader_factory();
  1018. }
  1019. void ElectronBrowserClient::OnNetworkServiceCreated(
  1020. network::mojom::NetworkService* network_service) {
  1021. if (!g_browser_process)
  1022. return;
  1023. g_browser_process->system_network_context_manager()->OnNetworkServiceCreated(
  1024. network_service);
  1025. }
  1026. std::vector<base::FilePath>
  1027. ElectronBrowserClient::GetNetworkContextsParentDirectory() {
  1028. base::FilePath user_data_dir;
  1029. base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
  1030. DCHECK(!user_data_dir.empty());
  1031. return {user_data_dir};
  1032. }
  1033. std::string ElectronBrowserClient::GetProduct() {
  1034. return "Chrome/" CHROME_VERSION_STRING;
  1035. }
  1036. std::string ElectronBrowserClient::GetUserAgent() {
  1037. if (user_agent_override_.empty())
  1038. return GetApplicationUserAgent();
  1039. return user_agent_override_;
  1040. }
  1041. void ElectronBrowserClient::SetUserAgent(const std::string& user_agent) {
  1042. user_agent_override_ = user_agent;
  1043. }
  1044. blink::UserAgentMetadata ElectronBrowserClient::GetUserAgentMetadata() {
  1045. return embedder_support::GetUserAgentMetadata();
  1046. }
  1047. void ElectronBrowserClient::RegisterNonNetworkNavigationURLLoaderFactories(
  1048. int frame_tree_node_id,
  1049. ukm::SourceIdObj ukm_source_id,
  1050. NonNetworkURLLoaderFactoryMap* factories) {
  1051. content::WebContents* web_contents =
  1052. content::WebContents::FromFrameTreeNodeId(frame_tree_node_id);
  1053. content::BrowserContext* context = web_contents->GetBrowserContext();
  1054. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1055. factories->emplace(
  1056. extensions::kExtensionScheme,
  1057. extensions::CreateExtensionNavigationURLLoaderFactory(
  1058. context, ukm_source_id,
  1059. false /* we don't support extensions::WebViewGuest */));
  1060. #endif
  1061. // Always allow navigating to file:// URLs.
  1062. auto* protocol_registry = ProtocolRegistry::FromBrowserContext(context);
  1063. protocol_registry->RegisterURLLoaderFactories(factories,
  1064. true /* allow_file_access */);
  1065. }
  1066. void ElectronBrowserClient::
  1067. RegisterNonNetworkWorkerMainResourceURLLoaderFactories(
  1068. content::BrowserContext* browser_context,
  1069. NonNetworkURLLoaderFactoryMap* factories) {
  1070. auto* protocol_registry =
  1071. ProtocolRegistry::FromBrowserContext(browser_context);
  1072. // Workers are not allowed to request file:// URLs, there is no particular
  1073. // reason for it, and we could consider supporting it in future.
  1074. protocol_registry->RegisterURLLoaderFactories(factories,
  1075. false /* allow_file_access */);
  1076. }
  1077. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1078. namespace {
  1079. // The FileURLLoaderFactory provided to the extension background pages.
  1080. // Checks with the ChildProcessSecurityPolicy to validate the file access.
  1081. class FileURLLoaderFactory : public network::SelfDeletingURLLoaderFactory {
  1082. public:
  1083. static mojo::PendingRemote<network::mojom::URLLoaderFactory> Create(
  1084. int child_id) {
  1085. mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_remote;
  1086. // The FileURLLoaderFactory will delete itself when there are no more
  1087. // receivers - see the SelfDeletingURLLoaderFactory::OnDisconnect method.
  1088. new FileURLLoaderFactory(child_id,
  1089. pending_remote.InitWithNewPipeAndPassReceiver());
  1090. return pending_remote;
  1091. }
  1092. // disable copy
  1093. FileURLLoaderFactory(const FileURLLoaderFactory&) = delete;
  1094. FileURLLoaderFactory& operator=(const FileURLLoaderFactory&) = delete;
  1095. private:
  1096. explicit FileURLLoaderFactory(
  1097. int child_id,
  1098. mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver)
  1099. : network::SelfDeletingURLLoaderFactory(std::move(factory_receiver)),
  1100. child_id_(child_id) {}
  1101. ~FileURLLoaderFactory() override = default;
  1102. // network::mojom::URLLoaderFactory:
  1103. void CreateLoaderAndStart(
  1104. mojo::PendingReceiver<network::mojom::URLLoader> loader,
  1105. int32_t request_id,
  1106. uint32_t options,
  1107. const network::ResourceRequest& request,
  1108. mojo::PendingRemote<network::mojom::URLLoaderClient> client,
  1109. const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
  1110. override {
  1111. if (!content::ChildProcessSecurityPolicy::GetInstance()->CanRequestURL(
  1112. child_id_, request.url)) {
  1113. mojo::Remote<network::mojom::URLLoaderClient>(std::move(client))
  1114. ->OnComplete(
  1115. network::URLLoaderCompletionStatus(net::ERR_ACCESS_DENIED));
  1116. return;
  1117. }
  1118. content::CreateFileURLLoaderBypassingSecurityChecks(
  1119. request, std::move(loader), std::move(client),
  1120. /*observer=*/nullptr,
  1121. /* allow_directory_listing */ true);
  1122. }
  1123. int child_id_;
  1124. };
  1125. } // namespace
  1126. #endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1127. void ElectronBrowserClient::RegisterNonNetworkSubresourceURLLoaderFactories(
  1128. int render_process_id,
  1129. int render_frame_id,
  1130. const absl::optional<url::Origin>& request_initiator_origin,
  1131. NonNetworkURLLoaderFactoryMap* factories) {
  1132. auto* render_process_host =
  1133. content::RenderProcessHost::FromID(render_process_id);
  1134. DCHECK(render_process_host);
  1135. if (!render_process_host || !render_process_host->GetBrowserContext())
  1136. return;
  1137. content::RenderFrameHost* frame_host =
  1138. content::RenderFrameHost::FromID(render_process_id, render_frame_id);
  1139. content::WebContents* web_contents =
  1140. content::WebContents::FromRenderFrameHost(frame_host);
  1141. // Allow accessing file:// subresources from non-file protocols if web
  1142. // security is disabled.
  1143. bool allow_file_access = false;
  1144. if (web_contents) {
  1145. const auto& web_preferences = web_contents->GetOrCreateWebPreferences();
  1146. if (!web_preferences.web_security_enabled)
  1147. allow_file_access = true;
  1148. }
  1149. ProtocolRegistry::FromBrowserContext(render_process_host->GetBrowserContext())
  1150. ->RegisterURLLoaderFactories(factories, allow_file_access);
  1151. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1152. auto factory = extensions::CreateExtensionURLLoaderFactory(render_process_id,
  1153. render_frame_id);
  1154. if (factory)
  1155. factories->emplace(extensions::kExtensionScheme, std::move(factory));
  1156. if (!web_contents)
  1157. return;
  1158. extensions::ElectronExtensionWebContentsObserver* web_observer =
  1159. extensions::ElectronExtensionWebContentsObserver::FromWebContents(
  1160. web_contents);
  1161. // There is nothing to do if no ElectronExtensionWebContentsObserver is
  1162. // attached to the |web_contents|.
  1163. if (!web_observer)
  1164. return;
  1165. const extensions::Extension* extension =
  1166. web_observer->GetExtensionFromFrame(frame_host, false);
  1167. if (!extension)
  1168. return;
  1169. // Support for chrome:// scheme if appropriate.
  1170. if (extension->is_extension() &&
  1171. extensions::Manifest::IsComponentLocation(extension->location())) {
  1172. // Components of chrome that are implemented as extensions or platform apps
  1173. // are allowed to use chrome://resources/ and chrome://theme/ URLs.
  1174. factories->emplace(content::kChromeUIScheme,
  1175. content::CreateWebUIURLLoaderFactory(
  1176. frame_host, content::kChromeUIScheme,
  1177. {content::kChromeUIResourcesHost}));
  1178. }
  1179. // Extensions with the necessary permissions get access to file:// URLs that
  1180. // gets approval from ChildProcessSecurityPolicy. Keep this logic in sync with
  1181. // ExtensionWebContentsObserver::RenderFrameCreated.
  1182. extensions::Manifest::Type type = extension->GetType();
  1183. if (type == extensions::Manifest::TYPE_EXTENSION &&
  1184. AllowFileAccess(extension->id(), web_contents->GetBrowserContext())) {
  1185. factories->emplace(url::kFileScheme,
  1186. FileURLLoaderFactory::Create(render_process_id));
  1187. }
  1188. #endif
  1189. }
  1190. void ElectronBrowserClient::
  1191. RegisterNonNetworkServiceWorkerUpdateURLLoaderFactories(
  1192. content::BrowserContext* browser_context,
  1193. NonNetworkURLLoaderFactoryMap* factories) {
  1194. DCHECK(browser_context);
  1195. DCHECK(factories);
  1196. auto* protocol_registry =
  1197. ProtocolRegistry::FromBrowserContext(browser_context);
  1198. protocol_registry->RegisterURLLoaderFactories(factories,
  1199. false /* allow_file_access */);
  1200. #if BUILDFLAG(ENABLE_EXTENSIONS)
  1201. factories->emplace(
  1202. extensions::kExtensionScheme,
  1203. extensions::CreateExtensionServiceWorkerScriptURLLoaderFactory(
  1204. browser_context));
  1205. #endif // BUILDFLAG(ENABLE_EXTENSIONS)
  1206. }
  1207. bool ElectronBrowserClient::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
  1208. base::StringPiece scheme,
  1209. bool is_embedded_origin_secure) {
  1210. if (is_embedded_origin_secure && scheme == content::kChromeUIScheme)
  1211. return true;
  1212. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1213. return scheme == extensions::kExtensionScheme;
  1214. #else
  1215. return false;
  1216. #endif
  1217. }
  1218. bool ElectronBrowserClient::WillInterceptWebSocket(
  1219. content::RenderFrameHost* frame) {
  1220. if (!frame)
  1221. return false;
  1222. v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
  1223. v8::HandleScope scope(isolate);
  1224. auto* browser_context = frame->GetProcess()->GetBrowserContext();
  1225. auto web_request = api::WebRequest::FromOrCreate(isolate, browser_context);
  1226. // NOTE: Some unit test environments do not initialize
  1227. // BrowserContextKeyedAPI factories for e.g. WebRequest.
  1228. if (!web_request.get())
  1229. return false;
  1230. bool has_listener = web_request->HasListener();
  1231. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1232. const auto* web_request_api =
  1233. extensions::BrowserContextKeyedAPIFactory<extensions::WebRequestAPI>::Get(
  1234. browser_context);
  1235. if (web_request_api)
  1236. has_listener |= web_request_api->MayHaveProxies();
  1237. #endif
  1238. return has_listener;
  1239. }
  1240. void ElectronBrowserClient::CreateWebSocket(
  1241. content::RenderFrameHost* frame,
  1242. WebSocketFactory factory,
  1243. const GURL& url,
  1244. const net::SiteForCookies& site_for_cookies,
  1245. const absl::optional<std::string>& user_agent,
  1246. mojo::PendingRemote<network::mojom::WebSocketHandshakeClient>
  1247. handshake_client) {
  1248. v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
  1249. v8::HandleScope scope(isolate);
  1250. auto* browser_context = frame->GetProcess()->GetBrowserContext();
  1251. auto web_request = api::WebRequest::FromOrCreate(isolate, browser_context);
  1252. DCHECK(web_request.get());
  1253. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1254. if (!web_request->HasListener()) {
  1255. auto* web_request_api = extensions::BrowserContextKeyedAPIFactory<
  1256. extensions::WebRequestAPI>::Get(browser_context);
  1257. if (web_request_api && web_request_api->MayHaveProxies()) {
  1258. web_request_api->ProxyWebSocket(frame, std::move(factory), url,
  1259. site_for_cookies, user_agent,
  1260. std::move(handshake_client));
  1261. return;
  1262. }
  1263. }
  1264. #endif
  1265. ProxyingWebSocket::StartProxying(
  1266. web_request.get(), std::move(factory), url, site_for_cookies, user_agent,
  1267. std::move(handshake_client), true, frame->GetProcess()->GetID(),
  1268. frame->GetRoutingID(), frame->GetLastCommittedOrigin(), browser_context,
  1269. &next_id_);
  1270. }
  1271. bool ElectronBrowserClient::WillCreateURLLoaderFactory(
  1272. content::BrowserContext* browser_context,
  1273. content::RenderFrameHost* frame_host,
  1274. int render_process_id,
  1275. URLLoaderFactoryType type,
  1276. const url::Origin& request_initiator,
  1277. absl::optional<int64_t> navigation_id,
  1278. ukm::SourceIdObj ukm_source_id,
  1279. mojo::PendingReceiver<network::mojom::URLLoaderFactory>* factory_receiver,
  1280. mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>*
  1281. header_client,
  1282. bool* bypass_redirect_checks,
  1283. bool* disable_secure_dns,
  1284. network::mojom::URLLoaderFactoryOverridePtr* factory_override) {
  1285. v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
  1286. v8::HandleScope scope(isolate);
  1287. auto web_request = api::WebRequest::FromOrCreate(isolate, browser_context);
  1288. DCHECK(web_request.get());
  1289. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1290. if (!web_request->HasListener()) {
  1291. auto* web_request_api = extensions::BrowserContextKeyedAPIFactory<
  1292. extensions::WebRequestAPI>::Get(browser_context);
  1293. DCHECK(web_request_api);
  1294. bool use_proxy_for_web_request =
  1295. web_request_api->MaybeProxyURLLoaderFactory(
  1296. browser_context, frame_host, render_process_id, type, navigation_id,
  1297. ukm_source_id, factory_receiver, header_client);
  1298. if (bypass_redirect_checks)
  1299. *bypass_redirect_checks = use_proxy_for_web_request;
  1300. if (use_proxy_for_web_request)
  1301. return true;
  1302. }
  1303. #endif
  1304. auto proxied_receiver = std::move(*factory_receiver);
  1305. mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory_remote;
  1306. *factory_receiver = target_factory_remote.InitWithNewPipeAndPassReceiver();
  1307. // Required by WebRequestInfoInitParams.
  1308. //
  1309. // Note that in Electron we allow webRequest to capture requests sent from
  1310. // browser process, so creation of |navigation_ui_data| is different from
  1311. // Chromium which only does for renderer-initialized navigations.
  1312. std::unique_ptr<extensions::ExtensionNavigationUIData> navigation_ui_data;
  1313. if (navigation_id.has_value()) {
  1314. navigation_ui_data =
  1315. std::make_unique<extensions::ExtensionNavigationUIData>();
  1316. }
  1317. mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient>
  1318. header_client_receiver;
  1319. if (header_client)
  1320. header_client_receiver = header_client->InitWithNewPipeAndPassReceiver();
  1321. auto* protocol_registry =
  1322. ProtocolRegistry::FromBrowserContext(browser_context);
  1323. new ProxyingURLLoaderFactory(
  1324. web_request.get(), protocol_registry->intercept_handlers(),
  1325. render_process_id,
  1326. frame_host ? frame_host->GetRoutingID() : MSG_ROUTING_NONE, &next_id_,
  1327. std::move(navigation_ui_data), std::move(navigation_id),
  1328. std::move(proxied_receiver), std::move(target_factory_remote),
  1329. std::move(header_client_receiver), type);
  1330. return true;
  1331. }
  1332. std::vector<std::unique_ptr<content::URLLoaderRequestInterceptor>>
  1333. ElectronBrowserClient::WillCreateURLLoaderRequestInterceptors(
  1334. content::NavigationUIData* navigation_ui_data,
  1335. int frame_tree_node_id,
  1336. const scoped_refptr<network::SharedURLLoaderFactory>&
  1337. network_loader_factory) {
  1338. std::vector<std::unique_ptr<content::URLLoaderRequestInterceptor>>
  1339. interceptors;
  1340. #if BUILDFLAG(ENABLE_PDF_VIEWER)
  1341. {
  1342. std::unique_ptr<content::URLLoaderRequestInterceptor> pdf_interceptor =
  1343. pdf::PdfURLLoaderRequestInterceptor::MaybeCreateInterceptor(
  1344. frame_tree_node_id, std::make_unique<ChromePdfStreamDelegate>());
  1345. if (pdf_interceptor)
  1346. interceptors.push_back(std::move(pdf_interceptor));
  1347. }
  1348. #endif
  1349. return interceptors;
  1350. }
  1351. void ElectronBrowserClient::OverrideURLLoaderFactoryParams(
  1352. content::BrowserContext* browser_context,
  1353. const url::Origin& origin,
  1354. bool is_for_isolated_world,
  1355. network::mojom::URLLoaderFactoryParams* factory_params) {
  1356. if (factory_params->top_frame_id) {
  1357. // Bypass CORB and CORS when web security is disabled.
  1358. auto* rfh = content::RenderFrameHost::FromFrameToken(
  1359. factory_params->process_id,
  1360. blink::LocalFrameToken(factory_params->top_frame_id.value()));
  1361. auto* web_contents = content::WebContents::FromRenderFrameHost(rfh);
  1362. auto* prefs = WebContentsPreferences::From(web_contents);
  1363. if (prefs && !prefs->IsWebSecurityEnabled()) {
  1364. factory_params->is_corb_enabled = false;
  1365. factory_params->disable_web_security = true;
  1366. }
  1367. }
  1368. extensions::URLLoaderFactoryManager::OverrideURLLoaderFactoryParams(
  1369. browser_context, origin, is_for_isolated_world, factory_params);
  1370. }
  1371. #if BUILDFLAG(IS_WIN)
  1372. bool ElectronBrowserClient::PreSpawnChild(sandbox::TargetPolicy* policy,
  1373. sandbox::mojom::Sandbox sandbox_type,
  1374. ChildSpawnFlags flags) {
  1375. // Allow crashpad to communicate via named pipe.
  1376. sandbox::ResultCode result = policy->AddRule(
  1377. sandbox::TargetPolicy::SUBSYS_FILES,
  1378. sandbox::TargetPolicy::FILES_ALLOW_ANY, L"\\??\\pipe\\crashpad_*");
  1379. if (result != sandbox::SBOX_ALL_OK)
  1380. return false;
  1381. return true;
  1382. }
  1383. #endif // BUILDFLAG(IS_WIN)
  1384. void ElectronBrowserClient::
  1385. RegisterAssociatedInterfaceBindersForRenderFrameHost(
  1386. content::RenderFrameHost&
  1387. render_frame_host, // NOLINT(runtime/references)
  1388. blink::AssociatedInterfaceRegistry&
  1389. associated_registry) { // NOLINT(runtime/references)
  1390. auto* contents =
  1391. content::WebContents::FromRenderFrameHost(&render_frame_host);
  1392. if (contents) {
  1393. auto* prefs = WebContentsPreferences::From(contents);
  1394. if (render_frame_host.GetFrameTreeNodeId() ==
  1395. contents->GetMainFrame()->GetFrameTreeNodeId() ||
  1396. (prefs && prefs->AllowsNodeIntegrationInSubFrames())) {
  1397. associated_registry.AddInterface(base::BindRepeating(
  1398. [](content::RenderFrameHost* render_frame_host,
  1399. mojo::PendingAssociatedReceiver<electron::mojom::ElectronApiIPC>
  1400. receiver) {
  1401. ElectronApiIPCHandlerImpl::Create(render_frame_host,
  1402. std::move(receiver));
  1403. },
  1404. &render_frame_host));
  1405. }
  1406. }
  1407. associated_registry.AddInterface(base::BindRepeating(
  1408. [](content::RenderFrameHost* render_frame_host,
  1409. mojo::PendingAssociatedReceiver<
  1410. electron::mojom::ElectronWebContentsUtility> receiver) {
  1411. ElectronWebContentsUtilityHandlerImpl::Create(render_frame_host,
  1412. std::move(receiver));
  1413. },
  1414. &render_frame_host));
  1415. associated_registry.AddInterface(base::BindRepeating(
  1416. [](content::RenderFrameHost* render_frame_host,
  1417. mojo::PendingAssociatedReceiver<mojom::ElectronAutofillDriver>
  1418. receiver) {
  1419. AutofillDriverFactory::BindAutofillDriver(std::move(receiver),
  1420. render_frame_host);
  1421. },
  1422. &render_frame_host));
  1423. #if BUILDFLAG(ENABLE_PRINTING)
  1424. associated_registry.AddInterface(base::BindRepeating(
  1425. [](content::RenderFrameHost* render_frame_host,
  1426. mojo::PendingAssociatedReceiver<printing::mojom::PrintManagerHost>
  1427. receiver) {
  1428. PrintViewManagerElectron::BindPrintManagerHost(std::move(receiver),
  1429. render_frame_host);
  1430. },
  1431. &render_frame_host));
  1432. #endif
  1433. #if BUILDFLAG(ENABLE_EXTENSIONS)
  1434. associated_registry.AddInterface(base::BindRepeating(
  1435. [](content::RenderFrameHost* render_frame_host,
  1436. mojo::PendingAssociatedReceiver<extensions::mojom::LocalFrameHost>
  1437. receiver) {
  1438. extensions::ExtensionWebContentsObserver::BindLocalFrameHost(
  1439. std::move(receiver), render_frame_host);
  1440. },
  1441. &render_frame_host));
  1442. #endif
  1443. #if BUILDFLAG(ENABLE_PDF_VIEWER)
  1444. associated_registry.AddInterface(base::BindRepeating(
  1445. [](content::RenderFrameHost* render_frame_host,
  1446. mojo::PendingAssociatedReceiver<pdf::mojom::PdfService> receiver) {
  1447. pdf::PDFWebContentsHelper::BindPdfService(std::move(receiver),
  1448. render_frame_host);
  1449. },
  1450. &render_frame_host));
  1451. #endif
  1452. }
  1453. std::string ElectronBrowserClient::GetApplicationLocale() {
  1454. if (BrowserThread::CurrentlyOn(BrowserThread::IO))
  1455. return g_io_thread_application_locale.Get();
  1456. return *g_application_locale;
  1457. }
  1458. base::FilePath ElectronBrowserClient::GetFontLookupTableCacheDir() {
  1459. base::FilePath user_data_dir;
  1460. base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
  1461. DCHECK(!user_data_dir.empty());
  1462. return user_data_dir.Append(FILE_PATH_LITERAL("FontLookupTableCache"));
  1463. }
  1464. bool ElectronBrowserClient::ShouldEnableStrictSiteIsolation() {
  1465. // Enable site isolation. It is off by default in Chromium <= 69.
  1466. return true;
  1467. }
  1468. void ElectronBrowserClient::BindHostReceiverForRenderer(
  1469. content::RenderProcessHost* render_process_host,
  1470. mojo::GenericPendingReceiver receiver) {
  1471. #if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
  1472. if (auto host_receiver = receiver.As<spellcheck::mojom::SpellCheckHost>()) {
  1473. SpellCheckHostChromeImpl::Create(render_process_host->GetID(),
  1474. std::move(host_receiver));
  1475. return;
  1476. }
  1477. #endif
  1478. }
  1479. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1480. void BindMimeHandlerService(
  1481. content::RenderFrameHost* frame_host,
  1482. mojo::PendingReceiver<extensions::mime_handler::MimeHandlerService>
  1483. receiver) {
  1484. content::WebContents* contents =
  1485. content::WebContents::FromRenderFrameHost(frame_host);
  1486. auto* guest_view =
  1487. extensions::MimeHandlerViewGuest::FromWebContents(contents);
  1488. if (!guest_view)
  1489. return;
  1490. extensions::MimeHandlerServiceImpl::Create(guest_view->GetStreamWeakPtr(),
  1491. std::move(receiver));
  1492. }
  1493. void BindBeforeUnloadControl(
  1494. content::RenderFrameHost* frame_host,
  1495. mojo::PendingReceiver<extensions::mime_handler::BeforeUnloadControl>
  1496. receiver) {
  1497. auto* web_contents = content::WebContents::FromRenderFrameHost(frame_host);
  1498. if (!web_contents)
  1499. return;
  1500. auto* guest_view =
  1501. extensions::MimeHandlerViewGuest::FromWebContents(web_contents);
  1502. if (!guest_view)
  1503. return;
  1504. guest_view->FuseBeforeUnloadControl(std::move(receiver));
  1505. }
  1506. #endif
  1507. void ElectronBrowserClient::ExposeInterfacesToRenderer(
  1508. service_manager::BinderRegistry* registry,
  1509. blink::AssociatedInterfaceRegistry* associated_registry,
  1510. content::RenderProcessHost* render_process_host) {
  1511. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1512. associated_registry->AddInterface(base::BindRepeating(
  1513. &extensions::EventRouter::BindForRenderer, render_process_host->GetID()));
  1514. associated_registry->AddInterface(
  1515. base::BindRepeating(&extensions::ExtensionsGuestView::CreateForExtensions,
  1516. render_process_host->GetID()));
  1517. #endif
  1518. }
  1519. void ElectronBrowserClient::RegisterBrowserInterfaceBindersForFrame(
  1520. content::RenderFrameHost* render_frame_host,
  1521. mojo::BinderMapWithContext<content::RenderFrameHost*>* map) {
  1522. map->Add<network_hints::mojom::NetworkHintsHandler>(
  1523. base::BindRepeating(&BindNetworkHintsHandler));
  1524. map->Add<blink::mojom::BadgeService>(
  1525. base::BindRepeating(&badging::BadgeManager::BindFrameReceiver));
  1526. map->Add<blink::mojom::KeyboardLockService>(base::BindRepeating(
  1527. &content::KeyboardLockServiceImpl::CreateMojoService));
  1528. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1529. map->Add<extensions::mime_handler::MimeHandlerService>(
  1530. base::BindRepeating(&BindMimeHandlerService));
  1531. map->Add<extensions::mime_handler::BeforeUnloadControl>(
  1532. base::BindRepeating(&BindBeforeUnloadControl));
  1533. content::WebContents* web_contents =
  1534. content::WebContents::FromRenderFrameHost(render_frame_host);
  1535. if (!web_contents)
  1536. return;
  1537. const GURL& site = render_frame_host->GetSiteInstance()->GetSiteURL();
  1538. if (!site.SchemeIs(extensions::kExtensionScheme))
  1539. return;
  1540. content::BrowserContext* browser_context =
  1541. render_frame_host->GetProcess()->GetBrowserContext();
  1542. auto* extension = extensions::ExtensionRegistry::Get(browser_context)
  1543. ->enabled_extensions()
  1544. .GetByID(site.host());
  1545. if (!extension)
  1546. return;
  1547. extensions::ExtensionsBrowserClient::Get()
  1548. ->RegisterBrowserInterfaceBindersForFrame(map, render_frame_host,
  1549. extension);
  1550. #endif
  1551. }
  1552. #if BUILDFLAG(IS_LINUX)
  1553. void ElectronBrowserClient::GetAdditionalMappedFilesForChildProcess(
  1554. const base::CommandLine& command_line,
  1555. int child_process_id,
  1556. content::PosixFileDescriptorInfo* mappings) {
  1557. int crash_signal_fd = GetCrashSignalFD(command_line);
  1558. if (crash_signal_fd >= 0) {
  1559. mappings->Share(kCrashDumpSignal, crash_signal_fd);
  1560. }
  1561. }
  1562. #endif
  1563. std::unique_ptr<content::LoginDelegate>
  1564. ElectronBrowserClient::CreateLoginDelegate(
  1565. const net::AuthChallengeInfo& auth_info,
  1566. content::WebContents* web_contents,
  1567. const content::GlobalRequestID& request_id,
  1568. bool is_main_frame,
  1569. const GURL& url,
  1570. scoped_refptr<net::HttpResponseHeaders> response_headers,
  1571. bool first_auth_attempt,
  1572. LoginAuthRequiredCallback auth_required_callback) {
  1573. return std::make_unique<LoginHandler>(
  1574. auth_info, web_contents, is_main_frame, url, response_headers,
  1575. first_auth_attempt, std::move(auth_required_callback));
  1576. }
  1577. std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
  1578. ElectronBrowserClient::CreateURLLoaderThrottles(
  1579. const network::ResourceRequest& request,
  1580. content::BrowserContext* browser_context,
  1581. const base::RepeatingCallback<content::WebContents*()>& wc_getter,
  1582. content::NavigationUIData* navigation_ui_data,
  1583. int frame_tree_node_id) {
  1584. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  1585. std::vector<std::unique_ptr<blink::URLLoaderThrottle>> result;
  1586. #if BUILDFLAG(ENABLE_PLUGINS) && BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1587. result.push_back(std::make_unique<PluginResponseInterceptorURLLoaderThrottle>(
  1588. request.destination, frame_tree_node_id));
  1589. #endif
  1590. return result;
  1591. }
  1592. base::flat_set<std::string>
  1593. ElectronBrowserClient::GetPluginMimeTypesWithExternalHandlers(
  1594. content::BrowserContext* browser_context) {
  1595. base::flat_set<std::string> mime_types;
  1596. #if BUILDFLAG(ENABLE_PLUGINS) && BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1597. auto map = PluginUtils::GetMimeTypeToExtensionIdMap(browser_context);
  1598. for (const auto& pair : map)
  1599. mime_types.insert(pair.first);
  1600. #endif
  1601. #if BUILDFLAG(ENABLE_PDF_VIEWER)
  1602. mime_types.insert(pdf::kInternalPluginMimeType);
  1603. #endif
  1604. return mime_types;
  1605. }
  1606. content::SerialDelegate* ElectronBrowserClient::GetSerialDelegate() {
  1607. if (!serial_delegate_)
  1608. serial_delegate_ = std::make_unique<ElectronSerialDelegate>();
  1609. return serial_delegate_.get();
  1610. }
  1611. content::BluetoothDelegate* ElectronBrowserClient::GetBluetoothDelegate() {
  1612. if (!bluetooth_delegate_)
  1613. bluetooth_delegate_ = std::make_unique<ElectronBluetoothDelegate>();
  1614. return bluetooth_delegate_.get();
  1615. }
  1616. void BindBadgeServiceForServiceWorker(
  1617. const content::ServiceWorkerVersionBaseInfo& info,
  1618. mojo::PendingReceiver<blink::mojom::BadgeService> receiver) {
  1619. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  1620. content::RenderProcessHost* render_process_host =
  1621. content::RenderProcessHost::FromID(info.process_id);
  1622. if (!render_process_host)
  1623. return;
  1624. badging::BadgeManager::BindServiceWorkerReceiver(
  1625. render_process_host, info.scope, std::move(receiver));
  1626. }
  1627. void ElectronBrowserClient::RegisterBrowserInterfaceBindersForServiceWorker(
  1628. mojo::BinderMapWithContext<const content::ServiceWorkerVersionBaseInfo&>*
  1629. map) {
  1630. map->Add<blink::mojom::BadgeService>(
  1631. base::BindRepeating(&BindBadgeServiceForServiceWorker));
  1632. }
  1633. device::GeolocationManager* ElectronBrowserClient::GetGeolocationManager() {
  1634. #if BUILDFLAG(IS_MAC)
  1635. return browser_main_parts_->GetGeolocationManager();
  1636. #else
  1637. return nullptr;
  1638. #endif
  1639. }
  1640. content::HidDelegate* ElectronBrowserClient::GetHidDelegate() {
  1641. if (!hid_delegate_)
  1642. hid_delegate_ = std::make_unique<ElectronHidDelegate>();
  1643. return hid_delegate_.get();
  1644. }
  1645. } // namespace electron