blob: a0bcaea56007d7937164d199579410b106973b58 [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
[email protected]5f26b8b2010-11-10 00:49:267#include "app/app_switches.h"
8#include "app/gfx/gl/gl_implementation.h"
[email protected]d4515eb2009-01-30 00:40:439#include "base/command_line.h"
[email protected]d8412052009-04-21 22:01:0110#include "base/file_path.h"
[email protected]d4515eb2009-01-30 00:40:4311#include "base/file_util.h"
[email protected]c2818d42010-10-18 02:47:3912#include "base/mac/scoped_nsautorelease_pool.h"
[email protected]d4515eb2009-01-30 00:40:4313#include "base/path_service.h"
[email protected]528c56d2010-07-30 19:28:4414#include "base/string_number_conversions.h"
[email protected]fb895c62009-10-09 18:20:3015#include "base/test/test_file_util.h"
[email protected]d4515eb2009-01-30 00:40:4316#include "chrome/browser/browser.h"
[email protected]b6e38ef2009-06-16 00:43:2317#include "chrome/browser/browser_list.h"
[email protected]d4515eb2009-01-30 00:40:4318#include "chrome/browser/browser_process.h"
19#include "chrome/browser/browser_shutdown.h"
[email protected]8281e48e2010-10-12 18:54:4920#include "chrome/browser/browser_thread.h"
[email protected]108c2a12009-06-05 22:18:0921#include "chrome/browser/browser_window.h"
[email protected]c4ff4952010-01-08 19:12:4722#include "chrome/browser/intranet_redirect_detector.h"
[email protected]0ac83682010-01-22 17:46:2723#include "chrome/browser/io_thread.h"
[email protected]cec4a272009-07-31 21:55:0324#include "chrome/browser/net/url_request_mock_util.h"
[email protected]d4515eb2009-01-30 00:40:4325#include "chrome/browser/profile.h"
26#include "chrome/browser/profile_manager.h"
[email protected]8bcdec92009-02-25 16:15:1827#include "chrome/browser/renderer_host/render_process_host.h"
[email protected]5c238752009-06-13 10:29:0728#include "chrome/browser/tab_contents/tab_contents.h"
[email protected]c848d3d92010-09-16 21:57:4529#include "chrome/browser/tabs/tab_strip_model.h"
[email protected]339d6dd2010-11-12 00:41:5830#include "chrome/browser/ui/browser_navigator.h"
[email protected]d4515eb2009-01-30 00:40:4331#include "chrome/common/chrome_constants.h"
32#include "chrome/common/chrome_paths.h"
33#include "chrome/common/chrome_switches.h"
[email protected]0750b1442010-11-02 21:59:3734#include "chrome/common/logging_chrome.h"
[email protected]d4515eb2009-01-30 00:40:4335#include "chrome/common/main_function_params.h"
[email protected]ad1f9bd2009-07-30 20:23:1536#include "chrome/common/notification_registrar.h"
37#include "chrome/common/notification_type.h"
[email protected]e0d481582009-09-15 21:06:2538#include "chrome/common/url_constants.h"
[email protected]470f7a52010-09-23 20:20:3839#include "chrome/test/test_launcher_utils.h"
[email protected]d4515eb2009-01-30 00:40:4340#include "chrome/test/testing_browser_process.h"
41#include "chrome/test/ui_test_utils.h"
[email protected]c4ff4952010-01-08 19:12:4742#include "net/base/mock_host_resolver.h"
[email protected]3985ba82010-07-29 21:44:1243#include "net/test/test_server.h"
[email protected]d4515eb2009-01-30 00:40:4344#include "sandbox/src/dep.h"
45
[email protected]c848d3d92010-09-16 21:57:4546#if defined(OS_WIN)
47#include "chrome/browser/views/frame/browser_view.h"
48#endif
49
[email protected]8ecd3aad2009-11-04 08:32:2250#if defined(OS_LINUX)
[email protected]470f7a52010-09-23 20:20:3851#include "base/environment.h"
[email protected]8ecd3aad2009-11-04 08:32:2252#include "base/singleton.h"
53#include "chrome/browser/renderer_host/render_sandbox_host_linux.h"
54#include "chrome/browser/zygote_host_linux.h"
55
56namespace {
57
58// A helper class to do Linux-only initialization only once per process.
59class LinuxHostInit {
60 public:
61 LinuxHostInit() {
[email protected]576a4ca2009-11-05 01:41:0962 RenderSandboxHostLinux* shost = Singleton<RenderSandboxHostLinux>::get();
[email protected]8ecd3aad2009-11-04 08:32:2263 shost->Init("");
[email protected]576a4ca2009-11-05 01:41:0964 ZygoteHost* zhost = Singleton<ZygoteHost>::get();
[email protected]8ecd3aad2009-11-04 08:32:2265 zhost->Init("");
66 }
67 ~LinuxHostInit() {}
68};
69
70} // namespace
71#endif
72
[email protected]02dbca0b2010-09-17 07:44:1073#if defined(OS_CHROMEOS)
74#include "chrome/browser/chromeos/cros/cros_library.h"
75#endif // defined(OS_CHROMEOS)
76
[email protected]e1c10f182010-09-30 08:53:0677namespace {
78
79void InitializeBrowser(Browser* browser) {
[email protected]cecc93a2010-10-05 15:58:5580 browser->AddSelectedTabWithURL(GURL(chrome::kAboutBlankURL),
81 PageTransition::START_PAGE);
[email protected]e1c10f182010-09-30 08:53:0682
83 // Wait for the page to finish loading.
84 ui_test_utils::WaitForNavigation(
85 &browser->GetSelectedTabContents()->controller());
86
87 browser->window()->Show();
88}
89
90} // namespace
91
[email protected]d4515eb2009-01-30 00:40:4392extern int BrowserMain(const MainFunctionParams&);
93
94const wchar_t kUnitTestShowWindows[] = L"show-windows";
95
[email protected]ddf8a4b02010-03-22 23:08:3096// Passed as value of kTestType.
97static const char kBrowserTestType[] = "browser";
98
[email protected]8bcdec92009-02-25 16:15:1899InProcessBrowserTest::InProcessBrowserTest()
100 : browser_(NULL),
[email protected]95409e12010-08-17 20:07:11101 test_server_(net::TestServer::TYPE_HTTP,
102 FilePath(FILE_PATH_LITERAL("chrome/test/data"))),
[email protected]8bcdec92009-02-25 16:15:18103 show_window_(false),
[email protected]56cdae32009-03-12 19:58:20104 dom_automation_enabled_(false),
[email protected]0b4d3382010-07-14 16:13:04105 tab_closeable_state_watcher_enabled_(false),
[email protected]4b614a62010-10-06 15:33:10106 original_single_process_(false) {
[email protected]d4515eb2009-01-30 00:40:43107}
108
[email protected]c4ff4952010-01-08 19:12:47109InProcessBrowserTest::~InProcessBrowserTest() {
110}
111
[email protected]d4515eb2009-01-30 00:40:43112void InProcessBrowserTest::SetUp() {
[email protected]470f7a52010-09-23 20:20:38113 // Remember the command line. Normally this doesn't matter, because the test
114 // harness creates a new process for each test, but when the test harness is
115 // running in single process mode, we can't let one test's command-line
116 // changes (e.g. enabling DOM automation) affect other tests.
117 // TODO(phajdan.jr): This save/restore logic is unnecessary. Remove it.
118 CommandLine* command_line = CommandLine::ForCurrentProcessMutable();
119 original_command_line_.reset(new CommandLine(*command_line));
[email protected]d4515eb2009-01-30 00:40:43120
[email protected]fc82ccf02010-10-15 18:12:47121 // Create a temporary user data directory if required.
122 ASSERT_TRUE(CreateUserDataDirectory())
123 << "Could not create user data directory.";
[email protected]4a44bc32010-05-28 22:22:44124
[email protected]d4515eb2009-01-30 00:40:43125 // The unit test suite creates a testingbrowser, but we want the real thing.
126 // Delete the current one. We'll install the testing one in TearDown.
127 delete g_browser_process;
[email protected]298883bc2010-04-30 14:50:58128 g_browser_process = NULL;
129
[email protected]470f7a52010-09-23 20:20:38130 // Allow subclasses the opportunity to make changes to the default user data
131 // dir before running any tests.
[email protected]fc82ccf02010-10-15 18:12:47132 ASSERT_TRUE(SetUpUserDataDirectory())
133 << "Could not set up user data directory.";
[email protected]d4515eb2009-01-30 00:40:43134
135 // Don't delete the resources when BrowserMain returns. Many ui classes
136 // cache SkBitmaps in a static field so that if we delete the resource
137 // bundle we'll crash.
138 browser_shutdown::delete_resources_on_shutdown = false;
139
[email protected]470f7a52010-09-23 20:20:38140 // Allow subclasses the opportunity to make changes to the command line before
141 // running any tests.
[email protected]9665fa62009-04-13 22:15:29142 SetUpCommandLine(command_line);
143
[email protected]108c2a12009-06-05 22:18:09144#if defined(OS_WIN)
[email protected]d4515eb2009-01-30 00:40:43145 // Hide windows on show.
[email protected]8bcdec92009-02-25 16:15:18146 if (!command_line->HasSwitch(kUnitTestShowWindows) && !show_window_)
[email protected]d4515eb2009-01-30 00:40:43147 BrowserView::SetShowState(SW_HIDE);
[email protected]108c2a12009-06-05 22:18:09148#endif
[email protected]d4515eb2009-01-30 00:40:43149
[email protected]8bcdec92009-02-25 16:15:18150 if (dom_automation_enabled_)
151 command_line->AppendSwitch(switches::kDomAutomationController);
152
[email protected]ddf8a4b02010-03-22 23:08:30153 // This is a Browser test.
[email protected]05076ba22010-07-30 05:59:57154 command_line->AppendSwitchASCII(switches::kTestType, kBrowserTestType);
[email protected]ddf8a4b02010-03-22 23:08:30155
[email protected]5f26b8b2010-11-10 00:49:26156 // Force tests to use OSMesa if they launch the GPU process.
157 command_line->AppendSwitchASCII(switches::kUseGL,
158 gfx::kGLImplementationOSMesaName);
159
160 // Mac does not support accelerated compositing with OSMesa. Disable on all
161 // platforms so it is consistent. http://crbug.com/58343
162 command_line->AppendSwitch(switches::kDisableAcceleratedCompositing);
163
[email protected]8bcdec92009-02-25 16:15:18164 // Single-process mode is not set in BrowserMain so it needs to be processed
[email protected]298883bc2010-04-30 14:50:58165 // explicitly.
[email protected]56cdae32009-03-12 19:58:20166 original_single_process_ = RenderProcessHost::run_renderer_in_process();
[email protected]8bcdec92009-02-25 16:15:18167 if (command_line->HasSwitch(switches::kSingleProcess))
168 RenderProcessHost::set_run_renderer_in_process(true);
169
[email protected]87bf9742010-06-09 20:31:41170#if defined(OS_WIN)
171 // The Windows sandbox requires that the browser and child processes are the
172 // same binary. So we launch browser_process.exe which loads chrome.dll
[email protected]4f08c83f2010-07-29 23:02:34173 command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
174 command_line->GetProgram());
[email protected]87bf9742010-06-09 20:31:41175#else
176 // Explicitly set the path of the binary used for child processes, otherwise
177 // they'll try to use browser_tests which doesn't contain ChromeMain.
[email protected]6cea14d2009-09-10 18:19:18178 FilePath subprocess_path;
[email protected]7f74a4e2009-04-30 17:00:24179 PathService::Get(base::FILE_EXE, &subprocess_path);
[email protected]6cea14d2009-09-10 18:19:18180 subprocess_path = subprocess_path.DirName();
181 subprocess_path = subprocess_path.AppendASCII(WideToASCII(
182 chrome::kBrowserProcessExecutablePath));
[email protected]32369d762010-08-24 20:50:06183#if defined(OS_MACOSX)
184 // Recreate the real environment, run the helper within the app bundle.
185 subprocess_path = subprocess_path.DirName().DirName();
186 DCHECK_EQ(subprocess_path.BaseName().value(), "Contents");
187 subprocess_path =
188 subprocess_path.Append("Versions").Append(chrome::kChromeVersion);
189 subprocess_path =
190 subprocess_path.Append(chrome::kHelperProcessExecutablePath);
191#endif
[email protected]4f08c83f2010-07-29 23:02:34192 command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
193 subprocess_path);
[email protected]87bf9742010-06-09 20:31:41194#endif
[email protected]d4515eb2009-01-30 00:40:43195
[email protected]0b4d3382010-07-14 16:13:04196 // If ncecessary, disable TabCloseableStateWatcher.
197 if (!tab_closeable_state_watcher_enabled_)
198 command_line->AppendSwitch(switches::kDisableTabCloseableStateWatcher);
199
[email protected]8e930952010-09-30 07:51:26200 test_launcher_utils::PrepareBrowserCommandLineForTests(command_line);
201
[email protected]02dbca0b2010-09-17 07:44:10202#if defined(OS_CHROMEOS)
203 chromeos::CrosLibrary::Get()->GetTestApi()->SetUseStubImpl();
[email protected]0750b1442010-11-02 21:59:37204
205 // Make sure that the log directory exists.
206 FilePath log_dir = logging::GetSessionLogFile(*command_line).DirName();
207 file_util::CreateDirectory(log_dir);
[email protected]02dbca0b2010-09-17 07:44:10208#endif // defined(OS_CHROMEOS)
209
[email protected]d4515eb2009-01-30 00:40:43210 SandboxInitWrapper sandbox_wrapper;
[email protected]7c321082009-02-09 15:35:47211 MainFunctionParams params(*command_line, sandbox_wrapper, NULL);
[email protected]d4515eb2009-01-30 00:40:43212 params.ui_task =
213 NewRunnableMethod(this, &InProcessBrowserTest::RunTestOnMainThreadLoop);
[email protected]13324ed2009-04-03 05:14:19214
[email protected]c4ff4952010-01-08 19:12:47215 host_resolver_ = new net::RuleBasedHostResolverProc(
216 new IntranetRedirectHostResolverProc(NULL));
[email protected]c7ad50f2009-09-11 06:28:15217
218 // Something inside the browser does this lookup implicitly. Make it fail
219 // to avoid external dependency. It won't break the tests.
220 host_resolver_->AddSimulatedFailure("*.google.com");
221
222 // See http://en.wikipedia.org/wiki/Web_Proxy_Autodiscovery_Protocol
223 // We don't want the test code to use it.
224 host_resolver_->AddSimulatedFailure("wpad");
225
[email protected]b59ff372009-07-15 22:04:32226 net::ScopedDefaultHostResolverProc scoped_host_resolver_proc(
[email protected]c7ad50f2009-09-11 06:28:15227 host_resolver_.get());
[email protected]5c5de8c2009-09-23 17:11:26228
229 SetUpInProcessBrowserTestFixture();
[email protected]60a782e2010-02-24 22:41:35230
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
246#if defined(OS_LINUX)
247 // Initialize the RenderSandbox and Zygote hosts. Apparently they get used
248 // for InProcessBrowserTest, and this is not the normal browser startup path.
249 Singleton<LinuxHostInit>::get();
250#endif
251
[email protected]d4515eb2009-01-30 00:40:43252 BrowserMain(params);
[email protected]5c5de8c2009-09-23 17:11:26253 TearDownInProcessBrowserTestFixture();
[email protected]d4515eb2009-01-30 00:40:43254}
255
[email protected]fc82ccf02010-10-15 18:12:47256bool InProcessBrowserTest::CreateUserDataDirectory() {
257 CommandLine* command_line = CommandLine::ForCurrentProcessMutable();
258 FilePath user_data_dir =
259 command_line->GetSwitchValuePath(switches::kUserDataDir);
260 if (user_data_dir.empty()) {
261 if (temp_user_data_dir_.CreateUniqueTempDir() &&
262 temp_user_data_dir_.IsValid()) {
263 user_data_dir = temp_user_data_dir_.path();
264 } else {
265 LOG(ERROR) << "Could not create temporary user data directory \""
266 << temp_user_data_dir_.path().value() << "\".";
267 return false;
268 }
269 }
270 return test_launcher_utils::OverrideUserDataDir(user_data_dir);
271}
272
[email protected]d4515eb2009-01-30 00:40:43273void InProcessBrowserTest::TearDown() {
274 // Reinstall testing browser process.
275 delete g_browser_process;
276 g_browser_process = new TestingBrowserProcess();
277
278 browser_shutdown::delete_resources_on_shutdown = true;
279
[email protected]eb1bd832010-05-18 20:39:58280#if defined(OS_WIN)
[email protected]d4515eb2009-01-30 00:40:43281 BrowserView::SetShowState(-1);
[email protected]108c2a12009-06-05 22:18:09282#endif
[email protected]56cdae32009-03-12 19:58:20283
284 *CommandLine::ForCurrentProcessMutable() = *original_command_line_;
285 RenderProcessHost::set_run_renderer_in_process(original_single_process_);
[email protected]d4515eb2009-01-30 00:40:43286}
287
[email protected]616381f02010-11-02 15:15:33288void InProcessBrowserTest::AddTabAtIndexToBrowser(
289 Browser* browser,
290 int index,
291 const GURL& url,
292 PageTransition::Type transition) {
293 browser::NavigateParams params(browser, url, transition);
294 params.tabstrip_index = index;
295 params.disposition = NEW_FOREGROUND_TAB;
296 browser::Navigate(&params);
297}
298
299void InProcessBrowserTest::AddTabAtIndex(
300 int index,
301 const GURL& url,
302 PageTransition::Type transition) {
303 AddTabAtIndexToBrowser(browser(), index, url, transition);
304}
305
[email protected]d4515eb2009-01-30 00:40:43306// Creates a browser with a single tab (about:blank), waits for the tab to
307// finish loading and shows the browser.
308Browser* InProcessBrowserTest::CreateBrowser(Profile* profile) {
309 Browser* browser = Browser::Create(profile);
[email protected]e1c10f182010-09-30 08:53:06310 InitializeBrowser(browser);
311 return browser;
312}
[email protected]d4515eb2009-01-30 00:40:43313
[email protected]e1c10f182010-09-30 08:53:06314Browser* InProcessBrowserTest::CreateBrowserForPopup(Profile* profile) {
[email protected]1b74d2122010-10-06 16:49:16315 Browser* browser = Browser::CreateForType(Browser::TYPE_POPUP, profile);
[email protected]e1c10f182010-09-30 08:53:06316 InitializeBrowser(browser);
[email protected]d4515eb2009-01-30 00:40:43317 return browser;
318}
319
[email protected]64f19312010-04-13 22:30:01320void InProcessBrowserTest::RunTestOnMainThreadLoop() {
[email protected]00d0ac22010-10-05 09:30:00321#if defined(OS_POSIX)
322 // Restore default signal handler for SIGTERM, so when the out-of-process
323 // test runner tries to terminate us, we don't catch it and possibly make it
324 // look like a success (http://crbug.com/57578).
325 signal(SIGTERM, SIG_DFL);
326#endif // defined(OS_POSIX)
327
[email protected]304a3172010-05-04 05:38:44328 // On Mac, without the following autorelease pool, code which is directly
329 // executed (as opposed to executed inside a message loop) would autorelease
330 // objects into a higher-level pool. This pool is not recycled in-sync with
331 // the message loops' pools and causes problems with code relying on
332 // deallocation via an autorelease pool (such as browser window closure and
333 // browser shutdown). To avoid this, the following pool is recycled after each
334 // time code is directly executed.
[email protected]c2818d42010-10-18 02:47:39335 base::mac::ScopedNSAutoreleasePool pool;
[email protected]304a3172010-05-04 05:38:44336
[email protected]64f19312010-04-13 22:30:01337 // Pump startup related events.
338 MessageLoopForUI::current()->RunAllPending();
339
340 // In the long term it would be great if we could use a TestingProfile
341 // here and only enable services you want tested, but that requires all
342 // consumers of Profile to handle NULL services.
343 Profile* profile = ProfileManager::GetDefaultProfile();
344 if (!profile) {
345 // We should only be able to get here if the profile already exists and
346 // has been created.
347 NOTREACHED();
348 return;
349 }
[email protected]304a3172010-05-04 05:38:44350 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01351
[email protected]0c7d74f2010-10-11 11:55:26352 BrowserThread::PostTask(
353 BrowserThread::IO, FROM_HERE,
[email protected]64f19312010-04-13 22:30:01354 NewRunnableFunction(chrome_browser_net::SetUrlRequestMocksEnabled, true));
355
356 browser_ = CreateBrowser(profile);
[email protected]304a3172010-05-04 05:38:44357 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01358
[email protected]64f19312010-04-13 22:30:01359 // Pump any pending events that were created as a result of creating a
360 // browser.
361 MessageLoopForUI::current()->RunAllPending();
362
363 RunTestOnMainThread();
[email protected]304a3172010-05-04 05:38:44364 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01365
366 CleanUpOnMainThread();
[email protected]304a3172010-05-04 05:38:44367 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01368
369 QuitBrowsers();
[email protected]304a3172010-05-04 05:38:44370 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01371}
372
373void InProcessBrowserTest::QuitBrowsers() {
374 if (BrowserList::size() == 0)
375 return;
376
377 // Invoke CloseAllBrowsersAndExit on a running message loop.
378 // CloseAllBrowsersAndExit exits the message loop after everything has been
379 // shut down properly.
380 MessageLoopForUI::current()->PostTask(
381 FROM_HERE,
382 NewRunnableFunction(&BrowserList::CloseAllBrowsersAndExit));
383 ui_test_utils::RunMessageLoop();
384}