blob: 3be8b01ca32f922fc8bf9784d216d1864c8a6ade [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]fb895c62009-10-09 18:20:3012#include "base/test/test_file_util.h"
[email protected]d4515eb2009-01-30 00:40:4313#include "chrome/browser/browser.h"
[email protected]b6e38ef2009-06-16 00:43:2314#include "chrome/browser/browser_list.h"
[email protected]d4515eb2009-01-30 00:40:4315#include "chrome/browser/browser_process.h"
16#include "chrome/browser/browser_shutdown.h"
[email protected]108c2a12009-06-05 22:18:0917#include "chrome/browser/browser_window.h"
[email protected]6fad2632009-11-02 05:59:3718#include "chrome/browser/chrome_thread.h"
[email protected]c4ff4952010-01-08 19:12:4719#include "chrome/browser/intranet_redirect_detector.h"
[email protected]0ac83682010-01-22 17:46:2720#include "chrome/browser/io_thread.h"
[email protected]cec4a272009-07-31 21:55:0321#include "chrome/browser/net/url_request_mock_util.h"
[email protected]d4515eb2009-01-30 00:40:4322#include "chrome/browser/profile.h"
23#include "chrome/browser/profile_manager.h"
[email protected]8bcdec92009-02-25 16:15:1824#include "chrome/browser/renderer_host/render_process_host.h"
[email protected]5c238752009-06-13 10:29:0725#include "chrome/browser/tab_contents/tab_contents.h"
[email protected]108c2a12009-06-05 22:18:0926#if defined(OS_WIN)
[email protected]d4515eb2009-01-30 00:40:4327#include "chrome/browser/views/frame/browser_view.h"
[email protected]108c2a12009-06-05 22:18:0928#endif
[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]d4515eb2009-01-30 00:40:4336#include "chrome/test/testing_browser_process.h"
37#include "chrome/test/ui_test_utils.h"
[email protected]c4ff4952010-01-08 19:12:4738#include "net/base/mock_host_resolver.h"
[email protected]d4515eb2009-01-30 00:40:4339#include "sandbox/src/dep.h"
40
[email protected]8ecd3aad2009-11-04 08:32:2241#if defined(OS_LINUX)
42#include "base/singleton.h"
43#include "chrome/browser/renderer_host/render_sandbox_host_linux.h"
44#include "chrome/browser/zygote_host_linux.h"
45
46namespace {
47
48// A helper class to do Linux-only initialization only once per process.
49class LinuxHostInit {
50 public:
51 LinuxHostInit() {
[email protected]576a4ca2009-11-05 01:41:0952 RenderSandboxHostLinux* shost = Singleton<RenderSandboxHostLinux>::get();
[email protected]8ecd3aad2009-11-04 08:32:2253 shost->Init("");
[email protected]576a4ca2009-11-05 01:41:0954 ZygoteHost* zhost = Singleton<ZygoteHost>::get();
[email protected]8ecd3aad2009-11-04 08:32:2255 zhost->Init("");
56 }
57 ~LinuxHostInit() {}
58};
59
60} // namespace
61#endif
62
[email protected]d4515eb2009-01-30 00:40:4363extern int BrowserMain(const MainFunctionParams&);
64
65const wchar_t kUnitTestShowWindows[] = L"show-windows";
66
[email protected]ddf8a4b02010-03-22 23:08:3067// Passed as value of kTestType.
68static const char kBrowserTestType[] = "browser";
69
[email protected]4ff446f2009-07-10 18:29:3970// Default delay for the time-out at which we stop the
71// inner-message loop the first time.
[email protected]b5f95102009-07-01 19:53:5972const int kInitialTimeoutInMS = 30000;
73
74// Delay for sub-sequent time-outs once the initial time-out happened.
75const int kSubsequentTimeoutInMS = 5000;
76
[email protected]8bcdec92009-02-25 16:15:1877InProcessBrowserTest::InProcessBrowserTest()
78 : browser_(NULL),
79 show_window_(false),
[email protected]56cdae32009-03-12 19:58:2080 dom_automation_enabled_(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]298883bc2010-04-30 14:50:5896 ASSERT_TRUE(file_util::DieFileDie(user_data_dir, true));
[email protected]d4515eb2009-01-30 00:40:4397
[email protected]4a44bc32010-05-28 22:22:4498 // Recreate the user data dir. (PathService::Get guarantees that the directory
99 // exists if it returns true, but it only actually checks on the first call,
100 // the rest are cached. Thus we need to recreate it ourselves to not break
101 // the PathService guarantee.)
102 ASSERT_TRUE(file_util::CreateDirectory(user_data_dir));
103
[email protected]d4515eb2009-01-30 00:40:43104 // The unit test suite creates a testingbrowser, but we want the real thing.
105 // Delete the current one. We'll install the testing one in TearDown.
106 delete g_browser_process;
[email protected]298883bc2010-04-30 14:50:58107 g_browser_process = NULL;
108
109 SetUpUserDataDirectory();
[email protected]d4515eb2009-01-30 00:40:43110
111 // Don't delete the resources when BrowserMain returns. Many ui classes
112 // cache SkBitmaps in a static field so that if we delete the resource
113 // bundle we'll crash.
114 browser_shutdown::delete_resources_on_shutdown = false;
115
[email protected]986088a62010-05-13 18:59:20116 // Remember the command line. Normally this doesn't matter, because the test
117 // harness creates a new process for each test, but when the test harness is
118 // running in single process mode, we can't let one test's command-line
119 // changes (e.g. enabling DOM automation) affect other tests.
[email protected]d4515eb2009-01-30 00:40:43120 CommandLine* command_line = CommandLine::ForCurrentProcessMutable();
[email protected]56cdae32009-03-12 19:58:20121 original_command_line_.reset(new CommandLine(*command_line));
[email protected]d4515eb2009-01-30 00:40:43122
[email protected]9665fa62009-04-13 22:15:29123 SetUpCommandLine(command_line);
124
[email protected]108c2a12009-06-05 22:18:09125#if defined(OS_WIN)
[email protected]d4515eb2009-01-30 00:40:43126 // Hide windows on show.
[email protected]8bcdec92009-02-25 16:15:18127 if (!command_line->HasSwitch(kUnitTestShowWindows) && !show_window_)
[email protected]d4515eb2009-01-30 00:40:43128 BrowserView::SetShowState(SW_HIDE);
[email protected]108c2a12009-06-05 22:18:09129#endif
[email protected]d4515eb2009-01-30 00:40:43130
[email protected]8bcdec92009-02-25 16:15:18131 if (dom_automation_enabled_)
132 command_line->AppendSwitch(switches::kDomAutomationController);
133
[email protected]cdbc1842009-08-26 02:56:58134 // Turn off tip loading for tests; see http://crbug.com/17725
135 command_line->AppendSwitch(switches::kDisableWebResources);
[email protected]0a519262009-07-13 18:14:08136
[email protected]23cc9a12009-07-30 21:27:01137 command_line->AppendSwitchWithValue(switches::kUserDataDir,
138 user_data_dir.ToWStringHack());
[email protected]d4515eb2009-01-30 00:40:43139
[email protected]e01aba812009-07-09 18:31:24140 // Don't show the first run ui.
141 command_line->AppendSwitch(switches::kNoFirstRun);
142
[email protected]ddf8a4b02010-03-22 23:08:30143 // This is a Browser test.
144 command_line->AppendSwitchWithValue(switches::kTestType,
145 ASCIIToWide(kBrowserTestType));
146
[email protected]8bcdec92009-02-25 16:15:18147 // Single-process mode is not set in BrowserMain so it needs to be processed
[email protected]298883bc2010-04-30 14:50:58148 // explicitly.
[email protected]56cdae32009-03-12 19:58:20149 original_single_process_ = RenderProcessHost::run_renderer_in_process();
[email protected]8bcdec92009-02-25 16:15:18150 if (command_line->HasSwitch(switches::kSingleProcess))
151 RenderProcessHost::set_run_renderer_in_process(true);
152
[email protected]87bf9742010-06-09 20:31:41153#if defined(OS_WIN)
154 // The Windows sandbox requires that the browser and child processes are the
155 // same binary. So we launch browser_process.exe which loads chrome.dll
156 command_line->AppendSwitchWithValue(switches::kBrowserSubprocessPath,
157 command_line->GetProgram().value());
158#else
159 // Explicitly set the path of the binary used for child processes, otherwise
160 // they'll try to use browser_tests which doesn't contain ChromeMain.
[email protected]6cea14d2009-09-10 18:19:18161 FilePath subprocess_path;
[email protected]7f74a4e2009-04-30 17:00:24162 PathService::Get(base::FILE_EXE, &subprocess_path);
[email protected]6cea14d2009-09-10 18:19:18163 subprocess_path = subprocess_path.DirName();
164 subprocess_path = subprocess_path.AppendASCII(WideToASCII(
165 chrome::kBrowserProcessExecutablePath));
[email protected]7f74a4e2009-04-30 17:00:24166 command_line->AppendSwitchWithValue(switches::kBrowserSubprocessPath,
[email protected]6cea14d2009-09-10 18:19:18167 subprocess_path.ToWStringHack());
[email protected]87bf9742010-06-09 20:31:41168#endif
[email protected]d4515eb2009-01-30 00:40:43169
[email protected]9c73efa2009-07-08 00:18:36170 // Enable warning level logging so that we can see when bad stuff happens.
171 command_line->AppendSwitch(switches::kEnableLogging);
172 command_line->AppendSwitchWithValue(switches::kLoggingLevel,
173 IntToWString(1)); // warning
174
[email protected]d4515eb2009-01-30 00:40:43175 SandboxInitWrapper sandbox_wrapper;
[email protected]7c321082009-02-09 15:35:47176 MainFunctionParams params(*command_line, sandbox_wrapper, NULL);
[email protected]d4515eb2009-01-30 00:40:43177 params.ui_task =
178 NewRunnableMethod(this, &InProcessBrowserTest::RunTestOnMainThreadLoop);
[email protected]13324ed2009-04-03 05:14:19179
[email protected]c4ff4952010-01-08 19:12:47180 host_resolver_ = new net::RuleBasedHostResolverProc(
181 new IntranetRedirectHostResolverProc(NULL));
[email protected]c7ad50f2009-09-11 06:28:15182
183 // Something inside the browser does this lookup implicitly. Make it fail
184 // to avoid external dependency. It won't break the tests.
185 host_resolver_->AddSimulatedFailure("*.google.com");
186
187 // See http://en.wikipedia.org/wiki/Web_Proxy_Autodiscovery_Protocol
188 // We don't want the test code to use it.
189 host_resolver_->AddSimulatedFailure("wpad");
190
[email protected]b59ff372009-07-15 22:04:32191 net::ScopedDefaultHostResolverProc scoped_host_resolver_proc(
[email protected]c7ad50f2009-09-11 06:28:15192 host_resolver_.get());
[email protected]5c5de8c2009-09-23 17:11:26193
194 SetUpInProcessBrowserTestFixture();
[email protected]60a782e2010-02-24 22:41:35195
196 // Before we run the browser, we have to hack the path to the exe to match
197 // what it would be if Chrome was running, because it is used to fork renderer
198 // processes, on Linux at least (failure to do so will cause a browser_test to
199 // be run instead of a renderer).
200 FilePath chrome_path;
201 CHECK(PathService::Get(base::FILE_EXE, &chrome_path));
202 chrome_path = chrome_path.DirName();
203#if defined(OS_WIN)
204 chrome_path = chrome_path.Append(chrome::kBrowserProcessExecutablePath);
205#elif defined(OS_POSIX)
206 chrome_path = chrome_path.Append(
207 WideToASCII(chrome::kBrowserProcessExecutablePath));
208#endif
209 CHECK(PathService::Override(base::FILE_EXE, chrome_path));
210
211#if defined(OS_LINUX)
212 // Initialize the RenderSandbox and Zygote hosts. Apparently they get used
213 // for InProcessBrowserTest, and this is not the normal browser startup path.
214 Singleton<LinuxHostInit>::get();
215#endif
216
[email protected]d4515eb2009-01-30 00:40:43217 BrowserMain(params);
[email protected]5c5de8c2009-09-23 17:11:26218 TearDownInProcessBrowserTestFixture();
[email protected]d4515eb2009-01-30 00:40:43219}
220
221void InProcessBrowserTest::TearDown() {
222 // Reinstall testing browser process.
223 delete g_browser_process;
224 g_browser_process = new TestingBrowserProcess();
225
226 browser_shutdown::delete_resources_on_shutdown = true;
227
[email protected]eb1bd832010-05-18 20:39:58228#if defined(OS_WIN)
[email protected]d4515eb2009-01-30 00:40:43229 BrowserView::SetShowState(-1);
[email protected]108c2a12009-06-05 22:18:09230#endif
[email protected]56cdae32009-03-12 19:58:20231
232 *CommandLine::ForCurrentProcessMutable() = *original_command_line_;
233 RenderProcessHost::set_run_renderer_in_process(original_single_process_);
[email protected]d4515eb2009-01-30 00:40:43234}
235
[email protected]d4515eb2009-01-30 00:40:43236HTTPTestServer* InProcessBrowserTest::StartHTTPServer() {
237 // The HTTPServer must run on the IO thread.
238 DCHECK(!http_server_.get());
239 http_server_ = HTTPTestServer::CreateServer(
240 L"chrome/test/data",
241 g_browser_process->io_thread()->message_loop());
242 return http_server_.get();
243}
244
245// Creates a browser with a single tab (about:blank), waits for the tab to
246// finish loading and shows the browser.
247Browser* InProcessBrowserTest::CreateBrowser(Profile* profile) {
248 Browser* browser = Browser::Create(profile);
249
[email protected]e0d481582009-09-15 21:06:25250 browser->AddTabWithURL(GURL(chrome::kAboutBlankURL), GURL(),
[email protected]715af7e2010-04-29 01:55:38251 PageTransition::START_PAGE, -1,
[email protected]4a1665442010-06-28 16:09:39252 TabStripModel::ADD_SELECTED, NULL, std::string());
[email protected]f0a51fb52009-03-05 12:46:38253
[email protected]d4515eb2009-01-30 00:40:43254 // Wait for the page to finish loading.
255 ui_test_utils::WaitForNavigation(
[email protected]ce3fa3c2009-04-20 19:55:57256 &browser->GetSelectedTabContents()->controller());
[email protected]d4515eb2009-01-30 00:40:43257
258 browser->window()->Show();
259
260 return browser;
261}
262
[email protected]64f19312010-04-13 22:30:01263void InProcessBrowserTest::RunTestOnMainThreadLoop() {
[email protected]304a3172010-05-04 05:38:44264 // On Mac, without the following autorelease pool, code which is directly
265 // executed (as opposed to executed inside a message loop) would autorelease
266 // objects into a higher-level pool. This pool is not recycled in-sync with
267 // the message loops' pools and causes problems with code relying on
268 // deallocation via an autorelease pool (such as browser window closure and
269 // browser shutdown). To avoid this, the following pool is recycled after each
270 // time code is directly executed.
271 base::ScopedNSAutoreleasePool pool;
272
[email protected]64f19312010-04-13 22:30:01273 // Pump startup related events.
274 MessageLoopForUI::current()->RunAllPending();
275
276 // In the long term it would be great if we could use a TestingProfile
277 // here and only enable services you want tested, but that requires all
278 // consumers of Profile to handle NULL services.
279 Profile* profile = ProfileManager::GetDefaultProfile();
280 if (!profile) {
281 // We should only be able to get here if the profile already exists and
282 // has been created.
283 NOTREACHED();
284 return;
285 }
[email protected]304a3172010-05-04 05:38:44286 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01287
288 ChromeThread::PostTask(
289 ChromeThread::IO, FROM_HERE,
290 NewRunnableFunction(chrome_browser_net::SetUrlRequestMocksEnabled, true));
291
292 browser_ = CreateBrowser(profile);
[email protected]304a3172010-05-04 05:38:44293 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01294
295 // Start the timeout timer to prevent hangs.
296 MessageLoopForUI::current()->PostDelayedTask(FROM_HERE,
297 NewRunnableMethod(this, &InProcessBrowserTest::TimedOut),
298 initial_timeout_);
299
300 // Pump any pending events that were created as a result of creating a
301 // browser.
302 MessageLoopForUI::current()->RunAllPending();
303
304 RunTestOnMainThread();
[email protected]304a3172010-05-04 05:38:44305 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01306
307 CleanUpOnMainThread();
[email protected]304a3172010-05-04 05:38:44308 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01309
310 QuitBrowsers();
[email protected]304a3172010-05-04 05:38:44311 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01312
313 // Stop the HTTP server.
314 http_server_ = NULL;
315}
316
317void InProcessBrowserTest::QuitBrowsers() {
318 if (BrowserList::size() == 0)
319 return;
320
321 // Invoke CloseAllBrowsersAndExit on a running message loop.
322 // CloseAllBrowsersAndExit exits the message loop after everything has been
323 // shut down properly.
324 MessageLoopForUI::current()->PostTask(
325 FROM_HERE,
326 NewRunnableFunction(&BrowserList::CloseAllBrowsersAndExit));
327 ui_test_utils::RunMessageLoop();
328}
[email protected]b5f95102009-07-01 19:53:59329
[email protected]5c00ca82010-04-08 21:30:42330void InProcessBrowserTest::TimedOut() {
[email protected]94ab2ad2009-10-15 18:18:51331 std::string error_message = "Test timed out. Each test runs for a max of ";
332 error_message += IntToString(kInitialTimeoutInMS);
333 error_message += " ms (kInitialTimeoutInMS).";
334
335 GTEST_NONFATAL_FAILURE_(error_message.c_str());
[email protected]b5f95102009-07-01 19:53:59336
[email protected]b5f95102009-07-01 19:53:59337 MessageLoopForUI::current()->Quit();
338}
[email protected]4ff446f2009-07-10 18:29:39339
340void InProcessBrowserTest::SetInitialTimeoutInMS(int timeout_value) {
341 DCHECK_GT(timeout_value, 0);
342 initial_timeout_ = timeout_value;
343}