diff options
author | joi@chromium.org <joi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-28 12:51:39 +0000 |
---|---|---|
committer | joi@chromium.org <joi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-28 12:51:39 +0000 |
commit | 042666f262a0c2ff601402e95f94fe9664a03f17 (patch) | |
tree | 508140a07a104fd3dd03b4c4c6548161de30f67f /chrome/browser | |
parent | 1d697f38d70b8edaca243a49f790b525c1c95a9d (diff) | |
download | chromium_src-042666f262a0c2ff601402e95f94fe9664a03f17.zip chromium_src-042666f262a0c2ff601402e95f94fe9664a03f17.tar.gz chromium_src-042666f262a0c2ff601402e95f94fe9664a03f17.tar.bz2 |
Have content/ create and destroy its own threads.
Change embedding API and embedders to allow for this.
Push inheritance of base::Thread down to content::BrowserThreadImpl so
that content::BrowserThread is just a namespace for API functions.
This change temporarily disables chrome_frame_net_tests as agreed by the CF lead, see bug 105435.
TBR=ben@chromium.org (IWYU change only)
BUG=98716,104578,105435
Review URL: http://codereview.chromium.org/8477004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111695 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/browser_process_impl.cc | 239 | ||||
-rw-r--r-- | chrome/browser/browser_process_impl.h | 51 | ||||
-rw-r--r-- | chrome/browser/browser_shutdown.cc | 6 | ||||
-rw-r--r-- | chrome/browser/browser_shutdown.h | 19 | ||||
-rw-r--r-- | chrome/browser/chrome_browser_main.cc | 151 | ||||
-rw-r--r-- | chrome/browser/chrome_browser_main.h | 20 | ||||
-rw-r--r-- | chrome/browser/chromeos/input_method/xkeyboard.cc | 8 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/login_utils_browsertest.cc | 35 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/webui_screen_locker.cc | 15 | ||||
-rw-r--r-- | chrome/browser/io_thread.cc | 53 | ||||
-rw-r--r-- | chrome/browser/io_thread.h | 47 | ||||
-rw-r--r-- | chrome/browser/sync/tools/DEPS | 2 | ||||
-rw-r--r-- | chrome/browser/sync/tools/sync_listen_notifications.cc | 7 | ||||
-rw-r--r-- | chrome/browser/ui/browser_list.cc | 27 | ||||
-rw-r--r-- | chrome/browser/ui/gtk/gtk_util.cc | 7 | ||||
-rw-r--r-- | chrome/browser/ui/gtk/select_file_dialog_impl_kde.cc | 7 |
16 files changed, 365 insertions, 329 deletions
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index 27ccef7..e84a219 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc @@ -68,7 +68,7 @@ #include "chrome/common/switch_utils.h" #include "chrome/common/url_constants.h" #include "chrome/installer/util/google_update_constants.h" -#include "content/browser/browser_process_sub_thread.h" +#include "content/browser/browser_child_process_host.h" #include "content/browser/child_process_security_policy.h" #include "content/browser/download/download_file_manager.h" #include "content/browser/download/download_status_updater.h" @@ -124,15 +124,7 @@ using content::BrowserThread; BrowserProcessImpl::BrowserProcessImpl(const CommandLine& command_line) : created_resource_dispatcher_host_(false), created_metrics_service_(false), - created_io_thread_(false), - created_file_thread_(false), - created_db_thread_(false), - created_process_launcher_thread_(false), - created_cache_thread_(false), created_watchdog_thread_(false), -#if defined(OS_CHROMEOS) - created_web_socket_proxy_thread_(false), -#endif created_profile_manager_(false), created_local_state_(false), created_icon_manager_(false), @@ -165,12 +157,20 @@ BrowserProcessImpl::BrowserProcessImpl(const CommandLine& command_line) } BrowserProcessImpl::~BrowserProcessImpl() { -#if defined(OS_CHROMEOS) - if (web_socket_proxy_thread_.get()) - chromeos::WebSocketProxyController::Shutdown(); - web_socket_proxy_thread_.reset(); -#endif + // See StartTearDown and PreStopThread functions below, this is where + // most destruction happens so that it can be interleaved with threads + // going away. + + // Wait for the pending print jobs to finish. + print_job_manager_->OnQuit(); + print_job_manager_.reset(); + tracked_objects::ThreadData::EnsureCleanupWasCalled(4); + + g_browser_process = NULL; +} + +void BrowserProcessImpl::StartTearDown() { // Delete the AutomationProviderList before NotificationService, // since it may try to unregister notifications // Both NotificationService and AutomationProvider are singleton instances in @@ -239,49 +239,65 @@ BrowserProcessImpl::~BrowserProcessImpl() { // Stop the watchdog thread before stopping other threads. watchdog_thread_.reset(); +} - // Need to stop io_thread_ before resource_dispatcher_host_, since - // io_thread_ may still deref ResourceDispatcherHost and handle resource - // request before going away. - io_thread_.reset(); - - // The IO thread was the only user of this thread. - cache_thread_.reset(); - - // Stop the process launcher thread after the IO thread, in case the IO thread - // posted a task to terminate a process on the process launcher thread. - process_launcher_thread_.reset(); +void BrowserProcessImpl::PreStartThread(BrowserThread::ID thread_id) { + switch (thread_id) { + case BrowserThread::IO: + CreateIOThreadState(); + break; - // Clean up state that lives on the file_thread_ before it goes away. - if (resource_dispatcher_host_.get()) { - resource_dispatcher_host()->download_file_manager()->Shutdown(); - resource_dispatcher_host()->save_file_manager()->Shutdown(); + default: + break; } +} - // Need to stop the file_thread_ here to force it to process messages in its - // message loop from the previous call to shutdown the DownloadFileManager, - // SaveFileManager and SessionService. - file_thread_.reset(); - - // With the file_thread_ flushed, we can release any icon resources. - icon_manager_.reset(); - - // Need to destroy ResourceDispatcherHost before PluginService and - // SafeBrowsingService, since it caches a pointer to it. This also - // causes the webkit thread to terminate. - resource_dispatcher_host_.reset(); - - // Wait for the pending print jobs to finish. - print_job_manager_->OnQuit(); - print_job_manager_.reset(); - - // Destroy TabCloseableStateWatcher before NotificationService since the - // former registers for notifications. - tab_closeable_state_watcher_.reset(); +void BrowserProcessImpl::PostStartThread(BrowserThread::ID thread_id) { +} - tracked_objects::ThreadData::EnsureCleanupWasCalled(4); +void BrowserProcessImpl::PreStopThread(BrowserThread::ID thread_id) { + switch (thread_id) { +#if defined(OS_CHROMEOS) + case BrowserThread::WEB_SOCKET_PROXY: + chromeos::WebSocketProxyController::Shutdown(); + break; +#endif + case BrowserThread::FILE: + // Clean up state that lives on or uses the file_thread_ before + // it goes away. + if (resource_dispatcher_host_.get()) { + resource_dispatcher_host()->download_file_manager()->Shutdown(); + resource_dispatcher_host()->save_file_manager()->Shutdown(); + } + break; + case BrowserThread::WEBKIT: + // Need to destroy ResourceDispatcherHost before PluginService + // and SafeBrowsingService, since it caches a pointer to + // it. This also causes the webkit thread to terminate (which is + // still the responsibility of the embedder, not of the content + // framework). + resource_dispatcher_host_.reset(); + break; + default: + break; + } +} - g_browser_process = NULL; +void BrowserProcessImpl::PostStopThread(BrowserThread::ID thread_id) { + switch (thread_id) { + case BrowserThread::FILE: + // With the file_thread_ flushed, we can release any icon resources. + icon_manager_.reset(); + break; + case BrowserThread::IO: + // 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. + io_thread_.reset(); + break; + default: + break; + } } #if defined(OS_WIN) @@ -395,37 +411,28 @@ MetricsService* BrowserProcessImpl::metrics_service() { IOThread* BrowserProcessImpl::io_thread() { DCHECK(CalledOnValidThread()); - if (!created_io_thread_) - CreateIOThread(); + DCHECK(io_thread_.get()); return io_thread_.get(); } base::Thread* BrowserProcessImpl::file_thread() { DCHECK(CalledOnValidThread()); - if (!created_file_thread_) - CreateFileThread(); - return file_thread_.get(); + return BrowserThread::UnsafeGetBrowserThread(BrowserThread::FILE); } base::Thread* BrowserProcessImpl::db_thread() { DCHECK(CalledOnValidThread()); - if (!created_db_thread_) - CreateDBThread(); - return db_thread_.get(); + return BrowserThread::UnsafeGetBrowserThread(BrowserThread::DB); } base::Thread* BrowserProcessImpl::process_launcher_thread() { DCHECK(CalledOnValidThread()); - if (!created_process_launcher_thread_) - CreateProcessLauncherThread(); - return process_launcher_thread_.get(); + return BrowserThread::UnsafeGetBrowserThread(BrowserThread::PROCESS_LAUNCHER); } base::Thread* BrowserProcessImpl::cache_thread() { DCHECK(CalledOnValidThread()); - if (!created_cache_thread_) - CreateCacheThread(); - return cache_thread_.get(); + return BrowserThread::UnsafeGetBrowserThread(BrowserThread::CACHE); } WatchDogThread* BrowserProcessImpl::watchdog_thread() { @@ -439,10 +446,7 @@ WatchDogThread* BrowserProcessImpl::watchdog_thread() { #if defined(OS_CHROMEOS) base::Thread* BrowserProcessImpl::web_socket_proxy_thread() { DCHECK(CalledOnValidThread()); - if (!created_web_socket_proxy_thread_) - CreateWebSocketProxyThread(); - DCHECK(web_socket_proxy_thread_.get() != NULL); - return web_socket_proxy_thread_.get(); + return BrowserThread::UnsafeGetBrowserThread(BrowserThread::WEB_SOCKET_PROXY); } #endif @@ -642,7 +646,10 @@ safe_browsing::ClientSideDetectionService* } bool BrowserProcessImpl::plugin_finder_disabled() const { - return *plugin_finder_disabled_pref_; + if (plugin_finder_disabled_pref_.get()) + return plugin_finder_disabled_pref_->GetValue(); + else + return false; } void BrowserProcessImpl::Observe(int type, @@ -757,14 +764,11 @@ void BrowserProcessImpl::CreateMetricsService() { metrics_service_.reset(new MetricsService); } -void BrowserProcessImpl::CreateIOThread() { - DCHECK(!created_io_thread_ && io_thread_.get() == NULL); - created_io_thread_ = true; - - // Prior to starting the io thread, we create the plugin service as - // it is predominantly used from the io thread, but must be created - // on the main thread. The service ctor is inexpensive and does not - // invoke the io_thread() accessor. +void BrowserProcessImpl::CreateIOThreadState() { + // Prior to any processing happening on the io thread, we create the + // plugin service as it is predominantly used from the io thread, + // but must be created on the main thread. The service ctor is + // inexpensive and does not invoke the io_thread() accessor. PluginService* plugin_service = PluginService::GetInstance(); plugin_service->Init(); plugin_service->set_filter(ChromePluginServiceFilter::GetInstance()); @@ -789,83 +793,9 @@ void BrowserProcessImpl::CreateIOThread() { scoped_ptr<IOThread> thread(new IOThread( local_state(), net_log_.get(), extension_event_router_forwarder_.get())); - base::Thread::Options options; - options.message_loop_type = MessageLoop::TYPE_IO; - if (!thread->StartWithOptions(options)) - return; io_thread_.swap(thread); } -void BrowserProcessImpl::CreateFileThread() { - DCHECK(!created_file_thread_ && file_thread_.get() == NULL); - created_file_thread_ = true; - - scoped_ptr<base::Thread> thread( - new content::BrowserProcessSubThread(BrowserThread::FILE)); - base::Thread::Options options; -#if defined(OS_WIN) - // On Windows, the FILE thread needs to be have a UI message loop which pumps - // messages in such a way that Google Update can communicate back to us. - options.message_loop_type = MessageLoop::TYPE_UI; -#else - options.message_loop_type = MessageLoop::TYPE_IO; -#endif - if (!thread->StartWithOptions(options)) - return; - file_thread_.swap(thread); -} - -#if defined(OS_CHROMEOS) -void BrowserProcessImpl::CreateWebSocketProxyThread() { - DCHECK(!created_web_socket_proxy_thread_); - DCHECK(web_socket_proxy_thread_.get() == NULL); - created_web_socket_proxy_thread_ = true; - - scoped_ptr<base::Thread> thread( - new content::BrowserProcessSubThread(BrowserThread::WEB_SOCKET_PROXY)); - base::Thread::Options options; - options.message_loop_type = MessageLoop::TYPE_IO; - if (!thread->StartWithOptions(options)) - return; - web_socket_proxy_thread_.swap(thread); -} -#endif - -void BrowserProcessImpl::CreateDBThread() { - DCHECK(!created_db_thread_ && db_thread_.get() == NULL); - created_db_thread_ = true; - - scoped_ptr<base::Thread> thread( - new content::BrowserProcessSubThread(BrowserThread::DB)); - if (!thread->Start()) - return; - db_thread_.swap(thread); -} - -void BrowserProcessImpl::CreateProcessLauncherThread() { - DCHECK(!created_process_launcher_thread_ && !process_launcher_thread_.get()); - created_process_launcher_thread_ = true; - - scoped_ptr<base::Thread> thread( - new content::BrowserProcessSubThread(BrowserThread::PROCESS_LAUNCHER)); - if (!thread->Start()) - return; - process_launcher_thread_.swap(thread); -} - -void BrowserProcessImpl::CreateCacheThread() { - DCHECK(!created_cache_thread_ && !cache_thread_.get()); - created_cache_thread_ = true; - - scoped_ptr<base::Thread> thread( - new content::DeprecatedBrowserThread(BrowserThread::CACHE)); - base::Thread::Options options; - options.message_loop_type = MessageLoop::TYPE_IO; - if (!thread->StartWithOptions(options)) - return; - cache_thread_.swap(thread); -} - void BrowserProcessImpl::CreateWatchdogThread() { DCHECK(!created_watchdog_thread_ && watchdog_thread_.get() == NULL); created_watchdog_thread_ = true; @@ -911,9 +841,10 @@ void BrowserProcessImpl::CreateLocalState() { // 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_.Init(prefs::kDisablePluginFinder, + 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); + 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. diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h index 46d4d52..2227ab0 100644 --- a/chrome/browser/browser_process_impl.h +++ b/chrome/browser/browser_process_impl.h @@ -21,6 +21,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/prefs/pref_change_registrar.h" #include "chrome/browser/prefs/pref_member.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "ipc/ipc_message.h" @@ -29,6 +30,7 @@ class BrowserOnlineStateObserver; class ChromeNetLog; class ChromeResourceDispatcherHostDelegate; class CommandLine; +class ChromeFrameFriendOfBrowserProcessImpl; // TODO(joi): Remove class RemoteDebuggingServer; class TabCloseableStateWatcher; @@ -44,6 +46,19 @@ class BrowserProcessImpl : public BrowserProcess, explicit BrowserProcessImpl(const CommandLine& command_line); virtual ~BrowserProcessImpl(); + // Some of our startup is interleaved with thread creation, driven + // by these functions. + void PreStartThread(content::BrowserThread::ID identifier); + void PostStartThread(content::BrowserThread::ID identifier); + + // Most cleanup is done by these functions, driven from + // ChromeBrowserMain based on notifications from the content + // framework, rather than in the destructor, so that we can + // interleave cleanup with threads being stopped. + void StartTearDown(); + void PreStopThread(content::BrowserThread::ID identifier); + void PostStopThread(content::BrowserThread::ID identifier); + base::Thread* process_launcher_thread(); // BrowserProcess methods @@ -117,20 +132,18 @@ class BrowserProcessImpl : public BrowserProcess, virtual CRLSetFetcher* crl_set_fetcher() OVERRIDE; private: + // TODO(joi): Remove. Temporary hack to get at CreateIOThreadState. + friend class ChromeFrameFriendOfBrowserProcessImpl; + + // Must be called right before the IO thread is started. + void CreateIOThreadState(); + void CreateResourceDispatcherHost(); void CreateMetricsService(); - void CreateIOThread(); - static void CleanupOnIOThread(); - - void CreateFileThread(); - void CreateDBThread(); - void CreateProcessLauncherThread(); - void CreateCacheThread(); - void CreateGpuThread(); void CreateWatchdogThread(); #if defined(OS_CHROMEOS) - void CreateWebSocketProxyThread(); + void InitializeWebSocketProxyThread(); #endif void CreateTemplateURLService(); void CreateProfileManager(); @@ -161,29 +174,11 @@ class BrowserProcessImpl : public BrowserProcess, bool created_metrics_service_; scoped_ptr<MetricsService> metrics_service_; - bool created_io_thread_; scoped_ptr<IOThread> io_thread_; - bool created_file_thread_; - scoped_ptr<base::Thread> file_thread_; - - bool created_db_thread_; - scoped_ptr<base::Thread> db_thread_; - - bool created_process_launcher_thread_; - scoped_ptr<base::Thread> process_launcher_thread_; - - bool created_cache_thread_; - scoped_ptr<base::Thread> cache_thread_; - bool created_watchdog_thread_; scoped_ptr<WatchDogThread> watchdog_thread_; -#if defined(OS_CHROMEOS) - bool created_web_socket_proxy_thread_; - scoped_ptr<base::Thread> web_socket_proxy_thread_; -#endif - bool created_profile_manager_; scoped_ptr<ProfileManager> profile_manager_; @@ -270,7 +265,7 @@ class BrowserProcessImpl : public BrowserProcess, scoped_refptr<MHTMLGenerationManager> mhtml_generation_manager_; // Monitors the state of the 'DisablePluginFinder' policy. - BooleanPrefMember plugin_finder_disabled_pref_; + scoped_ptr<BooleanPrefMember> plugin_finder_disabled_pref_; #if (defined(OS_WIN) || defined(OS_LINUX)) && !defined(OS_CHROMEOS) base::RepeatingTimer<BrowserProcessImpl> autoupdate_timer_; diff --git a/chrome/browser/browser_shutdown.cc b/chrome/browser/browser_shutdown.cc index 5aa4b66..044b505 100644 --- a/chrome/browser/browser_shutdown.cc +++ b/chrome/browser/browser_shutdown.cc @@ -114,7 +114,7 @@ FilePath GetShutdownMsPath() { return shutdown_ms_file.AppendASCII(kShutdownMsFile); } -void Shutdown() { +bool ShutdownPreThreadsStop() { #if defined(OS_CHROMEOS) chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker( "BrowserShutdownStarted", false); @@ -162,6 +162,10 @@ void Shutdown() { RLZTracker::CleanupRlz(); #endif + return restart_last_session; +} + +void ShutdownPostThreadsStop(bool restart_last_session) { // The jank'o'meter requires that the browser process has been destroyed // before calling UninstallJankometer(). delete g_browser_process; diff --git a/chrome/browser/browser_shutdown.h b/chrome/browser/browser_shutdown.h index b567b5d..78481b8 100644 --- a/chrome/browser/browser_shutdown.h +++ b/chrome/browser/browser_shutdown.h @@ -34,13 +34,18 @@ void OnShutdownStarting(ShutdownType type); // Get the current shutdown type. ShutdownType GetShutdownType(); -// Invoked in two ways: -// . When the last browser has been deleted and the message loop has finished -// running. -// . When ChromeFrame::EndSession is invoked and we need to do cleanup. -// NOTE: in this case the message loop is still running, but will die soon -// after this returns. -void Shutdown(); +// Performs the shutdown tasks that need to be done before +// BrowserProcess and the various threads go away. +// +// Returns true if the session should be restarted. +bool ShutdownPreThreadsStop(); + +// Performs the remaining shutdown tasks after all threads but the +// main thread have been stopped. This includes deleting g_browser_process. +// +// The provided parameter indicates whether a preference to restart +// the session was present. +void ShutdownPostThreadsStop(bool restart_last_session); // Called at startup to create a histogram from our previous shutdown time. void ReadLastShutdownInfo(); diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index 614da15..c0cf773 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc @@ -76,7 +76,6 @@ #include "chrome/browser/shell_integration.h" #include "chrome/browser/translate/translate_manager.h" #include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_init.h" #include "chrome/browser/ui/webui/chrome_url_data_manager_backend.h" #include "chrome/browser/web_resource/gpu_blacklist_updater.h" #include "chrome/common/child_process_logging.h" @@ -311,23 +310,6 @@ void InitializeURLRequestThrottlerManager(net::NetLog* net_log) { net::URLRequestThrottlerManager::GetInstance()->set_net_log(net_log); } -// Creates key child threads. We need to do this explicitly since -// BrowserThread::PostTask silently deletes a posted task if the target message -// loop isn't created. -void CreateChildThreads(BrowserProcessImpl* process) { - process->db_thread(); - process->file_thread(); - process->process_launcher_thread(); - process->cache_thread(); - process->io_thread(); -#if defined(OS_CHROMEOS) - process->web_socket_proxy_thread(); -#endif - // Create watchdog thread after creating all other threads because it will - // watch the other threads and they must be running. - process->watchdog_thread(); -} - // Returns the new local state object, guaranteed non-NULL. PrefService* InitializeLocalState(const CommandLine& parsed_command_line, bool is_first_run) { @@ -687,7 +669,12 @@ ChromeBrowserMainParts::ChromeBrowserMainParts( translate_manager_(NULL), profile_(NULL), run_message_loop_(true), - notify_result_(ProcessSingleton::PROCESS_NONE) { + notify_result_(ProcessSingleton::PROCESS_NONE), + is_first_run_(false), + first_run_ui_bypass_(false), + metrics_(NULL), + local_state_(NULL), + restart_last_session_(false) { // If we're running tests (ui_task is non-null). if (parameters.ui_task) browser_defaults::enable_help_app = false; @@ -1207,31 +1194,55 @@ void ChromeBrowserMainParts::PostMainMessageLoopStart() { chrome_extra_parts_[i]->PostMainMessageLoopStart(); } -void ChromeBrowserMainParts::PreMainMessageLoopRun() { - result_code_ = PreMainMessageLoopRunImpl(); +void ChromeBrowserMainParts::PreCreateThreads() { + result_code_ = PreCreateThreadsImpl(); for (size_t i = 0; i < chrome_extra_parts_.size(); ++i) chrome_extra_parts_[i]->PreMainMessageLoopRun(); } -int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { +void ChromeBrowserMainParts::PreStartThread( + content::BrowserThread::ID thread_id) { + browser_process_->PreStartThread(thread_id); +} + +void ChromeBrowserMainParts::PostStartThread( + content::BrowserThread::ID thread_id) { + browser_process_->PostStartThread(thread_id); + switch (thread_id) { + case BrowserThread::FILE: + // Now the command line has been mutated based on about:flags, + // and the file thread has been started, we can set up metrics + // and initialize field trials. + metrics_ = SetupMetricsAndFieldTrials(local_state_); + break; + + default: + break; + } +} + +void ChromeBrowserMainParts::PreMainMessageLoopRun() { + result_code_ = PreMainMessageLoopRunImpl(); +} + +int ChromeBrowserMainParts::PreCreateThreadsImpl() { run_message_loop_ = false; - FilePath user_data_dir; #if defined(OS_WIN) - PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); + PathService::Get(chrome::DIR_USER_DATA, &user_data_dir_); #else // Getting the user data dir can fail if the directory isn't // creatable, for example; on Windows in code below we bring up a // dialog prompting the user to pick a different directory. // However, ProcessSingleton needs a real user_data_dir on Mac/Linux, // so it's better to fail here than fail mysteriously elsewhere. - CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) + CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir_)) << "Must be able to get user data directory!"; #endif - process_singleton_.reset(new ProcessSingleton(user_data_dir)); + process_singleton_.reset(new ProcessSingleton(user_data_dir_)); - bool is_first_run = FirstRun::IsChromeFirstRun() || + is_first_run_ = FirstRun::IsChromeFirstRun() || parsed_command_line().HasSwitch(switches::kFirstRun); if (parsed_command_line().HasSwitch(switches::kImport) || @@ -1240,7 +1251,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { // instantiated (as it makes a net::URLRequest and we don't have an IO // thread, see bug #1292702). browser_process_.reset(new FirstRunBrowserProcess(parsed_command_line())); - is_first_run = false; + is_first_run_ = false; } else { browser_process_.reset(new BrowserProcessImpl(parsed_command_line())); } @@ -1258,8 +1269,8 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { // tabs. g_browser_process->tab_closeable_state_watcher(); - PrefService* local_state = InitializeLocalState(parsed_command_line(), - is_first_run); + local_state_ = InitializeLocalState(parsed_command_line(), + is_first_run_); #if defined(USE_LINUX_BREAKPAD) // Needs to be called after we have chrome::DIR_USER_DATA and @@ -1267,7 +1278,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE, new GetLinuxDistroTask()); - if (IsCrashReportingEnabled(local_state)) + if (IsCrashReportingEnabled(local_state_)) InitCrashReporter(); #endif @@ -1283,7 +1294,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { g_browser_process->SetApplicationLocale(l10n_util::GetLocaleOverride()); #else const std::string locale = - local_state->GetString(prefs::kApplicationLocale); + local_state_->GetString(prefs::kApplicationLocale); // On a POSIX OS other than ChromeOS, the parameter that is passed to the // method InitSharedInstance is ignored. const std::string loaded_locale = @@ -1343,19 +1354,19 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { // browser's profile_manager object is created, but after ResourceBundle // is initialized. master_prefs_.reset(new FirstRun::MasterPrefs); - bool first_run_ui_bypass = false; // True to skip first run UI. - if (is_first_run) { - first_run_ui_bypass = - !FirstRun::ProcessMasterPreferences(user_data_dir, master_prefs_.get()); + first_run_ui_bypass_ = false; // True to skip first run UI. + if (is_first_run_) { + first_run_ui_bypass_ = !FirstRun::ProcessMasterPreferences( + user_data_dir_, master_prefs_.get()); AddFirstRunNewTabs(browser_init_.get(), master_prefs_->new_tabs); // If we are running in App mode, we do not want to show the importer // (first run) UI. - if (!first_run_ui_bypass && + if (!first_run_ui_bypass_ && (parsed_command_line().HasSwitch(switches::kApp) || parsed_command_line().HasSwitch(switches::kAppId) || parsed_command_line().HasSwitch(switches::kNoFirstRun))) - first_run_ui_bypass = true; + first_run_ui_bypass_ = true; } // TODO(viettrungluu): why don't we run this earlier? @@ -1364,17 +1375,17 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { // Enable print preview once for supported platforms. #if defined(GOOGLE_CHROME_BUILD) - local_state->RegisterBooleanPref(prefs::kPrintingPrintPreviewEnabledOnce, + local_state_->RegisterBooleanPref(prefs::kPrintingPrintPreviewEnabledOnce, false, PrefService::UNSYNCABLE_PREF); - if (!local_state->GetBoolean(prefs::kPrintingPrintPreviewEnabledOnce)) { - local_state->SetBoolean(prefs::kPrintingPrintPreviewEnabledOnce, true); - about_flags::SetExperimentEnabled(local_state, "print-preview", true); + if (!local_state_->GetBoolean(prefs::kPrintingPrintPreviewEnabledOnce)) { + local_state_->SetBoolean(prefs::kPrintingPrintPreviewEnabledOnce, true); + about_flags::SetExperimentEnabled(local_state_, "print-preview", true); } #endif // Convert active labs into switches. Modifies the current command line. - about_flags::ConvertFlagsToSwitches(local_state, + about_flags::ConvertFlagsToSwitches(local_state_, CommandLine::ForCurrentProcess()); // Reset the command line in the crash report details, since we may have @@ -1391,10 +1402,6 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { histogram_synchronizer_ = new HistogramSynchronizer(); tracking_synchronizer_ = new chrome_browser_metrics::TrackingSynchronizer(); - // Now the command line has been mutated based on about:flags, we can - // set up metrics and initialize field trials. - MetricsService* metrics = SetupMetricsAndFieldTrials(local_state); - #if defined(USE_WEBKIT_COMPOSITOR) // We need to ensure WebKit has been initialized before we start the WebKit // compositor. This is done by the ResourceDispatcherHost on creation. @@ -1405,9 +1412,9 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { // for the uninstall metrics if this is our first run. This only actually // gets used if the user has metrics reporting enabled at uninstall time. int64 install_date = - local_state->GetInt64(prefs::kUninstallMetricsInstallDate); + local_state_->GetInt64(prefs::kUninstallMetricsInstallDate); if (install_date == 0) { - local_state->SetInt64(prefs::kUninstallMetricsInstallDate, + local_state_->SetInt64(prefs::kUninstallMetricsInstallDate, base::Time::Now().ToTimeT()); } @@ -1421,7 +1428,13 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { SecKeychainAddCallback(&KeychainCallback, 0, NULL); #endif - CreateChildThreads(browser_process_.get()); + return content::RESULT_CODE_NORMAL_EXIT; +} + +int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { + // Create watchdog thread after creating all other threads because it will + // watch the other threads and they must be running. + browser_process_->watchdog_thread(); #if defined(OS_CHROMEOS) // Now that the file thread exists we can record our stats. @@ -1571,13 +1584,13 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { } #endif - if (is_first_run) { + if (is_first_run_) { // Warn the ProfileManager that an import process will run, possibly // locking the WebDataService directory of the next Profile created. g_browser_process->profile_manager()->SetWillImport(); } - profile_ = CreateProfile(parameters(), user_data_dir, parsed_command_line()); + profile_ = CreateProfile(parameters(), user_data_dir_, parsed_command_line()); if (!profile_) return content::RESULT_CODE_NORMAL_EXIT; @@ -1661,8 +1674,8 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { // Note that this be done _after_ the PrefService is initialized and all // preferences are registered, since some of the code that the importer // touches reads preferences. - if (is_first_run) { - if (!first_run_ui_bypass) { + if (is_first_run_) { + if (!first_run_ui_bypass_) { FirstRun::AutoImport(profile_, master_prefs_->homepage_defined, master_prefs_->do_import_items, @@ -1678,9 +1691,9 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { // If stats reporting was turned on by the first run dialog then toggle // the pref. if (GoogleUpdateSettings::GetCollectStatsConsent()) - local_state->SetBoolean(prefs::kMetricsReportingEnabled, true); + local_state_->SetBoolean(prefs::kMetricsReportingEnabled, true); #endif // OS_POSIX - } // if (!first_run_ui_bypass) + } // if (!first_run_ui_bypass_) Browser::SetNewHomePagePrefs(profile_->GetPrefs()); g_browser_process->profile_manager()->OnImportFinished(profile_); @@ -1799,8 +1812,8 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { #endif HandleTestParameters(parsed_command_line()); - RecordBreakpadStatusUMA(metrics); - about_flags::RecordUMAStatistics(local_state); + RecordBreakpadStatusUMA(metrics_); + about_flags::RecordUMAStatistics(local_state_); LanguageUsageMetrics::RecordAcceptLanguages( profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)); LanguageUsageMetrics::RecordApplicationLanguage( @@ -1811,7 +1824,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { #endif #if defined(OS_CHROMEOS) - metrics->StartExternalMetrics(); + metrics_->StartExternalMetrics(); // Initialize the audio handler on ChromeOS. chromeos::AudioHandler::Initialize(); @@ -1844,7 +1857,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { #if defined(OS_WIN) // We check this here because if the profile is OTR (chromeos possibility) // it won't still be accessible after browser is destroyed. - record_search_engine_ = is_first_run && !profile_->IsOffTheRecord(); + record_search_engine_ = is_first_run_ && !profile_->IsOffTheRecord(); #endif // ChildProcess:: is a misnomer unless you consider context. Use @@ -1900,8 +1913,9 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() { // We are in regular browser boot sequence. Open initial tabs and enter the // main message loop. + int result_code; if (browser_init_->Start(parsed_command_line(), FilePath(), profile_, - &result_code_)) { + &result_code)) { #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS)) // Initialize autoupdate timer. Timer callback costs basically nothing // when browser is not in persistent mode, so it's OK to let it ride on @@ -2068,10 +2082,23 @@ void ChromeBrowserMainParts::PostMainMessageLoopRun() { chromeos::AudioHandler::Shutdown(); #endif + restart_last_session_ = browser_shutdown::ShutdownPreThreadsStop(); + browser_process_->StartTearDown(); +} + +void ChromeBrowserMainParts::PreStopThread(BrowserThread::ID identifier) { + browser_process_->PreStopThread(identifier); +} + +void ChromeBrowserMainParts::PostStopThread(BrowserThread::ID identifier) { + browser_process_->PostStopThread(identifier); +} + +void ChromeBrowserMainParts::PostDestroyThreads() { // browser_shutdown takes care of deleting browser_process, so we need to // release it. ignore_result(browser_process_.release()); - browser_shutdown::Shutdown(); + browser_shutdown::ShutdownPostThreadsStop(restart_last_session_); master_prefs_.reset(); process_singleton_.reset(); diff --git a/chrome/browser/chrome_browser_main.h b/chrome/browser/chrome_browser_main.h index 7f40f35..5ef3eb9 100644 --- a/chrome/browser/chrome_browser_main.h +++ b/chrome/browser/chrome_browser_main.h @@ -14,7 +14,9 @@ #include "base/tracked_objects.h" #include "chrome/browser/first_run/first_run.h" #include "chrome/browser/process_singleton.h" +#include "chrome/browser/ui/browser_init.h" #include "content/public/browser/browser_main_parts.h" +#include "content/public/browser/browser_thread.h" class BrowserInit; class BrowserProcessImpl; @@ -58,9 +60,15 @@ class ChromeBrowserMainParts : public content::BrowserMainParts { virtual void ToolkitInitialized() OVERRIDE; virtual void PreMainMessageLoopStart() OVERRIDE; virtual void PostMainMessageLoopStart() OVERRIDE; + virtual void PreCreateThreads() OVERRIDE; + virtual void PreStartThread(content::BrowserThread::ID identifier) OVERRIDE; + virtual void PostStartThread(content::BrowserThread::ID identifier) OVERRIDE; virtual void PreMainMessageLoopRun() OVERRIDE; virtual bool MainMessageLoopRun(int* result_code) OVERRIDE; virtual void PostMainMessageLoopRun() OVERRIDE; + virtual void PreStopThread(content::BrowserThread::ID identifier) OVERRIDE; + virtual void PostStopThread(content::BrowserThread::ID identifier) OVERRIDE; + virtual void PostDestroyThreads() OVERRIDE; // Displays a warning message that we can't find any locale data files. virtual void ShowMissingLocaleMessageBox() = 0; @@ -121,6 +129,7 @@ class ChromeBrowserMainParts : public content::BrowserMainParts { // Methods for Main Message Loop ------------------------------------------- + int PreCreateThreadsImpl(); int PreMainMessageLoopRunImpl(); // Members initialized on construction --------------------------------------- @@ -165,6 +174,17 @@ class ChromeBrowserMainParts : public content::BrowserMainParts { // Initialized in SetupMetricsAndFieldTrials. scoped_refptr<FieldTrialSynchronizer> field_trial_synchronizer_; + // Members initialized in PreMainMessageLoopRun, needed in + // PreMainMessageLoopRunThreadsCreated. + bool is_first_run_; + bool first_run_ui_bypass_; + MetricsService* metrics_; + PrefService* local_state_; + FilePath user_data_dir_; + + // Members needed across shutdown methods. + bool restart_last_session_; + FRIEND_TEST_ALL_PREFIXES(BrowserMainTest, WarmConnectionFieldTrial_WarmestSocket); FRIEND_TEST_ALL_PREFIXES(BrowserMainTest, WarmConnectionFieldTrial_Random); diff --git a/chrome/browser/chromeos/input_method/xkeyboard.cc b/chrome/browser/chromeos/input_method/xkeyboard.cc index e3379b2..c69c211 100644 --- a/chrome/browser/chromeos/input_method/xkeyboard.cc +++ b/chrome/browser/chromeos/input_method/xkeyboard.cc @@ -9,9 +9,6 @@ #include <string> #include <utility> -#include <X11/XKBlib.h> -#include <X11/Xlib.h> -#include <glib.h> #include <stdlib.h> #include <string.h> @@ -25,6 +22,11 @@ #include "content/public/browser/browser_thread.h" #include "ui/base/x/x11_util.h" +// These includes conflict with base/tracked_objects.h so must come last. +#include <X11/XKBlib.h> +#include <X11/Xlib.h> +#include <glib.h> + using content::BrowserThread; namespace chromeos { diff --git a/chrome/browser/chromeos/login/login_utils_browsertest.cc b/chrome/browser/chromeos/login/login_utils_browsertest.cc index 85b15a4..72257ed 100644 --- a/chrome/browser/chromeos/login/login_utils_browsertest.cc +++ b/chrome/browser/chromeos/login/login_utils_browsertest.cc @@ -30,6 +30,7 @@ #include "chrome/common/net/gaia/gaia_auth_consumer.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_pref_service.h" +#include "content/public/browser/browser_thread.h" #include "content/public/common/url_fetcher_delegate.h" #include "content/test/test_browser_thread.h" #include "content/test/test_url_fetcher_factory.h" @@ -48,6 +49,7 @@ using ::testing::DoAll; using ::testing::Return; using ::testing::SetArgPointee; using ::testing::_; +using content::BrowserThread; const char kTrue[] = "true"; const char kDomain[] = "domain.com"; @@ -74,20 +76,19 @@ ACTION_P(MockSessionManagerClientPolicyCallback, policy) { arg0.Run(policy); } -// Subclass IOThread to expose set_message_loop. -class TestIOThread : public IOThread { - public: - explicit TestIOThread(PrefService* local_state) - : IOThread(local_state, NULL, NULL) {} - - using IOThread::set_message_loop; -}; - template<typename TESTBASE> class LoginUtilsTestBase : public TESTBASE, public LoginUtils::Delegate, public LoginStatusConsumer { public: + // Initialization here is important. The UI thread gets the test's + // message loop, as does the file thread (which never actually gets + // started - so this is a way to fake multiple threads on a single + // test thread). The IO thread does not get the message loop set, + // and is never started. This is necessary so that we skip various + // bits of initialization that get posted to the IO thread. We do + // however, at one point in the test, temporarily set the message + // loop for the IO thread. LoginUtilsTestBase() : loop_(MessageLoop::TYPE_IO), browser_process_( @@ -95,7 +96,8 @@ class LoginUtilsTestBase : public TESTBASE, local_state_(browser_process_), ui_thread_(content::BrowserThread::UI, &loop_), file_thread_(content::BrowserThread::FILE, &loop_), - io_thread_(local_state_.Get()), + io_thread_(content::BrowserThread::IO), + io_thread_state_(local_state_.Get(), NULL, NULL), prepared_profile_(NULL) {} virtual void SetUp() OVERRIDE { @@ -111,7 +113,7 @@ class LoginUtilsTestBase : public TESTBASE, local_state_.Get()->RegisterStringPref(prefs::kApplicationLocale, ""); - browser_process_->SetIOThread(&io_thread_); + browser_process_->SetIOThread(&io_thread_state_); DBusThreadManager::InitializeForTesting(&dbus_thread_manager_); @@ -169,12 +171,16 @@ class LoginUtilsTestBase : public TESTBASE, // g_browser_process->profile_manager() is valid during initialization. // Run a task on a temporary BrowserThread::IO that allows skipping // these routines. - io_thread_.set_message_loop(&loop_); + // + // It is important to not have a fake message loop on the IO + // thread for the whole test, see comment on LoginUtilsTestBase + // constructor for details. + io_thread_.DeprecatedSetMessageLoop(&loop_); loop_.PostTask(FROM_HERE, base::Bind(&LoginUtilsTestBase::TearDownOnIO, base::Unretained(this))); loop_.RunAllPending(); - io_thread_.set_message_loop(NULL); + io_thread_.DeprecatedSetMessageLoop(NULL); } // These trigger some tasks that have to run while BrowserThread::UI @@ -305,7 +311,8 @@ class LoginUtilsTestBase : public TESTBASE, content::TestBrowserThread ui_thread_; content::TestBrowserThread file_thread_; - TestIOThread io_thread_; + content::TestBrowserThread io_thread_; + IOThread io_thread_state_; MockDBusThreadManager dbus_thread_manager_; TestURLFetcherFactory test_url_fetcher_factory_; diff --git a/chrome/browser/chromeos/login/webui_screen_locker.cc b/chrome/browser/chromeos/login/webui_screen_locker.cc index 4294eeb..a6798c7 100644 --- a/chrome/browser/chromeos/login/webui_screen_locker.cc +++ b/chrome/browser/chromeos/login/webui_screen_locker.cc @@ -4,15 +4,6 @@ #include "chrome/browser/chromeos/login/webui_screen_locker.h" -#include <X11/extensions/XTest.h> -#include <X11/keysym.h> -#include <gdk/gdkkeysyms.h> -#include <gdk/gdkx.h> - -// Evil hack to undo X11 evil #define. -#undef None -#undef Status - #include "base/command_line.h" #include "base/utf_string_conversions.h" #include "base/values.h" @@ -35,6 +26,12 @@ #include "ui/gfx/screen.h" #include "ui/views/widget/native_widget_gtk.h" +// These conflict with some of the Chrome headers, so must be included last. +#include <X11/extensions/XTest.h> +#include <X11/keysym.h> +#include <gdk/gdkkeysyms.h> +#include <gdk/gdkx.h> + namespace { // URL which corresponds to the login WebUI. diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index 18d1d2b..17b17a4 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc @@ -316,7 +316,8 @@ class SystemURLRequestContextGetter : public net::URLRequestContextGetter { SystemURLRequestContextGetter::SystemURLRequestContextGetter( IOThread* io_thread) : io_thread_(io_thread), - io_message_loop_proxy_(io_thread->message_loop_proxy()) { + io_message_loop_proxy_( + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)) { } SystemURLRequestContextGetter::~SystemURLRequestContextGetter() {} @@ -347,8 +348,7 @@ IOThread::IOThread( PrefService* local_state, ChromeNetLog* net_log, ExtensionEventRouterForwarder* extension_event_router_forwarder) - : content::BrowserProcessSubThread(BrowserThread::IO), - net_log_(net_log), + : net_log_(net_log), extension_event_router_forwarder_(extension_event_router_forwarder), globals_(NULL), sdch_manager_(NULL), @@ -371,17 +371,17 @@ IOThread::IOThread( local_state); ssl_config_service_manager_.reset( SSLConfigServiceManager::CreateDefaultManager(local_state)); - MessageLoop::current()->PostTask( - FROM_HERE, base::Bind(&IOThread::InitSystemRequestContext, - weak_factory_.GetWeakPtr())); + + BrowserThread::SetDelegate(BrowserThread::IO, this); } IOThread::~IOThread() { + // This isn't needed for production code, but in tests, IOThread may + // be multiply constructed. + BrowserThread::SetDelegate(BrowserThread::IO, NULL); + if (pref_proxy_config_tracker_.get()) pref_proxy_config_tracker_->DetachFromPrefService(); - // We cannot rely on our base class to stop the thread since we want our - // CleanUp function to run. - Stop(); DCHECK(!globals_); } @@ -407,9 +407,7 @@ void IOThread::Init() { // messages around; it shouldn't be allowed to perform any blocking disk I/O. base::ThreadRestrictions::SetIOAllowed(false); - content::BrowserProcessSubThread::Init(); - - DCHECK_EQ(MessageLoop::TYPE_IO, message_loop()->type()); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); #if defined(USE_NSS) net::SetMessageLoopForOCSP(); @@ -480,6 +478,26 @@ void IOThread::Init() { sdch_manager_ = new net::SdchManager(); sdch_manager_->set_sdch_fetcher(new SdchDictionaryFetcher); + + // InitSystemRequestContext turns right around and posts a task back + // to the IO thread, so we can't let it run until we know the IO + // thread has started. + // + // Note that since we are at BrowserThread::Init time, the UI thread + // is blocked waiting for the thread to start. Therefore, posting + // this task to the main thread's message loop here is guaranteed to + // get it onto the message loop while the IOThread object still + // exists. However, the message might not be processed on the UI + // thread until after IOThread is gone, so use a weak pointer. + BrowserThread::PostTask(BrowserThread::UI, + FROM_HERE, + base::Bind(&IOThread::InitSystemRequestContext, + weak_factory_.GetWeakPtr())); + + // We constructed the weak pointer on the IO thread but it will be + // used on the UI thread. Call this to avoid a thread checker + // error. + weak_factory_.DetachFromThread(); } void IOThread::CleanUp() { @@ -520,10 +538,6 @@ void IOThread::CleanUp() { base::debug::LeakTracker<net::URLRequest>::CheckForLeaks(); base::debug::LeakTracker<SystemURLRequestContextGetter>::CheckForLeaks(); - - // This will delete the |notification_service_|. Make sure it's done after - // anything else can reference it. - content::BrowserProcessSubThread::CleanUp(); } // static @@ -574,6 +588,11 @@ void IOThread::ClearHostCache() { host_cache->clear(); } +MessageLoop* IOThread::message_loop() const { + return BrowserThread::UnsafeGetBrowserThread( + BrowserThread::IO)->message_loop(); +} + net::SSLConfigService* IOThread::GetSSLConfigService() { return ssl_config_service_manager_->Get(); } @@ -593,6 +612,8 @@ void IOThread::InitSystemRequestContext() { } system_url_request_context_getter_ = new SystemURLRequestContextGetter(this); + // Safe to post an unretained this pointer, since IOThread is + // guaranteed to outlive the IO BrowserThread. message_loop()->PostTask( FROM_HERE, base::Bind(&IOThread::InitSystemRequestContextOnIOThread, base::Unretained(this))); diff --git a/chrome/browser/io_thread.h b/chrome/browser/io_thread.h index b8be74b..41be0c9 100644 --- a/chrome/browser/io_thread.h +++ b/chrome/browser/io_thread.h @@ -9,13 +9,26 @@ #include <string> #include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/net/ssl_config_service_manager.h" #include "chrome/browser/prefs/pref_member.h" -#include "content/browser/browser_process_sub_thread.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/browser_thread_delegate.h" #include "net/base/network_change_notifier.h" +// TODO(joi): Remove these in a follow-up change and IWYU in files +// that were getting them directly or indirectly from here. +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop.h" +#include "base/message_loop_proxy.h" +#include "base/synchronization/lock.h" +#include "base/threading/thread.h" + +class BrowserProcessImpl; class ChromeNetLog; class ExtensionEventRouterForwarder; class MediaInternals; @@ -43,7 +56,10 @@ class URLRequestContextGetter; class URLSecurityManager; } // namespace net -class IOThread : public content::BrowserProcessSubThread { +// Contains state associated with, initialized and cleaned up on, and +// primarily used on, the IO thread. Also acts as a convenience +// accessor to the Thread object for the IO thread. +class IOThread : public content::BrowserThreadDelegate { public: struct Globals { Globals(); @@ -109,26 +125,37 @@ class IOThread : public content::BrowserProcessSubThread { // called on the IO thread. void ClearHostCache(); - protected: + // Convenience method similar to base::Thread, giving access to the + // actual IO thread. + // TODO(joi): Remove this in follow-up changes. + MessageLoop* message_loop() const; + + private: + // BrowserThreadDelegate implementation, runs on the IO thread. + // This handles initialization and destruction of state that must + // live on the IO thread. virtual void Init() OVERRIDE; virtual void CleanUp() OVERRIDE; - private: // Provide SystemURLRequestContextGetter with access to // InitSystemRequestContext(). friend class SystemURLRequestContextGetter; - static void RegisterPrefs(PrefService* local_state); - - net::HttpAuthHandlerFactory* CreateDefaultAuthHandlerFactory( - net::HostResolver* resolver); - + // Global state must be initialized on the IO thread, then this + // method must be invoked on the UI thread. void InitSystemRequestContext(); // Lazy initialization of system request context for - // SystemURLRequestContextGetter. To be called on IO thread. + // SystemURLRequestContextGetter. To be called on IO thread only + // after global state has been initialized on the IO thread, and + // SystemRequestContext state has been initialized on the UI thread. void InitSystemRequestContextOnIOThread(); + static void RegisterPrefs(PrefService* local_state); + + net::HttpAuthHandlerFactory* CreateDefaultAuthHandlerFactory( + net::HostResolver* resolver); + // Returns an SSLConfigService instance. net::SSLConfigService* GetSSLConfigService(); diff --git a/chrome/browser/sync/tools/DEPS b/chrome/browser/sync/tools/DEPS index 877f421..5fa3c59 100644 --- a/chrome/browser/sync/tools/DEPS +++ b/chrome/browser/sync/tools/DEPS @@ -1,4 +1,6 @@ include_rules = [ + # sync_tools needs to manage its own BrowserThreads. + "+content/browser", # sync_tools depends on the google cache invalidation API. "+google/cacheinvalidation", # sync_tools depends on libjingle. diff --git a/chrome/browser/sync/tools/sync_listen_notifications.cc b/chrome/browser/sync/tools/sync_listen_notifications.cc index 91d1fed..b380daa 100644 --- a/chrome/browser/sync/tools/sync_listen_notifications.cc +++ b/chrome/browser/sync/tools/sync_listen_notifications.cc @@ -14,6 +14,7 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/message_loop.h" +#include "base/threading/thread.h" #include "chrome/browser/sync/notifier/invalidation_version_tracker.h" #include "chrome/browser/sync/notifier/sync_notifier.h" #include "chrome/browser/sync/notifier/sync_notifier_factory.h" @@ -22,6 +23,7 @@ #include "chrome/browser/sync/syncable/model_type_payload_map.h" #include "chrome/test/base/test_url_request_context_getter.h" #include "content/public/browser/browser_thread.h" +#include "content/browser/browser_thread_impl.h" using content::BrowserThread; @@ -95,9 +97,8 @@ int main(int argc, char* argv[]) { logging::DISABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS); MessageLoop ui_loop; - content::DeprecatedBrowserThread ui_thread(BrowserThread::UI, &ui_loop); - - content::DeprecatedBrowserThread io_thread(BrowserThread::IO); + content::BrowserThreadImpl ui_thread(BrowserThread::UI, &ui_loop); + content::BrowserThreadImpl io_thread(BrowserThread::IO); base::Thread::Options options; options.message_loop_type = MessageLoop::TYPE_IO; io_thread.StartWithOptions(options); diff --git a/chrome/browser/ui/browser_list.cc b/chrome/browser/ui/browser_list.cc index daaead6..6827139 100644 --- a/chrome/browser/ui/browser_list.cc +++ b/chrome/browser/ui/browser_list.cc @@ -20,6 +20,7 @@ #include "chrome/common/chrome_notification_types.h" #include "chrome/common/pref_names.h" #include "content/browser/tab_contents/navigation_details.h" +#include "content/public/browser/browser_shutdown.h" #include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/render_process_host.h" @@ -548,7 +549,12 @@ void BrowserList::ExitCleanly() { } #endif -static void TimeLimitedSessionEnding() { +// static +void BrowserList::SessionEnding() { + // This is a time-limited shutdown where we need to write as much to + // disk as we can as soon as we can, and where we must kill the + // process within a hang timeout to avoid user prompts. + // Start watching for hang during shutdown, and crash it if takes too long. // We disarm when |shutdown_watcher| object is destroyed, which is when we // exit this function. @@ -582,23 +588,8 @@ static void TimeLimitedSessionEnding() { content::NotificationService::AllSources(), content::NotificationService::NoDetails()); - // And shutdown. - browser_shutdown::Shutdown(); -} - -// static -void BrowserList::SessionEnding() { - TimeLimitedSessionEnding(); - -#if defined(OS_WIN) - // At this point the message loop is still running yet we've shut everything - // down. If any messages are processed we'll likely crash. Exit now. - ExitProcess(content::RESULT_CODE_NORMAL_EXIT); -#elif defined(OS_POSIX) && !defined(OS_MACOSX) - _exit(content::RESULT_CODE_NORMAL_EXIT); -#else - NOTIMPLEMENTED(); -#endif + // This will end by terminating the process. + content::ImmediateShutdownAndExitProcess(); } // static diff --git a/chrome/browser/ui/gtk/gtk_util.cc b/chrome/browser/ui/gtk/gtk_util.cc index b00c062..7c1c9e36 100644 --- a/chrome/browser/ui/gtk/gtk_util.cc +++ b/chrome/browser/ui/gtk/gtk_util.cc @@ -5,10 +5,9 @@ #include "chrome/browser/ui/gtk/gtk_util.h" #include <cairo/cairo.h> -#include <gdk/gdkx.h> -#include <gtk/gtk.h> #include <cstdarg> + #include <map> #include "base/environment.h" @@ -53,6 +52,10 @@ #include "chrome/browser/ui/gtk/browser_window_gtk.h" #endif +// These conflict with base/tracked_objects.h, so need to come last. +#include <gdk/gdkx.h> +#include <gtk/gtk.h> + namespace { #if defined(GOOGLE_CHROME_BUILD) diff --git a/chrome/browser/ui/gtk/select_file_dialog_impl_kde.cc b/chrome/browser/ui/gtk/select_file_dialog_impl_kde.cc index dac604b7..ca0e2cd 100644 --- a/chrome/browser/ui/gtk/select_file_dialog_impl_kde.cc +++ b/chrome/browser/ui/gtk/select_file_dialog_impl_kde.cc @@ -2,8 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <gdk/gdkx.h> -#include <gtk/gtk.h> +#include "content/public/browser/browser_thread.h" #include <set> @@ -22,6 +21,10 @@ #include "grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" +// These conflict with base/tracked_objects.h, so need to come last. +#include <gdk/gdkx.h> +#include <gtk/gtk.h> + using content::BrowserThread; namespace { |