// Copyright 2012 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/browser_process_impl.h" #include #include #include #include #include #include #include #include "base/atomic_ref_count.h" #include "base/command_line.h" #include "base/compiler_specific.h" #include "base/debug/leak_annotations.h" #include "base/files/file_path.h" #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/functional/callback_helpers.h" #include "base/location.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_functions.h" #include "base/notimplemented.h" #include "base/notreached.h" #include "base/path_service.h" #include "base/run_loop.h" #include "base/synchronization/waitable_event.h" #include "base/task/sequenced_task_runner.h" #include "base/task/single_thread_task_runner.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "base/threading/thread.h" #include "base/threading/thread_restrictions.h" #include "base/time/default_clock.h" #include "base/time/default_tick_clock.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "build/config/linux/dbus/buildflags.h" #include "chrome/browser/accessibility/soda_installer_impl.h" #include "chrome/browser/battery/battery_metrics.h" #include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/buildflags.h" #include "chrome/browser/chrome_browser_main.h" #include "chrome/browser/chrome_content_browser_client.h" #include "chrome/browser/component_updater/chrome_component_updater_configurator.h" #include "chrome/browser/controlled_frame/controlled_frame_extensions_browser_api_provider.h" #include "chrome/browser/defaults.h" #include "chrome/browser/devtools/remote_debugging_server.h" #include "chrome/browser/download/download_request_limiter.h" #include "chrome/browser/download/download_status_updater.h" #include "chrome/browser/global_features.h" #include "chrome/browser/google/google_brand.h" #include "chrome/browser/gpu/gpu_mode_manager.h" #include "chrome/browser/icon_manager.h" #include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/lifetime/browser_shutdown.h" #include "chrome/browser/media/audio_process_ml_model_forwarder.h" #include "chrome/browser/media/chrome_media_session_client.h" #include "chrome/browser/media/router/providers/cast/dual_media_sink_service.h" #include "chrome/browser/media/webrtc/webrtc_event_log_manager.h" #include "chrome/browser/media/webrtc/webrtc_log_uploader.h" #include "chrome/browser/metrics/chrome_feature_list_creator.h" #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" #include "chrome/browser/metrics/chrome_metrics_services_manager_client.h" #include "chrome/browser/metrics/metrics_reporting_state.h" #include "chrome/browser/net/system_network_context_manager.h" #include "chrome/browser/notifications/notification_platform_bridge.h" #include "chrome/browser/notifications/system_notification_helper.h" #include "chrome/browser/optimization_guide/model_execution/optimization_guide_global_state.h" #include "chrome/browser/permissions/chrome_permissions_client.h" #include "chrome/browser/policy/chrome_browser_policy_connector.h" #include "chrome/browser/prefs/browser_prefs.h" #include "chrome/browser/prefs/chrome_pref_service_factory.h" #include "chrome/browser/printing/background_printing_manager.h" #include "chrome/browser/printing/print_job_manager.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/resource_coordinator/resource_coordinator_parts.h" #include "chrome/browser/serial/serial_policy_allowed_ports.h" #include "chrome/browser/shell_integration.h" #include "chrome/browser/site_isolation/prefs_observer.h" #include "chrome/browser/speech/speech_recognition_small_expert_model_installer.h" #include "chrome/browser/ssl/secure_origin_prefs_observer.h" #include "chrome/browser/startup_data.h" #include "chrome/browser/status_icons/status_tray.h" #include "chrome/browser/ui/dialogs/browser_dialogs.h" #include "chrome/browser/update_client/chrome_update_query_params_delegate.h" #include "chrome/browser/updater/updater.h" #include "chrome/common/buildflags.h" #include "chrome/common/channel_info.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_features.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" #include "chrome/grit/branded_strings.h" #include "chrome/installer/util/google_update_settings.h" #include "components/activity_reporter/activity_reporter.h" #include "components/application_locale_storage/application_locale_storage.h" #include "components/breadcrumbs/core/application_breadcrumbs_logger.h" #include "components/breadcrumbs/core/breadcrumb_persistent_storage_util.h" #include "components/breadcrumbs/core/breadcrumbs_status.h" #include "components/breadcrumbs/core/crash_reporter_breadcrumb_observer.h" #include "components/component_updater/component_updater_service.h" #include "components/component_updater/timer_update_scheduler.h" #include "components/crash/core/common/crash_key.h" #include "components/embedder_support/origin_trials/origin_trials_settings_storage.h" #include "components/gcm_driver/gcm_driver.h" #include "components/javascript_dialogs/app_modal_dialog_queue.h" #include "components/keep_alive_registry/keep_alive_types.h" #include "components/language/core/browser/pref_names.h" #include "components/metrics/metrics_pref_names.h" #include "components/metrics/metrics_service.h" #include "components/metrics_services_manager/metrics_services_manager.h" #include "components/metrics_services_manager/metrics_services_manager_client.h" #include "components/network_time/network_time_tracker.h" #include "components/os_crypt/async/browser/os_crypt_async.h" #include "components/permissions/permissions_client.h" #include "components/policy/core/common/policy_service.h" #include "components/prefs/json_pref_store.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" #include "components/safe_browsing/content/browser/safe_browsing_service_interface.h" #include "components/sessions/core/session_id_generator.h" #include "components/signin/core/browser/active_primary_accounts_metrics_recorder.h" #include "components/subresource_filter/content/browser/ruleset_service.h" #include "components/subresource_filter/content/browser/safe_browsing_ruleset_publisher.h" #include "components/subresource_filter/core/browser/subresource_filter_features.h" #include "components/subresource_filter/core/common/constants.h" #include "components/supervised_user/core/browser/device_parental_controls.h" #include "components/supervised_user/core/browser/device_parental_controls_noop_impl.h" #include "components/translate/core/browser/translate_download_manager.h" #include "components/ukm/ukm_service.h" #include "components/update_client/net/network_chromium.h" #include "components/update_client/update_query_params.h" #include "components/variations/service/variations_service.h" #include "components/web_resource/web_resource_pref_names.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/network_quality_observer_factory.h" #include "content/public/browser/network_service_instance.h" #include "content/public/browser/process_visibility_util.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/service_worker_context.h" #include "content/public/browser/storage_partition.h" #include "content/public/common/buildflags.h" #include "extensions/buildflags/buildflags.h" #include "extensions/common/constants.h" #include "media/media_buildflags.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "printing/buildflags/buildflags.h" #include "services/network/public/cpp/features.h" #include "ui/base/idle/idle.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/ui_base_features.h" #include "ui/base/unowned_user_data/unowned_user_data_host.h" #if BUILDFLAG(IS_WIN) #include "base/win/windows_version.h" #include "chrome/browser/browser_features.h" #include "chrome/browser/os_crypt/app_bound_encryption_provider_win.h" #include "chrome/installer/util/install_util.h" #include "components/os_crypt/async/browser/dpapi_key_provider.h" #elif BUILDFLAG(IS_MAC) #include "chrome/browser/chrome_browser_main_mac.h" #include "chrome/browser/shutdown_watchdog_mac.h" #endif #if BUILDFLAG(IS_WIN) #include "chrome/browser/win/isolated_browser/isolated_browser_support.h" #endif // BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_CHROMEOS) #include "ash/constants/ash_pref_names.h" #include "chrome/browser/ash/extensions/chromeos_extensions_browser_api_provider.h" #include "chrome/browser/media_galleries/media_file_system_registry.h" #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/soda/soda_installer_impl_chromeos.h" #else #include "ui/message_center/message_center.h" #endif #if BUILDFLAG(IS_ANDROID) #include "chrome/browser/accessibility/accessibility_prefs/android/accessibility_prefs_controller.h" #include "chrome/browser/flags/android/chrome_feature_list.h" #include "chrome/browser/ssl/chrome_security_state_client.h" #include "chrome/browser/webapps/webapps_client_android.h" #include "chrome/browser/webauthn/android/chrome_webauthn_client_android.h" #include "components/supervised_user/core/browser/android/android_parental_controls.h" #include "components/webauthn/android/webauthn_client_android.h" namespace chrome_browser_prefs { void OnLocalStatePrefsLoaded(); } // namespace chrome_browser_prefs #else #include "chrome/browser/devtools/devtools_auto_opener.h" #include "chrome/browser/error_reporting/chrome_js_error_report_processor.h" #include "chrome/browser/gcm/gcm_product_util.h" #include "chrome/browser/hid/hid_system_tray_icon.h" #include "chrome/browser/intranet_redirect_detector.h" #include "chrome/browser/lifetime/application_lifetime_desktop.h" #include "chrome/browser/resource_coordinator/tab_manager.h" #include "chrome/browser/usb/usb_system_tray_icon.h" #include "chrome/browser/web_applications/isolated_web_apps/runtime_init.h" #include "chrome/browser/webapps/webapps_client_desktop.h" #include "components/gcm_driver/gcm_client_factory.h" #include "components/gcm_driver/gcm_desktop_utils.h" #include "components/keep_alive_registry/keep_alive_registry.h" #endif // BUILDFLAG(IS_ANDROID) #if BUILDFLAG(ENABLE_BACKGROUND_MODE) #include "chrome/browser/background/extensions/background_mode_manager.h" #endif #if BUILDFLAG(ENABLE_EXTENSIONS_CORE) #include "chrome/browser/extensions/chrome_extensions_browser_client.h" #include "chrome/common/initialize_extensions_client.h" #endif #if BUILDFLAG(ENABLE_EXTENSIONS) #include "chrome/common/extensions/chrome_extensions_client.h" #include "components/storage_monitor/storage_monitor.h" // nogncheck crbug.com/40147906 #include "extensions/common/context_data.h" #include "extensions/common/extension_l10n_util.h" #endif #if BUILDFLAG(ENABLE_PLATFORM_APPS) #include "chrome/browser/apps/platform_apps/chrome_apps_browser_api_provider.h" #include "chrome/browser/ui/apps/chrome_app_window_client.h" #endif #if BUILDFLAG(ENABLE_PLUGINS) #include "chrome/browser/plugins/chrome_plugin_service_filter.h" #include "content/public/browser/plugin_service.h" #endif #if BUILDFLAG(ENABLE_PRINT_PREVIEW) #include "chrome/browser/printing/print_preview_dialog_controller.h" #endif #if BUILDFLAG(ENABLE_SESSION_SERVICE) #include "chrome/browser/sessions/exit_type_service.h" #endif #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS) #include "chrome/browser/first_run/upgrade_util.h" #include "chrome/browser/ui/profiles/profile_picker.h" #endif #if BUILDFLAG(ENABLE_CHROME_NOTIFICATIONS) #include "chrome/browser/notifications/notification_ui_manager.h" #endif #if BUILDFLAG(IS_CHROMEOS) #include "chrome/browser/chromeos/extensions/telemetry/chromeos_telemetry_extensions_browser_api_provider.h" #include "chrome/browser/hid/hid_pinned_notification.h" #include "chrome/browser/screen_ai/screen_ai_downloader_chromeos.h" #include "chrome/browser/usb/usb_pinned_notification.h" #include "components/crash/core/app/crashpad.h" #elif !BUILDFLAG(IS_ANDROID) #include "chrome/browser/hid/hid_status_icon.h" #include "chrome/browser/screen_ai/screen_ai_downloader_non_chromeos.h" #include "chrome/browser/usb/usb_status_icon.h" #include "components/enterprise/browser/controller/chrome_browser_cloud_management_controller.h" #endif #if BUILDFLAG(IS_LINUX) && BUILDFLAG(USE_DBUS) #include "chrome/browser/browser_features.h" #include "components/os_crypt/async/browser/freedesktop_secret_key_provider.h" #include "components/os_crypt/async/browser/secret_portal_key_provider.h" #include "components/password_manager/core/browser/password_manager_switches.h" #endif #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC) #include "components/os_crypt/async/browser/posix_key_provider.h" #endif #if BUILDFLAG(IS_MAC) #include "components/os_crypt/async/browser/keychain_key_provider.h" #endif #if BUILDFLAG(SAFE_BROWSING_AVAILABLE) #include "base/memory/scoped_refptr.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "components/os_crypt/async/common/encryptor.h" #endif #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) // How often to check if the persistent instance of Chrome needs to restart // to install an update. static const int kUpdateCheckIntervalHours = 6; #endif // LINT.IfChange(EndSessionTimeout) #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_OZONE) || BUILDFLAG(IS_MAC) // How long to wait for the File thread to complete during EndSession on // Windows, Linux, and macOS. A timeout is used here because the UI message // loop cannot run and there is some deadlock risk. The only option is to exit // anyway. // Note: On macOS, shutdown_watchdog_mac.cc relies on this timeout budget. static constexpr base::TimeDelta kEndSessionTimeout = base::Seconds(10); #endif // LINT.ThenChange(//chrome/browser/shutdown_watchdog_mac.cc:EndSessionTimeout) using content::BrowserThread; using content::ChildProcessSecurityPolicy; BrowserProcessImpl::BrowserProcessImpl(StartupData* startup_data) : startup_data_(startup_data), browser_policy_connector_(startup_data->chrome_feature_list_creator() ->TakeChromeBrowserPolicyConnector()), local_state_( startup_data->chrome_feature_list_creator()->TakePrefService()), active_primary_accounts_metrics_recorder_( std::make_unique( *local_state_)), #if BUILDFLAG(IS_ANDROID) device_parental_controls_( std::make_unique()), #else device_parental_controls_( std::make_unique()), #endif platform_part_(std::make_unique()), network_time_tracker_(startup_data->chrome_feature_list_creator() ->TakeNetworkTimeTracker()), features_(GlobalFeatures::CreateGlobalFeatures()) { CHECK(!g_browser_process); g_browser_process = this; features_->Init(); DCHECK(browser_policy_connector_); DCHECK(local_state_); DCHECK(startup_data); // The network time tracker is created (so that other early objects can // subscribe to it) but it is not yet initialized. CHECK(network_time_tracker_); // Most work should be done in Init(). } ui::UnownedUserDataHost& BrowserProcessImpl::GetUnownedUserDataHost() { return unowned_user_data_host_; } const ui::UnownedUserDataHost& BrowserProcessImpl::GetUnownedUserDataHost() const { return unowned_user_data_host_; } void BrowserProcessImpl::Init() { #if BUILDFLAG(IS_ANDROID) device_parental_controls_->Init(); #endif #if BUILDFLAG(IS_CHROMEOS) // Forces creation of |metrics_services_manager_client_| if necessary // (typically this call is a no-op as MetricsServicesManager has already been // created). GetMetricsServicesManager(); DCHECK(metrics_services_manager_client_); metrics_services_manager_client_->OnCrosSettingsCreated(); #endif download_status_updater_ = std::make_unique(); #if BUILDFLAG(ENABLE_PRINTING) print_job_manager_ = std::make_unique(); #endif #if !BUILDFLAG(IS_ANDROID) if (!base::FeatureList::IsEnabled(features::kInstantUsesSpareRenderer)) { ChildProcessSecurityPolicy::GetInstance()->RegisterWebSafeScheme( chrome::kChromeSearchScheme); } else { ChildProcessSecurityPolicy::GetInstance()->RegisterWebSafeIsolatedScheme( chrome::kChromeSearchScheme); } #endif #if BUILDFLAG(IS_MAC) ui::InitIdleMonitor(); #endif #if BUILDFLAG(ENABLE_EXTENSIONS_CORE) EnsureExtensionsClientInitialized(); // Initialize the ExtensionsBrowserClient. This isn't in extension-specific // code because a number of external concepts that extensions shouldn't know // about leverage the extensions system, such as platform apps and controlled // frame. On Android the ExtensionsBrowserClient is created elsewhere, // as BrowserContextKeyedServices are initialized earlier on Android. However, // ownership is transferred here, as this object lives long into shutdown, and // ExtensionsBrowserClient must also live during most of shutdown. // TODO(devlin): Move this block out of BrowserProcessImpl to somewhere like // //chrome/browser/initialize_extensions_browser_client, analogous to // `EnsureExtensionsClientInitialized()` above? #if BUILDFLAG(ENABLE_DESKTOP_ANDROID_EXTENSIONS) extensions_browser_client_ = startup_data()->TakeExtensionsBrowserClient(); #elif BUILDFLAG(ENABLE_EXTENSIONS) extensions_browser_client_ = std::make_unique(); #else // Neither ENABLE_EXTENSIONS nor ENABLE_DESKTOP_ANDROID_EXTENSIONS are // enabled. Unknown configuration. #error "Unknown configuration." #endif extensions_browser_client_->Init(); #if BUILDFLAG(ENABLE_PLATFORM_APPS) extensions_browser_client_->AddAPIProvider( std::make_unique()); extensions::AppWindowClient::Set(ChromeAppWindowClient::GetInstance()); #endif // BUILDFLAG(ENABLE_PLATFORM_APPS) #if BUILDFLAG(ENABLE_EXTENSIONS) extensions_browser_client_->AddAPIProvider( std::make_unique< controlled_frame::ControlledFrameExtensionsBrowserAPIProvider>()); #endif // BUILDFLAG(ENABLE_EXTENSIONS) #if BUILDFLAG(IS_CHROMEOS) extensions_browser_client_->AddAPIProvider( std::make_unique()); extensions_browser_client_->AddAPIProvider( std::make_unique< chromeos::ChromeOSTelemetryExtensionsBrowserAPIProvider>()); #endif // BUILDFLAG(IS_CHROMEOS) extensions::ExtensionsBrowserClient::Set(extensions_browser_client_.get()); #endif // BUILDFLAG(ENABLE_EXTENSIONS_CORE) #if BUILDFLAG(ENABLE_CHROME_NOTIFICATIONS) message_center::MessageCenter::Initialize(); // Set the system notification source display name ("Google Chrome" or // "Chromium"). if (message_center::MessageCenter::Get()) { message_center::MessageCenter::Get()->SetSystemNotificationAppName( l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); } #endif system_notification_helper_ = std::make_unique(); update_client::UpdateQueryParams::SetDelegate( ChromeUpdateQueryParamsDelegate::GetInstance()); // Make sure permissions client has been set. ChromePermissionsClient::GetInstance(); // Make sure media session client has been set. ChromeMediaSessionClient::GetInstance(); // Make sure webapps client has been set. #if BUILDFLAG(IS_ANDROID) webapps::WebappsClientAndroid::CreateSingleton(); #else webapps::WebappsClientDesktop::CreateSingleton(); #endif #if !BUILDFLAG(IS_ANDROID) web_app::InitializeIsolatedWebAppRuntime(base::PassKey()); #endif #if !BUILDFLAG(IS_ANDROID) KeepAliveRegistry::GetInstance()->SetIsShuttingDown(false); KeepAliveRegistry::GetInstance()->AddObserver(this); #endif // !BUILDFLAG(IS_ANDROID) MigrateObsoleteLocalStatePrefs(local_state()); pref_change_registrar_.Init(local_state()); #if BUILDFLAG(IS_ANDROID) chrome_browser_prefs::OnLocalStatePrefsLoaded(); #endif // Initialize the notification for the default browser setting policy. pref_change_registrar_.Add( prefs::kDefaultBrowserSettingEnabled, base::BindRepeating(&BrowserProcessImpl::ApplyDefaultBrowserPolicy, base::Unretained(this))); // This preference must be kept in sync with external values; update them // whenever the preference or its controlling policy changes. pref_change_registrar_.Add( metrics::prefs::kMetricsReportingEnabled, base::BindRepeating(&metrics::ApplyMetricsReportingPolicy)); #if !BUILDFLAG(IS_ANDROID) pref_change_registrar_.Add( prefs::kDevToolsRemoteDebuggingAllowed, base::BindRepeating( &BrowserProcessImpl::OnDevToolsRemoteDebuggingAllowedChanged, base::Unretained(this))); #endif #if BUILDFLAG(IS_WIN) // If the user pref on disk differs from the actual trusted state, it means // either the registry was modified out-of-band, or the untrusted JSON was // tampered with. In either case, the user pref is untrusted. Clear it to // prevent an attacker from bypassing the trusted state when there is no // policy. const base::Value* user_value = local_state()->GetUserPrefValue(prefs::kProcessIsolationEnabled); if (user_value && user_value->GetIfBool().value_or(false) != chrome::IsIsolationEnabled()) { local_state()->ClearPref(prefs::kProcessIsolationEnabled); } // After potentially clearing the untrusted user value, if the effective value // of the pref (which now comes from policies, or a trusted user value, or // default) differs from the actual state, queue a state update. if (local_state()->GetBoolean(prefs::kProcessIsolationEnabled) != chrome::IsIsolationEnabled()) { UpdateProcessIsolationState(); } pref_change_registrar_.Add( prefs::kProcessIsolationEnabled, base::BindRepeating(&BrowserProcessImpl::UpdateProcessIsolationState, base::Unretained(this))); #endif // BUILDFLAG(IS_WIN) DCHECK(!webrtc_event_log_manager_); webrtc_event_log_manager_ = WebRtcEventLogManager::CreateSingletonInstance(); #if BUILDFLAG(IS_ANDROID) webauthn::WebAuthnClientAndroid::SetClient( std::make_unique()); #endif accessibility_prefs_controller_ = std::make_unique( local_state()); #if !BUILDFLAG(IS_ANDROID) #if BUILDFLAG(IS_CHROMEOS) hid_system_tray_icon_ = std::make_unique(); usb_system_tray_icon_ = std::make_unique(); #else hid_system_tray_icon_ = std::make_unique(); usb_system_tray_icon_ = std::make_unique(); #endif // BUILDFLAG(IS_CHROMEOS) #endif // !BUILDFLAG(IS_ANDROID) features_->PostBrowserProcessInit(); // `Unretained` is safe as CallbackListSubscription does not outlive `this`. on_locale_changed_callback_subscription_ = features_->application_locale_storage()->RegisterOnLocaleChangedCallback( base::BindRepeating(&BrowserProcessImpl::OnLocaleChanged, base::Unretained(this))); // Initialize the locale. const std::string& locale = startup_data_->chrome_feature_list_creator()->actual_locale(); CHECK(!locale.empty()); features_->application_locale_storage()->Set(locale); } #if !BUILDFLAG(IS_ANDROID) void BrowserProcessImpl::SetQuitClosure(base::OnceClosure quit_closure) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(quit_closure); DCHECK(!quit_closure_); quit_closure_ = std::move(quit_closure); } #endif #if BUILDFLAG(IS_MAC) void BrowserProcessImpl::ClearQuitClosure() { quit_closure_.Reset(); } #endif BrowserProcessImpl::~BrowserProcessImpl() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); #if BUILDFLAG(ENABLE_EXTENSIONS) extensions::ExtensionsBrowserClient::Set(nullptr); #endif #if BUILDFLAG(ENABLE_PLATFORM_APPS) extensions::AppWindowClient::Set(nullptr); #endif #if !BUILDFLAG(IS_ANDROID) KeepAliveRegistry::GetInstance()->RemoveObserver(this); #endif g_browser_process = nullptr; } #if !BUILDFLAG(IS_ANDROID) void BrowserProcessImpl::StartTearDown() { #if BUILDFLAG(IS_MAC) // Emergency bound on UI-initiated shutdown; see shutdown_watchdog_mac.h. shutdown_watchdog::OnBrowserTearDownStarted(); #endif TRACE_EVENT0("shutdown", "BrowserProcessImpl::StartTearDown"); // TODO(crbug.com/41222012): Fix the tests that make the check of // |tearing_down_| necessary in IsShuttingDown(). tearing_down_ = true; DCHECK(IsShuttingDown()); features_->PostMainMessageLoopRun(); metrics_services_manager_client_ = nullptr; metrics_services_manager_.reset(); intranet_redirect_detector_.reset(); #if BUILDFLAG(SAFE_BROWSING_AVAILABLE) if (safe_browsing_service_.get()) { safe_browsing_service()->ShutDown(); } #endif network_time_tracker_.reset(); #if !BUILDFLAG(IS_CHROMEOS) // Initial cleanup for ChromeBrowserCloudManagement, shutdown components that // depend on profile and notification system. For example, ProfileManager // observer and KeyServices observer need to be removed before profiles. auto* cloud_management_controller = browser_policy_connector_->chrome_browser_cloud_management_controller(); if (cloud_management_controller) { cloud_management_controller->ShutDown(); } #endif // !BUILDFLAG(IS_CHROMEOS) // `hid_system_tray_icon_` and `usb_system_tray_icon_` must be destroyed // before `system_notification_helper_` for ChromeOS and `status_tray_` for // non-ChromeOS, and before `profile_manager_`. hid_system_tray_icon_.reset(); usb_system_tray_icon_.reset(); system_notification_helper_.reset(); #if BUILDFLAG(ENABLE_CHROME_NOTIFICATIONS) // Need to clear the desktop notification balloons before the IO thread and // before the profiles, since if there are any still showing we will access // those things during teardown. notification_ui_manager_.reset(); #endif // BUILDFLAG(ENABLE_CHROME_NOTIFICATIONS) // Debugger must be cleaned up before ProfileManager. remote_debugging_server_.reset(); devtools_auto_opener_.reset(); battery_metrics_.reset(); #if BUILDFLAG(ENABLE_EXTENSIONS_CORE) // The Extensions Browser Client needs to teardown some members while the // profile manager is still alive. extensions_browser_client_->StartTearDown(); #endif // BUILDFLAG(ENABLE_EXTENSIONS_CORE) // Need to clear profiles (download managers) before the IO thread. { TRACE_EVENT0("shutdown", "BrowserProcessImpl::StartTearDown:ProfileManager"); #if !BUILDFLAG(IS_CHROMEOS) // The desktop profile picker needs to be closed before the guest profile // can be destroyed. ProfilePicker::Hide(); #endif // !BUILDFLAG(IS_CHROMEOS) // `profile_manager_` must be destroyed before `background_mode_manager_`, // because the background mode manager does not stop observing profile // changes at destruction (notifying the observers would cause a use-after- // free). #if BUILDFLAG(IS_MAC) // Scoped: the key must clear when this phase completes so later dumps // don't misattribute hangs to a finished phase. static crash_reporter::CrashKeyString<64> mac_teardown_phase_key( "mac_teardown_phase"); crash_reporter::ScopedCrashKeyString scoped_teardown_phase( &mac_teardown_phase_key, "profile_manager_reset"); #endif profile_manager_.reset(); } if (media_router::DualMediaSinkService::HasInstance()) { media_router::DualMediaSinkService::GetInstance() ->StopObservingPrefChanges(); } #if BUILDFLAG(IS_CHROMEOS) // The `media_file_system_registry_` cannot be reset until the // `profile_manager_` has been. media_file_system_registry_.reset(); #endif #if BUILDFLAG(ENABLE_EXTENSIONS) // Remove the global instance of the Storage Monitor now. Otherwise the // FILE thread would be gone when we try to release it in the dtor and // Valgrind would report a leak on almost every single browser_test. // TODO(gbillock): Make this unnecessary. storage_monitor::StorageMonitor::Destroy(); #endif // BUILDFLAG(ENABLE_EXTENSIONS) #if BUILDFLAG(ENABLE_CHROME_NOTIFICATIONS) if (message_center::MessageCenter::Get()) { message_center::MessageCenter::Shutdown(); } #endif // BUILDFLAG(ENABLE_CHROME_NOTIFICATIONS) // The policy providers managed by |browser_policy_connector_| need to shut // down while the IO and FILE threads are still alive. The monitoring // framework owned by |browser_policy_connector_| relies on |gcm_driver_|, so // this must be shutdown before |gcm_driver_| below. browser_policy_connector_->Shutdown(); // The |gcm_driver_| must shut down while the IO thread is still alive. if (gcm_driver_) { gcm_driver_->Shutdown(); } platform_part()->StartTearDown(); // Cancel any uploads to release the system url request context references. if (webrtc_log_uploader_) { webrtc_log_uploader_->Shutdown(); } sessions::SessionIdGenerator::GetInstance()->Shutdown(); // Resetting the status tray will result in calls to // |g_browser_process->local_state()|. See crbug.com/40754301 status_tray_.reset(); local_state_->CommitPendingWrite(); // This expects to be destroyed before the task scheduler is torn down. SystemNetworkContextManager::DeleteInstance(); if (component_updater_) { component_updater_->Stop(); } // The ApplicationBreadcrumbsLogger logs a shutdown event via a task when it // is destroyed, so it should be destroyed before the task scheduler is torn // down. application_breadcrumbs_logger_.reset(); } #endif // !BUILDFLAG(IS_ANDROID) #if !BUILDFLAG(IS_ANDROID) void BrowserProcessImpl::PostDestroyThreads() { platform_part_->PostDestroyThreads(); // With the file_thread_ flushed, we can release any icon resources. icon_manager_.reset(); // Must outlive the worker threads. webrtc_log_uploader_.reset(); // ResourceCoordinatorParts owns TabLifecycleUnitSource, which depends on a // Global Feature (GlobalBrowserCollection). Thus, we need to make sure // ResourceCoordinatorParts is destroyed before GlobalFeatures is completely // shut down. resource_coordinator_parts_.reset(); #if BUILDFLAG(ENABLE_BACKGROUND_MODE) // BackgroundModeManager observes GlobalBrowserCollection, a Global Feature. // Thus, we need to make sure BackgroundModeManager is destroyed before // GlobalFeatures is completely shut down. background_mode_manager_.reset(); #endif features_->PostDestroyThreads(); } #endif // !BUILDFLAG(IS_ANDROID) void BrowserProcessImpl::SetMetricsServices( std::unique_ptr manager, metrics_services_manager::MetricsServicesManagerClient* client) { metrics_services_manager_ = std::move(manager); metrics_services_manager_client_ = static_cast(client); } namespace { // Used at the end of session to block the UI thread for completion of sentinel // tasks on the set of threads used to persist profile data and local state. // This is done to ensure that the data has been persisted to disk before // continuing. class RundownTaskCounter : public base::RefCountedThreadSafe { public: RundownTaskCounter(); RundownTaskCounter(const RundownTaskCounter&) = delete; RundownTaskCounter& operator=(const RundownTaskCounter&) = delete; // Increments |count_| and returns a closure bound to Decrement(). All // closures returned by this RundownTaskCounter's GetRundownClosure() method // must be invoked for TimedWait() to complete its wait without timing // out. base::OnceClosure GetRundownClosure(); // Waits until the count is zero or |timeout| expires. // This can only be called once per instance. void TimedWait(base::TimeDelta timeout); private: friend class base::RefCountedThreadSafe; ~RundownTaskCounter() = default; // Decrements the counter and releases the waitable event on transition to // zero. void Decrement(); // The count starts at one to defer the possibility of one->zero transitions // until TimedWait is called. base::AtomicRefCount count_{1}; base::WaitableEvent waitable_event_; }; RundownTaskCounter::RundownTaskCounter() = default; base::OnceClosure RundownTaskCounter::GetRundownClosure() { // As the count starts off at one, it should never get to zero unless // TimedWait has been called. DCHECK(!count_.IsZero()); count_.Increment(); return base::BindOnce(&RundownTaskCounter::Decrement, this); } void RundownTaskCounter::Decrement() { if (!count_.Decrement()) { waitable_event_.Signal(); } } void RundownTaskCounter::TimedWait(base::TimeDelta timeout) { // Decrement the excess count from the constructor. Decrement(); // RundownTaskCounter::TimedWait() could return // |waitable_event_.TimedWait()|'s result if any user ever cared about whether // it returned per success or timeout. Currently no user of this API cares and // as such this return value is ignored. waitable_event_.TimedWait(timeout); } #if !BUILDFLAG(IS_ANDROID) void RequestProxyResolvingSocketFactoryOnUIThread( mojo::PendingReceiver receiver) { network::mojom::NetworkContext* network_context = g_browser_process->system_network_context_manager()->GetContext(); network_context->CreateProxyResolvingSocketFactory(std::move(receiver)); } void RequestProxyResolvingSocketFactory( mojo::PendingReceiver receiver) { content::GetUIThreadTaskRunner({})->PostTask( FROM_HERE, base::BindOnce(&RequestProxyResolvingSocketFactoryOnUIThread, std::move(receiver))); } #endif } // namespace void BrowserProcessImpl::EndSession() { // Mark all the profiles as clean. ProfileManager* pm = profile_manager(); scoped_refptr rundown_counter = base::MakeRefCounted(); for (Profile* profile : pm->GetLoadedProfiles()) { #if BUILDFLAG(ENABLE_SESSION_SERVICE) ExitTypeService* exit_type_service = ExitTypeService::GetInstanceForProfile(profile); if (exit_type_service) { exit_type_service->SetCurrentSessionExitType(ExitType::kForcedShutdown); } #endif if (profile->GetPrefs()) { profile->GetPrefs()->CommitPendingWrite( base::OnceClosure(), rundown_counter->GetRundownClosure()); } } // Tell the metrics service it was cleanly shutdown. metrics::MetricsService* metrics = g_browser_process->metrics_service(); if (metrics) { metrics->LogCleanShutdown(); #if !BUILDFLAG(IS_CHROMEOS) // The MetricsService may update Local State prefs in memory without // writing the updated prefs to disk, so schedule a Local State write now. // // Do not schedule a write on ChromeOS because writing to disk multiple // times during shutdown was causing shutdown problems. See // crbug.com/41062061. local_state_->CommitPendingWrite(base::OnceClosure(), rundown_counter->GetRundownClosure()); #endif } // This wait is legitimate and necessary on Windows, since the process will // be terminated soon. // http://crbug.com/40198606 base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait; #if BUILDFLAG(IS_CHROMEOS_DEVICE) // The browser is already shutting down, so the DeleteFile inside // DeleteCrashpadIsReadyFile cannot causing UI jank. Also, this code // cannot use other MayBlock threads, as the process will be disappearing // momentarily. { base::ScopedAllowBlocking allow_delete; // Crashes after this point will generate a bunch of unnecessary work // in crash reporter, so call this function as late as possible, after // approximately everything that can crash is complete. crash_reporter::DeleteCrashpadIsReadyFile(); } #endif // The profile and metrics service must be recorded as shutting down cleanly, // otherwise startup will treat it as a crash. The thread blocks until done // and then proceeds with normal shutdown. // // If you change the condition here, be sure to also change // ProfileBrowserTests to match. // LINT.IfChange(EndSessionPlatforms) #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_OZONE) || BUILDFLAG(IS_MAC) // Do a best-effort wait on the successful countdown of rundown tasks. Note // that if shutdown does not complete quickly enough, the OS (Windows or // macOS/launchd) will terminate the process. // // On Windows, we previously posted a message to FILE and then ran a nested // message loop, waiting for that message to be processed until quitting. // However, doing so means that other messages will also be processed. In // particular, if the GPU process host notices that the GPU has been killed // during shutdown, it races exiting the nested loop with the process host // blocking the message loop attempting to re-establish a connection to the // GPU process synchronously. Because the system may not be allowing // processes to launch, this can result in a hang. See // http://crbug.com/40341017. rundown_counter->TimedWait(kEndSessionTimeout); #else NOTIMPLEMENTED(); #endif // LINT.ThenChange(//chrome/browser/profiles/profile_browsertest.cc:EndSessionPlatforms) } metrics_services_manager::MetricsServicesManager* BrowserProcessImpl::GetMetricsServicesManager() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Only create the objects if teardown hasn't started yet, as otherwise these // may have already been destroyed. if (!metrics_services_manager_ && !tearing_down_) { auto client = std::make_unique(local_state()); metrics_services_manager_client_ = client.get(); metrics_services_manager_ = std::make_unique( std::move(client)); } return metrics_services_manager_.get(); } metrics::MetricsService* BrowserProcessImpl::metrics_service() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); auto* metrics_services_manager = GetMetricsServicesManager(); if (metrics_services_manager) { return metrics_services_manager->GetMetricsService(); } return nullptr; } embedder_support::OriginTrialsSettingsStorage* BrowserProcessImpl::GetOriginTrialsSettingsStorage() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!origin_trials_settings_storage_) { origin_trials_settings_storage_ = std::make_unique(); } return origin_trials_settings_storage_.get(); } SystemNetworkContextManager* BrowserProcessImpl::system_network_context_manager() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(SystemNetworkContextManager::GetInstance()); return SystemNetworkContextManager::GetInstance(); } scoped_refptr BrowserProcessImpl::shared_url_loader_factory() { return system_network_context_manager()->GetSharedURLLoaderFactory(); } network::NetworkQualityTracker* BrowserProcessImpl::network_quality_tracker() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!network_quality_tracker_) { network_quality_tracker_ = std::make_unique( base::BindRepeating(&content::GetNetworkService)); } return network_quality_tracker_.get(); } ProfileManager* BrowserProcessImpl::profile_manager() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!created_profile_manager_) { CreateProfileManager(); } return profile_manager_.get(); } PrefService* BrowserProcessImpl::local_state() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return local_state_.get(); } signin::ActivePrimaryAccountsMetricsRecorder* BrowserProcessImpl::active_primary_accounts_metrics_recorder() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return active_primary_accounts_metrics_recorder_.get(); } variations::VariationsService* BrowserProcessImpl::variations_service() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); auto* metrics_services_manager = GetMetricsServicesManager(); if (metrics_services_manager) { return metrics_services_manager->GetVariationsService(); } return nullptr; } BrowserProcessPlatformPart* BrowserProcessImpl::platform_part() { return platform_part_.get(); } NotificationUIManager* BrowserProcessImpl::notification_ui_manager() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); #if BUILDFLAG(ENABLE_CHROME_NOTIFICATIONS) if (!created_notification_ui_manager_ && !shutting_down_) { CreateNotificationUIManager(); } return notification_ui_manager_.get(); #else return nullptr; #endif } NotificationPlatformBridge* BrowserProcessImpl::notification_platform_bridge() { if (!created_notification_bridge_) { CreateNotificationPlatformBridge(); } return notification_bridge_.get(); } policy::ChromeBrowserPolicyConnector* BrowserProcessImpl::browser_policy_connector() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return browser_policy_connector_.get(); } policy::PolicyService* BrowserProcessImpl::policy_service() { return browser_policy_connector()->GetPolicyService(); } IconManager* BrowserProcessImpl::icon_manager() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!created_icon_manager_) { CreateIconManager(); } return icon_manager_.get(); } GpuModeManager* BrowserProcessImpl::gpu_mode_manager() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!gpu_mode_manager_) { gpu_mode_manager_ = std::make_unique(); } return gpu_mode_manager_.get(); } void BrowserProcessImpl::CreateDevToolsProtocolHandler() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); #if !BUILDFLAG(IS_ANDROID) auto maybe_remote_debugging_server = RemoteDebuggingServer::GetInstance(local_state_.get()); if (maybe_remote_debugging_server.has_value()) { remote_debugging_server_ = std::move(*maybe_remote_debugging_server); return; } // For errors, follow content/browser/devtools/devtools_http_handler.cc that // reports its remote debugging port on stderr for symmetry. switch (maybe_remote_debugging_server.error()) { case RemoteDebuggingServer::NotStartedReason::kNotRequested: break; case RemoteDebuggingServer::NotStartedReason::kDisabledByPolicy: fprintf( stderr, "%s", "\nDevTools remote debugging is disallowed by the system admin.\n"); fflush(stderr); break; case RemoteDebuggingServer::NotStartedReason::kDisabledByDefaultUserDataDir: fprintf( stderr, "%s", "\nDevTools remote debugging requires a non-default data directory. " "Specify this using --user-data-dir.\n"); fflush(stderr); break; } #endif } #if !BUILDFLAG(IS_ANDROID) void BrowserProcessImpl::OnDevToolsRemoteDebuggingAllowedChanged() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // On policy change to disallowed, immediately shut down the server cancelling // all active debugging sessions, while keeping listeners alive. Also clear // the user preference so that when the policy is dynamically allowed again, // the UI reflects the disabled state and an explicit user action is required // to restart. if (!local_state()->GetBoolean(prefs::kDevToolsRemoteDebuggingAllowed)) { local_state()->ClearPref(prefs::kDevToolsRemoteDebuggingEnabled); if (remote_debugging_server_) { remote_debugging_server_->StopServer(); fprintf( stderr, "%s", "\nDevTools remote debugging is disallowed by the system admin.\n"); fflush(stderr); } } } #endif void BrowserProcessImpl::CreateDevToolsAutoOpener() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); #if !BUILDFLAG(IS_ANDROID) // StartupBrowserCreator::LaunchBrowser can be run multiple times when browser // is started with several profiles or existing browser process is reused. if (!devtools_auto_opener_) { devtools_auto_opener_ = std::make_unique(); } #endif } bool BrowserProcessImpl::IsShuttingDown() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // TODO (crbug.com/41222012): Fix the tests that make the check of // |tearing_down_| necessary here. // TODO (crbug.com/40160014): Maybe use browser_shutdown::HasShutdownStarted // here. return shutting_down_ || tearing_down_; } printing::PrintJobManager* BrowserProcessImpl::print_job_manager() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); #if BUILDFLAG(ENABLE_PRINTING) return print_job_manager_.get(); #else NOTREACHED(); #endif } printing::PrintPreviewDialogController* BrowserProcessImpl::print_preview_dialog_controller() { #if BUILDFLAG(ENABLE_PRINT_PREVIEW) DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!print_preview_dialog_controller_.get()) { CreatePrintPreviewDialogController(); } return print_preview_dialog_controller_.get(); #else NOTIMPLEMENTED(); return NULL; #endif } printing::BackgroundPrintingManager* BrowserProcessImpl::background_printing_manager() { #if BUILDFLAG(ENABLE_PRINT_PREVIEW) DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!background_printing_manager_) { CreateBackgroundPrintingManager(); } return background_printing_manager_.get(); #else NOTIMPLEMENTED(); return NULL; #endif } supervised_user::DeviceParentalControls& BrowserProcessImpl::device_parental_controls() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return *device_parental_controls_; } #if !BUILDFLAG(IS_ANDROID) IntranetRedirectDetector* BrowserProcessImpl::intranet_redirect_detector() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!intranet_redirect_detector_) { intranet_redirect_detector_ = std::make_unique(); } return intranet_redirect_detector_.get(); } #endif const std::string& BrowserProcessImpl::GetApplicationLocale() { #if !BUILDFLAG(IS_CHROMEOS) // TODO(crbug.com/40663419): Remove #if. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); #endif // TODO(crbug.com/407681800): Replace this with CHECK(features_) once we've // confirmed no such code path exists. if (!features_) { return startup_data_->chrome_feature_list_creator()->actual_locale(); } CHECK(features_->application_locale_storage()); const std::string& locale = features_->application_locale_storage()->Get(); DCHECK(!locale.empty()); return locale; } void BrowserProcessImpl::SetApplicationLocale( const std::string& actual_locale) { CHECK(features_); CHECK(features_->application_locale_storage()); features_->application_locale_storage()->Set(actual_locale); } DownloadStatusUpdater* BrowserProcessImpl::download_status_updater() { return download_status_updater_.get(); } #if BUILDFLAG(IS_CHROMEOS) MediaFileSystemRegistry* BrowserProcessImpl::media_file_system_registry() { if (!media_file_system_registry_) { media_file_system_registry_ = std::make_unique(); } return media_file_system_registry_.get(); } #endif WebRtcLogUploader* BrowserProcessImpl::webrtc_log_uploader() { if (!webrtc_log_uploader_) { webrtc_log_uploader_ = std::make_unique(); } return webrtc_log_uploader_.get(); } network_time::NetworkTimeTracker* BrowserProcessImpl::network_time_tracker() { return network_time_tracker_.get(); } #if !BUILDFLAG(IS_ANDROID) gcm::GCMDriver* BrowserProcessImpl::gcm_driver() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!gcm_driver_) { CreateGCMDriver(); } return gcm_driver_.get(); } #endif resource_coordinator::TabManager* BrowserProcessImpl::GetTabManager() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return resource_coordinator_parts()->tab_manager(); } resource_coordinator::ResourceCoordinatorParts* BrowserProcessImpl::resource_coordinator_parts() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!resource_coordinator_parts_) { resource_coordinator_parts_ = std::make_unique(); } return resource_coordinator_parts_.get(); } SerialPolicyAllowedPorts* BrowserProcessImpl::serial_policy_allowed_ports() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!serial_policy_allowed_ports_) { serial_policy_allowed_ports_ = std::make_unique(local_state()); } return serial_policy_allowed_ports_.get(); } #if !BUILDFLAG(IS_ANDROID) HidSystemTrayIcon* BrowserProcessImpl::hid_system_tray_icon() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return hid_system_tray_icon_.get(); } void BrowserProcessImpl::set_hid_system_tray_icon_for_test( std::unique_ptr icon) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); hid_system_tray_icon_ = std::move(icon); } UsbSystemTrayIcon* BrowserProcessImpl::usb_system_tray_icon() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return usb_system_tray_icon_.get(); } void BrowserProcessImpl::set_usb_system_tray_icon_for_test( std::unique_ptr icon) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); usb_system_tray_icon_ = std::move(icon); } #endif os_crypt_async::OSCryptAsync* BrowserProcessImpl::os_crypt_async() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return os_crypt_async_.get(); } void BrowserProcessImpl::set_additional_os_crypt_async_provider_for_test( size_t precedence, std::unique_ptr provider) { CHECK(!additional_provider_for_test_); CHECK(!os_crypt_async_); additional_provider_for_test_.emplace( std::make_pair(precedence, std::move(provider))); } BuildState* BrowserProcessImpl::GetBuildState() { #if !BUILDFLAG(IS_ANDROID) DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return &build_state_; #else NOTIMPLEMENTED(); return nullptr; #endif } // static void BrowserProcessImpl::RegisterPrefs(PrefRegistrySimple* registry) { registry->RegisterBooleanPref(prefs::kDefaultBrowserSettingEnabled, false); registry->RegisterBooleanPref(prefs::kAllowCrossOriginAuthPrompt, false); #if BUILDFLAG(IS_WIN) // Isolation state is determined dynamically at startup based on the system // configuration. registry->RegisterBooleanPref(prefs::kProcessIsolationEnabled, chrome::IsIsolationEnabled()); #endif // BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) registry->RegisterBooleanPref(prefs::kEulaAccepted, false); #endif // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) registry->RegisterStringPref(language::prefs::kApplicationLocale, std::string()); #if BUILDFLAG(IS_CHROMEOS) registry->RegisterStringPref(ash::prefs::kOwnerLocale, std::string()); registry->RegisterStringPref(ash::prefs::kHardwareKeyboardLayout, std::string()); registry->RegisterBooleanPref( password_manager::prefs::kPinAuthenticationAvailableOnChromeOS, false); #endif // BUILDFLAG(IS_CHROMEOS) registry->RegisterBooleanPref(metrics::prefs::kMetricsReportingEnabled, GoogleUpdateSettings::GetCollectStatsConsent()); registry->RegisterBooleanPref(prefs::kDevToolsRemoteDebuggingAllowed, true); registry->RegisterBooleanPref(prefs::kDevToolsRemoteDebuggingEnabled, false); #if BUILDFLAG(IS_LINUX) && BUILDFLAG(USE_DBUS) os_crypt_async::SecretPortalKeyProvider::RegisterLocalPrefs(registry); #endif } GlobalFeatures* BrowserProcessImpl::GetFeatures() { return features_.get(); } #if !BUILDFLAG(IS_ANDROID) speech::SpeechRecognitionSmallExpertModelInstaller* BrowserProcessImpl::speech_recognition_small_expert_model_installer() { return speech_recognition_small_expert_model_installer_.get(); } #endif DownloadRequestLimiter* BrowserProcessImpl::download_request_limiter() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!download_request_limiter_.get()) { download_request_limiter_ = base::MakeRefCounted(); } return download_request_limiter_.get(); } #if BUILDFLAG(ENABLE_BACKGROUND_MODE) BackgroundModeManager* BrowserProcessImpl::background_mode_manager() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!background_mode_manager_) { CreateBackgroundModeManager(); } return background_mode_manager_.get(); } void BrowserProcessImpl::set_background_mode_manager_for_test( std::unique_ptr manager) { background_mode_manager_ = std::move(manager); } #endif StatusTray* BrowserProcessImpl::status_tray() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!status_tray_) { CreateStatusTray(); } return status_tray_.get(); } #if BUILDFLAG(SAFE_BROWSING_AVAILABLE) safe_browsing::SafeBrowsingService* BrowserProcessImpl::safe_browsing_service() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!created_safe_browsing_service_) { CreateSafeBrowsingService(); } return safe_browsing_service_.get(); } #endif subresource_filter::RulesetService* BrowserProcessImpl::subresource_filter_ruleset_service() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!created_subresource_filter_ruleset_service_) { CreateSubresourceFilterRulesetService(); } return subresource_filter_ruleset_service_.get(); } StartupData* BrowserProcessImpl::startup_data() { return startup_data_; } #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) void BrowserProcessImpl::StartAutoupdateTimer() { autoupdate_timer_.Start(FROM_HERE, base::Hours(kUpdateCheckIntervalHours), this, &BrowserProcessImpl::OnAutoupdateTimer); } #endif activity_reporter::ActivityReporter* BrowserProcessImpl::activity_reporter() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!activity_reporter_) { activity_reporter_ = activity_reporter::CreateActivityReporter( base::BindRepeating( [](PrefService* pref_service) { return pref_service; }, local_state()), base::MakeRefCounted( system_network_context_manager()->GetSharedURLLoaderFactory(), // Never send cookies for activity reports. base::BindRepeating([](const GURL& url) { return false; })), base::BindRepeating(&chrome::GetChannel), base::BindRepeating([] { std::string brand; google_brand::GetBrand(&brand); return brand; }), base::BindRepeating(&updater::SetActive), #if BUILDFLAG(IS_WIN) InstallUtil::IsPerUserInstall() #else false #endif ); } return activity_reporter_.get(); } component_updater::ComponentUpdateService* BrowserProcessImpl::component_updater() { if (component_updater_) { return component_updater_.get(); } if (!BrowserThread::CurrentlyOn(BrowserThread::UI) || tearing_down_) { return nullptr; } std::unique_ptr scheduler = std::make_unique(); std::string brand; google_brand::GetBrand(&brand); component_updater_ = component_updater::ComponentUpdateServiceFactory( component_updater::MakeChromeComponentUpdaterConfigurator( base::CommandLine::ForCurrentProcess(), g_browser_process->local_state()), std::move(scheduler), brand); return component_updater_.get(); } void BrowserProcessImpl::OnKeepAliveStateChanged(bool is_keeping_alive) { if (is_keeping_alive) { Pin(); } else { Unpin(); } } void BrowserProcessImpl::CreateNetworkQualityObserver() { DCHECK(!network_quality_observer_); network_quality_observer_ = content::CreateNetworkQualityObserver(network_quality_tracker()); DCHECK(network_quality_observer_); } void BrowserProcessImpl::OnKeepAliveRestartStateChanged(bool can_restart) {} void BrowserProcessImpl::CreateProfileManager() { DCHECK(!created_profile_manager_ && !profile_manager_); created_profile_manager_ = true; base::FilePath user_data_dir; base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); profile_manager_ = std::make_unique(user_data_dir); } void BrowserProcessImpl::PreCreateThreads() { #if BUILDFLAG(ENABLE_EXTENSIONS_CORE) // chrome-extension:// URLs are safe to request anywhere, but may only // commit (including in iframes) in extension processes. ChildProcessSecurityPolicy::GetInstance()->RegisterWebSafeIsolatedScheme( extensions::kExtensionScheme); #endif battery_metrics_ = std::make_unique(); #if BUILDFLAG(IS_ANDROID) app_state_listener_ = base::android::ApplicationStatusListener::New( base::BindRepeating([](base::android::ApplicationState state) { content::OnBrowserVisibilityChanged( state == base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES || state == base::android::APPLICATION_STATE_HAS_PAUSED_ACTIVITIES); })); content::OnBrowserVisibilityChanged( base::android::ApplicationStatusListener::HasVisibleActivities()); #endif // BUILDFLAG(IS_ANDROID) secure_origin_prefs_observer_ = std::make_unique(local_state()); site_isolation_prefs_observer_ = std::make_unique(local_state()); // Create SystemNetworkContextManager without a NetworkService if it has not // been requested yet. if (!SystemNetworkContextManager::HasInstance()) { SystemNetworkContextManager::CreateInstance(local_state()); } } #if BUILDFLAG(IS_WIN) void BrowserProcessImpl::UpdateProcessIsolationState() { chrome::SetIsolationState( local_state()->GetBoolean(prefs::kProcessIsolationEnabled) ? chrome::IsolationState::kProcessIsolation : chrome::IsolationState::kIsolationDisabled, local_state(), base::BindOnce(&BrowserProcessImpl::OnProcessIsolationStateSet, base::Unretained(this))); } void BrowserProcessImpl::OnProcessIsolationStateSet( base::expected result) { if (result.has_value()) { return; } // Need to notify the UI that changing the switch hasn't worked, and switch // it back again. However, to avoid reentrancy in the notification and // `UpdateProcessIsolationState` being called again, unregister the // notification before setting the pref. pref_change_registrar_.Remove(prefs::kProcessIsolationEnabled); // Pref is updated to the current isolation state to indicate to the UI when // changing the process isolation state failed. local_state()->SetBoolean(prefs::kProcessIsolationEnabled, chrome::IsIsolationEnabled()); pref_change_registrar_.Add( prefs::kProcessIsolationEnabled, base::BindRepeating(&BrowserProcessImpl::UpdateProcessIsolationState, base::Unretained(this))); } #endif // BUILDFLAG(IS_WIN) void BrowserProcessImpl::PreMainMessageLoopRun() { TRACE_EVENT0("startup", "BrowserProcessImpl::PreMainMessageLoopRun"); // Initialize the SessionIdGenerator instance, providing a PrefService to // ensure the persistent storage of current max SessionId. sessions::SessionIdGenerator::GetInstance()->Init(local_state_.get()); // OSCryptAsync provider configuration. This must run before // `browser_policy_connector_` initialization since implementations like // BrowserPolicyConnectorAsh require an OSCryptAsync. std::vector>> providers; if (additional_provider_for_test_) { // Explicitly move the KeyProvider but leave the std::optional holding the // pair, this ensures it can only be set once in testing. providers.emplace_back( std::get<0>(*additional_provider_for_test_), std::move(std::get<1>(*additional_provider_for_test_))); } #if BUILDFLAG(IS_WIN) // The DPAPI key provider requires os_crypt_async::Init to have already been // called to initialize the key storage. This happens in // ChromeBrowserMainPartsWin::PreCreateMainMessageLoop. providers.emplace_back(std::make_pair( /*precedence=*/10u, std::make_unique(local_state()))); providers.emplace_back(std::make_pair( // Note: 15 is chosen to be higher than the 10 precedence above for // DPAPI. This ensures that when the provider is enabled for // encryption, the App-Bound encryption key is used and not the DPAPI // one. /*precedence=*/15u, std::make_unique( local_state(), /*force_protection_level=*/std::nullopt))); #endif // BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_LINUX) && BUILDFLAG(USE_DBUS) base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); const auto password_store = cmd_line->GetSwitchValueASCII(password_manager::kPasswordStore); if (password_store != "basic") { if (base::FeatureList::IsEnabled(features::kDbusSecretPortal)) { // Use a higher priority than the FreedesktopSecretKeyProvider. providers.emplace_back( /*precedence=*/15u, std::make_unique( local_state(), base::FeatureList::IsEnabled( features::kSecretPortalKeyProviderUseForEncryption))); } } providers.emplace_back( /*precedence=*/10u, std::make_unique( password_store, l10n_util::GetStringUTF8(IDS_PRODUCT_NAME), nullptr)); #endif // BUILDFLAG(IS_LINUX) #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC) // On other POSIX systems, this is the only key provider. On Linux, it is used // as a fallback. providers.emplace_back( /*precedence=*/5u, std::make_unique()); #endif // BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_LINUX) #if BUILDFLAG(IS_MAC) if (base::FeatureList::IsEnabled(features::kUseKeychainKeyProvider)) { providers.emplace_back(std::make_pair( /*precedence=*/10u, std::make_unique())); } #endif // BUILDFLAG(IS_MAC) os_crypt_async_ = std::make_unique(std::move(providers)); // Trigger async initialization of OSCrypt key providers. os_crypt_async_->GetInstance(base::BindOnce( [](base::TimeTicks start_time, scoped_refptr encryptor) { base::UmaHistogramTimes("OSCrypt.AsyncInitialization.Time", base::TimeTicks::Now() - start_time); }, base::TimeTicks::Now())); // browser_policy_connector() is created very early because local_state() // needs policy to be initialized with the managed preference values. // However, policy fetches from the network and loading of disk caches // requires that threads are running; this Init() call lets the connector // resume its initialization now that the loops are spinning and the // system request context is available for the fetchers. browser_policy_connector()->Init( local_state(), system_network_context_manager()->GetSharedURLLoaderFactory()); if (local_state_->IsManagedPreference(prefs::kDefaultBrowserSettingEnabled)) { ApplyDefaultBrowserPolicy(); } metrics::ApplyMetricsReportingPolicy(); #if BUILDFLAG(ENABLE_PLUGINS) content::PluginService::GetInstance()->SetFilter( ChromePluginServiceFilter::GetInstance()); #endif // BUILDFLAG(ENABLE_PLUGINS) #if !BUILDFLAG(IS_ANDROID) ChromeJsErrorReportProcessor::Create(); storage_monitor::StorageMonitor::Create(); #endif features_->PreMainMessageLoopRun(); platform_part_->PreMainMessageLoopRun(); InitializeNetworkTimeTracker(); CreateNetworkQualityObserver(); #if BUILDFLAG(IS_ANDROID) // This needs to be here so that SecurityStateClient is non-null when // SecurityStateModel code is called. security_state::SetSecurityStateClient(new ChromeSecurityStateClient()); #endif // Create the global SodaInstaller instance. #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS) soda_installer_impl_ = std::make_unique(); #endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS) #if BUILDFLAG(IS_CHROMEOS) soda_installer_impl_ = std::make_unique(); #endif // BUILDFLAG(IS_CHROMEOS) #if !BUILDFLAG(IS_ANDROID) screen_ai_download_ = screen_ai::ScreenAIInstallState::Create(); speech_recognition_small_expert_model_installer_ = std::make_unique(); #endif base::FilePath user_data_dir; bool result = base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); DCHECK(result); if (breadcrumbs::MaybeEnableBasedOnChannel(local_state_.get(), chrome::GetChannel())) { // Start crash reporter listening for breadcrumb events. Collected // breadcrumbs will be attached to crash reports. breadcrumbs::CrashReporterBreadcrumbObserver::GetInstance(); application_breadcrumbs_logger_ = std::make_unique( user_data_dir, base::BindRepeating([] { return ChromeMetricsServiceAccessor:: IsMetricsAndCrashReportingEnabled(); })); } else { breadcrumbs::DeleteBreadcrumbFiles(user_data_dir); } if (features_->audio_process_ml_model_forwarder()) { // TODO(crbug.com/454930933): Once the model provider is available from // PreCreateThreads, move this init to GlobalFeatures initialization. features_->audio_process_ml_model_forwarder()->Initialize( features_->optimization_guide_global_feature()->GetModelProvider()); } } void BrowserProcessImpl::CreateIconManager() { DCHECK(!created_icon_manager_ && !icon_manager_); created_icon_manager_ = true; icon_manager_ = std::make_unique(); } void BrowserProcessImpl::CreateNotificationPlatformBridge() { DCHECK(!notification_bridge_); notification_bridge_ = NotificationPlatformBridge::Create(); created_notification_bridge_ = true; } void BrowserProcessImpl::CreateNotificationUIManager() { #if BUILDFLAG(ENABLE_CHROME_NOTIFICATIONS) DCHECK(!notification_ui_manager_); notification_ui_manager_ = NotificationUIManager::Create(); created_notification_ui_manager_ = !!notification_ui_manager_; #endif } void BrowserProcessImpl::CreateBackgroundModeManager() { #if BUILDFLAG(ENABLE_BACKGROUND_MODE) DCHECK(!background_mode_manager_); background_mode_manager_ = std::make_unique( *base::CommandLine::ForCurrentProcess(), &profile_manager()->GetProfileAttributesStorage()); #endif } void BrowserProcessImpl::CreateStatusTray() { DCHECK(!status_tray_); status_tray_ = StatusTray::Create(); } void BrowserProcessImpl::CreatePrintPreviewDialogController() { #if BUILDFLAG(ENABLE_PRINT_PREVIEW) DCHECK(!print_preview_dialog_controller_); print_preview_dialog_controller_ = std::make_unique(); #else NOTIMPLEMENTED(); #endif } void BrowserProcessImpl::CreateBackgroundPrintingManager() { #if BUILDFLAG(ENABLE_PRINT_PREVIEW) DCHECK(!background_printing_manager_); background_printing_manager_ = std::make_unique(); #else NOTIMPLEMENTED(); #endif } #if BUILDFLAG(SAFE_BROWSING_AVAILABLE) void BrowserProcessImpl::CreateSafeBrowsingService() { DCHECK(!safe_browsing_service_); // Set this flag to true so that we don't retry indefinitely to // create the service class if there was an error. created_safe_browsing_service_ = true; // The factory can be overridden in tests. if (!safe_browsing::SafeBrowsingServiceInterface::HasFactory()) { safe_browsing::SafeBrowsingServiceInterface::RegisterFactory( safe_browsing::GetSafeBrowsingServiceFactory()); } // TODO(crbug.com/41437292): Port consumers of the |safe_browsing_service_| to // use the interface in components/safe_browsing, and remove this cast. safe_browsing_service_ = static_cast( safe_browsing::SafeBrowsingServiceInterface::CreateSafeBrowsingService()); if (safe_browsing_service_) { safe_browsing_service_->Initialize(); } } #endif void BrowserProcessImpl::CreateSubresourceFilterRulesetService() { DCHECK(!subresource_filter_ruleset_service_); created_subresource_filter_ruleset_service_ = true; if (!base::FeatureList::IsEnabled( subresource_filter::kSafeBrowsingSubresourceFilter)) { return; } base::FilePath user_data_dir; base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); subresource_filter_ruleset_service_ = subresource_filter::RulesetService::Create( subresource_filter::kSafeBrowsingRulesetConfig, local_state(), user_data_dir, subresource_filter::SafeBrowsingRulesetPublisher::Factory()); } #if !BUILDFLAG(IS_ANDROID) // Android's GCMDriver currently makes the assumption that it's a singleton. // Until this gets fixed, instantiating multiple Java GCMDrivers will throw an // exception, but because they're only initialized on demand these crashes // would be very difficult to triage. See http://crbug.com/41145548. void BrowserProcessImpl::CreateGCMDriver() { DCHECK(!gcm_driver_); base::FilePath store_path; CHECK(base::PathService::Get(chrome::DIR_GLOBAL_GCM_STORE, &store_path)); scoped_refptr blocking_task_runner( base::ThreadPool::CreateSequencedTaskRunner( {base::MayBlock(), base::TaskPriority::BEST_EFFORT, base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})); gcm_driver_ = gcm::CreateGCMDriverDesktop( base::WrapUnique(new gcm::GCMClientFactory), local_state(), store_path, base::BindRepeating(&RequestProxyResolvingSocketFactory), system_network_context_manager()->GetSharedURLLoaderFactory(), content::GetNetworkConnectionTracker(), chrome::GetChannel(), gcm::GetProductCategoryForSubtypes(local_state()), content::GetUIThreadTaskRunner({}), content::GetIOThreadTaskRunner({}), blocking_task_runner, os_crypt_async()); } #endif // !BUILDFLAG(IS_ANDROID) void BrowserProcessImpl::InitializeNetworkTimeTracker() { CHECK(!network_time_tracker_->is_initialized()); network_time_tracker_->Initialize( local_state(), system_network_context_manager()->GetSharedURLLoaderFactory()); } void BrowserProcessImpl::ApplyDefaultBrowserPolicy() { if (local_state()->GetBoolean(prefs::kDefaultBrowserSettingEnabled)) { // The worker pointer is reference counted. While it is running, the // message loops of the FILE and UI thread will hold references to it // and it will be automatically freed once all its tasks have finished. auto set_browser_worker = base::MakeRefCounted(); // The user interaction must always be disabled when applying the default // browser policy since it is done at each browser startup and the result // of the interaction cannot be forced. set_browser_worker->set_interactive_permitted(false); set_browser_worker->StartSetAsDefault(base::NullCallback()); } } void BrowserProcessImpl::OnLocaleChanged(const std::string& new_locale) { // TODO(crbug.com/406985310): The cache for IO thread should be integrated // into ApplicationLocaleStorage. ChromeContentBrowserClient::SetApplicationLocale(new_locale); // TODO(crbug.com/406985310): Implement ApplicationLocaleStorage::Observer for // TranslateDownloadManager, or refactor //components/translate so that it can // directly depend on ApplicationLocaleStorage. translate::TranslateDownloadManager::GetInstance()->set_application_locale( new_locale); } void BrowserProcessImpl::Pin() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); CHECK(!IsShuttingDown()); } void BrowserProcessImpl::Unpin() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); #if !BUILDFLAG(IS_ANDROID) // The quit closure is set by ChromeBrowserMainParts to transfer ownership of // the browser's lifetime to the BrowserProcess. Any KeepAlives registered and // unregistered prior to setting the quit closure are ignored. Only once the // quit closure is set should unpinning start process shutdown. if (!quit_closure_) { return; } #endif DCHECK(!shutting_down_); shutting_down_ = true; javascript_dialogs::AppModalDialogQueue::GetInstance()->CancelAllDialogs(); #if !BUILDFLAG(IS_ANDROID) KeepAliveRegistry::GetInstance()->SetIsShuttingDown(); #endif // !BUILDFLAG(IS_ANDROID) #if BUILDFLAG(ENABLE_PRINTING) // Wait for the pending print jobs to finish. Don't do this later, since // this might cause a nested run loop to run, and we don't want pending // tasks to run once teardown has started. print_job_manager_->Shutdown(); #endif #if defined(LEAK_SANITIZER) // Check for memory leaks now, before we start shutting down threads. Doing // this early means we won't report any shutdown-only leaks (as they have // not yet happened at this point). // If leaks are found, this will make the process exit immediately. __lsan_do_leak_check(); #endif CHECK(base::RunLoop::IsRunningOnCurrentThread()); #if BUILDFLAG(IS_MAC) base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( FROM_HERE, base::BindOnce(ChromeBrowserMainPartsMac::DidEndMainMessageLoop)); #endif #if !BUILDFLAG(IS_ANDROID) std::move(quit_closure_).Run(); chrome::ShutdownIfNeeded(); #endif // !BUILDFLAG(IS_ANDROID) } // Mac is currently not supported. #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) bool BrowserProcessImpl::IsRunningInBackground() const { // Check if browser is in the background. const auto* const keep_alive_registry = KeepAliveRegistry::GetInstance(); return !keep_alive_registry->IsOriginRegistered(KeepAliveOrigin::BROWSER) && keep_alive_registry->IsKeepingAlive(); } void BrowserProcessImpl::RestartBackgroundInstance() { DLOG(WARNING) << "Detected update. Restarting background browser instance."; chrome::AttemptRestartWithMode(chrome::RelaunchMode::kBackground); } void BrowserProcessImpl::OnAutoupdateTimer() { if (IsRunningInBackground()) { // upgrade_util::IsUpdatePendingRestart touches the disk, so do it on a // suitable thread. base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN, base::MayBlock()}, base::BindOnce(&upgrade_util::IsUpdatePendingRestart), base::BindOnce(&BrowserProcessImpl::OnPendingRestartResult, base::Unretained(this))); } } void BrowserProcessImpl::OnPendingRestartResult( bool is_update_pending_restart) { // Make sure that the browser is still in the background after returning from // the check. if (is_update_pending_restart && IsRunningInBackground()) { DLOG(WARNING) << "Detected update. Restarting browser."; RestartBackgroundInstance(); } } #endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX)