blob: 45cb676e6b67ffae68714d2b3795c41f514f01c3 [file] [log] [blame]
[email protected]9e790bd2011-01-10 23:48:541// Copyright (c) 2011 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"
[email protected]c2818d42010-10-18 02:47:3910#include "base/mac/scoped_nsautorelease_pool.h"
[email protected]d4515eb2009-01-30 00:40:4311#include "base/path_service.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]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]8281e48e2010-10-12 18:54:4917#include "chrome/browser/browser_thread.h"
[email protected]108c2a12009-06-05 22:18:0918#include "chrome/browser/browser_window.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]8ecad5e2010-12-02 21:18:3322#include "chrome/browser/profiles/profile.h"
23#include "chrome/browser/profiles/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]c848d3d92010-09-16 21:57:4526#include "chrome/browser/tabs/tab_strip_model.h"
[email protected]f46be6e2010-11-16 03:52:3227#include "chrome/browser/ui/browser.h"
[email protected]339d6dd2010-11-12 00:41:5828#include "chrome/browser/ui/browser_navigator.h"
[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"
[email protected]0750b1442010-11-02 21:59:3732#include "chrome/common/logging_chrome.h"
[email protected]d4515eb2009-01-30 00:40:4333#include "chrome/common/main_function_params.h"
[email protected]ad1f9bd2009-07-30 20:23:1534#include "chrome/common/notification_type.h"
[email protected]e0d481582009-09-15 21:06:2535#include "chrome/common/url_constants.h"
[email protected]470f7a52010-09-23 20:20:3836#include "chrome/test/test_launcher_utils.h"
[email protected]d4515eb2009-01-30 00:40:4337#include "chrome/test/testing_browser_process.h"
38#include "chrome/test/ui_test_utils.h"
[email protected]c4ff4952010-01-08 19:12:4739#include "net/base/mock_host_resolver.h"
[email protected]3985ba82010-07-29 21:44:1240#include "net/test/test_server.h"
[email protected]d4515eb2009-01-30 00:40:4341#include "sandbox/src/dep.h"
42
[email protected]7fac8882010-11-15 19:52:5243#if defined(OS_MACOSX)
[email protected]0378bf42011-01-01 18:20:1444#include "base/mac/mac_util.h"
[email protected]7fac8882010-11-15 19:52:5245#endif
46
47#if defined(OS_WIN)
[email protected]9e790bd2011-01-10 23:48:5448#include "chrome/browser/ui/views/frame/browser_view.h"
[email protected]7fac8882010-11-15 19:52:5249#endif
50
[email protected]e1c10f182010-09-30 08:53:0651namespace {
52
53void InitializeBrowser(Browser* browser) {
[email protected]cecc93a2010-10-05 15:58:5554 browser->AddSelectedTabWithURL(GURL(chrome::kAboutBlankURL),
55 PageTransition::START_PAGE);
[email protected]e1c10f182010-09-30 08:53:0656
57 // Wait for the page to finish loading.
58 ui_test_utils::WaitForNavigation(
59 &browser->GetSelectedTabContents()->controller());
60
61 browser->window()->Show();
62}
63
64} // namespace
65
[email protected]d4515eb2009-01-30 00:40:4366extern int BrowserMain(const MainFunctionParams&);
67
[email protected]711a3532010-12-08 22:18:3768const char kUnitTestShowWindows[] = "show-windows";
[email protected]d4515eb2009-01-30 00:40:4369
[email protected]ddf8a4b02010-03-22 23:08:3070// Passed as value of kTestType.
71static const char kBrowserTestType[] = "browser";
72
[email protected]8bcdec92009-02-25 16:15:1873InProcessBrowserTest::InProcessBrowserTest()
74 : browser_(NULL),
75 show_window_(false),
[email protected]56cdae32009-03-12 19:58:2076 dom_automation_enabled_(false),
[email protected]0b4d3382010-07-14 16:13:0477 tab_closeable_state_watcher_enabled_(false),
[email protected]4b614a62010-10-06 15:33:1078 original_single_process_(false) {
[email protected]7fac8882010-11-15 19:52:5279#if defined(OS_MACOSX)
[email protected]0378bf42011-01-01 18:20:1480 base::mac::SetOverrideAmIBundled(true);
[email protected]7fac8882010-11-15 19:52:5281#endif
82
83 // Before we run the browser, we have to hack the path to the exe to match
84 // what it would be if Chrome was running, because it is used to fork renderer
85 // processes, on Linux at least (failure to do so will cause a browser_test to
86 // be run instead of a renderer).
87 FilePath chrome_path;
88 CHECK(PathService::Get(base::FILE_EXE, &chrome_path));
89 chrome_path = chrome_path.DirName();
[email protected]7fac8882010-11-15 19:52:5290 chrome_path = chrome_path.Append(chrome::kBrowserProcessExecutablePath);
[email protected]7fac8882010-11-15 19:52:5291 CHECK(PathService::Override(base::FILE_EXE, chrome_path));
92
93 test_server_.reset(new net::TestServer(
94 net::TestServer::TYPE_HTTP,
95 FilePath(FILE_PATH_LITERAL("chrome/test/data"))));
[email protected]d4515eb2009-01-30 00:40:4396}
97
[email protected]c4ff4952010-01-08 19:12:4798InProcessBrowserTest::~InProcessBrowserTest() {
99}
100
[email protected]d4515eb2009-01-30 00:40:43101void InProcessBrowserTest::SetUp() {
[email protected]470f7a52010-09-23 20:20:38102 // Remember the command line. Normally this doesn't matter, because the test
103 // harness creates a new process for each test, but when the test harness is
104 // running in single process mode, we can't let one test's command-line
105 // changes (e.g. enabling DOM automation) affect other tests.
106 // TODO(phajdan.jr): This save/restore logic is unnecessary. Remove it.
107 CommandLine* command_line = CommandLine::ForCurrentProcessMutable();
108 original_command_line_.reset(new CommandLine(*command_line));
[email protected]d4515eb2009-01-30 00:40:43109
[email protected]fc82ccf02010-10-15 18:12:47110 // Create a temporary user data directory if required.
111 ASSERT_TRUE(CreateUserDataDirectory())
112 << "Could not create user data directory.";
[email protected]4a44bc32010-05-28 22:22:44113
[email protected]d4515eb2009-01-30 00:40:43114 // The unit test suite creates a testingbrowser, but we want the real thing.
115 // Delete the current one. We'll install the testing one in TearDown.
116 delete g_browser_process;
[email protected]298883bc2010-04-30 14:50:58117 g_browser_process = NULL;
118
[email protected]470f7a52010-09-23 20:20:38119 // Allow subclasses the opportunity to make changes to the default user data
120 // dir before running any tests.
[email protected]fc82ccf02010-10-15 18:12:47121 ASSERT_TRUE(SetUpUserDataDirectory())
122 << "Could not set up user data directory.";
[email protected]d4515eb2009-01-30 00:40:43123
124 // Don't delete the resources when BrowserMain returns. Many ui classes
125 // cache SkBitmaps in a static field so that if we delete the resource
126 // bundle we'll crash.
127 browser_shutdown::delete_resources_on_shutdown = false;
128
[email protected]470f7a52010-09-23 20:20:38129 // Allow subclasses the opportunity to make changes to the command line before
130 // running any tests.
[email protected]9665fa62009-04-13 22:15:29131 SetUpCommandLine(command_line);
[email protected]03c79d502010-11-16 00:38:26132 // Add command line arguments that are used by all InProcessBrowserTests.
133 PrepareTestCommandLine(command_line);
[email protected]9665fa62009-04-13 22:15:29134
[email protected]03c79d502010-11-16 00:38:26135 // Save the single process mode state before it was reset in this test. This
136 // state will be recovered in TearDown(). Single-process mode is not set in
137 // BrowserMain so it needs to be processed explicitly.
[email protected]56cdae32009-03-12 19:58:20138 original_single_process_ = RenderProcessHost::run_renderer_in_process();
[email protected]8bcdec92009-02-25 16:15:18139 if (command_line->HasSwitch(switches::kSingleProcess))
140 RenderProcessHost::set_run_renderer_in_process(true);
141
[email protected]02dbca0b2010-09-17 07:44:10142#if defined(OS_CHROMEOS)
[email protected]0750b1442010-11-02 21:59:37143 // Make sure that the log directory exists.
144 FilePath log_dir = logging::GetSessionLogFile(*command_line).DirName();
145 file_util::CreateDirectory(log_dir);
[email protected]02dbca0b2010-09-17 07:44:10146#endif // defined(OS_CHROMEOS)
147
[email protected]d4515eb2009-01-30 00:40:43148 SandboxInitWrapper sandbox_wrapper;
[email protected]7c321082009-02-09 15:35:47149 MainFunctionParams params(*command_line, sandbox_wrapper, NULL);
[email protected]d4515eb2009-01-30 00:40:43150 params.ui_task =
151 NewRunnableMethod(this, &InProcessBrowserTest::RunTestOnMainThreadLoop);
[email protected]13324ed2009-04-03 05:14:19152
[email protected]c4ff4952010-01-08 19:12:47153 host_resolver_ = new net::RuleBasedHostResolverProc(
154 new IntranetRedirectHostResolverProc(NULL));
[email protected]c7ad50f2009-09-11 06:28:15155
156 // Something inside the browser does this lookup implicitly. Make it fail
157 // to avoid external dependency. It won't break the tests.
158 host_resolver_->AddSimulatedFailure("*.google.com");
159
160 // See http://en.wikipedia.org/wiki/Web_Proxy_Autodiscovery_Protocol
161 // We don't want the test code to use it.
162 host_resolver_->AddSimulatedFailure("wpad");
163
[email protected]b59ff372009-07-15 22:04:32164 net::ScopedDefaultHostResolverProc scoped_host_resolver_proc(
[email protected]c7ad50f2009-09-11 06:28:15165 host_resolver_.get());
[email protected]5c5de8c2009-09-23 17:11:26166
167 SetUpInProcessBrowserTestFixture();
[email protected]60a782e2010-02-24 22:41:35168
[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
[email protected]03c79d502010-11-16 00:38:26173void InProcessBrowserTest::PrepareTestCommandLine(
174 CommandLine* command_line) {
175 // Propagate commandline settings from test_launcher_utils.
176 test_launcher_utils::PrepareBrowserCommandLineForTests(command_line);
177
178#if defined(OS_WIN)
179 // Hide windows on show.
180 if (!command_line->HasSwitch(kUnitTestShowWindows) && !show_window_)
181 BrowserView::SetShowState(SW_HIDE);
182#endif
183
184 if (dom_automation_enabled_)
185 command_line->AppendSwitch(switches::kDomAutomationController);
186
187 // This is a Browser test.
188 command_line->AppendSwitchASCII(switches::kTestType, kBrowserTestType);
189
190#if defined(OS_WIN)
191 // The Windows sandbox requires that the browser and child processes are the
192 // same binary. So we launch browser_process.exe which loads chrome.dll
193 command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
194 command_line->GetProgram());
195#else
196 // Explicitly set the path of the binary used for child processes, otherwise
197 // they'll try to use browser_tests which doesn't contain ChromeMain.
198 FilePath subprocess_path;
199 PathService::Get(base::FILE_EXE, &subprocess_path);
200#if defined(OS_MACOSX)
201 // Recreate the real environment, run the helper within the app bundle.
202 subprocess_path = subprocess_path.DirName().DirName();
203 DCHECK_EQ(subprocess_path.BaseName().value(), "Contents");
204 subprocess_path =
205 subprocess_path.Append("Versions").Append(chrome::kChromeVersion);
206 subprocess_path =
207 subprocess_path.Append(chrome::kHelperProcessExecutablePath);
208#endif
209 command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
210 subprocess_path);
211#endif
212
[email protected]7c8b20672011-02-11 21:18:01213 // If neccessary, disable TabCloseableStateWatcher.
[email protected]03c79d502010-11-16 00:38:26214 if (!tab_closeable_state_watcher_enabled_)
215 command_line->AppendSwitch(switches::kDisableTabCloseableStateWatcher);
216}
217
[email protected]fc82ccf02010-10-15 18:12:47218bool InProcessBrowserTest::CreateUserDataDirectory() {
219 CommandLine* command_line = CommandLine::ForCurrentProcessMutable();
220 FilePath user_data_dir =
221 command_line->GetSwitchValuePath(switches::kUserDataDir);
222 if (user_data_dir.empty()) {
223 if (temp_user_data_dir_.CreateUniqueTempDir() &&
224 temp_user_data_dir_.IsValid()) {
225 user_data_dir = temp_user_data_dir_.path();
226 } else {
227 LOG(ERROR) << "Could not create temporary user data directory \""
228 << temp_user_data_dir_.path().value() << "\".";
229 return false;
230 }
231 }
232 return test_launcher_utils::OverrideUserDataDir(user_data_dir);
233}
234
[email protected]d4515eb2009-01-30 00:40:43235void InProcessBrowserTest::TearDown() {
236 // Reinstall testing browser process.
237 delete g_browser_process;
238 g_browser_process = new TestingBrowserProcess();
239
240 browser_shutdown::delete_resources_on_shutdown = true;
241
[email protected]eb1bd832010-05-18 20:39:58242#if defined(OS_WIN)
[email protected]d4515eb2009-01-30 00:40:43243 BrowserView::SetShowState(-1);
[email protected]108c2a12009-06-05 22:18:09244#endif
[email protected]56cdae32009-03-12 19:58:20245
246 *CommandLine::ForCurrentProcessMutable() = *original_command_line_;
247 RenderProcessHost::set_run_renderer_in_process(original_single_process_);
[email protected]d4515eb2009-01-30 00:40:43248}
249
[email protected]616381f02010-11-02 15:15:33250void InProcessBrowserTest::AddTabAtIndexToBrowser(
251 Browser* browser,
252 int index,
253 const GURL& url,
254 PageTransition::Type transition) {
255 browser::NavigateParams params(browser, url, transition);
256 params.tabstrip_index = index;
257 params.disposition = NEW_FOREGROUND_TAB;
258 browser::Navigate(&params);
259}
260
261void InProcessBrowserTest::AddTabAtIndex(
262 int index,
263 const GURL& url,
264 PageTransition::Type transition) {
265 AddTabAtIndexToBrowser(browser(), index, url, transition);
266}
267
[email protected]fadc607b62011-02-07 17:55:50268bool InProcessBrowserTest::SetUpUserDataDirectory() {
269 return true;
270}
271
[email protected]d4515eb2009-01-30 00:40:43272// Creates a browser with a single tab (about:blank), waits for the tab to
273// finish loading and shows the browser.
274Browser* InProcessBrowserTest::CreateBrowser(Profile* profile) {
275 Browser* browser = Browser::Create(profile);
[email protected]e1c10f182010-09-30 08:53:06276 InitializeBrowser(browser);
277 return browser;
278}
[email protected]d4515eb2009-01-30 00:40:43279
[email protected]46f979d2011-01-10 17:08:44280Browser* InProcessBrowserTest::CreateIncognitoBrowser() {
281 // Create a new browser with using the incognito profile.
282 Browser* incognito =
283 Browser::Create(browser()->profile()->GetOffTheRecordProfile());
284 InitializeBrowser(incognito);
285 return incognito;
286}
287
[email protected]e1c10f182010-09-30 08:53:06288Browser* InProcessBrowserTest::CreateBrowserForPopup(Profile* profile) {
[email protected]1b74d2122010-10-06 16:49:16289 Browser* browser = Browser::CreateForType(Browser::TYPE_POPUP, profile);
[email protected]e1c10f182010-09-30 08:53:06290 InitializeBrowser(browser);
[email protected]d4515eb2009-01-30 00:40:43291 return browser;
292}
293
[email protected]64f19312010-04-13 22:30:01294void InProcessBrowserTest::RunTestOnMainThreadLoop() {
[email protected]00d0ac22010-10-05 09:30:00295#if defined(OS_POSIX)
296 // Restore default signal handler for SIGTERM, so when the out-of-process
297 // test runner tries to terminate us, we don't catch it and possibly make it
298 // look like a success (http://crbug.com/57578).
299 signal(SIGTERM, SIG_DFL);
300#endif // defined(OS_POSIX)
301
[email protected]304a3172010-05-04 05:38:44302 // On Mac, without the following autorelease pool, code which is directly
303 // executed (as opposed to executed inside a message loop) would autorelease
304 // objects into a higher-level pool. This pool is not recycled in-sync with
305 // the message loops' pools and causes problems with code relying on
306 // deallocation via an autorelease pool (such as browser window closure and
307 // browser shutdown). To avoid this, the following pool is recycled after each
308 // time code is directly executed.
[email protected]c2818d42010-10-18 02:47:39309 base::mac::ScopedNSAutoreleasePool pool;
[email protected]304a3172010-05-04 05:38:44310
[email protected]64f19312010-04-13 22:30:01311 // 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 }
[email protected]304a3172010-05-04 05:38:44324 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01325
[email protected]0c7d74f2010-10-11 11:55:26326 BrowserThread::PostTask(
327 BrowserThread::IO, FROM_HERE,
[email protected]64f19312010-04-13 22:30:01328 NewRunnableFunction(chrome_browser_net::SetUrlRequestMocksEnabled, true));
329
330 browser_ = CreateBrowser(profile);
[email protected]304a3172010-05-04 05:38:44331 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01332
[email protected]64f19312010-04-13 22:30:01333 // Pump any pending events that were created as a result of creating a
334 // browser.
335 MessageLoopForUI::current()->RunAllPending();
336
[email protected]28dabab72011-01-05 03:31:26337 SetUpOnMainThread();
338 pool.Recycle();
339
[email protected]64f19312010-04-13 22:30:01340 RunTestOnMainThread();
[email protected]304a3172010-05-04 05:38:44341 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01342
343 CleanUpOnMainThread();
[email protected]304a3172010-05-04 05:38:44344 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01345
346 QuitBrowsers();
[email protected]304a3172010-05-04 05:38:44347 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01348}
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}