electron_browser_client.cc 69 KB

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