| // Copyright 2019 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 "weblayer/browser/content_browser_client_impl.h" |
| |
| #include <memory> |
| #include <utility> |
| |
| #include "base/command_line.h" |
| #include "base/containers/flat_set.h" |
| #include "base/files/file.h" |
| #include "base/files/file_util.h" |
| #include "base/path_service.h" |
| #include "base/strings/string_piece.h" |
| #include "base/threading/thread_restrictions.h" |
| #include "base/time/time.h" |
| #include "build/build_config.h" |
| #include "build/chromeos_buildflags.h" |
| #include "components/autofill/content/browser/content_autofill_driver_factory.h" |
| #include "components/blocked_content/popup_blocker.h" |
| #include "components/captive_portal/core/buildflags.h" |
| #include "components/content_capture/browser/onscreen_content_provider.h" |
| #include "components/content_settings/core/browser/cookie_settings.h" |
| #include "components/embedder_support/content_settings_utils.h" |
| #include "components/embedder_support/switches.h" |
| #include "components/embedder_support/user_agent_utils.h" |
| #include "components/error_page/common/error.h" |
| #include "components/error_page/common/localized_error.h" |
| #include "components/error_page/content/browser/net_error_auto_reloader.h" |
| #include "components/metrics/metrics_service.h" |
| #include "components/network_time/network_time_tracker.h" |
| #include "components/no_state_prefetch/browser/no_state_prefetch_manager.h" |
| #include "components/no_state_prefetch/common/prerender_url_loader_throttle.h" |
| #include "components/page_load_metrics/browser/metrics_navigation_throttle.h" |
| #include "components/page_load_metrics/browser/metrics_web_contents_observer.h" |
| #include "components/performance_manager/embedder/performance_manager_registry.h" |
| #include "components/permissions/quota_permission_context_impl.h" |
| #include "components/prefs/json_pref_store.h" |
| #include "components/prefs/pref_registry_simple.h" |
| #include "components/prefs/pref_service_factory.h" |
| #include "components/prefs/scoped_user_pref_update.h" |
| #include "components/security_interstitials/content/insecure_form_navigation_throttle.h" |
| #include "components/security_interstitials/content/security_interstitial_tab_helper.h" |
| #include "components/security_interstitials/content/ssl_cert_reporter.h" |
| #include "components/security_interstitials/content/ssl_error_handler.h" |
| #include "components/security_interstitials/content/ssl_error_navigation_throttle.h" |
| #include "components/site_isolation/pref_names.h" |
| #include "components/site_isolation/preloaded_isolated_origins.h" |
| #include "components/site_isolation/site_isolation_policy.h" |
| #include "components/strings/grit/components_locale_settings.h" |
| #include "components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h" |
| #include "components/subresource_filter/content/browser/ruleset_version.h" |
| #include "components/user_prefs/user_prefs.h" |
| #include "components/variations/service/variations_service.h" |
| #include "components/version_info/version_info.h" |
| #include "content/public/browser/browser_context.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/client_certificate_delegate.h" |
| #include "content/public/browser/devtools_manager_delegate.h" |
| #include "content/public/browser/generated_code_cache_settings.h" |
| #include "content/public/browser/navigation_handle.h" |
| #include "content/public/browser/navigation_throttle.h" |
| #include "content/public/browser/network_service_instance.h" |
| #include "content/public/browser/page_navigator.h" |
| #include "content/public/browser/permission_controller.h" |
| #include "content/public/browser/render_process_host.h" |
| #include "content/public/common/content_features.h" |
| #include "content/public/common/content_switches.h" |
| #include "content/public/common/url_constants.h" |
| #include "content/public/common/window_container_type.mojom.h" |
| #include "mojo/public/cpp/bindings/binder_map.h" |
| #include "net/cert/x509_certificate.h" |
| #include "net/cookies/site_for_cookies.h" |
| #include "net/proxy_resolution/proxy_config.h" |
| #include "net/ssl/client_cert_identity.h" |
| #include "net/ssl/ssl_private_key.h" |
| #include "net/traffic_annotation/network_traffic_annotation.h" |
| #include "services/network/network_service.h" |
| #include "services/network/public/mojom/network_context.mojom.h" |
| #include "services/network/public/mojom/network_service.mojom.h" |
| #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" |
| #include "third_party/blink/public/common/loader/url_loader_throttle.h" |
| #include "third_party/blink/public/common/permissions/permission_utils.h" |
| #include "third_party/blink/public/common/user_agent/user_agent_metadata.h" |
| #include "third_party/blink/public/common/web_preferences/web_preferences.h" |
| #include "ui/base/l10n/l10n_util.h" |
| #include "ui/base/page_transition_types.h" |
| #include "url/gurl.h" |
| #include "url/origin.h" |
| #include "url/url_constants.h" |
| #include "weblayer/browser/browser_main_parts_impl.h" |
| #include "weblayer/browser/browser_process.h" |
| #include "weblayer/browser/cookie_settings_factory.h" |
| #include "weblayer/browser/download_manager_delegate_impl.h" |
| #include "weblayer/browser/feature_list_creator.h" |
| #include "weblayer/browser/host_content_settings_map_factory.h" |
| #include "weblayer/browser/i18n_util.h" |
| #include "weblayer/browser/navigation_controller_impl.h" |
| #include "weblayer/browser/navigation_error_navigation_throttle.h" |
| #include "weblayer/browser/navigation_ui_data_impl.h" |
| #include "weblayer/browser/no_state_prefetch/no_state_prefetch_manager_factory.h" |
| #include "weblayer/browser/no_state_prefetch/no_state_prefetch_utils.h" |
| #include "weblayer/browser/page_specific_content_settings_delegate.h" |
| #include "weblayer/browser/password_manager_driver_factory.h" |
| #include "weblayer/browser/popup_navigation_delegate_impl.h" |
| #include "weblayer/browser/profile_impl.h" |
| #include "weblayer/browser/signin_url_loader_throttle.h" |
| #include "weblayer/browser/system_network_context_manager.h" |
| #include "weblayer/browser/tab_impl.h" |
| #include "weblayer/browser/web_contents_view_delegate_impl.h" |
| #include "weblayer/browser/weblayer_browser_interface_binders.h" |
| #include "weblayer/browser/weblayer_security_blocking_page_factory.h" |
| #include "weblayer/browser/weblayer_speech_recognition_manager_delegate.h" |
| #include "weblayer/common/features.h" |
| #include "weblayer/common/weblayer_paths.h" |
| #include "weblayer/public/fullscreen_delegate.h" |
| #include "weblayer/public/main.h" |
| |
| #if BUILDFLAG(IS_ANDROID) |
| #include "base/android/bundle_utils.h" |
| #include "base/android/jni_android.h" |
| #include "base/android/jni_string.h" |
| #include "base/android/path_utils.h" |
| #include "base/bind.h" |
| #include "components/browser_ui/client_certificate/android/ssl_client_certificate_request.h" |
| #include "components/cdm/browser/cdm_message_filter_android.h" |
| #include "components/cdm/browser/media_drm_storage_impl.h" // nogncheck |
| #include "components/crash/content/browser/crash_handler_host_linux.h" |
| #include "components/embedder_support/android/metrics/android_metrics_service_client.h" |
| #include "components/media_router/browser/presentation/presentation_service_delegate_impl.h" // nogncheck |
| #include "components/navigation_interception/intercept_navigation_delegate.h" |
| #include "components/permissions/bluetooth_delegate_impl.h" |
| #include "components/safe_browsing/core/browser/realtime/policy_engine.h" // nogncheck |
| #include "components/safe_browsing/core/browser/realtime/url_lookup_service.h" // nogncheck |
| #include "components/safe_browsing/core/common/safe_browsing_prefs.h" |
| #include "components/spellcheck/browser/spell_check_host_impl.h" // nogncheck |
| #include "content/public/browser/browser_task_traits.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "mojo/public/cpp/bindings/self_owned_receiver.h" |
| #include "ui/base/resource/resource_bundle_android.h" |
| #include "weblayer/browser/android/metrics/weblayer_metrics_service_client.h" |
| #include "weblayer/browser/android_descriptors.h" |
| #include "weblayer/browser/bluetooth/weblayer_bluetooth_delegate_impl_client.h" |
| #include "weblayer/browser/browser_context_impl.h" |
| #include "weblayer/browser/devtools_manager_delegate_android.h" |
| #include "weblayer/browser/http_auth_handler_impl.h" |
| #include "weblayer/browser/media/media_router_factory.h" |
| #include "weblayer/browser/proxying_url_loader_factory_impl.h" |
| #include "weblayer/browser/safe_browsing/real_time_url_lookup_service_factory.h" |
| #include "weblayer/browser/safe_browsing/safe_browsing_service.h" |
| #include "weblayer/browser/tts_environment_android_impl.h" |
| #include "weblayer/browser/weblayer_factory_impl_android.h" |
| #endif |
| |
| // TODO(crbug.com/1052397): Revisit once build flag switch of lacros-chrome is |
| // complete. |
| #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) || \ |
| BUILDFLAG(IS_ANDROID) |
| #include "content/public/common/content_descriptors.h" |
| #endif |
| |
| #if BUILDFLAG(IS_WIN) |
| #include "sandbox/policy/win/sandbox_win.h" |
| #include "sandbox/win/src/sandbox.h" |
| #endif |
| |
| #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) |
| #include "weblayer/browser/captive_portal_service_factory.h" |
| #endif |
| |
| #if BUILDFLAG(ENABLE_ARCORE) |
| #include "weblayer/browser/xr/xr_integration_client_impl.h" |
| #endif // BUILDFLAG(ENABLE_ARCORE) |
| |
| namespace switches { |
| // Specifies a list of hosts for whom we bypass proxy settings and use direct |
| // connections. Ignored if --proxy-auto-detect or --no-proxy-server are also |
| // specified. This is a comma-separated list of bypass rules. See: |
| // "net/proxy_resolution/proxy_bypass_rules.h" for the format of these rules. |
| // TODO(alexclarke): Find a better place for this. |
| const char kProxyBypassList[] = "proxy-bypass-list"; |
| } // namespace switches |
| |
| namespace weblayer { |
| |
| namespace { |
| |
| bool IsSafebrowsingSupported() { |
| // TODO(timvolodine): consider the non-android case, see crbug.com/1015809. |
| // TODO(timvolodine): consider refactoring this out into safe_browsing/. |
| #if BUILDFLAG(IS_ANDROID) |
| return true; |
| #else |
| return false; |
| #endif |
| } |
| |
| bool IsNetworkErrorAutoReloadEnabled() { |
| const base::CommandLine& command_line = |
| *base::CommandLine::ForCurrentProcess(); |
| if (command_line.HasSwitch(embedder_support::kEnableAutoReload)) |
| return true; |
| if (command_line.HasSwitch(embedder_support::kDisableAutoReload)) |
| return false; |
| return true; |
| } |
| |
| bool IsInHostedApp(content::WebContents* web_contents) { |
| return false; |
| } |
| |
| bool ShouldIgnoreInterstitialBecauseNavigationDefaultedToHttps( |
| content::NavigationHandle* handle) { |
| return false; |
| } |
| |
| class SSLCertReporterImpl : public SSLCertReporter { |
| public: |
| void ReportInvalidCertificateChain( |
| const std::string& serialized_report) override {} |
| }; |
| |
| // Wrapper for SSLErrorHandler::HandleSSLError() that supplies //weblayer-level |
| // parameters. |
| void HandleSSLErrorWrapper( |
| content::WebContents* web_contents, |
| int cert_error, |
| const net::SSLInfo& ssl_info, |
| const GURL& request_url, |
| std::unique_ptr<SSLCertReporter> ssl_cert_reporter, |
| SSLErrorHandler::BlockingPageReadyCallback blocking_page_ready_callback) { |
| captive_portal::CaptivePortalService* captive_portal_service = nullptr; |
| |
| #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION) |
| captive_portal_service = CaptivePortalServiceFactory::GetForBrowserContext( |
| web_contents->GetBrowserContext()); |
| #endif |
| |
| SSLErrorHandler::HandleSSLError( |
| web_contents, cert_error, ssl_info, request_url, |
| std::move(ssl_cert_reporter), std::move(blocking_page_ready_callback), |
| BrowserProcess::GetInstance()->GetNetworkTimeTracker(), |
| captive_portal_service, |
| std::make_unique<WebLayerSecurityBlockingPageFactory>()); |
| } |
| |
| #if BUILDFLAG(IS_ANDROID) |
| void CreateOriginId(cdm::MediaDrmStorageImpl::OriginIdObtainedCB callback) { |
| std::move(callback).Run(true, base::UnguessableToken::Create()); |
| } |
| |
| void AllowEmptyOriginIdCB(base::OnceCallback<void(bool)> callback) { |
| // Since CreateOriginId() always returns a non-empty origin ID, we don't need |
| // to allow empty origin ID. |
| std::move(callback).Run(false); |
| } |
| |
| void CreateMediaDrmStorage( |
| content::RenderFrameHost* render_frame_host, |
| mojo::PendingReceiver<::media::mojom::MediaDrmStorage> receiver) { |
| DCHECK(render_frame_host); |
| |
| if (render_frame_host->GetLastCommittedOrigin().opaque()) { |
| DVLOG(1) << __func__ << ": Unique origin."; |
| return; |
| } |
| |
| // The object will be deleted on connection error, or when the frame navigates |
| // away. |
| new cdm::MediaDrmStorageImpl( |
| render_frame_host, base::BindRepeating(&CreateOriginId), |
| base::BindRepeating(&AllowEmptyOriginIdCB), std::move(receiver)); |
| } |
| #endif // BUILDFLAG(IS_ANDROID) |
| |
| void RegisterPrefs(PrefRegistrySimple* pref_registry) { |
| network_time::NetworkTimeTracker::RegisterPrefs(pref_registry); |
| pref_registry->RegisterIntegerPref(kDownloadNextIDPref, 0); |
| #if BUILDFLAG(IS_ANDROID) |
| metrics::AndroidMetricsServiceClient::RegisterPrefs(pref_registry); |
| safe_browsing::RegisterLocalStatePrefs(pref_registry); |
| #else |
| // Call MetricsService::RegisterPrefs() as VariationsService::RegisterPrefs() |
| // CHECKs that kVariationsCrashStreak has already been registered. |
| // |
| // Note that the above call to AndroidMetricsServiceClient::RegisterPrefs() |
| // implicitly calls MetricsService::RegisterPrefs(), so the below call is |
| // necessary only on non-Android platforms. |
| metrics::MetricsService::RegisterPrefs(pref_registry); |
| #endif |
| variations::VariationsService::RegisterPrefs(pref_registry); |
| subresource_filter::IndexedRulesetVersion::RegisterPrefs(pref_registry); |
| } |
| |
| mojo::PendingRemote<prerender::mojom::PrerenderCanceler> GetPrerenderCanceler( |
| content::WebContents* web_contents) { |
| mojo::PendingRemote<prerender::mojom::PrerenderCanceler> canceler; |
| weblayer::NoStatePrefetchContentsFromWebContents(web_contents) |
| ->AddPrerenderCancelerReceiver(canceler.InitWithNewPipeAndPassReceiver()); |
| return canceler; |
| } |
| |
| } // namespace |
| |
| ContentBrowserClientImpl::ContentBrowserClientImpl(MainParams* params) |
| : params_(params) { |
| } |
| |
| ContentBrowserClientImpl::~ContentBrowserClientImpl() = default; |
| |
| std::unique_ptr<content::BrowserMainParts> |
| ContentBrowserClientImpl::CreateBrowserMainParts( |
| bool /* is_integration_test */) { |
| // This should be called after CreateFeatureListAndFieldTrials(), which |
| // creates |local_state_|. |
| DCHECK(local_state_); |
| std::unique_ptr<BrowserMainPartsImpl> browser_main_parts = |
| std::make_unique<BrowserMainPartsImpl>(params_, std::move(local_state_)); |
| |
| return browser_main_parts; |
| } |
| |
| std::string ContentBrowserClientImpl::GetApplicationLocale() { |
| return i18n::GetApplicationLocale(); |
| } |
| |
| std::string ContentBrowserClientImpl::GetAcceptLangs( |
| content::BrowserContext* context) { |
| return i18n::GetAcceptLangs(); |
| } |
| |
| content::AllowServiceWorkerResult ContentBrowserClientImpl::AllowServiceWorker( |
| const GURL& scope, |
| const net::SiteForCookies& site_for_cookies, |
| const absl::optional<url::Origin>& top_frame_origin, |
| const GURL& script_url, |
| content::BrowserContext* context) { |
| return embedder_support::AllowServiceWorker( |
| scope, site_for_cookies, top_frame_origin, |
| CookieSettingsFactory::GetForBrowserContext(context).get(), |
| HostContentSettingsMapFactory::GetForBrowserContext(context)); |
| } |
| |
| bool ContentBrowserClientImpl::AllowSharedWorker( |
| const GURL& worker_url, |
| const net::SiteForCookies& site_for_cookies, |
| const absl::optional<url::Origin>& top_frame_origin, |
| const std::string& name, |
| const blink::StorageKey& storage_key, |
| content::BrowserContext* context, |
| int render_process_id, |
| int render_frame_id) { |
| return embedder_support::AllowSharedWorker( |
| worker_url, site_for_cookies, top_frame_origin, name, storage_key, |
| render_process_id, render_frame_id, |
| CookieSettingsFactory::GetForBrowserContext(context).get()); |
| } |
| |
| void ContentBrowserClientImpl::AllowWorkerFileSystem( |
| const GURL& url, |
| content::BrowserContext* browser_context, |
| const std::vector<content::GlobalRenderFrameHostId>& render_frames, |
| base::OnceCallback<void(bool)> callback) { |
| std::move(callback).Run(embedder_support::AllowWorkerFileSystem( |
| url, render_frames, |
| CookieSettingsFactory::GetForBrowserContext(browser_context).get())); |
| } |
| |
| bool ContentBrowserClientImpl::AllowWorkerIndexedDB( |
| const GURL& url, |
| content::BrowserContext* browser_context, |
| const std::vector<content::GlobalRenderFrameHostId>& render_frames) { |
| return embedder_support::AllowWorkerIndexedDB( |
| url, render_frames, |
| CookieSettingsFactory::GetForBrowserContext(browser_context).get()); |
| } |
| |
| bool ContentBrowserClientImpl::AllowWorkerCacheStorage( |
| const GURL& url, |
| content::BrowserContext* browser_context, |
| const std::vector<content::GlobalRenderFrameHostId>& render_frames) { |
| return embedder_support::AllowWorkerCacheStorage( |
| url, render_frames, |
| CookieSettingsFactory::GetForBrowserContext(browser_context).get()); |
| } |
| |
| bool ContentBrowserClientImpl::AllowWorkerWebLocks( |
| const GURL& url, |
| content::BrowserContext* browser_context, |
| const std::vector<content::GlobalRenderFrameHostId>& render_frames) { |
| return embedder_support::AllowWorkerWebLocks( |
| url, CookieSettingsFactory::GetForBrowserContext(browser_context).get()); |
| } |
| |
| std::unique_ptr<content::WebContentsViewDelegate> |
| ContentBrowserClientImpl::GetWebContentsViewDelegate( |
| content::WebContents* web_contents) { |
| performance_manager::PerformanceManagerRegistry::GetInstance() |
| ->MaybeCreatePageNodeForWebContents(web_contents); |
| return std::make_unique<WebContentsViewDelegateImpl>(web_contents); |
| } |
| |
| bool ContentBrowserClientImpl::CanShutdownGpuProcessNowOnIOThread() { |
| return true; |
| } |
| |
| std::unique_ptr<content::DevToolsManagerDelegate> |
| ContentBrowserClientImpl::CreateDevToolsManagerDelegate() { |
| #if BUILDFLAG(IS_ANDROID) |
| return std::make_unique<DevToolsManagerDelegateAndroid>(); |
| #else |
| return std::make_unique<content::DevToolsManagerDelegate>(); |
| #endif |
| } |
| |
| void ContentBrowserClientImpl::LogWebFeatureForCurrentPage( |
| content::RenderFrameHost* render_frame_host, |
| blink::mojom::WebFeature feature) { |
| page_load_metrics::MetricsWebContentsObserver::RecordFeatureUsage( |
| render_frame_host, feature); |
| } |
| |
| std::string ContentBrowserClientImpl::GetProduct() { |
| return version_info::GetProductNameAndVersionForUserAgent(); |
| } |
| |
| std::string ContentBrowserClientImpl::GetUserAgent() { |
| return embedder_support::GetUserAgent(); |
| } |
| |
| std::string ContentBrowserClientImpl::GetFullUserAgent() { |
| return embedder_support::GetFullUserAgent(); |
| } |
| |
| std::string ContentBrowserClientImpl::GetReducedUserAgent() { |
| return embedder_support::GetReducedUserAgent(); |
| } |
| |
| blink::UserAgentMetadata ContentBrowserClientImpl::GetUserAgentMetadata() { |
| return embedder_support::GetUserAgentMetadata(); |
| } |
| |
| void ContentBrowserClientImpl::OverrideWebkitPrefs( |
| content::WebContents* web_contents, |
| blink::web_pref::WebPreferences* prefs) { |
| prefs->default_encoding = l10n_util::GetStringUTF8(IDS_DEFAULT_ENCODING); |
| |
| TabImpl* tab = TabImpl::FromWebContents(web_contents); |
| if (tab) |
| tab->SetWebPreferences(prefs); |
| } |
| |
| void ContentBrowserClientImpl::ConfigureNetworkContextParams( |
| content::BrowserContext* context, |
| bool in_memory, |
| const base::FilePath& relative_partition_path, |
| network::mojom::NetworkContextParams* context_params, |
| cert_verifier::mojom::CertVerifierCreationParams* |
| cert_verifier_creation_params) { |
| SystemNetworkContextManager::ConfigureDefaultNetworkContextParams( |
| context_params, GetUserAgent()); |
| // Headers coming from the embedder are implicitly trusted and should not |
| // trigger CORS checks. |
| context_params->allow_any_cors_exempt_header_for_browser = true; |
| context_params->accept_language = GetAcceptLangs(context); |
| if (!context->IsOffTheRecord()) { |
| context_params->file_paths = network::mojom::NetworkContextFilePaths::New(); |
| context_params->file_paths->data_directory = context->GetPath(); |
| context_params->file_paths->cookie_database_name = |
| base::FilePath(FILE_PATH_LITERAL("Cookies")); |
| context_params->http_cache_directory = |
| ProfileImpl::GetCachePath(context).Append(FILE_PATH_LITERAL("Cache")); |
| } |
| base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| if (command_line->HasSwitch(::switches::kProxyServer)) { |
| std::string proxy_server = |
| command_line->GetSwitchValueASCII(::switches::kProxyServer); |
| net::ProxyConfig proxy_config; |
| proxy_config.proxy_rules().ParseFromString(proxy_server); |
| if (command_line->HasSwitch(::switches::kProxyBypassList)) { |
| std::string bypass_list = |
| command_line->GetSwitchValueASCII(::switches::kProxyBypassList); |
| proxy_config.proxy_rules().bypass_rules.ParseFromString(bypass_list); |
| } |
| context_params->initial_proxy_config = net::ProxyConfigWithAnnotation( |
| proxy_config, |
| net::DefineNetworkTrafficAnnotation("undefined", "Nothing here yet.")); |
| } |
| if (command_line->HasSwitch(embedder_support::kShortReportingDelay)) { |
| context_params->reporting_delivery_interval = base::Milliseconds(100); |
| } |
| } |
| |
| void ContentBrowserClientImpl::OnNetworkServiceCreated( |
| network::mojom::NetworkService* network_service) { |
| if (!SystemNetworkContextManager::HasInstance()) |
| SystemNetworkContextManager::CreateInstance( |
| embedder_support::GetUserAgent()); |
| SystemNetworkContextManager::GetInstance()->OnNetworkServiceCreated( |
| network_service); |
| } |
| |
| std::vector<std::unique_ptr<blink::URLLoaderThrottle>> |
| ContentBrowserClientImpl::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; |
| |
| if (base::FeatureList::IsEnabled(features::kWebLayerSafeBrowsing) && |
| IsSafebrowsingSupported()) { |
| #if BUILDFLAG(IS_ANDROID) |
| BrowserContextImpl* browser_context_impl = |
| static_cast<BrowserContextImpl*>(browser_context); |
| bool is_safe_browsing_enabled = safe_browsing::IsSafeBrowsingEnabled( |
| *browser_context_impl->pref_service()); |
| |
| if (is_safe_browsing_enabled) { |
| bool is_real_time_lookup_enabled = |
| safe_browsing::RealTimePolicyEngine::CanPerformFullURLLookup( |
| browser_context_impl->pref_service(), |
| browser_context_impl->IsOffTheRecord(), |
| FeatureListCreator::GetInstance()->variations_service()); |
| |
| // |url_lookup_service| is used when real time url check is enabled. |
| safe_browsing::RealTimeUrlLookupServiceBase* url_lookup_service = |
| is_real_time_lookup_enabled |
| ? RealTimeUrlLookupServiceFactory::GetForBrowserContext( |
| browser_context) |
| : nullptr; |
| result.push_back(GetSafeBrowsingService()->CreateURLLoaderThrottle( |
| wc_getter, frame_tree_node_id, url_lookup_service)); |
| } |
| #endif |
| } |
| |
| auto signin_throttle = |
| SigninURLLoaderThrottle::Create(browser_context, wc_getter); |
| if (signin_throttle) |
| result.push_back(std::move(signin_throttle)); |
| |
| // Create prerender URL throttle. |
| auto* web_contents = wc_getter.Run(); |
| auto* no_state_prefetch_contents = |
| NoStatePrefetchContentsFromWebContents(web_contents); |
| if (no_state_prefetch_contents) { |
| result.push_back(std::make_unique<prerender::PrerenderURLLoaderThrottle>( |
| prerender::PrerenderHistograms::GetHistogramPrefix( |
| no_state_prefetch_contents->origin()), |
| GetPrerenderCanceler(web_contents))); |
| } |
| |
| return result; |
| } |
| |
| bool ContentBrowserClientImpl::IsHandledURL(const GURL& url) { |
| if (!url.is_valid()) { |
| // WebLayer handles error cases. |
| return true; |
| } |
| |
| std::string scheme = url.scheme(); |
| |
| DCHECK_EQ(scheme, base::ToLowerASCII(scheme)); |
| static const char* const kProtocolList[] = { |
| url::kHttpScheme, |
| url::kHttpsScheme, |
| #if BUILDFLAG(ENABLE_WEBSOCKETS) |
| url::kWsScheme, |
| url::kWssScheme, |
| #endif // BUILDFLAG(ENABLE_WEBSOCKETS) |
| url::kFileScheme, |
| content::kChromeDevToolsScheme, |
| content::kChromeUIScheme, |
| content::kChromeUIUntrustedScheme, |
| url::kDataScheme, |
| #if BUILDFLAG(IS_ANDROID) |
| url::kContentScheme, |
| #endif // BUILDFLAG(IS_ANDROID) |
| url::kAboutScheme, |
| url::kBlobScheme, |
| url::kFileSystemScheme, |
| }; |
| for (const char* supported_protocol : kProtocolList) { |
| if (scheme == supported_protocol) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| std::vector<url::Origin> |
| ContentBrowserClientImpl::GetOriginsRequiringDedicatedProcess() { |
| return site_isolation::GetBrowserSpecificBuiltInIsolatedOrigins(); |
| } |
| |
| bool ContentBrowserClientImpl::MayReuseHost( |
| content::RenderProcessHost* process_host) { |
| // If there is currently a no-state prefetcher in progress for the host |
| // provided, it may not be shared. We require prefetchers to be by themselves |
| // in a separate process so that we can monitor their resource usage. |
| prerender::NoStatePrefetchManager* no_state_prefetch_manager = |
| NoStatePrefetchManagerFactory::GetForBrowserContext( |
| process_host->GetBrowserContext()); |
| if (no_state_prefetch_manager && |
| !no_state_prefetch_manager->MayReuseProcessHost(process_host)) { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| void ContentBrowserClientImpl::OverridePageVisibilityState( |
| content::RenderFrameHost* render_frame_host, |
| content::PageVisibilityState* visibility_state) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| |
| content::WebContents* web_contents = |
| content::WebContents::FromRenderFrameHost(render_frame_host); |
| DCHECK(web_contents); |
| |
| prerender::NoStatePrefetchManager* no_state_prefetch_manager = |
| NoStatePrefetchManagerFactory::GetForBrowserContext( |
| web_contents->GetBrowserContext()); |
| if (no_state_prefetch_manager && |
| no_state_prefetch_manager->IsWebContentsPrefetching(web_contents)) { |
| *visibility_state = content::PageVisibilityState::kHiddenButPainting; |
| } |
| } |
| |
| bool ContentBrowserClientImpl::ShouldDisableSiteIsolation( |
| content::SiteIsolationMode site_isolation_mode) { |
| return site_isolation::SiteIsolationPolicy:: |
| ShouldDisableSiteIsolationDueToMemoryThreshold(site_isolation_mode); |
| } |
| |
| std::vector<std::string> |
| ContentBrowserClientImpl::GetAdditionalSiteIsolationModes() { |
| if (site_isolation::SiteIsolationPolicy::IsIsolationForPasswordSitesEnabled()) |
| return {"Isolate Password Sites"}; |
| return {}; |
| } |
| |
| void ContentBrowserClientImpl::PersistIsolatedOrigin( |
| content::BrowserContext* context, |
| const url::Origin& origin, |
| content::ChildProcessSecurityPolicy::IsolatedOriginSource source) { |
| site_isolation::SiteIsolationPolicy::PersistIsolatedOrigin(context, origin, |
| source); |
| } |
| |
| base::OnceClosure ContentBrowserClientImpl::SelectClientCertificate( |
| content::WebContents* web_contents, |
| net::SSLCertRequestInfo* cert_request_info, |
| net::ClientCertIdentityList client_certs, |
| std::unique_ptr<content::ClientCertificateDelegate> delegate) { |
| #if BUILDFLAG(IS_ANDROID) |
| return browser_ui::ShowSSLClientCertificateSelector( |
| web_contents, cert_request_info, std::move(delegate)); |
| #else |
| delegate->ContinueWithCertificate(nullptr, nullptr); |
| return base::OnceClosure(); |
| #endif |
| } |
| |
| bool ContentBrowserClientImpl::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) { |
| *no_javascript_access = false; |
| |
| content::WebContents* web_contents = |
| content::WebContents::FromRenderFrameHost(opener); |
| |
| // Block popups if there is no NewTabDelegate. |
| TabImpl* tab = TabImpl::FromWebContents(web_contents); |
| if (!tab || !tab->has_new_tab_delegate()) |
| return false; |
| |
| if (container_type == content::mojom::WindowContainerType::BACKGROUND || |
| container_type == content::mojom::WindowContainerType::PERSISTENT) { |
| // WebLayer does not support extensions/apps, which are the only permitted |
| // users of background windows. |
| return false; |
| } |
| |
| // WindowOpenDisposition has a *ton* of types, but the following are really |
| // the only ones that should be hit for this code path. |
| switch (disposition) { |
| case WindowOpenDisposition::NEW_FOREGROUND_TAB: |
| [[fallthrough]]; |
| case WindowOpenDisposition::NEW_BACKGROUND_TAB: |
| [[fallthrough]]; |
| case WindowOpenDisposition::NEW_POPUP: |
| [[fallthrough]]; |
| case WindowOpenDisposition::NEW_WINDOW: |
| break; |
| default: |
| return false; |
| } |
| |
| GURL popup_url(target_url); |
| opener->GetProcess()->FilterURL(false, &popup_url); |
| // Use ui::PAGE_TRANSITION_LINK to match the similar logic in //chrome. |
| content::OpenURLParams params(popup_url, referrer, disposition, |
| ui::PAGE_TRANSITION_LINK, |
| /*is_renderer_initiated*/ true); |
| params.user_gesture = user_gesture; |
| params.initiator_origin = source_origin; |
| params.source_render_frame_id = opener->GetRoutingID(); |
| params.source_render_process_id = opener->GetProcess()->GetID(); |
| params.source_site_instance = opener->GetSiteInstance(); |
| // The content::OpenURLParams are created just for the delegate, and do not |
| // correspond to actual params created by //content, so pass null for the |
| // |open_url_params| argument here. |
| return blocked_content::MaybeBlockPopup( |
| web_contents, &opener_top_level_frame_url, |
| std::make_unique<PopupNavigationDelegateImpl>(params, web_contents, |
| opener), |
| /*open_url_params*/ nullptr, features, |
| HostContentSettingsMapFactory::GetForBrowserContext( |
| web_contents->GetBrowserContext())) != nullptr; |
| } |
| |
| content::ControllerPresentationServiceDelegate* |
| ContentBrowserClientImpl::GetControllerPresentationServiceDelegate( |
| content::WebContents* web_contents) { |
| #if BUILDFLAG(IS_ANDROID) |
| if (WebLayerFactoryImplAndroid::GetClientMajorVersion() < 88) |
| return nullptr; |
| |
| if (MediaRouterFactory::IsFeatureEnabled()) { |
| MediaRouterFactory::DoPlatformInitIfNeeded(); |
| return media_router::PresentationServiceDelegateImpl:: |
| GetOrCreateForWebContents(web_contents); |
| } |
| #endif |
| |
| return nullptr; |
| } |
| |
| void ContentBrowserClientImpl::OpenURL( |
| content::SiteInstance* site_instance, |
| const content::OpenURLParams& params, |
| base::OnceCallback<void(content::WebContents*)> callback) { |
| std::move(callback).Run( |
| ProfileImpl::FromBrowserContext(site_instance->GetBrowserContext()) |
| ->OpenUrl(params)); |
| } |
| |
| std::vector<std::unique_ptr<content::NavigationThrottle>> |
| ContentBrowserClientImpl::CreateThrottlesForNavigation( |
| content::NavigationHandle* handle) { |
| std::vector<std::unique_ptr<content::NavigationThrottle>> throttles; |
| |
| TabImpl* tab = TabImpl::FromWebContents(handle->GetWebContents()); |
| NavigationControllerImpl* navigation_controller = nullptr; |
| if (tab) { |
| navigation_controller = |
| static_cast<NavigationControllerImpl*>(tab->GetNavigationController()); |
| } |
| |
| NavigationImpl* navigation_impl = nullptr; |
| if (navigation_controller) { |
| navigation_impl = |
| navigation_controller->GetNavigationImplFromHandle(handle); |
| } |
| |
| if (handle->IsInMainFrame()) { |
| NavigationUIDataImpl* navigation_ui_data = |
| static_cast<NavigationUIDataImpl*>(handle->GetNavigationUIData()); |
| |
| if ((!navigation_ui_data || |
| !navigation_ui_data->disable_network_error_auto_reload()) && |
| (!navigation_impl || |
| !navigation_impl->disable_network_error_auto_reload()) && |
| IsNetworkErrorAutoReloadEnabled()) { |
| auto auto_reload_throttle = |
| error_page::NetErrorAutoReloader::MaybeCreateThrottleFor(handle); |
| if (auto_reload_throttle) |
| throttles.push_back(std::move(auto_reload_throttle)); |
| } |
| |
| // MetricsNavigationThrottle requires that it runs before |
| // NavigationThrottles that may delay or cancel navigations, so only |
| // NavigationThrottles that don't delay or cancel navigations (e.g. |
| // throttles that are only observing callbacks without affecting navigation |
| // behavior) should be added before MetricsNavigationThrottle. |
| throttles.push_back( |
| page_load_metrics::MetricsNavigationThrottle::Create(handle)); |
| if (TabImpl::FromWebContents(handle->GetWebContents())) { |
| throttles.push_back( |
| std::make_unique<NavigationErrorNavigationThrottle>(handle)); |
| } |
| } |
| |
| // The next highest priority throttle *must* be this as it's responsible for |
| // calling to NavigationController for certain events. |
| if (tab) { |
| auto throttle = navigation_controller->CreateNavigationThrottle(handle); |
| if (throttle) |
| throttles.push_back(std::move(throttle)); |
| } |
| |
| throttles.push_back(std::make_unique<SSLErrorNavigationThrottle>( |
| handle, std::make_unique<SSLCertReporterImpl>(), |
| base::BindOnce(&HandleSSLErrorWrapper), base::BindOnce(&IsInHostedApp), |
| base::BindOnce( |
| &ShouldIgnoreInterstitialBecauseNavigationDefaultedToHttps))); |
| |
| std::unique_ptr<security_interstitials::InsecureFormNavigationThrottle> |
| insecure_form_throttle = security_interstitials:: |
| InsecureFormNavigationThrottle::MaybeCreateNavigationThrottle( |
| handle, std::make_unique<WebLayerSecurityBlockingPageFactory>(), |
| nullptr); |
| if (insecure_form_throttle) { |
| throttles.push_back(std::move(insecure_form_throttle)); |
| } |
| |
| if (auto* throttle_manager = |
| subresource_filter::ContentSubresourceFilterThrottleManager:: |
| FromNavigationHandle(*handle)) { |
| throttle_manager->MaybeAppendNavigationThrottles(handle, &throttles); |
| } |
| |
| #if BUILDFLAG(IS_ANDROID) |
| if (IsSafebrowsingSupported()) { |
| std::unique_ptr<content::NavigationThrottle> safe_browsing_throttle = |
| GetSafeBrowsingService()->MaybeCreateSafeBrowsingNavigationThrottleFor( |
| handle); |
| if (safe_browsing_throttle) |
| throttles.push_back(std::move(safe_browsing_throttle)); |
| } |
| |
| if (!navigation_impl || !navigation_impl->disable_intent_processing()) { |
| std::unique_ptr<content::NavigationThrottle> intercept_navigation_throttle = |
| navigation_interception::InterceptNavigationDelegate:: |
| MaybeCreateThrottleFor( |
| handle, navigation_interception::SynchronyMode::kAsync); |
| if (intercept_navigation_throttle) |
| throttles.push_back(std::move(intercept_navigation_throttle)); |
| } |
| #endif |
| return throttles; |
| } |
| |
| content::GeneratedCodeCacheSettings |
| ContentBrowserClientImpl::GetGeneratedCodeCacheSettings( |
| content::BrowserContext* context) { |
| DCHECK(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. |
| return content::GeneratedCodeCacheSettings( |
| true, 0, ProfileImpl::GetCachePath(context)); |
| } |
| |
| void ContentBrowserClientImpl:: |
| RegisterAssociatedInterfaceBindersForRenderFrameHost( |
| content::RenderFrameHost& render_frame_host, |
| blink::AssociatedInterfaceRegistry& associated_registry) { |
| // TODO(https://crbug.com/1265864): Move the registry logic below to a |
| // dedicated file to ensure security review coverage. |
| // TODO(lingqi): Swap the parameters so that lambda functions are not needed. |
| associated_registry.AddInterface(base::BindRepeating( |
| [](content::RenderFrameHost* render_frame_host, |
| mojo::PendingAssociatedReceiver<autofill::mojom::AutofillDriver> |
| receiver) { |
| autofill::ContentAutofillDriverFactory::BindAutofillDriver( |
| std::move(receiver), render_frame_host); |
| }, |
| &render_frame_host)); |
| associated_registry.AddInterface(base::BindRepeating( |
| [](content::RenderFrameHost* render_frame_host, |
| mojo::PendingAssociatedReceiver<autofill::mojom::PasswordManagerDriver> |
| receiver) { |
| PasswordManagerDriverFactory::BindPasswordManagerDriver( |
| std::move(receiver), render_frame_host); |
| }, |
| &render_frame_host)); |
| associated_registry.AddInterface(base::BindRepeating( |
| [](content::RenderFrameHost* render_frame_host, |
| mojo::PendingAssociatedReceiver< |
| content_capture::mojom::ContentCaptureReceiver> receiver) { |
| content_capture::OnscreenContentProvider::BindContentCaptureReceiver( |
| std::move(receiver), render_frame_host); |
| }, |
| &render_frame_host)); |
| associated_registry.AddInterface(base::BindRepeating( |
| [](content::RenderFrameHost* render_frame_host, |
| mojo::PendingAssociatedReceiver< |
| page_load_metrics::mojom::PageLoadMetrics> receiver) { |
| page_load_metrics::MetricsWebContentsObserver::BindPageLoadMetrics( |
| std::move(receiver), render_frame_host); |
| }, |
| &render_frame_host)); |
| associated_registry.AddInterface(base::BindRepeating( |
| [](content::RenderFrameHost* render_frame_host, |
| mojo::PendingAssociatedReceiver< |
| security_interstitials::mojom::InterstitialCommands> receiver) { |
| security_interstitials::SecurityInterstitialTabHelper:: |
| BindInterstitialCommands(std::move(receiver), render_frame_host); |
| }, |
| &render_frame_host)); |
| associated_registry.AddInterface(base::BindRepeating( |
| [](content::RenderFrameHost* render_frame_host, |
| mojo::PendingAssociatedReceiver< |
| subresource_filter::mojom::SubresourceFilterHost> receiver) { |
| subresource_filter::ContentSubresourceFilterThrottleManager:: |
| BindReceiver(std::move(receiver), render_frame_host); |
| }, |
| &render_frame_host)); |
| } |
| |
| void ContentBrowserClientImpl::ExposeInterfacesToRenderer( |
| service_manager::BinderRegistry* registry, |
| blink::AssociatedInterfaceRegistry* associated_registry, |
| content::RenderProcessHost* render_process_host) { |
| performance_manager::PerformanceManagerRegistry::GetInstance() |
| ->CreateProcessNodeAndExposeInterfacesToRendererProcess( |
| registry, render_process_host); |
| #if BUILDFLAG(IS_ANDROID) |
| auto create_spellcheck_host = |
| [](mojo::PendingReceiver<spellcheck::mojom::SpellCheckHost> receiver) { |
| mojo::MakeSelfOwnedReceiver(std::make_unique<SpellCheckHostImpl>(), |
| std::move(receiver)); |
| }; |
| registry->AddInterface(base::BindRepeating(create_spellcheck_host), |
| content::GetUIThreadTaskRunner({})); |
| |
| if (base::FeatureList::IsEnabled(features::kWebLayerSafeBrowsing) && |
| IsSafebrowsingSupported()) { |
| GetSafeBrowsingService()->AddInterface(registry, render_process_host); |
| } |
| #endif // BUILDFLAG(IS_ANDROID) |
| } |
| |
| void ContentBrowserClientImpl::BindMediaServiceReceiver( |
| content::RenderFrameHost* render_frame_host, |
| mojo::GenericPendingReceiver receiver) { |
| #if BUILDFLAG(IS_ANDROID) |
| if (auto r = receiver.As<media::mojom::MediaDrmStorage>()) { |
| CreateMediaDrmStorage(render_frame_host, std::move(r)); |
| return; |
| } |
| #endif |
| } |
| |
| void ContentBrowserClientImpl::RegisterBrowserInterfaceBindersForFrame( |
| content::RenderFrameHost* render_frame_host, |
| mojo::BinderMapWithContext<content::RenderFrameHost*>* map) { |
| PopulateWebLayerFrameBinders(render_frame_host, map); |
| performance_manager::PerformanceManagerRegistry::GetInstance() |
| ->ExposeInterfacesToRenderFrame(map); |
| } |
| |
| void ContentBrowserClientImpl::RenderProcessWillLaunch( |
| content::RenderProcessHost* host) { |
| #if BUILDFLAG(IS_ANDROID) |
| host->AddFilter(new cdm::CdmMessageFilterAndroid( |
| !host->GetBrowserContext()->IsOffTheRecord(), |
| /*force_to_support_secure_codecs*/ false)); |
| #endif |
| PageSpecificContentSettingsDelegate::InitializeRenderer(host); |
| } |
| |
| scoped_refptr<content::QuotaPermissionContext> |
| ContentBrowserClientImpl::CreateQuotaPermissionContext() { |
| return base::MakeRefCounted<permissions::QuotaPermissionContextImpl>(); |
| } |
| |
| void ContentBrowserClientImpl::CreateFeatureListAndFieldTrials() { |
| local_state_ = CreateLocalState(); |
| feature_list_creator_ = |
| std::make_unique<FeatureListCreator>(local_state_.get()); |
| if (!SystemNetworkContextManager::HasInstance()) |
| SystemNetworkContextManager::CreateInstance(GetUserAgent()); |
| feature_list_creator_->SetSystemNetworkContextManager( |
| SystemNetworkContextManager::GetInstance()); |
| feature_list_creator_->CreateFeatureListAndFieldTrials(); |
| } |
| |
| #if BUILDFLAG(IS_ANDROID) |
| SafeBrowsingService* ContentBrowserClientImpl::GetSafeBrowsingService() { |
| return BrowserProcess::GetInstance()->GetSafeBrowsingService(); |
| } |
| #endif |
| |
| // TODO(crbug.com/1052397): Revisit once build flag switch of lacros-chrome is |
| // complete. |
| #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) || \ |
| BUILDFLAG(IS_ANDROID) |
| void ContentBrowserClientImpl::GetAdditionalMappedFilesForChildProcess( |
| const base::CommandLine& command_line, |
| int child_process_id, |
| content::PosixFileDescriptorInfo* mappings) { |
| #if BUILDFLAG(IS_ANDROID) |
| base::MemoryMappedFile::Region region; |
| int fd = ui::GetMainAndroidPackFd(®ion); |
| mappings->ShareWithRegion(kWebLayerMainPakDescriptor, fd, region); |
| |
| fd = ui::GetCommonResourcesPackFd(®ion); |
| mappings->ShareWithRegion(kWebLayer100PercentPakDescriptor, fd, region); |
| |
| fd = ui::GetLocalePackFd(®ion); |
| mappings->ShareWithRegion(kWebLayerLocalePakDescriptor, fd, region); |
| |
| if (base::android::BundleUtils::IsBundle()) { |
| fd = ui::GetSecondaryLocalePackFd(®ion); |
| mappings->ShareWithRegion(kWebLayerSecondaryLocalePakDescriptor, fd, |
| region); |
| } else { |
| mappings->ShareWithRegion(kWebLayerSecondaryLocalePakDescriptor, |
| base::GlobalDescriptors::GetInstance()->Get( |
| kWebLayerSecondaryLocalePakDescriptor), |
| base::GlobalDescriptors::GetInstance()->GetRegion( |
| kWebLayerSecondaryLocalePakDescriptor)); |
| } |
| |
| int crash_signal_fd = |
| crashpad::CrashHandlerHost::Get()->GetDeathSignalSocket(); |
| if (crash_signal_fd >= 0) |
| mappings->Share(kCrashDumpSignal, crash_signal_fd); |
| #endif // BUILDFLAG(IS_ANDROID) |
| } |
| #endif |
| |
| void ContentBrowserClientImpl::AppendExtraCommandLineSwitches( |
| base::CommandLine* command_line, |
| int child_process_id) { |
| const base::CommandLine& browser_command_line( |
| *base::CommandLine::ForCurrentProcess()); |
| std::string process_type = |
| command_line->GetSwitchValueASCII(::switches::kProcessType); |
| if (process_type == ::switches::kRendererProcess) { |
| // Please keep this in alphabetical order. |
| static const char* const kSwitchNames[] = { |
| embedder_support::kOriginTrialDisabledFeatures, |
| embedder_support::kOriginTrialDisabledTokens, |
| embedder_support::kOriginTrialPublicKey, |
| }; |
| command_line->CopySwitchesFrom(browser_command_line, kSwitchNames, |
| std::size(kSwitchNames)); |
| } |
| } |
| |
| // static |
| std::unique_ptr<PrefService> ContentBrowserClientImpl::CreateLocalState() { |
| auto pref_registry = base::MakeRefCounted<PrefRegistrySimple>(); |
| |
| RegisterPrefs(pref_registry.get()); |
| base::FilePath path; |
| CHECK(base::PathService::Get(DIR_USER_DATA, &path)); |
| path = path.AppendASCII("Local State"); |
| PrefServiceFactory pref_service_factory; |
| pref_service_factory.set_user_prefs( |
| base::MakeRefCounted<JsonPrefStore>(path)); |
| |
| { |
| // Creating the prefs service may require reading the preferences from |
| // disk. |
| base::ScopedAllowBlocking allow_io; |
| return pref_service_factory.Create(pref_registry); |
| } |
| } |
| |
| #if BUILDFLAG(IS_ANDROID) |
| bool ContentBrowserClientImpl::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) { |
| // The navigation API intercepting API only supports main frame navigations. |
| if (type != URLLoaderFactoryType::kNavigation || frame->GetParent()) |
| return false; |
| |
| auto* web_contents = content::WebContents::FromRenderFrameHost(frame); |
| TabImpl* tab = TabImpl::FromWebContents(web_contents); |
| if (!tab) |
| return false; |
| |
| auto* navigation_controller = |
| static_cast<NavigationControllerImpl*>(tab->GetNavigationController()); |
| auto* navigation_impl = |
| navigation_controller->GetNavigationImplFromId(*navigation_id); |
| if (!navigation_impl) |
| return false; |
| |
| auto response = navigation_impl->TakeResponse(); |
| if (!response && !ProxyingURLLoaderFactoryImpl::HasCachedInputStream( |
| frame->GetFrameTreeNodeId(), |
| navigation_impl->navigation_entry_unique_id())) { |
| return false; |
| } |
| |
| mojo::PendingReceiver<network::mojom::URLLoaderFactory> proxied_receiver = |
| std::move(*factory_receiver); |
| mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory_remote; |
| *factory_receiver = target_factory_remote.InitWithNewPipeAndPassReceiver(); |
| |
| // Owns itself. |
| new ProxyingURLLoaderFactoryImpl( |
| std::move(proxied_receiver), std::move(target_factory_remote), |
| navigation_impl->GetURL(), std::move(response), |
| frame->GetFrameTreeNodeId(), |
| navigation_impl->navigation_entry_unique_id()); |
| |
| return true; |
| } |
| |
| content::ContentBrowserClient::WideColorGamutHeuristic |
| ContentBrowserClientImpl::GetWideColorGamutHeuristic() { |
| // Always match window since a mismatch can cause inefficiency in surface |
| // flinger. |
| return WideColorGamutHeuristic::kUseWindow; |
| } |
| |
| std::unique_ptr<content::LoginDelegate> |
| ContentBrowserClientImpl::CreateLoginDelegate( |
| const net::AuthChallengeInfo& auth_info, |
| content::WebContents* web_contents, |
| const content::GlobalRequestID& request_id, |
| bool is_request_for_primary_main_frame, |
| const GURL& url, |
| scoped_refptr<net::HttpResponseHeaders> response_headers, |
| bool first_auth_attempt, |
| LoginAuthRequiredCallback auth_required_callback) { |
| return std::make_unique<HttpAuthHandlerImpl>( |
| auth_info, web_contents, first_auth_attempt, |
| std::move(auth_required_callback)); |
| } |
| |
| std::unique_ptr<content::TtsEnvironmentAndroid> |
| ContentBrowserClientImpl::CreateTtsEnvironmentAndroid() { |
| return std::make_unique<TtsEnvironmentAndroidImpl>(); |
| } |
| |
| bool ContentBrowserClientImpl:: |
| ShouldObserveContainerViewLocationForDialogOverlays() { |
| // Observe location changes of the container view as WebLayer might be |
| // embedded in a scrollable container and we need to update the position of |
| // any DialogOverlays. |
| return true; |
| } |
| |
| content::BluetoothDelegate* ContentBrowserClientImpl::GetBluetoothDelegate() { |
| if (!bluetooth_delegate_) { |
| bluetooth_delegate_ = std::make_unique<permissions::BluetoothDelegateImpl>( |
| std::make_unique<WebLayerBluetoothDelegateImplClient>()); |
| } |
| return bluetooth_delegate_.get(); |
| } |
| |
| #endif // BUILDFLAG(IS_ANDROID) |
| |
| content::SpeechRecognitionManagerDelegate* |
| ContentBrowserClientImpl::CreateSpeechRecognitionManagerDelegate() { |
| return new WebLayerSpeechRecognitionManagerDelegate(); |
| } |
| |
| #if BUILDFLAG(ENABLE_ARCORE) |
| content::XrIntegrationClient* |
| ContentBrowserClientImpl::GetXrIntegrationClient() { |
| if (!XrIntegrationClientImpl::IsEnabled()) |
| return nullptr; |
| |
| if (!xr_integration_client_) |
| xr_integration_client_ = std::make_unique<XrIntegrationClientImpl>(); |
| return xr_integration_client_.get(); |
| } |
| #endif // BUILDFLAG(ENABLE_ARCORE) |
| |
| ukm::UkmService* ContentBrowserClientImpl::GetUkmService() { |
| #if BUILDFLAG(IS_ANDROID) |
| return WebLayerMetricsServiceClient::GetInstance()->GetUkmService(); |
| #else |
| return nullptr; |
| #endif |
| } |
| |
| bool ContentBrowserClientImpl::HasErrorPage(int http_status_code) { |
| // Use an internal error page, if we have one for the status code. |
| return error_page::LocalizedError::HasStrings( |
| error_page::Error::kHttpErrorDomain, http_status_code); |
| } |
| |
| bool ContentBrowserClientImpl::IsClipboardPasteAllowed( |
| content::RenderFrameHost* render_frame_host) { |
| DCHECK(render_frame_host); |
| |
| content::BrowserContext* browser_context = |
| render_frame_host->GetBrowserContext(); |
| DCHECK(browser_context); |
| |
| content::PermissionController* permission_controller = |
| browser_context->GetPermissionController(); |
| blink::mojom::PermissionStatus status = |
| permission_controller->GetPermissionStatusForCurrentDocument( |
| blink::PermissionType::CLIPBOARD_READ_WRITE, render_frame_host); |
| |
| if (!render_frame_host->HasTransientUserActivation() && |
| status != blink::mojom::PermissionStatus::GRANTED) { |
| // Paste requires either user activation, or granted web permission. |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool ContentBrowserClientImpl::ShouldPreconnectNavigation( |
| content::BrowserContext* browser_context) { |
| return true; |
| } |
| |
| } // namespace weblayer |