blob: df3021c6d7f65a27acebbc0d7139e5b5becdf4f2 [file] [log] [blame]
[email protected]94ab2ad2009-10-15 18:18:511// Copyright (c) 2009 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]cec4a272009-07-31 21:55:0318#include "chrome/browser/net/url_request_mock_util.h"
[email protected]d4515eb2009-01-30 00:40:4319#include "chrome/browser/profile.h"
20#include "chrome/browser/profile_manager.h"
[email protected]8bcdec92009-02-25 16:15:1821#include "chrome/browser/renderer_host/render_process_host.h"
[email protected]5c238752009-06-13 10:29:0722#include "chrome/browser/tab_contents/tab_contents.h"
[email protected]108c2a12009-06-05 22:18:0923#if defined(OS_WIN)
[email protected]d4515eb2009-01-30 00:40:4324#include "chrome/browser/views/frame/browser_view.h"
[email protected]108c2a12009-06-05 22:18:0925#endif
[email protected]d4515eb2009-01-30 00:40:4326#include "chrome/common/chrome_constants.h"
27#include "chrome/common/chrome_paths.h"
28#include "chrome/common/chrome_switches.h"
29#include "chrome/common/main_function_params.h"
[email protected]ad1f9bd2009-07-30 20:23:1530#include "chrome/common/notification_registrar.h"
31#include "chrome/common/notification_type.h"
[email protected]e0d481582009-09-15 21:06:2532#include "chrome/common/url_constants.h"
[email protected]d4515eb2009-01-30 00:40:4333#include "chrome/test/testing_browser_process.h"
34#include "chrome/test/ui_test_utils.h"
[email protected]d4515eb2009-01-30 00:40:4335#include "sandbox/src/dep.h"
36
[email protected]8ecd3aad2009-11-04 08:32:2237#if defined(OS_LINUX)
38#include "base/singleton.h"
39#include "chrome/browser/renderer_host/render_sandbox_host_linux.h"
40#include "chrome/browser/zygote_host_linux.h"
41
42namespace {
43
44// A helper class to do Linux-only initialization only once per process.
45class LinuxHostInit {
46 public:
47 LinuxHostInit() {
48 RenderSandboxHostLinux* shost = Singleton<RenderSandboxHostLinux>().get();
49 shost->Init("");
50 ZygoteHost* zhost = Singleton<ZygoteHost>().get();
51 zhost->Init("");
52 }
53 ~LinuxHostInit() {}
54};
55
56} // namespace
57#endif
58
[email protected]d4515eb2009-01-30 00:40:4359extern int BrowserMain(const MainFunctionParams&);
60
61const wchar_t kUnitTestShowWindows[] = L"show-windows";
62
[email protected]4ff446f2009-07-10 18:29:3963// Default delay for the time-out at which we stop the
64// inner-message loop the first time.
[email protected]b5f95102009-07-01 19:53:5965const int kInitialTimeoutInMS = 30000;
66
67// Delay for sub-sequent time-outs once the initial time-out happened.
68const int kSubsequentTimeoutInMS = 5000;
69
[email protected]8bcdec92009-02-25 16:15:1870InProcessBrowserTest::InProcessBrowserTest()
71 : browser_(NULL),
72 show_window_(false),
[email protected]56cdae32009-03-12 19:58:2073 dom_automation_enabled_(false),
74 single_process_(false),
[email protected]4ff446f2009-07-10 18:29:3975 original_single_process_(false),
76 initial_timeout_(kInitialTimeoutInMS) {
[email protected]d4515eb2009-01-30 00:40:4377}
78
79void InProcessBrowserTest::SetUp() {
80 // Cleanup the user data dir.
[email protected]23cc9a12009-07-30 21:27:0181 FilePath user_data_dir;
[email protected]d4515eb2009-01-30 00:40:4382 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
[email protected]23cc9a12009-07-30 21:27:0183 ASSERT_LT(10, static_cast<int>(user_data_dir.value().size())) <<
[email protected]d4515eb2009-01-30 00:40:4384 "The user data directory name passed into this test was too "
85 "short to delete safely. Please check the user-data-dir "
86 "argument and try again.";
[email protected]2c9bf9d72009-08-07 00:43:4987 if (ShouldDeleteProfile())
88 ASSERT_TRUE(file_util::DieFileDie(user_data_dir, true));
[email protected]d4515eb2009-01-30 00:40:4389
90 // The unit test suite creates a testingbrowser, but we want the real thing.
91 // Delete the current one. We'll install the testing one in TearDown.
92 delete g_browser_process;
93
94 // Don't delete the resources when BrowserMain returns. Many ui classes
95 // cache SkBitmaps in a static field so that if we delete the resource
96 // bundle we'll crash.
97 browser_shutdown::delete_resources_on_shutdown = false;
98
99 CommandLine* command_line = CommandLine::ForCurrentProcessMutable();
[email protected]56cdae32009-03-12 19:58:20100 original_command_line_.reset(new CommandLine(*command_line));
[email protected]d4515eb2009-01-30 00:40:43101
[email protected]9665fa62009-04-13 22:15:29102 SetUpCommandLine(command_line);
103
[email protected]108c2a12009-06-05 22:18:09104#if defined(OS_WIN)
[email protected]d4515eb2009-01-30 00:40:43105 // Hide windows on show.
[email protected]8bcdec92009-02-25 16:15:18106 if (!command_line->HasSwitch(kUnitTestShowWindows) && !show_window_)
[email protected]d4515eb2009-01-30 00:40:43107 BrowserView::SetShowState(SW_HIDE);
[email protected]108c2a12009-06-05 22:18:09108#endif
[email protected]d4515eb2009-01-30 00:40:43109
[email protected]8bcdec92009-02-25 16:15:18110 if (dom_automation_enabled_)
111 command_line->AppendSwitch(switches::kDomAutomationController);
112
[email protected]56cdae32009-03-12 19:58:20113 if (single_process_)
114 command_line->AppendSwitch(switches::kSingleProcess);
115
[email protected]cdbc1842009-08-26 02:56:58116 // Turn off tip loading for tests; see http://crbug.com/17725
117 command_line->AppendSwitch(switches::kDisableWebResources);
[email protected]0a519262009-07-13 18:14:08118
[email protected]23cc9a12009-07-30 21:27:01119 command_line->AppendSwitchWithValue(switches::kUserDataDir,
120 user_data_dir.ToWStringHack());
[email protected]d4515eb2009-01-30 00:40:43121
122 // For some reason the sandbox wasn't happy running in test mode. These
123 // tests aren't intended to test the sandbox, so we turn it off.
124 command_line->AppendSwitch(switches::kNoSandbox);
125
[email protected]e01aba812009-07-09 18:31:24126 // Don't show the first run ui.
127 command_line->AppendSwitch(switches::kNoFirstRun);
128
[email protected]8bcdec92009-02-25 16:15:18129 // Single-process mode is not set in BrowserMain so it needs to be processed
130 // explicitlty.
[email protected]56cdae32009-03-12 19:58:20131 original_single_process_ = RenderProcessHost::run_renderer_in_process();
[email protected]8bcdec92009-02-25 16:15:18132 if (command_line->HasSwitch(switches::kSingleProcess))
133 RenderProcessHost::set_run_renderer_in_process(true);
134
[email protected]7f74a4e2009-04-30 17:00:24135 // Explicitly set the path of the exe used for the renderer and plugin,
136 // otherwise they'll try to use unit_test.exe.
[email protected]6cea14d2009-09-10 18:19:18137 FilePath subprocess_path;
[email protected]7f74a4e2009-04-30 17:00:24138 PathService::Get(base::FILE_EXE, &subprocess_path);
[email protected]6cea14d2009-09-10 18:19:18139 subprocess_path = subprocess_path.DirName();
140 subprocess_path = subprocess_path.AppendASCII(WideToASCII(
141 chrome::kBrowserProcessExecutablePath));
[email protected]7f74a4e2009-04-30 17:00:24142 command_line->AppendSwitchWithValue(switches::kBrowserSubprocessPath,
[email protected]6cea14d2009-09-10 18:19:18143 subprocess_path.ToWStringHack());
[email protected]d4515eb2009-01-30 00:40:43144
[email protected]9c73efa2009-07-08 00:18:36145 // Enable warning level logging so that we can see when bad stuff happens.
146 command_line->AppendSwitch(switches::kEnableLogging);
147 command_line->AppendSwitchWithValue(switches::kLoggingLevel,
148 IntToWString(1)); // warning
149
[email protected]d4515eb2009-01-30 00:40:43150 SandboxInitWrapper sandbox_wrapper;
[email protected]7c321082009-02-09 15:35:47151 MainFunctionParams params(*command_line, sandbox_wrapper, NULL);
[email protected]d4515eb2009-01-30 00:40:43152 params.ui_task =
153 NewRunnableMethod(this, &InProcessBrowserTest::RunTestOnMainThreadLoop);
[email protected]13324ed2009-04-03 05:14:19154
[email protected]c7ad50f2009-09-11 06:28:15155 host_resolver_ = new net::RuleBasedHostResolverProc(NULL);
156
157 // Something inside the browser does this lookup implicitly. Make it fail
158 // to avoid external dependency. It won't break the tests.
159 host_resolver_->AddSimulatedFailure("*.google.com");
160
161 // See http://en.wikipedia.org/wiki/Web_Proxy_Autodiscovery_Protocol
162 // We don't want the test code to use it.
163 host_resolver_->AddSimulatedFailure("wpad");
164
[email protected]b59ff372009-07-15 22:04:32165 net::ScopedDefaultHostResolverProc scoped_host_resolver_proc(
[email protected]c7ad50f2009-09-11 06:28:15166 host_resolver_.get());
[email protected]5c5de8c2009-09-23 17:11:26167
168 SetUpInProcessBrowserTestFixture();
[email protected]d4515eb2009-01-30 00:40:43169 BrowserMain(params);
[email protected]5c5de8c2009-09-23 17:11:26170 TearDownInProcessBrowserTestFixture();
[email protected]d4515eb2009-01-30 00:40:43171}
172
173void InProcessBrowserTest::TearDown() {
174 // Reinstall testing browser process.
175 delete g_browser_process;
176 g_browser_process = new TestingBrowserProcess();
177
178 browser_shutdown::delete_resources_on_shutdown = true;
179
[email protected]108c2a12009-06-05 22:18:09180#if defined(WIN)
[email protected]d4515eb2009-01-30 00:40:43181 BrowserView::SetShowState(-1);
[email protected]108c2a12009-06-05 22:18:09182#endif
[email protected]56cdae32009-03-12 19:58:20183
184 *CommandLine::ForCurrentProcessMutable() = *original_command_line_;
185 RenderProcessHost::set_run_renderer_in_process(original_single_process_);
[email protected]d4515eb2009-01-30 00:40:43186}
187
[email protected]d4515eb2009-01-30 00:40:43188HTTPTestServer* InProcessBrowserTest::StartHTTPServer() {
189 // The HTTPServer must run on the IO thread.
190 DCHECK(!http_server_.get());
191 http_server_ = HTTPTestServer::CreateServer(
192 L"chrome/test/data",
193 g_browser_process->io_thread()->message_loop());
194 return http_server_.get();
195}
196
197// Creates a browser with a single tab (about:blank), waits for the tab to
198// finish loading and shows the browser.
199Browser* InProcessBrowserTest::CreateBrowser(Profile* profile) {
200 Browser* browser = Browser::Create(profile);
201
[email protected]e0d481582009-09-15 21:06:25202 browser->AddTabWithURL(GURL(chrome::kAboutBlankURL), GURL(),
203 PageTransition::START_PAGE, true, -1, false, NULL);
[email protected]f0a51fb52009-03-05 12:46:38204
[email protected]d4515eb2009-01-30 00:40:43205 // Wait for the page to finish loading.
206 ui_test_utils::WaitForNavigation(
[email protected]ce3fa3c2009-04-20 19:55:57207 &browser->GetSelectedTabContents()->controller());
[email protected]d4515eb2009-01-30 00:40:43208
209 browser->window()->Show();
210
211 return browser;
212}
213
214void InProcessBrowserTest::RunTestOnMainThreadLoop() {
215 // In the long term it would be great if we could use a TestingProfile
216 // here and only enable services you want tested, but that requires all
217 // consumers of Profile to handle NULL services.
218 FilePath user_data_dir;
219 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
220 ProfileManager* profile_manager = g_browser_process->profile_manager();
221 Profile* profile = profile_manager->GetDefaultProfile(user_data_dir);
222 if (!profile) {
223 // We should only be able to get here if the profile already exists and
224 // has been created.
225 NOTREACHED();
226 MessageLoopForUI::current()->Quit();
227 return;
228 }
229
[email protected]eca6a4f2009-06-25 17:29:09230
231 // Before we run the browser, we have to hack the path to the exe to match
232 // what it would be if Chrome was running, because it is used to fork renderer
233 // processes, on Linux at least (failure to do so will cause a browser_test to
234 // be run instead of a renderer).
235 FilePath chrome_path;
236 CHECK(PathService::Get(base::FILE_EXE, &chrome_path));
237 chrome_path = chrome_path.DirName();
238#if defined(OS_WIN)
239 chrome_path = chrome_path.Append(chrome::kBrowserProcessExecutablePath);
240#elif defined(OS_POSIX)
241 chrome_path = chrome_path.Append(
242 WideToASCII(chrome::kBrowserProcessExecutablePath));
243#endif
244 CHECK(PathService::Override(base::FILE_EXE, chrome_path));
245
[email protected]6fad2632009-11-02 05:59:37246 ChromeThread::PostTask(
247 ChromeThread::IO, FROM_HERE,
[email protected]cec4a272009-07-31 21:55:03248 NewRunnableFunction(chrome_browser_net::SetUrlRequestMocksEnabled, true));
249
[email protected]8ecd3aad2009-11-04 08:32:22250#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 browser_ = CreateBrowser(profile);
257
[email protected]b5f95102009-07-01 19:53:59258 // Start the timeout timer to prevent hangs.
259 MessageLoopForUI::current()->PostDelayedTask(FROM_HERE,
260 NewRunnableMethod(this, &InProcessBrowserTest::TimedOut),
[email protected]4ff446f2009-07-10 18:29:39261 initial_timeout_);
[email protected]b5f95102009-07-01 19:53:59262
[email protected]d4515eb2009-01-30 00:40:43263 RunTestOnMainThread();
[email protected]17c4f3c2009-07-04 16:36:25264 CleanUpOnMainThread();
[email protected]d4515eb2009-01-30 00:40:43265
[email protected]cc661e52009-07-27 19:18:41266 // Close all browser windows. This might not happen immediately, since some
267 // may need to wait for beforeunload and unload handlers to fire in a tab.
268 // When all windows are closed, the last window will call Quit().
[email protected]e6152c22009-06-23 23:33:27269 BrowserList::const_iterator browser = BrowserList::begin();
270 for (; browser != BrowserList::end(); ++browser)
[email protected]cc661e52009-07-27 19:18:41271 (*browser)->CloseWindow();
[email protected]d4515eb2009-01-30 00:40:43272
273 // Stop the HTTP server.
274 http_server_ = NULL;
[email protected]d4515eb2009-01-30 00:40:43275}
[email protected]deb27ae2009-04-10 02:37:22276
[email protected]b5f95102009-07-01 19:53:59277void InProcessBrowserTest::TimedOut() {
278 DCHECK(MessageLoopForUI::current()->IsNested());
279
[email protected]94ab2ad2009-10-15 18:18:51280 std::string error_message = "Test timed out. Each test runs for a max of ";
281 error_message += IntToString(kInitialTimeoutInMS);
282 error_message += " ms (kInitialTimeoutInMS).";
283
284 GTEST_NONFATAL_FAILURE_(error_message.c_str());
[email protected]b5f95102009-07-01 19:53:59285
286 // Start the timeout timer to prevent hangs.
287 MessageLoopForUI::current()->PostDelayedTask(FROM_HERE,
288 NewRunnableMethod(this, &InProcessBrowserTest::TimedOut),
289 kSubsequentTimeoutInMS);
290
291 MessageLoopForUI::current()->Quit();
292}
[email protected]4ff446f2009-07-10 18:29:39293
294void InProcessBrowserTest::SetInitialTimeoutInMS(int timeout_value) {
295 DCHECK_GT(timeout_value, 0);
296 initial_timeout_ = timeout_value;
297}