• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "libcef/browser/alloy/alloy_content_browser_client.h"
6 
7 #include <algorithm>
8 #include <utility>
9 
10 #include "include/cef_version.h"
11 #include "libcef/browser/alloy/alloy_browser_context.h"
12 #include "libcef/browser/alloy/alloy_browser_host_impl.h"
13 #include "libcef/browser/alloy/alloy_browser_main.h"
14 #include "libcef/browser/browser_context.h"
15 #include "libcef/browser/browser_info.h"
16 #include "libcef/browser/browser_info_manager.h"
17 #include "libcef/browser/browser_message_filter.h"
18 #include "libcef/browser/browser_platform_delegate.h"
19 #include "libcef/browser/context.h"
20 #include "libcef/browser/devtools/devtools_manager_delegate.h"
21 #include "libcef/browser/extensions/extension_system.h"
22 #include "libcef/browser/extensions/extension_web_contents_observer.h"
23 #include "libcef/browser/media_capture_devices_dispatcher.h"
24 #include "libcef/browser/net/chrome_scheme_handler.h"
25 #include "libcef/browser/net/throttle_handler.h"
26 #include "libcef/browser/net_service/cookie_manager_impl.h"
27 #include "libcef/browser/net_service/login_delegate.h"
28 #include "libcef/browser/net_service/proxy_url_loader_factory.h"
29 #include "libcef/browser/net_service/resource_request_handler_wrapper.h"
30 #include "libcef/browser/plugins/plugin_service_filter.h"
31 #include "libcef/browser/prefs/renderer_prefs.h"
32 #include "libcef/browser/speech_recognition_manager_delegate.h"
33 #include "libcef/browser/ssl_info_impl.h"
34 #include "libcef/browser/thread_util.h"
35 #include "libcef/browser/x509_certificate_impl.h"
36 #include "libcef/common/alloy/alloy_content_client.h"
37 #include "libcef/common/app_manager.h"
38 #include "libcef/common/cef_messages.h"
39 #include "libcef/common/cef_switches.h"
40 #include "libcef/common/command_line_impl.h"
41 #include "libcef/common/extensions/extensions_util.h"
42 #include "libcef/common/net/scheme_registration.h"
43 #include "libcef/common/request_impl.h"
44 
45 #include "base/base_switches.h"
46 #include "base/command_line.h"
47 #include "base/files/file_path.h"
48 #include "base/json/json_reader.h"
49 #include "base/path_service.h"
50 #include "base/stl_util.h"
51 #include "base/threading/thread_restrictions.h"
52 #include "cef/grit/cef_resources.h"
53 #include "chrome/browser/browser_process.h"
54 #include "chrome/browser/content_settings/cookie_settings_factory.h"
55 #include "chrome/browser/net/profile_network_context_service.h"
56 #include "chrome/browser/net/profile_network_context_service_factory.h"
57 #include "chrome/browser/net/system_network_context_manager.h"
58 #include "chrome/browser/plugins/plugin_info_host_impl.h"
59 #include "chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.h"
60 #include "chrome/browser/plugins/plugin_utils.h"
61 #include "chrome/browser/profiles/profile.h"
62 #include "chrome/browser/profiles/renderer_updater.h"
63 #include "chrome/browser/profiles/renderer_updater_factory.h"
64 #include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h"
65 #include "chrome/browser/spellchecker/spell_check_host_chrome_impl.h"
66 #include "chrome/common/chrome_content_client.h"
67 #include "chrome/common/chrome_paths.h"
68 #include "chrome/common/chrome_switches.h"
69 #include "chrome/common/google_url_loader_throttle.h"
70 #include "chrome/common/pref_names.h"
71 #include "chrome/common/webui_url_constants.h"
72 #include "chrome/grit/browser_resources.h"
73 #include "chrome/grit/generated_resources.h"
74 #include "chrome/services/printing/printing_service.h"
75 #include "components/content_settings/core/browser/cookie_settings.h"
76 #include "components/embedder_support/switches.h"
77 #include "components/embedder_support/user_agent_utils.h"
78 #include "components/spellcheck/common/spellcheck.mojom.h"
79 #include "components/version_info/version_info.h"
80 #include "content/browser/plugin_service_impl.h"
81 #include "content/browser/renderer_host/render_frame_host_impl.h"
82 #include "content/public/browser/browser_context.h"
83 #include "content/public/browser/browser_ppapi_host.h"
84 #include "content/public/browser/browser_thread.h"
85 #include "content/public/browser/client_certificate_delegate.h"
86 #include "content/public/browser/navigation_handle.h"
87 #include "content/public/browser/overlay_window.h"
88 #include "content/public/browser/page_navigator.h"
89 #include "content/public/browser/quota_permission_context.h"
90 #include "content/public/browser/render_frame_host.h"
91 #include "content/public/browser/render_process_host.h"
92 #include "content/public/browser/render_view_host.h"
93 #include "content/public/browser/render_widget_host.h"
94 #include "content/public/browser/render_widget_host_view.h"
95 #include "content/public/browser/storage_partition.h"
96 #include "content/public/browser/web_ui_url_loader_factory.h"
97 #include "content/public/common/content_switches.h"
98 #include "content/public/common/storage_quota_params.h"
99 #include "content/public/common/url_constants.h"
100 #include "content/public/common/user_agent.h"
101 #include "extensions/browser/extension_message_filter.h"
102 #include "extensions/browser/extension_protocols.h"
103 #include "extensions/browser/extension_registry.h"
104 #include "extensions/browser/extensions_browser_client.h"
105 #include "extensions/browser/guest_view/extensions_guest_view_message_filter.h"
106 #include "extensions/browser/guest_view/web_view/web_view_guest.h"
107 #include "extensions/browser/info_map.h"
108 #include "extensions/browser/process_map.h"
109 #include "extensions/browser/url_loader_factory_manager.h"
110 #include "extensions/common/constants.h"
111 #include "extensions/common/switches.h"
112 #include "mojo/public/cpp/bindings/remote.h"
113 #include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
114 #include "net/base/auth.h"
115 #include "net/ssl/ssl_cert_request_info.h"
116 #include "ppapi/host/ppapi_host.h"
117 #include "sandbox/policy/switches.h"
118 #include "services/network/public/cpp/network_switches.h"
119 #include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h"
120 #include "services/service_manager/public/mojom/connector.mojom.h"
121 #include "storage/browser/quota/quota_settings.h"
122 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
123 #include "third_party/blink/public/mojom/insecure_input/insecure_input_service.mojom.h"
124 #include "third_party/blink/public/mojom/prerender/prerender.mojom.h"
125 #include "third_party/blink/public/web/web_window_features.h"
126 #include "third_party/widevine/cdm/buildflags.h"
127 #include "ui/base/l10n/l10n_util.h"
128 #include "ui/base/resource/resource_bundle.h"
129 #include "ui/base/ui_base_switches.h"
130 #include "url/gurl.h"
131 
132 #if defined(OS_LINUX)
133 #include "libcef/common/widevine_loader.h"
134 #endif
135 
136 #if defined(OS_POSIX) && !defined(OS_MAC)
137 #include "base/debug/leak_annotations.h"
138 #include "chrome/common/chrome_paths.h"
139 #include "components/crash/content/browser/crash_handler_host_linux.h"
140 #include "components/crash/core/app/breakpad_linux.h"
141 #include "content/public/common/content_descriptors.h"
142 #endif
143 
144 #if defined(OS_MAC)
145 #include "net/ssl/client_cert_store_mac.h"
146 #include "services/video_capture/public/mojom/constants.mojom.h"
147 #endif
148 
149 #if defined(OS_WIN)
150 #include "net/ssl/client_cert_store_win.h"
151 #include "sandbox/win/src/sandbox_policy.h"
152 #endif
153 
154 #if defined(USE_NSS_CERTS)
155 #include "net/ssl/client_cert_store_nss.h"
156 #endif
157 
158 #if BUILDFLAG(HAS_SPELLCHECK_PANEL)
159 #include "chrome/browser/spellchecker/spell_check_panel_host_impl.h"
160 #endif
161 
162 namespace {
163 
164 class CefQuotaCallbackImpl : public CefRequestCallback {
165  public:
166   using CallbackType = content::QuotaPermissionContext::PermissionCallback;
167 
CefQuotaCallbackImpl(CallbackType callback)168   explicit CefQuotaCallbackImpl(CallbackType callback)
169       : callback_(std::move(callback)) {}
170 
~CefQuotaCallbackImpl()171   ~CefQuotaCallbackImpl() {
172     if (!callback_.is_null()) {
173       // The callback is still pending. Cancel it now.
174       if (CEF_CURRENTLY_ON_IOT()) {
175         RunNow(std::move(callback_), false);
176       } else {
177         CEF_POST_TASK(CEF_IOT, base::BindOnce(&CefQuotaCallbackImpl::RunNow,
178                                               std::move(callback_), false));
179       }
180     }
181   }
182 
Continue(bool allow)183   void Continue(bool allow) override {
184     if (CEF_CURRENTLY_ON_IOT()) {
185       if (!callback_.is_null()) {
186         RunNow(std::move(callback_), allow);
187       }
188     } else {
189       CEF_POST_TASK(CEF_IOT, base::BindOnce(&CefQuotaCallbackImpl::Continue,
190                                             this, allow));
191     }
192   }
193 
Cancel()194   void Cancel() override { Continue(false); }
195 
Disconnect()196   CallbackType Disconnect() WARN_UNUSED_RESULT { return std::move(callback_); }
197 
198  private:
RunNow(CallbackType callback,bool allow)199   static void RunNow(CallbackType callback, bool allow) {
200     CEF_REQUIRE_IOT();
201     std::move(callback).Run(
202         allow ? content::QuotaPermissionContext::QUOTA_PERMISSION_RESPONSE_ALLOW
203               : content::QuotaPermissionContext::
204                     QUOTA_PERMISSION_RESPONSE_DISALLOW);
205   }
206 
207   CallbackType callback_;
208 
209   IMPLEMENT_REFCOUNTING(CefQuotaCallbackImpl);
210   DISALLOW_COPY_AND_ASSIGN(CefQuotaCallbackImpl);
211 };
212 
213 class CefAllowCertificateErrorCallbackImpl : public CefRequestCallback {
214  public:
215   typedef base::OnceCallback<void(content::CertificateRequestResultType)>
216       CallbackType;
217 
CefAllowCertificateErrorCallbackImpl(CallbackType callback)218   explicit CefAllowCertificateErrorCallbackImpl(CallbackType callback)
219       : callback_(std::move(callback)) {}
220 
~CefAllowCertificateErrorCallbackImpl()221   ~CefAllowCertificateErrorCallbackImpl() {
222     if (!callback_.is_null()) {
223       // The callback is still pending. Cancel it now.
224       if (CEF_CURRENTLY_ON_UIT()) {
225         RunNow(std::move(callback_), false);
226       } else {
227         CEF_POST_TASK(
228             CEF_UIT,
229             base::BindOnce(&CefAllowCertificateErrorCallbackImpl::RunNow,
230                            std::move(callback_), false));
231       }
232     }
233   }
234 
Continue(bool allow)235   void Continue(bool allow) override {
236     if (CEF_CURRENTLY_ON_UIT()) {
237       if (!callback_.is_null()) {
238         RunNow(std::move(callback_), allow);
239       }
240     } else {
241       CEF_POST_TASK(CEF_UIT,
242                     base::Bind(&CefAllowCertificateErrorCallbackImpl::Continue,
243                                this, allow));
244     }
245   }
246 
Cancel()247   void Cancel() override { Continue(false); }
248 
Disconnect()249   CallbackType Disconnect() WARN_UNUSED_RESULT { return std::move(callback_); }
250 
251  private:
RunNow(CallbackType callback,bool allow)252   static void RunNow(CallbackType callback, bool allow) {
253     CEF_REQUIRE_UIT();
254     std::move(callback).Run(
255         allow ? content::CERTIFICATE_REQUEST_RESULT_TYPE_CONTINUE
256               : content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY);
257   }
258 
259   CallbackType callback_;
260 
261   IMPLEMENT_REFCOUNTING(CefAllowCertificateErrorCallbackImpl);
262   DISALLOW_COPY_AND_ASSIGN(CefAllowCertificateErrorCallbackImpl);
263 };
264 
265 class CefSelectClientCertificateCallbackImpl
266     : public CefSelectClientCertificateCallback {
267  public:
CefSelectClientCertificateCallbackImpl(std::unique_ptr<content::ClientCertificateDelegate> delegate)268   explicit CefSelectClientCertificateCallbackImpl(
269       std::unique_ptr<content::ClientCertificateDelegate> delegate)
270       : delegate_(std::move(delegate)) {}
271 
~CefSelectClientCertificateCallbackImpl()272   ~CefSelectClientCertificateCallbackImpl() {
273     // If Select has not been called, call it with NULL to continue without any
274     // client certificate.
275     if (delegate_)
276       DoSelect(nullptr);
277   }
278 
Select(CefRefPtr<CefX509Certificate> cert)279   void Select(CefRefPtr<CefX509Certificate> cert) override {
280     if (delegate_)
281       DoSelect(cert);
282   }
283 
284  private:
DoSelect(CefRefPtr<CefX509Certificate> cert)285   void DoSelect(CefRefPtr<CefX509Certificate> cert) {
286     if (CEF_CURRENTLY_ON_UIT()) {
287       RunNow(std::move(delegate_), cert);
288     } else {
289       CEF_POST_TASK(
290           CEF_UIT,
291           base::BindOnce(&CefSelectClientCertificateCallbackImpl::RunNow,
292                          std::move(delegate_), cert));
293     }
294   }
295 
RunNow(std::unique_ptr<content::ClientCertificateDelegate> delegate,CefRefPtr<CefX509Certificate> cert)296   static void RunNow(
297       std::unique_ptr<content::ClientCertificateDelegate> delegate,
298       CefRefPtr<CefX509Certificate> cert) {
299     CEF_REQUIRE_UIT();
300 
301     if (cert) {
302       CefX509CertificateImpl* certImpl =
303           static_cast<CefX509CertificateImpl*>(cert.get());
304       certImpl->AcquirePrivateKey(base::BindOnce(
305           &CefSelectClientCertificateCallbackImpl::RunWithPrivateKey,
306           std::move(delegate), cert));
307       return;
308     }
309 
310     delegate->ContinueWithCertificate(nullptr, nullptr);
311   }
312 
RunWithPrivateKey(std::unique_ptr<content::ClientCertificateDelegate> delegate,CefRefPtr<CefX509Certificate> cert,scoped_refptr<net::SSLPrivateKey> key)313   static void RunWithPrivateKey(
314       std::unique_ptr<content::ClientCertificateDelegate> delegate,
315       CefRefPtr<CefX509Certificate> cert,
316       scoped_refptr<net::SSLPrivateKey> key) {
317     CEF_REQUIRE_UIT();
318     DCHECK(cert);
319 
320     if (key) {
321       CefX509CertificateImpl* certImpl =
322           static_cast<CefX509CertificateImpl*>(cert.get());
323       delegate->ContinueWithCertificate(certImpl->GetInternalCertObject(), key);
324     } else {
325       delegate->ContinueWithCertificate(nullptr, nullptr);
326     }
327   }
328 
329   std::unique_ptr<content::ClientCertificateDelegate> delegate_;
330 
331   IMPLEMENT_REFCOUNTING(CefSelectClientCertificateCallbackImpl);
332   DISALLOW_COPY_AND_ASSIGN(CefSelectClientCertificateCallbackImpl);
333 };
334 
335 class CefQuotaPermissionContext : public content::QuotaPermissionContext {
336  public:
CefQuotaPermissionContext()337   CefQuotaPermissionContext() {}
338 
339   // The callback will be dispatched on the IO thread.
RequestQuotaPermission(const content::StorageQuotaParams & params,int render_process_id,PermissionCallback callback)340   void RequestQuotaPermission(const content::StorageQuotaParams& params,
341                               int render_process_id,
342                               PermissionCallback callback) override {
343     if (params.storage_type != blink::mojom::StorageType::kPersistent) {
344       // To match Chrome behavior we only support requesting quota with this
345       // interface for Persistent storage type.
346       std::move(callback).Run(QUOTA_PERMISSION_RESPONSE_DISALLOW);
347       return;
348     }
349 
350     bool handled = false;
351 
352     CefRefPtr<AlloyBrowserHostImpl> browser =
353         AlloyBrowserHostImpl::GetBrowserForFrameRoute(render_process_id,
354                                                       params.render_frame_id);
355     if (browser.get()) {
356       CefRefPtr<CefClient> client = browser->GetClient();
357       if (client.get()) {
358         CefRefPtr<CefRequestHandler> handler = client->GetRequestHandler();
359         if (handler.get()) {
360           CefRefPtr<CefQuotaCallbackImpl> callbackImpl(
361               new CefQuotaCallbackImpl(std::move(callback)));
362           handled = handler->OnQuotaRequest(
363               browser.get(), params.origin_url.spec(), params.requested_size,
364               callbackImpl.get());
365           if (!handled) {
366             // May return nullptr if the client has already executed the
367             // callback.
368             callback = callbackImpl->Disconnect();
369           }
370         }
371       }
372     }
373 
374     if (!handled && !callback.is_null()) {
375       // Disallow the request by default.
376       std::move(callback).Run(QUOTA_PERMISSION_RESPONSE_DISALLOW);
377     }
378   }
379 
380  private:
~CefQuotaPermissionContext()381   ~CefQuotaPermissionContext() override {}
382 
383   DISALLOW_COPY_AND_ASSIGN(CefQuotaPermissionContext);
384 };
385 
386 #if defined(OS_POSIX) && !defined(OS_MAC)
CreateCrashHandlerHost(const std::string & process_type)387 breakpad::CrashHandlerHostLinux* CreateCrashHandlerHost(
388     const std::string& process_type) {
389   base::FilePath dumps_path;
390   base::PathService::Get(chrome::DIR_CRASH_DUMPS, &dumps_path);
391   {
392     ANNOTATE_SCOPED_MEMORY_LEAK;
393     // Uploads will only occur if a non-empty crash URL is specified in
394     // AlloyMainDelegate::InitCrashReporter.
395     breakpad::CrashHandlerHostLinux* crash_handler =
396         new breakpad::CrashHandlerHostLinux(process_type, dumps_path,
397                                             true /* upload */);
398     crash_handler->StartUploaderThread();
399     return crash_handler;
400   }
401 }
402 
GetCrashSignalFD(const base::CommandLine & command_line)403 int GetCrashSignalFD(const base::CommandLine& command_line) {
404   if (!breakpad::IsCrashReporterEnabled())
405     return -1;
406 
407   // Extensions have the same process type as renderers.
408   if (command_line.HasSwitch(extensions::switches::kExtensionProcess)) {
409     static breakpad::CrashHandlerHostLinux* crash_handler = nullptr;
410     if (!crash_handler)
411       crash_handler = CreateCrashHandlerHost("extension");
412     return crash_handler->GetDeathSignalSocket();
413   }
414 
415   std::string process_type =
416       command_line.GetSwitchValueASCII(switches::kProcessType);
417 
418   if (process_type == switches::kRendererProcess) {
419     static breakpad::CrashHandlerHostLinux* crash_handler = nullptr;
420     if (!crash_handler)
421       crash_handler = CreateCrashHandlerHost(process_type);
422     return crash_handler->GetDeathSignalSocket();
423   }
424 
425   if (process_type == switches::kPpapiPluginProcess) {
426     static breakpad::CrashHandlerHostLinux* crash_handler = nullptr;
427     if (!crash_handler)
428       crash_handler = CreateCrashHandlerHost(process_type);
429     return crash_handler->GetDeathSignalSocket();
430   }
431 
432   if (process_type == switches::kGpuProcess) {
433     static breakpad::CrashHandlerHostLinux* crash_handler = nullptr;
434     if (!crash_handler)
435       crash_handler = CreateCrashHandlerHost(process_type);
436     return crash_handler->GetDeathSignalSocket();
437   }
438 
439   return -1;
440 }
441 #endif  // defined(OS_POSIX) && !defined(OS_MAC)
442 
443 // From chrome/browser/plugins/chrome_content_browser_client_plugins_part.cc.
BindPluginInfoHost(int render_process_id,mojo::PendingAssociatedReceiver<chrome::mojom::PluginInfoHost> receiver)444 void BindPluginInfoHost(
445     int render_process_id,
446     mojo::PendingAssociatedReceiver<chrome::mojom::PluginInfoHost> receiver) {
447   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
448   content::RenderProcessHost* host =
449       content::RenderProcessHost::FromID(render_process_id);
450   if (!host)
451     return;
452 
453   Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext());
454   mojo::MakeSelfOwnedAssociatedReceiver(
455       std::make_unique<PluginInfoHostImpl>(render_process_id, profile),
456       std::move(receiver));
457 }
458 
GetRootCachePath()459 base::FilePath GetRootCachePath() {
460   // The CefContext::ValidateCachePath method enforces the requirement that all
461   // cache_path values be either equal to or a child of root_cache_path.
462   return base::FilePath(
463       CefString(&CefContext::Get()->settings().root_cache_path));
464 }
465 
466 // Register BrowserInterfaceBroker's GetInterface() handler callbacks for
467 // chrome-specific document-scoped interfaces.
468 // Stub implementations to silence "Empty binder for interface
469 // blink.mojom.[Name] for the frame/document scope" errors.
470 // Based on chrome/browser/chrome_browser_interface_binders.cc.
PopulateChromeFrameBinders(mojo::BinderMapWithContext<content::RenderFrameHost * > * map)471 void PopulateChromeFrameBinders(
472     mojo::BinderMapWithContext<content::RenderFrameHost*>* map) {
473   map->Add<blink::mojom::InsecureInputService>(base::BindRepeating(
474       [](content::RenderFrameHost* frame_host,
475          mojo::PendingReceiver<blink::mojom::InsecureInputService> receiver) {
476       }));
477 
478   map->Add<blink::mojom::PrerenderProcessor>(base::BindRepeating(
479       [](content::RenderFrameHost* frame_host,
480          mojo::PendingReceiver<blink::mojom::PrerenderProcessor> receiver) {}));
481 }
482 
483 }  // namespace
484 
AlloyContentBrowserClient()485 AlloyContentBrowserClient::AlloyContentBrowserClient() {
486   plugin_service_filter_.reset(new CefPluginServiceFilter);
487   content::PluginServiceImpl::GetInstance()->SetFilter(
488       plugin_service_filter_.get());
489 }
490 
~AlloyContentBrowserClient()491 AlloyContentBrowserClient::~AlloyContentBrowserClient() {}
492 
493 std::unique_ptr<content::BrowserMainParts>
CreateBrowserMainParts(const content::MainFunctionParams & parameters)494 AlloyContentBrowserClient::CreateBrowserMainParts(
495     const content::MainFunctionParams& parameters) {
496   browser_main_parts_ = new AlloyBrowserMainParts(parameters);
497   return base::WrapUnique(browser_main_parts_);
498 }
499 
RenderProcessWillLaunch(content::RenderProcessHost * host)500 void AlloyContentBrowserClient::RenderProcessWillLaunch(
501     content::RenderProcessHost* host) {
502   const int id = host->GetID();
503   Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext());
504 
505   host->AddFilter(new CefBrowserMessageFilter(id));
506 
507   if (extensions::ExtensionsEnabled()) {
508     host->AddFilter(new extensions::ExtensionMessageFilter(id, profile));
509     host->AddFilter(
510         new extensions::ExtensionsGuestViewMessageFilter(id, profile));
511   }
512 
513   // If the renderer process crashes then the host may already have
514   // CefBrowserInfoManager as an observer. Try to remove it first before adding
515   // to avoid DCHECKs.
516   host->RemoveObserver(CefBrowserInfoManager::GetInstance());
517   host->AddObserver(CefBrowserInfoManager::GetInstance());
518 
519   // Forwards dynamic parameters to CefRenderThreadObserver.
520   Profile* original_profile = profile->GetOriginalProfile();
521   RendererUpdaterFactory::GetForProfile(original_profile)
522       ->InitializeRenderer(host);
523 }
524 
ShouldUseProcessPerSite(content::BrowserContext * browser_context,const GURL & effective_url)525 bool AlloyContentBrowserClient::ShouldUseProcessPerSite(
526     content::BrowserContext* browser_context,
527     const GURL& effective_url) {
528   if (!extensions::ExtensionsEnabled())
529     return false;
530 
531   if (!effective_url.SchemeIs(extensions::kExtensionScheme))
532     return false;
533 
534   extensions::ExtensionRegistry* registry =
535       extensions::ExtensionRegistry::Get(browser_context);
536   if (!registry)
537     return false;
538 
539   const extensions::Extension* extension =
540       registry->enabled_extensions().GetByID(effective_url.host());
541   if (!extension)
542     return false;
543 
544   // TODO(extensions): Extra checks required if type is TYPE_HOSTED_APP.
545 
546   // Hosted apps that have script access to their background page must use
547   // process per site, since all instances can make synchronous calls to the
548   // background window.  Other extensions should use process per site as well.
549   return true;
550 }
551 
552 // Based on
553 // ChromeContentBrowserClientExtensionsPart::DoesSiteRequireDedicatedProcess.
DoesSiteRequireDedicatedProcess(content::BrowserContext * browser_context,const GURL & effective_site_url)554 bool AlloyContentBrowserClient::DoesSiteRequireDedicatedProcess(
555     content::BrowserContext* browser_context,
556     const GURL& effective_site_url) {
557   if (!extensions::ExtensionsEnabled())
558     return false;
559 
560   const extensions::Extension* extension =
561       extensions::ExtensionRegistry::Get(browser_context)
562           ->enabled_extensions()
563           .GetExtensionOrAppByURL(effective_site_url);
564   // Isolate all extensions.
565   return extension != nullptr;
566 }
567 
OverrideURLLoaderFactoryParams(content::BrowserContext * browser_context,const url::Origin & origin,bool is_for_isolated_world,network::mojom::URLLoaderFactoryParams * factory_params)568 void AlloyContentBrowserClient::OverrideURLLoaderFactoryParams(
569     content::BrowserContext* browser_context,
570     const url::Origin& origin,
571     bool is_for_isolated_world,
572     network::mojom::URLLoaderFactoryParams* factory_params) {
573   if (extensions::ExtensionsEnabled()) {
574     extensions::URLLoaderFactoryManager::OverrideURLLoaderFactoryParams(
575         browser_context, origin, is_for_isolated_world, factory_params);
576   }
577 }
578 
GetAdditionalWebUISchemes(std::vector<std::string> * additional_schemes)579 void AlloyContentBrowserClient::GetAdditionalWebUISchemes(
580     std::vector<std::string>* additional_schemes) {
581   // Any schemes listed here are treated as WebUI schemes but do not get WebUI
582   // bindings. Also, view-source is allowed for these schemes. WebUI schemes
583   // will not be passed to HandleExternalProtocol.
584 }
585 
GetAdditionalViewSourceSchemes(std::vector<std::string> * additional_schemes)586 void AlloyContentBrowserClient::GetAdditionalViewSourceSchemes(
587     std::vector<std::string>* additional_schemes) {
588   GetAdditionalWebUISchemes(additional_schemes);
589 
590   additional_schemes->push_back(extensions::kExtensionScheme);
591 }
592 
GetAdditionalAllowedSchemesForFileSystem(std::vector<std::string> * additional_allowed_schemes)593 void AlloyContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
594     std::vector<std::string>* additional_allowed_schemes) {
595   ContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
596       additional_allowed_schemes);
597   additional_allowed_schemes->push_back(content::kChromeDevToolsScheme);
598   additional_allowed_schemes->push_back(content::kChromeUIScheme);
599 }
600 
IsWebUIAllowedToMakeNetworkRequests(const url::Origin & origin)601 bool AlloyContentBrowserClient::IsWebUIAllowedToMakeNetworkRequests(
602     const url::Origin& origin) {
603   return scheme::IsWebUIAllowedToMakeNetworkRequests(origin);
604 }
605 
IsHandledURL(const GURL & url)606 bool AlloyContentBrowserClient::IsHandledURL(const GURL& url) {
607   if (!url.is_valid())
608     return false;
609   const std::string& scheme = url.scheme();
610   DCHECK_EQ(scheme, base::ToLowerASCII(scheme));
611 
612   if (scheme::IsInternalHandledScheme(scheme))
613     return true;
614 
615   return CefAppManager::Get()->HasCustomScheme(scheme);
616 }
617 
SiteInstanceGotProcess(content::SiteInstance * site_instance)618 void AlloyContentBrowserClient::SiteInstanceGotProcess(
619     content::SiteInstance* site_instance) {
620   if (!extensions::ExtensionsEnabled())
621     return;
622 
623   // If this isn't an extension renderer there's nothing to do.
624   const extensions::Extension* extension = GetExtension(site_instance);
625   if (!extension)
626     return;
627 
628   auto browser_context =
629       static_cast<AlloyBrowserContext*>(site_instance->GetBrowserContext());
630 
631   extensions::ProcessMap::Get(browser_context)
632       ->Insert(extension->id(), site_instance->GetProcess()->GetID(),
633                site_instance->GetId());
634 }
635 
SiteInstanceDeleting(content::SiteInstance * site_instance)636 void AlloyContentBrowserClient::SiteInstanceDeleting(
637     content::SiteInstance* site_instance) {
638   if (!extensions::ExtensionsEnabled())
639     return;
640 
641   // May be NULL during shutdown.
642   if (!extensions::ExtensionsBrowserClient::Get())
643     return;
644 
645   // May be NULL during shutdown.
646   if (!site_instance->HasProcess())
647     return;
648 
649   // If this isn't an extension renderer there's nothing to do.
650   const extensions::Extension* extension = GetExtension(site_instance);
651   if (!extension)
652     return;
653 
654   auto browser_context =
655       static_cast<AlloyBrowserContext*>(site_instance->GetBrowserContext());
656 
657   extensions::ProcessMap::Get(browser_context)
658       ->Remove(extension->id(), site_instance->GetProcess()->GetID(),
659                site_instance->GetId());
660 }
661 
BindHostReceiverForRenderer(content::RenderProcessHost * render_process_host,mojo::GenericPendingReceiver receiver)662 void AlloyContentBrowserClient::BindHostReceiverForRenderer(
663     content::RenderProcessHost* render_process_host,
664     mojo::GenericPendingReceiver receiver) {
665   if (auto host_receiver = receiver.As<spellcheck::mojom::SpellCheckHost>()) {
666     SpellCheckHostChromeImpl::Create(render_process_host->GetID(),
667                                      std::move(host_receiver));
668     return;
669   }
670 
671 #if BUILDFLAG(HAS_SPELLCHECK_PANEL)
672   if (auto panel_host_receiver =
673           receiver.As<spellcheck::mojom::SpellCheckPanelHost>()) {
674     SpellCheckPanelHostImpl::Create(render_process_host->GetID(),
675                                     std::move(panel_host_receiver));
676     return;
677   }
678 #endif  // BUILDFLAG(HAS_SPELLCHECK_PANEL)
679 }
680 
AppendExtraCommandLineSwitches(base::CommandLine * command_line,int child_process_id)681 void AlloyContentBrowserClient::AppendExtraCommandLineSwitches(
682     base::CommandLine* command_line,
683     int child_process_id) {
684   const base::CommandLine* browser_cmd = base::CommandLine::ForCurrentProcess();
685 
686   {
687     // Propagate the following switches to all command lines (along with any
688     // associated values) if present in the browser command line.
689     static const char* const kSwitchNames[] = {
690       switches::kDisablePackLoading,
691 #if defined(OS_MAC)
692       switches::kFrameworkDirPath,
693       switches::kMainBundlePath,
694 #endif
695       switches::kLocalesDirPath,
696       switches::kLogFile,
697       switches::kLogSeverity,
698       switches::kResourcesDirPath,
699       embedder_support::kUserAgent,
700       switches::kUserAgentProductAndVersion,
701     };
702     command_line->CopySwitchesFrom(*browser_cmd, kSwitchNames,
703                                    base::size(kSwitchNames));
704   }
705 
706   const std::string& process_type =
707       command_line->GetSwitchValueASCII(switches::kProcessType);
708   if (process_type == switches::kRendererProcess) {
709     // Propagate the following switches to the renderer command line (along with
710     // any associated values) if present in the browser command line.
711     static const char* const kSwitchNames[] = {
712         switches::kDisableExtensions,
713         switches::kDisablePdfExtension,
714         switches::kDisablePlugins,
715         switches::kDisablePrintPreview,
716         switches::kDisableScrollBounce,
717         switches::kDisableSpellChecking,
718         switches::kEnableSpeechInput,
719         switches::kUncaughtExceptionStackSize,
720         network::switches::kUnsafelyTreatInsecureOriginAsSecure,
721     };
722     command_line->CopySwitchesFrom(*browser_cmd, kSwitchNames,
723                                    base::size(kSwitchNames));
724 
725     if (extensions::ExtensionsEnabled()) {
726       content::RenderProcessHost* process =
727           content::RenderProcessHost::FromID(child_process_id);
728       auto browser_context = process->GetBrowserContext();
729       CefBrowserContext* cef_browser_context =
730           process ? CefBrowserContext::FromBrowserContext(browser_context)
731                   : nullptr;
732       if (cef_browser_context) {
733         if (cef_browser_context->IsPrintPreviewSupported()) {
734           command_line->AppendSwitch(switches::kEnablePrintPreview);
735         }
736 
737         // Based on ChromeContentBrowserClientExtensionsPart::
738         // AppendExtraRendererCommandLineSwitches
739         if (extensions::ProcessMap::Get(browser_context)
740                 ->Contains(process->GetID())) {
741           command_line->AppendSwitch(extensions::switches::kExtensionProcess);
742         }
743       }
744     }
745   } else {
746     // Propagate the following switches to non-renderer command line (along with
747     // any associated values) if present in the browser command line.
748     static const char* const kSwitchNames[] = {
749         switches::kLang,
750     };
751     command_line->CopySwitchesFrom(*browser_cmd, kSwitchNames,
752                                    base::size(kSwitchNames));
753   }
754 
755 #if defined(OS_LINUX)
756   if (process_type == switches::kZygoteProcess) {
757 #if BUILDFLAG(ENABLE_WIDEVINE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
758     if (!browser_cmd->HasSwitch(sandbox::policy::switches::kNoSandbox)) {
759       // Pass the Widevine CDM path to the Zygote process. See comments in
760       // CefWidevineLoader::AddContentDecryptionModules.
761       const base::FilePath& cdm_path = CefWidevineLoader::GetInstance()->path();
762       if (!cdm_path.empty())
763         command_line->AppendSwitchPath(switches::kWidevineCdmPath, cdm_path);
764     }
765 #endif
766 
767     if (browser_cmd->HasSwitch(switches::kBrowserSubprocessPath)) {
768       // Force use of the sub-process executable path for the zygote process.
769       const base::FilePath& subprocess_path =
770           browser_cmd->GetSwitchValuePath(switches::kBrowserSubprocessPath);
771       if (!subprocess_path.empty())
772         command_line->SetProgram(subprocess_path);
773     }
774   }
775 #endif  // defined(OS_LINUX)
776 
777   CefRefPtr<CefApp> app = CefAppManager::Get()->GetApplication();
778   if (app.get()) {
779     CefRefPtr<CefBrowserProcessHandler> handler =
780         app->GetBrowserProcessHandler();
781     if (handler.get()) {
782       CefRefPtr<CefCommandLineImpl> commandLinePtr(
783           new CefCommandLineImpl(command_line, false, false));
784       handler->OnBeforeChildProcessLaunch(commandLinePtr.get());
785       commandLinePtr->Detach(nullptr);
786     }
787   }
788 }
789 
GetApplicationLocale()790 std::string AlloyContentBrowserClient::GetApplicationLocale() {
791   return g_browser_process->GetApplicationLocale();
792 }
793 
794 scoped_refptr<network::SharedURLLoaderFactory>
GetSystemSharedURLLoaderFactory()795 AlloyContentBrowserClient::GetSystemSharedURLLoaderFactory() {
796   DCHECK(
797       content::BrowserThread::CurrentlyOn(content::BrowserThread::UI) ||
798       !content::BrowserThread::IsThreadInitialized(content::BrowserThread::UI));
799 
800   if (!SystemNetworkContextManager::GetInstance())
801     return nullptr;
802 
803   return SystemNetworkContextManager::GetInstance()
804       ->GetSharedURLLoaderFactory();
805 }
806 
807 network::mojom::NetworkContext*
GetSystemNetworkContext()808 AlloyContentBrowserClient::GetSystemNetworkContext() {
809   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
810   DCHECK(SystemNetworkContextManager::GetInstance());
811   return SystemNetworkContextManager::GetInstance()->GetContext();
812 }
813 
814 scoped_refptr<content::QuotaPermissionContext>
CreateQuotaPermissionContext()815 AlloyContentBrowserClient::CreateQuotaPermissionContext() {
816   return new CefQuotaPermissionContext();
817 }
818 
GetMediaObserver()819 content::MediaObserver* AlloyContentBrowserClient::GetMediaObserver() {
820   return CefMediaCaptureDevicesDispatcher::GetInstance();
821 }
822 
823 content::SpeechRecognitionManagerDelegate*
CreateSpeechRecognitionManagerDelegate()824 AlloyContentBrowserClient::CreateSpeechRecognitionManagerDelegate() {
825   const base::CommandLine* command_line =
826       base::CommandLine::ForCurrentProcess();
827   if (command_line->HasSwitch(switches::kEnableSpeechInput))
828     return new CefSpeechRecognitionManagerDelegate();
829 
830   return nullptr;
831 }
832 
833 content::GeneratedCodeCacheSettings
GetGeneratedCodeCacheSettings(content::BrowserContext * context)834 AlloyContentBrowserClient::GetGeneratedCodeCacheSettings(
835     content::BrowserContext* context) {
836   // If we pass 0 for size, disk_cache will pick a default size using the
837   // heuristics based on available disk size. These are implemented in
838   // disk_cache::PreferredCacheSize in net/disk_cache/cache_util.cc.
839   const base::FilePath& cache_path = context->GetPath();
840   return content::GeneratedCodeCacheSettings(!cache_path.empty() /* enabled */,
841                                              0 /* size */, cache_path);
842 }
843 
AllowCertificateError(content::WebContents * web_contents,int cert_error,const net::SSLInfo & ssl_info,const GURL & request_url,bool is_main_frame_request,bool strict_enforcement,base::OnceCallback<void (content::CertificateRequestResultType)> callback)844 void AlloyContentBrowserClient::AllowCertificateError(
845     content::WebContents* web_contents,
846     int cert_error,
847     const net::SSLInfo& ssl_info,
848     const GURL& request_url,
849     bool is_main_frame_request,
850     bool strict_enforcement,
851     base::OnceCallback<void(content::CertificateRequestResultType)> callback) {
852   CEF_REQUIRE_UIT();
853 
854   if (!is_main_frame_request) {
855     // A sub-resource has a certificate error. The user doesn't really
856     // have a context for making the right decision, so block the request
857     // hard.
858     std::move(callback).Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY);
859     return;
860   }
861 
862   CefRefPtr<AlloyBrowserHostImpl> browser =
863       AlloyBrowserHostImpl::GetBrowserForContents(web_contents);
864   if (!browser.get())
865     return;
866   CefRefPtr<CefClient> client = browser->GetClient();
867   if (!client.get())
868     return;
869   CefRefPtr<CefRequestHandler> handler = client->GetRequestHandler();
870   if (!handler.get())
871     return;
872 
873   CefRefPtr<CefSSLInfo> cef_ssl_info = new CefSSLInfoImpl(ssl_info);
874 
875   CefRefPtr<CefAllowCertificateErrorCallbackImpl> callbackImpl(
876       new CefAllowCertificateErrorCallbackImpl(std::move(callback)));
877 
878   bool proceed = handler->OnCertificateError(
879       browser.get(), static_cast<cef_errorcode_t>(cert_error),
880       request_url.spec(), cef_ssl_info, callbackImpl.get());
881   if (!proceed) {
882     // |callback| may be null if the user executed it despite returning false.
883     callback = callbackImpl->Disconnect();
884     if (!callback.is_null()) {
885       std::move(callback).Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY);
886     }
887   }
888 }
889 
SelectClientCertificate(content::WebContents * web_contents,net::SSLCertRequestInfo * cert_request_info,net::ClientCertIdentityList client_certs,std::unique_ptr<content::ClientCertificateDelegate> delegate)890 base::OnceClosure AlloyContentBrowserClient::SelectClientCertificate(
891     content::WebContents* web_contents,
892     net::SSLCertRequestInfo* cert_request_info,
893     net::ClientCertIdentityList client_certs,
894     std::unique_ptr<content::ClientCertificateDelegate> delegate) {
895   CEF_REQUIRE_UIT();
896 
897   CefRefPtr<CefRequestHandler> handler;
898   CefRefPtr<AlloyBrowserHostImpl> browser =
899       AlloyBrowserHostImpl::GetBrowserForContents(web_contents);
900   if (browser.get()) {
901     CefRefPtr<CefClient> client = browser->GetClient();
902     if (client.get())
903       handler = client->GetRequestHandler();
904   }
905 
906   if (!handler.get()) {
907     delegate->ContinueWithCertificate(nullptr, nullptr);
908     return base::OnceClosure();
909   }
910 
911   CefRequestHandler::X509CertificateList certs;
912   for (net::ClientCertIdentityList::iterator iter = client_certs.begin();
913        iter != client_certs.end(); iter++) {
914     certs.push_back(new CefX509CertificateImpl(std::move(*iter)));
915   }
916 
917   CefRefPtr<CefSelectClientCertificateCallbackImpl> callbackImpl(
918       new CefSelectClientCertificateCallbackImpl(std::move(delegate)));
919 
920   bool proceed = handler->OnSelectClientCertificate(
921       browser.get(), cert_request_info->is_proxy,
922       cert_request_info->host_and_port.host(),
923       cert_request_info->host_and_port.port(), certs, callbackImpl.get());
924 
925   if (!proceed && !certs.empty()) {
926     callbackImpl->Select(certs[0]);
927   }
928   return base::OnceClosure();
929 }
930 
CanCreateWindow(content::RenderFrameHost * opener,const GURL & opener_url,const GURL & opener_top_level_frame_url,const url::Origin & source_origin,content::mojom::WindowContainerType container_type,const GURL & target_url,const content::Referrer & referrer,const std::string & frame_name,WindowOpenDisposition disposition,const blink::mojom::WindowFeatures & features,bool user_gesture,bool opener_suppressed,bool * no_javascript_access)931 bool AlloyContentBrowserClient::CanCreateWindow(
932     content::RenderFrameHost* opener,
933     const GURL& opener_url,
934     const GURL& opener_top_level_frame_url,
935     const url::Origin& source_origin,
936     content::mojom::WindowContainerType container_type,
937     const GURL& target_url,
938     const content::Referrer& referrer,
939     const std::string& frame_name,
940     WindowOpenDisposition disposition,
941     const blink::mojom::WindowFeatures& features,
942     bool user_gesture,
943     bool opener_suppressed,
944     bool* no_javascript_access) {
945   CEF_REQUIRE_UIT();
946   *no_javascript_access = false;
947 
948   return CefBrowserInfoManager::GetInstance()->CanCreateWindow(
949       opener, target_url, referrer, frame_name, disposition, features,
950       user_gesture, opener_suppressed, no_javascript_access);
951 }
952 
OverrideWebkitPrefs(content::WebContents * web_contents,blink::web_pref::WebPreferences * prefs)953 void AlloyContentBrowserClient::OverrideWebkitPrefs(
954     content::WebContents* web_contents,
955     blink::web_pref::WebPreferences* prefs) {
956   auto rvh = web_contents->GetRenderViewHost();
957 
958   // Using RVH instead of RFH here because rvh->GetMainFrame() may be nullptr
959   // when this method is called.
960   renderer_prefs::PopulateWebPreferences(rvh, *prefs);
961 
962   if (rvh->GetWidget()->GetView()) {
963     rvh->GetWidget()->GetView()->SetBackgroundColor(
964         prefs->base_background_color);
965   }
966 }
967 
OverrideWebPreferencesAfterNavigation(content::WebContents * web_contents,blink::web_pref::WebPreferences * prefs)968 bool AlloyContentBrowserClient::OverrideWebPreferencesAfterNavigation(
969     content::WebContents* web_contents,
970     blink::web_pref::WebPreferences* prefs) {
971   return renderer_prefs::PopulateWebPreferencesAfterNavigation(web_contents,
972                                                                *prefs);
973 }
974 
BrowserURLHandlerCreated(content::BrowserURLHandler * handler)975 void AlloyContentBrowserClient::BrowserURLHandlerCreated(
976     content::BrowserURLHandler* handler) {
977   scheme::BrowserURLHandlerCreated(handler);
978 }
979 
GetDefaultDownloadName()980 std::string AlloyContentBrowserClient::GetDefaultDownloadName() {
981   return "download";
982 }
983 
DidCreatePpapiPlugin(content::BrowserPpapiHost * browser_host)984 void AlloyContentBrowserClient::DidCreatePpapiPlugin(
985     content::BrowserPpapiHost* browser_host) {
986   browser_host->GetPpapiHost()->AddHostFactoryFilter(
987       std::unique_ptr<ppapi::host::HostFactory>(
988           new ChromeBrowserPepperHostFactory(browser_host)));
989 }
990 
991 std::unique_ptr<content::DevToolsManagerDelegate>
CreateDevToolsManagerDelegate()992 AlloyContentBrowserClient::CreateDevToolsManagerDelegate() {
993   return std::make_unique<CefDevToolsManagerDelegate>();
994 }
995 
996 std::vector<std::unique_ptr<content::NavigationThrottle>>
CreateThrottlesForNavigation(content::NavigationHandle * navigation_handle)997 AlloyContentBrowserClient::CreateThrottlesForNavigation(
998     content::NavigationHandle* navigation_handle) {
999   throttle::NavigationThrottleList throttles;
1000   throttle::CreateThrottlesForNavigation(navigation_handle, throttles);
1001   return throttles;
1002 }
1003 
1004 std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
CreateURLLoaderThrottles(const network::ResourceRequest & request,content::BrowserContext * browser_context,const base::RepeatingCallback<content::WebContents * ()> & wc_getter,content::NavigationUIData * navigation_ui_data,int frame_tree_node_id)1005 AlloyContentBrowserClient::CreateURLLoaderThrottles(
1006     const network::ResourceRequest& request,
1007     content::BrowserContext* browser_context,
1008     const base::RepeatingCallback<content::WebContents*()>& wc_getter,
1009     content::NavigationUIData* navigation_ui_data,
1010     int frame_tree_node_id) {
1011   std::vector<std::unique_ptr<blink::URLLoaderThrottle>> result;
1012 
1013   // Used to substitute View ID for PDF contents when using the PDF plugin.
1014   result.push_back(std::make_unique<PluginResponseInterceptorURLLoaderThrottle>(
1015       request.destination, frame_tree_node_id));
1016 
1017   Profile* profile = Profile::FromBrowserContext(browser_context);
1018 
1019   chrome::mojom::DynamicParams dynamic_params = {
1020       profile->GetPrefs()->GetBoolean(prefs::kForceGoogleSafeSearch),
1021       profile->GetPrefs()->GetInteger(prefs::kForceYouTubeRestrict),
1022       profile->GetPrefs()->GetString(prefs::kAllowedDomainsForApps)};
1023   result.push_back(
1024       std::make_unique<GoogleURLLoaderThrottle>(std::move(dynamic_params)));
1025 
1026   return result;
1027 }
1028 
1029 #if defined(OS_LINUX)
GetAdditionalMappedFilesForChildProcess(const base::CommandLine & command_line,int child_process_id,content::PosixFileDescriptorInfo * mappings)1030 void AlloyContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
1031     const base::CommandLine& command_line,
1032     int child_process_id,
1033     content::PosixFileDescriptorInfo* mappings) {
1034   int crash_signal_fd = GetCrashSignalFD(command_line);
1035   if (crash_signal_fd >= 0) {
1036     mappings->Share(kCrashDumpSignal, crash_signal_fd);
1037   }
1038 }
1039 #endif  // defined(OS_LINUX)
1040 
ExposeInterfacesToRenderer(service_manager::BinderRegistry * registry,blink::AssociatedInterfaceRegistry * associated_registry,content::RenderProcessHost * host)1041 void AlloyContentBrowserClient::ExposeInterfacesToRenderer(
1042     service_manager::BinderRegistry* registry,
1043     blink::AssociatedInterfaceRegistry* associated_registry,
1044     content::RenderProcessHost* host) {
1045   associated_registry->AddInterface(
1046       base::BindRepeating(&BindPluginInfoHost, host->GetID()));
1047 }
1048 
1049 std::unique_ptr<net::ClientCertStore>
CreateClientCertStore(content::BrowserContext * browser_context)1050 AlloyContentBrowserClient::CreateClientCertStore(
1051     content::BrowserContext* browser_context) {
1052   // Match the logic in ProfileNetworkContextService::CreateClientCertStore.
1053 #if defined(USE_NSS_CERTS)
1054   // TODO: Add support for client implementation of crypto password dialog.
1055   return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreNSS(
1056       net::ClientCertStoreNSS::PasswordDelegateFactory()));
1057 #elif defined(OS_WIN)
1058   return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreWin());
1059 #elif defined(OS_MAC)
1060   return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreMac());
1061 #else
1062 #error Unknown platform.
1063 #endif
1064 }
1065 
1066 std::unique_ptr<content::LoginDelegate>
CreateLoginDelegate(const net::AuthChallengeInfo & auth_info,content::WebContents * web_contents,const content::GlobalRequestID & request_id,bool is_request_for_main_frame,const GURL & url,scoped_refptr<net::HttpResponseHeaders> response_headers,bool first_auth_attempt,LoginAuthRequiredCallback auth_required_callback)1067 AlloyContentBrowserClient::CreateLoginDelegate(
1068     const net::AuthChallengeInfo& auth_info,
1069     content::WebContents* web_contents,
1070     const content::GlobalRequestID& request_id,
1071     bool is_request_for_main_frame,
1072     const GURL& url,
1073     scoped_refptr<net::HttpResponseHeaders> response_headers,
1074     bool first_auth_attempt,
1075     LoginAuthRequiredCallback auth_required_callback) {
1076   return std::make_unique<net_service::LoginDelegate>(
1077       auth_info, web_contents, request_id, url,
1078       std::move(auth_required_callback));
1079 }
1080 
RegisterNonNetworkNavigationURLLoaderFactories(int frame_tree_node_id,ukm::SourceIdObj ukm_source_id,NonNetworkURLLoaderFactoryMap * factories)1081 void AlloyContentBrowserClient::RegisterNonNetworkNavigationURLLoaderFactories(
1082     int frame_tree_node_id,
1083     ukm::SourceIdObj ukm_source_id,
1084     NonNetworkURLLoaderFactoryMap* factories) {
1085   if (!extensions::ExtensionsEnabled())
1086     return;
1087 
1088   content::WebContents* web_contents =
1089       content::WebContents::FromFrameTreeNodeId(frame_tree_node_id);
1090   factories->emplace(
1091       extensions::kExtensionScheme,
1092       extensions::CreateExtensionNavigationURLLoaderFactory(
1093           web_contents->GetBrowserContext(), ukm_source_id,
1094           !!extensions::WebViewGuest::FromWebContents(web_contents)));
1095 }
1096 
RegisterNonNetworkSubresourceURLLoaderFactories(int render_process_id,int render_frame_id,NonNetworkURLLoaderFactoryMap * factories)1097 void AlloyContentBrowserClient::RegisterNonNetworkSubresourceURLLoaderFactories(
1098     int render_process_id,
1099     int render_frame_id,
1100     NonNetworkURLLoaderFactoryMap* factories) {
1101   if (!extensions::ExtensionsEnabled())
1102     return;
1103 
1104   auto factory = extensions::CreateExtensionURLLoaderFactory(render_process_id,
1105                                                              render_frame_id);
1106   if (factory)
1107     factories->emplace(extensions::kExtensionScheme, std::move(factory));
1108 
1109   content::RenderFrameHost* frame_host =
1110       content::RenderFrameHost::FromID(render_process_id, render_frame_id);
1111   content::WebContents* web_contents =
1112       content::WebContents::FromRenderFrameHost(frame_host);
1113   if (!web_contents)
1114     return;
1115 
1116   extensions::CefExtensionWebContentsObserver* web_observer =
1117       extensions::CefExtensionWebContentsObserver::FromWebContents(
1118           web_contents);
1119 
1120   // There is nothing to do if no CefExtensionWebContentsObserver is attached
1121   // to the |web_contents|.
1122   if (!web_observer)
1123     return;
1124 
1125   const extensions::Extension* extension =
1126       web_observer->GetExtensionFromFrame(frame_host, false);
1127   if (!extension)
1128     return;
1129 
1130   std::vector<std::string> allowed_webui_hosts;
1131   // Support for chrome:// scheme if appropriate.
1132   if ((extension->is_extension() || extension->is_platform_app()) &&
1133       extensions::Manifest::IsComponentLocation(extension->location())) {
1134     // Components of chrome that are implemented as extensions or platform apps
1135     // are allowed to use chrome://resources/ and chrome://theme/ URLs.
1136     // See also HasCrossOriginWhitelistEntry.
1137     allowed_webui_hosts.emplace_back(content::kChromeUIResourcesHost);
1138     allowed_webui_hosts.emplace_back(chrome::kChromeUIThemeHost);
1139   }
1140   if (!allowed_webui_hosts.empty()) {
1141     factories->emplace(content::kChromeUIScheme,
1142                        content::CreateWebUIURLLoaderFactory(
1143                            frame_host, content::kChromeUIScheme,
1144                            std::move(allowed_webui_hosts)));
1145   }
1146 }
1147 
WillCreateURLLoaderFactory(content::BrowserContext * browser_context,content::RenderFrameHost * frame,int render_process_id,URLLoaderFactoryType type,const url::Origin & request_initiator,base::Optional<int64_t> navigation_id,ukm::SourceIdObj ukm_source_id,mojo::PendingReceiver<network::mojom::URLLoaderFactory> * factory_receiver,mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient> * header_client,bool * bypass_redirect_checks,bool * disable_secure_dns,network::mojom::URLLoaderFactoryOverridePtr * factory_override)1148 bool AlloyContentBrowserClient::WillCreateURLLoaderFactory(
1149     content::BrowserContext* browser_context,
1150     content::RenderFrameHost* frame,
1151     int render_process_id,
1152     URLLoaderFactoryType type,
1153     const url::Origin& request_initiator,
1154     base::Optional<int64_t> navigation_id,
1155     ukm::SourceIdObj ukm_source_id,
1156     mojo::PendingReceiver<network::mojom::URLLoaderFactory>* factory_receiver,
1157     mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>*
1158         header_client,
1159     bool* bypass_redirect_checks,
1160     bool* disable_secure_dns,
1161     network::mojom::URLLoaderFactoryOverridePtr* factory_override) {
1162   auto request_handler = net_service::CreateInterceptedRequestHandler(
1163       browser_context, frame, render_process_id,
1164       type == URLLoaderFactoryType::kNavigation,
1165       type == URLLoaderFactoryType::kDownload, request_initiator);
1166 
1167   net_service::ProxyURLLoaderFactory::CreateProxy(
1168       browser_context, factory_receiver, header_client,
1169       std::move(request_handler));
1170   return true;
1171 }
1172 
OnNetworkServiceCreated(network::mojom::NetworkService * network_service)1173 void AlloyContentBrowserClient::OnNetworkServiceCreated(
1174     network::mojom::NetworkService* network_service) {
1175   DCHECK(g_browser_process);
1176   PrefService* local_state = g_browser_process->local_state();
1177   DCHECK(local_state);
1178 
1179   // Need to set up global NetworkService state before anything else uses it.
1180   DCHECK(SystemNetworkContextManager::GetInstance());
1181   SystemNetworkContextManager::GetInstance()->OnNetworkServiceCreated(
1182       network_service);
1183 }
1184 
ConfigureNetworkContextParams(content::BrowserContext * context,bool in_memory,const base::FilePath & relative_partition_path,network::mojom::NetworkContextParams * network_context_params,cert_verifier::mojom::CertVerifierCreationParams * cert_verifier_creation_params)1185 void AlloyContentBrowserClient::ConfigureNetworkContextParams(
1186     content::BrowserContext* context,
1187     bool in_memory,
1188     const base::FilePath& relative_partition_path,
1189     network::mojom::NetworkContextParams* network_context_params,
1190     cert_verifier::mojom::CertVerifierCreationParams*
1191         cert_verifier_creation_params) {
1192   // This method may be called during shutdown when using multi-threaded
1193   // message loop mode. In that case exit early to avoid crashes.
1194   if (!SystemNetworkContextManager::GetInstance()) {
1195     // This must match the value expected in
1196     // StoragePartitionImpl::InitNetworkContext.
1197     network_context_params->context_name = "magic_shutting_down";
1198     return;
1199   }
1200 
1201   auto cef_context = CefBrowserContext::FromBrowserContext(context);
1202 
1203   Profile* profile = cef_context->AsProfile();
1204   ProfileNetworkContextService* service =
1205       ProfileNetworkContextServiceFactory::GetForContext(profile);
1206   if (service) {
1207     service->ConfigureNetworkContextParams(in_memory, relative_partition_path,
1208                                            network_context_params,
1209                                            cert_verifier_creation_params);
1210   } else {
1211     // Set default params.
1212     network_context_params->user_agent = GetUserAgent();
1213     network_context_params->accept_language = GetApplicationLocale();
1214   }
1215 
1216   network_context_params->cookieable_schemes =
1217       cef_context->GetCookieableSchemes();
1218 
1219   // TODO(cef): Remove this and add required NetworkIsolationKeys,
1220   // this is currently not the case and this was not required pre M84.
1221   network_context_params->require_network_isolation_key = false;
1222 }
1223 
1224 // The sandbox may block read/write access from the NetworkService to
1225 // directories that are not returned by this method.
1226 std::vector<base::FilePath>
GetNetworkContextsParentDirectory()1227 AlloyContentBrowserClient::GetNetworkContextsParentDirectory() {
1228   base::FilePath user_data_path;
1229   base::PathService::Get(chrome::DIR_USER_DATA, &user_data_path);
1230   DCHECK(!user_data_path.empty());
1231 
1232   const auto& root_cache_path = GetRootCachePath();
1233 
1234   // root_cache_path may sometimes be empty or a child of user_data_path, so
1235   // only return the one path in that case.
1236   if (root_cache_path.empty() || user_data_path.IsParent(root_cache_path)) {
1237     return {user_data_path};
1238   }
1239 
1240   return {user_data_path, root_cache_path};
1241 }
1242 
HandleExternalProtocol(const GURL & url,content::WebContents::OnceGetter web_contents_getter,int child_id,int frame_tree_node_id,content::NavigationUIData * navigation_data,bool is_main_frame,ui::PageTransition page_transition,bool has_user_gesture,const base::Optional<url::Origin> & initiating_origin,mojo::PendingRemote<network::mojom::URLLoaderFactory> * out_factory)1243 bool AlloyContentBrowserClient::HandleExternalProtocol(
1244     const GURL& url,
1245     content::WebContents::OnceGetter web_contents_getter,
1246     int child_id,
1247     int frame_tree_node_id,
1248     content::NavigationUIData* navigation_data,
1249     bool is_main_frame,
1250     ui::PageTransition page_transition,
1251     bool has_user_gesture,
1252     const base::Optional<url::Origin>& initiating_origin,
1253     mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory) {
1254   // Call the other HandleExternalProtocol variant.
1255   return false;
1256 }
1257 
HandleExternalProtocol(content::WebContents::Getter web_contents_getter,int frame_tree_node_id,content::NavigationUIData * navigation_data,const network::ResourceRequest & resource_request,mojo::PendingRemote<network::mojom::URLLoaderFactory> * out_factory)1258 bool AlloyContentBrowserClient::HandleExternalProtocol(
1259     content::WebContents::Getter web_contents_getter,
1260     int frame_tree_node_id,
1261     content::NavigationUIData* navigation_data,
1262     const network::ResourceRequest& resource_request,
1263     mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory) {
1264   mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver =
1265       out_factory->InitWithNewPipeAndPassReceiver();
1266 
1267   // CefBrowserPlatformDelegate::HandleExternalProtocol may be called if
1268   // nothing handles the request.
1269   auto request_handler = net_service::CreateInterceptedRequestHandler(
1270       web_contents_getter, frame_tree_node_id, resource_request,
1271       base::Bind(CefBrowserPlatformDelegate::HandleExternalProtocol,
1272                  resource_request.url));
1273 
1274   net_service::ProxyURLLoaderFactory::CreateProxy(
1275       web_contents_getter, std::move(receiver), std::move(request_handler));
1276   return true;
1277 }
1278 
1279 std::unique_ptr<content::OverlayWindow>
CreateWindowForPictureInPicture(content::PictureInPictureWindowController * controller)1280 AlloyContentBrowserClient::CreateWindowForPictureInPicture(
1281     content::PictureInPictureWindowController* controller) {
1282   // Note: content::OverlayWindow::Create() is defined by platform-specific
1283   // implementation in chrome/browser/ui/views. This layering hack, which goes
1284   // through //content and ContentBrowserClient, allows us to work around the
1285   // dependency constraints that disallow directly calling
1286   // chrome/browser/ui/views code either from here or from other code in
1287   // chrome/browser.
1288   return content::OverlayWindow::Create(controller);
1289 }
1290 
RegisterBrowserInterfaceBindersForFrame(content::RenderFrameHost * render_frame_host,mojo::BinderMapWithContext<content::RenderFrameHost * > * map)1291 void AlloyContentBrowserClient::RegisterBrowserInterfaceBindersForFrame(
1292     content::RenderFrameHost* render_frame_host,
1293     mojo::BinderMapWithContext<content::RenderFrameHost*>* map) {
1294   PopulateChromeFrameBinders(map);
1295 
1296   if (!extensions::ExtensionsEnabled())
1297     return;
1298 
1299   content::WebContents* web_contents =
1300       content::WebContents::FromRenderFrameHost(render_frame_host);
1301   if (!web_contents)
1302     return;
1303 
1304   const GURL& site = render_frame_host->GetSiteInstance()->GetSiteURL();
1305   if (!site.SchemeIs(extensions::kExtensionScheme))
1306     return;
1307 
1308   content::BrowserContext* browser_context =
1309       render_frame_host->GetProcess()->GetBrowserContext();
1310   auto* extension = extensions::ExtensionRegistry::Get(browser_context)
1311                         ->enabled_extensions()
1312                         .GetByID(site.host());
1313   if (!extension)
1314     return;
1315   extensions::ExtensionsBrowserClient::Get()
1316       ->RegisterBrowserInterfaceBindersForFrame(map, render_frame_host,
1317                                                 extension);
1318 }
1319 
1320 base::FilePath
GetSandboxedStorageServiceDataDirectory()1321 AlloyContentBrowserClient::GetSandboxedStorageServiceDataDirectory() {
1322   return GetRootCachePath();
1323 }
1324 
GetProduct()1325 std::string AlloyContentBrowserClient::GetProduct() {
1326   return embedder_support::GetProduct();
1327 }
1328 
GetChromeProduct()1329 std::string AlloyContentBrowserClient::GetChromeProduct() {
1330   return version_info::GetProductNameAndVersionForUserAgent();
1331 }
1332 
GetUserAgent()1333 std::string AlloyContentBrowserClient::GetUserAgent() {
1334   return embedder_support::GetUserAgent();
1335 }
1336 
GetUserAgentMetadata()1337 blink::UserAgentMetadata AlloyContentBrowserClient::GetUserAgentMetadata() {
1338   blink::UserAgentMetadata metadata;
1339 
1340   metadata.brand_version_list = {blink::UserAgentBrandVersion{
1341       version_info::GetProductName(), version_info::GetMajorVersionNumber()}};
1342   metadata.full_version = version_info::GetVersionNumber();
1343   metadata.platform = version_info::GetOSType();
1344 
1345   // TODO(mkwst): Poke at BuildUserAgentFromProduct to split out these pieces.
1346   metadata.architecture = "";
1347   metadata.model = "";
1348 
1349   return metadata;
1350 }
1351 
1352 base::flat_set<std::string>
GetPluginMimeTypesWithExternalHandlers(content::BrowserContext * browser_context)1353 AlloyContentBrowserClient::GetPluginMimeTypesWithExternalHandlers(
1354     content::BrowserContext* browser_context) {
1355   base::flat_set<std::string> mime_types;
1356   auto map = PluginUtils::GetMimeTypeToExtensionIdMap(browser_context);
1357   for (const auto& pair : map)
1358     mime_types.insert(pair.first);
1359   return mime_types;
1360 }
1361 
ArePersistentMediaDeviceIDsAllowed(content::BrowserContext * browser_context,const GURL & url,const GURL & site_for_cookies,const base::Optional<url::Origin> & top_frame_origin)1362 bool AlloyContentBrowserClient::ArePersistentMediaDeviceIDsAllowed(
1363     content::BrowserContext* browser_context,
1364     const GURL& url,
1365     const GURL& site_for_cookies,
1366     const base::Optional<url::Origin>& top_frame_origin) {
1367   // Persistent MediaDevice IDs are allowed if cookies are allowed.
1368   return CookieSettingsFactory::GetForProfile(
1369              Profile::FromBrowserContext(browser_context))
1370       ->IsCookieAccessAllowed(url, site_for_cookies, top_frame_origin);
1371 }
1372 
ShouldAllowPluginCreation(const url::Origin & embedder_origin,const content::PepperPluginInfo & plugin_info)1373 bool AlloyContentBrowserClient::ShouldAllowPluginCreation(
1374     const url::Origin& embedder_origin,
1375     const content::PepperPluginInfo& plugin_info) {
1376   if (plugin_info.name == ChromeContentClient::kPDFInternalPluginName) {
1377     // Allow embedding the internal PDF plugin in the built-in PDF extension.
1378     if (embedder_origin.scheme() == extensions::kExtensionScheme &&
1379         embedder_origin.host() == extension_misc::kPdfExtensionId) {
1380       return true;
1381     }
1382 
1383     // Allow embedding the internal PDF plugin in chrome://print.
1384     if (embedder_origin ==
1385         url::Origin::Create(GURL(chrome::kChromeUIPrintURL))) {
1386       return true;
1387     }
1388 
1389     // Only allow the PDF plugin in the known, trustworthy origins that are
1390     // allowlisted above.  See also https://crbug.com/520422 and
1391     // https://crbug.com/1027173.
1392     return false;
1393   }
1394 
1395   return true;
1396 }
1397 
request_context() const1398 CefRefPtr<CefRequestContextImpl> AlloyContentBrowserClient::request_context()
1399     const {
1400   return browser_main_parts_->request_context();
1401 }
1402 
devtools_delegate() const1403 CefDevToolsDelegate* AlloyContentBrowserClient::devtools_delegate() const {
1404   return browser_main_parts_->devtools_delegate();
1405 }
1406 
1407 scoped_refptr<base::SingleThreadTaskRunner>
background_task_runner() const1408 AlloyContentBrowserClient::background_task_runner() const {
1409   return browser_main_parts_->background_task_runner();
1410 }
1411 
1412 scoped_refptr<base::SingleThreadTaskRunner>
user_visible_task_runner() const1413 AlloyContentBrowserClient::user_visible_task_runner() const {
1414   return browser_main_parts_->user_visible_task_runner();
1415 }
1416 
1417 scoped_refptr<base::SingleThreadTaskRunner>
user_blocking_task_runner() const1418 AlloyContentBrowserClient::user_blocking_task_runner() const {
1419   return browser_main_parts_->user_blocking_task_runner();
1420 }
1421 
GetExtension(content::SiteInstance * site_instance)1422 const extensions::Extension* AlloyContentBrowserClient::GetExtension(
1423     content::SiteInstance* site_instance) {
1424   extensions::ExtensionRegistry* registry =
1425       extensions::ExtensionRegistry::Get(site_instance->GetBrowserContext());
1426   if (!registry)
1427     return nullptr;
1428   return registry->enabled_extensions().GetExtensionOrAppByURL(
1429       site_instance->GetSiteURL());
1430 }
1431