blob: 75740ae7aa866dbe80539be7d577e5171a54d526 [file] [log] [blame]
[email protected]c4ff4952010-01-08 19:12:471// Copyright (c) 2010 The Chromium Authors. All rights reserved.
[email protected]d4515eb2009-01-30 00:40:432// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/test/in_process_browser_test.h"
6
7#include "base/command_line.h"
[email protected]d8412052009-04-21 22:01:018#include "base/file_path.h"
[email protected]d4515eb2009-01-30 00:40:439#include "base/file_util.h"
10#include "base/path_service.h"
[email protected]304a3172010-05-04 05:38:4411#include "base/scoped_nsautorelease_pool.h"
[email protected]470f7a52010-09-23 20:20:3812#include "base/scoped_temp_dir.h"
[email protected]528c56d2010-07-30 19:28:4413#include "base/string_number_conversions.h"
[email protected]fb895c62009-10-09 18:20:3014#include "base/test/test_file_util.h"
[email protected]d4515eb2009-01-30 00:40:4315#include "chrome/browser/browser.h"
[email protected]b6e38ef2009-06-16 00:43:2316#include "chrome/browser/browser_list.h"
[email protected]d4515eb2009-01-30 00:40:4317#include "chrome/browser/browser_process.h"
18#include "chrome/browser/browser_shutdown.h"
[email protected]108c2a12009-06-05 22:18:0919#include "chrome/browser/browser_window.h"
[email protected]6fad2632009-11-02 05:59:3720#include "chrome/browser/chrome_thread.h"
[email protected]c4ff4952010-01-08 19:12:4721#include "chrome/browser/intranet_redirect_detector.h"
[email protected]0ac83682010-01-22 17:46:2722#include "chrome/browser/io_thread.h"
[email protected]cec4a272009-07-31 21:55:0323#include "chrome/browser/net/url_request_mock_util.h"
[email protected]d4515eb2009-01-30 00:40:4324#include "chrome/browser/profile.h"
25#include "chrome/browser/profile_manager.h"
[email protected]8bcdec92009-02-25 16:15:1826#include "chrome/browser/renderer_host/render_process_host.h"
[email protected]5c238752009-06-13 10:29:0727#include "chrome/browser/tab_contents/tab_contents.h"
[email protected]c848d3d92010-09-16 21:57:4528#include "chrome/browser/tabs/tab_strip_model.h"
[email protected]d4515eb2009-01-30 00:40:4329#include "chrome/common/chrome_constants.h"
30#include "chrome/common/chrome_paths.h"
31#include "chrome/common/chrome_switches.h"
32#include "chrome/common/main_function_params.h"
[email protected]ad1f9bd2009-07-30 20:23:1533#include "chrome/common/notification_registrar.h"
34#include "chrome/common/notification_type.h"
[email protected]e0d481582009-09-15 21:06:2535#include "chrome/common/url_constants.h"
[email protected]470f7a52010-09-23 20:20:3836#include "chrome/test/test_launcher_utils.h"
[email protected]d4515eb2009-01-30 00:40:4337#include "chrome/test/testing_browser_process.h"
38#include "chrome/test/ui_test_utils.h"
[email protected]c4ff4952010-01-08 19:12:4739#include "net/base/mock_host_resolver.h"
[email protected]3985ba82010-07-29 21:44:1240#include "net/test/test_server.h"
[email protected]d4515eb2009-01-30 00:40:4341#include "sandbox/src/dep.h"
42
[email protected]c848d3d92010-09-16 21:57:4543#if defined(OS_WIN)
44#include "chrome/browser/views/frame/browser_view.h"
45#endif
46
[email protected]8ecd3aad2009-11-04 08:32:2247#if defined(OS_LINUX)
[email protected]470f7a52010-09-23 20:20:3848#include "base/environment.h"
[email protected]8ecd3aad2009-11-04 08:32:2249#include "base/singleton.h"
50#include "chrome/browser/renderer_host/render_sandbox_host_linux.h"
51#include "chrome/browser/zygote_host_linux.h"
52
53namespace {
54
55// A helper class to do Linux-only initialization only once per process.
56class LinuxHostInit {
57 public:
58 LinuxHostInit() {
[email protected]576a4ca2009-11-05 01:41:0959 RenderSandboxHostLinux* shost = Singleton<RenderSandboxHostLinux>::get();
[email protected]8ecd3aad2009-11-04 08:32:2260 shost->Init("");
[email protected]576a4ca2009-11-05 01:41:0961 ZygoteHost* zhost = Singleton<ZygoteHost>::get();
[email protected]8ecd3aad2009-11-04 08:32:2262 zhost->Init("");
63 }
64 ~LinuxHostInit() {}
65};
66
67} // namespace
68#endif
69
[email protected]02dbca0b2010-09-17 07:44:1070#if defined(OS_CHROMEOS)
71#include "chrome/browser/chromeos/cros/cros_library.h"
72#endif // defined(OS_CHROMEOS)
73
[email protected]e1c10f182010-09-30 08:53:0674namespace {
75
76void InitializeBrowser(Browser* browser) {
77 browser->AddTabWithURL(GURL(chrome::kAboutBlankURL), GURL(),
78 PageTransition::START_PAGE, -1,
79 TabStripModel::ADD_SELECTED, NULL, std::string(),
80 &browser);
81
82 // Wait for the page to finish loading.
83 ui_test_utils::WaitForNavigation(
84 &browser->GetSelectedTabContents()->controller());
85
86 browser->window()->Show();
87}
88
89} // namespace
90
[email protected]d4515eb2009-01-30 00:40:4391extern int BrowserMain(const MainFunctionParams&);
92
93const wchar_t kUnitTestShowWindows[] = L"show-windows";
94
[email protected]ddf8a4b02010-03-22 23:08:3095// Passed as value of kTestType.
96static const char kBrowserTestType[] = "browser";
97
[email protected]ad834d2e2010-09-14 20:33:0198// Default delay for the time-out at which we stop the
99// inner-message loop the first time.
100const int kInitialTimeoutInMS = 30000;
101
102// Delay for sub-sequent time-outs once the initial time-out happened.
103const int kSubsequentTimeoutInMS = 5000;
104
[email protected]8bcdec92009-02-25 16:15:18105InProcessBrowserTest::InProcessBrowserTest()
106 : browser_(NULL),
[email protected]95409e12010-08-17 20:07:11107 test_server_(net::TestServer::TYPE_HTTP,
108 FilePath(FILE_PATH_LITERAL("chrome/test/data"))),
[email protected]8bcdec92009-02-25 16:15:18109 show_window_(false),
[email protected]56cdae32009-03-12 19:58:20110 dom_automation_enabled_(false),
[email protected]0b4d3382010-07-14 16:13:04111 tab_closeable_state_watcher_enabled_(false),
[email protected]ad834d2e2010-09-14 20:33:01112 original_single_process_(false),
113 initial_timeout_(kInitialTimeoutInMS) {
[email protected]d4515eb2009-01-30 00:40:43114}
115
[email protected]c4ff4952010-01-08 19:12:47116InProcessBrowserTest::~InProcessBrowserTest() {
117}
118
[email protected]d4515eb2009-01-30 00:40:43119void InProcessBrowserTest::SetUp() {
[email protected]470f7a52010-09-23 20:20:38120 // Remember the command line. Normally this doesn't matter, because the test
121 // harness creates a new process for each test, but when the test harness is
122 // running in single process mode, we can't let one test's command-line
123 // changes (e.g. enabling DOM automation) affect other tests.
124 // TODO(phajdan.jr): This save/restore logic is unnecessary. Remove it.
125 CommandLine* command_line = CommandLine::ForCurrentProcessMutable();
126 original_command_line_.reset(new CommandLine(*command_line));
[email protected]d4515eb2009-01-30 00:40:43127
[email protected]470f7a52010-09-23 20:20:38128 // Update the information about user data directory location before calling
129 // BrowserMain(). In some cases there will be no --user-data-dir switch (for
130 // example, when debugging). If there is no switch, do nothing.
131 FilePath user_data_dir =
132 command_line->GetSwitchValuePath(switches::kUserDataDir);
133 if (user_data_dir.empty()) {
134 // TODO(rohitrao): Create a ScopedTempDir here if people have problems.
135 LOG(ERROR) << "InProcessBrowserTest is using the default user data dir.";
136 } else {
137 ASSERT_TRUE(test_launcher_utils::OverrideUserDataDir(user_data_dir));
138 }
[email protected]4a44bc32010-05-28 22:22:44139
[email protected]d4515eb2009-01-30 00:40:43140 // The unit test suite creates a testingbrowser, but we want the real thing.
141 // Delete the current one. We'll install the testing one in TearDown.
142 delete g_browser_process;
[email protected]298883bc2010-04-30 14:50:58143 g_browser_process = NULL;
144
[email protected]470f7a52010-09-23 20:20:38145 // Allow subclasses the opportunity to make changes to the default user data
146 // dir before running any tests.
[email protected]298883bc2010-04-30 14:50:58147 SetUpUserDataDirectory();
[email protected]d4515eb2009-01-30 00:40:43148
149 // Don't delete the resources when BrowserMain returns. Many ui classes
150 // cache SkBitmaps in a static field so that if we delete the resource
151 // bundle we'll crash.
152 browser_shutdown::delete_resources_on_shutdown = false;
153
[email protected]470f7a52010-09-23 20:20:38154 // Allow subclasses the opportunity to make changes to the command line before
155 // running any tests.
[email protected]9665fa62009-04-13 22:15:29156 SetUpCommandLine(command_line);
157
[email protected]108c2a12009-06-05 22:18:09158#if defined(OS_WIN)
[email protected]d4515eb2009-01-30 00:40:43159 // Hide windows on show.
[email protected]8bcdec92009-02-25 16:15:18160 if (!command_line->HasSwitch(kUnitTestShowWindows) && !show_window_)
[email protected]d4515eb2009-01-30 00:40:43161 BrowserView::SetShowState(SW_HIDE);
[email protected]108c2a12009-06-05 22:18:09162#endif
[email protected]d4515eb2009-01-30 00:40:43163
[email protected]8bcdec92009-02-25 16:15:18164 if (dom_automation_enabled_)
165 command_line->AppendSwitch(switches::kDomAutomationController);
166
[email protected]4f08c83f2010-07-29 23:02:34167 command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir);
[email protected]d4515eb2009-01-30 00:40:43168
[email protected]ddf8a4b02010-03-22 23:08:30169 // This is a Browser test.
[email protected]05076ba22010-07-30 05:59:57170 command_line->AppendSwitchASCII(switches::kTestType, kBrowserTestType);
[email protected]ddf8a4b02010-03-22 23:08:30171
[email protected]8bcdec92009-02-25 16:15:18172 // Single-process mode is not set in BrowserMain so it needs to be processed
[email protected]298883bc2010-04-30 14:50:58173 // explicitly.
[email protected]56cdae32009-03-12 19:58:20174 original_single_process_ = RenderProcessHost::run_renderer_in_process();
[email protected]8bcdec92009-02-25 16:15:18175 if (command_line->HasSwitch(switches::kSingleProcess))
176 RenderProcessHost::set_run_renderer_in_process(true);
177
[email protected]87bf9742010-06-09 20:31:41178#if defined(OS_WIN)
179 // The Windows sandbox requires that the browser and child processes are the
180 // same binary. So we launch browser_process.exe which loads chrome.dll
[email protected]4f08c83f2010-07-29 23:02:34181 command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
182 command_line->GetProgram());
[email protected]87bf9742010-06-09 20:31:41183#else
184 // Explicitly set the path of the binary used for child processes, otherwise
185 // they'll try to use browser_tests which doesn't contain ChromeMain.
[email protected]6cea14d2009-09-10 18:19:18186 FilePath subprocess_path;
[email protected]7f74a4e2009-04-30 17:00:24187 PathService::Get(base::FILE_EXE, &subprocess_path);
[email protected]6cea14d2009-09-10 18:19:18188 subprocess_path = subprocess_path.DirName();
189 subprocess_path = subprocess_path.AppendASCII(WideToASCII(
190 chrome::kBrowserProcessExecutablePath));
[email protected]32369d762010-08-24 20:50:06191#if defined(OS_MACOSX)
192 // Recreate the real environment, run the helper within the app bundle.
193 subprocess_path = subprocess_path.DirName().DirName();
194 DCHECK_EQ(subprocess_path.BaseName().value(), "Contents");
195 subprocess_path =
196 subprocess_path.Append("Versions").Append(chrome::kChromeVersion);
197 subprocess_path =
198 subprocess_path.Append(chrome::kHelperProcessExecutablePath);
199#endif
[email protected]4f08c83f2010-07-29 23:02:34200 command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
201 subprocess_path);
[email protected]87bf9742010-06-09 20:31:41202#endif
[email protected]d4515eb2009-01-30 00:40:43203
[email protected]0b4d3382010-07-14 16:13:04204 // If ncecessary, disable TabCloseableStateWatcher.
205 if (!tab_closeable_state_watcher_enabled_)
206 command_line->AppendSwitch(switches::kDisableTabCloseableStateWatcher);
207
[email protected]8e930952010-09-30 07:51:26208 test_launcher_utils::PrepareBrowserCommandLineForTests(command_line);
209
[email protected]02dbca0b2010-09-17 07:44:10210#if defined(OS_CHROMEOS)
211 chromeos::CrosLibrary::Get()->GetTestApi()->SetUseStubImpl();
212#endif // defined(OS_CHROMEOS)
213
[email protected]d4515eb2009-01-30 00:40:43214 SandboxInitWrapper sandbox_wrapper;
[email protected]7c321082009-02-09 15:35:47215 MainFunctionParams params(*command_line, sandbox_wrapper, NULL);
[email protected]d4515eb2009-01-30 00:40:43216 params.ui_task =
217 NewRunnableMethod(this, &InProcessBrowserTest::RunTestOnMainThreadLoop);
[email protected]13324ed2009-04-03 05:14:19218
[email protected]c4ff4952010-01-08 19:12:47219 host_resolver_ = new net::RuleBasedHostResolverProc(
220 new IntranetRedirectHostResolverProc(NULL));
[email protected]c7ad50f2009-09-11 06:28:15221
222 // Something inside the browser does this lookup implicitly. Make it fail
223 // to avoid external dependency. It won't break the tests.
224 host_resolver_->AddSimulatedFailure("*.google.com");
225
226 // See http://en.wikipedia.org/wiki/Web_Proxy_Autodiscovery_Protocol
227 // We don't want the test code to use it.
228 host_resolver_->AddSimulatedFailure("wpad");
229
[email protected]b59ff372009-07-15 22:04:32230 net::ScopedDefaultHostResolverProc scoped_host_resolver_proc(
[email protected]c7ad50f2009-09-11 06:28:15231 host_resolver_.get());
[email protected]5c5de8c2009-09-23 17:11:26232
233 SetUpInProcessBrowserTestFixture();
[email protected]60a782e2010-02-24 22:41:35234
235 // Before we run the browser, we have to hack the path to the exe to match
236 // what it would be if Chrome was running, because it is used to fork renderer
237 // processes, on Linux at least (failure to do so will cause a browser_test to
238 // be run instead of a renderer).
239 FilePath chrome_path;
240 CHECK(PathService::Get(base::FILE_EXE, &chrome_path));
241 chrome_path = chrome_path.DirName();
242#if defined(OS_WIN)
243 chrome_path = chrome_path.Append(chrome::kBrowserProcessExecutablePath);
244#elif defined(OS_POSIX)
245 chrome_path = chrome_path.Append(
246 WideToASCII(chrome::kBrowserProcessExecutablePath));
247#endif
248 CHECK(PathService::Override(base::FILE_EXE, chrome_path));
249
250#if defined(OS_LINUX)
251 // Initialize the RenderSandbox and Zygote hosts. Apparently they get used
252 // for InProcessBrowserTest, and this is not the normal browser startup path.
253 Singleton<LinuxHostInit>::get();
254#endif
255
[email protected]d4515eb2009-01-30 00:40:43256 BrowserMain(params);
[email protected]5c5de8c2009-09-23 17:11:26257 TearDownInProcessBrowserTestFixture();
[email protected]d4515eb2009-01-30 00:40:43258}
259
260void InProcessBrowserTest::TearDown() {
261 // Reinstall testing browser process.
262 delete g_browser_process;
263 g_browser_process = new TestingBrowserProcess();
264
265 browser_shutdown::delete_resources_on_shutdown = true;
266
[email protected]eb1bd832010-05-18 20:39:58267#if defined(OS_WIN)
[email protected]d4515eb2009-01-30 00:40:43268 BrowserView::SetShowState(-1);
[email protected]108c2a12009-06-05 22:18:09269#endif
[email protected]56cdae32009-03-12 19:58:20270
271 *CommandLine::ForCurrentProcessMutable() = *original_command_line_;
272 RenderProcessHost::set_run_renderer_in_process(original_single_process_);
[email protected]d4515eb2009-01-30 00:40:43273}
274
[email protected]d4515eb2009-01-30 00:40:43275// Creates a browser with a single tab (about:blank), waits for the tab to
276// finish loading and shows the browser.
277Browser* InProcessBrowserTest::CreateBrowser(Profile* profile) {
278 Browser* browser = Browser::Create(profile);
[email protected]e1c10f182010-09-30 08:53:06279 InitializeBrowser(browser);
280 return browser;
281}
[email protected]d4515eb2009-01-30 00:40:43282
[email protected]e1c10f182010-09-30 08:53:06283Browser* InProcessBrowserTest::CreateBrowserForPopup(Profile* profile) {
284 Browser* browser = Browser::CreateForPopup(profile);
285 InitializeBrowser(browser);
[email protected]d4515eb2009-01-30 00:40:43286 return browser;
287}
288
[email protected]64f19312010-04-13 22:30:01289void InProcessBrowserTest::RunTestOnMainThreadLoop() {
[email protected]00d0ac22010-10-05 09:30:00290#if defined(OS_POSIX)
291 // Restore default signal handler for SIGTERM, so when the out-of-process
292 // test runner tries to terminate us, we don't catch it and possibly make it
293 // look like a success (http://crbug.com/57578).
294 signal(SIGTERM, SIG_DFL);
295#endif // defined(OS_POSIX)
296
[email protected]304a3172010-05-04 05:38:44297 // On Mac, without the following autorelease pool, code which is directly
298 // executed (as opposed to executed inside a message loop) would autorelease
299 // objects into a higher-level pool. This pool is not recycled in-sync with
300 // the message loops' pools and causes problems with code relying on
301 // deallocation via an autorelease pool (such as browser window closure and
302 // browser shutdown). To avoid this, the following pool is recycled after each
303 // time code is directly executed.
304 base::ScopedNSAutoreleasePool pool;
305
[email protected]64f19312010-04-13 22:30:01306 // Pump startup related events.
307 MessageLoopForUI::current()->RunAllPending();
308
309 // In the long term it would be great if we could use a TestingProfile
310 // here and only enable services you want tested, but that requires all
311 // consumers of Profile to handle NULL services.
312 Profile* profile = ProfileManager::GetDefaultProfile();
313 if (!profile) {
314 // We should only be able to get here if the profile already exists and
315 // has been created.
316 NOTREACHED();
317 return;
318 }
[email protected]304a3172010-05-04 05:38:44319 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01320
321 ChromeThread::PostTask(
322 ChromeThread::IO, FROM_HERE,
323 NewRunnableFunction(chrome_browser_net::SetUrlRequestMocksEnabled, true));
324
325 browser_ = CreateBrowser(profile);
[email protected]304a3172010-05-04 05:38:44326 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01327
[email protected]ad834d2e2010-09-14 20:33:01328 // Start the timeout timer to prevent hangs.
329 MessageLoopForUI::current()->PostDelayedTask(FROM_HERE,
330 NewRunnableMethod(this, &InProcessBrowserTest::TimedOut),
331 initial_timeout_);
332
[email protected]64f19312010-04-13 22:30:01333 // Pump any pending events that were created as a result of creating a
334 // browser.
335 MessageLoopForUI::current()->RunAllPending();
336
337 RunTestOnMainThread();
[email protected]304a3172010-05-04 05:38:44338 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01339
340 CleanUpOnMainThread();
[email protected]304a3172010-05-04 05:38:44341 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01342
343 QuitBrowsers();
[email protected]304a3172010-05-04 05:38:44344 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01345}
346
347void InProcessBrowserTest::QuitBrowsers() {
348 if (BrowserList::size() == 0)
349 return;
350
351 // Invoke CloseAllBrowsersAndExit on a running message loop.
352 // CloseAllBrowsersAndExit exits the message loop after everything has been
353 // shut down properly.
354 MessageLoopForUI::current()->PostTask(
355 FROM_HERE,
356 NewRunnableFunction(&BrowserList::CloseAllBrowsersAndExit));
357 ui_test_utils::RunMessageLoop();
358}
[email protected]ad834d2e2010-09-14 20:33:01359
360void InProcessBrowserTest::TimedOut() {
361 std::string error_message = "Test timed out. Each test runs for a max of ";
362 error_message += base::IntToString(initial_timeout_);
363 error_message += " ms (kInitialTimeoutInMS).";
364
365 MessageLoopForUI::current()->Quit();
366
367 // WARNING: This must be after Quit as it returns.
368 FAIL() << error_message;
369}
370
371void InProcessBrowserTest::SetInitialTimeoutInMS(int timeout_value) {
372 DCHECK_GT(timeout_value, 0);
373 initial_timeout_ = timeout_value;
374}