| Index: content/browser/browser_main_loop.cc
|
| diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
|
| index 97da69ea79747081835c8d661897dd20bb346a8e..ad9871d06ba73c53b5d1d9603f06280b34200db9 100644
|
| --- a/content/browser/browser_main_loop.cc
|
| +++ b/content/browser/browser_main_loop.cc
|
| @@ -262,8 +262,50 @@ void BrowserMainLoop::MainMessageLoopStart() {
|
|
|
| void BrowserMainLoop::RunMainMessageLoopParts(
|
| bool* completed_main_message_loop) {
|
| + IOThreadDelegate* io_thread_delegate = NULL;
|
| + for (size_t i = 0; i < parts_list_.size(); ++i) {
|
| + IOThreadDelegate* current_delegate =
|
| + parts_list_[i]->PreMainMessageLoopRun();
|
| + if (current_delegate) {
|
| + DCHECK(!io_thread_delegate) << "Only one delegate allowed.";
|
| + io_thread_delegate = current_delegate;
|
| + }
|
| + }
|
| +
|
| + base::Thread::Options io_message_loop_options;
|
| + io_message_loop_options.message_loop_type = MessageLoop::TYPE_IO;
|
| + base::Thread::Options ui_message_loop_options;
|
| + ui_message_loop_options.message_loop_type = MessageLoop::TYPE_UI;
|
| +
|
| + db_thread_.reset(new BrowserProcessSubThread(BrowserThread::DB));
|
| + db_thread_->Start();
|
| +
|
| + file_thread_.reset(new BrowserProcessSubThread(BrowserThread::FILE));
|
| +#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.
|
| + file_thread_->StartWithOptions(ui_message_loop_options);
|
| +#else
|
| + file_thread_->StartWithOptions(io_message_loop_options);
|
| +#endif
|
| +
|
| + process_launcher_thread_.reset(
|
| + new BrowserProcessSubThread(BrowserThread::PROCESS_LAUNCHER));
|
| + process_launcher_thread_->Start();
|
| +
|
| + cache_thread_.reset(new BrowserProcessSubThread(BrowserThread::CACHE));
|
| + cache_thread_->StartWithOptions(io_message_loop_options);
|
| + io_thread_.reset(new BrowserProcessIOThread(io_thread_delegate));
|
| + io_thread_->StartWithOptions(io_message_loop_options);
|
| +#if defined(OS_CHROMEOS)
|
| + web_socket_proxy_thread_.reset(
|
| + new BrowserProcessSubThread(BrowserThread::WEB_SOCKET_PROXY));
|
| + web_socket_proxy_thread_->StartWithOptions(io_message_loop_options);
|
| +#endif
|
| +
|
| for (size_t i = 0; i < parts_list_.size(); ++i)
|
| - parts_list_[i]->PreMainMessageLoopRun();
|
| + parts_list_[i]->PreMainMessageLoopRunThreadsCreated();
|
|
|
| TRACE_EVENT_BEGIN_ETW("BrowserMain:MESSAGE_LOOP", 0, "");
|
| // If the UI thread blocks, the whole UI is unresponsive.
|
| @@ -289,8 +331,91 @@ void BrowserMainLoop::RunMainMessageLoopParts(
|
| if (completed_main_message_loop)
|
| *completed_main_message_loop = true;
|
|
|
| + // Teardown may start in PostMainMessageLoopRun, and during teardown we
|
| + // need to be able to perform IO.
|
| + base::ThreadRestrictions::SetIOAllowed(true);
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO,
|
| + FROM_HERE,
|
| + NewRunnableFunction(&base::ThreadRestrictions::SetIOAllowed, true));
|
| +
|
| for (size_t i = 0; i < parts_list_.size(); ++i)
|
| parts_list_[i]->PostMainMessageLoopRun();
|
| +
|
| + // Must be size_t so we can subtract from it.
|
| + for (size_t thread_id = BrowserThread::ID_COUNT - 1;
|
| + thread_id >= BrowserThread::DB;
|
| + --thread_id) {
|
| + // Find the thread object we want to stop. Looping over all valid
|
| + // BrowserThread IDs and DCHECKing on a missing case in the switch
|
| + // statement helps avoid a mismatch between this code and the
|
| + // BrowserThread::ID enumeration.
|
| + //
|
| + // The destruction order is the reverse order of occurrence in the
|
| + // BrowserThread::ID list. The rationale for the order is as
|
| + // follows (need to be filled in a bit):
|
| + //
|
| + // - (Not sure why the WEB_SOCKET_PROXY thread is stopped first.)
|
| + //
|
| + // - The IO thread is the only user of the CACHE thread.
|
| + //
|
| + // - The PROCESS_LAUNCHER thread must be stopped after IO in case
|
| + // the IO thread posted a task to terminate a process on the
|
| + // process launcher thread.
|
| + //
|
| + // - (Not sure why FILE needs to stop before WEBKIT.)
|
| + //
|
| + // - The WEBKIT thread (which currently is the responsibility of
|
| + // the embedder to stop, by destroying ResourceDispatcherHost
|
| + // before the DB thread is stopped)
|
| + //
|
| + // - (Not sure why DB stops last.)
|
| + scoped_ptr<BrowserProcessSubThread>* thread_to_stop = NULL;
|
| + switch (thread_id) {
|
| + case BrowserThread::UI:
|
| + case BrowserThread::ID_COUNT:
|
| + NOTREACHED();
|
| + break;
|
| + case BrowserThread::DB:
|
| + thread_to_stop = &db_thread_;
|
| + break;
|
| + case BrowserThread::WEBKIT:
|
| + // For now, the WebKit thread in the browser is owned by
|
| + // ResourceDispatcherHost, not by the content framework. Until
|
| + // this is fixed, we don't stop the thread but still call
|
| + // Pre/PostStopThread for the ID.
|
| + break;
|
| + case BrowserThread::FILE:
|
| + thread_to_stop = &file_thread_;
|
| + break;
|
| + case BrowserThread::PROCESS_LAUNCHER:
|
| + thread_to_stop = &process_launcher_thread_;
|
| + break;
|
| + case BrowserThread::CACHE:
|
| + thread_to_stop = &cache_thread_;
|
| + break;
|
| + case BrowserThread::IO:
|
| + thread_to_stop = &io_thread_;
|
| + break;
|
| +#if defined(OS_CHROMEOS)
|
| + case BrowserThread::WEB_SOCKET_PROXY:
|
| + thread_to_stop = &web_socket_proxy_thread_;
|
| + break;
|
| +#endif
|
| + }
|
| +
|
| + BrowserThread::ID id = static_cast<BrowserThread::ID>(thread_id);
|
| +
|
| + for (size_t i = 0; i < parts_list_.size(); ++i)
|
| + parts_list_[i]->PreStopThread(id);
|
| + if (thread_to_stop)
|
| + thread_to_stop->reset();
|
| + for (size_t i = 0; i < parts_list_.size(); ++i)
|
| + parts_list_[i]->PostStopThread(id);
|
| + }
|
| +
|
| + for (size_t i = 0; i < parts_list_.size(); ++i)
|
| + parts_list_[i]->FinalCleanup();
|
| }
|
|
|
| void BrowserMainLoop::InitializeMainThread() {
|
|
|