1// Copyright 2013 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.
4
5#include "content/public/test/test_browser_thread_bundle.h"
6
7#include "base/message_loop/message_loop.h"
8#include "base/run_loop.h"
9#include "content/browser/browser_thread_impl.h"
10#include "content/public/test/test_browser_thread.h"
11
12namespace content {
13
14TestBrowserThreadBundle::TestBrowserThreadBundle() {
15  Init(DEFAULT);
16}
17
18TestBrowserThreadBundle::TestBrowserThreadBundle(int options) {
19  Init(options);
20}
21
22TestBrowserThreadBundle::~TestBrowserThreadBundle() {
23  // To avoid memory leaks, we must ensure that any tasks posted to the blocking
24  // pool via PostTaskAndReply are able to reply back to the originating thread.
25  // Thus we must flush the blocking pool while the browser threads still exist.
26  base::RunLoop().RunUntilIdle();
27  BrowserThreadImpl::FlushThreadPoolHelperForTesting();
28
29  // To ensure a clean teardown, each thread's message loop must be flushed
30  // just before the thread is destroyed. But destroying a fake thread does not
31  // automatically flush the message loop, so we have to do it manually.
32  // See http://crbug.com/247525 for discussion.
33  base::RunLoop().RunUntilIdle();
34  io_thread_.reset();
35  base::RunLoop().RunUntilIdle();
36  cache_thread_.reset();
37  base::RunLoop().RunUntilIdle();
38  process_launcher_thread_.reset();
39  base::RunLoop().RunUntilIdle();
40  file_user_blocking_thread_.reset();
41  base::RunLoop().RunUntilIdle();
42  file_thread_.reset();
43  base::RunLoop().RunUntilIdle();
44  db_thread_.reset();
45  base::RunLoop().RunUntilIdle();
46  // This is the point at which we normally shut down the thread pool. So flush
47  // it again in case any shutdown tasks have been posted to the pool from the
48  // threads above.
49  BrowserThreadImpl::FlushThreadPoolHelperForTesting();
50  base::RunLoop().RunUntilIdle();
51  ui_thread_.reset();
52  base::RunLoop().RunUntilIdle();
53}
54
55void TestBrowserThreadBundle::Init(int options) {
56  if (options & IO_MAINLOOP) {
57    message_loop_.reset(new base::MessageLoopForIO());
58  } else {
59    message_loop_.reset(new base::MessageLoopForUI());
60  }
61
62  ui_thread_.reset(new TestBrowserThread(BrowserThread::UI,
63                                         message_loop_.get()));
64
65  if (options & REAL_DB_THREAD) {
66    db_thread_.reset(new TestBrowserThread(BrowserThread::DB));
67    db_thread_->Start();
68  } else {
69    db_thread_.reset(new TestBrowserThread(BrowserThread::DB,
70                                           message_loop_.get()));
71  }
72
73  if (options & REAL_FILE_THREAD) {
74    file_thread_.reset(new TestBrowserThread(BrowserThread::FILE));
75    file_thread_->Start();
76  } else {
77    file_thread_.reset(new TestBrowserThread(BrowserThread::FILE,
78                                             message_loop_.get()));
79  }
80
81  if (options & REAL_FILE_USER_BLOCKING_THREAD) {
82    file_user_blocking_thread_.reset(
83        new TestBrowserThread(BrowserThread::FILE_USER_BLOCKING));
84    file_user_blocking_thread_->Start();
85  } else {
86    file_user_blocking_thread_.reset(
87        new TestBrowserThread(BrowserThread::FILE_USER_BLOCKING,
88                              message_loop_.get()));
89  }
90
91  if (options & REAL_PROCESS_LAUNCHER_THREAD) {
92    process_launcher_thread_.reset(
93        new TestBrowserThread(BrowserThread::PROCESS_LAUNCHER));
94    process_launcher_thread_->Start();
95  } else {
96    process_launcher_thread_.reset(
97        new TestBrowserThread(BrowserThread::PROCESS_LAUNCHER,
98                              message_loop_.get()));
99  }
100
101  if (options & REAL_CACHE_THREAD) {
102    cache_thread_.reset(new TestBrowserThread(BrowserThread::CACHE));
103    cache_thread_->Start();
104  } else {
105    cache_thread_.reset(new TestBrowserThread(BrowserThread::CACHE,
106                                              message_loop_.get()));
107  }
108
109  if (options & REAL_IO_THREAD) {
110    io_thread_.reset(new TestBrowserThread(BrowserThread::IO));
111    io_thread_->StartIOThread();
112  } else {
113    io_thread_.reset(
114        new TestBrowserThread(BrowserThread::IO, message_loop_.get()));
115  }
116}
117
118}  // namespace content
119