electron_browser_client.cc 67 KB

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