// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/browser_process_impl.h" #include #include #include #include #include "base/bind.h" #include "base/bind_helpers.h" #include "base/command_line.h" #include "base/debug/alias.h" #include "base/file_util.h" #include "base/path_service.h" #include "base/prefs/json_pref_store.h" #include "base/synchronization/waitable_event.h" #include "base/threading/thread.h" #include "base/threading/thread_restrictions.h" #include "chrome/browser/automation/automation_provider_list.h" #include "chrome/browser/background/background_mode_manager.h" #include "chrome/browser/chrome_browser_main.h" #include "chrome/browser/chrome_content_browser_client.h" #include "chrome/browser/component_updater/component_updater_configurator.h" #include "chrome/browser/component_updater/component_updater_service.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/extensions/event_router_forwarder.h" #include "chrome/browser/extensions/extension_renderer_state.h" #include "chrome/browser/first_run/upgrade_util.h" #include "chrome/browser/gpu/gl_string_manager.h" #include "chrome/browser/icon_manager.h" #include "chrome/browser/intranet_redirect_detector.h" #include "chrome/browser/io_thread.h" #include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/media_gallery/media_file_system_registry.h" #include "chrome/browser/metrics/metrics_service.h" #include "chrome/browser/metrics/thread_watcher.h" #include "chrome/browser/metrics/variations/variations_service.h" #include "chrome/browser/net/chrome_net_log.h" #include "chrome/browser/net/crl_set_fetcher.h" #include "chrome/browser/net/sdch_dictionary_fetcher.h" #include "chrome/browser/notifications/notification_ui_manager.h" #include "chrome/browser/plugins/chrome_plugin_service_filter.h" #include "chrome/browser/plugins/plugin_finder.h" #include "chrome/browser/policy/policy_service.h" #include "chrome/browser/prefs/browser_prefs.h" #include "chrome/browser/prefs/chrome_pref_service_factory.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/prerender/prerender_tracker.h" #include "chrome/browser/printing/background_printing_manager.h" #include "chrome/browser/printing/print_job_manager.h" #include "chrome/browser/printing/print_preview_dialog_controller.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/browser/shell_integration.h" #include "chrome/browser/status_icons/status_tray.h" #include "chrome/browser/thumbnails/render_widget_snapshot_taker.h" #include "chrome/browser/ui/bookmarks/bookmark_prompt_controller.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/web_resource/promo_resource_service.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_notification_types.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/extension_l10n_util.h" #include "chrome/common/extensions/extension_resource.h" #include "chrome/common/pref_names.h" #include "chrome/common/switch_utils.h" #include "chrome/common/url_constants.h" #include "chrome/installer/util/google_update_constants.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/plugin_service.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/resource_dispatcher_host.h" #include "extensions/common/constants.h" #include "net/socket/client_socket_pool_manager.h" #include "net/url_request/url_request_context_getter.h" #include "ui/base/l10n/l10n_util.h" #if defined(ENABLE_CONFIGURATION_POLICY) #include "chrome/browser/policy/browser_policy_connector.h" #else #include "chrome/browser/policy/policy_service_stub.h" #endif // defined(ENABLE_CONFIGURATION_POLICY) #if defined(ENABLE_MESSAGE_CENTER) && defined(USE_ASH) #include "ash/shell.h" #endif #if defined(ENABLE_MESSAGE_CENTER) #include "ui/message_center/message_center.h" #endif #if defined(OS_WIN) #include "base/win/windows_version.h" #include "ui/views/focus/view_storage.h" #if defined(USE_AURA) #include "chrome/browser/metro_viewer/metro_viewer_process_host_win.h" #endif #elif defined(OS_MACOSX) #include "chrome/browser/chrome_browser_main_mac.h" #endif #if defined(USE_AURA) #include "ui/aura/env.h" #endif #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/memory/oom_priority_manager.h" #endif // defined(OS_CHROMEOS) #if defined(ENABLE_PLUGIN_INSTALLATION) #include "chrome/browser/web_resource/plugins_resource_service.h" #endif #if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS) // How often to check if the persistent instance of Chrome needs to restart // to install an update. static const int kUpdateCheckIntervalHours = 6; #endif #if defined(OS_WIN) // Attest to the fact that the call to the file thread to save preferences has // run, and it is safe to terminate. This avoids the potential of some other // task prematurely terminating our waiting message loop by posting a // QuitTask(). static bool g_end_session_file_thread_has_completed = false; #endif #if defined(USE_X11) // How long to wait for the File thread to complete during EndSession, on // Linux. We have a timeout here because we're unable to run the UI messageloop // and there's some deadlock risk. Our only option is to exit anyway. static const int kEndSessionTimeoutSeconds = 10; #endif using content::BrowserThread; using content::ChildProcessSecurityPolicy; using content::PluginService; using content::ResourceDispatcherHost; BrowserProcessImpl::BrowserProcessImpl( base::SequencedTaskRunner* local_state_task_runner, const CommandLine& command_line) : created_metrics_service_(false), created_watchdog_thread_(false), created_browser_policy_connector_(false), created_profile_manager_(false), created_local_state_(false), created_icon_manager_(false), created_notification_ui_manager_(false), #if defined(ENABLE_MESSAGE_CENTER) && !defined(USE_ASH) created_message_center_(false), #endif created_safe_browsing_service_(false), module_ref_count_(0), did_start_(false), checked_for_new_frames_(false), using_new_frames_(false), render_widget_snapshot_taker_(new RenderWidgetSnapshotTaker), download_status_updater_(new DownloadStatusUpdater), local_state_task_runner_(local_state_task_runner) { g_browser_process = this; #if defined(ENABLE_PRINTING) // Must be created after the NotificationService. print_job_manager_.reset(new printing::PrintJobManager); #endif net_log_.reset(new ChromeNetLog); ChildProcessSecurityPolicy::GetInstance()->RegisterWebSafeScheme( extensions::kExtensionScheme); ChildProcessSecurityPolicy::GetInstance()->RegisterWebSafeScheme( chrome::kExtensionResourceScheme); extension_event_router_forwarder_ = new extensions::EventRouterForwarder; ExtensionRendererState::GetInstance()->Init(); } BrowserProcessImpl::~BrowserProcessImpl() { tracked_objects::ThreadData::EnsureCleanupWasCalled(4); g_browser_process = NULL; } void BrowserProcessImpl::StartTearDown() { #if defined(ENABLE_AUTOMATION) // Delete the AutomationProviderList before NotificationService, // since it may try to unregister notifications // Both NotificationService and AutomationProvider are singleton instances in // the BrowserProcess. Since AutomationProvider may have some active // notification observers, it is essential that it gets destroyed before the // NotificationService. NotificationService won't be destroyed until after // this destructor is run. automation_provider_list_.reset(); #endif // We need to shutdown the SdchDictionaryFetcher as it regularly holds // a pointer to a URLFetcher, and that URLFetcher (upon destruction) will do // a PostDelayedTask onto the IO thread. This shutdown call will both discard // any pending URLFetchers, and avoid creating any more. BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(&SdchDictionaryFetcher::Shutdown)); // We need to destroy the MetricsService, VariationsService, // IntranetRedirectDetector, PromoResourceService, and SafeBrowsing // ClientSideDetectionService (owned by the SafeBrowsingService) before the // io_thread_ gets destroyed, since their destructors can call the URLFetcher // destructor, which does a PostDelayedTask operation on the IO thread. (The // IO thread will handle that URLFetcher operation before going away.) metrics_service_.reset(); variations_service_.reset(); intranet_redirect_detector_.reset(); #if defined(FULL_SAFE_BROWSING) || defined(MOBILE_SAFE_BROWSING) if (safe_browsing_service_.get()) safe_browsing_service()->ShutDown(); #endif // 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(); // Need to clear profiles (download managers) before the io_thread_. profile_manager_.reset(); #if !defined(OS_ANDROID) // Debugger must be cleaned up before IO thread and NotificationService. remote_debugging_server_.reset(); #endif ExtensionRendererState::GetInstance()->Shutdown(); #if defined(ENABLE_CONFIGURATION_POLICY) // The policy providers managed by |browser_policy_connector_| need to shut // down while the IO and FILE threads are still alive. if (browser_policy_connector_) browser_policy_connector_->Shutdown(); #endif // Stop the watchdog thread before stopping other threads. watchdog_thread_.reset(); #if defined(USE_AURA) // Delete aura after the metrics service has been deleted as it accesses // monitor information. aura::Env::DeleteInstance(); #endif } void BrowserProcessImpl::PostDestroyThreads() { // With the file_thread_ flushed, we can release any icon resources. icon_manager_.reset(); // Reset associated state right after actual thread is stopped, // as io_thread_.global_ cleanup happens in CleanUp on the IO // thread, i.e. as the thread exits its message loop. // // This is important also because in various places, the // IOThread object being NULL is considered synonymous with the // IO thread having stopped. io_thread_.reset(); } #if defined(OS_WIN) // Send a QuitTask to the given MessageLoop when the (file) thread has processed // our (other) recent requests (to save preferences). // Change the boolean so that the receiving thread will know that we did indeed // send the QuitTask that terminated the message loop. static void PostQuit(MessageLoop* message_loop) { g_end_session_file_thread_has_completed = true; message_loop->PostTask(FROM_HERE, MessageLoop::QuitClosure()); } #elif defined(USE_X11) static void Signal(base::WaitableEvent* event) { event->Signal(); } #endif unsigned int BrowserProcessImpl::AddRefModule() { DCHECK(CalledOnValidThread()); // CHECK(!IsShuttingDown()); if (IsShuttingDown()) { // Copy the stacktrace which released the final reference onto our stack so // it will be available in the crash report for inspection. base::debug::StackTrace callstack = release_last_reference_callstack_; base::debug::Alias(&callstack); CHECK(false); } did_start_ = true; module_ref_count_++; return module_ref_count_; } unsigned int BrowserProcessImpl::ReleaseModule() { DCHECK(CalledOnValidThread()); DCHECK_NE(0u, module_ref_count_); module_ref_count_--; if (0 == module_ref_count_) { release_last_reference_callstack_ = base::debug::StackTrace(); #if defined(ENABLE_PRINTING) // Wait for the pending print jobs to finish. Don't do this later, since // this might cause a nested message loop to run, and we don't want pending // tasks to run once teardown has started. print_job_manager_->OnQuit(); print_job_manager_.reset(); #endif CHECK(MessageLoop::current()->is_running()); #if defined(OS_MACOSX) MessageLoop::current()->PostTask( FROM_HERE, base::Bind(ChromeBrowserMainPartsMac::DidEndMainMessageLoop)); #endif MessageLoop::current()->Quit(); } return module_ref_count_; } void BrowserProcessImpl::EndSession() { // Mark all the profiles as clean. ProfileManager* pm = profile_manager(); std::vector profiles(pm->GetLoadedProfiles()); for (size_t i = 0; i < profiles.size(); ++i) profiles[i]->SetExitType(Profile::EXIT_SESSION_ENDED); // Tell the metrics service it was cleanly shutdown. MetricsService* metrics = g_browser_process->metrics_service(); if (metrics && local_state()) { metrics->RecordStartOfSessionEnd(); // MetricsService lazily writes to prefs, force it to write now. local_state()->CommitPendingWrite(); } // http://crbug.com/125207 base::ThreadRestrictions::ScopedAllowWait allow_wait; // We must write that the profile and metrics service shutdown cleanly, // otherwise on startup we'll think we crashed. So we block until done and // then proceed with normal shutdown. #if defined(USE_X11) // Can't run a local loop on linux. Instead create a waitable event. scoped_ptr done_writing( new base::WaitableEvent(false, false)); BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind(Signal, done_writing.get())); // If all file writes haven't cleared in the timeout, leak the WaitableEvent // so that there's no race to reference it in Signal(). if (!done_writing->TimedWait( base::TimeDelta::FromSeconds(kEndSessionTimeoutSeconds))) { ignore_result(done_writing.release()); } #elif defined(OS_WIN) BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind(PostQuit, MessageLoop::current())); int quits_received = 0; do { MessageLoop::current()->Run(); ++quits_received; } while (!g_end_session_file_thread_has_completed); // If we did get extra quits, then we should re-post them to the message loop. while (--quits_received > 0) MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure()); #else NOTIMPLEMENTED(); #endif } MetricsService* BrowserProcessImpl::metrics_service() { DCHECK(CalledOnValidThread()); if (!created_metrics_service_) CreateMetricsService(); return metrics_service_.get(); } IOThread* BrowserProcessImpl::io_thread() { DCHECK(CalledOnValidThread()); DCHECK(io_thread_.get()); return io_thread_.get(); } WatchDogThread* BrowserProcessImpl::watchdog_thread() { DCHECK(CalledOnValidThread()); if (!created_watchdog_thread_) CreateWatchdogThread(); DCHECK(watchdog_thread_.get() != NULL); return watchdog_thread_.get(); } ProfileManager* BrowserProcessImpl::profile_manager() { DCHECK(CalledOnValidThread()); if (!created_profile_manager_) CreateProfileManager(); return profile_manager_.get(); } // TODO(joi): Switch to returning just PrefService, since those // calling this function shouldn't be doing ad-hoc registration, that // happens earlier in browser_prefs::RegisterLocalState. PrefServiceSimple* BrowserProcessImpl::local_state() { DCHECK(CalledOnValidThread()); if (!created_local_state_) CreateLocalState(); return local_state_.get(); } net::URLRequestContextGetter* BrowserProcessImpl::system_request_context() { DCHECK(CalledOnValidThread()); return io_thread()->system_url_request_context_getter(); } chrome_variations::VariationsService* BrowserProcessImpl::variations_service() { DCHECK(CalledOnValidThread()); if (!variations_service_.get()) variations_service_.reset(chrome_variations::VariationsService::Create()); return variations_service_.get(); } #if defined(OS_CHROMEOS) chromeos::OomPriorityManager* BrowserProcessImpl::oom_priority_manager() { DCHECK(CalledOnValidThread()); if (!oom_priority_manager_.get()) oom_priority_manager_.reset(new chromeos::OomPriorityManager()); return oom_priority_manager_.get(); } #endif // defined(OS_CHROMEOS) extensions::EventRouterForwarder* BrowserProcessImpl::extension_event_router_forwarder() { return extension_event_router_forwarder_.get(); } NotificationUIManager* BrowserProcessImpl::notification_ui_manager() { DCHECK(CalledOnValidThread()); if (!created_notification_ui_manager_) CreateNotificationUIManager(); return notification_ui_manager_.get(); } #if defined(ENABLE_MESSAGE_CENTER) message_center::MessageCenter* BrowserProcessImpl::message_center() { DCHECK(CalledOnValidThread()); #if defined(USE_ASH) return ash::Shell::GetInstance()->message_center(); #else if (!created_message_center_) CreateMessageCenter(); return message_center_.get(); #endif } #endif policy::BrowserPolicyConnector* BrowserProcessImpl::browser_policy_connector() { DCHECK(CalledOnValidThread()); #if defined(ENABLE_CONFIGURATION_POLICY) if (!created_browser_policy_connector_) { // Init() should not reenter this function. If it does this will DCHECK. DCHECK(!browser_policy_connector_); browser_policy_connector_.reset(new policy::BrowserPolicyConnector()); browser_policy_connector_->Init(); created_browser_policy_connector_ = true; } return browser_policy_connector_.get(); #else return NULL; #endif } policy::PolicyService* BrowserProcessImpl::policy_service() { #if defined(ENABLE_CONFIGURATION_POLICY) return browser_policy_connector()->GetPolicyService(); #else if (!policy_service_.get()) policy_service_.reset(new policy::PolicyServiceStub()); return policy_service_.get(); #endif } IconManager* BrowserProcessImpl::icon_manager() { DCHECK(CalledOnValidThread()); if (!created_icon_manager_) CreateIconManager(); return icon_manager_.get(); } GLStringManager* BrowserProcessImpl::gl_string_manager() { DCHECK(CalledOnValidThread()); if (!gl_string_manager_.get()) gl_string_manager_.reset(new GLStringManager()); return gl_string_manager_.get(); } RenderWidgetSnapshotTaker* BrowserProcessImpl::GetRenderWidgetSnapshotTaker() { return render_widget_snapshot_taker_.get(); } AutomationProviderList* BrowserProcessImpl::GetAutomationProviderList() { DCHECK(CalledOnValidThread()); #if defined(ENABLE_AUTOMATION) if (automation_provider_list_.get() == NULL) automation_provider_list_.reset(new AutomationProviderList()); return automation_provider_list_.get(); #else return NULL; #endif } void BrowserProcessImpl::CreateDevToolsHttpProtocolHandler( Profile* profile, const std::string& ip, int port, const std::string& frontend_url) { DCHECK(CalledOnValidThread()); #if !defined(OS_ANDROID) // StartupBrowserCreator::LaunchBrowser can be run multiple times when browser // is started with several profiles or existing browser process is reused. if (!remote_debugging_server_.get()) { remote_debugging_server_.reset( new RemoteDebuggingServer(profile, ip, port, frontend_url)); } #endif } bool BrowserProcessImpl::IsShuttingDown() { DCHECK(CalledOnValidThread()); return did_start_ && 0 == module_ref_count_; } printing::PrintJobManager* BrowserProcessImpl::print_job_manager() { // TODO(abarth): DCHECK(CalledOnValidThread()); // http://code.google.com/p/chromium/issues/detail?id=6828 // print_job_manager_ is initialized in the constructor and destroyed in the // destructor, so it should always be valid. DCHECK(print_job_manager_.get()); return print_job_manager_.get(); } printing::PrintPreviewDialogController* BrowserProcessImpl::print_preview_dialog_controller() { #if defined(ENABLE_PRINTING) DCHECK(CalledOnValidThread()); 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 defined(ENABLE_PRINTING) DCHECK(CalledOnValidThread()); if (!background_printing_manager_.get()) CreateBackgroundPrintingManager(); return background_printing_manager_.get(); #else NOTIMPLEMENTED(); return NULL; #endif } IntranetRedirectDetector* BrowserProcessImpl::intranet_redirect_detector() { DCHECK(CalledOnValidThread()); if (!intranet_redirect_detector_.get()) CreateIntranetRedirectDetector(); return intranet_redirect_detector_.get(); } const std::string& BrowserProcessImpl::GetApplicationLocale() { DCHECK(!locale_.empty()); return locale_; } void BrowserProcessImpl::SetApplicationLocale(const std::string& locale) { locale_ = locale; extension_l10n_util::SetProcessLocale(locale); static_cast( content::GetContentClient()->browser())->SetApplicationLocale(locale); } DownloadStatusUpdater* BrowserProcessImpl::download_status_updater() { return download_status_updater_.get(); } BookmarkPromptController* BrowserProcessImpl::bookmark_prompt_controller() { #if defined(OS_ANDROID) return NULL; #else return bookmark_prompt_controller_.get(); #endif } chrome::MediaFileSystemRegistry* BrowserProcessImpl::media_file_system_registry() { if (!media_file_system_registry_) media_file_system_registry_.reset(new chrome::MediaFileSystemRegistry()); return media_file_system_registry_.get(); } #if !defined(OS_WIN) void BrowserProcessImpl::PlatformSpecificCommandLineProcessing( const CommandLine& command_line) { } #endif DownloadRequestLimiter* BrowserProcessImpl::download_request_limiter() { DCHECK(CalledOnValidThread()); if (!download_request_limiter_) download_request_limiter_ = new DownloadRequestLimiter(); return download_request_limiter_; } BackgroundModeManager* BrowserProcessImpl::background_mode_manager() { DCHECK(CalledOnValidThread()); #if defined(ENABLE_BACKGROUND) if (!background_mode_manager_.get()) CreateBackgroundModeManager(); return background_mode_manager_.get(); #else NOTIMPLEMENTED(); return NULL; #endif } StatusTray* BrowserProcessImpl::status_tray() { DCHECK(CalledOnValidThread()); if (!status_tray_.get()) CreateStatusTray(); return status_tray_.get(); } SafeBrowsingService* BrowserProcessImpl::safe_browsing_service() { DCHECK(CalledOnValidThread()); if (!created_safe_browsing_service_) CreateSafeBrowsingService(); return safe_browsing_service_.get(); } safe_browsing::ClientSideDetectionService* BrowserProcessImpl::safe_browsing_detection_service() { DCHECK(CalledOnValidThread()); if (safe_browsing_service()) return safe_browsing_service()->safe_browsing_detection_service(); return NULL; } #if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS) void BrowserProcessImpl::StartAutoupdateTimer() { autoupdate_timer_.Start(FROM_HERE, base::TimeDelta::FromHours(kUpdateCheckIntervalHours), this, &BrowserProcessImpl::OnAutoupdateTimer); } #endif ChromeNetLog* BrowserProcessImpl::net_log() { return net_log_.get(); } prerender::PrerenderTracker* BrowserProcessImpl::prerender_tracker() { if (!prerender_tracker_.get()) prerender_tracker_.reset(new prerender::PrerenderTracker); return prerender_tracker_.get(); } ComponentUpdateService* BrowserProcessImpl::component_updater() { #if defined(OS_CHROMEOS) return NULL; #else if (!component_updater_.get()) { ComponentUpdateService::Configurator* configurator = MakeChromeComponentUpdaterConfigurator( CommandLine::ForCurrentProcess(), io_thread()->system_url_request_context_getter()); // Creating the component updater does not do anything, components // need to be registered and Start() needs to be called. component_updater_.reset(ComponentUpdateServiceFactory(configurator)); } return component_updater_.get(); #endif } CRLSetFetcher* BrowserProcessImpl::crl_set_fetcher() { #if defined(OS_CHROMEOS) // There's no component updater on ChromeOS so there can't be a CRLSetFetcher // either. return NULL; #else if (!crl_set_fetcher_.get()) crl_set_fetcher_ = new CRLSetFetcher(); return crl_set_fetcher_.get(); #endif } void BrowserProcessImpl::ResourceDispatcherHostCreated() { resource_dispatcher_host_delegate_.reset( new ChromeResourceDispatcherHostDelegate(prerender_tracker())); ResourceDispatcherHost::Get()->SetDelegate( resource_dispatcher_host_delegate_.get()); pref_change_registrar_.Add( prefs::kAllowCrossOriginAuthPrompt, base::Bind(&BrowserProcessImpl::ApplyAllowCrossOriginAuthPromptPolicy, base::Unretained(this))); ApplyAllowCrossOriginAuthPromptPolicy(); } void BrowserProcessImpl::CreateMetricsService() { DCHECK(!created_metrics_service_ && metrics_service_.get() == NULL); created_metrics_service_ = true; metrics_service_.reset(new MetricsService); } void BrowserProcessImpl::CreateWatchdogThread() { DCHECK(!created_watchdog_thread_ && watchdog_thread_.get() == NULL); created_watchdog_thread_ = true; scoped_ptr thread(new WatchDogThread()); if (!thread->Start()) return; watchdog_thread_.swap(thread); } void BrowserProcessImpl::CreateProfileManager() { DCHECK(!created_profile_manager_ && profile_manager_.get() == NULL); created_profile_manager_ = true; FilePath user_data_dir; PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); profile_manager_.reset(new ProfileManager(user_data_dir)); } void BrowserProcessImpl::CreateLocalState() { DCHECK(!created_local_state_ && local_state_.get() == NULL); created_local_state_ = true; FilePath local_state_path; CHECK(PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path)); local_state_.reset( chrome_prefs::CreateLocalState(local_state_path, local_state_task_runner_, policy_service(), NULL, false)); // Initialize the prefs of the local state. chrome::RegisterLocalState(local_state_.get()); pref_change_registrar_.Init(local_state_.get()); // Initialize the notification for the default browser setting policy. local_state_->RegisterBooleanPref(prefs::kDefaultBrowserSettingEnabled, false); pref_change_registrar_.Add( prefs::kDefaultBrowserSettingEnabled, base::Bind(&BrowserProcessImpl::ApplyDefaultBrowserPolicy, base::Unretained(this))); // This policy needs to be defined before the net subsystem is initialized, // so we do it here. local_state_->RegisterIntegerPref(prefs::kMaxConnectionsPerProxy, net::kDefaultMaxSocketsPerProxyServer); int max_per_proxy = local_state_->GetInteger(prefs::kMaxConnectionsPerProxy); net::ClientSocketPoolManager::set_max_sockets_per_proxy_server( net::HttpNetworkSession::NORMAL_SOCKET_POOL, std::max(std::min(max_per_proxy, 99), net::ClientSocketPoolManager::max_sockets_per_group( net::HttpNetworkSession::NORMAL_SOCKET_POOL))); // This is observed by ChildProcessSecurityPolicy, which lives in content/ // though, so it can't register itself. local_state_->RegisterListPref(prefs::kDisabledSchemes); pref_change_registrar_.Add( prefs::kDisabledSchemes, base::Bind(&BrowserProcessImpl::ApplyDisabledSchemesPolicy, base::Unretained(this))); ApplyDisabledSchemesPolicy(); local_state_->RegisterBooleanPref(prefs::kAllowCrossOriginAuthPrompt, false); #if defined(OS_WIN) if (base::win::GetVersion() >= base::win::VERSION_WIN8) local_state_->RegisterBooleanPref(prefs::kRestartSwitchMode, false); #endif } void BrowserProcessImpl::PreCreateThreads() { io_thread_.reset(new IOThread(local_state(), policy_service(), net_log_.get(), extension_event_router_forwarder_.get())); } void BrowserProcessImpl::PreMainMessageLoopRun() { if (local_state_->IsManagedPreference(prefs::kDefaultBrowserSettingEnabled)) ApplyDefaultBrowserPolicy(); #if defined(ENABLE_PLUGINS) PluginService* plugin_service = PluginService::GetInstance(); plugin_service->SetFilter(ChromePluginServiceFilter::GetInstance()); plugin_service->StartWatchingPlugins(); #if defined(OS_POSIX) // Also find plugins in a user-specific plugins dir, // e.g. ~/.config/chromium/Plugins. FilePath user_data_dir; if (PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) plugin_service->AddExtraPluginDir(user_data_dir.Append("Plugins")); #endif // Triggers initialization of the singleton instance on UI thread. PluginFinder::GetInstance()->Init(); #if defined(ENABLE_PLUGIN_INSTALLATION) DCHECK(!plugins_resource_service_.get()); plugins_resource_service_ = new PluginsResourceService(local_state()); plugins_resource_service_->StartAfterDelay(); #endif #endif // defined(ENABLE_PLUGINS) const CommandLine& command_line = *CommandLine::ForCurrentProcess(); if (!command_line.HasSwitch(switches::kDisableWebResources)) { DCHECK(!promo_resource_service_.get()); promo_resource_service_ = new PromoResourceService; promo_resource_service_->StartAfterDelay(); } #if !defined(OS_ANDROID) if (browser_defaults::bookmarks_enabled && BookmarkPromptController::IsEnabled()) { bookmark_prompt_controller_.reset(new BookmarkPromptController()); } #endif } void BrowserProcessImpl::CreateIconManager() { DCHECK(!created_icon_manager_ && icon_manager_.get() == NULL); created_icon_manager_ = true; icon_manager_.reset(new IconManager); } void BrowserProcessImpl::CreateIntranetRedirectDetector() { DCHECK(intranet_redirect_detector_.get() == NULL); scoped_ptr intranet_redirect_detector( new IntranetRedirectDetector); intranet_redirect_detector_.swap(intranet_redirect_detector); } void BrowserProcessImpl::CreateNotificationUIManager() { #if defined(ENABLE_NOTIFICATIONS) DCHECK(notification_ui_manager_.get() == NULL); notification_ui_manager_.reset(NotificationUIManager::Create(local_state())); created_notification_ui_manager_ = true; #endif } #if defined(ENABLE_MESSAGE_CENTER) && !defined(USE_ASH) void BrowserProcessImpl::CreateMessageCenter() { DCHECK(message_center_.get() == NULL); message_center_.reset(new message_center::MessageCenter()); created_message_center_ = true; } #endif void BrowserProcessImpl::CreateBackgroundModeManager() { DCHECK(background_mode_manager_.get() == NULL); background_mode_manager_.reset( new BackgroundModeManager(CommandLine::ForCurrentProcess(), &profile_manager()->GetProfileInfoCache())); } void BrowserProcessImpl::CreateStatusTray() { DCHECK(status_tray_.get() == NULL); status_tray_.reset(StatusTray::Create()); } void BrowserProcessImpl::CreatePrintPreviewDialogController() { #if defined(ENABLE_PRINTING) DCHECK(print_preview_dialog_controller_.get() == NULL); print_preview_dialog_controller_ = new printing::PrintPreviewDialogController(); #else NOTIMPLEMENTED(); #endif } void BrowserProcessImpl::CreateBackgroundPrintingManager() { #if defined(ENABLE_PRINTING) DCHECK(background_printing_manager_.get() == NULL); background_printing_manager_.reset(new printing::BackgroundPrintingManager()); #else NOTIMPLEMENTED(); #endif } void BrowserProcessImpl::CreateSafeBrowsingService() { DCHECK(safe_browsing_service_.get() == NULL); // 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; #if defined(FULL_SAFE_BROWSING) || defined(MOBILE_SAFE_BROWSING) safe_browsing_service_ = SafeBrowsingService::CreateSafeBrowsingService(); safe_browsing_service_->Initialize(); #endif } void BrowserProcessImpl::ApplyDisabledSchemesPolicy() { std::set schemes; const ListValue* scheme_list = local_state()->GetList(prefs::kDisabledSchemes); for (ListValue::const_iterator iter = scheme_list->begin(); iter != scheme_list->end(); ++iter) { std::string scheme; if ((*iter)->GetAsString(&scheme)) schemes.insert(scheme); } ChildProcessSecurityPolicy::GetInstance()->RegisterDisabledSchemes(schemes); } void BrowserProcessImpl::ApplyDefaultBrowserPolicy() { if (local_state()->GetBoolean(prefs::kDefaultBrowserSettingEnabled)) { scoped_refptr set_browser_worker = new ShellIntegration::DefaultBrowserWorker(NULL); set_browser_worker->StartSetAsDefault(); } } void BrowserProcessImpl::ApplyAllowCrossOriginAuthPromptPolicy() { bool value = local_state()->GetBoolean(prefs::kAllowCrossOriginAuthPrompt); ResourceDispatcherHost::Get()->SetAllowCrossOriginAuthPrompt(value); } // Mac is currently not supported. #if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS) bool BrowserProcessImpl::CanAutorestartForUpdate() const { // Check if browser is in the background and if it needs to be restarted to // apply a pending update. return BrowserList::size() == 0 && browser::WillKeepAlive() && upgrade_util::IsUpdatePendingRestart(); } // Switches to add when auto-restarting Chrome. const char* const kSwitchesToAddOnAutorestart[] = { switches::kNoStartupWindow }; void BrowserProcessImpl::RestartBackgroundInstance() { CommandLine* old_cl = CommandLine::ForCurrentProcess(); scoped_ptr new_cl(new CommandLine(old_cl->GetProgram())); std::map switches = old_cl->GetSwitches(); switches::RemoveSwitchesForAutostart(&switches); // Append the rest of the switches (along with their values, if any) // to the new command line for (std::map::const_iterator i = switches.begin(); i != switches.end(); ++i) { CommandLine::StringType switch_value = i->second; if (switch_value.length() > 0) { new_cl->AppendSwitchNative(i->first, i->second); } else { new_cl->AppendSwitch(i->first); } } // Ensure that our desired switches are set on the new process. for (size_t i = 0; i < arraysize(kSwitchesToAddOnAutorestart); ++i) { if (!new_cl->HasSwitch(kSwitchesToAddOnAutorestart[i])) new_cl->AppendSwitch(kSwitchesToAddOnAutorestart[i]); } DLOG(WARNING) << "Shutting down current instance of the browser."; browser::AttemptExit(); // Transfer ownership to Upgrade. upgrade_util::SetNewCommandLine(new_cl.release()); } void BrowserProcessImpl::OnAutoupdateTimer() { if (CanAutorestartForUpdate()) { DLOG(WARNING) << "Detected update. Restarting browser."; RestartBackgroundInstance(); } } #endif // (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS)