Index: chrome/browser/browser_process_impl.cc |
=================================================================== |
--- chrome/browser/browser_process_impl.cc (revision 111697) |
+++ chrome/browser/browser_process_impl.cc (working copy) |
@@ -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_child_process_host.h" |
+#include "content/browser/browser_process_sub_thread.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,7 +124,15 @@ |
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), |
@@ -157,20 +165,12 @@ |
} |
BrowserProcessImpl::~BrowserProcessImpl() { |
- // See StartTearDown and PreStopThread functions below, this is where |
- // most destruction happens so that it can be interleaved with threads |
- // going away. |
+#if defined(OS_CHROMEOS) |
+ if (web_socket_proxy_thread_.get()) |
+ chromeos::WebSocketProxyController::Shutdown(); |
+ web_socket_proxy_thread_.reset(); |
+#endif |
- // 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,65 +239,49 @@ |
// Stop the watchdog thread before stopping other threads. |
watchdog_thread_.reset(); |
-} |
-void BrowserProcessImpl::PreStartThread(BrowserThread::ID thread_id) { |
- switch (thread_id) { |
- case BrowserThread::IO: |
- CreateIOThreadState(); |
- break; |
+ // 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(); |
- default: |
- break; |
- } |
-} |
+ // The IO thread was the only user of this thread. |
+ cache_thread_.reset(); |
-void BrowserProcessImpl::PostStartThread(BrowserThread::ID thread_id) { |
-} |
+ // 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::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; |
+ // 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(); |
} |
-} |
-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; |
- } |
+ // 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(); |
+ |
+ tracked_objects::ThreadData::EnsureCleanupWasCalled(4); |
+ |
+ g_browser_process = NULL; |
} |
#if defined(OS_WIN) |
@@ -411,28 +395,37 @@ |
IOThread* BrowserProcessImpl::io_thread() { |
DCHECK(CalledOnValidThread()); |
- DCHECK(io_thread_.get()); |
+ if (!created_io_thread_) |
+ CreateIOThread(); |
return io_thread_.get(); |
} |
base::Thread* BrowserProcessImpl::file_thread() { |
DCHECK(CalledOnValidThread()); |
- return BrowserThread::UnsafeGetBrowserThread(BrowserThread::FILE); |
+ if (!created_file_thread_) |
+ CreateFileThread(); |
+ return file_thread_.get(); |
} |
base::Thread* BrowserProcessImpl::db_thread() { |
DCHECK(CalledOnValidThread()); |
- return BrowserThread::UnsafeGetBrowserThread(BrowserThread::DB); |
+ if (!created_db_thread_) |
+ CreateDBThread(); |
+ return db_thread_.get(); |
} |
base::Thread* BrowserProcessImpl::process_launcher_thread() { |
DCHECK(CalledOnValidThread()); |
- return BrowserThread::UnsafeGetBrowserThread(BrowserThread::PROCESS_LAUNCHER); |
+ if (!created_process_launcher_thread_) |
+ CreateProcessLauncherThread(); |
+ return process_launcher_thread_.get(); |
} |
base::Thread* BrowserProcessImpl::cache_thread() { |
DCHECK(CalledOnValidThread()); |
- return BrowserThread::UnsafeGetBrowserThread(BrowserThread::CACHE); |
+ if (!created_cache_thread_) |
+ CreateCacheThread(); |
+ return cache_thread_.get(); |
} |
WatchDogThread* BrowserProcessImpl::watchdog_thread() { |
@@ -446,7 +439,10 @@ |
#if defined(OS_CHROMEOS) |
base::Thread* BrowserProcessImpl::web_socket_proxy_thread() { |
DCHECK(CalledOnValidThread()); |
- return BrowserThread::UnsafeGetBrowserThread(BrowserThread::WEB_SOCKET_PROXY); |
+ if (!created_web_socket_proxy_thread_) |
+ CreateWebSocketProxyThread(); |
+ DCHECK(web_socket_proxy_thread_.get() != NULL); |
+ return web_socket_proxy_thread_.get(); |
} |
#endif |
@@ -646,10 +642,7 @@ |
} |
bool BrowserProcessImpl::plugin_finder_disabled() const { |
- if (plugin_finder_disabled_pref_.get()) |
- return plugin_finder_disabled_pref_->GetValue(); |
- else |
- return false; |
+ return *plugin_finder_disabled_pref_; |
} |
void BrowserProcessImpl::Observe(int type, |
@@ -764,11 +757,14 @@ |
metrics_service_.reset(new MetricsService); |
} |
-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. |
+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. |
PluginService* plugin_service = PluginService::GetInstance(); |
plugin_service->Init(); |
plugin_service->set_filter(ChromePluginServiceFilter::GetInstance()); |
@@ -793,9 +789,83 @@ |
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; |
@@ -841,10 +911,9 @@ |
// Initialize the preference for the plugin finder policy. |
// This preference is only needed on the IO thread so make it available there. |
local_state_->RegisterBooleanPref(prefs::kDisablePluginFinder, false); |
- plugin_finder_disabled_pref_.reset(new BooleanPrefMember); |
- plugin_finder_disabled_pref_->Init(prefs::kDisablePluginFinder, |
+ 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. |