| // Copyright 2017 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #import "ios/web_view/internal/app/application_context.h" |
| |
| #import "base/base_paths.h" |
| #import "base/command_line.h" |
| #import "base/functional/bind.h" |
| #import "base/no_destructor.h" |
| #import "base/path_service.h" |
| #import "components/autofill/core/common/autofill_features.h" |
| #import "components/component_updater/component_updater_service.h" |
| #import "components/component_updater/installer_policies/autofill_states_component_installer.h" |
| #import "components/component_updater/timer_update_scheduler.h" |
| #import "components/metrics/demographics/user_demographics.h" |
| #import "components/os_crypt/async/browser/os_crypt_async.h" |
| #import "components/prefs/json_pref_store.h" |
| #import "components/prefs/pref_registry_simple.h" |
| #import "components/prefs/pref_service.h" |
| #import "components/prefs/pref_service_factory.h" |
| #import "components/proxy_config/pref_proxy_config_tracker_impl.h" |
| #import "components/sessions/core/session_id_generator.h" |
| #import "components/signin/public/identity_manager/identity_manager.h" |
| #import "components/translate/core/browser/translate_download_manager.h" |
| #import "components/update_client/update_client.h" |
| #import "components/variations/net/variations_http_headers.h" |
| #import "components/webui/flags/pref_service_flags_storage.h" |
| #import "ios/components/security_interstitials/safe_browsing/safe_browsing_service_impl.h" |
| #import "ios/web/public/thread/web_task_traits.h" |
| #import "ios/web/public/thread/web_thread.h" |
| #import "ios/web_view/internal/app/web_view_io_thread.h" |
| #import "ios/web_view/internal/component_updater/web_view_component_updater_configurator.h" |
| #import "ios/web_view/internal/cwv_flags_internal.h" |
| #import "mojo/public/cpp/bindings/pending_receiver.h" |
| #import "net/log/net_log.h" |
| #import "net/socket/client_socket_pool_manager.h" |
| #import "services/network/network_change_manager.h" |
| #import "services/network/public/cpp/network_connection_tracker.h" |
| #import "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" |
| #import "services/network/public/mojom/network_context.mojom.h" |
| #import "ui/base/device_form_factor.h" |
| #import "ui/base/l10n/l10n_util_mac.h" |
| |
| namespace ios_web_view { |
| namespace { |
| |
| // Passed to NetworkConnectionTracker to bind a NetworkChangeManager receiver. |
| void BindNetworkChangeManagerReceiver( |
| network::NetworkChangeManager* network_change_manager, |
| mojo::PendingReceiver<network::mojom::NetworkChangeManager> receiver) { |
| network_change_manager->AddReceiver(std::move(receiver)); |
| } |
| |
| } // namespace |
| |
| ApplicationContext* ApplicationContext::GetInstance() { |
| static base::NoDestructor<ApplicationContext> instance; |
| return instance.get(); |
| } |
| |
| ApplicationContext::ApplicationContext() { |
| SetApplicationLocale(l10n_util::GetLocaleOverride()); |
| } |
| |
| ApplicationContext::~ApplicationContext() = default; |
| |
| void ApplicationContext::PreCreateThreads() { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| web_view_io_thread_ = |
| std::make_unique<WebViewIOThread>(GetLocalState(), GetNetLog()); |
| } |
| |
| void ApplicationContext::PostCreateThreads() { |
| // Delegate all encryption calls to OSCrypt. |
| os_crypt_async_ = std::make_unique<os_crypt_async::OSCryptAsync>( |
| std::vector<std::pair<os_crypt_async::OSCryptAsync::Precedence, |
| std::unique_ptr<os_crypt_async::KeyProvider>>>()); |
| |
| // Trigger an instance grab on a background thread if necessary. |
| os_crypt_async_->GetInstance(base::DoNothing()); |
| |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| web::GetIOThreadTaskRunner({})->PostTask( |
| FROM_HERE, base::BindOnce(&WebViewIOThread::InitOnIO, |
| base::Unretained(web_view_io_thread_.get()))); |
| } |
| |
| void ApplicationContext::SaveState() { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| if (local_state_) { |
| local_state_->CommitPendingWrite(); |
| sessions::SessionIdGenerator::GetInstance()->Shutdown(); |
| } |
| |
| if (shared_url_loader_factory_) { |
| shared_url_loader_factory_->Detach(); |
| } |
| |
| if (network_context_) { |
| web::GetIOThreadTaskRunner({})->DeleteSoon( |
| FROM_HERE, network_context_owner_.release()); |
| } |
| } |
| |
| void ApplicationContext::PostDestroyThreads() { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| // Resets associated state right after actual thread is stopped as |
| // WebViewIOThread::Globals cleanup happens in CleanUp on the IO |
| // thread, i.e. as the thread exits its message loop. |
| // |
| // This is important because in various places, the WebViewIOThread |
| // object being null is considered synonymous with the IO thread |
| // having stopped. |
| web_view_io_thread_.reset(); |
| } |
| |
| PrefService* ApplicationContext::GetLocalState() { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| if (!local_state_) { |
| // Register local state preferences. |
| scoped_refptr<PrefRegistrySimple> pref_registry(new PrefRegistrySimple); |
| flags_ui::PrefServiceFlagsStorage::RegisterPrefs(pref_registry.get()); |
| PrefProxyConfigTrackerImpl::RegisterPrefs(pref_registry.get()); |
| signin::IdentityManager::RegisterLocalStatePrefs(pref_registry.get()); |
| component_updater::RegisterComponentUpdateServicePrefs(pref_registry.get()); |
| update_client::RegisterPrefs(pref_registry.get()); |
| component_updater::AutofillStatesComponentInstallerPolicy::RegisterPrefs( |
| pref_registry.get()); |
| metrics::RegisterDemographicsLocalStatePrefs(pref_registry.get()); |
| sessions::SessionIdGenerator::RegisterPrefs(pref_registry.get()); |
| |
| base::FilePath local_state_path; |
| base::PathService::Get(base::DIR_APP_DATA, &local_state_path); |
| local_state_path = |
| local_state_path.Append(FILE_PATH_LITERAL("ChromeWebViewLocalState")); |
| |
| scoped_refptr<PersistentPrefStore> user_pref_store = |
| new JsonPrefStore(std::move(local_state_path)); |
| |
| PrefServiceFactory factory; |
| factory.set_user_prefs(user_pref_store); |
| local_state_ = factory.Create(pref_registry.get()); |
| |
| sessions::SessionIdGenerator::GetInstance()->Init(local_state_.get()); |
| |
| int max_normal_socket_pool_count = |
| net::ClientSocketPoolManager::max_sockets_per_group( |
| net::HttpNetworkSession::NORMAL_SOCKET_POOL); |
| int socket_count = std::max<int>(net::kDefaultMaxSocketsPerProxyChain, |
| max_normal_socket_pool_count); |
| net::ClientSocketPoolManager::set_max_sockets_per_proxy_chain( |
| net::HttpNetworkSession::NORMAL_SOCKET_POOL, socket_count); |
| } |
| return local_state_.get(); |
| } |
| |
| net::URLRequestContextGetter* ApplicationContext::GetSystemURLRequestContext() { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| return web_view_io_thread_->system_url_request_context_getter(); |
| } |
| |
| scoped_refptr<network::SharedURLLoaderFactory> |
| ApplicationContext::GetSharedURLLoaderFactory() { |
| if (!url_loader_factory_) { |
| auto url_loader_factory_params = |
| network::mojom::URLLoaderFactoryParams::New(); |
| url_loader_factory_params->process_id = network::mojom::kBrowserProcessId; |
| url_loader_factory_params->is_orb_enabled = false; |
| GetSystemNetworkContext()->CreateURLLoaderFactory( |
| url_loader_factory_.BindNewPipeAndPassReceiver(), |
| std::move(url_loader_factory_params)); |
| shared_url_loader_factory_ = |
| base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( |
| url_loader_factory_.get()); |
| } |
| return shared_url_loader_factory_; |
| } |
| |
| network::mojom::NetworkContext* ApplicationContext::GetSystemNetworkContext() { |
| if (!network_context_) { |
| network::mojom::NetworkContextParamsPtr network_context_params = |
| network::mojom::NetworkContextParams::New(); |
| variations::UpdateCorsExemptHeaderForVariations( |
| network_context_params.get()); |
| network_context_owner_ = std::make_unique<web::NetworkContextOwner>( |
| GetSystemURLRequestContext(), |
| network_context_params->cors_exempt_header_list, &network_context_); |
| } |
| return network_context_.get(); |
| } |
| |
| network::NetworkConnectionTracker* |
| ApplicationContext::GetNetworkConnectionTracker() { |
| if (!network_connection_tracker_) { |
| if (!network_change_manager_) { |
| network_change_manager_ = |
| std::make_unique<network::NetworkChangeManager>(nullptr); |
| } |
| network_connection_tracker_ = |
| std::make_unique<network::NetworkConnectionTracker>(base::BindRepeating( |
| &BindNetworkChangeManagerReceiver, |
| base::Unretained(network_change_manager_.get()))); |
| } |
| return network_connection_tracker_.get(); |
| } |
| |
| const std::string& ApplicationContext::GetApplicationLocale() { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| DCHECK(!application_locale_.empty()); |
| return application_locale_; |
| } |
| |
| net::NetLog* ApplicationContext::GetNetLog() { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| return net::NetLog::Get(); |
| } |
| |
| component_updater::ComponentUpdateService* |
| ApplicationContext::GetComponentUpdateService() { |
| if (!component_updater_) { |
| // TODO(crbug.com/40215633): Brand code should be configurable. |
| std::string brand_code = |
| ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET ? "APLB" |
| : "APLA"; |
| component_updater_ = component_updater::ComponentUpdateServiceFactory( |
| MakeComponentUpdaterConfigurator( |
| base::CommandLine::ForCurrentProcess()), |
| std::make_unique<component_updater::TimerUpdateScheduler>(), |
| brand_code); |
| } |
| return component_updater_.get(); |
| } |
| |
| os_crypt_async::OSCryptAsync* ApplicationContext::GetOSCryptAsync() { |
| return os_crypt_async_.get(); |
| } |
| |
| WebViewIOThread* ApplicationContext::GetWebViewIOThread() { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| DCHECK(web_view_io_thread_.get()); |
| return web_view_io_thread_.get(); |
| } |
| |
| void ApplicationContext::SetApplicationLocale(const std::string& locale) { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| application_locale_ = locale; |
| translate::TranslateDownloadManager::GetInstance()->set_application_locale( |
| application_locale_); |
| } |
| |
| SafeBrowsingService* ApplicationContext::GetSafeBrowsingService() { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| if (!safe_browsing_service_) { |
| safe_browsing_service_ = base::MakeRefCounted<SafeBrowsingServiceImpl>(); |
| safe_browsing_service_->Initialize( |
| base::PathService::CheckedGet(base::DIR_APP_DATA)); |
| } |
| return safe_browsing_service_.get(); |
| } |
| |
| void ApplicationContext::ShutdownSafeBrowsingServiceIfNecessary() { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| if (safe_browsing_service_) { |
| safe_browsing_service_->ShutDown(); |
| } |
| } |
| |
| } // namespace ios_web_view |