electron_browser_client.cc 66 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747
  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 "extensions/common/extension_id.h"
  58. #include "mojo/public/cpp/bindings/binder_map.h"
  59. #include "net/ssl/ssl_cert_request_info.h"
  60. #include "net/ssl/ssl_private_key.h"
  61. #include "ppapi/buildflags/buildflags.h"
  62. #include "ppapi/host/ppapi_host.h"
  63. #include "printing/buildflags/buildflags.h"
  64. #include "services/device/public/cpp/geolocation/geolocation_system_permission_manager.h"
  65. #include "services/device/public/cpp/geolocation/location_provider.h"
  66. #include "services/network/public/cpp/features.h"
  67. #include "services/network/public/cpp/is_potentially_trustworthy.h"
  68. #include "services/network/public/cpp/network_switches.h"
  69. #include "services/network/public/cpp/resource_request_body.h"
  70. #include "services/network/public/cpp/self_deleting_url_loader_factory.h"
  71. #include "services/network/public/cpp/url_loader_factory_builder.h"
  72. #include "shell/app/electron_crash_reporter_client.h"
  73. #include "shell/browser/api/electron_api_app.h"
  74. #include "shell/browser/api/electron_api_crash_reporter.h"
  75. #include "shell/browser/api/electron_api_protocol.h"
  76. #include "shell/browser/api/electron_api_session.h"
  77. #include "shell/browser/api/electron_api_web_contents.h"
  78. #include "shell/browser/api/electron_api_web_request.h"
  79. #include "shell/browser/badging/badge_manager.h"
  80. #include "shell/browser/child_web_contents_tracker.h"
  81. #include "shell/browser/electron_api_ipc_handler_impl.h"
  82. #include "shell/browser/electron_autofill_driver_factory.h"
  83. #include "shell/browser/electron_browser_context.h"
  84. #include "shell/browser/electron_browser_main_parts.h"
  85. #include "shell/browser/electron_navigation_throttle.h"
  86. #include "shell/browser/electron_speech_recognition_manager_delegate.h"
  87. #include "shell/browser/electron_web_contents_utility_handler_impl.h"
  88. #include "shell/browser/font_defaults.h"
  89. #include "shell/browser/javascript_environment.h"
  90. #include "shell/browser/media/media_capture_devices_dispatcher.h"
  91. #include "shell/browser/native_window.h"
  92. #include "shell/browser/net/network_context_service.h"
  93. #include "shell/browser/net/network_context_service_factory.h"
  94. #include "shell/browser/net/proxying_url_loader_factory.h"
  95. #include "shell/browser/net/proxying_websocket.h"
  96. #include "shell/browser/net/system_network_context_manager.h"
  97. #include "shell/browser/network_hints_handler_impl.h"
  98. #include "shell/browser/notifications/notification_presenter.h"
  99. #include "shell/browser/notifications/platform_notification_service.h"
  100. #include "shell/browser/protocol_registry.h"
  101. #include "shell/browser/serial/electron_serial_delegate.h"
  102. #include "shell/browser/session_preferences.h"
  103. #include "shell/browser/ui/devtools_manager_delegate.h"
  104. #include "shell/browser/web_contents_permission_helper.h"
  105. #include "shell/browser/web_contents_preferences.h"
  106. #include "shell/browser/webauthn/electron_authenticator_request_delegate.h"
  107. #include "shell/browser/window_list.h"
  108. #include "shell/common/api/api.mojom.h"
  109. #include "shell/common/application_info.h"
  110. #include "shell/common/electron_paths.h"
  111. #include "shell/common/logging.h"
  112. #include "shell/common/options_switches.h"
  113. #include "shell/common/platform_util.h"
  114. #include "shell/common/thread_restrictions.h"
  115. #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
  116. #include "third_party/blink/public/common/loader/url_loader_throttle.h"
  117. #include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
  118. #include "third_party/blink/public/common/tokens/tokens.h"
  119. #include "third_party/blink/public/common/web_preferences/web_preferences.h"
  120. #include "third_party/blink/public/mojom/badging/badging.mojom.h"
  121. #include "ui/base/resource/resource_bundle.h"
  122. #include "ui/native_theme/native_theme.h"
  123. #include "v8/include/v8.h"
  124. #if BUILDFLAG(USE_NSS_CERTS)
  125. #include "net/ssl/client_cert_store_nss.h"
  126. #elif BUILDFLAG(IS_WIN)
  127. #include "net/ssl/client_cert_store_win.h"
  128. #elif BUILDFLAG(IS_MAC)
  129. #include "net/ssl/client_cert_store_mac.h"
  130. #elif defined(USE_OPENSSL)
  131. #include "net/ssl/client_cert_store.h"
  132. #endif
  133. #if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
  134. #include "chrome/browser/spellchecker/spell_check_host_chrome_impl.h" // nogncheck
  135. #include "chrome/browser/spellchecker/spell_check_initialization_host_impl.h" // nogncheck
  136. #include "components/spellcheck/common/spellcheck.mojom.h" // nogncheck
  137. #endif
  138. #if BUILDFLAG(OVERRIDE_LOCATION_PROVIDER)
  139. #include "shell/browser/fake_location_provider.h"
  140. #endif // BUILDFLAG(OVERRIDE_LOCATION_PROVIDER)
  141. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  142. #include "base/functional/bind.h"
  143. #include "chrome/common/webui_url_constants.h"
  144. #include "components/guest_view/common/guest_view.mojom.h"
  145. #include "content/public/browser/child_process_security_policy.h"
  146. #include "content/public/browser/file_url_loader.h"
  147. #include "content/public/browser/web_ui_url_loader_factory.h"
  148. #include "extensions/browser/api/mime_handler_private/mime_handler_private.h"
  149. #include "extensions/browser/api/web_request/web_request_api.h"
  150. #include "extensions/browser/browser_context_keyed_api_factory.h"
  151. #include "extensions/browser/event_router.h"
  152. #include "extensions/browser/extension_host.h"
  153. #include "extensions/browser/extension_navigation_throttle.h"
  154. #include "extensions/browser/extension_prefs.h"
  155. #include "extensions/browser/extension_protocols.h"
  156. #include "extensions/browser/extension_registry.h"
  157. #include "extensions/browser/extensions_browser_client.h"
  158. #include "extensions/browser/guest_view/extensions_guest_view.h"
  159. #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
  160. #include "extensions/browser/process_manager.h"
  161. #include "extensions/browser/process_map.h"
  162. #include "extensions/browser/renderer_startup_helper.h"
  163. #include "extensions/browser/service_worker/service_worker_host.h"
  164. #include "extensions/browser/url_loader_factory_manager.h"
  165. #include "extensions/common/api/mime_handler.mojom.h"
  166. #include "extensions/common/constants.h"
  167. #include "extensions/common/extension.h"
  168. #include "extensions/common/mojom/event_router.mojom.h"
  169. #include "extensions/common/mojom/guest_view.mojom.h"
  170. #include "extensions/common/mojom/renderer_host.mojom.h"
  171. #include "extensions/common/switches.h"
  172. #include "shell/browser/extensions/electron_extension_system.h"
  173. #include "shell/browser/extensions/electron_extension_web_contents_observer.h"
  174. #endif
  175. #if BUILDFLAG(ENABLE_PLUGINS)
  176. #include "chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.h" // nogncheck
  177. #include "shell/browser/plugins/plugin_utils.h"
  178. #endif
  179. #if BUILDFLAG(IS_MAC)
  180. #include "content/browser/mac_helpers.h"
  181. #include "content/public/browser/child_process_host.h"
  182. #endif
  183. #if BUILDFLAG(IS_LINUX)
  184. #include "components/crash/core/app/crash_switches.h" // nogncheck
  185. #include "components/crash/core/app/crashpad.h" // nogncheck
  186. #endif
  187. #if BUILDFLAG(IS_WIN)
  188. #include "chrome/browser/ui/views/overlay/video_overlay_window_views.h"
  189. #include "shell/browser/browser.h"
  190. #include "ui/aura/window.h"
  191. #include "ui/aura/window_tree_host.h"
  192. #include "ui/base/win/shell.h"
  193. #include "ui/views/widget/widget.h"
  194. #endif
  195. #if BUILDFLAG(ENABLE_PRINTING)
  196. #include "shell/browser/printing/print_view_manager_electron.h"
  197. #endif
  198. #if BUILDFLAG(ENABLE_PDF_VIEWER)
  199. #include "chrome/browser/pdf/chrome_pdf_stream_delegate.h"
  200. #include "chrome/browser/plugins/pdf_iframe_navigation_throttle.h" // nogncheck
  201. #include "components/pdf/browser/pdf_document_helper.h" // nogncheck
  202. #include "components/pdf/browser/pdf_navigation_throttle.h"
  203. #include "components/pdf/browser/pdf_url_loader_request_interceptor.h"
  204. #include "components/pdf/common/constants.h" // nogncheck
  205. #include "shell/browser/electron_pdf_document_helper_client.h"
  206. #endif
  207. using content::BrowserThread;
  208. namespace electron {
  209. namespace {
  210. ElectronBrowserClient* g_browser_client = nullptr;
  211. base::NoDestructor<std::string> g_io_thread_application_locale;
  212. base::NoDestructor<std::string> g_application_locale;
  213. void SetApplicationLocaleOnIOThread(const std::string& locale) {
  214. DCHECK_CURRENTLY_ON(BrowserThread::IO);
  215. *g_io_thread_application_locale = locale;
  216. }
  217. void BindNetworkHintsHandler(
  218. content::RenderFrameHost* frame_host,
  219. mojo::PendingReceiver<network_hints::mojom::NetworkHintsHandler> receiver) {
  220. NetworkHintsHandlerImpl::Create(frame_host, std::move(receiver));
  221. }
  222. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  223. // Used by the GetPrivilegeRequiredByUrl() and GetProcessPrivilege() functions
  224. // below. Extension, and isolated apps require different privileges to be
  225. // granted to their RenderProcessHosts. This classification allows us to make
  226. // sure URLs are served by hosts with the right set of privileges.
  227. enum class RenderProcessHostPrivilege {
  228. kNormal,
  229. kHosted,
  230. kIsolated,
  231. kExtension,
  232. };
  233. // Copied from chrome/browser/extensions/extension_util.cc.
  234. bool AllowFileAccess(const std::string& extension_id,
  235. content::BrowserContext* context) {
  236. return base::CommandLine::ForCurrentProcess()->HasSwitch(
  237. extensions::switches::kDisableExtensionsFileAccessCheck) ||
  238. extensions::ExtensionPrefs::Get(context)->AllowFileAccess(
  239. extension_id);
  240. }
  241. RenderProcessHostPrivilege GetPrivilegeRequiredByUrl(
  242. const GURL& url,
  243. extensions::ExtensionRegistry* registry) {
  244. // Default to a normal renderer cause it is lower privileged. This should only
  245. // occur if the URL on a site instance is either malformed, or uninitialized.
  246. // If it is malformed, then there is no need for better privileges anyways.
  247. // If it is uninitialized, but eventually settles on being an a scheme other
  248. // than normal webrenderer, the navigation logic will correct us out of band
  249. // anyways.
  250. if (!url.is_valid())
  251. return RenderProcessHostPrivilege::kNormal;
  252. if (!url.SchemeIs(extensions::kExtensionScheme))
  253. return RenderProcessHostPrivilege::kNormal;
  254. return RenderProcessHostPrivilege::kExtension;
  255. }
  256. RenderProcessHostPrivilege GetProcessPrivilege(
  257. content::RenderProcessHost* process_host,
  258. extensions::ProcessMap* process_map) {
  259. std::optional<extensions::ExtensionId> extension_id =
  260. process_map->GetExtensionIdForProcess(process_host->GetID());
  261. if (!extension_id.has_value())
  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->in_forced_colors = native_theme->InForcedColorsMode();
  378. prefs->preferred_color_scheme =
  379. native_theme->ShouldUseDarkColors()
  380. ? blink::mojom::PreferredColorScheme::kDark
  381. : blink::mojom::PreferredColorScheme::kLight;
  382. SetFontDefaults(prefs);
  383. // Custom preferences of guest page.
  384. auto* web_preferences = WebContentsPreferences::From(web_contents);
  385. if (web_preferences) {
  386. web_preferences->OverrideWebkitPrefs(prefs, renderer_prefs);
  387. }
  388. }
  389. void ElectronBrowserClient::RegisterPendingSiteInstance(
  390. content::RenderFrameHost* rfh,
  391. content::SiteInstance* pending_site_instance) {
  392. // Remember the original web contents for the pending renderer process.
  393. auto* web_contents = content::WebContents::FromRenderFrameHost(rfh);
  394. auto* pending_process = pending_site_instance->GetProcess();
  395. pending_processes_[pending_process->GetID()] = web_contents;
  396. if (rfh->GetParent())
  397. renderer_is_subframe_.insert(pending_process->GetID());
  398. else
  399. renderer_is_subframe_.erase(pending_process->GetID());
  400. }
  401. void ElectronBrowserClient::AppendExtraCommandLineSwitches(
  402. base::CommandLine* command_line,
  403. int process_id) {
  404. // Make sure we're about to launch a known executable
  405. #if BUILDFLAG(IS_LINUX)
  406. // On Linux, do not perform this check for /proc/self/exe. It will always
  407. // point to the currently running executable so this check is not
  408. // necessary, and if the executable has been deleted it will return a fake
  409. // name that causes this check to fail.
  410. if (command_line->GetProgram() != base::FilePath(base::kProcSelfExe)) {
  411. #else
  412. {
  413. #endif
  414. ScopedAllowBlockingForElectron allow_blocking;
  415. base::FilePath child_path;
  416. base::FilePath program =
  417. base::MakeAbsoluteFilePath(command_line->GetProgram());
  418. #if BUILDFLAG(IS_MAC)
  419. auto renderer_child_path = content::ChildProcessHost::GetChildPath(
  420. content::ChildProcessHost::CHILD_RENDERER);
  421. auto gpu_child_path = content::ChildProcessHost::GetChildPath(
  422. content::ChildProcessHost::CHILD_GPU);
  423. auto plugin_child_path = content::ChildProcessHost::GetChildPath(
  424. content::ChildProcessHost::CHILD_PLUGIN);
  425. if (program != renderer_child_path && program != gpu_child_path &&
  426. program != plugin_child_path) {
  427. child_path = content::ChildProcessHost::GetChildPath(
  428. content::ChildProcessHost::CHILD_NORMAL);
  429. CHECK_EQ(program, child_path)
  430. << "Aborted from launching unexpected helper executable";
  431. }
  432. #else
  433. if (!base::PathService::Get(content::CHILD_PROCESS_EXE, &child_path)) {
  434. CHECK(false) << "Unable to get child process binary name.";
  435. }
  436. SCOPED_CRASH_KEY_STRING256("ChildProcess", "child_process_exe",
  437. child_path.AsUTF8Unsafe());
  438. SCOPED_CRASH_KEY_STRING256("ChildProcess", "program",
  439. program.AsUTF8Unsafe());
  440. CHECK_EQ(program, child_path);
  441. #endif
  442. }
  443. std::string process_type =
  444. command_line->GetSwitchValueASCII(::switches::kProcessType);
  445. #if BUILDFLAG(IS_LINUX)
  446. pid_t pid;
  447. if (crash_reporter::GetHandlerSocket(nullptr, &pid)) {
  448. command_line->AppendSwitchASCII(
  449. crash_reporter::switches::kCrashpadHandlerPid,
  450. base::NumberToString(pid));
  451. }
  452. // Zygote Process gets booted before any JS runs, accessing GetClientId
  453. // will end up touching DIR_USER_DATA path provider and this will
  454. // configure default value because app.name from browser_init has
  455. // not run yet.
  456. if (process_type != ::switches::kZygoteProcess) {
  457. std::string switch_value =
  458. api::crash_reporter::GetClientId() + ",no_channel";
  459. command_line->AppendSwitchASCII(::switches::kEnableCrashReporter,
  460. switch_value);
  461. }
  462. #endif
  463. // The zygote process is booted before JS runs, so DIR_USER_DATA isn't usable
  464. // at that time. It doesn't need --user-data-dir to be correct anyway, since
  465. // the zygote itself doesn't access anything in that directory.
  466. if (process_type != ::switches::kZygoteProcess) {
  467. base::FilePath user_data_dir;
  468. if (base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
  469. command_line->AppendSwitchPath(::switches::kUserDataDir, user_data_dir);
  470. }
  471. if (process_type == ::switches::kUtilityProcess ||
  472. process_type == ::switches::kRendererProcess) {
  473. // Copy following switches to child process.
  474. static const char* const kCommonSwitchNames[] = {
  475. switches::kStandardSchemes, switches::kEnableSandbox,
  476. switches::kSecureSchemes, switches::kBypassCSPSchemes,
  477. switches::kCORSSchemes, switches::kFetchSchemes,
  478. switches::kServiceWorkerSchemes, switches::kStreamingSchemes,
  479. switches::kCodeCacheSchemes};
  480. command_line->CopySwitchesFrom(*base::CommandLine::ForCurrentProcess(),
  481. kCommonSwitchNames);
  482. if (process_type == ::switches::kUtilityProcess ||
  483. content::RenderProcessHost::FromID(process_id)) {
  484. MaybeAppendSecureOriginsAllowlistSwitch(command_line);
  485. }
  486. }
  487. if (process_type == ::switches::kRendererProcess) {
  488. #if BUILDFLAG(IS_WIN)
  489. // Append --app-user-model-id.
  490. PWSTR current_app_id;
  491. if (SUCCEEDED(GetCurrentProcessExplicitAppUserModelID(&current_app_id))) {
  492. command_line->AppendSwitchNative(switches::kAppUserModelId,
  493. current_app_id);
  494. CoTaskMemFree(current_app_id);
  495. }
  496. #endif
  497. if (delegate_) {
  498. auto app_path = static_cast<api::App*>(delegate_)->GetAppPath();
  499. command_line->AppendSwitchPath(switches::kAppPath, app_path);
  500. }
  501. auto env = base::Environment::Create();
  502. if (env->HasVar("ELECTRON_PROFILE_INIT_SCRIPTS")) {
  503. command_line->AppendSwitch("profile-electron-init");
  504. }
  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) == privilege_required;
  664. #else
  665. return content::ContentBrowserClient::IsSuitableHost(process_host, site_url);
  666. #endif
  667. }
  668. bool ElectronBrowserClient::ShouldUseProcessPerSite(
  669. content::BrowserContext* browser_context,
  670. const GURL& effective_url) {
  671. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  672. const extensions::Extension* extension =
  673. GetEnabledExtensionFromEffectiveURL(browser_context, effective_url);
  674. return extension != nullptr;
  675. #else
  676. return content::ContentBrowserClient::ShouldUseProcessPerSite(browser_context,
  677. effective_url);
  678. #endif
  679. }
  680. void ElectronBrowserClient::GetMediaDeviceIDSalt(
  681. content::RenderFrameHost* rfh,
  682. const net::SiteForCookies& site_for_cookies,
  683. const blink::StorageKey& storage_key,
  684. base::OnceCallback<void(bool, const std::string&)> callback) {
  685. constexpr bool persistent_media_device_id_allowed = true;
  686. std::string persistent_media_device_id_salt =
  687. static_cast<ElectronBrowserContext*>(rfh->GetBrowserContext())
  688. ->GetMediaDeviceIDSalt();
  689. std::move(callback).Run(persistent_media_device_id_allowed,
  690. persistent_media_device_id_salt);
  691. }
  692. base::FilePath ElectronBrowserClient::GetLoggingFileName(
  693. const base::CommandLine& cmd_line) {
  694. return logging::GetLogFileName(cmd_line);
  695. }
  696. std::unique_ptr<net::ClientCertStore>
  697. ElectronBrowserClient::CreateClientCertStore(
  698. content::BrowserContext* browser_context) {
  699. #if BUILDFLAG(USE_NSS_CERTS)
  700. return std::make_unique<net::ClientCertStoreNSS>(
  701. net::ClientCertStoreNSS::PasswordDelegateFactory());
  702. #elif BUILDFLAG(IS_WIN)
  703. return std::make_unique<net::ClientCertStoreWin>();
  704. #elif BUILDFLAG(IS_MAC)
  705. return std::make_unique<net::ClientCertStoreMac>();
  706. #elif defined(USE_OPENSSL)
  707. return std::unique_ptr<net::ClientCertStore>();
  708. #endif
  709. }
  710. std::unique_ptr<device::LocationProvider>
  711. ElectronBrowserClient::OverrideSystemLocationProvider() {
  712. #if BUILDFLAG(OVERRIDE_LOCATION_PROVIDER)
  713. return std::make_unique<FakeLocationProvider>();
  714. #else
  715. return nullptr;
  716. #endif
  717. }
  718. void ElectronBrowserClient::ConfigureNetworkContextParams(
  719. content::BrowserContext* browser_context,
  720. bool in_memory,
  721. const base::FilePath& relative_partition_path,
  722. network::mojom::NetworkContextParams* network_context_params,
  723. cert_verifier::mojom::CertVerifierCreationParams*
  724. cert_verifier_creation_params) {
  725. DCHECK(browser_context);
  726. return NetworkContextServiceFactory::GetForContext(browser_context)
  727. ->ConfigureNetworkContextParams(network_context_params,
  728. cert_verifier_creation_params);
  729. }
  730. network::mojom::NetworkContext*
  731. ElectronBrowserClient::GetSystemNetworkContext() {
  732. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  733. DCHECK(g_browser_process->system_network_context_manager());
  734. return g_browser_process->system_network_context_manager()->GetContext();
  735. }
  736. std::unique_ptr<content::BrowserMainParts>
  737. ElectronBrowserClient::CreateBrowserMainParts(bool /* is_integration_test */) {
  738. return std::make_unique<ElectronBrowserMainParts>();
  739. }
  740. void ElectronBrowserClient::WebNotificationAllowed(
  741. content::RenderFrameHost* rfh,
  742. base::OnceCallback<void(bool, bool)> callback) {
  743. content::WebContents* web_contents =
  744. content::WebContents::FromRenderFrameHost(rfh);
  745. if (!web_contents) {
  746. std::move(callback).Run(false, false);
  747. return;
  748. }
  749. auto* permission_helper =
  750. WebContentsPermissionHelper::FromWebContents(web_contents);
  751. if (!permission_helper) {
  752. std::move(callback).Run(false, false);
  753. return;
  754. }
  755. permission_helper->RequestWebNotificationPermission(
  756. rfh, base::BindOnce(std::move(callback), web_contents->IsAudioMuted()));
  757. }
  758. void ElectronBrowserClient::RenderProcessHostDestroyed(
  759. content::RenderProcessHost* host) {
  760. int process_id = host->GetID();
  761. pending_processes_.erase(process_id);
  762. renderer_is_subframe_.erase(process_id);
  763. host->RemoveObserver(this);
  764. }
  765. void ElectronBrowserClient::RenderProcessReady(
  766. content::RenderProcessHost* host) {
  767. if (delegate_) {
  768. static_cast<api::App*>(delegate_)->RenderProcessReady(host);
  769. }
  770. }
  771. void ElectronBrowserClient::RenderProcessExited(
  772. content::RenderProcessHost* host,
  773. const content::ChildProcessTerminationInfo& info) {
  774. if (delegate_) {
  775. static_cast<api::App*>(delegate_)->RenderProcessExited(host);
  776. }
  777. }
  778. namespace {
  779. void OnOpenExternal(const GURL& escaped_url, bool allowed) {
  780. if (allowed) {
  781. platform_util::OpenExternal(
  782. escaped_url, platform_util::OpenExternalOptions(), base::DoNothing());
  783. }
  784. }
  785. void HandleExternalProtocolInUI(
  786. const GURL& url,
  787. content::WeakDocumentPtr document_ptr,
  788. content::WebContents::OnceGetter web_contents_getter,
  789. bool has_user_gesture) {
  790. content::WebContents* web_contents = std::move(web_contents_getter).Run();
  791. if (!web_contents)
  792. return;
  793. auto* permission_helper =
  794. WebContentsPermissionHelper::FromWebContents(web_contents);
  795. if (!permission_helper)
  796. return;
  797. content::RenderFrameHost* rfh = document_ptr.AsRenderFrameHostIfValid();
  798. if (!rfh) {
  799. // If the render frame host is not valid it means it was a top level
  800. // navigation and the frame has already been disposed of. In this case we
  801. // take the current main frame and declare it responsible for the
  802. // transition.
  803. rfh = web_contents->GetPrimaryMainFrame();
  804. }
  805. GURL escaped_url(base::EscapeExternalHandlerValue(url.spec()));
  806. auto callback = base::BindOnce(&OnOpenExternal, escaped_url);
  807. permission_helper->RequestOpenExternalPermission(rfh, std::move(callback),
  808. has_user_gesture, url);
  809. }
  810. } // namespace
  811. bool ElectronBrowserClient::HandleExternalProtocol(
  812. const GURL& url,
  813. content::WebContents::Getter web_contents_getter,
  814. int frame_tree_node_id,
  815. content::NavigationUIData* navigation_data,
  816. bool is_primary_main_frame,
  817. bool is_in_fenced_frame_tree,
  818. network::mojom::WebSandboxFlags sandbox_flags,
  819. ui::PageTransition page_transition,
  820. bool has_user_gesture,
  821. const std::optional<url::Origin>& initiating_origin,
  822. content::RenderFrameHost* initiator_document,
  823. mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory) {
  824. content::GetUIThreadTaskRunner({})->PostTask(
  825. FROM_HERE,
  826. base::BindOnce(&HandleExternalProtocolInUI, url,
  827. initiator_document
  828. ? initiator_document->GetWeakDocumentPtr()
  829. : content::WeakDocumentPtr(),
  830. std::move(web_contents_getter), has_user_gesture));
  831. return true;
  832. }
  833. std::vector<std::unique_ptr<content::NavigationThrottle>>
  834. ElectronBrowserClient::CreateThrottlesForNavigation(
  835. content::NavigationHandle* handle) {
  836. std::vector<std::unique_ptr<content::NavigationThrottle>> throttles;
  837. throttles.push_back(std::make_unique<ElectronNavigationThrottle>(handle));
  838. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  839. throttles.push_back(
  840. std::make_unique<extensions::ExtensionNavigationThrottle>(handle));
  841. #endif
  842. #if BUILDFLAG(ENABLE_PDF_VIEWER)
  843. throttles.push_back(std::make_unique<PDFIFrameNavigationThrottle>(handle));
  844. throttles.push_back(std::make_unique<pdf::PdfNavigationThrottle>(
  845. handle, std::make_unique<ChromePdfStreamDelegate>()));
  846. #endif
  847. return throttles;
  848. }
  849. content::MediaObserver* ElectronBrowserClient::GetMediaObserver() {
  850. return MediaCaptureDevicesDispatcher::GetInstance();
  851. }
  852. std::unique_ptr<content::DevToolsManagerDelegate>
  853. ElectronBrowserClient::CreateDevToolsManagerDelegate() {
  854. return std::make_unique<DevToolsManagerDelegate>();
  855. }
  856. NotificationPresenter* ElectronBrowserClient::GetNotificationPresenter() {
  857. if (!notification_presenter_)
  858. notification_presenter_ = NotificationPresenter::Create();
  859. return notification_presenter_.get();
  860. }
  861. content::PlatformNotificationService*
  862. ElectronBrowserClient::GetPlatformNotificationService() {
  863. if (!notification_service_) {
  864. notification_service_ = std::make_unique<PlatformNotificationService>(this);
  865. }
  866. return notification_service_.get();
  867. }
  868. base::FilePath ElectronBrowserClient::GetDefaultDownloadDirectory() {
  869. base::FilePath download_path;
  870. if (base::PathService::Get(chrome::DIR_DEFAULT_DOWNLOADS, &download_path))
  871. return download_path;
  872. return base::FilePath();
  873. }
  874. scoped_refptr<network::SharedURLLoaderFactory>
  875. ElectronBrowserClient::GetSystemSharedURLLoaderFactory() {
  876. if (!g_browser_process)
  877. return nullptr;
  878. return g_browser_process->shared_url_loader_factory();
  879. }
  880. void ElectronBrowserClient::OnNetworkServiceCreated(
  881. network::mojom::NetworkService* network_service) {
  882. if (!g_browser_process)
  883. return;
  884. g_browser_process->system_network_context_manager()->OnNetworkServiceCreated(
  885. network_service);
  886. }
  887. std::vector<base::FilePath>
  888. ElectronBrowserClient::GetNetworkContextsParentDirectory() {
  889. base::FilePath session_data;
  890. base::PathService::Get(DIR_SESSION_DATA, &session_data);
  891. DCHECK(!session_data.empty());
  892. return {session_data};
  893. }
  894. std::string ElectronBrowserClient::GetProduct() {
  895. return "Chrome/" CHROME_VERSION_STRING;
  896. }
  897. std::string ElectronBrowserClient::GetUserAgent() {
  898. if (user_agent_override_.empty())
  899. return GetApplicationUserAgent();
  900. return user_agent_override_;
  901. }
  902. void ElectronBrowserClient::SetUserAgent(const std::string& user_agent) {
  903. user_agent_override_ = user_agent;
  904. }
  905. blink::UserAgentMetadata ElectronBrowserClient::GetUserAgentMetadata() {
  906. return embedder_support::GetUserAgentMetadata();
  907. }
  908. mojo::PendingRemote<network::mojom::URLLoaderFactory>
  909. ElectronBrowserClient::CreateNonNetworkNavigationURLLoaderFactory(
  910. const std::string& scheme,
  911. int frame_tree_node_id) {
  912. content::WebContents* web_contents =
  913. content::WebContents::FromFrameTreeNodeId(frame_tree_node_id);
  914. content::BrowserContext* context = web_contents->GetBrowserContext();
  915. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  916. if (scheme == extensions::kExtensionScheme) {
  917. return extensions::CreateExtensionNavigationURLLoaderFactory(
  918. context, false /* we don't support extensions::WebViewGuest */);
  919. }
  920. #endif
  921. // Always allow navigating to file:// URLs.
  922. auto* protocol_registry = ProtocolRegistry::FromBrowserContext(context);
  923. return protocol_registry->CreateNonNetworkNavigationURLLoaderFactory(scheme);
  924. }
  925. void ElectronBrowserClient::
  926. RegisterNonNetworkWorkerMainResourceURLLoaderFactories(
  927. content::BrowserContext* browser_context,
  928. NonNetworkURLLoaderFactoryMap* factories) {
  929. auto* protocol_registry =
  930. ProtocolRegistry::FromBrowserContext(browser_context);
  931. // Workers are not allowed to request file:// URLs, there is no particular
  932. // reason for it, and we could consider supporting it in future.
  933. protocol_registry->RegisterURLLoaderFactories(factories,
  934. false /* allow_file_access */);
  935. }
  936. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  937. namespace {
  938. // The FileURLLoaderFactory provided to the extension background pages.
  939. // Checks with the ChildProcessSecurityPolicy to validate the file access.
  940. class FileURLLoaderFactory : public network::SelfDeletingURLLoaderFactory {
  941. public:
  942. static mojo::PendingRemote<network::mojom::URLLoaderFactory> Create(
  943. int child_id) {
  944. mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_remote;
  945. // The FileURLLoaderFactory will delete itself when there are no more
  946. // receivers - see the SelfDeletingURLLoaderFactory::OnDisconnect method.
  947. new FileURLLoaderFactory(child_id,
  948. pending_remote.InitWithNewPipeAndPassReceiver());
  949. return pending_remote;
  950. }
  951. // disable copy
  952. FileURLLoaderFactory(const FileURLLoaderFactory&) = delete;
  953. FileURLLoaderFactory& operator=(const FileURLLoaderFactory&) = delete;
  954. private:
  955. explicit FileURLLoaderFactory(
  956. int child_id,
  957. mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver)
  958. : network::SelfDeletingURLLoaderFactory(std::move(factory_receiver)),
  959. child_id_(child_id) {}
  960. ~FileURLLoaderFactory() override = default;
  961. // network::mojom::URLLoaderFactory:
  962. void CreateLoaderAndStart(
  963. mojo::PendingReceiver<network::mojom::URLLoader> loader,
  964. int32_t request_id,
  965. uint32_t options,
  966. const network::ResourceRequest& request,
  967. mojo::PendingRemote<network::mojom::URLLoaderClient> client,
  968. const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
  969. override {
  970. if (!content::ChildProcessSecurityPolicy::GetInstance()->CanRequestURL(
  971. child_id_, request.url)) {
  972. mojo::Remote<network::mojom::URLLoaderClient>(std::move(client))
  973. ->OnComplete(
  974. network::URLLoaderCompletionStatus(net::ERR_ACCESS_DENIED));
  975. return;
  976. }
  977. content::CreateFileURLLoaderBypassingSecurityChecks(
  978. request, std::move(loader), std::move(client),
  979. /*observer=*/nullptr,
  980. /* allow_directory_listing */ true);
  981. }
  982. int child_id_;
  983. };
  984. } // namespace
  985. #endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  986. void ElectronBrowserClient::RegisterNonNetworkSubresourceURLLoaderFactories(
  987. int render_process_id,
  988. int render_frame_id,
  989. const std::optional<url::Origin>& request_initiator_origin,
  990. NonNetworkURLLoaderFactoryMap* factories) {
  991. auto* render_process_host =
  992. content::RenderProcessHost::FromID(render_process_id);
  993. DCHECK(render_process_host);
  994. if (!render_process_host || !render_process_host->GetBrowserContext())
  995. return;
  996. content::RenderFrameHost* frame_host =
  997. content::RenderFrameHost::FromID(render_process_id, render_frame_id);
  998. content::WebContents* web_contents =
  999. content::WebContents::FromRenderFrameHost(frame_host);
  1000. // Allow accessing file:// subresources from non-file protocols if web
  1001. // security is disabled.
  1002. bool allow_file_access = false;
  1003. if (web_contents) {
  1004. const auto& web_preferences = web_contents->GetOrCreateWebPreferences();
  1005. if (!web_preferences.web_security_enabled)
  1006. allow_file_access = true;
  1007. }
  1008. ProtocolRegistry::FromBrowserContext(render_process_host->GetBrowserContext())
  1009. ->RegisterURLLoaderFactories(factories, allow_file_access);
  1010. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1011. auto factory = extensions::CreateExtensionURLLoaderFactory(render_process_id,
  1012. render_frame_id);
  1013. if (factory)
  1014. factories->emplace(extensions::kExtensionScheme, std::move(factory));
  1015. if (!web_contents)
  1016. return;
  1017. extensions::ElectronExtensionWebContentsObserver* web_observer =
  1018. extensions::ElectronExtensionWebContentsObserver::FromWebContents(
  1019. web_contents);
  1020. // There is nothing to do if no ElectronExtensionWebContentsObserver is
  1021. // attached to the |web_contents|.
  1022. if (!web_observer)
  1023. return;
  1024. const extensions::Extension* extension =
  1025. web_observer->GetExtensionFromFrame(frame_host, false);
  1026. if (!extension)
  1027. return;
  1028. // Support for chrome:// scheme if appropriate.
  1029. if (extension->is_extension() &&
  1030. extensions::Manifest::IsComponentLocation(extension->location())) {
  1031. // Components of chrome that are implemented as extensions or platform apps
  1032. // are allowed to use chrome://resources/ and chrome://theme/ URLs.
  1033. factories->emplace(content::kChromeUIScheme,
  1034. content::CreateWebUIURLLoaderFactory(
  1035. frame_host, content::kChromeUIScheme,
  1036. {content::kChromeUIResourcesHost}));
  1037. }
  1038. // Extensions with the necessary permissions get access to file:// URLs that
  1039. // gets approval from ChildProcessSecurityPolicy. Keep this logic in sync with
  1040. // ExtensionWebContentsObserver::RenderFrameCreated.
  1041. extensions::Manifest::Type type = extension->GetType();
  1042. if (type == extensions::Manifest::TYPE_EXTENSION &&
  1043. AllowFileAccess(extension->id(), web_contents->GetBrowserContext())) {
  1044. factories->emplace(url::kFileScheme,
  1045. FileURLLoaderFactory::Create(render_process_id));
  1046. }
  1047. #endif
  1048. }
  1049. void ElectronBrowserClient::
  1050. RegisterNonNetworkServiceWorkerUpdateURLLoaderFactories(
  1051. content::BrowserContext* browser_context,
  1052. NonNetworkURLLoaderFactoryMap* factories) {
  1053. DCHECK(browser_context);
  1054. DCHECK(factories);
  1055. auto* protocol_registry =
  1056. ProtocolRegistry::FromBrowserContext(browser_context);
  1057. protocol_registry->RegisterURLLoaderFactories(factories,
  1058. false /* allow_file_access */);
  1059. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1060. factories->emplace(
  1061. extensions::kExtensionScheme,
  1062. extensions::CreateExtensionServiceWorkerScriptURLLoaderFactory(
  1063. browser_context));
  1064. #endif // BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1065. }
  1066. bool ElectronBrowserClient::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
  1067. base::StringPiece scheme,
  1068. bool is_embedded_origin_secure) {
  1069. if (is_embedded_origin_secure && scheme == content::kChromeUIScheme)
  1070. return true;
  1071. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1072. return scheme == extensions::kExtensionScheme;
  1073. #else
  1074. return false;
  1075. #endif
  1076. }
  1077. bool ElectronBrowserClient::WillInterceptWebSocket(
  1078. content::RenderFrameHost* frame) {
  1079. if (!frame)
  1080. return false;
  1081. v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
  1082. v8::HandleScope scope(isolate);
  1083. auto* browser_context = frame->GetProcess()->GetBrowserContext();
  1084. auto web_request = api::WebRequest::FromOrCreate(isolate, browser_context);
  1085. // NOTE: Some unit test environments do not initialize
  1086. // BrowserContextKeyedAPI factories for e.g. WebRequest.
  1087. if (!web_request.get())
  1088. return false;
  1089. bool has_listener = web_request->HasListener();
  1090. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1091. const auto* web_request_api =
  1092. extensions::BrowserContextKeyedAPIFactory<extensions::WebRequestAPI>::Get(
  1093. browser_context);
  1094. if (web_request_api)
  1095. has_listener |= web_request_api->MayHaveProxies();
  1096. #endif
  1097. return has_listener;
  1098. }
  1099. void ElectronBrowserClient::CreateWebSocket(
  1100. content::RenderFrameHost* frame,
  1101. WebSocketFactory factory,
  1102. const GURL& url,
  1103. const net::SiteForCookies& site_for_cookies,
  1104. const std::optional<std::string>& user_agent,
  1105. mojo::PendingRemote<network::mojom::WebSocketHandshakeClient>
  1106. handshake_client) {
  1107. v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
  1108. v8::HandleScope scope(isolate);
  1109. auto* browser_context = frame->GetProcess()->GetBrowserContext();
  1110. auto web_request = api::WebRequest::FromOrCreate(isolate, browser_context);
  1111. DCHECK(web_request.get());
  1112. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1113. if (!web_request->HasListener()) {
  1114. auto* web_request_api = extensions::BrowserContextKeyedAPIFactory<
  1115. extensions::WebRequestAPI>::Get(browser_context);
  1116. if (web_request_api && web_request_api->MayHaveProxies()) {
  1117. web_request_api->ProxyWebSocket(frame, std::move(factory), url,
  1118. site_for_cookies, user_agent,
  1119. std::move(handshake_client));
  1120. return;
  1121. }
  1122. }
  1123. #endif
  1124. ProxyingWebSocket::StartProxying(
  1125. web_request.get(), std::move(factory), url, site_for_cookies, user_agent,
  1126. std::move(handshake_client), true, frame->GetProcess()->GetID(),
  1127. frame->GetRoutingID(), frame->GetLastCommittedOrigin(), browser_context,
  1128. &next_id_);
  1129. }
  1130. void ElectronBrowserClient::WillCreateURLLoaderFactory(
  1131. content::BrowserContext* browser_context,
  1132. content::RenderFrameHost* frame_host,
  1133. int render_process_id,
  1134. URLLoaderFactoryType type,
  1135. const url::Origin& request_initiator,
  1136. const net::IsolationInfo& isolation_info,
  1137. std::optional<int64_t> navigation_id,
  1138. ukm::SourceIdObj ukm_source_id,
  1139. network::URLLoaderFactoryBuilder& factory_builder,
  1140. mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>*
  1141. header_client,
  1142. bool* bypass_redirect_checks,
  1143. bool* disable_secure_dns,
  1144. network::mojom::URLLoaderFactoryOverridePtr* factory_override,
  1145. scoped_refptr<base::SequencedTaskRunner> navigation_response_task_runner) {
  1146. v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
  1147. v8::HandleScope scope(isolate);
  1148. auto web_request = api::WebRequest::FromOrCreate(isolate, browser_context);
  1149. DCHECK(web_request.get());
  1150. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1151. if (!web_request->HasListener()) {
  1152. auto* web_request_api = extensions::BrowserContextKeyedAPIFactory<
  1153. extensions::WebRequestAPI>::Get(browser_context);
  1154. DCHECK(web_request_api);
  1155. bool used_proxy_for_web_request =
  1156. web_request_api->MaybeProxyURLLoaderFactory(
  1157. browser_context, frame_host, render_process_id, type, navigation_id,
  1158. ukm_source_id, factory_builder, header_client,
  1159. navigation_response_task_runner);
  1160. if (bypass_redirect_checks)
  1161. *bypass_redirect_checks = used_proxy_for_web_request;
  1162. if (used_proxy_for_web_request)
  1163. return;
  1164. }
  1165. #endif
  1166. auto [proxied_receiver, target_factory_remote] = factory_builder.Append();
  1167. // Required by WebRequestInfoInitParams.
  1168. //
  1169. // Note that in Electron we allow webRequest to capture requests sent from
  1170. // browser process, so creation of |navigation_ui_data| is different from
  1171. // Chromium which only does for renderer-initialized navigations.
  1172. std::unique_ptr<extensions::ExtensionNavigationUIData> navigation_ui_data;
  1173. if (navigation_id.has_value()) {
  1174. navigation_ui_data =
  1175. std::make_unique<extensions::ExtensionNavigationUIData>();
  1176. }
  1177. mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient>
  1178. header_client_receiver;
  1179. if (header_client)
  1180. header_client_receiver = header_client->InitWithNewPipeAndPassReceiver();
  1181. auto* protocol_registry =
  1182. ProtocolRegistry::FromBrowserContext(browser_context);
  1183. new ProxyingURLLoaderFactory(
  1184. web_request.get(), protocol_registry->intercept_handlers(),
  1185. render_process_id,
  1186. frame_host ? frame_host->GetRoutingID() : MSG_ROUTING_NONE, &next_id_,
  1187. std::move(navigation_ui_data), std::move(navigation_id),
  1188. std::move(proxied_receiver), std::move(target_factory_remote),
  1189. std::move(header_client_receiver), type);
  1190. }
  1191. std::vector<std::unique_ptr<content::URLLoaderRequestInterceptor>>
  1192. ElectronBrowserClient::WillCreateURLLoaderRequestInterceptors(
  1193. content::NavigationUIData* navigation_ui_data,
  1194. int frame_tree_node_id,
  1195. int64_t navigation_id,
  1196. scoped_refptr<base::SequencedTaskRunner> navigation_response_task_runner) {
  1197. std::vector<std::unique_ptr<content::URLLoaderRequestInterceptor>>
  1198. interceptors;
  1199. #if BUILDFLAG(ENABLE_PDF_VIEWER)
  1200. {
  1201. std::unique_ptr<content::URLLoaderRequestInterceptor> pdf_interceptor =
  1202. pdf::PdfURLLoaderRequestInterceptor::MaybeCreateInterceptor(
  1203. frame_tree_node_id, std::make_unique<ChromePdfStreamDelegate>());
  1204. if (pdf_interceptor)
  1205. interceptors.push_back(std::move(pdf_interceptor));
  1206. }
  1207. #endif
  1208. return interceptors;
  1209. }
  1210. void ElectronBrowserClient::OverrideURLLoaderFactoryParams(
  1211. content::BrowserContext* browser_context,
  1212. const url::Origin& origin,
  1213. bool is_for_isolated_world,
  1214. network::mojom::URLLoaderFactoryParams* factory_params) {
  1215. if (factory_params->top_frame_id) {
  1216. // Bypass CORB and CORS when web security is disabled.
  1217. auto* rfh = content::RenderFrameHost::FromFrameToken(
  1218. content::GlobalRenderFrameHostToken(
  1219. factory_params->process_id,
  1220. blink::LocalFrameToken(factory_params->top_frame_id.value())));
  1221. auto* web_contents = content::WebContents::FromRenderFrameHost(rfh);
  1222. auto* prefs = WebContentsPreferences::From(web_contents);
  1223. if (prefs && !prefs->IsWebSecurityEnabled()) {
  1224. factory_params->is_orb_enabled = false;
  1225. factory_params->disable_web_security = true;
  1226. }
  1227. }
  1228. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1229. extensions::URLLoaderFactoryManager::OverrideURLLoaderFactoryParams(
  1230. browser_context, origin, is_for_isolated_world, factory_params);
  1231. #endif
  1232. }
  1233. void ElectronBrowserClient::RegisterAssociatedInterfaceBindersForServiceWorker(
  1234. const content::ServiceWorkerVersionBaseInfo& service_worker_version_info,
  1235. blink::AssociatedInterfaceRegistry& associated_registry) {
  1236. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1237. associated_registry.AddInterface<extensions::mojom::RendererHost>(
  1238. base::BindRepeating(&extensions::RendererStartupHelper::BindForRenderer,
  1239. service_worker_version_info.process_id));
  1240. associated_registry.AddInterface<extensions::mojom::ServiceWorkerHost>(
  1241. base::BindRepeating(&extensions::ServiceWorkerHost::BindReceiver,
  1242. service_worker_version_info.process_id));
  1243. #endif
  1244. }
  1245. void ElectronBrowserClient::
  1246. RegisterAssociatedInterfaceBindersForRenderFrameHost(
  1247. content::RenderFrameHost&
  1248. render_frame_host, // NOLINT(runtime/references)
  1249. blink::AssociatedInterfaceRegistry&
  1250. associated_registry) { // NOLINT(runtime/references)
  1251. auto* contents =
  1252. content::WebContents::FromRenderFrameHost(&render_frame_host);
  1253. if (contents) {
  1254. auto* prefs = WebContentsPreferences::From(contents);
  1255. if (render_frame_host.GetFrameTreeNodeId() ==
  1256. contents->GetPrimaryMainFrame()->GetFrameTreeNodeId() ||
  1257. (prefs && prefs->AllowsNodeIntegrationInSubFrames())) {
  1258. associated_registry.AddInterface<mojom::ElectronApiIPC>(
  1259. base::BindRepeating(
  1260. [](content::RenderFrameHost* render_frame_host,
  1261. mojo::PendingAssociatedReceiver<mojom::ElectronApiIPC>
  1262. receiver) {
  1263. ElectronApiIPCHandlerImpl::Create(render_frame_host,
  1264. std::move(receiver));
  1265. },
  1266. &render_frame_host));
  1267. }
  1268. }
  1269. associated_registry.AddInterface<mojom::ElectronWebContentsUtility>(
  1270. base::BindRepeating(
  1271. [](content::RenderFrameHost* render_frame_host,
  1272. mojo::PendingAssociatedReceiver<mojom::ElectronWebContentsUtility>
  1273. receiver) {
  1274. ElectronWebContentsUtilityHandlerImpl::Create(render_frame_host,
  1275. std::move(receiver));
  1276. },
  1277. &render_frame_host));
  1278. associated_registry.AddInterface<mojom::ElectronAutofillDriver>(
  1279. base::BindRepeating(
  1280. [](content::RenderFrameHost* render_frame_host,
  1281. mojo::PendingAssociatedReceiver<mojom::ElectronAutofillDriver>
  1282. receiver) {
  1283. AutofillDriverFactory::BindAutofillDriver(std::move(receiver),
  1284. render_frame_host);
  1285. },
  1286. &render_frame_host));
  1287. #if BUILDFLAG(ENABLE_PRINTING)
  1288. associated_registry.AddInterface<printing::mojom::PrintManagerHost>(
  1289. base::BindRepeating(
  1290. [](content::RenderFrameHost* render_frame_host,
  1291. mojo::PendingAssociatedReceiver<printing::mojom::PrintManagerHost>
  1292. receiver) {
  1293. PrintViewManagerElectron::BindPrintManagerHost(std::move(receiver),
  1294. render_frame_host);
  1295. },
  1296. &render_frame_host));
  1297. #endif
  1298. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1299. int render_process_id = render_frame_host.GetProcess()->GetID();
  1300. associated_registry.AddInterface<extensions::mojom::EventRouter>(
  1301. base::BindRepeating(&extensions::EventRouter::BindForRenderer,
  1302. render_process_id));
  1303. associated_registry.AddInterface<extensions::mojom::RendererHost>(
  1304. base::BindRepeating(&extensions::RendererStartupHelper::BindForRenderer,
  1305. render_process_id));
  1306. associated_registry.AddInterface<extensions::mojom::LocalFrameHost>(
  1307. base::BindRepeating(
  1308. [](content::RenderFrameHost* render_frame_host,
  1309. mojo::PendingAssociatedReceiver<extensions::mojom::LocalFrameHost>
  1310. receiver) {
  1311. extensions::ExtensionWebContentsObserver::BindLocalFrameHost(
  1312. std::move(receiver), render_frame_host);
  1313. },
  1314. &render_frame_host));
  1315. associated_registry.AddInterface<guest_view::mojom::GuestViewHost>(
  1316. base::BindRepeating(&extensions::ExtensionsGuestView::CreateForComponents,
  1317. render_frame_host.GetGlobalId()));
  1318. associated_registry.AddInterface<extensions::mojom::GuestView>(
  1319. base::BindRepeating(&extensions::ExtensionsGuestView::CreateForExtensions,
  1320. render_frame_host.GetGlobalId()));
  1321. #endif
  1322. #if BUILDFLAG(ENABLE_PDF_VIEWER)
  1323. associated_registry.AddInterface<pdf::mojom::PdfHost>(base::BindRepeating(
  1324. [](content::RenderFrameHost* render_frame_host,
  1325. mojo::PendingAssociatedReceiver<pdf::mojom::PdfHost> receiver) {
  1326. pdf::PDFDocumentHelper::BindPdfHost(
  1327. std::move(receiver), render_frame_host,
  1328. std::make_unique<ElectronPDFDocumentHelperClient>());
  1329. },
  1330. &render_frame_host));
  1331. #endif
  1332. }
  1333. std::string ElectronBrowserClient::GetApplicationLocale() {
  1334. return BrowserThread::CurrentlyOn(BrowserThread::IO)
  1335. ? *g_io_thread_application_locale
  1336. : *g_application_locale;
  1337. }
  1338. bool ElectronBrowserClient::ShouldEnableStrictSiteIsolation() {
  1339. // Enable site isolation. It is off by default in Chromium <= 69.
  1340. return true;
  1341. }
  1342. void ElectronBrowserClient::BindHostReceiverForRenderer(
  1343. content::RenderProcessHost* render_process_host,
  1344. mojo::GenericPendingReceiver receiver) {
  1345. #if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
  1346. if (auto host_receiver =
  1347. receiver.As<spellcheck::mojom::SpellCheckInitializationHost>()) {
  1348. SpellCheckInitializationHostImpl::Create(render_process_host->GetID(),
  1349. std::move(host_receiver));
  1350. return;
  1351. }
  1352. #endif
  1353. }
  1354. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1355. namespace {
  1356. void BindMimeHandlerService(
  1357. content::RenderFrameHost* frame_host,
  1358. mojo::PendingReceiver<extensions::mime_handler::MimeHandlerService>
  1359. receiver) {
  1360. content::WebContents* contents =
  1361. content::WebContents::FromRenderFrameHost(frame_host);
  1362. auto* guest_view =
  1363. extensions::MimeHandlerViewGuest::FromWebContents(contents);
  1364. if (!guest_view)
  1365. return;
  1366. extensions::MimeHandlerServiceImpl::Create(guest_view->GetStreamWeakPtr(),
  1367. std::move(receiver));
  1368. }
  1369. void BindBeforeUnloadControl(
  1370. content::RenderFrameHost* frame_host,
  1371. mojo::PendingReceiver<extensions::mime_handler::BeforeUnloadControl>
  1372. receiver) {
  1373. auto* web_contents = content::WebContents::FromRenderFrameHost(frame_host);
  1374. if (!web_contents)
  1375. return;
  1376. auto* guest_view =
  1377. extensions::MimeHandlerViewGuest::FromWebContents(web_contents);
  1378. if (!guest_view)
  1379. return;
  1380. guest_view->FuseBeforeUnloadControl(std::move(receiver));
  1381. }
  1382. } // namespace
  1383. #endif
  1384. void ElectronBrowserClient::ExposeInterfacesToRenderer(
  1385. service_manager::BinderRegistry* registry,
  1386. blink::AssociatedInterfaceRegistry* associated_registry,
  1387. content::RenderProcessHost* render_process_host) {
  1388. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1389. associated_registry->AddInterface<extensions::mojom::RendererHost>(
  1390. base::BindRepeating(&extensions::RendererStartupHelper::BindForRenderer,
  1391. render_process_host->GetID()));
  1392. #endif
  1393. }
  1394. void ElectronBrowserClient::RegisterBrowserInterfaceBindersForFrame(
  1395. content::RenderFrameHost* render_frame_host,
  1396. mojo::BinderMapWithContext<content::RenderFrameHost*>* map) {
  1397. map->Add<network_hints::mojom::NetworkHintsHandler>(
  1398. base::BindRepeating(&BindNetworkHintsHandler));
  1399. map->Add<blink::mojom::BadgeService>(
  1400. base::BindRepeating(&badging::BadgeManager::BindFrameReceiver));
  1401. map->Add<blink::mojom::KeyboardLockService>(base::BindRepeating(
  1402. &content::KeyboardLockServiceImpl::CreateMojoService));
  1403. #if BUILDFLAG(ENABLE_BUILTIN_SPELLCHECKER)
  1404. map->Add<spellcheck::mojom::SpellCheckHost>(base::BindRepeating(
  1405. [](content::RenderFrameHost* frame_host,
  1406. mojo::PendingReceiver<spellcheck::mojom::SpellCheckHost> receiver) {
  1407. SpellCheckHostChromeImpl::Create(frame_host->GetProcess()->GetID(),
  1408. std::move(receiver));
  1409. }));
  1410. #endif
  1411. #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1412. map->Add<extensions::mime_handler::MimeHandlerService>(
  1413. base::BindRepeating(&BindMimeHandlerService));
  1414. map->Add<extensions::mime_handler::BeforeUnloadControl>(
  1415. base::BindRepeating(&BindBeforeUnloadControl));
  1416. content::WebContents* web_contents =
  1417. content::WebContents::FromRenderFrameHost(render_frame_host);
  1418. if (!web_contents)
  1419. return;
  1420. const GURL& site = render_frame_host->GetSiteInstance()->GetSiteURL();
  1421. if (!site.SchemeIs(extensions::kExtensionScheme))
  1422. return;
  1423. content::BrowserContext* browser_context =
  1424. render_frame_host->GetProcess()->GetBrowserContext();
  1425. auto* extension = extensions::ExtensionRegistry::Get(browser_context)
  1426. ->enabled_extensions()
  1427. .GetByID(site.host());
  1428. if (!extension)
  1429. return;
  1430. extensions::ExtensionsBrowserClient::Get()
  1431. ->RegisterBrowserInterfaceBindersForFrame(map, render_frame_host,
  1432. extension);
  1433. #endif
  1434. }
  1435. #if BUILDFLAG(IS_LINUX)
  1436. void ElectronBrowserClient::GetAdditionalMappedFilesForChildProcess(
  1437. const base::CommandLine& command_line,
  1438. int child_process_id,
  1439. content::PosixFileDescriptorInfo* mappings) {
  1440. int crash_signal_fd = GetCrashSignalFD(command_line);
  1441. if (crash_signal_fd >= 0) {
  1442. mappings->Share(kCrashDumpSignal, crash_signal_fd);
  1443. }
  1444. }
  1445. #endif
  1446. std::unique_ptr<content::LoginDelegate>
  1447. ElectronBrowserClient::CreateLoginDelegate(
  1448. const net::AuthChallengeInfo& auth_info,
  1449. content::WebContents* web_contents,
  1450. content::BrowserContext* browser_context,
  1451. const content::GlobalRequestID& request_id,
  1452. bool is_main_frame,
  1453. const GURL& url,
  1454. scoped_refptr<net::HttpResponseHeaders> response_headers,
  1455. bool first_auth_attempt,
  1456. LoginAuthRequiredCallback auth_required_callback) {
  1457. return std::make_unique<LoginHandler>(
  1458. auth_info, web_contents, is_main_frame, url, response_headers,
  1459. first_auth_attempt, std::move(auth_required_callback));
  1460. }
  1461. std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
  1462. ElectronBrowserClient::CreateURLLoaderThrottles(
  1463. const network::ResourceRequest& request,
  1464. content::BrowserContext* browser_context,
  1465. const base::RepeatingCallback<content::WebContents*()>& wc_getter,
  1466. content::NavigationUIData* navigation_ui_data,
  1467. int frame_tree_node_id,
  1468. absl::optional<int64_t> navigation_id) {
  1469. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  1470. std::vector<std::unique_ptr<blink::URLLoaderThrottle>> result;
  1471. #if BUILDFLAG(ENABLE_PLUGINS) && BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1472. result.push_back(std::make_unique<PluginResponseInterceptorURLLoaderThrottle>(
  1473. request.destination, frame_tree_node_id));
  1474. #endif
  1475. return result;
  1476. }
  1477. base::flat_set<std::string>
  1478. ElectronBrowserClient::GetPluginMimeTypesWithExternalHandlers(
  1479. content::BrowserContext* browser_context) {
  1480. base::flat_set<std::string> mime_types;
  1481. #if BUILDFLAG(ENABLE_PLUGINS) && BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
  1482. auto map = PluginUtils::GetMimeTypeToExtensionIdMap(browser_context);
  1483. for (const auto& pair : map)
  1484. mime_types.insert(pair.first);
  1485. #endif
  1486. #if BUILDFLAG(ENABLE_PDF_VIEWER)
  1487. mime_types.insert(pdf::kInternalPluginMimeType);
  1488. #endif
  1489. return mime_types;
  1490. }
  1491. content::SerialDelegate* ElectronBrowserClient::GetSerialDelegate() {
  1492. if (!serial_delegate_)
  1493. serial_delegate_ = std::make_unique<ElectronSerialDelegate>();
  1494. return serial_delegate_.get();
  1495. }
  1496. content::BluetoothDelegate* ElectronBrowserClient::GetBluetoothDelegate() {
  1497. if (!bluetooth_delegate_)
  1498. bluetooth_delegate_ = std::make_unique<ElectronBluetoothDelegate>();
  1499. return bluetooth_delegate_.get();
  1500. }
  1501. content::UsbDelegate* ElectronBrowserClient::GetUsbDelegate() {
  1502. if (!usb_delegate_)
  1503. usb_delegate_ = std::make_unique<ElectronUsbDelegate>();
  1504. return usb_delegate_.get();
  1505. }
  1506. namespace {
  1507. void BindBadgeServiceForServiceWorker(
  1508. const content::ServiceWorkerVersionBaseInfo& info,
  1509. mojo::PendingReceiver<blink::mojom::BadgeService> receiver) {
  1510. DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  1511. content::RenderProcessHost* render_process_host =
  1512. content::RenderProcessHost::FromID(info.process_id);
  1513. if (!render_process_host)
  1514. return;
  1515. badging::BadgeManager::BindServiceWorkerReceiver(
  1516. render_process_host, info.scope, std::move(receiver));
  1517. }
  1518. } // namespace
  1519. void ElectronBrowserClient::RegisterBrowserInterfaceBindersForServiceWorker(
  1520. content::BrowserContext* browser_context,
  1521. const content::ServiceWorkerVersionBaseInfo& service_worker_version_info,
  1522. mojo::BinderMapWithContext<const content::ServiceWorkerVersionBaseInfo&>*
  1523. map) {
  1524. map->Add<blink::mojom::BadgeService>(
  1525. base::BindRepeating(&BindBadgeServiceForServiceWorker));
  1526. }
  1527. #if BUILDFLAG(IS_MAC)
  1528. device::GeolocationSystemPermissionManager*
  1529. ElectronBrowserClient::GetGeolocationSystemPermissionManager() {
  1530. return device::GeolocationSystemPermissionManager::GetInstance();
  1531. }
  1532. #endif
  1533. content::HidDelegate* ElectronBrowserClient::GetHidDelegate() {
  1534. if (!hid_delegate_)
  1535. hid_delegate_ = std::make_unique<ElectronHidDelegate>();
  1536. return hid_delegate_.get();
  1537. }
  1538. content::WebAuthenticationDelegate*
  1539. ElectronBrowserClient::GetWebAuthenticationDelegate() {
  1540. if (!web_authentication_delegate_) {
  1541. web_authentication_delegate_ =
  1542. std::make_unique<ElectronWebAuthenticationDelegate>();
  1543. }
  1544. return web_authentication_delegate_.get();
  1545. }
  1546. } // namespace electron