blob: 2e8006a1072fd647a835b450fe3df568512728ea [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]fb895c62009-10-09 18:20:3011#include "base/test/test_file_util.h"
[email protected]d4515eb2009-01-30 00:40:4312#include "chrome/browser/browser.h"
[email protected]b6e38ef2009-06-16 00:43:2313#include "chrome/browser/browser_list.h"
[email protected]d4515eb2009-01-30 00:40:4314#include "chrome/browser/browser_process.h"
15#include "chrome/browser/browser_shutdown.h"
[email protected]108c2a12009-06-05 22:18:0916#include "chrome/browser/browser_window.h"
[email protected]6fad2632009-11-02 05:59:3717#include "chrome/browser/chrome_thread.h"
[email protected]c4ff4952010-01-08 19:12:4718#include "chrome/browser/intranet_redirect_detector.h"
[email protected]0ac83682010-01-22 17:46:2719#include "chrome/browser/io_thread.h"
[email protected]cec4a272009-07-31 21:55:0320#include "chrome/browser/net/url_request_mock_util.h"
[email protected]d4515eb2009-01-30 00:40:4321#include "chrome/browser/profile.h"
22#include "chrome/browser/profile_manager.h"
[email protected]8bcdec92009-02-25 16:15:1823#include "chrome/browser/renderer_host/render_process_host.h"
[email protected]5c238752009-06-13 10:29:0724#include "chrome/browser/tab_contents/tab_contents.h"
[email protected]108c2a12009-06-05 22:18:0925#if defined(OS_WIN)
[email protected]d4515eb2009-01-30 00:40:4326#include "chrome/browser/views/frame/browser_view.h"
[email protected]108c2a12009-06-05 22:18:0927#endif
[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]d4515eb2009-01-30 00:40:4338#include "sandbox/src/dep.h"
39
[email protected]8ecd3aad2009-11-04 08:32:2240#if defined(OS_LINUX)
41#include "base/singleton.h"
42#include "chrome/browser/renderer_host/render_sandbox_host_linux.h"
43#include "chrome/browser/zygote_host_linux.h"
44
45namespace {
46
47// A helper class to do Linux-only initialization only once per process.
48class LinuxHostInit {
49 public:
50 LinuxHostInit() {
[email protected]576a4ca2009-11-05 01:41:0951 RenderSandboxHostLinux* shost = Singleton<RenderSandboxHostLinux>::get();
[email protected]8ecd3aad2009-11-04 08:32:2252 shost->Init("");
[email protected]576a4ca2009-11-05 01:41:0953 ZygoteHost* zhost = Singleton<ZygoteHost>::get();
[email protected]8ecd3aad2009-11-04 08:32:2254 zhost->Init("");
55 }
56 ~LinuxHostInit() {}
57};
58
59} // namespace
60#endif
61
[email protected]d4515eb2009-01-30 00:40:4362extern int BrowserMain(const MainFunctionParams&);
63
64const wchar_t kUnitTestShowWindows[] = L"show-windows";
65
[email protected]ddf8a4b02010-03-22 23:08:3066// Passed as value of kTestType.
67static const char kBrowserTestType[] = "browser";
68
[email protected]4ff446f2009-07-10 18:29:3969// Default delay for the time-out at which we stop the
70// inner-message loop the first time.
[email protected]b5f95102009-07-01 19:53:5971const int kInitialTimeoutInMS = 30000;
72
73// Delay for sub-sequent time-outs once the initial time-out happened.
74const int kSubsequentTimeoutInMS = 5000;
75
[email protected]8bcdec92009-02-25 16:15:1876InProcessBrowserTest::InProcessBrowserTest()
77 : browser_(NULL),
78 show_window_(false),
[email protected]56cdae32009-03-12 19:58:2079 dom_automation_enabled_(false),
80 single_process_(false),
[email protected]4ff446f2009-07-10 18:29:3981 original_single_process_(false),
82 initial_timeout_(kInitialTimeoutInMS) {
[email protected]d4515eb2009-01-30 00:40:4383}
84
[email protected]c4ff4952010-01-08 19:12:4785InProcessBrowserTest::~InProcessBrowserTest() {
86}
87
[email protected]d4515eb2009-01-30 00:40:4388void InProcessBrowserTest::SetUp() {
89 // Cleanup the user data dir.
[email protected]23cc9a12009-07-30 21:27:0190 FilePath user_data_dir;
[email protected]d4515eb2009-01-30 00:40:4391 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
[email protected]23cc9a12009-07-30 21:27:0192 ASSERT_LT(10, static_cast<int>(user_data_dir.value().size())) <<
[email protected]d4515eb2009-01-30 00:40:4393 "The user data directory name passed into this test was too "
94 "short to delete safely. Please check the user-data-dir "
95 "argument and try again.";
[email protected]20d241c332010-04-15 22:28:1896 if (ShouldDeleteProfile())
97 ASSERT_TRUE(file_util::DieFileDie(user_data_dir, true));
[email protected]d4515eb2009-01-30 00:40:4398
99 // The unit test suite creates a testingbrowser, but we want the real thing.
100 // Delete the current one. We'll install the testing one in TearDown.
101 delete g_browser_process;
102
103 // Don't delete the resources when BrowserMain returns. Many ui classes
104 // cache SkBitmaps in a static field so that if we delete the resource
105 // bundle we'll crash.
106 browser_shutdown::delete_resources_on_shutdown = false;
107
108 CommandLine* command_line = CommandLine::ForCurrentProcessMutable();
[email protected]56cdae32009-03-12 19:58:20109 original_command_line_.reset(new CommandLine(*command_line));
[email protected]d4515eb2009-01-30 00:40:43110
[email protected]9665fa62009-04-13 22:15:29111 SetUpCommandLine(command_line);
112
[email protected]108c2a12009-06-05 22:18:09113#if defined(OS_WIN)
[email protected]d4515eb2009-01-30 00:40:43114 // Hide windows on show.
[email protected]8bcdec92009-02-25 16:15:18115 if (!command_line->HasSwitch(kUnitTestShowWindows) && !show_window_)
[email protected]d4515eb2009-01-30 00:40:43116 BrowserView::SetShowState(SW_HIDE);
[email protected]108c2a12009-06-05 22:18:09117#endif
[email protected]d4515eb2009-01-30 00:40:43118
[email protected]8bcdec92009-02-25 16:15:18119 if (dom_automation_enabled_)
120 command_line->AppendSwitch(switches::kDomAutomationController);
121
[email protected]56cdae32009-03-12 19:58:20122 if (single_process_)
123 command_line->AppendSwitch(switches::kSingleProcess);
124
[email protected]cdbc1842009-08-26 02:56:58125 // Turn off tip loading for tests; see http://crbug.com/17725
126 command_line->AppendSwitch(switches::kDisableWebResources);
[email protected]0a519262009-07-13 18:14:08127
[email protected]23cc9a12009-07-30 21:27:01128 command_line->AppendSwitchWithValue(switches::kUserDataDir,
129 user_data_dir.ToWStringHack());
[email protected]d4515eb2009-01-30 00:40:43130
131 // For some reason the sandbox wasn't happy running in test mode. These
132 // tests aren't intended to test the sandbox, so we turn it off.
133 command_line->AppendSwitch(switches::kNoSandbox);
134
[email protected]e01aba812009-07-09 18:31:24135 // Don't show the first run ui.
136 command_line->AppendSwitch(switches::kNoFirstRun);
137
[email protected]ddf8a4b02010-03-22 23:08:30138 // This is a Browser test.
139 command_line->AppendSwitchWithValue(switches::kTestType,
140 ASCIIToWide(kBrowserTestType));
141
[email protected]8bcdec92009-02-25 16:15:18142 // Single-process mode is not set in BrowserMain so it needs to be processed
[email protected]20d241c332010-04-15 22:28:18143 // explicitlty.
[email protected]56cdae32009-03-12 19:58:20144 original_single_process_ = RenderProcessHost::run_renderer_in_process();
[email protected]8bcdec92009-02-25 16:15:18145 if (command_line->HasSwitch(switches::kSingleProcess))
146 RenderProcessHost::set_run_renderer_in_process(true);
147
[email protected]7f74a4e2009-04-30 17:00:24148 // Explicitly set the path of the exe used for the renderer and plugin,
149 // otherwise they'll try to use unit_test.exe.
[email protected]6cea14d2009-09-10 18:19:18150 FilePath subprocess_path;
[email protected]7f74a4e2009-04-30 17:00:24151 PathService::Get(base::FILE_EXE, &subprocess_path);
[email protected]6cea14d2009-09-10 18:19:18152 subprocess_path = subprocess_path.DirName();
153 subprocess_path = subprocess_path.AppendASCII(WideToASCII(
154 chrome::kBrowserProcessExecutablePath));
[email protected]7f74a4e2009-04-30 17:00:24155 command_line->AppendSwitchWithValue(switches::kBrowserSubprocessPath,
[email protected]6cea14d2009-09-10 18:19:18156 subprocess_path.ToWStringHack());
[email protected]d4515eb2009-01-30 00:40:43157
[email protected]9c73efa2009-07-08 00:18:36158 // Enable warning level logging so that we can see when bad stuff happens.
159 command_line->AppendSwitch(switches::kEnableLogging);
160 command_line->AppendSwitchWithValue(switches::kLoggingLevel,
161 IntToWString(1)); // warning
162
[email protected]d4515eb2009-01-30 00:40:43163 SandboxInitWrapper sandbox_wrapper;
[email protected]7c321082009-02-09 15:35:47164 MainFunctionParams params(*command_line, sandbox_wrapper, NULL);
[email protected]459773c22010-04-22 15:24:14165#if defined(OS_MACOSX)
[email protected]64f19312010-04-13 22:30:01166 params.ui_task =
167 NewRunnableMethod(this,
168 &InProcessBrowserTest::RunTestOnMainThreadLoopDeprecated);
169#else
[email protected]d4515eb2009-01-30 00:40:43170 params.ui_task =
171 NewRunnableMethod(this, &InProcessBrowserTest::RunTestOnMainThreadLoop);
[email protected]64f19312010-04-13 22:30:01172#endif
[email protected]13324ed2009-04-03 05:14:19173
[email protected]c4ff4952010-01-08 19:12:47174 host_resolver_ = new net::RuleBasedHostResolverProc(
175 new IntranetRedirectHostResolverProc(NULL));
[email protected]c7ad50f2009-09-11 06:28:15176
177 // Something inside the browser does this lookup implicitly. Make it fail
178 // to avoid external dependency. It won't break the tests.
179 host_resolver_->AddSimulatedFailure("*.google.com");
180
181 // See http://en.wikipedia.org/wiki/Web_Proxy_Autodiscovery_Protocol
182 // We don't want the test code to use it.
183 host_resolver_->AddSimulatedFailure("wpad");
184
[email protected]b59ff372009-07-15 22:04:32185 net::ScopedDefaultHostResolverProc scoped_host_resolver_proc(
[email protected]c7ad50f2009-09-11 06:28:15186 host_resolver_.get());
[email protected]5c5de8c2009-09-23 17:11:26187
188 SetUpInProcessBrowserTestFixture();
[email protected]60a782e2010-02-24 22:41:35189
190 // Before we run the browser, we have to hack the path to the exe to match
191 // what it would be if Chrome was running, because it is used to fork renderer
192 // processes, on Linux at least (failure to do so will cause a browser_test to
193 // be run instead of a renderer).
194 FilePath chrome_path;
195 CHECK(PathService::Get(base::FILE_EXE, &chrome_path));
196 chrome_path = chrome_path.DirName();
197#if defined(OS_WIN)
198 chrome_path = chrome_path.Append(chrome::kBrowserProcessExecutablePath);
199#elif defined(OS_POSIX)
200 chrome_path = chrome_path.Append(
201 WideToASCII(chrome::kBrowserProcessExecutablePath));
202#endif
203 CHECK(PathService::Override(base::FILE_EXE, chrome_path));
204
205#if defined(OS_LINUX)
206 // Initialize the RenderSandbox and Zygote hosts. Apparently they get used
207 // for InProcessBrowserTest, and this is not the normal browser startup path.
208 Singleton<LinuxHostInit>::get();
209#endif
210
[email protected]d4515eb2009-01-30 00:40:43211 BrowserMain(params);
[email protected]5c5de8c2009-09-23 17:11:26212 TearDownInProcessBrowserTestFixture();
[email protected]d4515eb2009-01-30 00:40:43213}
214
215void InProcessBrowserTest::TearDown() {
216 // Reinstall testing browser process.
217 delete g_browser_process;
218 g_browser_process = new TestingBrowserProcess();
219
220 browser_shutdown::delete_resources_on_shutdown = true;
221
[email protected]108c2a12009-06-05 22:18:09222#if defined(WIN)
[email protected]d4515eb2009-01-30 00:40:43223 BrowserView::SetShowState(-1);
[email protected]108c2a12009-06-05 22:18:09224#endif
[email protected]56cdae32009-03-12 19:58:20225
226 *CommandLine::ForCurrentProcessMutable() = *original_command_line_;
227 RenderProcessHost::set_run_renderer_in_process(original_single_process_);
[email protected]d4515eb2009-01-30 00:40:43228}
229
[email protected]d4515eb2009-01-30 00:40:43230HTTPTestServer* InProcessBrowserTest::StartHTTPServer() {
231 // The HTTPServer must run on the IO thread.
232 DCHECK(!http_server_.get());
233 http_server_ = HTTPTestServer::CreateServer(
234 L"chrome/test/data",
235 g_browser_process->io_thread()->message_loop());
236 return http_server_.get();
237}
238
239// Creates a browser with a single tab (about:blank), waits for the tab to
240// finish loading and shows the browser.
241Browser* InProcessBrowserTest::CreateBrowser(Profile* profile) {
242 Browser* browser = Browser::Create(profile);
243
[email protected]e0d481582009-09-15 21:06:25244 browser->AddTabWithURL(GURL(chrome::kAboutBlankURL), GURL(),
245 PageTransition::START_PAGE, true, -1, false, NULL);
[email protected]f0a51fb52009-03-05 12:46:38246
[email protected]d4515eb2009-01-30 00:40:43247 // Wait for the page to finish loading.
248 ui_test_utils::WaitForNavigation(
[email protected]ce3fa3c2009-04-20 19:55:57249 &browser->GetSelectedTabContents()->controller());
[email protected]d4515eb2009-01-30 00:40:43250
251 browser->window()->Show();
252
253 return browser;
254}
255
[email protected]459773c22010-04-22 15:24:14256#if defined(OS_MACOSX)
[email protected]64f19312010-04-13 22:30:01257void InProcessBrowserTest::RunTestOnMainThreadLoopDeprecated() {
[email protected]d4515eb2009-01-30 00:40:43258 // In the long term it would be great if we could use a TestingProfile
259 // here and only enable services you want tested, but that requires all
260 // consumers of Profile to handle NULL services.
[email protected]ddf8a4b02010-03-22 23:08:30261 Profile* profile = ProfileManager::GetDefaultProfile();
[email protected]d4515eb2009-01-30 00:40:43262 if (!profile) {
263 // We should only be able to get here if the profile already exists and
264 // has been created.
265 NOTREACHED();
266 MessageLoopForUI::current()->Quit();
267 return;
268 }
269
[email protected]6fad2632009-11-02 05:59:37270 ChromeThread::PostTask(
271 ChromeThread::IO, FROM_HERE,
[email protected]cec4a272009-07-31 21:55:03272 NewRunnableFunction(chrome_browser_net::SetUrlRequestMocksEnabled, true));
273
[email protected]d4515eb2009-01-30 00:40:43274 browser_ = CreateBrowser(profile);
275
[email protected]b5f95102009-07-01 19:53:59276 // Start the timeout timer to prevent hangs.
277 MessageLoopForUI::current()->PostDelayedTask(FROM_HERE,
278 NewRunnableMethod(this, &InProcessBrowserTest::TimedOut),
[email protected]4ff446f2009-07-10 18:29:39279 initial_timeout_);
[email protected]b5f95102009-07-01 19:53:59280
[email protected]20d241c332010-04-15 22:28:18281 RunTestOnMainThread();
[email protected]17c4f3c2009-07-04 16:36:25282 CleanUpOnMainThread();
[email protected]d4515eb2009-01-30 00:40:43283
[email protected]cc661e52009-07-27 19:18:41284 // Close all browser windows. This might not happen immediately, since some
285 // may need to wait for beforeunload and unload handlers to fire in a tab.
[email protected]235e78fa2010-03-30 16:20:14286 // When all windows are closed, the last window will call Quit(). Call
287 // Quit() explicitly if no windows are open.
[email protected]a0e790502010-04-08 22:10:01288#if defined(OS_MACOSX)
[email protected]0e28ef02009-11-23 17:46:53289 // When the browser window closes, Cocoa will generate an inner-loop that
290 // processes the RenderProcessHost delete task, so allow task nesting.
291 bool old_state = MessageLoopForUI::current()->NestableTasksAllowed();
292 MessageLoopForUI::current()->SetNestableTasksAllowed(true);
[email protected]a0e790502010-04-08 22:10:01293#endif
[email protected]e6152c22009-06-23 23:33:27294 BrowserList::const_iterator browser = BrowserList::begin();
[email protected]235e78fa2010-03-30 16:20:14295 if (browser == BrowserList::end()) {
296 MessageLoopForUI::current()->Quit();
297 } else {
298 for (; browser != BrowserList::end(); ++browser)
299 (*browser)->CloseWindow();
300 }
[email protected]a0e790502010-04-08 22:10:01301#if defined(OS_MACOSX)
[email protected]0e28ef02009-11-23 17:46:53302 MessageLoopForUI::current()->SetNestableTasksAllowed(old_state);
[email protected]a0e790502010-04-08 22:10:01303#endif
[email protected]5c00ca82010-04-08 21:30:42304
305 // Stop the HTTP server.
306 http_server_ = NULL;
307}
[email protected]459773c22010-04-22 15:24:14308#endif // defined(OS_MACOSX)
[email protected]64f19312010-04-13 22:30:01309
310void InProcessBrowserTest::RunTestOnMainThreadLoop() {
311 // Pump startup related events.
312 MessageLoopForUI::current()->RunAllPending();
313
314 // In the long term it would be great if we could use a TestingProfile
315 // here and only enable services you want tested, but that requires all
316 // consumers of Profile to handle NULL services.
317 Profile* profile = ProfileManager::GetDefaultProfile();
318 if (!profile) {
319 // We should only be able to get here if the profile already exists and
320 // has been created.
321 NOTREACHED();
322 return;
323 }
324
325 ChromeThread::PostTask(
326 ChromeThread::IO, FROM_HERE,
327 NewRunnableFunction(chrome_browser_net::SetUrlRequestMocksEnabled, true));
328
329 browser_ = CreateBrowser(profile);
330
331 // Start the timeout timer to prevent hangs.
332 MessageLoopForUI::current()->PostDelayedTask(FROM_HERE,
333 NewRunnableMethod(this, &InProcessBrowserTest::TimedOut),
334 initial_timeout_);
335
336 // Pump any pending events that were created as a result of creating a
337 // browser.
338 MessageLoopForUI::current()->RunAllPending();
339
340 RunTestOnMainThread();
341
342 CleanUpOnMainThread();
343
344 QuitBrowsers();
345
346 // Stop the HTTP server.
347 http_server_ = NULL;
348}
349
350void InProcessBrowserTest::QuitBrowsers() {
351 if (BrowserList::size() == 0)
352 return;
353
354 // Invoke CloseAllBrowsersAndExit on a running message loop.
355 // CloseAllBrowsersAndExit exits the message loop after everything has been
356 // shut down properly.
357 MessageLoopForUI::current()->PostTask(
358 FROM_HERE,
359 NewRunnableFunction(&BrowserList::CloseAllBrowsersAndExit));
360 ui_test_utils::RunMessageLoop();
361}
[email protected]b5f95102009-07-01 19:53:59362
[email protected]5c00ca82010-04-08 21:30:42363void InProcessBrowserTest::TimedOut() {
[email protected]94ab2ad2009-10-15 18:18:51364 std::string error_message = "Test timed out. Each test runs for a max of ";
365 error_message += IntToString(kInitialTimeoutInMS);
366 error_message += " ms (kInitialTimeoutInMS).";
367
368 GTEST_NONFATAL_FAILURE_(error_message.c_str());
[email protected]b5f95102009-07-01 19:53:59369
[email protected]b5f95102009-07-01 19:53:59370 MessageLoopForUI::current()->Quit();
371}
[email protected]4ff446f2009-07-10 18:29:39372
373void InProcessBrowserTest::SetInitialTimeoutInMS(int timeout_value) {
374 DCHECK_GT(timeout_value, 0);
375 initial_timeout_ = timeout_value;
376}