browser_test_base.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
1// Copyright (c) 2011 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/browser_test_base.h"
6
7#include "base/bind.h"
8#include "base/command_line.h"
9#include "base/debug/stack_trace.h"
10#include "base/process_util.h"
11#include "content/browser/renderer_host/render_process_host_impl.h"
12#include "content/public/browser/browser_thread.h"
13#include "content/public/common/content_switches.h"
14#include "content/public/common/main_function_params.h"
15#include "content/public/test/test_utils.h"
16
17#if defined(OS_MACOSX)
18#include "base/mac/mac_util.h"
19#include "base/power_monitor/power_monitor.h"
20#endif
21
22#if defined(OS_ANDROID)
23#include "base/threading/thread_restrictions.h"
24#include "content/public/browser/browser_main_runner.h"
25#include "content/public/browser/browser_thread.h"
26#endif
27
28namespace content {
29namespace {
30
31#if defined(OS_POSIX)
32// On SIGTERM (sent by the runner on timeouts), dump a stack trace (to make
33// debugging easier) and also exit with a known error code (so that the test
34// framework considers this a failure -- http://crbug.com/57578).
35// Note: We only want to do this in the browser process, and not forked
36// processes. That might lead to hangs because of locks inside tcmalloc or the
37// OS. See http://crbug.com/141302.
38static int g_browser_process_pid;
39static void DumpStackTraceSignalHandler(int signal) {
40  if (g_browser_process_pid == base::GetCurrentProcId()) {
41    logging::RawLog(logging::LOG_ERROR,
42                    "BrowserTestBase signal handler received SIGTERM. "
43                    "Backtrace:\n");
44    base::debug::StackTrace().PrintBacktrace();
45  }
46  _exit(128 + signal);
47}
48#endif  // defined(OS_POSIX)
49
50void RunTaskOnRendererThread(const base::Closure& task,
51                             const base::Closure& quit_task) {
52  task.Run();
53  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_task);
54}
55
56}  // namespace
57
58extern int BrowserMain(const MainFunctionParams&);
59
60BrowserTestBase::BrowserTestBase() {
61#if defined(OS_MACOSX)
62  base::mac::SetOverrideAmIBundled(true);
63  base::PowerMonitor::AllocateSystemIOPorts();
64#endif
65
66#if defined(OS_POSIX)
67  handle_sigterm_ = true;
68#endif
69}
70
71BrowserTestBase::~BrowserTestBase() {
72#if defined(OS_ANDROID)
73  // RemoteTestServer can cause wait on the UI thread.
74  base::ThreadRestrictions::ScopedAllowWait allow_wait;
75  test_server_.reset(NULL);
76#endif
77}
78
79void BrowserTestBase::SetUp() {
80  CommandLine* command_line = CommandLine::ForCurrentProcess();
81
82  // The tests assume that file:// URIs can freely access other file:// URIs.
83  command_line->AppendSwitch(switches::kAllowFileAccessFromFiles);
84
85  command_line->AppendSwitch(switches::kDomAutomationController);
86
87  command_line->AppendSwitch(switches::kSkipGpuDataLoading);
88
89  MainFunctionParams params(*command_line);
90  params.ui_task =
91      new base::Closure(
92          base::Bind(&BrowserTestBase::ProxyRunTestOnMainThreadLoop, this));
93
94  SetUpInProcessBrowserTestFixture();
95#if defined(OS_ANDROID)
96  BrowserMainRunner::Create()->Initialize(params);
97  // We are done running the test by now. During teardown we
98  // need to be able to perform IO.
99  base::ThreadRestrictions::SetIOAllowed(true);
100  BrowserThread::PostTask(
101      BrowserThread::IO, FROM_HERE,
102      base::Bind(base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed),
103                 true));
104#else
105  BrowserMain(params);
106#endif
107  TearDownInProcessBrowserTestFixture();
108}
109
110void BrowserTestBase::TearDown() {
111}
112
113void BrowserTestBase::ProxyRunTestOnMainThreadLoop() {
114#if defined(OS_POSIX)
115  if (handle_sigterm_) {
116    g_browser_process_pid = base::GetCurrentProcId();
117    signal(SIGTERM, DumpStackTraceSignalHandler);
118  }
119#endif  // defined(OS_POSIX)
120  RunTestOnMainThreadLoop();
121}
122
123void BrowserTestBase::CreateTestServer(const base::FilePath& test_server_base) {
124  CHECK(!test_server_.get());
125  test_server_.reset(new net::SpawnedTestServer(
126      net::SpawnedTestServer::TYPE_HTTP,
127      net::SpawnedTestServer::kLocalhost,
128      test_server_base));
129}
130
131void BrowserTestBase::PostTaskToInProcessRendererAndWait(
132    const base::Closure& task) {
133  CHECK(CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess));
134
135  scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner;
136
137  base::MessageLoop* renderer_loop =
138      RenderProcessHostImpl::GetInProcessRendererThreadForTesting();
139  CHECK(renderer_loop);
140
141  renderer_loop->PostTask(
142      FROM_HERE,
143      base::Bind(&RunTaskOnRendererThread, task, runner->QuitClosure()));
144  runner->Run();
145}
146
147}  // namespace content
148