blob: 57d43fde025d1d32272b1da306e2c1a28fa82d96 [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]528c56d2010-07-30 19:28:4412#include "base/string_number_conversions.h"
[email protected]fb895c62009-10-09 18:20:3013#include "base/test/test_file_util.h"
[email protected]d4515eb2009-01-30 00:40:4314#include "chrome/browser/browser.h"
[email protected]b6e38ef2009-06-16 00:43:2315#include "chrome/browser/browser_list.h"
[email protected]d4515eb2009-01-30 00:40:4316#include "chrome/browser/browser_process.h"
17#include "chrome/browser/browser_shutdown.h"
[email protected]108c2a12009-06-05 22:18:0918#include "chrome/browser/browser_window.h"
[email protected]6fad2632009-11-02 05:59:3719#include "chrome/browser/chrome_thread.h"
[email protected]c4ff4952010-01-08 19:12:4720#include "chrome/browser/intranet_redirect_detector.h"
[email protected]0ac83682010-01-22 17:46:2721#include "chrome/browser/io_thread.h"
[email protected]cec4a272009-07-31 21:55:0322#include "chrome/browser/net/url_request_mock_util.h"
[email protected]d4515eb2009-01-30 00:40:4323#include "chrome/browser/profile.h"
24#include "chrome/browser/profile_manager.h"
[email protected]8bcdec92009-02-25 16:15:1825#include "chrome/browser/renderer_host/render_process_host.h"
[email protected]5c238752009-06-13 10:29:0726#include "chrome/browser/tab_contents/tab_contents.h"
[email protected]c848d3d92010-09-16 21:57:4527#include "chrome/browser/tabs/tab_strip_model.h"
[email protected]d4515eb2009-01-30 00:40:4328#include "chrome/common/chrome_constants.h"
29#include "chrome/common/chrome_paths.h"
30#include "chrome/common/chrome_switches.h"
31#include "chrome/common/main_function_params.h"
[email protected]ad1f9bd2009-07-30 20:23:1532#include "chrome/common/notification_registrar.h"
33#include "chrome/common/notification_type.h"
[email protected]e0d481582009-09-15 21:06:2534#include "chrome/common/url_constants.h"
[email protected]d4515eb2009-01-30 00:40:4335#include "chrome/test/testing_browser_process.h"
36#include "chrome/test/ui_test_utils.h"
[email protected]c4ff4952010-01-08 19:12:4737#include "net/base/mock_host_resolver.h"
[email protected]3985ba82010-07-29 21:44:1238#include "net/test/test_server.h"
[email protected]d4515eb2009-01-30 00:40:4339#include "sandbox/src/dep.h"
40
[email protected]c848d3d92010-09-16 21:57:4541#if defined(OS_WIN)
42#include "chrome/browser/views/frame/browser_view.h"
43#endif
44
[email protected]8ecd3aad2009-11-04 08:32:2245#if defined(OS_LINUX)
46#include "base/singleton.h"
47#include "chrome/browser/renderer_host/render_sandbox_host_linux.h"
48#include "chrome/browser/zygote_host_linux.h"
49
50namespace {
51
52// A helper class to do Linux-only initialization only once per process.
53class LinuxHostInit {
54 public:
55 LinuxHostInit() {
[email protected]576a4ca2009-11-05 01:41:0956 RenderSandboxHostLinux* shost = Singleton<RenderSandboxHostLinux>::get();
[email protected]8ecd3aad2009-11-04 08:32:2257 shost->Init("");
[email protected]576a4ca2009-11-05 01:41:0958 ZygoteHost* zhost = Singleton<ZygoteHost>::get();
[email protected]8ecd3aad2009-11-04 08:32:2259 zhost->Init("");
60 }
61 ~LinuxHostInit() {}
62};
63
64} // namespace
65#endif
66
[email protected]02dbca0b2010-09-17 07:44:1067#if defined(OS_CHROMEOS)
68#include "chrome/browser/chromeos/cros/cros_library.h"
69#endif // defined(OS_CHROMEOS)
70
[email protected]d4515eb2009-01-30 00:40:4371extern int BrowserMain(const MainFunctionParams&);
72
73const wchar_t kUnitTestShowWindows[] = L"show-windows";
74
[email protected]ddf8a4b02010-03-22 23:08:3075// Passed as value of kTestType.
76static const char kBrowserTestType[] = "browser";
77
[email protected]ad834d2e2010-09-14 20:33:0178// Default delay for the time-out at which we stop the
79// inner-message loop the first time.
80const int kInitialTimeoutInMS = 30000;
81
82// Delay for sub-sequent time-outs once the initial time-out happened.
83const int kSubsequentTimeoutInMS = 5000;
84
[email protected]8bcdec92009-02-25 16:15:1885InProcessBrowserTest::InProcessBrowserTest()
86 : browser_(NULL),
[email protected]95409e12010-08-17 20:07:1187 test_server_(net::TestServer::TYPE_HTTP,
88 FilePath(FILE_PATH_LITERAL("chrome/test/data"))),
[email protected]8bcdec92009-02-25 16:15:1889 show_window_(false),
[email protected]56cdae32009-03-12 19:58:2090 dom_automation_enabled_(false),
[email protected]0b4d3382010-07-14 16:13:0491 tab_closeable_state_watcher_enabled_(false),
[email protected]ad834d2e2010-09-14 20:33:0192 original_single_process_(false),
93 initial_timeout_(kInitialTimeoutInMS) {
[email protected]d4515eb2009-01-30 00:40:4394}
95
[email protected]c4ff4952010-01-08 19:12:4796InProcessBrowserTest::~InProcessBrowserTest() {
97}
98
[email protected]d4515eb2009-01-30 00:40:4399void InProcessBrowserTest::SetUp() {
100 // Cleanup the user data dir.
[email protected]23cc9a12009-07-30 21:27:01101 FilePath user_data_dir;
[email protected]d4515eb2009-01-30 00:40:43102 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
[email protected]23cc9a12009-07-30 21:27:01103 ASSERT_LT(10, static_cast<int>(user_data_dir.value().size())) <<
[email protected]d4515eb2009-01-30 00:40:43104 "The user data directory name passed into this test was too "
105 "short to delete safely. Please check the user-data-dir "
106 "argument and try again.";
[email protected]298883bc2010-04-30 14:50:58107 ASSERT_TRUE(file_util::DieFileDie(user_data_dir, true));
[email protected]d4515eb2009-01-30 00:40:43108
[email protected]4a44bc32010-05-28 22:22:44109 // Recreate the user data dir. (PathService::Get guarantees that the directory
110 // exists if it returns true, but it only actually checks on the first call,
111 // the rest are cached. Thus we need to recreate it ourselves to not break
112 // the PathService guarantee.)
113 ASSERT_TRUE(file_util::CreateDirectory(user_data_dir));
114
[email protected]d4515eb2009-01-30 00:40:43115 // The unit test suite creates a testingbrowser, but we want the real thing.
116 // Delete the current one. We'll install the testing one in TearDown.
117 delete g_browser_process;
[email protected]298883bc2010-04-30 14:50:58118 g_browser_process = NULL;
119
120 SetUpUserDataDirectory();
[email protected]d4515eb2009-01-30 00:40:43121
122 // Don't delete the resources when BrowserMain returns. Many ui classes
123 // cache SkBitmaps in a static field so that if we delete the resource
124 // bundle we'll crash.
125 browser_shutdown::delete_resources_on_shutdown = false;
126
[email protected]986088a62010-05-13 18:59:20127 // Remember the command line. Normally this doesn't matter, because the test
128 // harness creates a new process for each test, but when the test harness is
129 // running in single process mode, we can't let one test's command-line
130 // changes (e.g. enabling DOM automation) affect other tests.
[email protected]d4515eb2009-01-30 00:40:43131 CommandLine* command_line = CommandLine::ForCurrentProcessMutable();
[email protected]56cdae32009-03-12 19:58:20132 original_command_line_.reset(new CommandLine(*command_line));
[email protected]d4515eb2009-01-30 00:40:43133
[email protected]9665fa62009-04-13 22:15:29134 SetUpCommandLine(command_line);
135
[email protected]108c2a12009-06-05 22:18:09136#if defined(OS_WIN)
[email protected]d4515eb2009-01-30 00:40:43137 // Hide windows on show.
[email protected]8bcdec92009-02-25 16:15:18138 if (!command_line->HasSwitch(kUnitTestShowWindows) && !show_window_)
[email protected]d4515eb2009-01-30 00:40:43139 BrowserView::SetShowState(SW_HIDE);
[email protected]108c2a12009-06-05 22:18:09140#endif
[email protected]d4515eb2009-01-30 00:40:43141
[email protected]8bcdec92009-02-25 16:15:18142 if (dom_automation_enabled_)
143 command_line->AppendSwitch(switches::kDomAutomationController);
144
[email protected]cdbc1842009-08-26 02:56:58145 // Turn off tip loading for tests; see http://crbug.com/17725
146 command_line->AppendSwitch(switches::kDisableWebResources);
[email protected]0a519262009-07-13 18:14:08147
[email protected]bfe0d722010-09-05 08:34:22148 // Turn off preconnects because they break the brittle python webserver.
149 command_line->AppendSwitch(switches::kDisablePreconnect);
150
[email protected]4f08c83f2010-07-29 23:02:34151 command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir);
[email protected]d4515eb2009-01-30 00:40:43152
[email protected]e01aba812009-07-09 18:31:24153 // Don't show the first run ui.
154 command_line->AppendSwitch(switches::kNoFirstRun);
155
[email protected]ddf8a4b02010-03-22 23:08:30156 // This is a Browser test.
[email protected]05076ba22010-07-30 05:59:57157 command_line->AppendSwitchASCII(switches::kTestType, kBrowserTestType);
[email protected]ddf8a4b02010-03-22 23:08:30158
[email protected]8bcdec92009-02-25 16:15:18159 // Single-process mode is not set in BrowserMain so it needs to be processed
[email protected]298883bc2010-04-30 14:50:58160 // explicitly.
[email protected]56cdae32009-03-12 19:58:20161 original_single_process_ = RenderProcessHost::run_renderer_in_process();
[email protected]8bcdec92009-02-25 16:15:18162 if (command_line->HasSwitch(switches::kSingleProcess))
163 RenderProcessHost::set_run_renderer_in_process(true);
164
[email protected]87bf9742010-06-09 20:31:41165#if defined(OS_WIN)
166 // The Windows sandbox requires that the browser and child processes are the
167 // same binary. So we launch browser_process.exe which loads chrome.dll
[email protected]4f08c83f2010-07-29 23:02:34168 command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
169 command_line->GetProgram());
[email protected]87bf9742010-06-09 20:31:41170#else
171 // Explicitly set the path of the binary used for child processes, otherwise
172 // they'll try to use browser_tests which doesn't contain ChromeMain.
[email protected]6cea14d2009-09-10 18:19:18173 FilePath subprocess_path;
[email protected]7f74a4e2009-04-30 17:00:24174 PathService::Get(base::FILE_EXE, &subprocess_path);
[email protected]6cea14d2009-09-10 18:19:18175 subprocess_path = subprocess_path.DirName();
176 subprocess_path = subprocess_path.AppendASCII(WideToASCII(
177 chrome::kBrowserProcessExecutablePath));
[email protected]32369d762010-08-24 20:50:06178#if defined(OS_MACOSX)
179 // Recreate the real environment, run the helper within the app bundle.
180 subprocess_path = subprocess_path.DirName().DirName();
181 DCHECK_EQ(subprocess_path.BaseName().value(), "Contents");
182 subprocess_path =
183 subprocess_path.Append("Versions").Append(chrome::kChromeVersion);
184 subprocess_path =
185 subprocess_path.Append(chrome::kHelperProcessExecutablePath);
186#endif
[email protected]4f08c83f2010-07-29 23:02:34187 command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
188 subprocess_path);
[email protected]87bf9742010-06-09 20:31:41189#endif
[email protected]d4515eb2009-01-30 00:40:43190
[email protected]9c73efa2009-07-08 00:18:36191 // Enable warning level logging so that we can see when bad stuff happens.
192 command_line->AppendSwitch(switches::kEnableLogging);
[email protected]0c605fe32010-07-30 06:00:38193 command_line->AppendSwitchASCII(switches::kLoggingLevel, "1"); // warning
[email protected]9c73efa2009-07-08 00:18:36194
[email protected]0b4d3382010-07-14 16:13:04195 // If ncecessary, disable TabCloseableStateWatcher.
196 if (!tab_closeable_state_watcher_enabled_)
197 command_line->AppendSwitch(switches::kDisableTabCloseableStateWatcher);
198
[email protected]02dbca0b2010-09-17 07:44:10199#if defined(OS_CHROMEOS)
200 chromeos::CrosLibrary::Get()->GetTestApi()->SetUseStubImpl();
201#endif // defined(OS_CHROMEOS)
202
[email protected]d4515eb2009-01-30 00:40:43203 SandboxInitWrapper sandbox_wrapper;
[email protected]7c321082009-02-09 15:35:47204 MainFunctionParams params(*command_line, sandbox_wrapper, NULL);
[email protected]d4515eb2009-01-30 00:40:43205 params.ui_task =
206 NewRunnableMethod(this, &InProcessBrowserTest::RunTestOnMainThreadLoop);
[email protected]13324ed2009-04-03 05:14:19207
[email protected]c4ff4952010-01-08 19:12:47208 host_resolver_ = new net::RuleBasedHostResolverProc(
209 new IntranetRedirectHostResolverProc(NULL));
[email protected]c7ad50f2009-09-11 06:28:15210
211 // Something inside the browser does this lookup implicitly. Make it fail
212 // to avoid external dependency. It won't break the tests.
213 host_resolver_->AddSimulatedFailure("*.google.com");
214
215 // See http://en.wikipedia.org/wiki/Web_Proxy_Autodiscovery_Protocol
216 // We don't want the test code to use it.
217 host_resolver_->AddSimulatedFailure("wpad");
218
[email protected]b59ff372009-07-15 22:04:32219 net::ScopedDefaultHostResolverProc scoped_host_resolver_proc(
[email protected]c7ad50f2009-09-11 06:28:15220 host_resolver_.get());
[email protected]5c5de8c2009-09-23 17:11:26221
222 SetUpInProcessBrowserTestFixture();
[email protected]60a782e2010-02-24 22:41:35223
224 // Before we run the browser, we have to hack the path to the exe to match
225 // what it would be if Chrome was running, because it is used to fork renderer
226 // processes, on Linux at least (failure to do so will cause a browser_test to
227 // be run instead of a renderer).
228 FilePath chrome_path;
229 CHECK(PathService::Get(base::FILE_EXE, &chrome_path));
230 chrome_path = chrome_path.DirName();
231#if defined(OS_WIN)
232 chrome_path = chrome_path.Append(chrome::kBrowserProcessExecutablePath);
233#elif defined(OS_POSIX)
234 chrome_path = chrome_path.Append(
235 WideToASCII(chrome::kBrowserProcessExecutablePath));
236#endif
237 CHECK(PathService::Override(base::FILE_EXE, chrome_path));
238
239#if defined(OS_LINUX)
240 // Initialize the RenderSandbox and Zygote hosts. Apparently they get used
241 // for InProcessBrowserTest, and this is not the normal browser startup path.
242 Singleton<LinuxHostInit>::get();
243#endif
244
[email protected]d4515eb2009-01-30 00:40:43245 BrowserMain(params);
[email protected]5c5de8c2009-09-23 17:11:26246 TearDownInProcessBrowserTestFixture();
[email protected]d4515eb2009-01-30 00:40:43247}
248
249void InProcessBrowserTest::TearDown() {
250 // Reinstall testing browser process.
251 delete g_browser_process;
252 g_browser_process = new TestingBrowserProcess();
253
254 browser_shutdown::delete_resources_on_shutdown = true;
255
[email protected]eb1bd832010-05-18 20:39:58256#if defined(OS_WIN)
[email protected]d4515eb2009-01-30 00:40:43257 BrowserView::SetShowState(-1);
[email protected]108c2a12009-06-05 22:18:09258#endif
[email protected]56cdae32009-03-12 19:58:20259
260 *CommandLine::ForCurrentProcessMutable() = *original_command_line_;
261 RenderProcessHost::set_run_renderer_in_process(original_single_process_);
[email protected]d4515eb2009-01-30 00:40:43262}
263
[email protected]d4515eb2009-01-30 00:40:43264// Creates a browser with a single tab (about:blank), waits for the tab to
265// finish loading and shows the browser.
266Browser* InProcessBrowserTest::CreateBrowser(Profile* profile) {
267 Browser* browser = Browser::Create(profile);
268
[email protected]e0d481582009-09-15 21:06:25269 browser->AddTabWithURL(GURL(chrome::kAboutBlankURL), GURL(),
[email protected]715af7e2010-04-29 01:55:38270 PageTransition::START_PAGE, -1,
[email protected]b283a7532010-08-12 21:24:59271 TabStripModel::ADD_SELECTED, NULL, std::string(),
272 &browser);
[email protected]f0a51fb52009-03-05 12:46:38273
[email protected]d4515eb2009-01-30 00:40:43274 // Wait for the page to finish loading.
275 ui_test_utils::WaitForNavigation(
[email protected]ce3fa3c2009-04-20 19:55:57276 &browser->GetSelectedTabContents()->controller());
[email protected]d4515eb2009-01-30 00:40:43277
278 browser->window()->Show();
279
280 return browser;
281}
282
[email protected]64f19312010-04-13 22:30:01283void InProcessBrowserTest::RunTestOnMainThreadLoop() {
[email protected]304a3172010-05-04 05:38:44284 // On Mac, without the following autorelease pool, code which is directly
285 // executed (as opposed to executed inside a message loop) would autorelease
286 // objects into a higher-level pool. This pool is not recycled in-sync with
287 // the message loops' pools and causes problems with code relying on
288 // deallocation via an autorelease pool (such as browser window closure and
289 // browser shutdown). To avoid this, the following pool is recycled after each
290 // time code is directly executed.
291 base::ScopedNSAutoreleasePool pool;
292
[email protected]64f19312010-04-13 22:30:01293 // Pump startup related events.
294 MessageLoopForUI::current()->RunAllPending();
295
296 // In the long term it would be great if we could use a TestingProfile
297 // here and only enable services you want tested, but that requires all
298 // consumers of Profile to handle NULL services.
299 Profile* profile = ProfileManager::GetDefaultProfile();
300 if (!profile) {
301 // We should only be able to get here if the profile already exists and
302 // has been created.
303 NOTREACHED();
304 return;
305 }
[email protected]304a3172010-05-04 05:38:44306 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01307
308 ChromeThread::PostTask(
309 ChromeThread::IO, FROM_HERE,
310 NewRunnableFunction(chrome_browser_net::SetUrlRequestMocksEnabled, true));
311
312 browser_ = CreateBrowser(profile);
[email protected]304a3172010-05-04 05:38:44313 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01314
[email protected]ad834d2e2010-09-14 20:33:01315 // Start the timeout timer to prevent hangs.
316 MessageLoopForUI::current()->PostDelayedTask(FROM_HERE,
317 NewRunnableMethod(this, &InProcessBrowserTest::TimedOut),
318 initial_timeout_);
319
[email protected]64f19312010-04-13 22:30:01320 // Pump any pending events that were created as a result of creating a
321 // browser.
322 MessageLoopForUI::current()->RunAllPending();
323
324 RunTestOnMainThread();
[email protected]304a3172010-05-04 05:38:44325 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01326
327 CleanUpOnMainThread();
[email protected]304a3172010-05-04 05:38:44328 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01329
330 QuitBrowsers();
[email protected]304a3172010-05-04 05:38:44331 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01332}
333
334void InProcessBrowserTest::QuitBrowsers() {
335 if (BrowserList::size() == 0)
336 return;
337
338 // Invoke CloseAllBrowsersAndExit on a running message loop.
339 // CloseAllBrowsersAndExit exits the message loop after everything has been
340 // shut down properly.
341 MessageLoopForUI::current()->PostTask(
342 FROM_HERE,
343 NewRunnableFunction(&BrowserList::CloseAllBrowsersAndExit));
344 ui_test_utils::RunMessageLoop();
345}
[email protected]ad834d2e2010-09-14 20:33:01346
347void InProcessBrowserTest::TimedOut() {
348 std::string error_message = "Test timed out. Each test runs for a max of ";
349 error_message += base::IntToString(initial_timeout_);
350 error_message += " ms (kInitialTimeoutInMS).";
351
352 MessageLoopForUI::current()->Quit();
353
354 // WARNING: This must be after Quit as it returns.
355 FAIL() << error_message;
356}
357
358void InProcessBrowserTest::SetInitialTimeoutInMS(int timeout_value) {
359 DCHECK_GT(timeout_value, 0);
360 initial_timeout_ = timeout_value;
361}