atom_browser_client.cc 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  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 "atom/browser/atom_browser_client.h"
  5. #if defined(OS_WIN)
  6. #include <shlobj.h>
  7. #endif
  8. #include <memory>
  9. #include <utility>
  10. #include "atom/browser/api/atom_api_app.h"
  11. #include "atom/browser/api/atom_api_protocol.h"
  12. #include "atom/browser/api/atom_api_web_contents.h"
  13. #include "atom/browser/atom_browser_context.h"
  14. #include "atom/browser/atom_browser_main_parts.h"
  15. #include "atom/browser/atom_navigation_throttle.h"
  16. #include "atom/browser/atom_quota_permission_context.h"
  17. #include "atom/browser/atom_resource_dispatcher_host_delegate.h"
  18. #include "atom/browser/atom_speech_recognition_manager_delegate.h"
  19. #include "atom/browser/child_web_contents_tracker.h"
  20. #include "atom/browser/io_thread.h"
  21. #include "atom/browser/native_window.h"
  22. #include "atom/browser/session_preferences.h"
  23. #include "atom/browser/web_contents_permission_helper.h"
  24. #include "atom/browser/web_contents_preferences.h"
  25. #include "atom/browser/window_list.h"
  26. #include "atom/common/google_api_key.h"
  27. #include "atom/common/options_switches.h"
  28. #include "atom/common/platform_util.h"
  29. #include "base/command_line.h"
  30. #include "base/environment.h"
  31. #include "base/files/file_util.h"
  32. #include "base/json/json_reader.h"
  33. #include "base/no_destructor.h"
  34. #include "base/stl_util.h"
  35. #include "base/strings/string_number_conversions.h"
  36. #include "base/strings/string_util.h"
  37. #include "base/strings/utf_string_conversions.h"
  38. #include "components/net_log/chrome_net_log.h"
  39. #include "content/public/browser/browser_ppapi_host.h"
  40. #include "content/public/browser/client_certificate_delegate.h"
  41. #include "content/public/browser/render_frame_host.h"
  42. #include "content/public/browser/render_process_host.h"
  43. #include "content/public/browser/render_view_host.h"
  44. #include "content/public/browser/resource_dispatcher_host.h"
  45. #include "content/public/browser/site_instance.h"
  46. #include "content/public/browser/web_contents.h"
  47. #include "content/public/common/content_paths.h"
  48. #include "content/public/common/content_switches.h"
  49. #include "content/public/common/service_names.mojom.h"
  50. #include "content/public/common/url_constants.h"
  51. #include "content/public/common/web_preferences.h"
  52. #include "electron/buildflags/buildflags.h"
  53. #include "electron/grit/electron_resources.h"
  54. #include "net/base/escape.h"
  55. #include "net/ssl/ssl_cert_request_info.h"
  56. #include "ppapi/host/ppapi_host.h"
  57. #include "printing/buildflags/buildflags.h"
  58. #include "services/device/public/cpp/geolocation/location_provider.h"
  59. #include "services/network/public/cpp/resource_request_body.h"
  60. #include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h"
  61. #include "ui/base/l10n/l10n_util.h"
  62. #include "ui/base/resource/resource_bundle.h"
  63. #include "v8/include/v8.h"
  64. #if defined(USE_NSS_CERTS)
  65. #include "net/ssl/client_cert_store_nss.h"
  66. #elif defined(OS_WIN)
  67. #include "net/ssl/client_cert_store_win.h"
  68. #elif defined(OS_MACOSX)
  69. #include "net/ssl/client_cert_store_mac.h"
  70. #elif defined(USE_OPENSSL)
  71. #include "net/ssl/client_cert_store.h"
  72. #endif
  73. #if BUILDFLAG(ENABLE_PEPPER_FLASH)
  74. #include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h"
  75. #endif // BUILDFLAG(ENABLE_PEPPER_FLASH)
  76. #if BUILDFLAG(OVERRIDE_LOCATION_PROVIDER)
  77. #include "atom/browser/fake_location_provider.h"
  78. #endif // BUILDFLAG(OVERRIDE_LOCATION_PROVIDER)
  79. #if BUILDFLAG(ENABLE_PRINTING)
  80. #include "chrome/browser/printing/printing_message_filter.h"
  81. #include "chrome/services/printing/public/mojom/constants.mojom.h"
  82. #include "components/services/pdf_compositor/public/interfaces/pdf_compositor.mojom.h"
  83. #endif // BUILDFLAG(ENABLE_PRINTING)
  84. #if BUILDFLAG(ENABLE_TTS)
  85. #include "chrome/browser/speech/tts_message_filter.h"
  86. #endif // BUILDFLAG(ENABLE_TTS)
  87. using content::BrowserThread;
  88. namespace atom {
  89. namespace {
  90. // Next navigation should not restart renderer process.
  91. bool g_suppress_renderer_process_restart = false;
  92. // Custom schemes to be registered to handle service worker.
  93. base::NoDestructor<std::string> g_custom_service_worker_schemes;
  94. bool IsSameWebSite(content::BrowserContext* browser_context,
  95. const GURL& src_url,
  96. const GURL& dest_url) {
  97. return content::SiteInstance::IsSameWebSite(browser_context, src_url,
  98. dest_url) ||
  99. // `IsSameWebSite` doesn't seem to work for some URIs such as `file:`,
  100. // handle these scenarios by comparing only the site as defined by
  101. // `GetSiteForURL`.
  102. content::SiteInstance::GetSiteForURL(browser_context, dest_url) ==
  103. src_url;
  104. }
  105. } // namespace
  106. // static
  107. void AtomBrowserClient::SuppressRendererProcessRestartForOnce() {
  108. g_suppress_renderer_process_restart = true;
  109. }
  110. void AtomBrowserClient::SetCustomServiceWorkerSchemes(
  111. const std::vector<std::string>& schemes) {
  112. *g_custom_service_worker_schemes = base::JoinString(schemes, ",");
  113. }
  114. AtomBrowserClient::AtomBrowserClient() {}
  115. AtomBrowserClient::~AtomBrowserClient() {}
  116. content::WebContents* AtomBrowserClient::GetWebContentsFromProcessID(
  117. int process_id) {
  118. // If the process is a pending process, we should use the web contents
  119. // for the frame host passed into OverrideSiteInstanceForNavigation.
  120. if (base::ContainsKey(pending_processes_, process_id))
  121. return pending_processes_[process_id];
  122. // Certain render process will be created with no associated render view,
  123. // for example: ServiceWorker.
  124. return WebContentsPreferences::GetWebContentsFromProcessID(process_id);
  125. }
  126. bool AtomBrowserClient::ShouldCreateNewSiteInstance(
  127. content::RenderFrameHost* render_frame_host,
  128. content::BrowserContext* browser_context,
  129. content::SiteInstance* current_instance,
  130. const GURL& url) {
  131. if (url.SchemeIs(url::kJavaScriptScheme))
  132. // "javacript:" scheme should always use same SiteInstance
  133. return false;
  134. int process_id = current_instance->GetProcess()->GetID();
  135. if (!IsRendererSandboxed(process_id)) {
  136. if (!RendererUsesNativeWindowOpen(process_id)) {
  137. // non-sandboxed renderers without native window.open should always create
  138. // a new SiteInstance
  139. return true;
  140. }
  141. auto* web_contents =
  142. content::WebContents::FromRenderFrameHost(render_frame_host);
  143. if (!ChildWebContentsTracker::IsChildWebContents(web_contents)) {
  144. // Root WebContents should always create new process to make sure
  145. // native addons are loaded correctly after reload / navigation.
  146. // (Non-root WebContents opened by window.open() should try to
  147. // reuse process to allow synchronous cross-window scripting.)
  148. return true;
  149. }
  150. }
  151. // Create new a SiteInstance if navigating to a different site.
  152. auto src_url = current_instance->GetSiteURL();
  153. return !IsSameWebSite(browser_context, src_url, url);
  154. }
  155. void AtomBrowserClient::AddProcessPreferences(
  156. int process_id,
  157. AtomBrowserClient::ProcessPreferences prefs) {
  158. base::AutoLock auto_lock(process_preferences_lock_);
  159. process_preferences_[process_id] = prefs;
  160. }
  161. void AtomBrowserClient::RemoveProcessPreferences(int process_id) {
  162. base::AutoLock auto_lock(process_preferences_lock_);
  163. process_preferences_.erase(process_id);
  164. }
  165. bool AtomBrowserClient::IsProcessObserved(int process_id) {
  166. base::AutoLock auto_lock(process_preferences_lock_);
  167. return process_preferences_.find(process_id) != process_preferences_.end();
  168. }
  169. bool AtomBrowserClient::IsRendererSandboxed(int process_id) {
  170. base::AutoLock auto_lock(process_preferences_lock_);
  171. auto it = process_preferences_.find(process_id);
  172. return it != process_preferences_.end() && it->second.sandbox;
  173. }
  174. bool AtomBrowserClient::RendererUsesNativeWindowOpen(int process_id) {
  175. base::AutoLock auto_lock(process_preferences_lock_);
  176. auto it = process_preferences_.find(process_id);
  177. return it != process_preferences_.end() && it->second.native_window_open;
  178. }
  179. bool AtomBrowserClient::RendererDisablesPopups(int process_id) {
  180. base::AutoLock auto_lock(process_preferences_lock_);
  181. auto it = process_preferences_.find(process_id);
  182. return it != process_preferences_.end() && it->second.disable_popups;
  183. }
  184. void AtomBrowserClient::RenderProcessWillLaunch(
  185. content::RenderProcessHost* host,
  186. service_manager::mojom::ServiceRequest* service_request) {
  187. // When a render process is crashed, it might be reused.
  188. int process_id = host->GetID();
  189. if (IsProcessObserved(process_id))
  190. return;
  191. #if BUILDFLAG(ENABLE_PRINTING)
  192. host->AddFilter(new printing::PrintingMessageFilter(
  193. process_id, host->GetBrowserContext()));
  194. #endif
  195. #if BUILDFLAG(ENABLE_TTS)
  196. host->AddFilter(new TtsMessageFilter(host->GetBrowserContext()));
  197. #endif
  198. ProcessPreferences prefs;
  199. auto* web_preferences =
  200. WebContentsPreferences::From(GetWebContentsFromProcessID(process_id));
  201. if (web_preferences) {
  202. prefs.sandbox = web_preferences->IsEnabled(options::kSandbox);
  203. prefs.native_window_open =
  204. web_preferences->IsEnabled(options::kNativeWindowOpen);
  205. prefs.disable_popups = web_preferences->IsEnabled("disablePopups");
  206. prefs.web_security = web_preferences->IsEnabled(options::kWebSecurity,
  207. true /* default value */);
  208. }
  209. AddProcessPreferences(host->GetID(), prefs);
  210. // ensure the ProcessPreferences is removed later
  211. host->AddObserver(this);
  212. }
  213. content::SpeechRecognitionManagerDelegate*
  214. AtomBrowserClient::CreateSpeechRecognitionManagerDelegate() {
  215. return new AtomSpeechRecognitionManagerDelegate;
  216. }
  217. void AtomBrowserClient::OverrideWebkitPrefs(content::RenderViewHost* host,
  218. content::WebPreferences* prefs) {
  219. prefs->javascript_enabled = true;
  220. prefs->web_security_enabled = true;
  221. prefs->plugins_enabled = true;
  222. prefs->dom_paste_enabled = true;
  223. prefs->allow_scripts_to_close_windows = true;
  224. prefs->javascript_can_access_clipboard = true;
  225. prefs->local_storage_enabled = true;
  226. prefs->databases_enabled = true;
  227. prefs->application_cache_enabled = true;
  228. prefs->allow_universal_access_from_file_urls = true;
  229. prefs->allow_file_access_from_file_urls = true;
  230. prefs->webgl1_enabled = true;
  231. prefs->webgl2_enabled = true;
  232. prefs->allow_running_insecure_content = false;
  233. prefs->default_minimum_page_scale_factor = 1.f;
  234. prefs->default_maximum_page_scale_factor = 1.f;
  235. prefs->navigate_on_drag_drop = false;
  236. // Custom preferences of guest page.
  237. auto* web_contents = content::WebContents::FromRenderViewHost(host);
  238. auto* web_preferences = WebContentsPreferences::From(web_contents);
  239. if (web_preferences)
  240. web_preferences->OverrideWebkitPrefs(prefs);
  241. }
  242. void AtomBrowserClient::OverrideSiteInstanceForNavigation(
  243. content::RenderFrameHost* rfh,
  244. content::BrowserContext* browser_context,
  245. const GURL& url,
  246. bool has_request_started,
  247. content::SiteInstance* candidate_instance,
  248. content::SiteInstance** new_instance) {
  249. if (g_suppress_renderer_process_restart) {
  250. g_suppress_renderer_process_restart = false;
  251. return;
  252. }
  253. content::SiteInstance* current_instance = rfh->GetSiteInstance();
  254. if (!ShouldCreateNewSiteInstance(rfh, browser_context, current_instance, url))
  255. return;
  256. // Do we have an affinity site to manage ?
  257. auto* web_contents = content::WebContents::FromRenderFrameHost(rfh);
  258. auto* web_preferences = WebContentsPreferences::From(web_contents);
  259. std::string affinity;
  260. if (web_preferences &&
  261. web_preferences->GetPreference("affinity", &affinity) &&
  262. !affinity.empty()) {
  263. affinity = base::ToLowerASCII(affinity);
  264. auto iter = site_per_affinities.find(affinity);
  265. GURL dest_site = content::SiteInstance::GetSiteForURL(browser_context, url);
  266. if (iter != site_per_affinities.end() &&
  267. IsSameWebSite(browser_context, iter->second->GetSiteURL(), dest_site)) {
  268. *new_instance = iter->second;
  269. } else {
  270. site_per_affinities[affinity] = candidate_instance;
  271. *new_instance = candidate_instance;
  272. // Remember the original web contents for the pending renderer process.
  273. auto* pending_process = candidate_instance->GetProcess();
  274. pending_processes_[pending_process->GetID()] = web_contents;
  275. }
  276. } else {
  277. // OverrideSiteInstanceForNavigation will be called more than once during a
  278. // navigation (currently twice, on request and when it's about to commit in
  279. // the renderer), look at RenderFrameHostManager::GetFrameHostForNavigation.
  280. // In the default mode we should resuse the same site instance until the
  281. // request commits otherwise it will get destroyed. Currently there is no
  282. // unique lifetime tracker for a navigation request during site instance
  283. // creation. We check for the state of the request, which should be one of
  284. // (WAITING_FOR_RENDERER_RESPONSE, STARTED, RESPONSE_STARTED, FAILED) along
  285. // with the availability of a speculative render frame host.
  286. if (has_request_started) {
  287. *new_instance = current_instance;
  288. return;
  289. }
  290. *new_instance = candidate_instance;
  291. // Remember the original web contents for the pending renderer process.
  292. auto* pending_process = candidate_instance->GetProcess();
  293. pending_processes_[pending_process->GetID()] = web_contents;
  294. }
  295. }
  296. void AtomBrowserClient::AppendExtraCommandLineSwitches(
  297. base::CommandLine* command_line,
  298. int process_id) {
  299. // Make sure we're about to launch a known executable
  300. {
  301. base::FilePath child_path;
  302. base::PathService::Get(content::CHILD_PROCESS_EXE, &child_path);
  303. base::ThreadRestrictions::ScopedAllowIO allow_io;
  304. CHECK(base::MakeAbsoluteFilePath(command_line->GetProgram()) == child_path);
  305. }
  306. std::string process_type =
  307. command_line->GetSwitchValueASCII(::switches::kProcessType);
  308. if (process_type != ::switches::kRendererProcess)
  309. return;
  310. // Copy following switches to child process.
  311. static const char* const kCommonSwitchNames[] = {switches::kStandardSchemes,
  312. switches::kEnableSandbox,
  313. switches::kSecureSchemes};
  314. command_line->CopySwitchesFrom(*base::CommandLine::ForCurrentProcess(),
  315. kCommonSwitchNames,
  316. arraysize(kCommonSwitchNames));
  317. // The registered service worker schemes.
  318. if (!g_custom_service_worker_schemes->empty())
  319. command_line->AppendSwitchASCII(switches::kRegisterServiceWorkerSchemes,
  320. *g_custom_service_worker_schemes);
  321. #if defined(OS_WIN)
  322. // Append --app-user-model-id.
  323. PWSTR current_app_id;
  324. if (SUCCEEDED(GetCurrentProcessExplicitAppUserModelID(&current_app_id))) {
  325. command_line->AppendSwitchNative(switches::kAppUserModelId, current_app_id);
  326. CoTaskMemFree(current_app_id);
  327. }
  328. #endif
  329. if (delegate_) {
  330. auto app_path = static_cast<api::App*>(delegate_)->GetAppPath();
  331. command_line->AppendSwitchPath(switches::kAppPath, app_path);
  332. }
  333. content::WebContents* web_contents = GetWebContentsFromProcessID(process_id);
  334. if (web_contents) {
  335. auto* web_preferences = WebContentsPreferences::From(web_contents);
  336. if (web_preferences)
  337. web_preferences->AppendCommandLineSwitches(command_line);
  338. SessionPreferences::AppendExtraCommandLineSwitches(
  339. web_contents->GetBrowserContext(), command_line);
  340. }
  341. }
  342. void AtomBrowserClient::DidCreatePpapiPlugin(content::BrowserPpapiHost* host) {
  343. #if BUILDFLAG(ENABLE_PEPPER_FLASH)
  344. host->GetPpapiHost()->AddHostFactoryFilter(
  345. base::WrapUnique(new ChromeBrowserPepperHostFactory(host)));
  346. #endif
  347. }
  348. std::string AtomBrowserClient::GetGeolocationApiKey() {
  349. std::unique_ptr<base::Environment> env(base::Environment::Create());
  350. std::string api_key;
  351. if (!env->GetVar("GOOGLE_API_KEY", &api_key))
  352. api_key = GOOGLEAPIS_API_KEY;
  353. return api_key;
  354. }
  355. content::QuotaPermissionContext*
  356. AtomBrowserClient::CreateQuotaPermissionContext() {
  357. return new AtomQuotaPermissionContext;
  358. }
  359. void AtomBrowserClient::AllowCertificateError(
  360. content::WebContents* web_contents,
  361. int cert_error,
  362. const net::SSLInfo& ssl_info,
  363. const GURL& request_url,
  364. content::ResourceType resource_type,
  365. bool strict_enforcement,
  366. bool expired_previous_decision,
  367. const base::Callback<void(content::CertificateRequestResultType)>&
  368. callback) {
  369. if (delegate_) {
  370. delegate_->AllowCertificateError(
  371. web_contents, cert_error, ssl_info, request_url, resource_type,
  372. strict_enforcement, expired_previous_decision, callback);
  373. }
  374. }
  375. void AtomBrowserClient::SelectClientCertificate(
  376. content::WebContents* web_contents,
  377. net::SSLCertRequestInfo* cert_request_info,
  378. net::ClientCertIdentityList client_certs,
  379. std::unique_ptr<content::ClientCertificateDelegate> delegate) {
  380. if (!client_certs.empty() && delegate_) {
  381. delegate_->SelectClientCertificate(web_contents, cert_request_info,
  382. std::move(client_certs),
  383. std::move(delegate));
  384. }
  385. }
  386. void AtomBrowserClient::ResourceDispatcherHostCreated() {
  387. resource_dispatcher_host_delegate_.reset(
  388. new AtomResourceDispatcherHostDelegate);
  389. content::ResourceDispatcherHost::Get()->SetDelegate(
  390. resource_dispatcher_host_delegate_.get());
  391. }
  392. bool AtomBrowserClient::CanCreateWindow(
  393. content::RenderFrameHost* opener,
  394. const GURL& opener_url,
  395. const GURL& opener_top_level_frame_url,
  396. const GURL& source_origin,
  397. content::mojom::WindowContainerType container_type,
  398. const GURL& target_url,
  399. const content::Referrer& referrer,
  400. const std::string& frame_name,
  401. WindowOpenDisposition disposition,
  402. const blink::mojom::WindowFeatures& features,
  403. const std::vector<std::string>& additional_features,
  404. const scoped_refptr<network::ResourceRequestBody>& body,
  405. bool user_gesture,
  406. bool opener_suppressed,
  407. bool* no_javascript_access) {
  408. DCHECK_CURRENTLY_ON(BrowserThread::UI);
  409. int opener_render_process_id = opener->GetProcess()->GetID();
  410. if (RendererUsesNativeWindowOpen(opener_render_process_id)) {
  411. if (RendererDisablesPopups(opener_render_process_id)) {
  412. // <webview> without allowpopups attribute should return
  413. // null from window.open calls
  414. return false;
  415. } else {
  416. *no_javascript_access = false;
  417. return true;
  418. }
  419. }
  420. if (delegate_) {
  421. return delegate_->CanCreateWindow(
  422. opener, opener_url, opener_top_level_frame_url, source_origin,
  423. container_type, target_url, referrer, frame_name, disposition, features,
  424. additional_features, body, user_gesture, opener_suppressed,
  425. no_javascript_access);
  426. }
  427. return false;
  428. }
  429. void AtomBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
  430. std::vector<std::string>* additional_schemes) {
  431. auto schemes_list = api::GetStandardSchemes();
  432. if (!schemes_list.empty())
  433. additional_schemes->insert(additional_schemes->end(), schemes_list.begin(),
  434. schemes_list.end());
  435. additional_schemes->push_back(content::kChromeDevToolsScheme);
  436. }
  437. void AtomBrowserClient::SiteInstanceDeleting(
  438. content::SiteInstance* site_instance) {
  439. // We are storing weak_ptr, is it fundamental to maintain the map up-to-date
  440. // when an instance is destroyed.
  441. for (auto iter = site_per_affinities.begin();
  442. iter != site_per_affinities.end(); ++iter) {
  443. if (iter->second == site_instance) {
  444. site_per_affinities.erase(iter);
  445. break;
  446. }
  447. }
  448. }
  449. std::unique_ptr<net::ClientCertStore> AtomBrowserClient::CreateClientCertStore(
  450. content::ResourceContext* resource_context) {
  451. #if defined(USE_NSS_CERTS)
  452. return std::make_unique<net::ClientCertStoreNSS>(
  453. net::ClientCertStoreNSS::PasswordDelegateFactory());
  454. #elif defined(OS_WIN)
  455. return std::make_unique<net::ClientCertStoreWin>();
  456. #elif defined(OS_MACOSX)
  457. return std::make_unique<net::ClientCertStoreMac>();
  458. #elif defined(USE_OPENSSL)
  459. return std::unique_ptr<net::ClientCertStore>();
  460. #endif
  461. }
  462. std::unique_ptr<device::LocationProvider>
  463. AtomBrowserClient::OverrideSystemLocationProvider() {
  464. #if BUILDFLAG(OVERRIDE_LOCATION_PROVIDER)
  465. return std::make_unique<FakeLocationProvider>();
  466. #else
  467. return nullptr;
  468. #endif
  469. }
  470. network::mojom::NetworkContextPtr AtomBrowserClient::CreateNetworkContext(
  471. content::BrowserContext* browser_context,
  472. bool /*in_memory*/,
  473. const base::FilePath& /*relative_partition_path*/) {
  474. if (!browser_context)
  475. return nullptr;
  476. return static_cast<AtomBrowserContext*>(browser_context)->GetNetworkContext();
  477. }
  478. void AtomBrowserClient::RegisterOutOfProcessServices(
  479. OutOfProcessServiceMap* services) {
  480. (*services)[proxy_resolver::mojom::kProxyResolverServiceName] =
  481. base::BindRepeating(&l10n_util::GetStringUTF16,
  482. IDS_UTILITY_PROCESS_PROXY_RESOLVER_NAME);
  483. #if BUILDFLAG(ENABLE_PRINTING)
  484. (*services)[printing::mojom::kServiceName] =
  485. base::BindRepeating(&l10n_util::GetStringUTF16,
  486. IDS_UTILITY_PROCESS_PDF_COMPOSITOR_SERVICE_NAME);
  487. (*services)[printing::mojom::kChromePrintingServiceName] =
  488. base::BindRepeating(&l10n_util::GetStringUTF16,
  489. IDS_UTILITY_PROCESS_PRINTING_SERVICE_NAME);
  490. #endif
  491. }
  492. std::unique_ptr<base::Value> AtomBrowserClient::GetServiceManifestOverlay(
  493. base::StringPiece name) {
  494. ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
  495. int id = -1;
  496. if (name == content::mojom::kBrowserServiceName)
  497. id = IDR_ELECTRON_CONTENT_BROWSER_MANIFEST_OVERLAY;
  498. else if (name == content::mojom::kPackagedServicesServiceName)
  499. id = IDR_ELECTRON_CONTENT_PACKAGED_SERVICES_MANIFEST_OVERLAY;
  500. if (id == -1)
  501. return nullptr;
  502. base::StringPiece manifest_contents = rb.GetRawDataResource(id);
  503. return base::JSONReader::Read(manifest_contents);
  504. }
  505. net::NetLog* AtomBrowserClient::GetNetLog() {
  506. return AtomBrowserMainParts::Get()->net_log();
  507. }
  508. brightray::BrowserMainParts* AtomBrowserClient::OverrideCreateBrowserMainParts(
  509. const content::MainFunctionParams& params) {
  510. return new AtomBrowserMainParts(params);
  511. }
  512. void AtomBrowserClient::WebNotificationAllowed(
  513. int render_process_id,
  514. const base::Callback<void(bool, bool)>& callback) {
  515. content::WebContents* web_contents =
  516. WebContentsPreferences::GetWebContentsFromProcessID(render_process_id);
  517. if (!web_contents) {
  518. callback.Run(false, false);
  519. return;
  520. }
  521. auto* permission_helper =
  522. WebContentsPermissionHelper::FromWebContents(web_contents);
  523. if (!permission_helper) {
  524. callback.Run(false, false);
  525. return;
  526. }
  527. permission_helper->RequestWebNotificationPermission(
  528. base::Bind(callback, web_contents->IsAudioMuted()));
  529. }
  530. void AtomBrowserClient::RenderProcessHostDestroyed(
  531. content::RenderProcessHost* host) {
  532. int process_id = host->GetID();
  533. pending_processes_.erase(process_id);
  534. RemoveProcessPreferences(process_id);
  535. }
  536. void AtomBrowserClient::RenderProcessReady(content::RenderProcessHost* host) {
  537. render_process_host_pids_[host->GetID()] =
  538. base::GetProcId(host->GetProcess().Handle());
  539. if (delegate_) {
  540. static_cast<api::App*>(delegate_)->RenderProcessReady(host);
  541. }
  542. }
  543. void AtomBrowserClient::RenderProcessExited(
  544. content::RenderProcessHost* host,
  545. const content::ChildProcessTerminationInfo& info) {
  546. auto host_pid = render_process_host_pids_.find(host->GetID());
  547. if (host_pid != render_process_host_pids_.end()) {
  548. if (delegate_) {
  549. static_cast<api::App*>(delegate_)->RenderProcessDisconnected(
  550. host_pid->second);
  551. }
  552. render_process_host_pids_.erase(host_pid);
  553. }
  554. }
  555. void OnOpenExternal(const GURL& escaped_url, bool allowed) {
  556. if (allowed)
  557. platform_util::OpenExternal(
  558. #if defined(OS_WIN)
  559. base::UTF8ToUTF16(escaped_url.spec()),
  560. #else
  561. escaped_url,
  562. #endif
  563. platform_util::OpenExternalOptions());
  564. }
  565. void HandleExternalProtocolInUI(
  566. const GURL& url,
  567. const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter,
  568. bool has_user_gesture) {
  569. content::WebContents* web_contents = web_contents_getter.Run();
  570. if (!web_contents)
  571. return;
  572. auto* permission_helper =
  573. WebContentsPermissionHelper::FromWebContents(web_contents);
  574. if (!permission_helper)
  575. return;
  576. GURL escaped_url(net::EscapeExternalHandlerValue(url.spec()));
  577. auto callback = base::Bind(&OnOpenExternal, escaped_url);
  578. permission_helper->RequestOpenExternalPermission(callback, has_user_gesture,
  579. url);
  580. }
  581. bool AtomBrowserClient::HandleExternalProtocol(
  582. const GURL& url,
  583. content::ResourceRequestInfo::WebContentsGetter web_contents_getter,
  584. int child_id,
  585. content::NavigationUIData* navigation_data,
  586. bool is_main_frame,
  587. ui::PageTransition page_transition,
  588. bool has_user_gesture) {
  589. BrowserThread::PostTask(
  590. BrowserThread::UI, FROM_HERE,
  591. base::BindOnce(&HandleExternalProtocolInUI, url, web_contents_getter,
  592. has_user_gesture));
  593. return true;
  594. }
  595. std::vector<std::unique_ptr<content::NavigationThrottle>>
  596. AtomBrowserClient::CreateThrottlesForNavigation(
  597. content::NavigationHandle* handle) {
  598. std::vector<std::unique_ptr<content::NavigationThrottle>> throttles;
  599. throttles.push_back(std::make_unique<AtomNavigationThrottle>(handle));
  600. return throttles;
  601. }
  602. bool AtomBrowserClient::ShouldBypassCORB(int render_process_id) {
  603. // This is called on the network thread.
  604. base::AutoLock auto_lock(process_preferences_lock_);
  605. auto it = process_preferences_.find(render_process_id);
  606. return it != process_preferences_.end() && !it->second.web_security;
  607. }
  608. } // namespace atom