// 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 "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/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/browser_trial.h" #include "chrome/browser/chrome_browser_main.h" #include "chrome/browser/chrome_plugin_service_filter.h" #include "chrome/browser/component_updater/component_updater_configurator.h" #include "chrome/browser/component_updater/component_updater_service.h" #include "chrome/browser/debugger/remote_debugging_server.h" #include "chrome/browser/download/download_request_limiter.h" #include "chrome/browser/download/download_status_updater.h" #include "chrome/browser/extensions/extension_event_router_forwarder.h" #include "chrome/browser/extensions/extension_tab_id_map.h" #include "chrome/browser/first_run/upgrade_util.h" #include "chrome/browser/icon_manager.h" #include "chrome/browser/intranet_redirect_detector.h" #include "chrome/browser/io_thread.h" #include "chrome/browser/metrics/metrics_service.h" #include "chrome/browser/metrics/thread_watcher.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/policy/browser_policy_connector.h" #include "chrome/browser/policy/policy_service_impl.h" #include "chrome/browser/policy/policy_service_stub.h" #include "chrome/browser/prefs/browser_prefs.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_tab_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/tab_closeable_state_watcher.h" #include "chrome/browser/tab_contents/thumbnail_generator.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_content_client.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/json_pref_store.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 "content/public/common/pepper_plugin_info.h" #include "net/socket/client_socket_pool_manager.h" #include "net/url_request/url_request_context_getter.h" #include "ui/base/clipboard/clipboard.h" #include "ui/base/l10n/l10n_util.h" #if defined(OS_WIN) #include "ui/views/focus/view_storage.h" #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/oom_priority_manager.h" #endif // defined(OS_CHROMEOS) #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(const CommandLine& command_line) : created_metrics_service_(false), created_watchdog_thread_(false), created_profile_manager_(false), created_local_state_(false), created_icon_manager_(false), created_browser_policy_connector_(false), created_notification_ui_manager_(false), created_safe_browsing_service_(false), module_ref_count_(0), did_start_(false), checked_for_new_frames_(false), using_new_frames_(false), thumbnail_generator_(new ThumbnailGenerator), download_status_updater_(new DownloadStatusUpdater) { g_browser_process = this; clipboard_.reset(new ui::Clipboard); #if !defined(OS_ANDROID) // Must be created after the NotificationService. print_job_manager_.reset(new printing::PrintJobManager); #endif net_log_.reset(new ChromeNetLog); ChildProcessSecurityPolicy::GetInstance()->RegisterWebSafeScheme( chrome::kExtensionScheme); extension_event_router_forwarder_ = new ExtensionEventRouterForwarder; ExtensionTabIdMap::GetInstance()->Init(); } BrowserProcessImpl::~BrowserProcessImpl() { #if !defined(OS_ANDROID) // Wait for the pending print jobs to finish. print_job_manager_->OnQuit(); print_job_manager_.reset(); #endif 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, IntranetRedirectDetector, 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(); intranet_redirect_detector_.reset(); #if defined(ENABLE_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(); // Debugger must be cleaned up before IO thread and NotificationService. remote_debugging_server_.reset(); ExtensionTabIdMap::GetInstance()->Shutdown(); // The policy providers managed by |browser_policy_connector_| need to shut // down while the IO and FILE threads are still alive. browser_policy_connector_.reset(); // 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(); CHECK(MessageLoop::current()->is_running()); // Allow UI and IO threads to do blocking IO on shutdown, since we do a lot // of it on shutdown for valid reasons. base::ThreadRestrictions::SetIOAllowed(true); CHECK(!BrowserList::GetLastActive()); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::Bind(base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed), true)); #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]->MarkAsCleanShutdown(); // 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(); } PrefService* BrowserProcessImpl::local_state() { DCHECK(CalledOnValidThread()); if (!created_local_state_) CreateLocalState(); return local_state_.get(); } ui::Clipboard* BrowserProcessImpl::clipboard() { DCHECK(CalledOnValidThread()); return clipboard_.get(); } net::URLRequestContextGetter* BrowserProcessImpl::system_request_context() { DCHECK(CalledOnValidThread()); return io_thread()->system_url_request_context_getter(); } #if defined(OS_CHROMEOS) browser::OomPriorityManager* BrowserProcessImpl::oom_priority_manager() { DCHECK(CalledOnValidThread()); if (!oom_priority_manager_.get()) oom_priority_manager_.reset(new browser::OomPriorityManager()); return oom_priority_manager_.get(); } #endif // defined(OS_CHROMEOS) ExtensionEventRouterForwarder* 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(); } policy::BrowserPolicyConnector* BrowserProcessImpl::browser_policy_connector() { DCHECK(CalledOnValidThread()); if (!created_browser_policy_connector_) { DCHECK(browser_policy_connector_.get() == NULL); created_browser_policy_connector_ = true; #if defined(ENABLE_CONFIGURATION_POLICY) browser_policy_connector_.reset(new policy::BrowserPolicyConnector()); browser_policy_connector_->Init(); #endif } return browser_policy_connector_.get(); } policy::PolicyService* BrowserProcessImpl::policy_service() { if (!policy_service_.get()) { #if defined(ENABLE_CONFIGURATION_POLICY) policy_service_.reset(browser_policy_connector()->CreatePolicyService()); #else policy_service_.reset(new policy::PolicyServiceStub()); #endif } return policy_service_.get(); } IconManager* BrowserProcessImpl::icon_manager() { DCHECK(CalledOnValidThread()); if (!created_icon_manager_) CreateIconManager(); return icon_manager_.get(); } ThumbnailGenerator* BrowserProcessImpl::GetThumbnailGenerator() { return thumbnail_generator_.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::InitDevToolsHttpProtocolHandler( Profile* profile, const std::string& ip, int port, const std::string& frontend_url) { DCHECK(CalledOnValidThread()); remote_debugging_server_.reset( new RemoteDebuggingServer(profile, ip, port, frontend_url)); } 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::PrintPreviewTabController* BrowserProcessImpl::print_preview_tab_controller() { #if defined(OS_ANDROID) NOTIMPLEMENTED(); return NULL; #else DCHECK(CalledOnValidThread()); if (!print_preview_tab_controller_.get()) CreatePrintPreviewTabController(); return print_preview_tab_controller_.get(); #endif } printing::BackgroundPrintingManager* BrowserProcessImpl::background_printing_manager() { #if defined(OS_ANDROID) NOTIMPLEMENTED(); return NULL; #else DCHECK(CalledOnValidThread()); if (!background_printing_manager_.get()) CreateBackgroundPrintingManager(); return background_printing_manager_.get(); #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); } DownloadStatusUpdater* BrowserProcessImpl::download_status_updater() { return download_status_updater_.get(); } DownloadRequestLimiter* BrowserProcessImpl::download_request_limiter() { DCHECK(CalledOnValidThread()); if (!download_request_limiter_) download_request_limiter_ = new DownloadRequestLimiter(); return download_request_limiter_; } TabCloseableStateWatcher* BrowserProcessImpl::tab_closeable_state_watcher() { DCHECK(CalledOnValidThread()); if (!tab_closeable_state_watcher_.get()) CreateTabCloseableStateWatcher(); return tab_closeable_state_watcher_.get(); } BackgroundModeManager* BrowserProcessImpl::background_mode_manager() { DCHECK(CalledOnValidThread()); if (!background_mode_manager_.get()) CreateBackgroundModeManager(); return background_mode_manager_.get(); } 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; } bool BrowserProcessImpl::plugin_finder_disabled() const { if (plugin_finder_disabled_pref_.get()) return plugin_finder_disabled_pref_->GetValue(); else return false; } void BrowserProcessImpl::Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) { if (type == chrome::NOTIFICATION_PREF_CHANGED) { std::string* pref = content::Details(details).ptr(); if (*pref == prefs::kDefaultBrowserSettingEnabled) { ApplyDefaultBrowserPolicy(); } else if (*pref == prefs::kDisabledSchemes) { ApplyDisabledSchemesPolicy(); } else if (*pref == prefs::kAllowCrossOriginAuthPrompt) { ApplyAllowCrossOriginAuthPromptPolicy(); } } else { NOTREACHED(); } } #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, 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; PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path); local_state_.reset( PrefService::CreatePrefService(local_state_path, NULL, false)); // Initialize the prefs of the local state. browser::RegisterLocalState(local_state_.get()); pref_change_registrar_.Init(local_state_.get()); #if !defined(OS_ANDROID) print_job_manager_->InitOnUIThread(local_state_.get()); #endif // Initialize the notification for the default browser setting policy. local_state_->RegisterBooleanPref(prefs::kDefaultBrowserSettingEnabled, false); pref_change_registrar_.Add(prefs::kDefaultBrowserSettingEnabled, this); // Initialize the preference for the plugin finder policy. // This preference is only needed on the IO thread so make it available there. local_state_->RegisterBooleanPref(prefs::kDisablePluginFinder, false); plugin_finder_disabled_pref_.reset(new BooleanPrefMember); plugin_finder_disabled_pref_->Init(prefs::kDisablePluginFinder, local_state_.get(), NULL); plugin_finder_disabled_pref_->MoveToThread(BrowserThread::IO); // Another policy that needs to be defined before the net subsystem is // initialized is MaxConnectionsPerProxy 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, this); ApplyDisabledSchemesPolicy(); local_state_->RegisterBooleanPref(prefs::kAllowCrossOriginAuthPrompt, false); } void BrowserProcessImpl::PreCreateThreads() { io_thread_.reset(new IOThread( local_state(), net_log_.get(), extension_event_router_forwarder_.get())); } void BrowserProcessImpl::PreMainMessageLoopRun() { PluginService* plugin_service = PluginService::GetInstance(); plugin_service->SetFilter(ChromePluginServiceFilter::GetInstance()); plugin_service->StartWatchingPlugins(); // Register the internal Flash if available. FilePath path; if (!CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableInternalFlash) && PathService::Get(chrome::FILE_FLASH_PLUGIN, &path)) { plugin_service->AddExtraPluginPath(path); } // Register bundled Pepper Flash if available. content::PepperPluginInfo plugin; bool add_at_beginning = false; chrome::ChromeContentClient* content_client = static_cast(content::GetContentClient()); if (content_client->GetBundledFieldTrialPepperFlash(&plugin, &add_at_beginning)) { plugin_service->RegisterInternalPlugin(plugin.ToWebPluginInfo(), add_at_beginning); } #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 if (local_state_->IsManagedPreference(prefs::kDefaultBrowserSettingEnabled)) ApplyDefaultBrowserPolicy(); } 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() { DCHECK(notification_ui_manager_.get() == NULL); notification_ui_manager_.reset(NotificationUIManager::Create(local_state())); created_notification_ui_manager_ = true; } void BrowserProcessImpl::CreateTabCloseableStateWatcher() { DCHECK(tab_closeable_state_watcher_.get() == NULL); tab_closeable_state_watcher_.reset(TabCloseableStateWatcher::Create()); } 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::CreatePrintPreviewTabController() { #if defined(OS_ANDROID) NOTIMPLEMENTED(); #else DCHECK(print_preview_tab_controller_.get() == NULL); print_preview_tab_controller_ = new printing::PrintPreviewTabController(); #endif } void BrowserProcessImpl::CreateBackgroundPrintingManager() { DCHECK(background_printing_manager_.get() == NULL); background_printing_manager_.reset(new printing::BackgroundPrintingManager()); } 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(ENABLE_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 && BrowserList::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."; BrowserList::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)