browser_process_impl.cc revision 3345a6884c488ff3a535c2c9acdd33d74b37e311
1// Copyright (c) 2010 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 <map> 8 9#include "app/clipboard/clipboard.h" 10#include "app/l10n_util.h" 11#include "base/command_line.h" 12#include "base/file_util.h" 13#include "base/path_service.h" 14#include "base/task.h" 15#include "base/thread.h" 16#include "base/waitable_event.h" 17#include "chrome/browser/appcache/chrome_appcache_service.h" 18#include "chrome/browser/automation/automation_provider_list.h" 19#include "chrome/browser/browser_child_process_host.h" 20#include "chrome/browser/browser_list.h" 21#include "chrome/browser/browser_main.h" 22#include "chrome/browser/browser_process_sub_thread.h" 23#include "chrome/browser/browser_trial.h" 24#include "chrome/browser/chrome_thread.h" 25#include "chrome/browser/debugger/debugger_wrapper.h" 26#include "chrome/browser/debugger/devtools_manager.h" 27#include "chrome/browser/download/download_file_manager.h" 28#include "chrome/browser/download/save_file_manager.h" 29#include "chrome/browser/first_run/first_run.h" 30#include "chrome/browser/google/google_url_tracker.h" 31#include "chrome/browser/icon_manager.h" 32#include "chrome/browser/in_process_webkit/dom_storage_context.h" 33#include "chrome/browser/intranet_redirect_detector.h" 34#include "chrome/browser/io_thread.h" 35#include "chrome/browser/metrics/metrics_service.h" 36#include "chrome/browser/net/predictor_api.h" 37#include "chrome/browser/net/sdch_dictionary_fetcher.h" 38#include "chrome/browser/net/sqlite_persistent_cookie_store.h" 39#include "chrome/browser/notifications/notification_ui_manager.h" 40#include "chrome/browser/plugin_service.h" 41#include "chrome/browser/plugin_updater.h" 42#include "chrome/browser/prefs/pref_service.h" 43#include "chrome/browser/printing/print_job_manager.h" 44#include "chrome/browser/profile_manager.h" 45#include "chrome/browser/renderer_host/render_process_host.h" 46#include "chrome/browser/renderer_host/resource_dispatcher_host.h" 47#include "chrome/browser/safe_browsing/safe_browsing_service.h" 48#include "chrome/browser/sidebar/sidebar_manager.h" 49#include "chrome/browser/tab_closeable_state_watcher.h" 50#include "chrome/common/chrome_constants.h" 51#include "chrome/common/chrome_paths.h" 52#include "chrome/common/chrome_switches.h" 53#include "chrome/common/extensions/extension_resource.h" 54#include "chrome/common/extensions/extension_l10n_util.h" 55#include "chrome/common/json_pref_store.h" 56#include "chrome/common/notification_service.h" 57#include "chrome/common/pref_names.h" 58#include "chrome/common/url_constants.h" 59#include "chrome/common/switch_utils.h" 60#include "chrome/installer/util/google_update_constants.h" 61#include "ipc/ipc_logging.h" 62#include "webkit/database/database_tracker.h" 63 64#if defined(OS_WIN) 65#include "views/focus/view_storage.h" 66#endif 67 68#if defined(IPC_MESSAGE_LOG_ENABLED) 69#include "chrome/common/plugin_messages.h" 70#include "chrome/common/render_messages.h" 71#endif 72 73#if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS) 74// How often to check if the persistent instance of Chrome needs to restart 75// to install an update. 76static const int kUpdateCheckIntervalHours = 6; 77#endif 78 79#if defined(USE_X11) 80// How long to wait for the File thread to complete during EndSession, on 81// Linux. We have a timeout here because we're unable to run the UI messageloop 82// and there's some deadlock risk. Our only option is to exit anyway. 83static const int kEndSessionTimeoutSeconds = 10; 84#endif 85 86BrowserProcessImpl::BrowserProcessImpl(const CommandLine& command_line) 87 : created_resource_dispatcher_host_(false), 88 created_metrics_service_(false), 89 created_io_thread_(false), 90 created_file_thread_(false), 91 created_db_thread_(false), 92 created_process_launcher_thread_(false), 93 created_cache_thread_(false), 94 created_profile_manager_(false), 95 created_local_state_(false), 96 created_icon_manager_(false), 97 created_debugger_wrapper_(false), 98 created_devtools_manager_(false), 99 created_sidebar_manager_(false), 100 created_notification_ui_manager_(false), 101 module_ref_count_(0), 102 did_start_(false), 103 checked_for_new_frames_(false), 104 using_new_frames_(false), 105 have_inspector_files_(true) { 106 g_browser_process = this; 107 clipboard_.reset(new Clipboard); 108 main_notification_service_.reset(new NotificationService); 109 110 // Must be created after the NotificationService. 111 print_job_manager_.reset(new printing::PrintJobManager); 112 113 shutdown_event_.reset(new base::WaitableEvent(true, false)); 114} 115 116BrowserProcessImpl::~BrowserProcessImpl() { 117 FilePath profile_path; 118 bool clear_local_state_on_exit; 119 120 // Store the profile path for clearing local state data on exit. 121 clear_local_state_on_exit = ShouldClearLocalState(&profile_path); 122 123 // Delete the AutomationProviderList before NotificationService, 124 // since it may try to unregister notifications 125 // Both NotificationService and AutomationProvider are singleton instances in 126 // the BrowserProcess. Since AutomationProvider may have some active 127 // notification observers, it is essential that it gets destroyed before the 128 // NotificationService. NotificationService won't be destroyed until after 129 // this destructor is run. 130 automation_provider_list_.reset(); 131 132 // We need to shutdown the SdchDictionaryFetcher as it regularly holds 133 // a pointer to a URLFetcher, and that URLFetcher (upon destruction) will do 134 // a PostDelayedTask onto the IO thread. This shutdown call will both discard 135 // any pending URLFetchers, and avoid creating any more. 136 SdchDictionaryFetcher::Shutdown(); 137 138 // We need to destroy the MetricsService, GoogleURLTracker, and 139 // IntranetRedirectDetector before the io_thread_ gets destroyed, since their 140 // destructors can call the URLFetcher destructor, which does a 141 // PostDelayedTask operation on the IO thread. (The IO thread will handle 142 // that URLFetcher operation before going away.) 143 metrics_service_.reset(); 144 google_url_tracker_.reset(); 145 intranet_redirect_detector_.reset(); 146 147 // Need to clear the desktop notification balloons before the io_thread_ and 148 // before the profiles, since if there are any still showing we will access 149 // those things during teardown. 150 notification_ui_manager_.reset(); 151 152 // Need to clear profiles (download managers) before the io_thread_. 153 profile_manager_.reset(); 154 155 // Debugger must be cleaned up before IO thread and NotificationService. 156 debugger_wrapper_ = NULL; 157 158 if (resource_dispatcher_host_.get()) { 159 // Need to tell Safe Browsing Service that the IO thread is going away 160 // since it cached a pointer to it. 161 if (resource_dispatcher_host()->safe_browsing_service()) 162 resource_dispatcher_host()->safe_browsing_service()->ShutDown(); 163 164 // Cancel pending requests and prevent new requests. 165 resource_dispatcher_host()->Shutdown(); 166 } 167 168#if defined(USE_X11) 169 // The IO thread must outlive the BACKGROUND_X11 thread. 170 background_x11_thread_.reset(); 171#endif 172 173 // Need to stop io_thread_ before resource_dispatcher_host_, since 174 // io_thread_ may still deref ResourceDispatcherHost and handle resource 175 // request before going away. 176 io_thread_.reset(); 177 178 // The IO thread was the only user of this thread. 179 cache_thread_.reset(); 180 181 // Stop the process launcher thread after the IO thread, in case the IO thread 182 // posted a task to terminate a process on the process launcher thread. 183 process_launcher_thread_.reset(); 184 185 // Clean up state that lives on the file_thread_ before it goes away. 186 if (resource_dispatcher_host_.get()) { 187 resource_dispatcher_host()->download_file_manager()->Shutdown(); 188 resource_dispatcher_host()->save_file_manager()->Shutdown(); 189 } 190 191 // Need to stop the file_thread_ here to force it to process messages in its 192 // message loop from the previous call to shutdown the DownloadFileManager, 193 // SaveFileManager and SessionService. 194 file_thread_.reset(); 195 196 // With the file_thread_ flushed, we can release any icon resources. 197 icon_manager_.reset(); 198 199 // Need to destroy ResourceDispatcherHost before PluginService and 200 // SafeBrowsingService, since it caches a pointer to it. This also 201 // causes the webkit thread to terminate. 202 resource_dispatcher_host_.reset(); 203 204 // Wait for the pending print jobs to finish. 205 print_job_manager_->OnQuit(); 206 print_job_manager_.reset(); 207 208 // Destroy TabCloseableStateWatcher before NotificationService since the 209 // former registers for notifications. 210 tab_closeable_state_watcher_.reset(); 211 212 // Now OK to destroy NotificationService. 213 main_notification_service_.reset(); 214 215 // Prior to clearing local state, we want to complete tasks pending 216 // on the db thread too. 217 db_thread_.reset(); 218 219 // At this point, no render process exist and the file, io, db, and 220 // webkit threads in this process have all terminated, so it's safe 221 // to access local state data such as cookies, database, or local storage. 222 if (clear_local_state_on_exit) 223 ClearLocalState(profile_path); 224 225 g_browser_process = NULL; 226} 227 228#if defined(OS_WIN) 229// Send a QuitTask to the given MessageLoop. 230static void PostQuit(MessageLoop* message_loop) { 231 message_loop->PostTask(FROM_HERE, new MessageLoop::QuitTask()); 232} 233#elif defined(USE_X11) 234static void Signal(base::WaitableEvent* event) { 235 event->Signal(); 236} 237#endif 238 239unsigned int BrowserProcessImpl::AddRefModule() { 240 DCHECK(CalledOnValidThread()); 241 did_start_ = true; 242 module_ref_count_++; 243 return module_ref_count_; 244} 245 246unsigned int BrowserProcessImpl::ReleaseModule() { 247 DCHECK(CalledOnValidThread()); 248 DCHECK_NE(0u, module_ref_count_); 249 module_ref_count_--; 250 if (0 == module_ref_count_) { 251 MessageLoop::current()->PostTask( 252 FROM_HERE, NewRunnableFunction(DidEndMainMessageLoop)); 253 MessageLoop::current()->Quit(); 254 } 255 return module_ref_count_; 256} 257 258void BrowserProcessImpl::EndSession() { 259#if defined(OS_WIN) || defined(USE_X11) 260 // Notify we are going away. 261 shutdown_event_->Signal(); 262#endif 263 264 // Mark all the profiles as clean. 265 ProfileManager* pm = profile_manager(); 266 for (ProfileManager::const_iterator i = pm->begin(); i != pm->end(); ++i) 267 (*i)->MarkAsCleanShutdown(); 268 269 // Tell the metrics service it was cleanly shutdown. 270 MetricsService* metrics = g_browser_process->metrics_service(); 271 if (metrics && local_state()) { 272 metrics->RecordCleanShutdown(); 273 274 metrics->RecordStartOfSessionEnd(); 275 276 // MetricsService lazily writes to prefs, force it to write now. 277 local_state()->SavePersistentPrefs(); 278 } 279 280 // We must write that the profile and metrics service shutdown cleanly, 281 // otherwise on startup we'll think we crashed. So we block until done and 282 // then proceed with normal shutdown. 283#if defined(USE_X11) 284 // Can't run a local loop on linux. Instead create a waitable event. 285 base::WaitableEvent done_writing(false, false); 286 ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE, 287 NewRunnableFunction(Signal, &done_writing)); 288 done_writing.TimedWait( 289 base::TimeDelta::FromSeconds(kEndSessionTimeoutSeconds)); 290#elif defined(OS_WIN) 291 ChromeThread::PostTask(ChromeThread::FILE, FROM_HERE, 292 NewRunnableFunction(PostQuit, MessageLoop::current())); 293 MessageLoop::current()->Run(); 294#else 295 NOTIMPLEMENTED(); 296#endif 297} 298 299ResourceDispatcherHost* BrowserProcessImpl::resource_dispatcher_host() { 300 DCHECK(CalledOnValidThread()); 301 if (!created_resource_dispatcher_host_) 302 CreateResourceDispatcherHost(); 303 return resource_dispatcher_host_.get(); 304} 305 306MetricsService* BrowserProcessImpl::metrics_service() { 307 DCHECK(CalledOnValidThread()); 308 if (!created_metrics_service_) 309 CreateMetricsService(); 310 return metrics_service_.get(); 311} 312 313IOThread* BrowserProcessImpl::io_thread() { 314 DCHECK(CalledOnValidThread()); 315 if (!created_io_thread_) 316 CreateIOThread(); 317 return io_thread_.get(); 318} 319 320base::Thread* BrowserProcessImpl::file_thread() { 321 DCHECK(CalledOnValidThread()); 322 if (!created_file_thread_) 323 CreateFileThread(); 324 return file_thread_.get(); 325} 326 327base::Thread* BrowserProcessImpl::db_thread() { 328 DCHECK(CalledOnValidThread()); 329 if (!created_db_thread_) 330 CreateDBThread(); 331 return db_thread_.get(); 332} 333 334base::Thread* BrowserProcessImpl::process_launcher_thread() { 335 DCHECK(CalledOnValidThread()); 336 if (!created_process_launcher_thread_) 337 CreateProcessLauncherThread(); 338 return process_launcher_thread_.get(); 339} 340 341base::Thread* BrowserProcessImpl::cache_thread() { 342 DCHECK(CalledOnValidThread()); 343 if (!created_cache_thread_) 344 CreateCacheThread(); 345 return cache_thread_.get(); 346} 347 348#if defined(USE_X11) 349base::Thread* BrowserProcessImpl::background_x11_thread() { 350 DCHECK(CalledOnValidThread()); 351 // The BACKGROUND_X11 thread is created when the IO thread is created. 352 if (!created_io_thread_) 353 CreateIOThread(); 354 return background_x11_thread_.get(); 355} 356#endif 357 358ProfileManager* BrowserProcessImpl::profile_manager() { 359 DCHECK(CalledOnValidThread()); 360 if (!created_profile_manager_) 361 CreateProfileManager(); 362 return profile_manager_.get(); 363} 364 365PrefService* BrowserProcessImpl::local_state() { 366 DCHECK(CalledOnValidThread()); 367 if (!created_local_state_) 368 CreateLocalState(); 369 return local_state_.get(); 370} 371 372DevToolsManager* BrowserProcessImpl::devtools_manager() { 373 DCHECK(CalledOnValidThread()); 374 if (!created_devtools_manager_) 375 CreateDevToolsManager(); 376 return devtools_manager_.get(); 377} 378 379SidebarManager* BrowserProcessImpl::sidebar_manager() { 380 DCHECK(CalledOnValidThread()); 381 if (!created_sidebar_manager_) 382 CreateSidebarManager(); 383 return sidebar_manager_.get(); 384} 385 386Clipboard* BrowserProcessImpl::clipboard() { 387 DCHECK(CalledOnValidThread()); 388 return clipboard_.get(); 389} 390 391NotificationUIManager* BrowserProcessImpl::notification_ui_manager() { 392 DCHECK(CalledOnValidThread()); 393 if (!created_notification_ui_manager_) 394 CreateNotificationUIManager(); 395 return notification_ui_manager_.get(); 396} 397 398IconManager* BrowserProcessImpl::icon_manager() { 399 DCHECK(CalledOnValidThread()); 400 if (!created_icon_manager_) 401 CreateIconManager(); 402 return icon_manager_.get(); 403} 404 405ThumbnailGenerator* BrowserProcessImpl::GetThumbnailGenerator() { 406 return &thumbnail_generator_; 407} 408 409AutomationProviderList* BrowserProcessImpl::InitAutomationProviderList() { 410 DCHECK(CalledOnValidThread()); 411 if (automation_provider_list_.get() == NULL) { 412 automation_provider_list_.reset(AutomationProviderList::GetInstance()); 413 } 414 return automation_provider_list_.get(); 415} 416 417void BrowserProcessImpl::InitDebuggerWrapper(int port, bool useHttp) { 418 DCHECK(CalledOnValidThread()); 419 if (!created_debugger_wrapper_) 420 CreateDebuggerWrapper(port, useHttp); 421} 422 423bool BrowserProcessImpl::IsShuttingDown() { 424 DCHECK(CalledOnValidThread()); 425 return did_start_ && 0 == module_ref_count_; 426} 427 428printing::PrintJobManager* BrowserProcessImpl::print_job_manager() { 429 // TODO(abarth): DCHECK(CalledOnValidThread()); 430 // http://code.google.com/p/chromium/issues/detail?id=6828 431 // print_job_manager_ is initialized in the constructor and destroyed in the 432 // destructor, so it should always be valid. 433 DCHECK(print_job_manager_.get()); 434 return print_job_manager_.get(); 435} 436 437GoogleURLTracker* BrowserProcessImpl::google_url_tracker() { 438 DCHECK(CalledOnValidThread()); 439 if (!google_url_tracker_.get()) 440 CreateGoogleURLTracker(); 441 return google_url_tracker_.get(); 442} 443 444IntranetRedirectDetector* BrowserProcessImpl::intranet_redirect_detector() { 445 DCHECK(CalledOnValidThread()); 446 if (!intranet_redirect_detector_.get()) 447 CreateIntranetRedirectDetector(); 448 return intranet_redirect_detector_.get(); 449} 450 451const std::string& BrowserProcessImpl::GetApplicationLocale() { 452 DCHECK(!locale_.empty()); 453 return locale_; 454} 455 456void BrowserProcessImpl::SetApplicationLocale(const std::string& locale) { 457 locale_ = locale; 458 extension_l10n_util::SetProcessLocale(locale); 459} 460 461DownloadStatusUpdater* BrowserProcessImpl::download_status_updater() { 462 return &download_status_updater_; 463} 464 465base::WaitableEvent* BrowserProcessImpl::shutdown_event() { 466 return shutdown_event_.get(); 467} 468 469TabCloseableStateWatcher* BrowserProcessImpl::tab_closeable_state_watcher() { 470 DCHECK(CalledOnValidThread()); 471 if (!tab_closeable_state_watcher_.get()) 472 CreateTabCloseableStateWatcher(); 473 return tab_closeable_state_watcher_.get(); 474} 475 476void BrowserProcessImpl::CheckForInspectorFiles() { 477 file_thread()->message_loop()->PostTask 478 (FROM_HERE, 479 NewRunnableMethod(this, &BrowserProcessImpl::DoInspectorFilesCheck)); 480} 481 482#if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS) 483void BrowserProcessImpl::StartAutoupdateTimer() { 484 autoupdate_timer_.Start( 485 base::TimeDelta::FromHours(kUpdateCheckIntervalHours), 486 this, 487 &BrowserProcessImpl::OnAutoupdateTimer); 488} 489#endif 490 491bool BrowserProcessImpl::have_inspector_files() const { 492 return have_inspector_files_; 493} 494 495void BrowserProcessImpl::ClearLocalState(const FilePath& profile_path) { 496 SQLitePersistentCookieStore::ClearLocalState(profile_path.Append( 497 chrome::kCookieFilename)); 498 DOMStorageContext::ClearLocalState(profile_path, chrome::kExtensionScheme); 499 webkit_database::DatabaseTracker::ClearLocalState(profile_path); 500 ChromeAppCacheService::ClearLocalState(profile_path); 501} 502 503bool BrowserProcessImpl::ShouldClearLocalState(FilePath* profile_path) { 504 FilePath user_data_dir; 505 Profile* profile; 506 507 // Check for the existence of a profile manager. When quitting early, 508 // e.g. because another chrome instance is running, or when invoked with 509 // options such as --uninstall or --try-chrome-again=0, the profile manager 510 // does not exist yet. 511 if (!profile_manager_.get()) 512 return false; 513 514 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); 515 profile = profile_manager_->GetDefaultProfile(user_data_dir); 516 if (!profile) 517 return false; 518 *profile_path = profile->GetPath(); 519 return profile->GetPrefs()->GetBoolean(prefs::kClearSiteDataOnExit); 520} 521 522void BrowserProcessImpl::CreateResourceDispatcherHost() { 523 DCHECK(!created_resource_dispatcher_host_ && 524 resource_dispatcher_host_.get() == NULL); 525 created_resource_dispatcher_host_ = true; 526 527 resource_dispatcher_host_.reset(new ResourceDispatcherHost()); 528 resource_dispatcher_host_->Initialize(); 529} 530 531void BrowserProcessImpl::CreateMetricsService() { 532 DCHECK(!created_metrics_service_ && metrics_service_.get() == NULL); 533 created_metrics_service_ = true; 534 535 metrics_service_.reset(new MetricsService); 536} 537 538void BrowserProcessImpl::CreateIOThread() { 539 DCHECK(!created_io_thread_ && io_thread_.get() == NULL); 540 created_io_thread_ = true; 541 542 // Prior to starting the io thread, we create the plugin service as 543 // it is predominantly used from the io thread, but must be created 544 // on the main thread. The service ctor is inexpensive and does not 545 // invoke the io_thread() accessor. 546 PluginService::GetInstance(); 547 548#if defined(USE_X11) 549 // The lifetime of the BACKGROUND_X11 thread is a subset of the IO thread so 550 // we start it now. 551 scoped_ptr<base::Thread> background_x11_thread( 552 new BrowserProcessSubThread(ChromeThread::BACKGROUND_X11)); 553 if (!background_x11_thread->Start()) 554 return; 555 background_x11_thread_.swap(background_x11_thread); 556#endif 557 558 scoped_ptr<IOThread> thread(new IOThread); 559 base::Thread::Options options; 560 options.message_loop_type = MessageLoop::TYPE_IO; 561 if (!thread->StartWithOptions(options)) 562 return; 563 io_thread_.swap(thread); 564} 565 566void BrowserProcessImpl::CreateFileThread() { 567 DCHECK(!created_file_thread_ && file_thread_.get() == NULL); 568 created_file_thread_ = true; 569 570 scoped_ptr<base::Thread> thread( 571 new BrowserProcessSubThread(ChromeThread::FILE)); 572 base::Thread::Options options; 573#if defined(OS_WIN) 574 // On Windows, the FILE thread needs to be have a UI message loop which pumps 575 // messages in such a way that Google Update can communicate back to us. 576 options.message_loop_type = MessageLoop::TYPE_UI; 577#else 578 options.message_loop_type = MessageLoop::TYPE_IO; 579#endif 580 if (!thread->StartWithOptions(options)) 581 return; 582 file_thread_.swap(thread); 583 584 // ExtensionResource is in chrome/common, so it cannot depend on 585 // chrome/browser, which means it cannot lookup what the File thread is. 586 // We therefore store the thread ID from here so we can validate the proper 587 // thread usage in the ExtensionResource class. 588 ExtensionResource::set_file_thread_id(file_thread_->thread_id()); 589} 590 591void BrowserProcessImpl::CreateDBThread() { 592 DCHECK(!created_db_thread_ && db_thread_.get() == NULL); 593 created_db_thread_ = true; 594 595 scoped_ptr<base::Thread> thread( 596 new BrowserProcessSubThread(ChromeThread::DB)); 597 if (!thread->Start()) 598 return; 599 db_thread_.swap(thread); 600} 601 602void BrowserProcessImpl::CreateProcessLauncherThread() { 603 DCHECK(!created_process_launcher_thread_ && !process_launcher_thread_.get()); 604 created_process_launcher_thread_ = true; 605 606 scoped_ptr<base::Thread> thread( 607 new BrowserProcessSubThread(ChromeThread::PROCESS_LAUNCHER)); 608 if (!thread->Start()) 609 return; 610 process_launcher_thread_.swap(thread); 611} 612 613void BrowserProcessImpl::CreateCacheThread() { 614 DCHECK(!created_cache_thread_ && !cache_thread_.get()); 615 created_cache_thread_ = true; 616 617 scoped_ptr<base::Thread> thread( 618 new BrowserProcessSubThread(ChromeThread::CACHE)); 619 base::Thread::Options options; 620 options.message_loop_type = MessageLoop::TYPE_IO; 621 if (!thread->StartWithOptions(options)) 622 return; 623 cache_thread_.swap(thread); 624} 625 626void BrowserProcessImpl::CreateProfileManager() { 627 DCHECK(!created_profile_manager_ && profile_manager_.get() == NULL); 628 created_profile_manager_ = true; 629 630 profile_manager_.reset(new ProfileManager()); 631} 632 633void BrowserProcessImpl::CreateLocalState() { 634 DCHECK(!created_local_state_ && local_state_.get() == NULL); 635 created_local_state_ = true; 636 637 FilePath local_state_path; 638 PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path); 639 local_state_.reset(PrefService::CreatePrefService(local_state_path, NULL)); 640 641 // Make sure the the plugin updater gets notifications of changes 642 // in the plugin blacklist. 643 local_state_->RegisterListPref(prefs::kPluginsPluginsBlacklist); 644 plugin_state_change_registrar_.Init(local_state_.get()); 645 plugin_state_change_registrar_.Add(prefs::kPluginsPluginsBlacklist, 646 PluginUpdater::GetPluginUpdater()); 647} 648 649void BrowserProcessImpl::CreateIconManager() { 650 DCHECK(!created_icon_manager_ && icon_manager_.get() == NULL); 651 created_icon_manager_ = true; 652 icon_manager_.reset(new IconManager); 653} 654 655void BrowserProcessImpl::CreateDebuggerWrapper(int port, bool useHttp) { 656 DCHECK(debugger_wrapper_.get() == NULL); 657 created_debugger_wrapper_ = true; 658 659 debugger_wrapper_ = new DebuggerWrapper(port, useHttp); 660} 661 662void BrowserProcessImpl::CreateDevToolsManager() { 663 DCHECK(devtools_manager_.get() == NULL); 664 created_devtools_manager_ = true; 665 devtools_manager_ = new DevToolsManager(); 666} 667 668void BrowserProcessImpl::CreateSidebarManager() { 669 DCHECK(sidebar_manager_.get() == NULL); 670 created_sidebar_manager_ = true; 671 sidebar_manager_ = new SidebarManager(); 672} 673 674void BrowserProcessImpl::CreateGoogleURLTracker() { 675 DCHECK(google_url_tracker_.get() == NULL); 676 scoped_ptr<GoogleURLTracker> google_url_tracker(new GoogleURLTracker); 677 google_url_tracker_.swap(google_url_tracker); 678} 679 680void BrowserProcessImpl::CreateIntranetRedirectDetector() { 681 DCHECK(intranet_redirect_detector_.get() == NULL); 682 scoped_ptr<IntranetRedirectDetector> intranet_redirect_detector( 683 new IntranetRedirectDetector); 684 intranet_redirect_detector_.swap(intranet_redirect_detector); 685} 686 687void BrowserProcessImpl::CreateNotificationUIManager() { 688 DCHECK(notification_ui_manager_.get() == NULL); 689 notification_ui_manager_.reset(NotificationUIManager::Create()); 690 created_notification_ui_manager_ = true; 691} 692 693void BrowserProcessImpl::CreateTabCloseableStateWatcher() { 694 DCHECK(tab_closeable_state_watcher_.get() == NULL); 695 tab_closeable_state_watcher_.reset(TabCloseableStateWatcher::Create()); 696} 697 698// The BrowserProcess object must outlive the file thread so we use traits 699// which don't do any management. 700DISABLE_RUNNABLE_METHOD_REFCOUNT(BrowserProcessImpl); 701 702#if defined(IPC_MESSAGE_LOG_ENABLED) 703 704void BrowserProcessImpl::SetIPCLoggingEnabled(bool enable) { 705 // First enable myself. 706 if (enable) 707 IPC::Logging::current()->Enable(); 708 else 709 IPC::Logging::current()->Disable(); 710 711 // Now tell subprocesses. Messages to ChildProcess-derived 712 // processes must be done on the IO thread. 713 io_thread()->message_loop()->PostTask 714 (FROM_HERE, 715 NewRunnableMethod( 716 this, 717 &BrowserProcessImpl::SetIPCLoggingEnabledForChildProcesses, 718 enable)); 719 720 // Finally, tell the renderers which don't derive from ChildProcess. 721 // Messages to the renderers must be done on the UI (main) thread. 722 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator()); 723 !i.IsAtEnd(); i.Advance()) 724 i.GetCurrentValue()->Send(new ViewMsg_SetIPCLoggingEnabled(enable)); 725} 726 727// Helper for SetIPCLoggingEnabled. 728void BrowserProcessImpl::SetIPCLoggingEnabledForChildProcesses(bool enabled) { 729 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)); 730 731 BrowserChildProcessHost::Iterator i; // default constr references a singleton 732 while (!i.Done()) { 733 i->Send(new PluginProcessMsg_SetIPCLoggingEnabled(enabled)); 734 ++i; 735 } 736} 737 738#endif // IPC_MESSAGE_LOG_ENABLED 739 740void BrowserProcessImpl::DoInspectorFilesCheck() { 741 // Runs on FILE thread. 742 DCHECK(file_thread_->message_loop() == MessageLoop::current()); 743 bool result = false; 744 745 FilePath inspector_dir; 746 if (PathService::Get(chrome::DIR_INSPECTOR, &inspector_dir)) { 747 result = file_util::PathExists(inspector_dir); 748 } 749 750 have_inspector_files_ = result; 751} 752 753// Mac is currently not supported. 754#if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS) 755 756bool BrowserProcessImpl::CanAutorestartForUpdate() const { 757 // Check if browser is in the background and if it needs to be restarted to 758 // apply a pending update. 759 return BrowserList::size() == 0 && BrowserList::WillKeepAlive() && 760 Upgrade::IsUpdatePendingRestart(); 761} 762 763// Switches to add when auto-restarting Chrome. 764const char* const kSwitchesToAddOnAutorestart[] = { 765 switches::kNoStartupWindow 766}; 767 768void BrowserProcessImpl::RestartPersistentInstance() { 769 CommandLine* old_cl = CommandLine::ForCurrentProcess(); 770 scoped_ptr<CommandLine> new_cl(new CommandLine(old_cl->GetProgram())); 771 772 std::map<std::string, CommandLine::StringType> switches = 773 old_cl->GetSwitches(); 774 775 switches::RemoveSwitchesForAutostart(&switches); 776 777 // Append the rest of the switches (along with their values, if any) 778 // to the new command line 779 for (std::map<std::string, CommandLine::StringType>::const_iterator i = 780 switches.begin(); i != switches.end(); ++i) { 781 CommandLine::StringType switch_value = i->second; 782 if (switch_value.length() > 0) { 783 new_cl->AppendSwitchNative(i->first, i->second); 784 } else { 785 new_cl->AppendSwitch(i->first); 786 } 787 } 788 789 // Ensure that our desired switches are set on the new process. 790 for (size_t i = 0; i < arraysize(kSwitchesToAddOnAutorestart); ++i) { 791 if (!new_cl->HasSwitch(kSwitchesToAddOnAutorestart[i])) 792 new_cl->AppendSwitch(kSwitchesToAddOnAutorestart[i]); 793 } 794 795 DLOG(WARNING) << "Shutting down current instance of the browser."; 796 BrowserList::CloseAllBrowsersAndExit(); 797 798 // Transfer ownership to Upgrade. 799 Upgrade::SetNewCommandLine(new_cl.release()); 800} 801 802void BrowserProcessImpl::OnAutoupdateTimer() { 803 if (CanAutorestartForUpdate()) { 804 DLOG(WARNING) << "Detected update. Restarting browser."; 805 RestartPersistentInstance(); 806 } 807} 808 809#endif // (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS) 810