[Session restore] Rename group name Enabled to Restore.
[chromium-blink-merge.git] / content / browser / browser_thread_impl.cc
bloba8ce1b0dcd510dea55cc7a95829e83bd116bd345
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/browser_thread_impl.h"
7 #include <string>
9 #include "base/atomicops.h"
10 #include "base/bind.h"
11 #include "base/compiler_specific.h"
12 #include "base/lazy_instance.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/message_loop/message_loop_proxy.h"
15 #include "base/threading/sequenced_worker_pool.h"
16 #include "base/threading/thread_restrictions.h"
17 #include "content/public/browser/browser_thread_delegate.h"
18 #include "net/disk_cache/simple/simple_backend_impl.h"
20 #if defined(OS_ANDROID)
21 #include "base/android/jni_android.h"
22 #endif
24 namespace content {
26 namespace {
28 // Friendly names for the well-known threads.
29 static const char* g_browser_thread_names[BrowserThread::ID_COUNT] = {
30 "", // UI (name assembled in browser_main.cc).
31 "Chrome_DBThread", // DB
32 "Chrome_FileThread", // FILE
33 "Chrome_FileUserBlockingThread", // FILE_USER_BLOCKING
34 "Chrome_ProcessLauncherThread", // PROCESS_LAUNCHER
35 "Chrome_CacheThread", // CACHE
36 "Chrome_IOThread", // IO
39 // An implementation of MessageLoopProxy to be used in conjunction
40 // with BrowserThread.
41 class BrowserThreadMessageLoopProxy : public base::MessageLoopProxy {
42 public:
43 explicit BrowserThreadMessageLoopProxy(BrowserThread::ID identifier)
44 : id_(identifier) {
47 // MessageLoopProxy implementation.
48 bool PostDelayedTask(const tracked_objects::Location& from_here,
49 const base::Closure& task,
50 base::TimeDelta delay) override {
51 return BrowserThread::PostDelayedTask(id_, from_here, task, delay);
54 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here,
55 const base::Closure& task,
56 base::TimeDelta delay) override {
57 return BrowserThread::PostNonNestableDelayedTask(id_, from_here, task,
58 delay);
61 bool RunsTasksOnCurrentThread() const override {
62 return BrowserThread::CurrentlyOn(id_);
65 protected:
66 ~BrowserThreadMessageLoopProxy() override {}
68 private:
69 BrowserThread::ID id_;
70 DISALLOW_COPY_AND_ASSIGN(BrowserThreadMessageLoopProxy);
73 // A separate helper is used just for the proxies, in order to avoid needing
74 // to initialize the globals to create a proxy.
75 struct BrowserThreadProxies {
76 BrowserThreadProxies() {
77 for (int i = 0; i < BrowserThread::ID_COUNT; ++i) {
78 proxies[i] =
79 new BrowserThreadMessageLoopProxy(static_cast<BrowserThread::ID>(i));
83 scoped_refptr<base::MessageLoopProxy> proxies[BrowserThread::ID_COUNT];
86 base::LazyInstance<BrowserThreadProxies>::Leaky
87 g_proxies = LAZY_INSTANCE_INITIALIZER;
89 struct BrowserThreadGlobals {
90 BrowserThreadGlobals()
91 : blocking_pool(new base::SequencedWorkerPool(3, "BrowserBlocking")) {
92 memset(threads, 0, BrowserThread::ID_COUNT * sizeof(threads[0]));
93 memset(thread_delegates, 0,
94 BrowserThread::ID_COUNT * sizeof(thread_delegates[0]));
97 // This lock protects |threads|. Do not read or modify that array
98 // without holding this lock. Do not block while holding this lock.
99 base::Lock lock;
101 // This array is protected by |lock|. The threads are not owned by this
102 // array. Typically, the threads are owned on the UI thread by
103 // BrowserMainLoop. BrowserThreadImpl objects remove themselves from this
104 // array upon destruction.
105 BrowserThreadImpl* threads[BrowserThread::ID_COUNT];
107 // Only atomic operations are used on this array. The delegates are not owned
108 // by this array, rather by whoever calls BrowserThread::SetDelegate.
109 BrowserThreadDelegate* thread_delegates[BrowserThread::ID_COUNT];
111 const scoped_refptr<base::SequencedWorkerPool> blocking_pool;
114 base::LazyInstance<BrowserThreadGlobals>::Leaky
115 g_globals = LAZY_INSTANCE_INITIALIZER;
117 } // namespace
119 BrowserThreadImpl::BrowserThreadImpl(ID identifier)
120 : Thread(g_browser_thread_names[identifier]),
121 identifier_(identifier) {
122 Initialize();
125 BrowserThreadImpl::BrowserThreadImpl(ID identifier,
126 base::MessageLoop* message_loop)
127 : Thread(message_loop->thread_name()), identifier_(identifier) {
128 set_message_loop(message_loop);
129 Initialize();
132 // static
133 void BrowserThreadImpl::ShutdownThreadPool() {
134 // The goal is to make it impossible for chrome to 'infinite loop' during
135 // shutdown, but to reasonably expect that all BLOCKING_SHUTDOWN tasks queued
136 // during shutdown get run. There's nothing particularly scientific about the
137 // number chosen.
138 const int kMaxNewShutdownBlockingTasks = 1000;
139 BrowserThreadGlobals& globals = g_globals.Get();
140 globals.blocking_pool->Shutdown(kMaxNewShutdownBlockingTasks);
143 // static
144 void BrowserThreadImpl::FlushThreadPoolHelperForTesting() {
145 // We don't want to create a pool if none exists.
146 if (g_globals == NULL)
147 return;
148 g_globals.Get().blocking_pool->FlushForTesting();
149 disk_cache::SimpleBackendImpl::FlushWorkerPoolForTesting();
152 void BrowserThreadImpl::Init() {
153 BrowserThreadGlobals& globals = g_globals.Get();
155 using base::subtle::AtomicWord;
156 AtomicWord* storage =
157 reinterpret_cast<AtomicWord*>(&globals.thread_delegates[identifier_]);
158 AtomicWord stored_pointer = base::subtle::NoBarrier_Load(storage);
159 BrowserThreadDelegate* delegate =
160 reinterpret_cast<BrowserThreadDelegate*>(stored_pointer);
161 if (delegate) {
162 delegate->Init();
163 message_loop()->PostTask(FROM_HERE,
164 base::Bind(&BrowserThreadDelegate::InitAsync,
165 // Delegate is expected to exist for the
166 // duration of the thread's lifetime
167 base::Unretained(delegate)));
171 // We disable optimizations for this block of functions so the compiler doesn't
172 // merge them all together.
173 MSVC_DISABLE_OPTIMIZE()
174 MSVC_PUSH_DISABLE_WARNING(4748)
176 NOINLINE void BrowserThreadImpl::UIThreadRun(base::MessageLoop* message_loop) {
177 volatile int line_number = __LINE__;
178 Thread::Run(message_loop);
179 CHECK_GT(line_number, 0);
182 NOINLINE void BrowserThreadImpl::DBThreadRun(base::MessageLoop* message_loop) {
183 volatile int line_number = __LINE__;
184 Thread::Run(message_loop);
185 CHECK_GT(line_number, 0);
188 NOINLINE void BrowserThreadImpl::FileThreadRun(
189 base::MessageLoop* message_loop) {
190 volatile int line_number = __LINE__;
191 Thread::Run(message_loop);
192 CHECK_GT(line_number, 0);
195 NOINLINE void BrowserThreadImpl::FileUserBlockingThreadRun(
196 base::MessageLoop* message_loop) {
197 volatile int line_number = __LINE__;
198 Thread::Run(message_loop);
199 CHECK_GT(line_number, 0);
202 NOINLINE void BrowserThreadImpl::ProcessLauncherThreadRun(
203 base::MessageLoop* message_loop) {
204 volatile int line_number = __LINE__;
205 Thread::Run(message_loop);
206 CHECK_GT(line_number, 0);
209 NOINLINE void BrowserThreadImpl::CacheThreadRun(
210 base::MessageLoop* message_loop) {
211 volatile int line_number = __LINE__;
212 Thread::Run(message_loop);
213 CHECK_GT(line_number, 0);
216 NOINLINE void BrowserThreadImpl::IOThreadRun(base::MessageLoop* message_loop) {
217 volatile int line_number = __LINE__;
218 Thread::Run(message_loop);
219 CHECK_GT(line_number, 0);
222 MSVC_POP_WARNING()
223 MSVC_ENABLE_OPTIMIZE();
225 void BrowserThreadImpl::Run(base::MessageLoop* message_loop) {
226 #if defined(OS_ANDROID)
227 // Not to reset thread name to "Thread-???" by VM, attach VM with thread name.
228 // Though it may create unnecessary VM thread objects, keeping thread name
229 // gives more benefit in debugging in the platform.
230 if (!thread_name().empty()) {
231 base::android::AttachCurrentThreadWithName(thread_name());
233 #endif
235 BrowserThread::ID thread_id = ID_COUNT;
236 if (!GetCurrentThreadIdentifier(&thread_id))
237 return Thread::Run(message_loop);
239 switch (thread_id) {
240 case BrowserThread::UI:
241 return UIThreadRun(message_loop);
242 case BrowserThread::DB:
243 return DBThreadRun(message_loop);
244 case BrowserThread::FILE:
245 return FileThreadRun(message_loop);
246 case BrowserThread::FILE_USER_BLOCKING:
247 return FileUserBlockingThreadRun(message_loop);
248 case BrowserThread::PROCESS_LAUNCHER:
249 return ProcessLauncherThreadRun(message_loop);
250 case BrowserThread::CACHE:
251 return CacheThreadRun(message_loop);
252 case BrowserThread::IO:
253 return IOThreadRun(message_loop);
254 case BrowserThread::ID_COUNT:
255 CHECK(false); // This shouldn't actually be reached!
256 break;
258 Thread::Run(message_loop);
261 void BrowserThreadImpl::CleanUp() {
262 BrowserThreadGlobals& globals = g_globals.Get();
264 using base::subtle::AtomicWord;
265 AtomicWord* storage =
266 reinterpret_cast<AtomicWord*>(&globals.thread_delegates[identifier_]);
267 AtomicWord stored_pointer = base::subtle::NoBarrier_Load(storage);
268 BrowserThreadDelegate* delegate =
269 reinterpret_cast<BrowserThreadDelegate*>(stored_pointer);
271 if (delegate)
272 delegate->CleanUp();
275 void BrowserThreadImpl::Initialize() {
276 BrowserThreadGlobals& globals = g_globals.Get();
278 base::AutoLock lock(globals.lock);
279 DCHECK(identifier_ >= 0 && identifier_ < ID_COUNT);
280 DCHECK(globals.threads[identifier_] == NULL);
281 globals.threads[identifier_] = this;
284 BrowserThreadImpl::~BrowserThreadImpl() {
285 // All Thread subclasses must call Stop() in the destructor. This is
286 // doubly important here as various bits of code check they are on
287 // the right BrowserThread.
288 Stop();
290 BrowserThreadGlobals& globals = g_globals.Get();
291 base::AutoLock lock(globals.lock);
292 globals.threads[identifier_] = NULL;
293 #ifndef NDEBUG
294 // Double check that the threads are ordered correctly in the enumeration.
295 for (int i = identifier_ + 1; i < ID_COUNT; ++i) {
296 DCHECK(!globals.threads[i]) <<
297 "Threads must be listed in the reverse order that they die";
299 #endif
302 // static
303 bool BrowserThreadImpl::PostTaskHelper(
304 BrowserThread::ID identifier,
305 const tracked_objects::Location& from_here,
306 const base::Closure& task,
307 base::TimeDelta delay,
308 bool nestable) {
309 DCHECK(identifier >= 0 && identifier < ID_COUNT);
310 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in
311 // order of lifetime. So no need to lock if we know that the target thread
312 // outlives current thread.
313 // Note: since the array is so small, ok to loop instead of creating a map,
314 // which would require a lock because std::map isn't thread safe, defeating
315 // the whole purpose of this optimization.
316 BrowserThread::ID current_thread = ID_COUNT;
317 bool target_thread_outlives_current =
318 GetCurrentThreadIdentifier(&current_thread) &&
319 current_thread >= identifier;
321 BrowserThreadGlobals& globals = g_globals.Get();
322 if (!target_thread_outlives_current)
323 globals.lock.Acquire();
325 base::MessageLoop* message_loop =
326 globals.threads[identifier] ? globals.threads[identifier]->message_loop()
327 : NULL;
328 if (message_loop) {
329 if (nestable) {
330 message_loop->PostDelayedTask(from_here, task, delay);
331 } else {
332 message_loop->PostNonNestableDelayedTask(from_here, task, delay);
336 if (!target_thread_outlives_current)
337 globals.lock.Release();
339 return !!message_loop;
342 // static
343 bool BrowserThread::PostBlockingPoolTask(
344 const tracked_objects::Location& from_here,
345 const base::Closure& task) {
346 return g_globals.Get().blocking_pool->PostWorkerTask(from_here, task);
349 // static
350 bool BrowserThread::PostBlockingPoolTaskAndReply(
351 const tracked_objects::Location& from_here,
352 const base::Closure& task,
353 const base::Closure& reply) {
354 return g_globals.Get().blocking_pool->PostTaskAndReply(
355 from_here, task, reply);
358 // static
359 bool BrowserThread::PostBlockingPoolSequencedTask(
360 const std::string& sequence_token_name,
361 const tracked_objects::Location& from_here,
362 const base::Closure& task) {
363 return g_globals.Get().blocking_pool->PostNamedSequencedWorkerTask(
364 sequence_token_name, from_here, task);
367 // static
368 base::SequencedWorkerPool* BrowserThread::GetBlockingPool() {
369 return g_globals.Get().blocking_pool.get();
372 // static
373 bool BrowserThread::IsThreadInitialized(ID identifier) {
374 if (g_globals == NULL)
375 return false;
377 BrowserThreadGlobals& globals = g_globals.Get();
378 base::AutoLock lock(globals.lock);
379 DCHECK(identifier >= 0 && identifier < ID_COUNT);
380 return globals.threads[identifier] != NULL;
383 // static
384 bool BrowserThread::CurrentlyOn(ID identifier) {
385 // We shouldn't use MessageLoop::current() since it uses LazyInstance which
386 // may be deleted by ~AtExitManager when a WorkerPool thread calls this
387 // function.
388 // http://crbug.com/63678
389 base::ThreadRestrictions::ScopedAllowSingleton allow_singleton;
390 BrowserThreadGlobals& globals = g_globals.Get();
391 base::AutoLock lock(globals.lock);
392 DCHECK(identifier >= 0 && identifier < ID_COUNT);
393 return globals.threads[identifier] &&
394 globals.threads[identifier]->message_loop() ==
395 base::MessageLoop::current();
398 static const char* GetThreadName(BrowserThread::ID thread) {
399 if (BrowserThread::UI < thread && thread < BrowserThread::ID_COUNT)
400 return g_browser_thread_names[thread];
401 if (thread == BrowserThread::UI)
402 return "Chrome_UIThread";
403 return "Unknown Thread";
406 // static
407 std::string BrowserThread::GetDCheckCurrentlyOnErrorMessage(ID expected) {
408 const base::MessageLoop* message_loop = base::MessageLoop::current();
409 ID actual_browser_thread;
410 const char* actual_name = "Unknown Thread";
411 if (message_loop && !message_loop->thread_name().empty()) {
412 actual_name = message_loop->thread_name().c_str();
413 } else if (GetCurrentThreadIdentifier(&actual_browser_thread)) {
414 actual_name = GetThreadName(actual_browser_thread);
416 std::string result = "Must be called on ";
417 result += GetThreadName(expected);
418 result += "; actually called on ";
419 result += actual_name;
420 result += ".";
421 return result;
424 // static
425 bool BrowserThread::IsMessageLoopValid(ID identifier) {
426 if (g_globals == NULL)
427 return false;
429 BrowserThreadGlobals& globals = g_globals.Get();
430 base::AutoLock lock(globals.lock);
431 DCHECK(identifier >= 0 && identifier < ID_COUNT);
432 return globals.threads[identifier] &&
433 globals.threads[identifier]->message_loop();
436 // static
437 bool BrowserThread::PostTask(ID identifier,
438 const tracked_objects::Location& from_here,
439 const base::Closure& task) {
440 return BrowserThreadImpl::PostTaskHelper(
441 identifier, from_here, task, base::TimeDelta(), true);
444 // static
445 bool BrowserThread::PostDelayedTask(ID identifier,
446 const tracked_objects::Location& from_here,
447 const base::Closure& task,
448 base::TimeDelta delay) {
449 return BrowserThreadImpl::PostTaskHelper(
450 identifier, from_here, task, delay, true);
453 // static
454 bool BrowserThread::PostNonNestableTask(
455 ID identifier,
456 const tracked_objects::Location& from_here,
457 const base::Closure& task) {
458 return BrowserThreadImpl::PostTaskHelper(
459 identifier, from_here, task, base::TimeDelta(), false);
462 // static
463 bool BrowserThread::PostNonNestableDelayedTask(
464 ID identifier,
465 const tracked_objects::Location& from_here,
466 const base::Closure& task,
467 base::TimeDelta delay) {
468 return BrowserThreadImpl::PostTaskHelper(
469 identifier, from_here, task, delay, false);
472 // static
473 bool BrowserThread::PostTaskAndReply(
474 ID identifier,
475 const tracked_objects::Location& from_here,
476 const base::Closure& task,
477 const base::Closure& reply) {
478 return GetMessageLoopProxyForThread(identifier)->PostTaskAndReply(from_here,
479 task,
480 reply);
483 // static
484 bool BrowserThread::GetCurrentThreadIdentifier(ID* identifier) {
485 if (g_globals == NULL)
486 return false;
488 // We shouldn't use MessageLoop::current() since it uses LazyInstance which
489 // may be deleted by ~AtExitManager when a WorkerPool thread calls this
490 // function.
491 // http://crbug.com/63678
492 base::ThreadRestrictions::ScopedAllowSingleton allow_singleton;
493 base::MessageLoop* cur_message_loop = base::MessageLoop::current();
494 BrowserThreadGlobals& globals = g_globals.Get();
495 for (int i = 0; i < ID_COUNT; ++i) {
496 if (globals.threads[i] &&
497 globals.threads[i]->message_loop() == cur_message_loop) {
498 *identifier = globals.threads[i]->identifier_;
499 return true;
503 return false;
506 // static
507 scoped_refptr<base::MessageLoopProxy>
508 BrowserThread::GetMessageLoopProxyForThread(ID identifier) {
509 return g_proxies.Get().proxies[identifier];
512 // static
513 base::MessageLoop* BrowserThread::UnsafeGetMessageLoopForThread(ID identifier) {
514 if (g_globals == NULL)
515 return NULL;
517 BrowserThreadGlobals& globals = g_globals.Get();
518 base::AutoLock lock(globals.lock);
519 base::Thread* thread = globals.threads[identifier];
520 DCHECK(thread);
521 base::MessageLoop* loop = thread->message_loop();
522 return loop;
525 // static
526 void BrowserThread::SetDelegate(ID identifier,
527 BrowserThreadDelegate* delegate) {
528 using base::subtle::AtomicWord;
529 BrowserThreadGlobals& globals = g_globals.Get();
530 AtomicWord* storage = reinterpret_cast<AtomicWord*>(
531 &globals.thread_delegates[identifier]);
532 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange(
533 storage, reinterpret_cast<AtomicWord>(delegate));
535 // This catches registration when previously registered.
536 DCHECK(!delegate || !old_pointer);
539 } // namespace content