summaryrefslogtreecommitdiff
path: root/libcef/browser/alloy/alloy_content_browser_client.cc
diff options
context:
space:
mode:
authorInna Palant <ipalant@google.com>2023-12-12 19:56:22 -0800
committerInna Palant <ipalant@google.com>2023-12-12 19:56:22 -0800
commit1ee1f36e3b492d7a6a0bf2367fe509365853aeaa (patch)
treea5790e155ff0d998639beb6172dfa0feb294aac9 /libcef/browser/alloy/alloy_content_browser_client.cc
parent1e76199e6f0ded437fca14eb9e512e0c6bd0fc1e (diff)
parentc33b736614ef77e4048cee551999a656a5ef465f (diff)
downloadcef-1ee1f36e3b492d7a6a0bf2367fe509365853aeaa.tar.gz
Merge remote-tracking branch 'origin/upstream'main
Import b/312293934
Diffstat (limited to 'libcef/browser/alloy/alloy_content_browser_client.cc')
-rw-r--r--libcef/browser/alloy/alloy_content_browser_client.cc1419
1 files changed, 1419 insertions, 0 deletions
diff --git a/libcef/browser/alloy/alloy_content_browser_client.cc b/libcef/browser/alloy/alloy_content_browser_client.cc
new file mode 100644
index 00000000..55711ca3
--- /dev/null
+++ b/libcef/browser/alloy/alloy_content_browser_client.cc
@@ -0,0 +1,1419 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "libcef/browser/alloy/alloy_content_browser_client.h"
+
+#include <algorithm>
+#include <tuple>
+#include <utility>
+
+#include "include/cef_version.h"
+#include "libcef/browser/alloy/alloy_browser_context.h"
+#include "libcef/browser/alloy/alloy_browser_host_impl.h"
+#include "libcef/browser/alloy/alloy_browser_main.h"
+#include "libcef/browser/alloy/alloy_web_contents_view_delegate.h"
+#include "libcef/browser/browser_context.h"
+#include "libcef/browser/browser_frame.h"
+#include "libcef/browser/browser_info.h"
+#include "libcef/browser/browser_info_manager.h"
+#include "libcef/browser/browser_manager.h"
+#include "libcef/browser/browser_platform_delegate.h"
+#include "libcef/browser/certificate_query.h"
+#include "libcef/browser/context.h"
+#include "libcef/browser/devtools/devtools_manager_delegate.h"
+#include "libcef/browser/extensions/extension_system.h"
+#include "libcef/browser/extensions/extension_web_contents_observer.h"
+#include "libcef/browser/media_capture_devices_dispatcher.h"
+#include "libcef/browser/net/chrome_scheme_handler.h"
+#include "libcef/browser/net/throttle_handler.h"
+#include "libcef/browser/net_service/cookie_manager_impl.h"
+#include "libcef/browser/net_service/login_delegate.h"
+#include "libcef/browser/net_service/proxy_url_loader_factory.h"
+#include "libcef/browser/net_service/resource_request_handler_wrapper.h"
+#include "libcef/browser/prefs/renderer_prefs.h"
+#include "libcef/browser/speech_recognition_manager_delegate.h"
+#include "libcef/browser/thread_util.h"
+#include "libcef/browser/x509_certificate_impl.h"
+#include "libcef/common/alloy/alloy_content_client.h"
+#include "libcef/common/app_manager.h"
+#include "libcef/common/cef_switches.h"
+#include "libcef/common/command_line_impl.h"
+#include "libcef/common/extensions/extensions_util.h"
+#include "libcef/common/frame_util.h"
+#include "libcef/common/net/scheme_registration.h"
+#include "libcef/common/request_impl.h"
+
+#include "base/base_switches.h"
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/json/json_reader.h"
+#include "base/path_service.h"
+#include "base/stl_util.h"
+#include "base/threading/thread_restrictions.h"
+#include "cef/grit/cef_resources.h"
+#include "chrome/browser/accessibility/live_caption_unavailability_notifier.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/content_settings/cookie_settings_factory.h"
+#include "chrome/browser/extensions/chrome_content_browser_client_extensions_part.h"
+#include "chrome/browser/net/profile_network_context_service.h"
+#include "chrome/browser/net/profile_network_context_service_factory.h"
+#include "chrome/browser/net/system_network_context_manager.h"
+#include "chrome/browser/pdf/chrome_pdf_stream_delegate.h"
+#include "chrome/browser/plugins/pdf_iframe_navigation_throttle.h"
+#include "chrome/browser/plugins/plugin_info_host_impl.h"
+#include "chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.h"
+#include "chrome/browser/plugins/plugin_utils.h"
+#include "chrome/browser/predictors/network_hints_handler_impl.h"
+#include "chrome/browser/printing/print_view_manager.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/renderer_updater.h"
+#include "chrome/browser/profiles/renderer_updater_factory.h"
+#include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h"
+#include "chrome/browser/spellchecker/spell_check_host_chrome_impl.h"
+#include "chrome/browser/ui/chrome_select_file_policy.h"
+#include "chrome/common/chrome_content_client.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/google_url_loader_throttle.h"
+#include "chrome/common/pdf_util.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/webui_url_constants.h"
+#include "chrome/grit/browser_resources.h"
+#include "chrome/grit/generated_resources.h"
+#include "chrome/services/printing/printing_service.h"
+#include "components/content_settings/core/browser/cookie_settings.h"
+#include "components/embedder_support/switches.h"
+#include "components/embedder_support/user_agent_utils.h"
+#include "components/pdf/browser/pdf_navigation_throttle.h"
+#include "components/pdf/browser/pdf_url_loader_request_interceptor.h"
+#include "components/pdf/browser/pdf_web_contents_helper.h"
+#include "components/pdf/common/internal_plugin_helpers.h"
+#include "components/spellcheck/common/spellcheck.mojom.h"
+#include "components/version_info/version_info.h"
+#include "content/browser/plugin_service_impl.h"
+#include "content/browser/renderer_host/render_frame_host_impl.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_ppapi_host.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/client_certificate_delegate.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/overlay_window.h"
+#include "content/public/browser/page_navigator.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/browser/web_ui_url_loader_factory.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/url_constants.h"
+#include "content/public/common/user_agent.h"
+#include "crypto/crypto_buildflags.h"
+#include "extensions/browser/event_router.h"
+#include "extensions/browser/extension_message_filter.h"
+#include "extensions/browser/extension_protocols.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extension_web_contents_observer.h"
+#include "extensions/browser/extensions_browser_client.h"
+#include "extensions/browser/guest_view/extensions_guest_view.h"
+#include "extensions/browser/guest_view/web_view/web_view_guest.h"
+#include "extensions/browser/info_map.h"
+#include "extensions/browser/process_map.h"
+#include "extensions/browser/renderer_startup_helper.h"
+#include "extensions/browser/url_loader_factory_manager.h"
+#include "extensions/common/constants.h"
+#include "extensions/common/switches.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
+#include "net/base/auth.h"
+#include "net/ssl/ssl_cert_request_info.h"
+#include "net/ssl/ssl_private_key.h"
+#include "pdf/pdf_features.h"
+#include "ppapi/host/ppapi_host.h"
+#include "sandbox/policy/switches.h"
+#include "services/network/public/cpp/network_switches.h"
+#include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h"
+#include "services/service_manager/public/mojom/connector.mojom.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
+#include "third_party/blink/public/common/web_preferences/web_preferences.h"
+#include "third_party/blink/public/mojom/badging/badging.mojom.h"
+#include "third_party/blink/public/mojom/prerender/prerender.mojom.h"
+#include "third_party/blink/public/web/web_window_features.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/ui_base_switches.h"
+#include "url/gurl.h"
+
+#if BUILDFLAG(IS_MAC)
+#include "net/ssl/client_cert_store_mac.h"
+#include "services/video_capture/public/mojom/constants.mojom.h"
+#elif BUILDFLAG(IS_POSIX)
+#include "components/crash/core/app/crash_switches.h"
+#include "components/crash/core/app/crashpad.h"
+#include "content/public/common/content_descriptors.h"
+#include "libcef/common/crash_reporting.h"
+#endif
+
+#if BUILDFLAG(IS_WIN)
+#include "net/ssl/client_cert_store_win.h"
+#include "sandbox/win/src/sandbox_policy.h"
+#endif
+
+#if BUILDFLAG(USE_NSS_CERTS)
+#include "net/ssl/client_cert_store_nss.h"
+#endif
+
+#if BUILDFLAG(HAS_SPELLCHECK_PANEL)
+#include "chrome/browser/spellchecker/spell_check_panel_host_impl.h"
+#endif
+
+namespace {
+
+class CefSelectClientCertificateCallbackImpl
+ : public CefSelectClientCertificateCallback {
+ public:
+ explicit CefSelectClientCertificateCallbackImpl(
+ std::unique_ptr<content::ClientCertificateDelegate> delegate)
+ : delegate_(std::move(delegate)) {}
+
+ CefSelectClientCertificateCallbackImpl(
+ const CefSelectClientCertificateCallbackImpl&) = delete;
+ CefSelectClientCertificateCallbackImpl& operator=(
+ const CefSelectClientCertificateCallbackImpl&) = delete;
+
+ ~CefSelectClientCertificateCallbackImpl() {
+ // If Select has not been called, call it with NULL to continue without any
+ // client certificate.
+ if (delegate_) {
+ DoSelect(nullptr);
+ }
+ }
+
+ void Select(CefRefPtr<CefX509Certificate> cert) override {
+ if (delegate_) {
+ DoSelect(cert);
+ }
+ }
+
+ private:
+ void DoSelect(CefRefPtr<CefX509Certificate> cert) {
+ if (CEF_CURRENTLY_ON_UIT()) {
+ RunNow(std::move(delegate_), cert);
+ } else {
+ CEF_POST_TASK(
+ CEF_UIT,
+ base::BindOnce(&CefSelectClientCertificateCallbackImpl::RunNow,
+ std::move(delegate_), cert));
+ }
+ }
+
+ static void RunNow(
+ std::unique_ptr<content::ClientCertificateDelegate> delegate,
+ CefRefPtr<CefX509Certificate> cert) {
+ CEF_REQUIRE_UIT();
+
+ if (cert) {
+ CefX509CertificateImpl* certImpl =
+ static_cast<CefX509CertificateImpl*>(cert.get());
+ certImpl->AcquirePrivateKey(base::BindOnce(
+ &CefSelectClientCertificateCallbackImpl::RunWithPrivateKey,
+ std::move(delegate), cert));
+ return;
+ }
+
+ delegate->ContinueWithCertificate(nullptr, nullptr);
+ }
+
+ static void RunWithPrivateKey(
+ std::unique_ptr<content::ClientCertificateDelegate> delegate,
+ CefRefPtr<CefX509Certificate> cert,
+ scoped_refptr<net::SSLPrivateKey> key) {
+ CEF_REQUIRE_UIT();
+ DCHECK(cert);
+
+ if (key) {
+ CefX509CertificateImpl* certImpl =
+ static_cast<CefX509CertificateImpl*>(cert.get());
+ delegate->ContinueWithCertificate(certImpl->GetInternalCertObject(), key);
+ } else {
+ delegate->ContinueWithCertificate(nullptr, nullptr);
+ }
+ }
+
+ std::unique_ptr<content::ClientCertificateDelegate> delegate_;
+
+ IMPLEMENT_REFCOUNTING(CefSelectClientCertificateCallbackImpl);
+};
+
+#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
+int GetCrashSignalFD() {
+ if (!crash_reporting::Enabled()) {
+ return -1;
+ }
+
+ int fd;
+ pid_t pid;
+ return crash_reporter::GetHandlerSocket(&fd, &pid) ? fd : -1;
+}
+#endif // BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
+
+// From chrome/browser/plugins/chrome_content_browser_client_plugins_part.cc.
+void BindPluginInfoHost(
+ int render_process_id,
+ mojo::PendingAssociatedReceiver<chrome::mojom::PluginInfoHost> receiver) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ content::RenderProcessHost* host =
+ content::RenderProcessHost::FromID(render_process_id);
+ if (!host) {
+ return;
+ }
+
+ Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext());
+ mojo::MakeSelfOwnedAssociatedReceiver(
+ std::make_unique<PluginInfoHostImpl>(render_process_id, profile),
+ std::move(receiver));
+}
+
+void BindBadgeService(
+ content::RenderFrameHost* frame_host,
+ mojo::PendingReceiver<blink::mojom::BadgeService> receiver) {}
+
+void BindBadgeServiceForServiceWorker(
+ const content::ServiceWorkerVersionBaseInfo& info,
+ mojo::PendingReceiver<blink::mojom::BadgeService> receiver) {}
+
+void BindMediaFoundationRendererNotifierHandler(
+ content::RenderFrameHost* frame_host,
+ mojo::PendingReceiver<media::mojom::MediaFoundationRendererNotifier>
+ receiver) {}
+
+void BindNetworkHintsHandler(
+ content::RenderFrameHost* frame_host,
+ mojo::PendingReceiver<network_hints::mojom::NetworkHintsHandler> receiver) {
+ predictors::NetworkHintsHandlerImpl::Create(frame_host, std::move(receiver));
+}
+
+base::FilePath GetRootCachePath() {
+ // The CefContext::ValidateCachePath method enforces the requirement that all
+ // cache_path values be either equal to or a child of root_cache_path.
+ return base::FilePath(
+ CefString(&CefContext::Get()->settings().root_cache_path));
+}
+
+const extensions::Extension* GetEnabledExtensionFromSiteURL(
+ content::BrowserContext* context,
+ const GURL& site_url) {
+ if (!site_url.SchemeIs(extensions::kExtensionScheme)) {
+ return nullptr;
+ }
+
+ auto registry = extensions::ExtensionRegistry::Get(context);
+ if (!registry) {
+ return nullptr;
+ }
+
+ return registry->enabled_extensions().GetByID(site_url.host());
+}
+
+} // namespace
+
+AlloyContentBrowserClient::AlloyContentBrowserClient() = default;
+
+AlloyContentBrowserClient::~AlloyContentBrowserClient() = default;
+
+std::unique_ptr<content::BrowserMainParts>
+AlloyContentBrowserClient::CreateBrowserMainParts(
+ bool /* is_integration_test */) {
+ auto browser_main_parts = std::make_unique<AlloyBrowserMainParts>();
+ browser_main_parts_ = browser_main_parts.get();
+ return browser_main_parts;
+}
+
+void AlloyContentBrowserClient::RenderProcessWillLaunch(
+ content::RenderProcessHost* host) {
+ const int id = host->GetID();
+ Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext());
+
+ if (extensions::ExtensionsEnabled()) {
+ host->AddFilter(new extensions::ExtensionMessageFilter(id, profile));
+ }
+
+ // If the renderer process crashes then the host may already have
+ // CefBrowserInfoManager as an observer. Try to remove it first before adding
+ // to avoid DCHECKs.
+ host->RemoveObserver(CefBrowserInfoManager::GetInstance());
+ host->AddObserver(CefBrowserInfoManager::GetInstance());
+
+ // Forwards dynamic parameters to CefRenderThreadObserver.
+ Profile* original_profile = profile->GetOriginalProfile();
+ RendererUpdaterFactory::GetForProfile(original_profile)
+ ->InitializeRenderer(host);
+}
+
+bool AlloyContentBrowserClient::ShouldUseProcessPerSite(
+ content::BrowserContext* browser_context,
+ const GURL& site_url) {
+ if (extensions::ExtensionsEnabled()) {
+ if (auto profile = Profile::FromBrowserContext(browser_context)) {
+ return extensions::ChromeContentBrowserClientExtensionsPart::
+ ShouldUseProcessPerSite(profile, site_url);
+ }
+ }
+
+ return content::ContentBrowserClient::ShouldUseProcessPerSite(browser_context,
+ site_url);
+}
+
+bool AlloyContentBrowserClient::ShouldUseSpareRenderProcessHost(
+ content::BrowserContext* browser_context,
+ const GURL& site_url) {
+ if (extensions::ExtensionsEnabled()) {
+ if (auto profile = Profile::FromBrowserContext(browser_context)) {
+ return extensions::ChromeContentBrowserClientExtensionsPart::
+ ShouldUseSpareRenderProcessHost(profile, site_url);
+ }
+ }
+
+ return content::ContentBrowserClient::ShouldUseSpareRenderProcessHost(
+ browser_context, site_url);
+}
+
+bool AlloyContentBrowserClient::DoesSiteRequireDedicatedProcess(
+ content::BrowserContext* browser_context,
+ const GURL& effective_site_url) {
+ if (extensions::ExtensionsEnabled()) {
+ return extensions::ChromeContentBrowserClientExtensionsPart::
+ DoesSiteRequireDedicatedProcess(browser_context, effective_site_url);
+ }
+
+ return content::ContentBrowserClient::DoesSiteRequireDedicatedProcess(
+ browser_context, effective_site_url);
+}
+
+bool AlloyContentBrowserClient::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
+ base::StringPiece scheme,
+ bool is_embedded_origin_secure) {
+ // This is needed to bypass the normal SameSite rules for any chrome:// page
+ // embedding a secure origin, regardless of the registrable domains of any
+ // intervening frames. For example, this is needed for browser UI to interact
+ // with SameSite cookies on accounts.google.com, which are used for logging
+ // into Cloud Print from chrome://print, for displaying a list of available
+ // accounts on the NTP (chrome://new-tab-page), etc.
+ if (is_embedded_origin_secure && scheme == content::kChromeUIScheme) {
+ return true;
+ }
+
+ if (extensions::ExtensionsEnabled()) {
+ return scheme == extensions::kExtensionScheme;
+ }
+
+ return false;
+}
+
+bool AlloyContentBrowserClient::
+ ShouldIgnoreSameSiteCookieRestrictionsWhenTopLevel(
+ base::StringPiece scheme,
+ bool is_embedded_origin_secure) {
+ return is_embedded_origin_secure && scheme == content::kChromeUIScheme;
+}
+
+void AlloyContentBrowserClient::OverrideURLLoaderFactoryParams(
+ content::BrowserContext* browser_context,
+ const url::Origin& origin,
+ bool is_for_isolated_world,
+ network::mojom::URLLoaderFactoryParams* factory_params) {
+ if (extensions::ExtensionsEnabled()) {
+ extensions::URLLoaderFactoryManager::OverrideURLLoaderFactoryParams(
+ browser_context, origin, is_for_isolated_world, factory_params);
+ }
+}
+
+void AlloyContentBrowserClient::GetAdditionalWebUISchemes(
+ std::vector<std::string>* additional_schemes) {
+ // Any schemes listed here are treated as WebUI schemes but do not get WebUI
+ // bindings. Also, view-source is allowed for these schemes. WebUI schemes
+ // will not be passed to HandleExternalProtocol.
+}
+
+void AlloyContentBrowserClient::GetAdditionalViewSourceSchemes(
+ std::vector<std::string>* additional_schemes) {
+ GetAdditionalWebUISchemes(additional_schemes);
+
+ additional_schemes->push_back(extensions::kExtensionScheme);
+}
+
+std::unique_ptr<ui::SelectFilePolicy>
+AlloyContentBrowserClient::CreateSelectFilePolicy(
+ content::WebContents* web_contents) {
+ return std::make_unique<ChromeSelectFilePolicy>(web_contents);
+}
+
+void AlloyContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
+ std::vector<std::string>* additional_allowed_schemes) {
+ ContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem(
+ additional_allowed_schemes);
+ additional_allowed_schemes->push_back(content::kChromeDevToolsScheme);
+ additional_allowed_schemes->push_back(content::kChromeUIScheme);
+ additional_allowed_schemes->push_back(content::kChromeUIUntrustedScheme);
+}
+
+bool AlloyContentBrowserClient::IsWebUIAllowedToMakeNetworkRequests(
+ const url::Origin& origin) {
+ return scheme::IsWebUIAllowedToMakeNetworkRequests(origin);
+}
+
+bool AlloyContentBrowserClient::IsHandledURL(const GURL& url) {
+ if (!url.is_valid()) {
+ return false;
+ }
+ const std::string& scheme = url.scheme();
+ DCHECK_EQ(scheme, base::ToLowerASCII(scheme));
+
+ if (scheme::IsInternalHandledScheme(scheme)) {
+ return true;
+ }
+
+ return CefAppManager::Get()->HasCustomScheme(scheme);
+}
+
+void AlloyContentBrowserClient::SiteInstanceGotProcess(
+ content::SiteInstance* site_instance) {
+ if (!extensions::ExtensionsEnabled()) {
+ return;
+ }
+
+ CHECK(site_instance->HasProcess());
+
+ auto context = site_instance->GetBrowserContext();
+
+ // Only add the process to the map if the SiteInstance's site URL is already
+ // a chrome-extension:// URL. This includes hosted apps, except in rare cases
+ // that a URL in the hosted app's extent is not treated as a hosted app (e.g.,
+ // for isolated origins or cross-site iframes). For that case, don't look up
+ // the hosted app's Extension from the site URL using GetExtensionOrAppByURL,
+ // since it isn't treated as a hosted app.
+ const auto extension =
+ GetEnabledExtensionFromSiteURL(context, site_instance->GetSiteURL());
+ if (!extension) {
+ return;
+ }
+
+ extensions::ProcessMap::Get(context)->Insert(
+ extension->id(), site_instance->GetProcess()->GetID(),
+ site_instance->GetId());
+}
+
+void AlloyContentBrowserClient::SiteInstanceDeleting(
+ content::SiteInstance* site_instance) {
+ if (!extensions::ExtensionsEnabled()) {
+ return;
+ }
+
+ if (!site_instance->HasProcess()) {
+ return;
+ }
+
+ auto context = site_instance->GetBrowserContext();
+ auto registry = extensions::ExtensionRegistry::Get(context);
+ if (!registry) {
+ return;
+ }
+
+ auto extension = registry->enabled_extensions().GetExtensionOrAppByURL(
+ site_instance->GetSiteURL());
+ if (!extension) {
+ return;
+ }
+
+ extensions::ProcessMap::Get(context)->Remove(
+ extension->id(), site_instance->GetProcess()->GetID(),
+ site_instance->GetId());
+}
+
+void AlloyContentBrowserClient::BindHostReceiverForRenderer(
+ content::RenderProcessHost* render_process_host,
+ mojo::GenericPendingReceiver receiver) {
+ if (auto host_receiver = receiver.As<spellcheck::mojom::SpellCheckHost>()) {
+ SpellCheckHostChromeImpl::Create(render_process_host->GetID(),
+ std::move(host_receiver));
+ return;
+ }
+
+#if BUILDFLAG(HAS_SPELLCHECK_PANEL)
+ if (auto panel_host_receiver =
+ receiver.As<spellcheck::mojom::SpellCheckPanelHost>()) {
+ SpellCheckPanelHostImpl::Create(render_process_host->GetID(),
+ std::move(panel_host_receiver));
+ return;
+ }
+#endif // BUILDFLAG(HAS_SPELLCHECK_PANEL)
+}
+
+void AlloyContentBrowserClient::AppendExtraCommandLineSwitches(
+ base::CommandLine* command_line,
+ int child_process_id) {
+ const base::CommandLine* browser_cmd = base::CommandLine::ForCurrentProcess();
+
+ {
+ // Propagate the following switches to all command lines (along with any
+ // associated values) if present in the browser command line.
+ static const char* const kSwitchNames[] = {
+ switches::kDisablePackLoading,
+#if BUILDFLAG(IS_MAC)
+ switches::kFrameworkDirPath,
+ switches::kMainBundlePath,
+#endif
+ switches::kLocalesDirPath,
+ switches::kLogSeverity,
+ switches::kResourcesDirPath,
+ embedder_support::kUserAgent,
+ switches::kUserAgentProductAndVersion,
+ };
+ command_line->CopySwitchesFrom(*browser_cmd, kSwitchNames,
+ std::size(kSwitchNames));
+ }
+
+ const std::string& process_type =
+ command_line->GetSwitchValueASCII(switches::kProcessType);
+ if (process_type == switches::kRendererProcess) {
+ // Propagate the following switches to the renderer command line (along with
+ // any associated values) if present in the browser command line.
+ static const char* const kSwitchNames[] = {
+ switches::kDisableExtensions,
+ switches::kDisablePdfExtension,
+ switches::kDisablePrintPreview,
+ switches::kDisableScrollBounce,
+ switches::kDisableSpellChecking,
+ switches::kEnableSpeechInput,
+ switches::kUncaughtExceptionStackSize,
+ network::switches::kUnsafelyTreatInsecureOriginAsSecure,
+ };
+ command_line->CopySwitchesFrom(*browser_cmd, kSwitchNames,
+ std::size(kSwitchNames));
+
+ if (extensions::ExtensionsEnabled()) {
+ content::RenderProcessHost* process =
+ content::RenderProcessHost::FromID(child_process_id);
+ auto browser_context = process->GetBrowserContext();
+ CefBrowserContext* cef_browser_context =
+ process ? CefBrowserContext::FromBrowserContext(browser_context)
+ : nullptr;
+ if (cef_browser_context) {
+ if (cef_browser_context->IsPrintPreviewSupported()) {
+ command_line->AppendSwitch(switches::kEnablePrintPreview);
+ }
+
+ // Based on ChromeContentBrowserClientExtensionsPart::
+ // AppendExtraRendererCommandLineSwitches
+ if (extensions::ProcessMap::Get(browser_context)
+ ->Contains(process->GetID())) {
+ command_line->AppendSwitch(extensions::switches::kExtensionProcess);
+ }
+ }
+ }
+ } else {
+ // Propagate the following switches to non-renderer command line (along with
+ // any associated values) if present in the browser command line.
+ static const char* const kSwitchNames[] = {
+ switches::kLang,
+ };
+ command_line->CopySwitchesFrom(*browser_cmd, kSwitchNames,
+ std::size(kSwitchNames));
+ }
+
+ // Necessary to populate DIR_USER_DATA in sub-processes.
+ // See resource_util.cc GetUserDataPath.
+ base::FilePath user_data_dir;
+ if (base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) {
+ command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir);
+ }
+
+#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
+ if (process_type == switches::kZygoteProcess) {
+ if (browser_cmd->HasSwitch(switches::kBrowserSubprocessPath)) {
+ // Force use of the sub-process executable path for the zygote process.
+ const base::FilePath& subprocess_path =
+ browser_cmd->GetSwitchValuePath(switches::kBrowserSubprocessPath);
+ if (!subprocess_path.empty()) {
+ command_line->SetProgram(subprocess_path);
+ }
+ }
+
+ // Propagate the following switches to the zygote command line (along with
+ // any associated values) if present in the browser command line.
+ static const char* const kSwitchNames[] = {
+ switches::kLogFile,
+ };
+ command_line->CopySwitchesFrom(*browser_cmd, kSwitchNames,
+ std::size(kSwitchNames));
+ }
+
+ if (crash_reporting::Enabled()) {
+ int fd;
+ pid_t pid;
+ if (crash_reporter::GetHandlerSocket(&fd, &pid)) {
+ command_line->AppendSwitchASCII(
+ crash_reporter::switches::kCrashpadHandlerPid,
+ base::NumberToString(pid));
+ }
+ }
+#endif // BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
+
+ CefRefPtr<CefApp> app = CefAppManager::Get()->GetApplication();
+ if (app.get()) {
+ CefRefPtr<CefBrowserProcessHandler> handler =
+ app->GetBrowserProcessHandler();
+ if (handler.get()) {
+ CefRefPtr<CefCommandLineImpl> commandLinePtr(
+ new CefCommandLineImpl(command_line, false, false));
+ handler->OnBeforeChildProcessLaunch(commandLinePtr.get());
+ std::ignore = commandLinePtr->Detach(nullptr);
+ }
+ }
+}
+
+std::string AlloyContentBrowserClient::GetApplicationLocale() {
+ return g_browser_process->GetApplicationLocale();
+}
+
+scoped_refptr<network::SharedURLLoaderFactory>
+AlloyContentBrowserClient::GetSystemSharedURLLoaderFactory() {
+ DCHECK(
+ content::BrowserThread::CurrentlyOn(content::BrowserThread::UI) ||
+ !content::BrowserThread::IsThreadInitialized(content::BrowserThread::UI));
+
+ if (!SystemNetworkContextManager::GetInstance()) {
+ return nullptr;
+ }
+
+ return SystemNetworkContextManager::GetInstance()
+ ->GetSharedURLLoaderFactory();
+}
+
+network::mojom::NetworkContext*
+AlloyContentBrowserClient::GetSystemNetworkContext() {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ DCHECK(SystemNetworkContextManager::GetInstance());
+ return SystemNetworkContextManager::GetInstance()->GetContext();
+}
+
+content::MediaObserver* AlloyContentBrowserClient::GetMediaObserver() {
+ return CefMediaCaptureDevicesDispatcher::GetInstance();
+}
+
+content::SpeechRecognitionManagerDelegate*
+AlloyContentBrowserClient::CreateSpeechRecognitionManagerDelegate() {
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kEnableSpeechInput)) {
+ return new CefSpeechRecognitionManagerDelegate();
+ }
+
+ return nullptr;
+}
+
+content::GeneratedCodeCacheSettings
+AlloyContentBrowserClient::GetGeneratedCodeCacheSettings(
+ content::BrowserContext* context) {
+ // If we pass 0 for size, disk_cache will pick a default size using the
+ // heuristics based on available disk size. These are implemented in
+ // disk_cache::PreferredCacheSize in net/disk_cache/cache_util.cc.
+ const base::FilePath& cache_path = context->GetPath();
+ return content::GeneratedCodeCacheSettings(!cache_path.empty() /* enabled */,
+ 0 /* size */, cache_path);
+}
+
+void AlloyContentBrowserClient::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) {
+ auto returned_callback = certificate_query::AllowCertificateError(
+ web_contents, cert_error, ssl_info, request_url, is_main_frame_request,
+ strict_enforcement, std::move(callback), /*default_disallow=*/true);
+ // Callback should not be returned.
+ DCHECK(returned_callback.is_null());
+}
+
+base::OnceClosure AlloyContentBrowserClient::SelectClientCertificate(
+ content::WebContents* web_contents,
+ net::SSLCertRequestInfo* cert_request_info,
+ net::ClientCertIdentityList client_certs,
+ std::unique_ptr<content::ClientCertificateDelegate> delegate) {
+ CEF_REQUIRE_UIT();
+
+ CefRefPtr<CefRequestHandler> handler;
+ CefRefPtr<AlloyBrowserHostImpl> browser =
+ AlloyBrowserHostImpl::GetBrowserForContents(web_contents);
+ if (browser.get()) {
+ CefRefPtr<CefClient> client = browser->GetClient();
+ if (client.get()) {
+ handler = client->GetRequestHandler();
+ }
+ }
+
+ if (!handler.get()) {
+ delegate->ContinueWithCertificate(nullptr, nullptr);
+ return base::OnceClosure();
+ }
+
+ CefRequestHandler::X509CertificateList certs;
+ for (net::ClientCertIdentityList::iterator iter = client_certs.begin();
+ iter != client_certs.end(); iter++) {
+ certs.push_back(new CefX509CertificateImpl(std::move(*iter)));
+ }
+
+ CefRefPtr<CefSelectClientCertificateCallbackImpl> callbackImpl(
+ new CefSelectClientCertificateCallbackImpl(std::move(delegate)));
+
+ bool proceed = handler->OnSelectClientCertificate(
+ browser.get(), cert_request_info->is_proxy,
+ cert_request_info->host_and_port.host(),
+ cert_request_info->host_and_port.port(), certs, callbackImpl.get());
+
+ if (!proceed && !certs.empty()) {
+ callbackImpl->Select(certs[0]);
+ }
+ return base::OnceClosure();
+}
+
+bool AlloyContentBrowserClient::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) {
+ CEF_REQUIRE_UIT();
+ *no_javascript_access = false;
+
+ return CefBrowserInfoManager::GetInstance()->CanCreateWindow(
+ opener, target_url, referrer, frame_name, disposition, features,
+ user_gesture, opener_suppressed, no_javascript_access);
+}
+
+void AlloyContentBrowserClient::OverrideWebkitPrefs(
+ content::WebContents* web_contents,
+ blink::web_pref::WebPreferences* prefs) {
+ auto rvh = web_contents->GetRenderViewHost();
+
+ // Using RVH instead of RFH here because rvh->GetMainFrame() may be nullptr
+ // when this method is called.
+ SkColor base_background_color;
+ renderer_prefs::PopulateWebPreferences(rvh, *prefs, base_background_color);
+
+ web_contents->SetPageBaseBackgroundColor(base_background_color);
+}
+
+bool AlloyContentBrowserClient::OverrideWebPreferencesAfterNavigation(
+ content::WebContents* web_contents,
+ blink::web_pref::WebPreferences* prefs) {
+ return renderer_prefs::PopulateWebPreferencesAfterNavigation(web_contents,
+ *prefs);
+}
+
+void AlloyContentBrowserClient::BrowserURLHandlerCreated(
+ content::BrowserURLHandler* handler) {
+ scheme::BrowserURLHandlerCreated(handler);
+}
+
+std::string AlloyContentBrowserClient::GetDefaultDownloadName() {
+ return "download";
+}
+
+void AlloyContentBrowserClient::DidCreatePpapiPlugin(
+ content::BrowserPpapiHost* browser_host) {
+ browser_host->GetPpapiHost()->AddHostFactoryFilter(
+ std::unique_ptr<ppapi::host::HostFactory>(
+ new ChromeBrowserPepperHostFactory(browser_host)));
+}
+
+std::unique_ptr<content::DevToolsManagerDelegate>
+AlloyContentBrowserClient::CreateDevToolsManagerDelegate() {
+ return std::make_unique<CefDevToolsManagerDelegate>();
+}
+
+void AlloyContentBrowserClient::
+ RegisterAssociatedInterfaceBindersForRenderFrameHost(
+ content::RenderFrameHost& render_frame_host,
+ blink::AssociatedInterfaceRegistry& associated_registry) {
+ associated_registry.AddInterface<extensions::mojom::LocalFrameHost>(
+ base::BindRepeating(
+ [](content::RenderFrameHost* render_frame_host,
+ mojo::PendingAssociatedReceiver<extensions::mojom::LocalFrameHost>
+ receiver) {
+ extensions::ExtensionWebContentsObserver::BindLocalFrameHost(
+ std::move(receiver), render_frame_host);
+ },
+ &render_frame_host));
+
+ associated_registry.AddInterface<printing::mojom::PrintManagerHost>(
+ base::BindRepeating(
+ [](content::RenderFrameHost* render_frame_host,
+ mojo::PendingAssociatedReceiver<printing::mojom::PrintManagerHost>
+ receiver) {
+ printing::PrintViewManager::BindPrintManagerHost(
+ std::move(receiver), render_frame_host);
+ },
+ &render_frame_host));
+
+ associated_registry.AddInterface<pdf::mojom::PdfService>(base::BindRepeating(
+ [](content::RenderFrameHost* render_frame_host,
+ mojo::PendingAssociatedReceiver<pdf::mojom::PdfService> receiver) {
+ pdf::PDFWebContentsHelper::BindPdfService(std::move(receiver),
+ render_frame_host);
+ },
+ &render_frame_host));
+}
+
+std::vector<std::unique_ptr<content::NavigationThrottle>>
+AlloyContentBrowserClient::CreateThrottlesForNavigation(
+ content::NavigationHandle* navigation_handle) {
+ throttle::NavigationThrottleList throttles;
+
+ if (extensions::ExtensionsEnabled()) {
+ auto pdf_iframe_throttle =
+ PDFIFrameNavigationThrottle::MaybeCreateThrottleFor(navigation_handle);
+ if (pdf_iframe_throttle) {
+ throttles.push_back(std::move(pdf_iframe_throttle));
+ }
+
+ auto pdf_throttle = pdf::PdfNavigationThrottle::MaybeCreateThrottleFor(
+ navigation_handle, std::make_unique<ChromePdfStreamDelegate>());
+ if (pdf_throttle) {
+ throttles.push_back(std::move(pdf_throttle));
+ }
+ }
+
+ throttle::CreateThrottlesForNavigation(navigation_handle, throttles);
+
+ return throttles;
+}
+
+std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
+AlloyContentBrowserClient::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) {
+ std::vector<std::unique_ptr<blink::URLLoaderThrottle>> result;
+
+ // Used to substitute View ID for PDF contents when using the PDF plugin.
+ result.push_back(std::make_unique<PluginResponseInterceptorURLLoaderThrottle>(
+ request.destination, frame_tree_node_id));
+
+ Profile* profile = Profile::FromBrowserContext(browser_context);
+
+ chrome::mojom::DynamicParams dynamic_params = {
+ profile->GetPrefs()->GetBoolean(prefs::kForceGoogleSafeSearch),
+ profile->GetPrefs()->GetInteger(prefs::kForceYouTubeRestrict),
+ profile->GetPrefs()->GetString(prefs::kAllowedDomainsForApps)};
+ result.push_back(
+ std::make_unique<GoogleURLLoaderThrottle>(std::move(dynamic_params)));
+
+ return result;
+}
+
+std::vector<std::unique_ptr<content::URLLoaderRequestInterceptor>>
+AlloyContentBrowserClient::WillCreateURLLoaderRequestInterceptors(
+ content::NavigationUIData* navigation_ui_data,
+ int frame_tree_node_id) {
+ std::vector<std::unique_ptr<content::URLLoaderRequestInterceptor>>
+ interceptors;
+
+ if (extensions::ExtensionsEnabled()) {
+ auto pdf_interceptor =
+ pdf::PdfURLLoaderRequestInterceptor::MaybeCreateInterceptor(
+ frame_tree_node_id, std::make_unique<ChromePdfStreamDelegate>());
+ if (pdf_interceptor) {
+ interceptors.push_back(std::move(pdf_interceptor));
+ }
+ }
+
+ return interceptors;
+}
+
+#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
+void AlloyContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
+ const base::CommandLine& command_line,
+ int child_process_id,
+ content::PosixFileDescriptorInfo* mappings) {
+ int crash_signal_fd = GetCrashSignalFD();
+ if (crash_signal_fd >= 0) {
+ mappings->Share(kCrashDumpSignal, crash_signal_fd);
+ }
+}
+#endif // BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
+
+void AlloyContentBrowserClient::ExposeInterfacesToRenderer(
+ service_manager::BinderRegistry* registry,
+ blink::AssociatedInterfaceRegistry* associated_registry,
+ content::RenderProcessHost* host) {
+ associated_registry->AddInterface<chrome::mojom::PluginInfoHost>(
+ base::BindRepeating(&BindPluginInfoHost, host->GetID()));
+
+ if (extensions::ExtensionsEnabled()) {
+ associated_registry->AddInterface<extensions::mojom::EventRouter>(
+ base::BindRepeating(&extensions::EventRouter::BindForRenderer,
+ host->GetID()));
+ associated_registry->AddInterface<guest_view::mojom::GuestViewHost>(
+ base::BindRepeating(
+ &extensions::ExtensionsGuestView::CreateForComponents,
+ host->GetID()));
+ associated_registry->AddInterface<extensions::mojom::GuestView>(
+ base::BindRepeating(
+ &extensions::ExtensionsGuestView::CreateForExtensions,
+ host->GetID()));
+ associated_registry->AddInterface<extensions::mojom::RendererHost>(
+ base::BindRepeating(&extensions::RendererStartupHelper::BindForRenderer,
+ host->GetID()));
+ }
+
+ CefBrowserManager::ExposeInterfacesToRenderer(registry, associated_registry,
+ host);
+}
+
+std::unique_ptr<net::ClientCertStore>
+AlloyContentBrowserClient::CreateClientCertStore(
+ content::BrowserContext* browser_context) {
+ // Match the logic in ProfileNetworkContextService::CreateClientCertStore.
+#if BUILDFLAG(USE_NSS_CERTS)
+ // TODO: Add support for client implementation of crypto password dialog.
+ return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreNSS(
+ net::ClientCertStoreNSS::PasswordDelegateFactory()));
+#elif BUILDFLAG(IS_WIN)
+ return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreWin());
+#elif BUILDFLAG(IS_MAC)
+ return std::unique_ptr<net::ClientCertStore>(new net::ClientCertStoreMac());
+#else
+#error Unknown platform.
+#endif
+}
+
+std::unique_ptr<content::LoginDelegate>
+AlloyContentBrowserClient::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) {
+ return std::make_unique<net_service::LoginDelegate>(
+ auth_info, web_contents, request_id, url,
+ std::move(auth_required_callback));
+}
+
+void AlloyContentBrowserClient::RegisterNonNetworkNavigationURLLoaderFactories(
+ int frame_tree_node_id,
+ ukm::SourceIdObj ukm_source_id,
+ NonNetworkURLLoaderFactoryMap* factories) {
+ if (!extensions::ExtensionsEnabled()) {
+ return;
+ }
+
+ content::WebContents* web_contents =
+ content::WebContents::FromFrameTreeNodeId(frame_tree_node_id);
+ factories->emplace(
+ extensions::kExtensionScheme,
+ extensions::CreateExtensionNavigationURLLoaderFactory(
+ web_contents->GetBrowserContext(), ukm_source_id,
+ !!extensions::WebViewGuest::FromWebContents(web_contents)));
+}
+
+void AlloyContentBrowserClient::RegisterNonNetworkSubresourceURLLoaderFactories(
+ int render_process_id,
+ int render_frame_id,
+ const absl::optional<url::Origin>& request_initiator_origin,
+ NonNetworkURLLoaderFactoryMap* factories) {
+ if (!extensions::ExtensionsEnabled()) {
+ return;
+ }
+
+ auto factory = extensions::CreateExtensionURLLoaderFactory(render_process_id,
+ render_frame_id);
+ if (factory) {
+ factories->emplace(extensions::kExtensionScheme, std::move(factory));
+ }
+
+ content::RenderFrameHost* frame_host =
+ content::RenderFrameHost::FromID(render_process_id, render_frame_id);
+ content::WebContents* web_contents =
+ content::WebContents::FromRenderFrameHost(frame_host);
+ if (!web_contents) {
+ return;
+ }
+
+ extensions::CefExtensionWebContentsObserver* web_observer =
+ extensions::CefExtensionWebContentsObserver::FromWebContents(
+ web_contents);
+
+ // There is nothing to do if no CefExtensionWebContentsObserver is attached
+ // to the |web_contents|.
+ if (!web_observer) {
+ return;
+ }
+
+ const extensions::Extension* extension =
+ web_observer->GetExtensionFromFrame(frame_host, false);
+ if (!extension) {
+ return;
+ }
+
+ std::vector<std::string> allowed_webui_hosts;
+ // Support for chrome:// scheme if appropriate.
+ if ((extension->is_extension() || extension->is_platform_app()) &&
+ extensions::Manifest::IsComponentLocation(extension->location())) {
+ // Components of chrome that are implemented as extensions or platform apps
+ // are allowed to use chrome://resources/ and chrome://theme/ URLs.
+ // See also HasCrossOriginWhitelistEntry.
+ allowed_webui_hosts.emplace_back(content::kChromeUIResourcesHost);
+ allowed_webui_hosts.emplace_back(chrome::kChromeUIThemeHost);
+ }
+ if (!allowed_webui_hosts.empty()) {
+ factories->emplace(content::kChromeUIScheme,
+ content::CreateWebUIURLLoaderFactory(
+ frame_host, content::kChromeUIScheme,
+ std::move(allowed_webui_hosts)));
+ }
+}
+
+bool AlloyContentBrowserClient::WillCreateURLLoaderFactory(
+ content::BrowserContext* browser_context,
+ content::RenderFrameHost* frame,
+ int render_process_id,
+ URLLoaderFactoryType type,
+ const url::Origin& request_initiator,
+ absl::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) {
+ auto request_handler = net_service::CreateInterceptedRequestHandler(
+ browser_context, frame, render_process_id,
+ type == URLLoaderFactoryType::kNavigation,
+ type == URLLoaderFactoryType::kDownload, request_initiator);
+
+ net_service::ProxyURLLoaderFactory::CreateProxy(
+ browser_context, factory_receiver, header_client,
+ std::move(request_handler));
+ return true;
+}
+
+void AlloyContentBrowserClient::OnNetworkServiceCreated(
+ network::mojom::NetworkService* network_service) {
+ DCHECK(g_browser_process);
+ PrefService* local_state = g_browser_process->local_state();
+ DCHECK(local_state);
+
+ // Need to set up global NetworkService state before anything else uses it.
+ DCHECK(SystemNetworkContextManager::GetInstance());
+ SystemNetworkContextManager::GetInstance()->OnNetworkServiceCreated(
+ network_service);
+}
+
+bool AlloyContentBrowserClient::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) {
+ // This method may be called during shutdown when using multi-threaded
+ // message loop mode. In that case exit early to avoid crashes.
+ if (!SystemNetworkContextManager::GetInstance()) {
+ // Cancel NetworkContext creation in
+ // StoragePartitionImpl::InitNetworkContext.
+ return false;
+ }
+
+ auto cef_context = CefBrowserContext::FromBrowserContext(context);
+
+ Profile* profile = cef_context->AsProfile();
+ ProfileNetworkContextService* service =
+ ProfileNetworkContextServiceFactory::GetForContext(profile);
+ if (service) {
+ service->ConfigureNetworkContextParams(in_memory, relative_partition_path,
+ network_context_params,
+ cert_verifier_creation_params);
+ } else {
+ // Set default params.
+ network_context_params->user_agent = GetUserAgent();
+ network_context_params->accept_language = GetApplicationLocale();
+ }
+
+ network_context_params->cookieable_schemes =
+ cef_context->GetCookieableSchemes();
+
+ // TODO(cef): Remove this and add required NetworkIsolationKeys,
+ // this is currently not the case and this was not required pre M84.
+ network_context_params->require_network_isolation_key = false;
+
+ return true;
+}
+
+// The sandbox may block read/write access from the NetworkService to
+// directories that are not returned by this method.
+std::vector<base::FilePath>
+AlloyContentBrowserClient::GetNetworkContextsParentDirectory() {
+ base::FilePath user_data_path;
+ base::PathService::Get(chrome::DIR_USER_DATA, &user_data_path);
+ DCHECK(!user_data_path.empty());
+
+ const auto& root_cache_path = GetRootCachePath();
+
+ // root_cache_path may sometimes be empty or a child of user_data_path, so
+ // only return the one path in that case.
+ if (root_cache_path.empty() || user_data_path.IsParent(root_cache_path)) {
+ return {user_data_path};
+ }
+
+ return {user_data_path, root_cache_path};
+}
+
+bool AlloyContentBrowserClient::HandleExternalProtocol(
+ const GURL& url,
+ content::WebContents::Getter web_contents_getter,
+ int frame_tree_node_id,
+ content::NavigationUIData* navigation_data,
+ bool is_primary_main_frame,
+ bool is_in_fenced_frame_tree,
+ network::mojom::WebSandboxFlags sandbox_flags,
+ ui::PageTransition page_transition,
+ bool has_user_gesture,
+ const absl::optional<url::Origin>& initiating_origin,
+ content::RenderFrameHost* initiator_document,
+ mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory) {
+ // Call the other HandleExternalProtocol variant.
+ return false;
+}
+
+bool AlloyContentBrowserClient::HandleExternalProtocol(
+ content::WebContents::Getter web_contents_getter,
+ int frame_tree_node_id,
+ content::NavigationUIData* navigation_data,
+ bool is_primary_main_frame,
+ bool is_in_fenced_frame_tree,
+ network::mojom::WebSandboxFlags sandbox_flags,
+ const network::ResourceRequest& resource_request,
+ const absl::optional<url::Origin>& initiating_origin,
+ content::RenderFrameHost* initiator_document,
+ mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory) {
+ mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver =
+ out_factory->InitWithNewPipeAndPassReceiver();
+
+ // CefBrowserPlatformDelegate::HandleExternalProtocol may be called if
+ // nothing handles the request.
+ auto request_handler = net_service::CreateInterceptedRequestHandler(
+ web_contents_getter, frame_tree_node_id, resource_request,
+ base::BindRepeating(CefBrowserPlatformDelegate::HandleExternalProtocol,
+ resource_request.url));
+
+ net_service::ProxyURLLoaderFactory::CreateProxy(
+ web_contents_getter, std::move(receiver), std::move(request_handler));
+ return true;
+}
+
+std::unique_ptr<content::VideoOverlayWindow>
+AlloyContentBrowserClient::CreateWindowForVideoPictureInPicture(
+ content::VideoPictureInPictureWindowController* controller) {
+ // Note: content::VideoOverlayWindow::Create() is defined by platform-specific
+ // implementation in chrome/browser/ui/views. This layering hack, which goes
+ // through //content and ContentBrowserClient, allows us to work around the
+ // dependency constraints that disallow directly calling
+ // chrome/browser/ui/views code either from here or from other code in
+ // chrome/browser.
+ return content::VideoOverlayWindow::Create(controller);
+}
+
+void AlloyContentBrowserClient::RegisterBrowserInterfaceBindersForFrame(
+ content::RenderFrameHost* render_frame_host,
+ mojo::BinderMapWithContext<content::RenderFrameHost*>* map) {
+ CefBrowserFrame::RegisterBrowserInterfaceBindersForFrame(render_frame_host,
+ map);
+
+ map->Add<blink::mojom::BadgeService>(base::BindRepeating(&BindBadgeService));
+ map->Add<media::mojom::MediaFoundationRendererNotifier>(
+ base::BindRepeating(&BindMediaFoundationRendererNotifierHandler));
+ map->Add<network_hints::mojom::NetworkHintsHandler>(
+ base::BindRepeating(&BindNetworkHintsHandler));
+
+ if (!extensions::ExtensionsEnabled()) {
+ return;
+ }
+
+ content::WebContents* web_contents =
+ content::WebContents::FromRenderFrameHost(render_frame_host);
+ if (!web_contents) {
+ return;
+ }
+
+ const GURL& site = render_frame_host->GetSiteInstance()->GetSiteURL();
+ if (!site.SchemeIs(extensions::kExtensionScheme)) {
+ return;
+ }
+
+ content::BrowserContext* browser_context =
+ render_frame_host->GetProcess()->GetBrowserContext();
+ auto* extension = extensions::ExtensionRegistry::Get(browser_context)
+ ->enabled_extensions()
+ .GetByID(site.host());
+ if (!extension) {
+ return;
+ }
+ extensions::ExtensionsBrowserClient::Get()
+ ->RegisterBrowserInterfaceBindersForFrame(map, render_frame_host,
+ extension);
+}
+
+void AlloyContentBrowserClient::RegisterBrowserInterfaceBindersForServiceWorker(
+ content::BrowserContext* browser_context,
+ const content::ServiceWorkerVersionBaseInfo& service_worker_version_info,
+ mojo::BinderMapWithContext<const content::ServiceWorkerVersionBaseInfo&>*
+ map) {
+ map->Add<blink::mojom::BadgeService>(
+ base::BindRepeating(&BindBadgeServiceForServiceWorker));
+}
+
+base::FilePath
+AlloyContentBrowserClient::GetSandboxedStorageServiceDataDirectory() {
+ return GetRootCachePath();
+}
+
+std::string AlloyContentBrowserClient::GetProduct() {
+ return GetChromeProduct();
+}
+
+std::string AlloyContentBrowserClient::GetChromeProduct() {
+ return version_info::GetProductNameAndVersionForUserAgent();
+}
+
+std::string AlloyContentBrowserClient::GetUserAgent() {
+ return embedder_support::GetUserAgent();
+}
+
+std::string AlloyContentBrowserClient::GetFullUserAgent() {
+ return embedder_support::GetFullUserAgent();
+}
+
+std::string AlloyContentBrowserClient::GetReducedUserAgent() {
+ return embedder_support::GetReducedUserAgent();
+}
+
+std::unique_ptr<content::WebContentsViewDelegate>
+AlloyContentBrowserClient::GetWebContentsViewDelegate(
+ content::WebContents* web_contents) {
+ return std::make_unique<AlloyWebContentsViewDelegate>(web_contents);
+}
+
+blink::UserAgentMetadata AlloyContentBrowserClient::GetUserAgentMetadata() {
+ blink::UserAgentMetadata metadata;
+
+ metadata.brand_version_list = {blink::UserAgentBrandVersion{
+ version_info::GetProductName(), version_info::GetMajorVersionNumber()}};
+ metadata.full_version = version_info::GetVersionNumber();
+ metadata.platform = version_info::GetOSType();
+
+ // TODO(mkwst): Poke at BuildUserAgentFromProduct to split out these pieces.
+ metadata.architecture = "";
+ metadata.model = "";
+
+ return metadata;
+}
+
+base::flat_set<std::string>
+AlloyContentBrowserClient::GetPluginMimeTypesWithExternalHandlers(
+ content::BrowserContext* browser_context) {
+ base::flat_set<std::string> mime_types;
+ auto map = PluginUtils::GetMimeTypeToExtensionIdMap(browser_context);
+ for (const auto& pair : map) {
+ mime_types.insert(pair.first);
+ }
+ mime_types.insert(pdf::kInternalPluginMimeType);
+ return mime_types;
+}
+
+bool AlloyContentBrowserClient::ArePersistentMediaDeviceIDsAllowed(
+ content::BrowserContext* browser_context,
+ const GURL& url,
+ const net::SiteForCookies& site_for_cookies,
+ const absl::optional<url::Origin>& top_frame_origin) {
+ // Persistent MediaDevice IDs are allowed if cookies are allowed.
+ return CookieSettingsFactory::GetForProfile(
+ Profile::FromBrowserContext(browser_context))
+ ->IsFullCookieAccessAllowed(
+ url, site_for_cookies, top_frame_origin,
+ net::CookieSettingOverrides(),
+ content_settings::CookieSettings::QueryReason::kSiteStorage);
+}
+
+void AlloyContentBrowserClient::OnWebContentsCreated(
+ content::WebContents* web_contents) {
+ // Attach universal WebContentsObservers. These are quite rare, and in most
+ // cases CefBrowserPlatformDelegateAlloy::BrowserCreated and/or
+ // CefExtensionsAPIClient::AttachWebContentsHelpers should be used instead.
+
+ if (extensions::ExtensionsEnabled()) {
+ extensions::CefExtensionWebContentsObserver::CreateForWebContents(
+ web_contents);
+ }
+}
+
+bool AlloyContentBrowserClient::IsFindInPageDisabledForOrigin(
+ const url::Origin& origin) {
+ // For PDF viewing with the PPAPI-free PDF Viewer, find-in-page should only
+ // display results from the PDF content, and not from the UI.
+ return IsPdfExtensionOrigin(origin);
+}
+
+CefRefPtr<CefRequestContextImpl> AlloyContentBrowserClient::request_context()
+ const {
+ return browser_main_parts_->request_context();
+}
+
+CefDevToolsDelegate* AlloyContentBrowserClient::devtools_delegate() const {
+ return browser_main_parts_->devtools_delegate();
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+AlloyContentBrowserClient::background_task_runner() const {
+ return browser_main_parts_->background_task_runner();
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+AlloyContentBrowserClient::user_visible_task_runner() const {
+ return browser_main_parts_->user_visible_task_runner();
+}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+AlloyContentBrowserClient::user_blocking_task_runner() const {
+ return browser_main_parts_->user_blocking_task_runner();
+}
+
+const extensions::Extension* AlloyContentBrowserClient::GetExtension(
+ content::SiteInstance* site_instance) {
+ extensions::ExtensionRegistry* registry =
+ extensions::ExtensionRegistry::Get(site_instance->GetBrowserContext());
+ if (!registry) {
+ return nullptr;
+ }
+ return registry->enabled_extensions().GetExtensionOrAppByURL(
+ site_instance->GetSiteURL());
+}