diff options
author | joi@chromium.org <joi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-28 14:00:36 +0000 |
---|---|---|
committer | joi@chromium.org <joi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-28 14:00:36 +0000 |
commit | 14f79fec5f13a623f837f0b9438556180e5e7896 (patch) | |
tree | f86cadba8422d4a453acc22792406ff2b2cb8da8 /content | |
parent | f8a7f81d377eb872c2c9760813966920810edfb3 (diff) | |
download | chromium_src-14f79fec5f13a623f837f0b9438556180e5e7896.zip chromium_src-14f79fec5f13a623f837f0b9438556180e5e7896.tar.gz chromium_src-14f79fec5f13a623f837f0b9438556180e5e7896.tar.bz2 |
Revert 111695 - Have content/ create and destroy its own threads.
Reason: Problems on official builders.
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
TBR=joi@chromium.org
Review URL: http://codereview.chromium.org/8718012
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@111698 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r-- | content/browser/browser_main_loop.cc | 199 | ||||
-rw-r--r-- | content/browser/browser_main_loop.h | 17 | ||||
-rw-r--r-- | content/browser/browser_process_sub_thread.cc | 6 | ||||
-rw-r--r-- | content/browser/browser_thread_impl.cc | 160 | ||||
-rw-r--r-- | content/browser/browser_thread_impl.h | 28 | ||||
-rw-r--r-- | content/content_browser.gypi | 2 | ||||
-rw-r--r-- | content/public/browser/browser_main_parts.h | 33 | ||||
-rw-r--r-- | content/public/browser/browser_shutdown.h | 32 | ||||
-rw-r--r-- | content/public/browser/browser_thread.h | 81 | ||||
-rw-r--r-- | content/public/browser/browser_thread_delegate.h | 32 | ||||
-rw-r--r-- | content/shell/shell_browser_context.cc | 7 | ||||
-rw-r--r-- | content/shell/shell_browser_main.cc | 49 | ||||
-rw-r--r-- | content/shell/shell_browser_main.h | 19 | ||||
-rw-r--r-- | content/test/test_browser_thread.cc | 32 | ||||
-rw-r--r-- | content/test/test_browser_thread.h | 8 |
15 files changed, 164 insertions, 541 deletions
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index c6d448a..dd93e58 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc @@ -16,7 +16,6 @@ #include "content/common/hi_res_timer_manager.h" #include "content/common/sandbox_policy.h" #include "content/public/browser/browser_main_parts.h" -#include "content/public/browser/browser_shutdown.h" #include "content/public/browser/content_browser_client.h" #include "content/public/common/content_switches.h" #include "content/public/common/main_function_params.h" @@ -146,33 +145,6 @@ static void SetUpGLibLogHandler() { namespace content { -// The currently-running BrowserMainLoop. There can be one or zero. -// This is stored to enable immediate shutdown when needed. -BrowserMainLoop* current_browser_main_loop = NULL; - -// This is just to be able to keep ShutdownThreadsAndCleanUp out of -// the public interface of BrowserMainLoop. -class BrowserShutdownImpl { - public: - static void ImmediateShutdownAndExitProcess() { - DCHECK(current_browser_main_loop); - current_browser_main_loop->ShutdownThreadsAndCleanUp(); - -#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 - } -}; - -void ImmediateShutdownAndExitProcess() { - BrowserShutdownImpl::ImmediateShutdownAndExitProcess(); -} // BrowserMainLoop construction / destructione ============================= @@ -180,16 +152,12 @@ BrowserMainLoop::BrowserMainLoop(const content::MainFunctionParams& parameters) : parameters_(parameters), parsed_command_line_(parameters.command_line), result_code_(content::RESULT_CODE_NORMAL_EXIT) { - DCHECK(!current_browser_main_loop); - current_browser_main_loop = this; #if defined(OS_WIN) OleInitialize(NULL); #endif } BrowserMainLoop::~BrowserMainLoop() { - DCHECK_EQ(this, current_browser_main_loop); - current_browser_main_loop = NULL; #if defined(OS_WIN) OleUninitialize(); #endif @@ -294,85 +262,6 @@ void BrowserMainLoop::MainMessageLoopStart() { void BrowserMainLoop::RunMainMessageLoopParts( bool* completed_main_message_loop) { if (parts_.get()) - parts_->PreCreateThreads(); - - base::Thread::Options default_options; - 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; - - // Start threads in the order they occur in the BrowserThread::ID - // enumeration, except for BrowserThread::UI which is the main - // thread. - // - // Must be size_t so we can increment it. - for (size_t thread_id = BrowserThread::UI + 1; - thread_id < BrowserThread::ID_COUNT; - ++thread_id) { - scoped_ptr<BrowserProcessSubThread>* thread_to_start = NULL; - base::Thread::Options* options = &default_options; - - switch (thread_id) { - case BrowserThread::DB: - thread_to_start = &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 start the thread but still call - // Pre/PostStartThread for the ID. - break; - case BrowserThread::FILE: - thread_to_start = &file_thread_; -#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 = &ui_message_loop_options; -#else - options = &io_message_loop_options; -#endif - break; - case BrowserThread::PROCESS_LAUNCHER: - thread_to_start = &process_launcher_thread_; - break; - case BrowserThread::CACHE: - thread_to_start = &cache_thread_; - options = &io_message_loop_options; - break; - case BrowserThread::IO: - thread_to_start = &io_thread_; - options = &io_message_loop_options; - break; -#if defined(OS_CHROMEOS) - case BrowserThread::WEB_SOCKET_PROXY: - thread_to_start = &web_socket_proxy_thread_; - options = &io_message_loop_options; - break; -#endif - case BrowserThread::UI: - case BrowserThread::ID_COUNT: - default: - NOTREACHED(); - break; - } - - BrowserThread::ID id = static_cast<BrowserThread::ID>(thread_id); - - if (parts_.get()) - parts_->PreStartThread(id); - - if (thread_to_start) { - (*thread_to_start).reset(new BrowserProcessSubThread(id)); - (*thread_to_start)->StartWithOptions(*options); - } - - if (parts_.get()) - parts_->PostStartThread(id); - } - - if (parts_.get()) parts_->PreMainMessageLoopRun(); TRACE_EVENT_BEGIN_ETW("BrowserMain:MESSAGE_LOOP", 0, ""); @@ -392,96 +281,8 @@ void BrowserMainLoop::RunMainMessageLoopParts( if (completed_main_message_loop) *completed_main_message_loop = true; - ShutdownThreadsAndCleanUp(); -} - -void BrowserMainLoop::ShutdownThreadsAndCleanUp() { - // 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)); - if (parts_.get()) parts_->PostMainMessageLoopRun(); - - // Must be size_t so we can subtract from it. - for (size_t thread_id = BrowserThread::ID_COUNT - 1; - thread_id >= (BrowserThread::UI + 1); - --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::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 - case BrowserThread::UI: - case BrowserThread::ID_COUNT: - default: - NOTREACHED(); - break; - } - - BrowserThread::ID id = static_cast<BrowserThread::ID>(thread_id); - - if (parts_.get()) - parts_->PreStopThread(id); - if (thread_to_stop) - thread_to_stop->reset(); - if (parts_.get()) - parts_->PostStopThread(id); - } - - if (parts_.get()) - parts_->PostDestroyThreads(); } void BrowserMainLoop::InitializeMainThread() { diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h index 3038332..d02d578 100644 --- a/content/browser/browser_main_loop.h +++ b/content/browser/browser_main_loop.h @@ -8,7 +8,6 @@ #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" -#include "content/browser/browser_process_sub_thread.h" class CommandLine; class HighResolutionTimerManager; @@ -26,7 +25,6 @@ class NetworkChangeNotifier; namespace content { class BrowserMainParts; -class BrowserShutdownImpl; class BrowserThreadImpl; struct MainFunctionParams; @@ -48,13 +46,6 @@ class BrowserMainLoop { int GetResultCode() const { return result_code_; } private: - // For ShutdownThreadsAndCleanUp. - friend class BrowserShutdownImpl; - - // Performs the shutdown sequence, starting with PostMainMessageLoopRun - // through stopping threads to PostDestroyThreads. - void ShutdownThreadsAndCleanUp(); - void InitializeMainThread(); // Members initialized on construction --------------------------------------- @@ -78,14 +69,6 @@ class BrowserMainLoop { // Members initialized in |InitializeMainThread()| --------------------------- // This must get destroyed before other threads that are created in parts_. scoped_ptr<BrowserThreadImpl> main_thread_; - scoped_ptr<BrowserProcessSubThread> io_thread_; - scoped_ptr<BrowserProcessSubThread> file_thread_; - scoped_ptr<BrowserProcessSubThread> db_thread_; - scoped_ptr<BrowserProcessSubThread> process_launcher_thread_; - scoped_ptr<BrowserProcessSubThread> cache_thread_; -#if defined(OS_CHROMEOS) - scoped_ptr<BrowserProcessSubThread> web_socket_proxy_thread_; -#endif DISALLOW_COPY_AND_ASSIGN(BrowserMainLoop); }; diff --git a/content/browser/browser_process_sub_thread.cc b/content/browser/browser_process_sub_thread.cc index 7c77d7e..31c129e 100644 --- a/content/browser/browser_process_sub_thread.cc +++ b/content/browser/browser_process_sub_thread.cc @@ -17,6 +17,8 @@ BrowserProcessSubThread::BrowserProcessSubThread(BrowserThread::ID identifier) : BrowserThreadImpl(identifier) {} BrowserProcessSubThread::~BrowserProcessSubThread() { + // We cannot rely on our base class to stop the thread since we want our + // CleanUp function to run. Stop(); } @@ -27,13 +29,9 @@ void BrowserProcessSubThread::Init() { #endif notification_service_ = new NotificationServiceImpl; - - BrowserThreadImpl::Init(); } void BrowserProcessSubThread::CleanUp() { - BrowserThreadImpl::CleanUp(); - delete notification_service_; notification_service_ = NULL; diff --git a/content/browser/browser_thread_impl.cc b/content/browser/browser_thread_impl.cc index 0025f77..023259b 100644 --- a/content/browser/browser_thread_impl.cc +++ b/content/browser/browser_thread_impl.cc @@ -4,19 +4,16 @@ #include "content/browser/browser_thread_impl.h" -#include "base/atomicops.h" #include "base/bind.h" #include "base/lazy_instance.h" #include "base/message_loop.h" #include "base/message_loop_proxy.h" #include "base/threading/thread_restrictions.h" -namespace content { - namespace { // Friendly names for the well-known threads. -static const char* g_browser_thread_names[BrowserThread::ID_COUNT] = { +static const char* browser_thread_names[content::BrowserThread::ID_COUNT] = { "", // UI (name assembled in browser_main.cc). "Chrome_DBThread", // DB "Chrome_WebKitThread", // WEBKIT @@ -29,86 +26,38 @@ static const char* g_browser_thread_names[BrowserThread::ID_COUNT] = { #endif }; -// This lock protects |g_browser_threads|. Do not read or modify that -// array without holding this lock. Do not block while holding this -// lock. +} // namespace + +namespace content { + +namespace { + +// This lock protects |g_browser_threads|. Do not read or modify that array +// without holding this lock. Do not block while holding this lock. base::LazyInstance<base::Lock, base::LeakyLazyInstanceTraits<base::Lock> > g_lock = LAZY_INSTANCE_INITIALIZER; -// This array is protected by |g_lock|. The threads are not owned by this -// array. Typically, the threads are owned on the UI thread by -// content::BrowserMainLoop. BrowserThreadImpl objects remove -// themselves from this array upon destruction. -static BrowserThreadImpl* g_browser_threads[BrowserThread::ID_COUNT]; -// Only atomic operations are used on this array. The delegates are -// not owned by this array, rather by whoever calls -// BrowserThread::SetDelegate. -static BrowserThreadDelegate* g_browser_thread_delegates[ - BrowserThread::ID_COUNT]; +// An array of the BrowserThread objects. This array is protected by |g_lock|. +// The threads are not owned by this array. Typically, the threads are owned +// on the UI thread by the g_browser_process object. BrowserThreads remove +// themselves from this array upon destruction. +BrowserThread* g_browser_threads[BrowserThread::ID_COUNT]; } // namespace -BrowserThreadImpl::BrowserThreadImpl(ID identifier) - : Thread(g_browser_thread_names[identifier]), - identifier_(identifier) { - Initialize(); +BrowserThreadImpl::BrowserThreadImpl(BrowserThread::ID identifier) + : BrowserThread(identifier) { } -BrowserThreadImpl::BrowserThreadImpl(ID identifier, +BrowserThreadImpl::BrowserThreadImpl(BrowserThread::ID identifier, MessageLoop* message_loop) - : Thread(message_loop->thread_name().c_str()), - identifier_(identifier) { - set_message_loop(message_loop); - Initialize(); -} - -void BrowserThreadImpl::Init() { - using base::subtle::AtomicWord; - AtomicWord* storage = - reinterpret_cast<AtomicWord*>(&g_browser_thread_delegates[identifier_]); - AtomicWord stored_pointer = base::subtle::NoBarrier_Load(storage); - BrowserThreadDelegate* delegate = - reinterpret_cast<BrowserThreadDelegate*>(stored_pointer); - if (delegate) - delegate->Init(); -} - -void BrowserThreadImpl::CleanUp() { - using base::subtle::AtomicWord; - AtomicWord* storage = - reinterpret_cast<AtomicWord*>(&g_browser_thread_delegates[identifier_]); - AtomicWord stored_pointer = base::subtle::NoBarrier_Load(storage); - BrowserThreadDelegate* delegate = - reinterpret_cast<BrowserThreadDelegate*>(stored_pointer); - - if (delegate) - delegate->CleanUp(); -} - -void BrowserThreadImpl::Initialize() { - base::AutoLock lock(g_lock.Get()); - DCHECK(identifier_ >= 0 && identifier_ < ID_COUNT); - DCHECK(g_browser_threads[identifier_] == NULL); - g_browser_threads[identifier_] = this; + : BrowserThread(identifier, message_loop) { } BrowserThreadImpl::~BrowserThreadImpl() { - // All Thread subclasses must call Stop() in the destructor. This is - // doubly important here as various bits of code check they are on - // the right BrowserThread. Stop(); - - base::AutoLock lock(g_lock.Get()); - g_browser_threads[identifier_] = NULL; -#ifndef NDEBUG - // Double check that the threads are ordered correctly in the enumeration. - for (int i = identifier_ + 1; i < ID_COUNT; ++i) { - DCHECK(!g_browser_threads[i]) << - "Threads must be listed in the reverse order that they die"; - } -#endif } // static @@ -128,7 +77,7 @@ bool BrowserThreadImpl::PostTaskHelper( BrowserThread::ID current_thread; bool guaranteed_to_outlive_target_thread = GetCurrentThreadIdentifier(¤t_thread) && - current_thread <= identifier; + current_thread >= identifier; if (!guaranteed_to_outlive_target_thread) g_lock.Get().Acquire(); @@ -169,7 +118,7 @@ bool BrowserThreadImpl::PostTaskHelper( BrowserThread::ID current_thread; bool guaranteed_to_outlive_target_thread = GetCurrentThreadIdentifier(¤t_thread) && - current_thread <= identifier; + current_thread >= identifier; if (!guaranteed_to_outlive_target_thread) g_lock.Get().Acquire(); @@ -190,6 +139,18 @@ bool BrowserThreadImpl::PostTaskHelper( return !!message_loop; } +// TODO(joi): Remove +DeprecatedBrowserThread::DeprecatedBrowserThread(BrowserThread::ID identifier) + : BrowserThread(identifier) { +} +DeprecatedBrowserThread::DeprecatedBrowserThread(BrowserThread::ID identifier, + MessageLoop* message_loop) + : BrowserThread(identifier, message_loop) { +} +DeprecatedBrowserThread::~DeprecatedBrowserThread() { + Stop(); +} + // An implementation of MessageLoopProxy to be used in conjunction // with BrowserThread. class BrowserThreadMessageLoopProxy : public base::MessageLoopProxy { @@ -254,6 +215,44 @@ class BrowserThreadMessageLoopProxy : public base::MessageLoopProxy { DISALLOW_COPY_AND_ASSIGN(BrowserThreadMessageLoopProxy); }; +BrowserThread::BrowserThread(ID identifier) + : Thread(browser_thread_names[identifier]), + identifier_(identifier) { + Initialize(); +} + +BrowserThread::BrowserThread(ID identifier, + MessageLoop* message_loop) + : Thread(message_loop->thread_name().c_str()), + identifier_(identifier) { + set_message_loop(message_loop); + Initialize(); +} + +void BrowserThread::Initialize() { + base::AutoLock lock(g_lock.Get()); + DCHECK(identifier_ >= 0 && identifier_ < ID_COUNT); + DCHECK(g_browser_threads[identifier_] == NULL); + g_browser_threads[identifier_] = this; +} + +BrowserThread::~BrowserThread() { + // Stop the thread here, instead of the parent's class destructor. This is so + // that if there are pending tasks that run, code that checks that it's on the + // correct BrowserThread succeeds. + Stop(); + + base::AutoLock lock(g_lock.Get()); + g_browser_threads[identifier_] = NULL; +#ifndef NDEBUG + // Double check that the threads are ordered correctly in the enumeration. + for (int i = identifier_ + 1; i < ID_COUNT; ++i) { + DCHECK(!g_browser_threads[i]) << + "Threads must be listed in the reverse order that they die"; + } +#endif +} + // static bool BrowserThread::IsWellKnownThread(ID identifier) { base::AutoLock lock(g_lock.Get()); @@ -394,23 +393,4 @@ BrowserThread::GetMessageLoopProxyForThread( return proxy; } -base::Thread* BrowserThread::UnsafeGetBrowserThread(ID identifier) { - base::AutoLock lock(g_lock.Get()); - base::Thread* thread = g_browser_threads[identifier]; - DCHECK(thread); - return thread; -} - -void BrowserThread::SetDelegate(ID identifier, - BrowserThreadDelegate* delegate) { - using base::subtle::AtomicWord; - AtomicWord* storage = reinterpret_cast<AtomicWord*>( - &g_browser_thread_delegates[identifier]); - AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange( - storage, reinterpret_cast<AtomicWord>(delegate)); - - // This catches registration when previously registered. - DCHECK(!delegate || !old_pointer); -} - } // namespace content diff --git a/content/browser/browser_thread_impl.h b/content/browser/browser_thread_impl.h index d00ff5b..e24b385 100644 --- a/content/browser/browser_thread_impl.h +++ b/content/browser/browser_thread_impl.h @@ -6,33 +6,22 @@ #define CONTENT_BROWSER_BROWSER_THREAD_IMPL_H_ #pragma once -#include "base/synchronization/lock.h" -#include "base/threading/thread.h" #include "content/common/content_export.h" #include "content/public/browser/browser_thread.h" namespace content { -class CONTENT_EXPORT BrowserThreadImpl - : public BrowserThread, public base::Thread { +class CONTENT_EXPORT BrowserThreadImpl : public BrowserThread { public: - // Construct a BrowserThreadImpl with the supplied identifier. It is an error - // to construct a BrowserThreadImpl that already exists. explicit BrowserThreadImpl(BrowserThread::ID identifier); - - // Special constructor for the main (UI) thread and unittests. We use a dummy - // thread here since the main thread already exists. BrowserThreadImpl(BrowserThread::ID identifier, MessageLoop* message_loop); virtual ~BrowserThreadImpl(); - protected: - virtual void Init() OVERRIDE; - virtual void CleanUp() OVERRIDE; - private: - // We implement all the functionality of the public BrowserThread - // functions, but state is stored in the BrowserThreadImpl to keep - // the API cleaner. Therefore make BrowserThread a friend class. + // We implement most functionality on the public set of + // BrowserThread functions, but state is stored in the + // BrowserThreadImpl to keep the public API cleaner. Therefore make + // BrowserThread a friend class. friend class BrowserThread; // TODO(brettw) remove this variant when Task->Closure migration is complete. @@ -48,13 +37,6 @@ class CONTENT_EXPORT BrowserThreadImpl const base::Closure& task, int64 delay_ms, bool nestable); - - // Common initialization code for the constructors. - void Initialize(); - - // The identifier of this thread. Only one thread can exist with a given - // identifier at a given time. - ID identifier_; }; } // namespace content diff --git a/content/content_browser.gypi b/content/content_browser.gypi index d55e9f5..0bfe9da 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -27,9 +27,7 @@ ], 'sources': [ 'public/browser/browser_main_parts.h', - 'public/browser/browser_shutdown.h', 'public/browser/browser_thread.h', - 'public/browser/browser_thread_delegate.h', 'public/browser/content_browser_client.h', 'public/browser/content_ipc_logging.h', 'public/browser/download_manager_delegate.h', diff --git a/content/public/browser/browser_main_parts.h b/content/public/browser/browser_main_parts.h index 4bce3cf..860541c 100644 --- a/content/public/browser/browser_main_parts.h +++ b/content/public/browser/browser_main_parts.h @@ -8,7 +8,6 @@ #include "base/basictypes.h" #include "content/common/content_export.h" -#include "content/public/browser/browser_thread.h" namespace content { @@ -65,24 +64,6 @@ class CONTENT_EXPORT BrowserMainParts { // Allows an embedder to do any extra toolkit initialization. virtual void ToolkitInitialized() = 0; - // Called just before any child threads owned by the content - // framework are created. - // - // The main message loop has been started at this point (but has not - // been run), and the toolkit has been initialized. - virtual void PreCreateThreads() = 0; - - // Called once for each thread owned by the content framework just - // before and just after the thread object is created and started. - // This happens in the order of the threads' appearence in the - // BrowserThread::ID enumeration. Note that there will be no such - // call for BrowserThread::UI, since it is the main thread of the - // application. - virtual void PreStartThread(BrowserThread::ID identifier) = 0; - virtual void PostStartThread(BrowserThread::ID identifier) = 0; - - // This is called just before the main message loop is run. The - // various browser threads have all been created at this point virtual void PreMainMessageLoopRun() = 0; // Returns true if the message loop was run, false otherwise. @@ -90,22 +71,8 @@ class CONTENT_EXPORT BrowserMainParts { // May set |result_code|, which will be returned by |BrowserMain()|. virtual bool MainMessageLoopRun(int* result_code) = 0; - // This happens after the main message loop has stopped, but before - // threads are stopped. virtual void PostMainMessageLoopRun() = 0; - // Called once for each thread owned by the content framework just - // before and just after it is torn down. This is in reverse order - // of the threads' appearance in the BrowserThread::ID enumeration. - // Note that you will not receive such a call for BrowserThread::UI, - // since it is the main thread of the application. - virtual void PreStopThread(BrowserThread::ID identifier) = 0; - virtual void PostStopThread(BrowserThread::ID identifier) = 0; - - // Called as the very last part of shutdown, after threads have been - // stopped and destroyed. - virtual void PostDestroyThreads() = 0; - private: DISALLOW_COPY_AND_ASSIGN(BrowserMainParts); }; diff --git a/content/public/browser/browser_shutdown.h b/content/public/browser/browser_shutdown.h deleted file mode 100644 index 72a4ce0..0000000 --- a/content/public/browser/browser_shutdown.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_PUBLIC_BROWSER_BROWSER_SHUTDOWN_H_ -#define CONTENT_PUBLIC_BROWSER_BROWSER_SHUTDOWN_H_ -#pragma once - -#include "content/common/content_export.h" - -namespace content { - -// This can be used for as-fast-as-possible shutdown, in cases where -// time for shutdown is limited and we just need to write out as much -// data as possible before our time runs out. -// -// This causes the shutdown sequence embodied by -// BrowserMainParts::PostMainMessageLoopRun through -// BrowserMainParts::PostDestroyThreads to occur, i.e. we pretend the -// message loop finished, all threads are stopped in sequence and -// PreStopThread/PostStopThread gets called, and at least, -// PostDestroyThreads is called. -// -// As this violates the normal order of shutdown, likely leaving the -// process in a bad state, the last thing this function does is -// terminate the process (right after calling -// BrowserMainParts::PostDestroyThreads). -CONTENT_EXPORT void ImmediateShutdownAndExitProcess(); - -} // namespace content - -#endif // CONTENT_PUBLIC_BROWSER_BROWSER_SHUTDOWN_H_ diff --git a/content/public/browser/browser_thread.h b/content/public/browser/browser_thread.h index 4478558..66dc009 100644 --- a/content/public/browser/browser_thread.h +++ b/content/public/browser/browser_thread.h @@ -6,21 +6,11 @@ #define CONTENT_PUBLIC_BROWSER_BROWSER_THREAD_H_ #pragma once -#include "base/basictypes.h" #include "base/callback.h" -#include "base/task.h" -#include "base/tracked_objects.h" -#include "content/common/content_export.h" -#include "content/public/browser/browser_thread_delegate.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/task.h" #include "base/threading/thread.h" +#include "content/common/content_export.h" #if defined(UNIT_TEST) #include "base/logging.h" @@ -28,12 +18,12 @@ namespace base { class MessageLoopProxy; -class Thread; } namespace content { class BrowserThreadImpl; +class DeprecatedBrowserThread; /////////////////////////////////////////////////////////////////////////////// // BrowserThread @@ -57,7 +47,7 @@ class BrowserThreadImpl; // task is posted to is guaranteed to outlive the current thread, then no locks // are used. You should never need to cache pointers to MessageLoops, since // they're not thread safe. -class CONTENT_EXPORT BrowserThread { +class CONTENT_EXPORT BrowserThread : public base::Thread { public: // An enumeration of the well-known threads. // NOTE: threads must be listed in the order of their life-time, with each @@ -180,33 +170,6 @@ class CONTENT_EXPORT BrowserThread { static scoped_refptr<base::MessageLoopProxy> GetMessageLoopProxyForThread( ID identifier); - // Gets the Thread object for the specified thread, or NULL if the - // thread has not been created (or has been destroyed during - // shutdown). - // - // Before calling this, you must have called content::ContentMain - // with a command-line that would specify a browser process (e.g. an - // empty command line). - // - // This is unsafe as your pointer may become invalid close to - // shutdown. - // - // TODO(joi): Remove this once clients such as BrowserProcessImpl - // (and classes that call things like - // g_browser_process->file_thread()) are switched to using - // MessageLoopProxy. - static base::Thread* UnsafeGetBrowserThread(ID identifier); - - // Sets the delegate for the specified BrowserThread. - // - // Only one delegate may be registered at a time. Delegates may be - // unregistered by providing a NULL pointer. - // - // If the caller unregisters a delegate before CleanUp has been - // called, it must perform its own locking to ensure the delegate is - // not deleted while unregistering. - static void SetDelegate(ID identifier, BrowserThreadDelegate* delegate); - // Use these templates in conjuction with RefCountedThreadSafe when you want // to ensure that an object is deleted on a specific thread. This is needed // when an object can hop between threads (i.e. IO -> FILE -> IO), and thread @@ -250,10 +213,40 @@ class CONTENT_EXPORT BrowserThread { struct DeleteOnWebKitThread : public DeleteOnThread<WEBKIT> { }; private: - friend class BrowserThreadImpl; + // Construct a BrowserThread with the supplied identifier. It is an error + // to construct a BrowserThread that already exists. + explicit BrowserThread(ID identifier); + + // Special constructor for the main (UI) thread and unittests. We use a dummy + // thread here since the main thread already exists. + BrowserThread(ID identifier, MessageLoop* message_loop); + + virtual ~BrowserThread(); + + // Common initialization code for the constructors. + void Initialize(); + + // Constructors are only available through this subclass. + friend class content::BrowserThreadImpl; - BrowserThread() {} - DISALLOW_COPY_AND_ASSIGN(BrowserThread); + // TODO(joi): Remove. + friend class DeprecatedBrowserThread; + + // The identifier of this thread. Only one thread can exist with a given + // identifier at a given time. + // TODO(joi): Move to BrowserThreadImpl, and make constructors here + // do-nothing. + ID identifier_; +}; + +// Temporary escape hatch for chrome/ to construct BrowserThread, +// until we make content/ construct its own threads. +class CONTENT_EXPORT DeprecatedBrowserThread : public BrowserThread { + public: + explicit DeprecatedBrowserThread(BrowserThread::ID identifier); + DeprecatedBrowserThread(BrowserThread::ID identifier, + MessageLoop* message_loop); + virtual ~DeprecatedBrowserThread(); }; } // namespace content diff --git a/content/public/browser/browser_thread_delegate.h b/content/public/browser/browser_thread_delegate.h deleted file mode 100644 index ae9fc7b..0000000 --- a/content/public/browser/browser_thread_delegate.h +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_PUBLIC_BROWSER_BROWSER_THREAD_DELEGATE_H_ -#define CONTENT_PUBLIC_BROWSER_BROWSER_THREAD_DELEGATE_H_ -#pragma once - -namespace content { - -// A class with this type may be registered via -// BrowserThread::SetDelegate. -// -// If registered as such, it will receive an Init() call right before -// the BrowserThread in question starts its message loop (and right -// after the BrowserThread has done its own initialization), and a -// CleanUp call right after the message loop ends (and before the -// BrowserThread has done its own clean-up). -class BrowserThreadDelegate { - public: - virtual ~BrowserThreadDelegate() {} - - // Called just prior to starting the message loop. - virtual void Init() = 0; - - // Called just after the message loop ends. - virtual void CleanUp() = 0; -}; - -} // namespace content - -#endif // CONTENT_PUBLIC_BROWSER_BROWSER_THREAD_DELEGATE_H_ diff --git a/content/shell/shell_browser_context.cc b/content/shell/shell_browser_context.cc index f011b32..0f75d89 100644 --- a/content/shell/shell_browser_context.cc +++ b/content/shell/shell_browser_context.cc @@ -8,7 +8,6 @@ #include "base/file_util.h" #include "base/logging.h" #include "base/path_service.h" -#include "base/threading/thread.h" #include "content/browser/appcache/chrome_appcache_service.h" #include "content/browser/chrome_blob_storage_context.h" #include "content/browser/download/download_id_factory.h" @@ -141,10 +140,8 @@ net::URLRequestContextGetter* ShellBrowserContext::GetRequestContext() { if (!url_request_getter_) { url_request_getter_ = new ShellURLRequestContextGetter( GetPath(), - BrowserThread::UnsafeGetBrowserThread( - BrowserThread::IO)->message_loop(), - BrowserThread::UnsafeGetBrowserThread( - BrowserThread::FILE)->message_loop()); + shell_main_parts_->io_thread()->message_loop(), + shell_main_parts_->file_thread()->message_loop()); } return url_request_getter_; } diff --git a/content/shell/shell_browser_main.cc b/content/shell/shell_browser_main.cc index 324139e..a5f2fbe 100644 --- a/content/shell/shell_browser_main.cc +++ b/content/shell/shell_browser_main.cc @@ -40,9 +40,41 @@ ShellBrowserMainParts::ShellBrowserMainParts( } ShellBrowserMainParts::~ShellBrowserMainParts() { + base::ThreadRestrictions::SetIOAllowed(true); + io_thread()->message_loop()->PostTask( + FROM_HERE, base::IgnoreReturn<bool>( + base::Bind(&base::ThreadRestrictions::SetIOAllowed, true))); + + browser_context_.reset(); + + resource_dispatcher_host_->download_file_manager()->Shutdown(); + resource_dispatcher_host_->save_file_manager()->Shutdown(); + resource_dispatcher_host_->Shutdown(); + io_thread_.reset(); + cache_thread_.reset(); + process_launcher_thread_.reset(); + file_thread_.reset(); + resource_dispatcher_host_.reset(); // Kills WebKit thread. + db_thread_.reset(); } -void ShellBrowserMainParts::PreCreateThreads() { +void ShellBrowserMainParts::PreMainMessageLoopRun() { + db_thread_.reset(new BrowserProcessSubThread(BrowserThread::DB)); + db_thread_->Start(); + file_thread_.reset(new BrowserProcessSubThread(BrowserThread::FILE)); + file_thread_->Start(); + process_launcher_thread_.reset( + new BrowserProcessSubThread(BrowserThread::PROCESS_LAUNCHER)); + process_launcher_thread_->Start(); + + base::Thread::Options options; + options.message_loop_type = MessageLoop::TYPE_IO; + + cache_thread_.reset(new BrowserProcessSubThread(BrowserThread::CACHE)); + cache_thread_->StartWithOptions(options); + io_thread_.reset(new BrowserProcessSubThread(BrowserThread::IO)); + io_thread_->StartWithOptions(options); + browser_context_.reset(new ShellBrowserContext(this)); Shell::PlatformInitialize(); @@ -53,22 +85,7 @@ void ShellBrowserMainParts::PreCreateThreads() { NULL, MSG_ROUTING_NONE, NULL); -} - -void ShellBrowserMainParts::PostMainMessageLoopRun() { - browser_context_.reset(); - resource_dispatcher_host_->download_file_manager()->Shutdown(); - resource_dispatcher_host_->save_file_manager()->Shutdown(); - resource_dispatcher_host_->Shutdown(); -} - -void ShellBrowserMainParts::PreStopThread(BrowserThread::ID id) { - if (id == BrowserThread::WEBKIT) { - // It remains the embedder's responsibility to kill the WebKit - // thread. This happens when RDH is destroyed. - resource_dispatcher_host_.reset(); - } } bool ShellBrowserMainParts::MainMessageLoopRun(int* result_code) { diff --git a/content/shell/shell_browser_main.h b/content/shell/shell_browser_main.h index ffa44e6..0e617ca 100644 --- a/content/shell/shell_browser_main.h +++ b/content/shell/shell_browser_main.h @@ -35,25 +35,28 @@ class ShellBrowserMainParts : public BrowserMainParts { virtual void PreMainMessageLoopStart() OVERRIDE {} virtual void ToolkitInitialized() OVERRIDE {} virtual void PostMainMessageLoopStart() OVERRIDE {} - virtual void PreCreateThreads() OVERRIDE; - virtual void PreStartThread(BrowserThread::ID id) OVERRIDE {} - virtual void PostStartThread(BrowserThread::ID id) OVERRIDE {} - virtual void PreMainMessageLoopRun() OVERRIDE {} + virtual void PreMainMessageLoopRun() OVERRIDE; virtual bool MainMessageLoopRun(int* result_code) OVERRIDE; - virtual void PostMainMessageLoopRun() OVERRIDE; - virtual void PreStopThread(BrowserThread::ID id) OVERRIDE; - virtual void PostStopThread(BrowserThread::ID) OVERRIDE {} - virtual void PostDestroyThreads() OVERRIDE {} + virtual void PostMainMessageLoopRun() OVERRIDE {} ResourceDispatcherHost* GetResourceDispatcherHost(); ui::Clipboard* GetClipboard(); + base::Thread* io_thread() { return io_thread_.get(); } + base::Thread* file_thread() { return file_thread_.get(); } + private: scoped_ptr<ShellBrowserContext> browser_context_; scoped_ptr<ResourceDispatcherHost> resource_dispatcher_host_; scoped_ptr<ui::Clipboard> clipboard_; + scoped_ptr<base::Thread> io_thread_; + scoped_ptr<base::Thread> file_thread_; + scoped_ptr<base::Thread> db_thread_; + scoped_ptr<base::Thread> process_launcher_thread_; + scoped_ptr<base::Thread> cache_thread_; + DISALLOW_COPY_AND_ASSIGN(ShellBrowserMainParts); }; diff --git a/content/test/test_browser_thread.cc b/content/test/test_browser_thread.cc index 9224726..bd31919 100644 --- a/content/test/test_browser_thread.cc +++ b/content/test/test_browser_thread.cc @@ -10,37 +10,13 @@ namespace content { -// This gives access to set_message_loop(). -class TestBrowserThreadImpl : public BrowserThreadImpl { - public: - explicit TestBrowserThreadImpl(BrowserThread::ID identifier) - : BrowserThreadImpl(identifier) { - } - - TestBrowserThreadImpl(BrowserThread::ID identifier, - MessageLoop* message_loop) - : BrowserThreadImpl(identifier, message_loop) { - } - - virtual ~TestBrowserThreadImpl() { - Stop(); - } - - void set_message_loop(MessageLoop* loop) { - Thread::set_message_loop(loop); - } - - private: - DISALLOW_COPY_AND_ASSIGN(TestBrowserThreadImpl); -}; - TestBrowserThread::TestBrowserThread(BrowserThread::ID identifier) - : impl_(new TestBrowserThreadImpl(identifier)) { + : impl_(new BrowserThreadImpl(identifier)) { } TestBrowserThread::TestBrowserThread(BrowserThread::ID identifier, MessageLoop* message_loop) - : impl_(new TestBrowserThreadImpl(identifier, message_loop)) { + : impl_(new BrowserThreadImpl(identifier, message_loop)) { } TestBrowserThread::~TestBrowserThread() { @@ -69,8 +45,4 @@ base::Thread* TestBrowserThread::DeprecatedGetThreadObject() { return impl_.get(); } -void TestBrowserThread::DeprecatedSetMessageLoop(MessageLoop* loop) { - impl_->set_message_loop(loop); -} - } // namespace content diff --git a/content/test/test_browser_thread.h b/content/test/test_browser_thread.h index 9466ae2..5d3439e 100644 --- a/content/test/test_browser_thread.h +++ b/content/test/test_browser_thread.h @@ -18,7 +18,7 @@ class Thread; namespace content { -class TestBrowserThreadImpl; +class BrowserThreadImpl; // A BrowserThread for unit tests; this lets unit tests in chrome/ // create BrowserThread instances. @@ -49,12 +49,8 @@ class TestBrowserThread { // in new tests. base::Thread* DeprecatedGetThreadObject(); - // Sets the message loop to use for the thread. This should not be - // used in new tests. - void DeprecatedSetMessageLoop(MessageLoop* loop); - private: - scoped_ptr<TestBrowserThreadImpl> impl_; + scoped_ptr<BrowserThreadImpl> impl_; DISALLOW_COPY_AND_ASSIGN(TestBrowserThread); }; |