Home | History | Annotate | Download | only in browser
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/browser_process_impl.h"
      6 
      7 #include <algorithm>
      8 #include <map>
      9 #include <vector>
     10 
     11 #include "base/bind.h"
     12 #include "base/bind_helpers.h"
     13 #include "base/command_line.h"
     14 #include "base/debug/alias.h"
     15 #include "base/debug/leak_annotations.h"
     16 #include "base/path_service.h"
     17 #include "base/prefs/json_pref_store.h"
     18 #include "base/prefs/pref_registry_simple.h"
     19 #include "base/prefs/pref_service.h"
     20 #include "base/synchronization/waitable_event.h"
     21 #include "base/threading/thread.h"
     22 #include "base/threading/thread_restrictions.h"
     23 #include "chrome/browser/apps/chrome_apps_client.h"
     24 #include "chrome/browser/automation/automation_provider_list.h"
     25 #include "chrome/browser/background/background_mode_manager.h"
     26 #include "chrome/browser/chrome_browser_main.h"
     27 #include "chrome/browser/chrome_content_browser_client.h"
     28 #include "chrome/browser/chrome_notification_types.h"
     29 #include "chrome/browser/component_updater/component_updater_configurator.h"
     30 #include "chrome/browser/component_updater/component_updater_service.h"
     31 #include "chrome/browser/component_updater/pnacl/pnacl_component_installer.h"
     32 #include "chrome/browser/defaults.h"
     33 #include "chrome/browser/devtools/remote_debugging_server.h"
     34 #include "chrome/browser/download/download_request_limiter.h"
     35 #include "chrome/browser/download/download_status_updater.h"
     36 #include "chrome/browser/extensions/chrome_extensions_browser_client.h"
     37 #include "chrome/browser/extensions/event_router_forwarder.h"
     38 #include "chrome/browser/extensions/extension_renderer_state.h"
     39 #include "chrome/browser/first_run/upgrade_util.h"
     40 #include "chrome/browser/gpu/gl_string_manager.h"
     41 #include "chrome/browser/gpu/gpu_mode_manager.h"
     42 #include "chrome/browser/icon_manager.h"
     43 #include "chrome/browser/idle.h"
     44 #include "chrome/browser/intranet_redirect_detector.h"
     45 #include "chrome/browser/io_thread.h"
     46 #include "chrome/browser/lifetime/application_lifetime.h"
     47 #include "chrome/browser/metrics/metrics_service.h"
     48 #include "chrome/browser/metrics/thread_watcher.h"
     49 #include "chrome/browser/metrics/variations/variations_service.h"
     50 #include "chrome/browser/net/chrome_net_log.h"
     51 #include "chrome/browser/net/crl_set_fetcher.h"
     52 #include "chrome/browser/net/sdch_dictionary_fetcher.h"
     53 #include "chrome/browser/notifications/notification_ui_manager.h"
     54 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
     55 #include "chrome/browser/plugins/plugin_finder.h"
     56 #include "chrome/browser/prefs/browser_prefs.h"
     57 #include "chrome/browser/prefs/chrome_pref_service_factory.h"
     58 #include "chrome/browser/prerender/prerender_tracker.h"
     59 #include "chrome/browser/printing/background_printing_manager.h"
     60 #include "chrome/browser/printing/print_job_manager.h"
     61 #include "chrome/browser/printing/print_preview_dialog_controller.h"
     62 #include "chrome/browser/profiles/profile_manager.h"
     63 #include "chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.h"
     64 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
     65 #include "chrome/browser/shell_integration.h"
     66 #include "chrome/browser/status_icons/status_tray.h"
     67 #include "chrome/browser/storage_monitor/storage_monitor.h"
     68 #include "chrome/browser/thumbnails/render_widget_snapshot_taker.h"
     69 #include "chrome/browser/ui/bookmarks/bookmark_prompt_controller.h"
     70 #include "chrome/browser/ui/browser_finder.h"
     71 #include "chrome/browser/web_resource/promo_resource_service.h"
     72 #include "chrome/common/chrome_constants.h"
     73 #include "chrome/common/chrome_paths.h"
     74 #include "chrome/common/chrome_switches.h"
     75 #include "chrome/common/extensions/chrome_extensions_client.h"
     76 #include "chrome/common/extensions/extension_l10n_util.h"
     77 #include "chrome/common/pref_names.h"
     78 #include "chrome/common/switch_utils.h"
     79 #include "chrome/common/url_constants.h"
     80 #include "chrome/installer/util/google_update_constants.h"
     81 #include "components/policy/core/common/policy_service.h"
     82 #include "content/public/browser/browser_thread.h"
     83 #include "content/public/browser/child_process_security_policy.h"
     84 #include "content/public/browser/notification_details.h"
     85 #include "content/public/browser/plugin_service.h"
     86 #include "content/public/browser/render_process_host.h"
     87 #include "content/public/browser/resource_dispatcher_host.h"
     88 #include "extensions/common/constants.h"
     89 #include "net/socket/client_socket_pool_manager.h"
     90 #include "net/url_request/url_request_context_getter.h"
     91 #include "ui/base/l10n/l10n_util.h"
     92 #include "ui/message_center/message_center.h"
     93 
     94 #if defined(ENABLE_CONFIGURATION_POLICY)
     95 #include "chrome/browser/policy/browser_policy_connector.h"
     96 #else
     97 #include "components/policy/core/common/policy_service_stub.h"
     98 #endif  // defined(ENABLE_CONFIGURATION_POLICY)
     99 
    100 #if defined(OS_WIN)
    101 #include "base/win/windows_version.h"
    102 #include "ui/views/focus/view_storage.h"
    103 #elif defined(OS_MACOSX)
    104 #include "chrome/browser/chrome_browser_main_mac.h"
    105 #endif
    106 
    107 #if defined(USE_AURA)
    108 #include "ui/aura/env.h"
    109 #endif
    110 
    111 #if !defined(OS_ANDROID) && !defined(OS_IOS)
    112 #include "chrome/browser/media_galleries/media_file_system_registry.h"
    113 #endif
    114 
    115 #if defined(ENABLE_PLUGIN_INSTALLATION)
    116 #include "chrome/browser/plugins/plugins_resource_service.h"
    117 #endif
    118 
    119 #if defined(ENABLE_WEBRTC)
    120 #include "chrome/browser/media/webrtc_log_uploader.h"
    121 #endif
    122 
    123 #if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS)
    124 // How often to check if the persistent instance of Chrome needs to restart
    125 // to install an update.
    126 static const int kUpdateCheckIntervalHours = 6;
    127 #endif
    128 
    129 #if defined(OS_WIN)
    130 // Attest to the fact that the call to the file thread to save preferences has
    131 // run, and it is safe to terminate.  This avoids the potential of some other
    132 // task prematurely terminating our waiting message loop by posting a
    133 // QuitTask().
    134 static bool g_end_session_file_thread_has_completed = false;
    135 #endif
    136 
    137 #if defined(USE_X11)
    138 // How long to wait for the File thread to complete during EndSession, on
    139 // Linux. We have a timeout here because we're unable to run the UI messageloop
    140 // and there's some deadlock risk. Our only option is to exit anyway.
    141 static const int kEndSessionTimeoutSeconds = 10;
    142 #endif
    143 
    144 using content::BrowserThread;
    145 using content::ChildProcessSecurityPolicy;
    146 using content::PluginService;
    147 using content::ResourceDispatcherHost;
    148 
    149 BrowserProcessImpl::BrowserProcessImpl(
    150     base::SequencedTaskRunner* local_state_task_runner,
    151     const CommandLine& command_line)
    152     : created_metrics_service_(false),
    153       created_watchdog_thread_(false),
    154       created_browser_policy_connector_(false),
    155       created_profile_manager_(false),
    156       created_local_state_(false),
    157       created_icon_manager_(false),
    158       created_notification_ui_manager_(false),
    159       created_safe_browsing_service_(false),
    160       module_ref_count_(0),
    161       did_start_(false),
    162       checked_for_new_frames_(false),
    163       using_new_frames_(false),
    164       render_widget_snapshot_taker_(new RenderWidgetSnapshotTaker),
    165       download_status_updater_(new DownloadStatusUpdater),
    166       local_state_task_runner_(local_state_task_runner) {
    167   g_browser_process = this;
    168   platform_part_.reset(new BrowserProcessPlatformPart());
    169 
    170 #if defined(ENABLE_PRINTING)
    171   // Must be created after the NotificationService.
    172   print_job_manager_.reset(new printing::PrintJobManager);
    173 #endif
    174 
    175   net_log_.reset(new ChromeNetLog);
    176 
    177   ChildProcessSecurityPolicy::GetInstance()->RegisterWebSafeScheme(
    178       extensions::kExtensionScheme);
    179   ChildProcessSecurityPolicy::GetInstance()->RegisterWebSafeScheme(
    180       chrome::kExtensionResourceScheme);
    181   ChildProcessSecurityPolicy::GetInstance()->RegisterWebSafeScheme(
    182       chrome::kChromeSearchScheme);
    183 
    184 #if defined(OS_MACOSX)
    185   InitIdleMonitor();
    186 #endif
    187 
    188   apps::AppsClient::Set(ChromeAppsClient::GetInstance());
    189   extensions::ExtensionsClient::Set(
    190       extensions::ChromeExtensionsClient::GetInstance());
    191 
    192   extensions_browser_client_.reset(
    193       new extensions::ChromeExtensionsBrowserClient);
    194   extensions::ExtensionsBrowserClient::Set(extensions_browser_client_.get());
    195 
    196   extension_event_router_forwarder_ = new extensions::EventRouterForwarder;
    197   ExtensionRendererState::GetInstance()->Init();
    198 
    199   message_center::MessageCenter::Initialize();
    200 }
    201 
    202 BrowserProcessImpl::~BrowserProcessImpl() {
    203   tracked_objects::ThreadData::EnsureCleanupWasCalled(4);
    204 
    205   g_browser_process = NULL;
    206 }
    207 
    208 void BrowserProcessImpl::StartTearDown() {
    209     TRACE_EVENT0("shutdown", "BrowserProcessImpl::StartTearDown");
    210 #if defined(ENABLE_AUTOMATION)
    211   // Delete the AutomationProviderList before NotificationService,
    212   // since it may try to unregister notifications
    213   // Both NotificationService and AutomationProvider are singleton instances in
    214   // the BrowserProcess. Since AutomationProvider may have some active
    215   // notification observers, it is essential that it gets destroyed before the
    216   // NotificationService. NotificationService won't be destroyed until after
    217   // this destructor is run.
    218   automation_provider_list_.reset();
    219 #endif
    220 
    221   // We need to shutdown the SdchDictionaryFetcher as it regularly holds
    222   // a pointer to a URLFetcher, and that URLFetcher (upon destruction) will do
    223   // a PostDelayedTask onto the IO thread.  This shutdown call will both discard
    224   // any pending URLFetchers, and avoid creating any more.
    225   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
    226                           base::Bind(&SdchDictionaryFetcher::Shutdown));
    227 
    228   // We need to destroy the MetricsService, VariationsService,
    229   // IntranetRedirectDetector, PromoResourceService, and SafeBrowsing
    230   // ClientSideDetectionService (owned by the SafeBrowsingService) before the
    231   // io_thread_ gets destroyed, since their destructors can call the URLFetcher
    232   // destructor, which does a PostDelayedTask operation on the IO thread. (The
    233   // IO thread will handle that URLFetcher operation before going away.)
    234   metrics_service_.reset();
    235   variations_service_.reset();
    236   intranet_redirect_detector_.reset();
    237 #if defined(FULL_SAFE_BROWSING) || defined(MOBILE_SAFE_BROWSING)
    238   if (safe_browsing_service_.get())
    239     safe_browsing_service()->ShutDown();
    240 #endif
    241 
    242   // Need to clear the desktop notification balloons before the io_thread_ and
    243   // before the profiles, since if there are any still showing we will access
    244   // those things during teardown.
    245   notification_ui_manager_.reset();
    246 
    247   // Need to clear profiles (download managers) before the io_thread_.
    248   {
    249     TRACE_EVENT0("shutdown",
    250                  "BrowserProcessImpl::StartTearDown:ProfileManager");
    251     profile_manager_.reset();
    252   }
    253 
    254 #if !defined(OS_ANDROID)
    255   // Debugger must be cleaned up before IO thread and NotificationService.
    256   remote_debugging_server_.reset();
    257 #endif
    258 
    259   ExtensionRendererState::GetInstance()->Shutdown();
    260 
    261 #if !defined(OS_ANDROID) && !defined(OS_IOS)
    262   media_file_system_registry_.reset();
    263   // Delete |storage_monitor_| now. Otherwise the FILE thread would be gone
    264   // when we try to release it in the dtor and Valgrind would report a
    265   // leak on almost every single browser_test.
    266   // TODO(gbillock): Make this unnecessary.
    267   storage_monitor_.reset();
    268 #endif
    269 
    270   message_center::MessageCenter::Shutdown();
    271 
    272 #if defined(ENABLE_CONFIGURATION_POLICY)
    273   // The policy providers managed by |browser_policy_connector_| need to shut
    274   // down while the IO and FILE threads are still alive.
    275   if (browser_policy_connector_)
    276     browser_policy_connector_->Shutdown();
    277 #endif
    278 
    279   // Stop the watchdog thread before stopping other threads.
    280   watchdog_thread_.reset();
    281 
    282 #if defined(USE_AURA)
    283   // Delete aura after the metrics service has been deleted as it accesses
    284   // monitor information.
    285   aura::Env::DeleteInstance();
    286 #endif
    287 
    288   platform_part()->StartTearDown();
    289 
    290 #if defined(ENABLE_WEBRTC)
    291   webrtc_log_uploader_.reset();
    292 #endif
    293 }
    294 
    295 void BrowserProcessImpl::PostDestroyThreads() {
    296   // With the file_thread_ flushed, we can release any icon resources.
    297   icon_manager_.reset();
    298 
    299   // Reset associated state right after actual thread is stopped,
    300   // as io_thread_.global_ cleanup happens in CleanUp on the IO
    301   // thread, i.e. as the thread exits its message loop.
    302   //
    303   // This is important also because in various places, the
    304   // IOThread object being NULL is considered synonymous with the
    305   // IO thread having stopped.
    306   io_thread_.reset();
    307 }
    308 
    309 #if defined(OS_WIN)
    310 // Send a QuitTask to the given MessageLoop when the (file) thread has processed
    311 // our (other) recent requests (to save preferences).
    312 // Change the boolean so that the receiving thread will know that we did indeed
    313 // send the QuitTask that terminated the message loop.
    314 static void PostQuit(base::MessageLoop* message_loop) {
    315   g_end_session_file_thread_has_completed = true;
    316   message_loop->PostTask(FROM_HERE, base::MessageLoop::QuitClosure());
    317 }
    318 #elif defined(USE_X11)
    319 static void Signal(base::WaitableEvent* event) {
    320   event->Signal();
    321 }
    322 #endif
    323 
    324 unsigned int BrowserProcessImpl::AddRefModule() {
    325   DCHECK(CalledOnValidThread());
    326 
    327   // CHECK(!IsShuttingDown());
    328   if (IsShuttingDown()) {
    329     // Copy the stacktrace which released the final reference onto our stack so
    330     // it will be available in the crash report for inspection.
    331     base::debug::StackTrace callstack = release_last_reference_callstack_;
    332     base::debug::Alias(&callstack);
    333     CHECK(false);
    334   }
    335 
    336   did_start_ = true;
    337   module_ref_count_++;
    338   return module_ref_count_;
    339 }
    340 
    341 unsigned int BrowserProcessImpl::ReleaseModule() {
    342   DCHECK(CalledOnValidThread());
    343   DCHECK_NE(0u, module_ref_count_);
    344   module_ref_count_--;
    345   if (0 == module_ref_count_) {
    346     release_last_reference_callstack_ = base::debug::StackTrace();
    347 
    348 #if defined(ENABLE_PRINTING)
    349     // Wait for the pending print jobs to finish. Don't do this later, since
    350     // this might cause a nested message loop to run, and we don't want pending
    351     // tasks to run once teardown has started.
    352     print_job_manager_->Shutdown();
    353 #endif
    354 
    355 #if defined(LEAK_SANITIZER)
    356     // Check for memory leaks now, before we start shutting down threads. Doing
    357     // this early means we won't report any shutdown-only leaks (as they have
    358     // not yet happened at this point).
    359     // If leaks are found, this will make the process exit immediately.
    360     __lsan_do_leak_check();
    361 #endif
    362 
    363     CHECK(base::MessageLoop::current()->is_running());
    364 
    365 #if defined(OS_MACOSX)
    366     base::MessageLoop::current()->PostTask(
    367         FROM_HERE,
    368         base::Bind(ChromeBrowserMainPartsMac::DidEndMainMessageLoop));
    369 #endif
    370     base::MessageLoop::current()->Quit();
    371   }
    372   return module_ref_count_;
    373 }
    374 
    375 void BrowserProcessImpl::EndSession() {
    376   // Mark all the profiles as clean.
    377   ProfileManager* pm = profile_manager();
    378   std::vector<Profile*> profiles(pm->GetLoadedProfiles());
    379   for (size_t i = 0; i < profiles.size(); ++i)
    380     profiles[i]->SetExitType(Profile::EXIT_SESSION_ENDED);
    381 
    382   // Tell the metrics service it was cleanly shutdown.
    383   MetricsService* metrics = g_browser_process->metrics_service();
    384   if (metrics && local_state()) {
    385     metrics->RecordStartOfSessionEnd();
    386 #if !defined(OS_CHROMEOS)
    387     // MetricsService lazily writes to prefs, force it to write now.
    388     // On ChromeOS, chrome gets killed when hangs, so no need to
    389     // commit prefs::kStabilitySessionEndCompleted change immediately.
    390     local_state()->CommitPendingWrite();
    391 #endif
    392   }
    393 
    394   // http://crbug.com/125207
    395   base::ThreadRestrictions::ScopedAllowWait allow_wait;
    396 
    397   // We must write that the profile and metrics service shutdown cleanly,
    398   // otherwise on startup we'll think we crashed. So we block until done and
    399   // then proceed with normal shutdown.
    400 #if defined(USE_X11)
    401   //  Can't run a local loop on linux. Instead create a waitable event.
    402   scoped_ptr<base::WaitableEvent> done_writing(
    403       new base::WaitableEvent(false, false));
    404   BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
    405       base::Bind(Signal, done_writing.get()));
    406   // If all file writes haven't cleared in the timeout, leak the WaitableEvent
    407   // so that there's no race to reference it in Signal().
    408   if (!done_writing->TimedWait(
    409       base::TimeDelta::FromSeconds(kEndSessionTimeoutSeconds))) {
    410     ignore_result(done_writing.release());
    411   }
    412 
    413 #elif defined(OS_WIN)
    414   BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
    415       base::Bind(PostQuit, base::MessageLoop::current()));
    416   int quits_received = 0;
    417   do {
    418     base::MessageLoop::current()->Run();
    419     ++quits_received;
    420   } while (!g_end_session_file_thread_has_completed);
    421   // If we did get extra quits, then we should re-post them to the message loop.
    422   while (--quits_received > 0) {
    423     base::MessageLoop::current()->PostTask(FROM_HERE,
    424                                            base::MessageLoop::QuitClosure());
    425   }
    426 #else
    427   NOTIMPLEMENTED();
    428 #endif
    429 }
    430 
    431 MetricsService* BrowserProcessImpl::metrics_service() {
    432   DCHECK(CalledOnValidThread());
    433   if (!created_metrics_service_)
    434     CreateMetricsService();
    435   return metrics_service_.get();
    436 }
    437 
    438 IOThread* BrowserProcessImpl::io_thread() {
    439   DCHECK(CalledOnValidThread());
    440   DCHECK(io_thread_.get());
    441   return io_thread_.get();
    442 }
    443 
    444 WatchDogThread* BrowserProcessImpl::watchdog_thread() {
    445   DCHECK(CalledOnValidThread());
    446   if (!created_watchdog_thread_)
    447     CreateWatchdogThread();
    448   DCHECK(watchdog_thread_.get() != NULL);
    449   return watchdog_thread_.get();
    450 }
    451 
    452 ProfileManager* BrowserProcessImpl::profile_manager() {
    453   DCHECK(CalledOnValidThread());
    454   if (!created_profile_manager_)
    455     CreateProfileManager();
    456   return profile_manager_.get();
    457 }
    458 
    459 PrefService* BrowserProcessImpl::local_state() {
    460   DCHECK(CalledOnValidThread());
    461   if (!created_local_state_)
    462     CreateLocalState();
    463   return local_state_.get();
    464 }
    465 
    466 net::URLRequestContextGetter* BrowserProcessImpl::system_request_context() {
    467   DCHECK(CalledOnValidThread());
    468   return io_thread()->system_url_request_context_getter();
    469 }
    470 
    471 chrome_variations::VariationsService* BrowserProcessImpl::variations_service() {
    472   DCHECK(CalledOnValidThread());
    473   if (!variations_service_.get()) {
    474     variations_service_.reset(
    475         chrome_variations::VariationsService::Create(local_state()));
    476   }
    477   return variations_service_.get();
    478 }
    479 
    480 BrowserProcessPlatformPart* BrowserProcessImpl::platform_part() {
    481   return platform_part_.get();
    482 }
    483 
    484 extensions::EventRouterForwarder*
    485 BrowserProcessImpl::extension_event_router_forwarder() {
    486   return extension_event_router_forwarder_.get();
    487 }
    488 
    489 NotificationUIManager* BrowserProcessImpl::notification_ui_manager() {
    490   DCHECK(CalledOnValidThread());
    491   if (!created_notification_ui_manager_)
    492     CreateNotificationUIManager();
    493   return notification_ui_manager_.get();
    494 }
    495 
    496 message_center::MessageCenter* BrowserProcessImpl::message_center() {
    497   DCHECK(CalledOnValidThread());
    498   return message_center::MessageCenter::Get();
    499 }
    500 
    501 policy::BrowserPolicyConnector* BrowserProcessImpl::browser_policy_connector() {
    502   DCHECK(CalledOnValidThread());
    503 #if defined(ENABLE_CONFIGURATION_POLICY)
    504   if (!created_browser_policy_connector_) {
    505     DCHECK(!browser_policy_connector_);
    506     browser_policy_connector_.reset(new policy::BrowserPolicyConnector());
    507     created_browser_policy_connector_ = true;
    508   }
    509   return browser_policy_connector_.get();
    510 #else
    511   return NULL;
    512 #endif
    513 }
    514 
    515 policy::PolicyService* BrowserProcessImpl::policy_service() {
    516 #if defined(ENABLE_CONFIGURATION_POLICY)
    517   return browser_policy_connector()->GetPolicyService();
    518 #else
    519   if (!policy_service_.get())
    520     policy_service_.reset(new policy::PolicyServiceStub());
    521   return policy_service_.get();
    522 #endif
    523 }
    524 
    525 IconManager* BrowserProcessImpl::icon_manager() {
    526   DCHECK(CalledOnValidThread());
    527   if (!created_icon_manager_)
    528     CreateIconManager();
    529   return icon_manager_.get();
    530 }
    531 
    532 GLStringManager* BrowserProcessImpl::gl_string_manager() {
    533   DCHECK(CalledOnValidThread());
    534   if (!gl_string_manager_.get())
    535     gl_string_manager_.reset(new GLStringManager());
    536   return gl_string_manager_.get();
    537 }
    538 
    539 GpuModeManager* BrowserProcessImpl::gpu_mode_manager() {
    540   DCHECK(CalledOnValidThread());
    541   if (!gpu_mode_manager_.get())
    542     gpu_mode_manager_.reset(new GpuModeManager());
    543   return gpu_mode_manager_.get();
    544 }
    545 
    546 RenderWidgetSnapshotTaker* BrowserProcessImpl::GetRenderWidgetSnapshotTaker() {
    547   return render_widget_snapshot_taker_.get();
    548 }
    549 
    550 AutomationProviderList* BrowserProcessImpl::GetAutomationProviderList() {
    551   DCHECK(CalledOnValidThread());
    552 #if defined(ENABLE_AUTOMATION)
    553   if (automation_provider_list_.get() == NULL)
    554     automation_provider_list_.reset(new AutomationProviderList());
    555   return automation_provider_list_.get();
    556 #else
    557   return NULL;
    558 #endif
    559 }
    560 
    561 void BrowserProcessImpl::CreateDevToolsHttpProtocolHandler(
    562     chrome::HostDesktopType host_desktop_type,
    563     const std::string& ip,
    564     int port,
    565     const std::string& frontend_url) {
    566   DCHECK(CalledOnValidThread());
    567 #if !defined(OS_ANDROID)
    568   // StartupBrowserCreator::LaunchBrowser can be run multiple times when browser
    569   // is started with several profiles or existing browser process is reused.
    570   if (!remote_debugging_server_.get()) {
    571     remote_debugging_server_.reset(
    572         new RemoteDebuggingServer(host_desktop_type, ip, port,
    573                                   frontend_url));
    574   }
    575 #endif
    576 }
    577 
    578 bool BrowserProcessImpl::IsShuttingDown() {
    579   DCHECK(CalledOnValidThread());
    580   return did_start_ && 0 == module_ref_count_;
    581 }
    582 
    583 printing::PrintJobManager* BrowserProcessImpl::print_job_manager() {
    584   DCHECK(CalledOnValidThread());
    585   return print_job_manager_.get();
    586 }
    587 
    588 printing::PrintPreviewDialogController*
    589     BrowserProcessImpl::print_preview_dialog_controller() {
    590 #if defined(ENABLE_FULL_PRINTING)
    591   DCHECK(CalledOnValidThread());
    592   if (!print_preview_dialog_controller_.get())
    593     CreatePrintPreviewDialogController();
    594   return print_preview_dialog_controller_.get();
    595 #else
    596   NOTIMPLEMENTED();
    597   return NULL;
    598 #endif
    599 }
    600 
    601 printing::BackgroundPrintingManager*
    602     BrowserProcessImpl::background_printing_manager() {
    603 #if defined(ENABLE_FULL_PRINTING)
    604   DCHECK(CalledOnValidThread());
    605   if (!background_printing_manager_.get())
    606     CreateBackgroundPrintingManager();
    607   return background_printing_manager_.get();
    608 #else
    609   NOTIMPLEMENTED();
    610   return NULL;
    611 #endif
    612 }
    613 
    614 IntranetRedirectDetector* BrowserProcessImpl::intranet_redirect_detector() {
    615   DCHECK(CalledOnValidThread());
    616   if (!intranet_redirect_detector_.get())
    617     CreateIntranetRedirectDetector();
    618   return intranet_redirect_detector_.get();
    619 }
    620 
    621 const std::string& BrowserProcessImpl::GetApplicationLocale() {
    622   DCHECK(!locale_.empty());
    623   return locale_;
    624 }
    625 
    626 void BrowserProcessImpl::SetApplicationLocale(const std::string& locale) {
    627   locale_ = locale;
    628   extension_l10n_util::SetProcessLocale(locale);
    629   chrome::ChromeContentBrowserClient::SetApplicationLocale(locale);
    630 }
    631 
    632 DownloadStatusUpdater* BrowserProcessImpl::download_status_updater() {
    633   return download_status_updater_.get();
    634 }
    635 
    636 BookmarkPromptController* BrowserProcessImpl::bookmark_prompt_controller() {
    637 #if defined(OS_ANDROID)
    638   return NULL;
    639 #else
    640   return bookmark_prompt_controller_.get();
    641 #endif
    642 }
    643 
    644 StorageMonitor* BrowserProcessImpl::storage_monitor() {
    645 #if defined(OS_ANDROID) || defined(OS_IOS)
    646   return NULL;
    647 #else
    648   return storage_monitor_.get();
    649 #endif
    650 }
    651 
    652 void BrowserProcessImpl::set_storage_monitor_for_test(
    653     scoped_ptr<StorageMonitor> monitor) {
    654 #if !defined(OS_ANDROID) && !defined(OS_IOS)
    655   storage_monitor_ = monitor.Pass();
    656 #endif
    657 }
    658 
    659 MediaFileSystemRegistry* BrowserProcessImpl::media_file_system_registry() {
    660 #if defined(OS_ANDROID) || defined(OS_IOS)
    661     return NULL;
    662 #else
    663   if (!media_file_system_registry_)
    664     media_file_system_registry_.reset(new MediaFileSystemRegistry());
    665   return media_file_system_registry_.get();
    666 #endif
    667 }
    668 
    669 bool BrowserProcessImpl::created_local_state() const {
    670     return created_local_state_;
    671 }
    672 
    673 #if defined(ENABLE_WEBRTC)
    674 WebRtcLogUploader* BrowserProcessImpl::webrtc_log_uploader() {
    675   if (!webrtc_log_uploader_.get())
    676     webrtc_log_uploader_.reset(new WebRtcLogUploader());
    677   return webrtc_log_uploader_.get();
    678 }
    679 #endif
    680 
    681 // static
    682 void BrowserProcessImpl::RegisterPrefs(PrefRegistrySimple* registry) {
    683   registry->RegisterBooleanPref(prefs::kDefaultBrowserSettingEnabled,
    684                                 false);
    685   // This policy needs to be defined before the net subsystem is initialized,
    686   // so we do it here.
    687   registry->RegisterIntegerPref(prefs::kMaxConnectionsPerProxy,
    688                                 net::kDefaultMaxSocketsPerProxyServer);
    689 
    690   registry->RegisterBooleanPref(prefs::kAllowCrossOriginAuthPrompt, false);
    691 
    692 #if defined(OS_CHROMEOS) || defined(OS_ANDROID) || defined(OS_IOS)
    693   registry->RegisterBooleanPref(prefs::kEulaAccepted, false);
    694 #endif  // defined(OS_CHROMEOS) || defined(OS_ANDROID) || defined(OS_IOS)
    695 #if defined(OS_WIN)
    696   if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
    697     registry->RegisterStringPref(prefs::kRelaunchMode,
    698                                  upgrade_util::kRelaunchModeDefault);
    699   }
    700 #endif
    701 
    702   // TODO(brettw,*): this comment about ResourceBundle was here since
    703   // initial commit.  This comment seems unrelated, bit-rotten and
    704   // a candidate for removal.
    705   // Initialize ResourceBundle which handles files loaded from external
    706   // sources. This has to be done before uninstall code path and before prefs
    707   // are registered.
    708   registry->RegisterStringPref(prefs::kApplicationLocale, std::string());
    709 #if defined(OS_CHROMEOS)
    710   registry->RegisterStringPref(prefs::kOwnerLocale, std::string());
    711   registry->RegisterStringPref(prefs::kHardwareKeyboardLayout,
    712                                std::string());
    713 #endif  // defined(OS_CHROMEOS)
    714 #if !defined(OS_CHROMEOS)
    715   registry->RegisterBooleanPref(
    716       prefs::kMetricsReportingEnabled,
    717       GoogleUpdateSettings::GetCollectStatsConsent());
    718 #endif  // !defined(OS_CHROMEOS)
    719 
    720 #if defined(OS_ANDROID)
    721   registry->RegisterBooleanPref(
    722       prefs::kCrashReportingEnabled, false);
    723 #endif  // defined(OS_ANDROID)
    724 }
    725 
    726 DownloadRequestLimiter* BrowserProcessImpl::download_request_limiter() {
    727   DCHECK(CalledOnValidThread());
    728   if (!download_request_limiter_.get())
    729     download_request_limiter_ = new DownloadRequestLimiter();
    730   return download_request_limiter_.get();
    731 }
    732 
    733 BackgroundModeManager* BrowserProcessImpl::background_mode_manager() {
    734   DCHECK(CalledOnValidThread());
    735 #if defined(ENABLE_BACKGROUND)
    736   if (!background_mode_manager_.get())
    737     CreateBackgroundModeManager();
    738   return background_mode_manager_.get();
    739 #else
    740   NOTIMPLEMENTED();
    741   return NULL;
    742 #endif
    743 }
    744 
    745 void BrowserProcessImpl::set_background_mode_manager_for_test(
    746     scoped_ptr<BackgroundModeManager> manager) {
    747   background_mode_manager_ = manager.Pass();
    748 }
    749 
    750 StatusTray* BrowserProcessImpl::status_tray() {
    751   DCHECK(CalledOnValidThread());
    752   if (!status_tray_.get())
    753     CreateStatusTray();
    754   return status_tray_.get();
    755 }
    756 
    757 
    758 SafeBrowsingService* BrowserProcessImpl::safe_browsing_service() {
    759   DCHECK(CalledOnValidThread());
    760   if (!created_safe_browsing_service_)
    761     CreateSafeBrowsingService();
    762   return safe_browsing_service_.get();
    763 }
    764 
    765 safe_browsing::ClientSideDetectionService*
    766     BrowserProcessImpl::safe_browsing_detection_service() {
    767   DCHECK(CalledOnValidThread());
    768   if (safe_browsing_service())
    769     return safe_browsing_service()->safe_browsing_detection_service();
    770   return NULL;
    771 }
    772 
    773 #if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS)
    774 void BrowserProcessImpl::StartAutoupdateTimer() {
    775   autoupdate_timer_.Start(FROM_HERE,
    776       base::TimeDelta::FromHours(kUpdateCheckIntervalHours),
    777       this,
    778       &BrowserProcessImpl::OnAutoupdateTimer);
    779 }
    780 #endif
    781 
    782 ChromeNetLog* BrowserProcessImpl::net_log() {
    783   return net_log_.get();
    784 }
    785 
    786 prerender::PrerenderTracker* BrowserProcessImpl::prerender_tracker() {
    787   if (!prerender_tracker_.get())
    788     prerender_tracker_.reset(new prerender::PrerenderTracker);
    789 
    790   return prerender_tracker_.get();
    791 }
    792 
    793 ComponentUpdateService* BrowserProcessImpl::component_updater() {
    794   if (!component_updater_.get()) {
    795     if (!BrowserThread::CurrentlyOn(BrowserThread::UI))
    796       return NULL;
    797     ComponentUpdateService::Configurator* configurator =
    798         MakeChromeComponentUpdaterConfigurator(
    799             CommandLine::ForCurrentProcess(),
    800             io_thread()->system_url_request_context_getter());
    801     // Creating the component updater does not do anything, components
    802     // need to be registered and Start() needs to be called.
    803     component_updater_.reset(ComponentUpdateServiceFactory(configurator));
    804   }
    805   return component_updater_.get();
    806 }
    807 
    808 CRLSetFetcher* BrowserProcessImpl::crl_set_fetcher() {
    809   if (!crl_set_fetcher_.get())
    810     crl_set_fetcher_ = new CRLSetFetcher();
    811   return crl_set_fetcher_.get();
    812 }
    813 
    814 PnaclComponentInstaller* BrowserProcessImpl::pnacl_component_installer() {
    815   if (!pnacl_component_installer_.get())
    816     pnacl_component_installer_.reset(new PnaclComponentInstaller());
    817   return pnacl_component_installer_.get();
    818 }
    819 
    820 void BrowserProcessImpl::ResourceDispatcherHostCreated() {
    821   resource_dispatcher_host_delegate_.reset(
    822       new ChromeResourceDispatcherHostDelegate(prerender_tracker()));
    823   ResourceDispatcherHost::Get()->SetDelegate(
    824       resource_dispatcher_host_delegate_.get());
    825 
    826   pref_change_registrar_.Add(
    827       prefs::kAllowCrossOriginAuthPrompt,
    828       base::Bind(&BrowserProcessImpl::ApplyAllowCrossOriginAuthPromptPolicy,
    829                  base::Unretained(this)));
    830   ApplyAllowCrossOriginAuthPromptPolicy();
    831 }
    832 
    833 void BrowserProcessImpl::CreateMetricsService() {
    834   DCHECK(!created_metrics_service_ && metrics_service_.get() == NULL);
    835   created_metrics_service_ = true;
    836 
    837   metrics_service_.reset(new MetricsService);
    838 }
    839 
    840 void BrowserProcessImpl::CreateWatchdogThread() {
    841   DCHECK(!created_watchdog_thread_ && watchdog_thread_.get() == NULL);
    842   created_watchdog_thread_ = true;
    843 
    844   scoped_ptr<WatchDogThread> thread(new WatchDogThread());
    845   if (!thread->Start())
    846     return;
    847   watchdog_thread_.swap(thread);
    848 }
    849 
    850 void BrowserProcessImpl::CreateProfileManager() {
    851   DCHECK(!created_profile_manager_ && profile_manager_.get() == NULL);
    852   created_profile_manager_ = true;
    853 
    854   base::FilePath user_data_dir;
    855   PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
    856   profile_manager_.reset(new ProfileManager(user_data_dir));
    857 }
    858 
    859 void BrowserProcessImpl::CreateLocalState() {
    860   DCHECK(!created_local_state_ && local_state_.get() == NULL);
    861   created_local_state_ = true;
    862 
    863   base::FilePath local_state_path;
    864   CHECK(PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path));
    865   scoped_refptr<PrefRegistrySimple> pref_registry = new PrefRegistrySimple;
    866 
    867   // Register local state preferences.
    868   chrome::RegisterLocalState(pref_registry.get());
    869 
    870   local_state_ =
    871       chrome_prefs::CreateLocalState(local_state_path,
    872                                      local_state_task_runner_.get(),
    873                                      policy_service(),
    874                                      pref_registry,
    875                                      false).Pass();
    876 
    877   pref_change_registrar_.Init(local_state_.get());
    878 
    879   // Initialize the notification for the default browser setting policy.
    880   pref_change_registrar_.Add(
    881       prefs::kDefaultBrowserSettingEnabled,
    882       base::Bind(&BrowserProcessImpl::ApplyDefaultBrowserPolicy,
    883                  base::Unretained(this)));
    884 
    885   // This preference must be kept in sync with external values; update them
    886   // whenever the preference or its controlling policy changes.
    887 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) && !defined(OS_IOS)
    888   pref_change_registrar_.Add(
    889       prefs::kMetricsReportingEnabled,
    890       base::Bind(&BrowserProcessImpl::ApplyMetricsReportingPolicy,
    891                  base::Unretained(this)));
    892 #endif
    893 
    894   int max_per_proxy = local_state_->GetInteger(prefs::kMaxConnectionsPerProxy);
    895   net::ClientSocketPoolManager::set_max_sockets_per_proxy_server(
    896       net::HttpNetworkSession::NORMAL_SOCKET_POOL,
    897       std::max(std::min(max_per_proxy, 99),
    898                net::ClientSocketPoolManager::max_sockets_per_group(
    899                    net::HttpNetworkSession::NORMAL_SOCKET_POOL)));
    900 }
    901 
    902 void BrowserProcessImpl::PreCreateThreads() {
    903   io_thread_.reset(new IOThread(local_state(), policy_service(), net_log_.get(),
    904                                 extension_event_router_forwarder_.get()));
    905 }
    906 
    907 void BrowserProcessImpl::PreMainMessageLoopRun() {
    908 #if defined(ENABLE_CONFIGURATION_POLICY)
    909   // browser_policy_connector() is created very early because local_state()
    910   // needs policy to be initialized with the managed preference values.
    911   // However, policy fetches from the network and loading of disk caches
    912   // requires that threads are running; this Init() call lets the connector
    913   // resume its initialization now that the loops are spinning and the
    914   // system request context is available for the fetchers.
    915   browser_policy_connector()->Init(local_state(), system_request_context());
    916 #endif
    917 
    918   if (local_state_->IsManagedPreference(prefs::kDefaultBrowserSettingEnabled))
    919     ApplyDefaultBrowserPolicy();
    920 
    921 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) && !defined(OS_IOS)
    922   ApplyMetricsReportingPolicy();
    923 #endif
    924 
    925 #if defined(ENABLE_PLUGINS)
    926   PluginService* plugin_service = PluginService::GetInstance();
    927   plugin_service->SetFilter(ChromePluginServiceFilter::GetInstance());
    928   plugin_service->StartWatchingPlugins();
    929 
    930 #if defined(OS_POSIX)
    931   // Also find plugins in a user-specific plugins dir,
    932   // e.g. ~/.config/chromium/Plugins.
    933   const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
    934   if (!cmd_line.HasSwitch(switches::kDisablePluginsDiscovery)) {
    935     base::FilePath user_data_dir;
    936     if (PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
    937       plugin_service->AddExtraPluginDir(user_data_dir.Append("Plugins"));
    938   }
    939 #endif
    940 
    941   // Triggers initialization of the singleton instance on UI thread.
    942   PluginFinder::GetInstance()->Init();
    943 
    944 #if defined(ENABLE_PLUGIN_INSTALLATION)
    945   DCHECK(!plugins_resource_service_.get());
    946   plugins_resource_service_ = new PluginsResourceService(local_state());
    947   plugins_resource_service_->Init();
    948 #endif
    949 #endif  // defined(ENABLE_PLUGINS)
    950 
    951   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
    952   if (!command_line.HasSwitch(switches::kDisableWebResources)) {
    953     DCHECK(!promo_resource_service_.get());
    954     promo_resource_service_ = new PromoResourceService;
    955     promo_resource_service_->StartAfterDelay();
    956   }
    957 
    958 #if !defined(OS_ANDROID)
    959   if (browser_defaults::bookmarks_enabled &&
    960       BookmarkPromptController::IsEnabled()) {
    961     bookmark_prompt_controller_.reset(new BookmarkPromptController());
    962   }
    963 #endif
    964 
    965 #if !defined(OS_ANDROID) && !defined(OS_IOS)
    966   storage_monitor_.reset(StorageMonitor::Create());
    967 #endif
    968 
    969   platform_part_->PreMainMessageLoopRun();
    970 }
    971 
    972 void BrowserProcessImpl::CreateIconManager() {
    973   DCHECK(!created_icon_manager_ && icon_manager_.get() == NULL);
    974   created_icon_manager_ = true;
    975   icon_manager_.reset(new IconManager);
    976 }
    977 
    978 void BrowserProcessImpl::CreateIntranetRedirectDetector() {
    979   DCHECK(intranet_redirect_detector_.get() == NULL);
    980   scoped_ptr<IntranetRedirectDetector> intranet_redirect_detector(
    981       new IntranetRedirectDetector);
    982   intranet_redirect_detector_.swap(intranet_redirect_detector);
    983 }
    984 
    985 void BrowserProcessImpl::CreateNotificationUIManager() {
    986 #if defined(ENABLE_NOTIFICATIONS)
    987   DCHECK(notification_ui_manager_.get() == NULL);
    988   notification_ui_manager_.reset(NotificationUIManager::Create(local_state()));
    989   created_notification_ui_manager_ = true;
    990 #endif
    991 }
    992 
    993 void BrowserProcessImpl::CreateBackgroundModeManager() {
    994   DCHECK(background_mode_manager_.get() == NULL);
    995   background_mode_manager_.reset(
    996       new BackgroundModeManager(CommandLine::ForCurrentProcess(),
    997                                 &profile_manager()->GetProfileInfoCache()));
    998 }
    999 
   1000 void BrowserProcessImpl::CreateStatusTray() {
   1001   DCHECK(status_tray_.get() == NULL);
   1002   status_tray_.reset(StatusTray::Create());
   1003 }
   1004 
   1005 void BrowserProcessImpl::CreatePrintPreviewDialogController() {
   1006 #if defined(ENABLE_FULL_PRINTING)
   1007   DCHECK(print_preview_dialog_controller_.get() == NULL);
   1008   print_preview_dialog_controller_ =
   1009       new printing::PrintPreviewDialogController();
   1010 #else
   1011   NOTIMPLEMENTED();
   1012 #endif
   1013 }
   1014 
   1015 void BrowserProcessImpl::CreateBackgroundPrintingManager() {
   1016 #if defined(ENABLE_FULL_PRINTING)
   1017   DCHECK(background_printing_manager_.get() == NULL);
   1018   background_printing_manager_.reset(new printing::BackgroundPrintingManager());
   1019 #else
   1020   NOTIMPLEMENTED();
   1021 #endif
   1022 }
   1023 
   1024 void BrowserProcessImpl::CreateSafeBrowsingService() {
   1025   DCHECK(safe_browsing_service_.get() == NULL);
   1026   // Set this flag to true so that we don't retry indefinitely to
   1027   // create the service class if there was an error.
   1028   created_safe_browsing_service_ = true;
   1029 #if defined(FULL_SAFE_BROWSING) || defined(MOBILE_SAFE_BROWSING)
   1030   safe_browsing_service_ = SafeBrowsingService::CreateSafeBrowsingService();
   1031   safe_browsing_service_->Initialize();
   1032 #endif
   1033 }
   1034 
   1035 void BrowserProcessImpl::ApplyDefaultBrowserPolicy() {
   1036   if (local_state()->GetBoolean(prefs::kDefaultBrowserSettingEnabled)) {
   1037     scoped_refptr<ShellIntegration::DefaultWebClientWorker>
   1038         set_browser_worker = new ShellIntegration::DefaultBrowserWorker(NULL);
   1039     set_browser_worker->StartSetAsDefault();
   1040   }
   1041 }
   1042 
   1043 void BrowserProcessImpl::ApplyAllowCrossOriginAuthPromptPolicy() {
   1044   bool value = local_state()->GetBoolean(prefs::kAllowCrossOriginAuthPrompt);
   1045   ResourceDispatcherHost::Get()->SetAllowCrossOriginAuthPrompt(value);
   1046 }
   1047 
   1048 void BrowserProcessImpl::ApplyMetricsReportingPolicy() {
   1049 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) && !defined(OS_IOS)
   1050   CHECK(BrowserThread::PostTask(
   1051       BrowserThread::FILE, FROM_HERE,
   1052       base::Bind(
   1053           base::IgnoreResult(&GoogleUpdateSettings::SetCollectStatsConsent),
   1054           local_state()->GetBoolean(prefs::kMetricsReportingEnabled))));
   1055 #endif
   1056 }
   1057 
   1058 // Mac is currently not supported.
   1059 #if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS)
   1060 
   1061 bool BrowserProcessImpl::CanAutorestartForUpdate() const {
   1062   // Check if browser is in the background and if it needs to be restarted to
   1063   // apply a pending update.
   1064   return chrome::GetTotalBrowserCount() == 0 && chrome::WillKeepAlive() &&
   1065          upgrade_util::IsUpdatePendingRestart();
   1066 }
   1067 
   1068 // Switches to add when auto-restarting Chrome.
   1069 const char* const kSwitchesToAddOnAutorestart[] = {
   1070   switches::kNoStartupWindow
   1071 };
   1072 
   1073 void BrowserProcessImpl::RestartBackgroundInstance() {
   1074   CommandLine* old_cl = CommandLine::ForCurrentProcess();
   1075   scoped_ptr<CommandLine> new_cl(new CommandLine(old_cl->GetProgram()));
   1076 
   1077   std::map<std::string, CommandLine::StringType> switches =
   1078       old_cl->GetSwitches();
   1079 
   1080   switches::RemoveSwitchesForAutostart(&switches);
   1081 
   1082   // Append the rest of the switches (along with their values, if any)
   1083   // to the new command line
   1084   for (std::map<std::string, CommandLine::StringType>::const_iterator i =
   1085       switches.begin(); i != switches.end(); ++i) {
   1086       CommandLine::StringType switch_value = i->second;
   1087       if (switch_value.length() > 0) {
   1088         new_cl->AppendSwitchNative(i->first, i->second);
   1089       } else {
   1090         new_cl->AppendSwitch(i->first);
   1091       }
   1092   }
   1093 
   1094   // Ensure that our desired switches are set on the new process.
   1095   for (size_t i = 0; i < arraysize(kSwitchesToAddOnAutorestart); ++i) {
   1096     if (!new_cl->HasSwitch(kSwitchesToAddOnAutorestart[i]))
   1097       new_cl->AppendSwitch(kSwitchesToAddOnAutorestart[i]);
   1098   }
   1099 
   1100   DLOG(WARNING) << "Shutting down current instance of the browser.";
   1101   chrome::AttemptExit();
   1102 
   1103   // Transfer ownership to Upgrade.
   1104   upgrade_util::SetNewCommandLine(new_cl.release());
   1105 }
   1106 
   1107 void BrowserProcessImpl::OnAutoupdateTimer() {
   1108   if (CanAutorestartForUpdate()) {
   1109     DLOG(WARNING) << "Detected update.  Restarting browser.";
   1110     RestartBackgroundInstance();
   1111   }
   1112 }
   1113 
   1114 #endif  // (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS)
   1115