electron_browser_client.cc 66 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750
  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_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"
  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. {
  405. ScopedAllowBlockingForElectron allow_blocking;
  406. base::FilePath child_path;
  407. base::FilePath program =
  408. base::MakeAbsoluteFilePath(command_line->GetProgram());
  409. #if BUILDFLAG(IS_MAC)
  410. auto renderer_child_path = content::ChildProcessHost::GetChildPath(
  411. content::ChildProcessHost::CHILD_RENDERER);
  412. auto gpu_child_path = content::ChildProcessHost::GetChildPath(
  413. content::ChildProcessHost::CHILD_GPU);
  414. auto plugin_child_path = content::ChildProcessHost::GetChildPath(
  415. content::ChildProcessHost::CHILD_PLUGIN);
  416. if (program != renderer_child_path && program != gpu_child_path &&
  417. program != plugin_child_path) {
  418. child_path = content::ChildProcessHost::GetChildPath(
  419. content::ChildProcessHost::CHILD_NORMAL);
  420. CHECK_EQ(program, child_path)
  421. << "Aborted from launching unexpected helper executable";
  422. }
  423. #else
  424. if (!base::PathService::Get(content::CHILD_PROCESS_EXE, &child_path)) {
  425. CHECK(false) << "Unable to get child process binary name.";
  426. }
  427. SCOPED_CRASH_KEY_STRING256("ChildProcess", "child_process_exe",
  428. child_path.AsUTF8Unsafe());
  429. SCOPED_CRASH_KEY_STRING256("ChildProcess", "program",
  430. program.AsUTF8Unsafe());
  431. CHECK_EQ(program, child_path);
  432. #endif
  433. }
  434. std::string process_type =
  435. command_line->GetSwitchValueASCII(::switches::kProcessType);
  436. #if BUILDFLAG(IS_LINUX)
  437. pid_t pid;
  438. if (crash_reporter::GetHandlerSocket(nullptr, &pid)) {
  439. command_line->AppendSwitchASCII(
  440. crash_reporter::switches::kCrashpadHandlerPid,
  441. base::NumberToString(pid));
  442. }
  443. // Zygote Process gets booted before any JS runs, accessing GetClientId
  444. // will end up touching DIR_USER_DATA path provider and this will
  445. // configure default value because app.name from browser_init has
  446. // not run yet.
  447. if (process_type != ::switches::kZygoteProcess) {
  448. std::string switch_value =
  449. api::crash_reporter::GetClientId() + ",no_channel";
  450. command_line->AppendSwitchASCII(::switches::kEnableCrashReporter,
  451. switch_value);
  452. }
  453. #endif
  454. // The zygote process is booted before JS runs, so DIR_USER_DATA isn't usable
  455. // at that time. It doesn't need --user-data-dir to be correct anyway, since
  456. // the zygote itself doesn't access anything in that directory.
  457. if (process_type != ::switches::kZygoteProcess) {
  458. base::FilePath user_data_dir;
  459. if (base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
  460. command_line->AppendSwitchPath(::switches::kUserDataDir, user_data_dir);
  461. }
  462. if (process_type == ::switches::kUtilityProcess ||
  463. process_type == ::switches::kRendererProcess) {
  464. // Copy following switches to child process.
  465. static const char* const kCommonSwitchNames[] = {
  466. switches::kStandardSchemes, switches::kEnableSandbox,
  467. switches::kSecureSchemes, switches::kBypassCSPSchemes,
  468. switches::kCORSSchemes, switches::kFetchSchemes,
  469. switches::kServiceWorkerSchemes, switches::kStreamingSchemes,
  470. switches::kCodeCacheSchemes};
  471. command_line->CopySwitchesFrom(*base::CommandLine::ForCurrentProcess(),
  472. kCommonSwitchNames);
  473. if (process_type == ::switches::kUtilityProcess ||
  474. content::RenderProcessHost::FromID(process_id)) {
  475. MaybeAppendSecureOriginsAllowlistSwitch(command_line);
  476. }
  477. }
  478. if (process_type == ::switches::kRendererProcess) {
  479. #if BUILDFLAG(IS_WIN)
  480. // Append --app-user-model-id.
  481. PWSTR current_app_id;
  482. if (SUCCEEDED(GetCurrentProcessExplicitAppUserModelID(&current_app_id))) {
  483. command_line->AppendSwitchNative(switches::kAppUserModelId,
  484. current_app_id);
  485. CoTaskMemFree(current_app_id);
  486. }
  487. #endif
  488. if (delegate_) {
  489. auto app_path = static_cast<api::App*>(delegate_)->GetAppPath();
  490. command_line->AppendSwitchPath(switches::kAppPath, app_path);
  491. }
  492. auto env = base::Environment::Create();
  493. if (env->HasVar("ELECTRON_PROFILE_INIT_SCRIPTS")) {
  494. command_line->AppendSwitch("profile-electron-init");
  495. }
  496. // Extension background pages don't have WebContentsPreferences, but they
  497. // support WebSQL by default.
  498. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  499. content::RenderProcessHost* process =
  500. content::RenderProcessHost::FromID(process_id);
  501. if (extensions::ProcessMap::Get(process->GetBrowserContext())
  502. ->Contains(process_id))
  503. command_line->AppendSwitch(switches::kEnableWebSQL);
  504. #endif
  505. content::WebContents* web_contents =
  506. GetWebContentsFromProcessID(process_id);
  507. if (web_contents) {
  508. auto* web_preferences = WebContentsPreferences::From(web_contents);
  509. if (web_preferences)
  510. web_preferences->AppendCommandLineSwitches(
  511. command_line, IsRendererSubFrame(process_id));
  512. }
  513. }
  514. }
  515. void ElectronBrowserClient::DidCreatePpapiPlugin(
  516. content::BrowserPpapiHost* host) {}
  517. // attempt to get api key from env
  518. std::string ElectronBrowserClient::GetGeolocationApiKey() {
  519. auto env = base::Environment::Create();
  520. std::string api_key;
  521. env->GetVar("GOOGLE_API_KEY", &api_key);
  522. return api_key;
  523. }
  524. content::GeneratedCodeCacheSettings
  525. ElectronBrowserClient::GetGeneratedCodeCacheSettings(
  526. content::BrowserContext* context) {
  527. // TODO(deepak1556): Use platform cache directory.
  528. base::FilePath cache_path = context->GetPath();
  529. // If we pass 0 for size, disk_cache will pick a default size using the
  530. // heuristics based on available disk size. These are implemented in
  531. // disk_cache::PreferredCacheSize in net/disk_cache/cache_util.cc.
  532. return content::GeneratedCodeCacheSettings(true, 0, cache_path);
  533. }
  534. void ElectronBrowserClient::AllowCertificateError(
  535. content::WebContents* web_contents,
  536. int cert_error,
  537. const net::SSLInfo& ssl_info,
  538. const GURL& request_url,
  539. bool is_main_frame_request,
  540. bool strict_enforcement,
  541. base::OnceCallback<void(content::CertificateRequestResultType)> callback) {
  542. if (delegate_) {
  543. delegate_->AllowCertificateError(web_contents, cert_error, ssl_info,
  544. request_url, is_main_frame_request,
  545. strict_enforcement, std::move(callback));
  546. }
  547. }
  548. base::OnceClosure ElectronBrowserClient::SelectClientCertificate(
  549. content::BrowserContext* browser_context,
  550. content::WebContents* web_contents,
  551. net::SSLCertRequestInfo* cert_request_info,
  552. net::ClientCertIdentityList client_certs,
  553. std::unique_ptr<content::ClientCertificateDelegate> delegate) {
  554. if (client_certs.empty()) {
  555. delegate->ContinueWithCertificate(nullptr, nullptr);
  556. } else if (delegate_) {
  557. delegate_->SelectClientCertificate(
  558. browser_context, web_contents, cert_request_info,
  559. std::move(client_certs), std::move(delegate));
  560. }
  561. return base::OnceClosure();
  562. }
  563. bool ElectronBrowserClient::CanCreateWindow(
  564. content::RenderFrameHost* opener,
  565. const GURL& opener_url,
  566. const GURL& opener_top_level_frame_url,
  567. const url::Origin& source_origin,
  568. content::mojom::WindowContainerType container_type,
  569. const GURL& target_url,
  570. const content::Referrer& referrer,
  571. const std::string& frame_name,
  572. WindowOpenDisposition disposition,
  573. const blink::mojom::WindowFeatures& features,
  574. const std::string& raw_features,
  575. const scoped_refptr<network::ResourceRequestBody>& body,
  576. bool user_gesture,
  577. bool opener_suppressed,
  578. bool* no_javascript_access) {
  579. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  580. content::WebContents* web_contents =
  581. content::WebContents::FromRenderFrameHost(opener);
  582. WebContentsPreferences* prefs = WebContentsPreferences::From(web_contents);
  583. if (prefs) {
  584. if (prefs->ShouldDisablePopups()) {
  585. // <webview> without allowpopups attribute should return
  586. // null from window.open calls
  587. return false;
  588. } else {
  589. *no_javascript_access = false;
  590. return true;
  591. }
  592. }
  593. if (delegate_) {
  594. return delegate_->CanCreateWindow(
  595. opener, opener_url, opener_top_level_frame_url, source_origin,
  596. container_type, target_url, referrer, frame_name, disposition, features,
  597. raw_features, body, user_gesture, opener_suppressed,
  598. no_javascript_access);
  599. }
  600. return false;
  601. }
  602. std::unique_ptr<content::VideoOverlayWindow>
  603. ElectronBrowserClient::CreateWindowForVideoPictureInPicture(
  604. content::VideoPictureInPictureWindowController* controller) {
  605. auto overlay_window = content::VideoOverlayWindow::Create(controller);
  606. #if BUILDFLAG(IS_WIN)
  607. std::wstring app_user_model_id = Browser::Get()->GetAppUserModelID();
  608. if (!app_user_model_id.empty()) {
  609. auto* overlay_window_view =
  610. static_cast<VideoOverlayWindowViews*>(overlay_window.get());
  611. ui::win::SetAppIdForWindow(app_user_model_id,
  612. overlay_window_view->GetNativeWindow()
  613. ->GetHost()
  614. ->GetAcceleratedWidget());
  615. }
  616. #endif
  617. return overlay_window;
  618. }
  619. void ElectronBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
  620. std::vector<std::string>* additional_schemes) {
  621. const auto& schemes_list = api::GetStandardSchemes();
  622. if (!schemes_list.empty())
  623. additional_schemes->insert(additional_schemes->end(), schemes_list.begin(),
  624. schemes_list.end());
  625. additional_schemes->push_back(content::kChromeDevToolsScheme);
  626. additional_schemes->push_back(content::kChromeUIScheme);
  627. }
  628. void ElectronBrowserClient::GetAdditionalWebUISchemes(
  629. std::vector<std::string>* additional_schemes) {
  630. additional_schemes->push_back(content::kChromeDevToolsScheme);
  631. }
  632. void ElectronBrowserClient::SiteInstanceGotProcessAndSite(
  633. content::SiteInstance* site_instance) {
  634. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  635. auto* browser_context =
  636. static_cast<ElectronBrowserContext*>(site_instance->GetBrowserContext());
  637. if (!browser_context->IsOffTheRecord()) {
  638. extensions::ExtensionRegistry* registry =
  639. extensions::ExtensionRegistry::Get(browser_context);
  640. const extensions::Extension* extension =
  641. registry->enabled_extensions().GetExtensionOrAppByURL(
  642. site_instance->GetSiteURL());
  643. if (!extension)
  644. return;
  645. extensions::ProcessMap::Get(browser_context)
  646. ->Insert(extension->id(), site_instance->GetProcess()->GetID());
  647. }
  648. #endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  649. }
  650. bool ElectronBrowserClient::IsSuitableHost(
  651. content::RenderProcessHost* process_host,
  652. const GURL& site_url) {
  653. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  654. auto* browser_context = process_host->GetBrowserContext();
  655. extensions::ExtensionRegistry* registry =
  656. extensions::ExtensionRegistry::Get(browser_context);
  657. extensions::ProcessMap* process_map =
  658. extensions::ProcessMap::Get(browser_context);
  659. // Otherwise, just make sure the process privilege matches the privilege
  660. // required by the site.
  661. RenderProcessHostPrivilege privilege_required =
  662. GetPrivilegeRequiredByUrl(site_url, registry);
  663. return GetProcessPrivilege(process_host, process_map, registry) ==
  664. privilege_required;
  665. #else
  666. return content::ContentBrowserClient::IsSuitableHost(process_host, site_url);
  667. #endif
  668. }
  669. bool ElectronBrowserClient::ShouldUseProcessPerSite(
  670. content::BrowserContext* browser_context,
  671. const GURL& effective_url) {
  672. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  673. const extensions::Extension* extension =
  674. GetEnabledExtensionFromEffectiveURL(browser_context, effective_url);
  675. return extension != nullptr;
  676. #else
  677. return content::ContentBrowserClient::ShouldUseProcessPerSite(browser_context,
  678. effective_url);
  679. #endif
  680. }
  681. void ElectronBrowserClient::GetMediaDeviceIDSalt(
  682. content::RenderFrameHost* rfh,
  683. const net::SiteForCookies& site_for_cookies,
  684. const blink::StorageKey& storage_key,
  685. base::OnceCallback<void(bool, const std::string&)> callback) {
  686. constexpr bool persistent_media_device_id_allowed = true;
  687. std::string persistent_media_device_id_salt =
  688. static_cast<ElectronBrowserContext*>(rfh->GetBrowserContext())
  689. ->GetMediaDeviceIDSalt();
  690. std::move(callback).Run(persistent_media_device_id_allowed,
  691. persistent_media_device_id_salt);
  692. }
  693. base::FilePath ElectronBrowserClient::GetLoggingFileName(
  694. const base::CommandLine& cmd_line) {
  695. return logging::GetLogFileName(cmd_line);
  696. }
  697. std::unique_ptr<net::ClientCertStore>
  698. ElectronBrowserClient::CreateClientCertStore(
  699. content::BrowserContext* browser_context) {
  700. #if BUILDFLAG(USE_NSS_CERTS)
  701. return std::make_unique<net::ClientCertStoreNSS>(
  702. net::ClientCertStoreNSS::PasswordDelegateFactory());
  703. #elif BUILDFLAG(IS_WIN)
  704. return std::make_unique<net::ClientCertStoreWin>();
  705. #elif BUILDFLAG(IS_MAC)
  706. return std::make_unique<net::ClientCertStoreMac>();
  707. #elif defined(USE_OPENSSL)
  708. return std::unique_ptr<net::ClientCertStore>();
  709. #endif
  710. }
  711. std::unique_ptr<device::LocationProvider>
  712. ElectronBrowserClient::OverrideSystemLocationProvider() {
  713. #if BUILDFLAG(OVERRIDE_LOCATION_PROVIDER)
  714. return std::make_unique<FakeLocationProvider>();
  715. #else
  716. return nullptr;
  717. #endif
  718. }
  719. void ElectronBrowserClient::ConfigureNetworkContextParams(
  720. content::BrowserContext* browser_context,
  721. bool in_memory,
  722. const base::FilePath& relative_partition_path,
  723. network::mojom::NetworkContextParams* network_context_params,
  724. cert_verifier::mojom::CertVerifierCreationParams*
  725. cert_verifier_creation_params) {
  726. DCHECK(browser_context);
  727. return NetworkContextServiceFactory::GetForContext(browser_context)
  728. ->ConfigureNetworkContextParams(network_context_params,
  729. cert_verifier_creation_params);
  730. }
  731. network::mojom::NetworkContext*
  732. ElectronBrowserClient::GetSystemNetworkContext() {
  733. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  734. DCHECK(g_browser_process->system_network_context_manager());
  735. return g_browser_process->system_network_context_manager()->GetContext();
  736. }
  737. std::unique_ptr<content::BrowserMainParts>
  738. ElectronBrowserClient::CreateBrowserMainParts(bool /* is_integration_test */) {
  739. auto browser_main_parts = std::make_unique<ElectronBrowserMainParts>();
  740. #if BUILDFLAG(IS_MAC)
  741. browser_main_parts_ = browser_main_parts.get();
  742. #endif
  743. return browser_main_parts;
  744. }
  745. void ElectronBrowserClient::WebNotificationAllowed(
  746. content::RenderFrameHost* rfh,
  747. base::OnceCallback<void(bool, bool)> callback) {
  748. content::WebContents* web_contents =
  749. content::WebContents::FromRenderFrameHost(rfh);
  750. if (!web_contents) {
  751. std::move(callback).Run(false, false);
  752. return;
  753. }
  754. auto* permission_helper =
  755. WebContentsPermissionHelper::FromWebContents(web_contents);
  756. if (!permission_helper) {
  757. std::move(callback).Run(false, false);
  758. return;
  759. }
  760. permission_helper->RequestWebNotificationPermission(
  761. rfh, base::BindOnce(std::move(callback), web_contents->IsAudioMuted()));
  762. }
  763. void ElectronBrowserClient::RenderProcessHostDestroyed(
  764. content::RenderProcessHost* host) {
  765. int process_id = host->GetID();
  766. pending_processes_.erase(process_id);
  767. renderer_is_subframe_.erase(process_id);
  768. host->RemoveObserver(this);
  769. }
  770. void ElectronBrowserClient::RenderProcessReady(
  771. content::RenderProcessHost* host) {
  772. if (delegate_) {
  773. static_cast<api::App*>(delegate_)->RenderProcessReady(host);
  774. }
  775. }
  776. void ElectronBrowserClient::RenderProcessExited(
  777. content::RenderProcessHost* host,
  778. const content::ChildProcessTerminationInfo& info) {
  779. if (delegate_) {
  780. static_cast<api::App*>(delegate_)->RenderProcessExited(host);
  781. }
  782. }
  783. void OnOpenExternal(const GURL& escaped_url, bool allowed) {
  784. if (allowed) {
  785. platform_util::OpenExternal(
  786. escaped_url, platform_util::OpenExternalOptions(), base::DoNothing());
  787. }
  788. }
  789. void HandleExternalProtocolInUI(
  790. const GURL& url,
  791. content::WeakDocumentPtr document_ptr,
  792. content::WebContents::OnceGetter web_contents_getter,
  793. bool has_user_gesture) {
  794. content::WebContents* web_contents = std::move(web_contents_getter).Run();
  795. if (!web_contents)
  796. return;
  797. auto* permission_helper =
  798. WebContentsPermissionHelper::FromWebContents(web_contents);
  799. if (!permission_helper)
  800. return;
  801. content::RenderFrameHost* rfh = document_ptr.AsRenderFrameHostIfValid();
  802. if (!rfh) {
  803. // If the render frame host is not valid it means it was a top level
  804. // navigation and the frame has already been disposed of. In this case we
  805. // take the current main frame and declare it responsible for the
  806. // transition.
  807. rfh = web_contents->GetPrimaryMainFrame();
  808. }
  809. GURL escaped_url(base::EscapeExternalHandlerValue(url.spec()));
  810. auto callback = base::BindOnce(&OnOpenExternal, escaped_url);
  811. permission_helper->RequestOpenExternalPermission(rfh, std::move(callback),
  812. has_user_gesture, url);
  813. }
  814. bool ElectronBrowserClient::HandleExternalProtocol(
  815. const GURL& url,
  816. content::WebContents::Getter web_contents_getter,
  817. int frame_tree_node_id,
  818. content::NavigationUIData* navigation_data,
  819. bool is_primary_main_frame,
  820. bool is_in_fenced_frame_tree,
  821. network::mojom::WebSandboxFlags sandbox_flags,
  822. ui::PageTransition page_transition,
  823. bool has_user_gesture,
  824. const std::optional<url::Origin>& initiating_origin,
  825. content::RenderFrameHost* initiator_document,
  826. mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory) {
  827. content::GetUIThreadTaskRunner({})->PostTask(
  828. FROM_HERE,
  829. base::BindOnce(&HandleExternalProtocolInUI, url,
  830. initiator_document
  831. ? initiator_document->GetWeakDocumentPtr()
  832. : content::WeakDocumentPtr(),
  833. std::move(web_contents_getter), has_user_gesture));
  834. return true;
  835. }
  836. std::vector<std::unique_ptr<content::NavigationThrottle>>
  837. ElectronBrowserClient::CreateThrottlesForNavigation(
  838. content::NavigationHandle* handle) {
  839. std::vector<std::unique_ptr<content::NavigationThrottle>> throttles;
  840. throttles.push_back(std::make_unique<ElectronNavigationThrottle>(handle));
  841. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  842. throttles.push_back(
  843. std::make_unique<extensions::ExtensionNavigationThrottle>(handle));
  844. #endif
  845. #if BUILDFLAG(ENABLE_PDF_VIEWER)
  846. std::unique_ptr<content::NavigationThrottle> pdf_iframe_throttle =
  847. PDFIFrameNavigationThrottle::MaybeCreateThrottleFor(handle);
  848. if (pdf_iframe_throttle)
  849. throttles.push_back(std::move(pdf_iframe_throttle));
  850. std::unique_ptr<content::NavigationThrottle> pdf_throttle =
  851. pdf::PdfNavigationThrottle::MaybeCreateThrottleFor(
  852. handle, std::make_unique<ChromePdfStreamDelegate>());
  853. if (pdf_throttle)
  854. throttles.push_back(std::move(pdf_throttle));
  855. #endif
  856. return throttles;
  857. }
  858. content::MediaObserver* ElectronBrowserClient::GetMediaObserver() {
  859. return MediaCaptureDevicesDispatcher::GetInstance();
  860. }
  861. std::unique_ptr<content::DevToolsManagerDelegate>
  862. ElectronBrowserClient::CreateDevToolsManagerDelegate() {
  863. return std::make_unique<DevToolsManagerDelegate>();
  864. }
  865. NotificationPresenter* ElectronBrowserClient::GetNotificationPresenter() {
  866. if (!notification_presenter_) {
  867. notification_presenter_.reset(NotificationPresenter::Create());
  868. }
  869. return notification_presenter_.get();
  870. }
  871. content::PlatformNotificationService*
  872. ElectronBrowserClient::GetPlatformNotificationService() {
  873. if (!notification_service_) {
  874. notification_service_ = std::make_unique<PlatformNotificationService>(this);
  875. }
  876. return notification_service_.get();
  877. }
  878. base::FilePath ElectronBrowserClient::GetDefaultDownloadDirectory() {
  879. base::FilePath download_path;
  880. if (base::PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &download_path))
  881. return download_path;
  882. return base::FilePath();
  883. }
  884. scoped_refptr<network::SharedURLLoaderFactory>
  885. ElectronBrowserClient::GetSystemSharedURLLoaderFactory() {
  886. if (!g_browser_process)
  887. return nullptr;
  888. return g_browser_process->shared_url_loader_factory();
  889. }
  890. void ElectronBrowserClient::OnNetworkServiceCreated(
  891. network::mojom::NetworkService* network_service) {
  892. if (!g_browser_process)
  893. return;
  894. g_browser_process->system_network_context_manager()->OnNetworkServiceCreated(
  895. network_service);
  896. }
  897. std::vector<base::FilePath>
  898. ElectronBrowserClient::GetNetworkContextsParentDirectory() {
  899. base::FilePath session_data;
  900. base::PathService::Get(DIR_SESSION_DATA, &session_data);
  901. DCHECK(!session_data.empty());
  902. return {session_data};
  903. }
  904. std::string ElectronBrowserClient::GetProduct() {
  905. return "Chrome/" CHROME_VERSION_STRING;
  906. }
  907. std::string ElectronBrowserClient::GetUserAgent() {
  908. if (user_agent_override_.empty())
  909. return GetApplicationUserAgent();
  910. return user_agent_override_;
  911. }
  912. void ElectronBrowserClient::SetUserAgent(const std::string& user_agent) {
  913. user_agent_override_ = user_agent;
  914. }
  915. blink::UserAgentMetadata ElectronBrowserClient::GetUserAgentMetadata() {
  916. return embedder_support::GetUserAgentMetadata();
  917. }
  918. void ElectronBrowserClient::RegisterNonNetworkNavigationURLLoaderFactories(
  919. int frame_tree_node_id,
  920. NonNetworkURLLoaderFactoryMap* factories) {
  921. content::WebContents* web_contents =
  922. content::WebContents::FromFrameTreeNodeId(frame_tree_node_id);
  923. content::BrowserContext* context = web_contents->GetBrowserContext();
  924. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  925. factories->emplace(
  926. extensions::kExtensionScheme,
  927. extensions::CreateExtensionNavigationURLLoaderFactory(
  928. context, false /* we don't support extensions::WebViewGuest */));
  929. #endif
  930. // Always allow navigating to file:// URLs.
  931. auto* protocol_registry = ProtocolRegistry::FromBrowserContext(context);
  932. protocol_registry->RegisterURLLoaderFactories(factories,
  933. true /* allow_file_access */);
  934. }
  935. void ElectronBrowserClient::
  936. RegisterNonNetworkWorkerMainResourceURLLoaderFactories(
  937. content::BrowserContext* browser_context,
  938. NonNetworkURLLoaderFactoryMap* factories) {
  939. auto* protocol_registry =
  940. ProtocolRegistry::FromBrowserContext(browser_context);
  941. // Workers are not allowed to request file:// URLs, there is no particular
  942. // reason for it, and we could consider supporting it in future.
  943. protocol_registry->RegisterURLLoaderFactories(factories,
  944. false /* allow_file_access */);
  945. }
  946. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  947. namespace {
  948. // The FileURLLoaderFactory provided to the extension background pages.
  949. // Checks with the ChildProcessSecurityPolicy to validate the file access.
  950. class FileURLLoaderFactory : public network::SelfDeletingURLLoaderFactory {
  951. public:
  952. static mojo::PendingRemote<network::mojom::URLLoaderFactory> Create(
  953. int child_id) {
  954. mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_remote;
  955. // The FileURLLoaderFactory will delete itself when there are no more
  956. // receivers - see the SelfDeletingURLLoaderFactory::OnDisconnect method.
  957. new FileURLLoaderFactory(child_id,
  958. pending_remote.InitWithNewPipeAndPassReceiver());
  959. return pending_remote;
  960. }
  961. // disable copy
  962. FileURLLoaderFactory(const FileURLLoaderFactory&) = delete;
  963. FileURLLoaderFactory& operator=(const FileURLLoaderFactory&) = delete;
  964. private:
  965. explicit FileURLLoaderFactory(
  966. int child_id,
  967. mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver)
  968. : network::SelfDeletingURLLoaderFactory(std::move(factory_receiver)),
  969. child_id_(child_id) {}
  970. ~FileURLLoaderFactory() override = default;
  971. // network::mojom::URLLoaderFactory:
  972. void CreateLoaderAndStart(
  973. mojo::PendingReceiver<network::mojom::URLLoader> loader,
  974. int32_t request_id,
  975. uint32_t options,
  976. const network::ResourceRequest& request,
  977. mojo::PendingRemote<network::mojom::URLLoaderClient> client,
  978. const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
  979. override {
  980. if (!content::ChildProcessSecurityPolicy::GetInstance()->CanRequestURL(
  981. child_id_, request.url)) {
  982. mojo::Remote<network::mojom::URLLoaderClient>(std::move(client))
  983. ->OnComplete(
  984. network::URLLoaderCompletionStatus(net::ERR_ACCESS_DENIED));
  985. return;
  986. }
  987. content::CreateFileURLLoaderBypassingSecurityChecks(
  988. request, std::move(loader), std::move(client),
  989. /*observer=*/nullptr,
  990. /* allow_directory_listing */ true);
  991. }
  992. int child_id_;
  993. };
  994. } // namespace
  995. #endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  996. void ElectronBrowserClient::RegisterNonNetworkSubresourceURLLoaderFactories(
  997. int render_process_id,
  998. int render_frame_id,
  999. const std::optional<url::Origin>& request_initiator_origin,
  1000. NonNetworkURLLoaderFactoryMap* factories) {
  1001. auto* render_process_host =
  1002. content::RenderProcessHost::FromID(render_process_id);
  1003. DCHECK(render_process_host);
  1004. if (!render_process_host || !render_process_host->GetBrowserContext())
  1005. return;
  1006. content::RenderFrameHost* frame_host =
  1007. content::RenderFrameHost::FromID(render_process_id, render_frame_id);
  1008. content::WebContents* web_contents =
  1009. content::WebContents::FromRenderFrameHost(frame_host);
  1010. // Allow accessing file:// subresources from non-file protocols if web
  1011. // security is disabled.
  1012. bool allow_file_access = false;
  1013. if (web_contents) {
  1014. const auto& web_preferences = web_contents->GetOrCreateWebPreferences();
  1015. if (!web_preferences.web_security_enabled)
  1016. allow_file_access = true;
  1017. }
  1018. ProtocolRegistry::FromBrowserContext(render_process_host->GetBrowserContext())
  1019. ->RegisterURLLoaderFactories(factories, allow_file_access);
  1020. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1021. auto factory = extensions::CreateExtensionURLLoaderFactory(render_process_id,
  1022. render_frame_id);
  1023. if (factory)
  1024. factories->emplace(extensions::kExtensionScheme, std::move(factory));
  1025. if (!web_contents)
  1026. return;
  1027. extensions::ElectronExtensionWebContentsObserver* web_observer =
  1028. extensions::ElectronExtensionWebContentsObserver::FromWebContents(
  1029. web_contents);
  1030. // There is nothing to do if no ElectronExtensionWebContentsObserver is
  1031. // attached to the |web_contents|.
  1032. if (!web_observer)
  1033. return;
  1034. const extensions::Extension* extension =
  1035. web_observer->GetExtensionFromFrame(frame_host, false);
  1036. if (!extension)
  1037. return;
  1038. // Support for chrome:// scheme if appropriate.
  1039. if (extension->is_extension() &&
  1040. extensions::Manifest::IsComponentLocation(extension->location())) {
  1041. // Components of chrome that are implemented as extensions or platform apps
  1042. // are allowed to use chrome://resources/ and chrome://theme/ URLs.
  1043. factories->emplace(content::kChromeUIScheme,
  1044. content::CreateWebUIURLLoaderFactory(
  1045. frame_host, content::kChromeUIScheme,
  1046. {content::kChromeUIResourcesHost}));
  1047. }
  1048. // Extensions with the necessary permissions get access to file:// URLs that
  1049. // gets approval from ChildProcessSecurityPolicy. Keep this logic in sync with
  1050. // ExtensionWebContentsObserver::RenderFrameCreated.
  1051. extensions::Manifest::Type type = extension->GetType();
  1052. if (type == extensions::Manifest::TYPE_EXTENSION &&
  1053. AllowFileAccess(extension->id(), web_contents->GetBrowserContext())) {
  1054. factories->emplace(url::kFileScheme,
  1055. FileURLLoaderFactory::Create(render_process_id));
  1056. }
  1057. #endif
  1058. }
  1059. void ElectronBrowserClient::
  1060. RegisterNonNetworkServiceWorkerUpdateURLLoaderFactories(
  1061. content::BrowserContext* browser_context,
  1062. NonNetworkURLLoaderFactoryMap* factories) {
  1063. DCHECK(browser_context);
  1064. DCHECK(factories);
  1065. auto* protocol_registry =
  1066. ProtocolRegistry::FromBrowserContext(browser_context);
  1067. protocol_registry->RegisterURLLoaderFactories(factories,
  1068. false /* allow_file_access */);
  1069. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1070. factories->emplace(
  1071. extensions::kExtensionScheme,
  1072. extensions::CreateExtensionServiceWorkerScriptURLLoaderFactory(
  1073. browser_context));
  1074. #endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1075. }
  1076. bool ElectronBrowserClient::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
  1077. base::StringPiece scheme,
  1078. bool is_embedded_origin_secure) {
  1079. if (is_embedded_origin_secure && scheme == content::kChromeUIScheme)
  1080. return true;
  1081. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1082. return scheme == extensions::kExtensionScheme;
  1083. #else
  1084. return false;
  1085. #endif
  1086. }
  1087. bool ElectronBrowserClient::WillInterceptWebSocket(
  1088. content::RenderFrameHost* frame) {
  1089. if (!frame)
  1090. return false;
  1091. v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
  1092. v8::HandleScope scope(isolate);
  1093. auto* browser_context = frame->GetProcess()->GetBrowserContext();
  1094. auto web_request = api::WebRequest::FromOrCreate(isolate, browser_context);
  1095. // NOTE: Some unit test environments do not initialize
  1096. // BrowserContextKeyedAPI factories for e.g. WebRequest.
  1097. if (!web_request.get())
  1098. return false;
  1099. bool has_listener = web_request->HasListener();
  1100. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1101. const auto* web_request_api =
  1102. extensions::BrowserContextKeyedAPIFactory<extensions::WebRequestAPI>::Get(
  1103. browser_context);
  1104. if (web_request_api)
  1105. has_listener |= web_request_api->MayHaveProxies();
  1106. #endif
  1107. return has_listener;
  1108. }
  1109. void ElectronBrowserClient::CreateWebSocket(
  1110. content::RenderFrameHost* frame,
  1111. WebSocketFactory factory,
  1112. const GURL& url,
  1113. const net::SiteForCookies& site_for_cookies,
  1114. const std::optional<std::string>& user_agent,
  1115. mojo::PendingRemote<network::mojom::WebSocketHandshakeClient>
  1116. handshake_client) {
  1117. v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
  1118. v8::HandleScope scope(isolate);
  1119. auto* browser_context = frame->GetProcess()->GetBrowserContext();
  1120. auto web_request = api::WebRequest::FromOrCreate(isolate, browser_context);
  1121. DCHECK(web_request.get());
  1122. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1123. if (!web_request->HasListener()) {
  1124. auto* web_request_api = extensions::BrowserContextKeyedAPIFactory<
  1125. extensions::WebRequestAPI>::Get(browser_context);
  1126. if (web_request_api && web_request_api->MayHaveProxies()) {
  1127. web_request_api->ProxyWebSocket(frame, std::move(factory), url,
  1128. site_for_cookies, user_agent,
  1129. std::move(handshake_client));
  1130. return;
  1131. }
  1132. }
  1133. #endif
  1134. ProxyingWebSocket::StartProxying(
  1135. web_request.get(), std::move(factory), url, site_for_cookies, user_agent,
  1136. std::move(handshake_client), true, frame->GetProcess()->GetID(),
  1137. frame->GetRoutingID(), frame->GetLastCommittedOrigin(), browser_context,
  1138. &next_id_);
  1139. }
  1140. void ElectronBrowserClient::WillCreateURLLoaderFactory(
  1141. content::BrowserContext* browser_context,
  1142. content::RenderFrameHost* frame_host,
  1143. int render_process_id,
  1144. URLLoaderFactoryType type,
  1145. const url::Origin& request_initiator,
  1146. std::optional<int64_t> navigation_id,
  1147. ukm::SourceIdObj ukm_source_id,
  1148. network::URLLoaderFactoryBuilder& factory_builder,
  1149. mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>*
  1150. header_client,
  1151. bool* bypass_redirect_checks,
  1152. bool* disable_secure_dns,
  1153. network::mojom::URLLoaderFactoryOverridePtr* factory_override,
  1154. scoped_refptr<base::SequencedTaskRunner> navigation_response_task_runner) {
  1155. v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
  1156. v8::HandleScope scope(isolate);
  1157. auto web_request = api::WebRequest::FromOrCreate(isolate, browser_context);
  1158. DCHECK(web_request.get());
  1159. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1160. if (!web_request->HasListener()) {
  1161. auto* web_request_api = extensions::BrowserContextKeyedAPIFactory<
  1162. extensions::WebRequestAPI>::Get(browser_context);
  1163. DCHECK(web_request_api);
  1164. bool used_proxy_for_web_request =
  1165. web_request_api->MaybeProxyURLLoaderFactory(
  1166. browser_context, frame_host, render_process_id, type, navigation_id,
  1167. ukm_source_id, factory_builder, header_client,
  1168. navigation_response_task_runner);
  1169. if (bypass_redirect_checks)
  1170. *bypass_redirect_checks = used_proxy_for_web_request;
  1171. if (used_proxy_for_web_request)
  1172. return;
  1173. }
  1174. #endif
  1175. auto [proxied_receiver, target_factory_remote] = factory_builder.Append();
  1176. // Required by WebRequestInfoInitParams.
  1177. //
  1178. // Note that in Electron we allow webRequest to capture requests sent from
  1179. // browser process, so creation of |navigation_ui_data| is different from
  1180. // Chromium which only does for renderer-initialized navigations.
  1181. std::unique_ptr<extensions::ExtensionNavigationUIData> navigation_ui_data;
  1182. if (navigation_id.has_value()) {
  1183. navigation_ui_data =
  1184. std::make_unique<extensions::ExtensionNavigationUIData>();
  1185. }
  1186. mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient>
  1187. header_client_receiver;
  1188. if (header_client)
  1189. header_client_receiver = header_client->InitWithNewPipeAndPassReceiver();
  1190. auto* protocol_registry =
  1191. ProtocolRegistry::FromBrowserContext(browser_context);
  1192. new ProxyingURLLoaderFactory(
  1193. web_request.get(), protocol_registry->intercept_handlers(),
  1194. render_process_id,
  1195. frame_host ? frame_host->GetRoutingID() : MSG_ROUTING_NONE, &next_id_,
  1196. std::move(navigation_ui_data), std::move(navigation_id),
  1197. std::move(proxied_receiver), std::move(target_factory_remote),
  1198. std::move(header_client_receiver), type);
  1199. }
  1200. std::vector<std::unique_ptr<content::URLLoaderRequestInterceptor>>
  1201. ElectronBrowserClient::WillCreateURLLoaderRequestInterceptors(
  1202. content::NavigationUIData* navigation_ui_data,
  1203. int frame_tree_node_id,
  1204. int64_t navigation_id,
  1205. scoped_refptr<base::SequencedTaskRunner> navigation_response_task_runner) {
  1206. std::vector<std::unique_ptr<content::URLLoaderRequestInterceptor>>
  1207. interceptors;
  1208. #if BUILDFLAG(ENABLE_PDF_VIEWER)
  1209. {
  1210. std::unique_ptr<content::URLLoaderRequestInterceptor> pdf_interceptor =
  1211. pdf::PdfURLLoaderRequestInterceptor::MaybeCreateInterceptor(
  1212. frame_tree_node_id, std::make_unique<ChromePdfStreamDelegate>());
  1213. if (pdf_interceptor)
  1214. interceptors.push_back(std::move(pdf_interceptor));
  1215. }
  1216. #endif
  1217. return interceptors;
  1218. }
  1219. void ElectronBrowserClient::OverrideURLLoaderFactoryParams(
  1220. content::BrowserContext* browser_context,
  1221. const url::Origin& origin,
  1222. bool is_for_isolated_world,
  1223. network::mojom::URLLoaderFactoryParams* factory_params) {
  1224. if (factory_params->top_frame_id) {
  1225. // Bypass CORB and CORS when web security is disabled.
  1226. auto* rfh = content::RenderFrameHost::FromFrameToken(
  1227. content::GlobalRenderFrameHostToken(
  1228. factory_params->process_id,
  1229. blink::LocalFrameToken(factory_params->top_frame_id.value())));
  1230. auto* web_contents = content::WebContents::FromRenderFrameHost(rfh);
  1231. auto* prefs = WebContentsPreferences::From(web_contents);
  1232. if (prefs && !prefs->IsWebSecurityEnabled()) {
  1233. factory_params->is_orb_enabled = false;
  1234. factory_params->disable_web_security = true;
  1235. }
  1236. }
  1237. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1238. extensions::URLLoaderFactoryManager::OverrideURLLoaderFactoryParams(
  1239. browser_context, origin, is_for_isolated_world, factory_params);
  1240. #endif
  1241. }
  1242. void ElectronBrowserClient::RegisterAssociatedInterfaceBindersForServiceWorker(
  1243. const content::ServiceWorkerVersionBaseInfo& service_worker_version_info,
  1244. blink::AssociatedInterfaceRegistry& associated_registry) {
  1245. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1246. associated_registry.AddInterface<extensions::mojom::RendererHost>(
  1247. base::BindRepeating(&extensions::RendererStartupHelper::BindForRenderer,
  1248. service_worker_version_info.process_id));
  1249. associated_registry.AddInterface<extensions::mojom::ServiceWorkerHost>(
  1250. base::BindRepeating(&extensions::ServiceWorkerHost::BindReceiver,
  1251. service_worker_version_info.process_id));
  1252. #endif
  1253. }
  1254. void ElectronBrowserClient::
  1255. RegisterAssociatedInterfaceBindersForRenderFrameHost(
  1256. content::RenderFrameHost&
  1257. render_frame_host, // NOLINT(runtime/references)
  1258. blink::AssociatedInterfaceRegistry&
  1259. associated_registry) { // NOLINT(runtime/references)
  1260. auto* contents =
  1261. content::WebContents::FromRenderFrameHost(&render_frame_host);
  1262. if (contents) {
  1263. auto* prefs = WebContentsPreferences::From(contents);
  1264. if (render_frame_host.GetFrameTreeNodeId() ==
  1265. contents->GetPrimaryMainFrame()->GetFrameTreeNodeId() ||
  1266. (prefs && prefs->AllowsNodeIntegrationInSubFrames())) {
  1267. associated_registry.AddInterface<mojom::ElectronApiIPC>(
  1268. base::BindRepeating(
  1269. [](content::RenderFrameHost* render_frame_host,
  1270. mojo::PendingAssociatedReceiver<mojom::ElectronApiIPC>
  1271. receiver) {
  1272. ElectronApiIPCHandlerImpl::Create(render_frame_host,
  1273. std::move(receiver));
  1274. },
  1275. &render_frame_host));
  1276. }
  1277. }
  1278. associated_registry.AddInterface<mojom::ElectronWebContentsUtility>(
  1279. base::BindRepeating(
  1280. [](content::RenderFrameHost* render_frame_host,
  1281. mojo::PendingAssociatedReceiver<mojom::ElectronWebContentsUtility>
  1282. receiver) {
  1283. ElectronWebContentsUtilityHandlerImpl::Create(render_frame_host,
  1284. std::move(receiver));
  1285. },
  1286. &render_frame_host));
  1287. associated_registry.AddInterface<mojom::ElectronAutofillDriver>(
  1288. base::BindRepeating(
  1289. [](content::RenderFrameHost* render_frame_host,
  1290. mojo::PendingAssociatedReceiver<mojom::ElectronAutofillDriver>
  1291. receiver) {
  1292. AutofillDriverFactory::BindAutofillDriver(std::move(receiver),
  1293. render_frame_host);
  1294. },
  1295. &render_frame_host));
  1296. #if BUILDFLAG(ENABLE_PRINTING)
  1297. associated_registry.AddInterface<printing::mojom::PrintManagerHost>(
  1298. base::BindRepeating(
  1299. [](content::RenderFrameHost* render_frame_host,
  1300. mojo::PendingAssociatedReceiver<printing::mojom::PrintManagerHost>
  1301. receiver) {
  1302. PrintViewManagerElectron::BindPrintManagerHost(std::move(receiver),
  1303. render_frame_host);
  1304. },
  1305. &render_frame_host));
  1306. #endif
  1307. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1308. int render_process_id = render_frame_host.GetProcess()->GetID();
  1309. associated_registry.AddInterface<extensions::mojom::EventRouter>(
  1310. base::BindRepeating(&extensions::EventRouter::BindForRenderer,
  1311. render_process_id));
  1312. associated_registry.AddInterface<extensions::mojom::RendererHost>(
  1313. base::BindRepeating(&extensions::RendererStartupHelper::BindForRenderer,
  1314. render_process_id));
  1315. associated_registry.AddInterface<extensions::mojom::LocalFrameHost>(
  1316. base::BindRepeating(
  1317. [](content::RenderFrameHost* render_frame_host,
  1318. mojo::PendingAssociatedReceiver<extensions::mojom::LocalFrameHost>
  1319. receiver) {
  1320. extensions::ExtensionWebContentsObserver::BindLocalFrameHost(
  1321. std::move(receiver), render_frame_host);
  1322. },
  1323. &render_frame_host));
  1324. associated_registry.AddInterface<guest_view::mojom::GuestViewHost>(
  1325. base::BindRepeating(&extensions::ExtensionsGuestView::CreateForComponents,
  1326. render_frame_host.GetGlobalId()));
  1327. associated_registry.AddInterface<extensions::mojom::GuestView>(
  1328. base::BindRepeating(&extensions::ExtensionsGuestView::CreateForExtensions,
  1329. render_frame_host.GetGlobalId()));
  1330. #endif
  1331. #if BUILDFLAG(ENABLE_PDF_VIEWER)
  1332. associated_registry.AddInterface<pdf::mojom::PdfService>(base::BindRepeating(
  1333. [](content::RenderFrameHost* render_frame_host,
  1334. mojo::PendingAssociatedReceiver<pdf::mojom::PdfService> receiver) {
  1335. pdf::PDFDocumentHelper::BindPdfService(
  1336. std::move(receiver), render_frame_host,
  1337. std::make_unique<ElectronPDFDocumentHelperClient>());
  1338. },
  1339. &render_frame_host));
  1340. #endif
  1341. }
  1342. std::string ElectronBrowserClient::GetApplicationLocale() {
  1343. return BrowserThread::CurrentlyOn(BrowserThread::IO)
  1344. ? *g_io_thread_application_locale
  1345. : *g_application_locale;
  1346. }
  1347. bool ElectronBrowserClient::ShouldEnableStrictSiteIsolation() {
  1348. // Enable site isolation. It is off by default in Chromium <= 69.
  1349. return true;
  1350. }
  1351. void ElectronBrowserClient::BindHostReceiverForRenderer(
  1352. content::RenderProcessHost* render_process_host,
  1353. mojo::GenericPendingReceiver receiver) {
  1354. #if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
  1355. if (auto host_receiver =
  1356. receiver.As<spellcheck::mojom::SpellCheckInitializationHost>()) {
  1357. SpellCheckInitializationHostImpl::Create(render_process_host->GetID(),
  1358. std::move(host_receiver));
  1359. return;
  1360. }
  1361. #endif
  1362. }
  1363. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1364. void BindMimeHandlerService(
  1365. content::RenderFrameHost* frame_host,
  1366. mojo::PendingReceiver<extensions::mime_handler::MimeHandlerService>
  1367. receiver) {
  1368. content::WebContents* contents =
  1369. content::WebContents::FromRenderFrameHost(frame_host);
  1370. auto* guest_view =
  1371. extensions::MimeHandlerViewGuest::FromWebContents(contents);
  1372. if (!guest_view)
  1373. return;
  1374. extensions::MimeHandlerServiceImpl::Create(guest_view->GetStreamWeakPtr(),
  1375. std::move(receiver));
  1376. }
  1377. void BindBeforeUnloadControl(
  1378. content::RenderFrameHost* frame_host,
  1379. mojo::PendingReceiver<extensions::mime_handler::BeforeUnloadControl>
  1380. receiver) {
  1381. auto* web_contents = content::WebContents::FromRenderFrameHost(frame_host);
  1382. if (!web_contents)
  1383. return;
  1384. auto* guest_view =
  1385. extensions::MimeHandlerViewGuest::FromWebContents(web_contents);
  1386. if (!guest_view)
  1387. return;
  1388. guest_view->FuseBeforeUnloadControl(std::move(receiver));
  1389. }
  1390. #endif
  1391. void ElectronBrowserClient::ExposeInterfacesToRenderer(
  1392. service_manager::BinderRegistry* registry,
  1393. blink::AssociatedInterfaceRegistry* associated_registry,
  1394. content::RenderProcessHost* render_process_host) {
  1395. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1396. associated_registry->AddInterface<extensions::mojom::RendererHost>(
  1397. base::BindRepeating(&extensions::RendererStartupHelper::BindForRenderer,
  1398. render_process_host->GetID()));
  1399. #endif
  1400. }
  1401. void ElectronBrowserClient::RegisterBrowserInterfaceBindersForFrame(
  1402. content::RenderFrameHost* render_frame_host,
  1403. mojo::BinderMapWithContext<content::RenderFrameHost*>* map) {
  1404. map->Add<network_hints::mojom::NetworkHintsHandler>(
  1405. base::BindRepeating(&BindNetworkHintsHandler));
  1406. map->Add<blink::mojom::BadgeService>(
  1407. base::BindRepeating(&badging::BadgeManager::BindFrameReceiver));
  1408. map->Add<blink::mojom::KeyboardLockService>(base::BindRepeating(
  1409. &content::KeyboardLockServiceImpl::CreateMojoService));
  1410. #if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
  1411. map->Add<spellcheck::mojom::SpellCheckHost>(base::BindRepeating(
  1412. [](content::RenderFrameHost* frame_host,
  1413. mojo::PendingReceiver<spellcheck::mojom::SpellCheckHost> receiver) {
  1414. SpellCheckHostChromeImpl::Create(frame_host->GetProcess()->GetID(),
  1415. std::move(receiver));
  1416. }));
  1417. #endif
  1418. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1419. map->Add<extensions::mime_handler::MimeHandlerService>(
  1420. base::BindRepeating(&BindMimeHandlerService));
  1421. map->Add<extensions::mime_handler::BeforeUnloadControl>(
  1422. base::BindRepeating(&BindBeforeUnloadControl));
  1423. content::WebContents* web_contents =
  1424. content::WebContents::FromRenderFrameHost(render_frame_host);
  1425. if (!web_contents)
  1426. return;
  1427. const GURL& site = render_frame_host->GetSiteInstance()->GetSiteURL();
  1428. if (!site.SchemeIs(extensions::kExtensionScheme))
  1429. return;
  1430. content::BrowserContext* browser_context =
  1431. render_frame_host->GetProcess()->GetBrowserContext();
  1432. auto* extension = extensions::ExtensionRegistry::Get(browser_context)
  1433. ->enabled_extensions()
  1434. .GetByID(site.host());
  1435. if (!extension)
  1436. return;
  1437. extensions::ExtensionsBrowserClient::Get()
  1438. ->RegisterBrowserInterfaceBindersForFrame(map, render_frame_host,
  1439. extension);
  1440. #endif
  1441. }
  1442. #if BUILDFLAG(IS_LINUX)
  1443. void ElectronBrowserClient::GetAdditionalMappedFilesForChildProcess(
  1444. const base::CommandLine& command_line,
  1445. int child_process_id,
  1446. content::PosixFileDescriptorInfo* mappings) {
  1447. int crash_signal_fd = GetCrashSignalFD(command_line);
  1448. if (crash_signal_fd >= 0) {
  1449. mappings->Share(kCrashDumpSignal, crash_signal_fd);
  1450. }
  1451. }
  1452. #endif
  1453. std::unique_ptr<content::LoginDelegate>
  1454. ElectronBrowserClient::CreateLoginDelegate(
  1455. const net::AuthChallengeInfo& auth_info,
  1456. content::WebContents* web_contents,
  1457. content::BrowserContext* browser_context,
  1458. const content::GlobalRequestID& request_id,
  1459. bool is_main_frame,
  1460. const GURL& url,
  1461. scoped_refptr<net::HttpResponseHeaders> response_headers,
  1462. bool first_auth_attempt,
  1463. LoginAuthRequiredCallback auth_required_callback) {
  1464. return std::make_unique<LoginHandler>(
  1465. auth_info, web_contents, is_main_frame, url, response_headers,
  1466. first_auth_attempt, std::move(auth_required_callback));
  1467. }
  1468. std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
  1469. ElectronBrowserClient::CreateURLLoaderThrottles(
  1470. const network::ResourceRequest& request,
  1471. content::BrowserContext* browser_context,
  1472. const base::RepeatingCallback<content::WebContents*()>& wc_getter,
  1473. content::NavigationUIData* navigation_ui_data,
  1474. int frame_tree_node_id,
  1475. absl::optional<int64_t> navigation_id) {
  1476. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  1477. std::vector<std::unique_ptr<blink::URLLoaderThrottle>> result;
  1478. #if BUILDFLAG(ENABLE_PLUGINS) && BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1479. result.push_back(std::make_unique<PluginResponseInterceptorURLLoaderThrottle>(
  1480. request.destination, frame_tree_node_id));
  1481. #endif
  1482. return result;
  1483. }
  1484. base::flat_set<std::string>
  1485. ElectronBrowserClient::GetPluginMimeTypesWithExternalHandlers(
  1486. content::BrowserContext* browser_context) {
  1487. base::flat_set<std::string> mime_types;
  1488. #if BUILDFLAG(ENABLE_PLUGINS) && BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1489. auto map = PluginUtils::GetMimeTypeToExtensionIdMap(browser_context);
  1490. for (const auto& pair : map)
  1491. mime_types.insert(pair.first);
  1492. #endif
  1493. #if BUILDFLAG(ENABLE_PDF_VIEWER)
  1494. mime_types.insert(pdf::kInternalPluginMimeType);
  1495. #endif
  1496. return mime_types;
  1497. }
  1498. content::SerialDelegate* ElectronBrowserClient::GetSerialDelegate() {
  1499. if (!serial_delegate_)
  1500. serial_delegate_ = std::make_unique<ElectronSerialDelegate>();
  1501. return serial_delegate_.get();
  1502. }
  1503. content::BluetoothDelegate* ElectronBrowserClient::GetBluetoothDelegate() {
  1504. if (!bluetooth_delegate_)
  1505. bluetooth_delegate_ = std::make_unique<ElectronBluetoothDelegate>();
  1506. return bluetooth_delegate_.get();
  1507. }
  1508. content::UsbDelegate* ElectronBrowserClient::GetUsbDelegate() {
  1509. if (!usb_delegate_)
  1510. usb_delegate_ = std::make_unique<ElectronUsbDelegate>();
  1511. return usb_delegate_.get();
  1512. }
  1513. void BindBadgeServiceForServiceWorker(
  1514. const content::ServiceWorkerVersionBaseInfo& info,
  1515. mojo::PendingReceiver<blink::mojom::BadgeService> receiver) {
  1516. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  1517. content::RenderProcessHost* render_process_host =
  1518. content::RenderProcessHost::FromID(info.process_id);
  1519. if (!render_process_host)
  1520. return;
  1521. badging::BadgeManager::BindServiceWorkerReceiver(
  1522. render_process_host, info.scope, std::move(receiver));
  1523. }
  1524. void ElectronBrowserClient::RegisterBrowserInterfaceBindersForServiceWorker(
  1525. content::BrowserContext* browser_context,
  1526. const content::ServiceWorkerVersionBaseInfo& service_worker_version_info,
  1527. mojo::BinderMapWithContext<const content::ServiceWorkerVersionBaseInfo&>*
  1528. map) {
  1529. map->Add<blink::mojom::BadgeService>(
  1530. base::BindRepeating(&BindBadgeServiceForServiceWorker));
  1531. }
  1532. #if BUILDFLAG(IS_MAC)
  1533. device::GeolocationManager* ElectronBrowserClient::GetGeolocationManager() {
  1534. return device::GeolocationManager::GetInstance();
  1535. }
  1536. #endif
  1537. content::HidDelegate* ElectronBrowserClient::GetHidDelegate() {
  1538. if (!hid_delegate_)
  1539. hid_delegate_ = std::make_unique<ElectronHidDelegate>();
  1540. return hid_delegate_.get();
  1541. }
  1542. content::WebAuthenticationDelegate*
  1543. ElectronBrowserClient::GetWebAuthenticationDelegate() {
  1544. if (!web_authentication_delegate_) {
  1545. web_authentication_delegate_ =
  1546. std::make_unique<ElectronWebAuthenticationDelegate>();
  1547. }
  1548. return web_authentication_delegate_.get();
  1549. }
  1550. } // namespace electron