summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorjoi@chromium.org <joi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-28 14:00:36 +0000
committerjoi@chromium.org <joi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-28 14:00:36 +0000
commit14f79fec5f13a623f837f0b9438556180e5e7896 (patch)
treef86cadba8422d4a453acc22792406ff2b2cb8da8 /content
parentf8a7f81d377eb872c2c9760813966920810edfb3 (diff)
downloadchromium_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.cc199
-rw-r--r--content/browser/browser_main_loop.h17
-rw-r--r--content/browser/browser_process_sub_thread.cc6
-rw-r--r--content/browser/browser_thread_impl.cc160
-rw-r--r--content/browser/browser_thread_impl.h28
-rw-r--r--content/content_browser.gypi2
-rw-r--r--content/public/browser/browser_main_parts.h33
-rw-r--r--content/public/browser/browser_shutdown.h32
-rw-r--r--content/public/browser/browser_thread.h81
-rw-r--r--content/public/browser/browser_thread_delegate.h32
-rw-r--r--content/shell/shell_browser_context.cc7
-rw-r--r--content/shell/shell_browser_main.cc49
-rw-r--r--content/shell/shell_browser_main.h19
-rw-r--r--content/test/test_browser_thread.cc32
-rw-r--r--content/test/test_browser_thread.h8
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(&current_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(&current_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);
};