blob: 9fed5227ca310859046a1684dd531d3f2a168e09 [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]06cc083a2011-03-01 02:28:4277 tab_closeable_state_watcher_enabled_(false) {
[email protected]7fac8882010-11-15 19:52:5278#if defined(OS_MACOSX)
[email protected]0378bf42011-01-01 18:20:1479 base::mac::SetOverrideAmIBundled(true);
[email protected]7fac8882010-11-15 19:52:5280#endif
81
82 // Before we run the browser, we have to hack the path to the exe to match
83 // what it would be if Chrome was running, because it is used to fork renderer
84 // processes, on Linux at least (failure to do so will cause a browser_test to
85 // be run instead of a renderer).
86 FilePath chrome_path;
87 CHECK(PathService::Get(base::FILE_EXE, &chrome_path));
88 chrome_path = chrome_path.DirName();
[email protected]7fac8882010-11-15 19:52:5289 chrome_path = chrome_path.Append(chrome::kBrowserProcessExecutablePath);
[email protected]7fac8882010-11-15 19:52:5290 CHECK(PathService::Override(base::FILE_EXE, chrome_path));
91
92 test_server_.reset(new net::TestServer(
93 net::TestServer::TYPE_HTTP,
94 FilePath(FILE_PATH_LITERAL("chrome/test/data"))));
[email protected]d4515eb2009-01-30 00:40:4395}
96
[email protected]c4ff4952010-01-08 19:12:4797InProcessBrowserTest::~InProcessBrowserTest() {
98}
99
[email protected]d4515eb2009-01-30 00:40:43100void InProcessBrowserTest::SetUp() {
[email protected]fc82ccf02010-10-15 18:12:47101 // Create a temporary user data directory if required.
102 ASSERT_TRUE(CreateUserDataDirectory())
103 << "Could not create user data directory.";
[email protected]4a44bc32010-05-28 22:22:44104
[email protected]d4515eb2009-01-30 00:40:43105 // The unit test suite creates a testingbrowser, but we want the real thing.
106 // Delete the current one. We'll install the testing one in TearDown.
107 delete g_browser_process;
[email protected]298883bc2010-04-30 14:50:58108 g_browser_process = NULL;
109
[email protected]470f7a52010-09-23 20:20:38110 // Allow subclasses the opportunity to make changes to the default user data
111 // dir before running any tests.
[email protected]fc82ccf02010-10-15 18:12:47112 ASSERT_TRUE(SetUpUserDataDirectory())
113 << "Could not set up user data directory.";
[email protected]d4515eb2009-01-30 00:40:43114
115 // Don't delete the resources when BrowserMain returns. Many ui classes
116 // cache SkBitmaps in a static field so that if we delete the resource
117 // bundle we'll crash.
118 browser_shutdown::delete_resources_on_shutdown = false;
119
[email protected]06cc083a2011-03-01 02:28:42120 CommandLine* command_line = CommandLine::ForCurrentProcess();
121 // Allow subclasses to change the command line before running any tests.
[email protected]9665fa62009-04-13 22:15:29122 SetUpCommandLine(command_line);
[email protected]03c79d502010-11-16 00:38:26123 // Add command line arguments that are used by all InProcessBrowserTests.
124 PrepareTestCommandLine(command_line);
[email protected]9665fa62009-04-13 22:15:29125
[email protected]06cc083a2011-03-01 02:28:42126 // Single-process mode is not set in BrowserMain, so process it explicitly.
[email protected]8bcdec92009-02-25 16:15:18127 if (command_line->HasSwitch(switches::kSingleProcess))
128 RenderProcessHost::set_run_renderer_in_process(true);
129
[email protected]02dbca0b2010-09-17 07:44:10130#if defined(OS_CHROMEOS)
[email protected]0750b1442010-11-02 21:59:37131 // Make sure that the log directory exists.
132 FilePath log_dir = logging::GetSessionLogFile(*command_line).DirName();
133 file_util::CreateDirectory(log_dir);
[email protected]02dbca0b2010-09-17 07:44:10134#endif // defined(OS_CHROMEOS)
135
[email protected]d4515eb2009-01-30 00:40:43136 SandboxInitWrapper sandbox_wrapper;
[email protected]7c321082009-02-09 15:35:47137 MainFunctionParams params(*command_line, sandbox_wrapper, NULL);
[email protected]d4515eb2009-01-30 00:40:43138 params.ui_task =
139 NewRunnableMethod(this, &InProcessBrowserTest::RunTestOnMainThreadLoop);
[email protected]13324ed2009-04-03 05:14:19140
[email protected]c4ff4952010-01-08 19:12:47141 host_resolver_ = new net::RuleBasedHostResolverProc(
142 new IntranetRedirectHostResolverProc(NULL));
[email protected]c7ad50f2009-09-11 06:28:15143
144 // Something inside the browser does this lookup implicitly. Make it fail
145 // to avoid external dependency. It won't break the tests.
146 host_resolver_->AddSimulatedFailure("*.google.com");
147
148 // See http://en.wikipedia.org/wiki/Web_Proxy_Autodiscovery_Protocol
149 // We don't want the test code to use it.
150 host_resolver_->AddSimulatedFailure("wpad");
151
[email protected]b59ff372009-07-15 22:04:32152 net::ScopedDefaultHostResolverProc scoped_host_resolver_proc(
[email protected]c7ad50f2009-09-11 06:28:15153 host_resolver_.get());
[email protected]5c5de8c2009-09-23 17:11:26154
155 SetUpInProcessBrowserTestFixture();
[email protected]60a782e2010-02-24 22:41:35156
[email protected]d4515eb2009-01-30 00:40:43157 BrowserMain(params);
[email protected]5c5de8c2009-09-23 17:11:26158 TearDownInProcessBrowserTestFixture();
[email protected]d4515eb2009-01-30 00:40:43159}
160
[email protected]06cc083a2011-03-01 02:28:42161void InProcessBrowserTest::PrepareTestCommandLine(CommandLine* command_line) {
[email protected]03c79d502010-11-16 00:38:26162 // Propagate commandline settings from test_launcher_utils.
163 test_launcher_utils::PrepareBrowserCommandLineForTests(command_line);
164
165#if defined(OS_WIN)
166 // Hide windows on show.
167 if (!command_line->HasSwitch(kUnitTestShowWindows) && !show_window_)
168 BrowserView::SetShowState(SW_HIDE);
169#endif
170
171 if (dom_automation_enabled_)
172 command_line->AppendSwitch(switches::kDomAutomationController);
173
174 // This is a Browser test.
175 command_line->AppendSwitchASCII(switches::kTestType, kBrowserTestType);
176
177#if defined(OS_WIN)
178 // The Windows sandbox requires that the browser and child processes are the
179 // same binary. So we launch browser_process.exe which loads chrome.dll
180 command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
181 command_line->GetProgram());
182#else
183 // Explicitly set the path of the binary used for child processes, otherwise
184 // they'll try to use browser_tests which doesn't contain ChromeMain.
185 FilePath subprocess_path;
186 PathService::Get(base::FILE_EXE, &subprocess_path);
187#if defined(OS_MACOSX)
188 // Recreate the real environment, run the helper within the app bundle.
189 subprocess_path = subprocess_path.DirName().DirName();
190 DCHECK_EQ(subprocess_path.BaseName().value(), "Contents");
191 subprocess_path =
192 subprocess_path.Append("Versions").Append(chrome::kChromeVersion);
193 subprocess_path =
194 subprocess_path.Append(chrome::kHelperProcessExecutablePath);
195#endif
196 command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
197 subprocess_path);
198#endif
199
[email protected]7c8b20672011-02-11 21:18:01200 // If neccessary, disable TabCloseableStateWatcher.
[email protected]03c79d502010-11-16 00:38:26201 if (!tab_closeable_state_watcher_enabled_)
202 command_line->AppendSwitch(switches::kDisableTabCloseableStateWatcher);
203}
204
[email protected]fc82ccf02010-10-15 18:12:47205bool InProcessBrowserTest::CreateUserDataDirectory() {
[email protected]06cc083a2011-03-01 02:28:42206 CommandLine* command_line = CommandLine::ForCurrentProcess();
[email protected]fc82ccf02010-10-15 18:12:47207 FilePath user_data_dir =
208 command_line->GetSwitchValuePath(switches::kUserDataDir);
209 if (user_data_dir.empty()) {
210 if (temp_user_data_dir_.CreateUniqueTempDir() &&
211 temp_user_data_dir_.IsValid()) {
212 user_data_dir = temp_user_data_dir_.path();
213 } else {
214 LOG(ERROR) << "Could not create temporary user data directory \""
215 << temp_user_data_dir_.path().value() << "\".";
216 return false;
217 }
218 }
219 return test_launcher_utils::OverrideUserDataDir(user_data_dir);
220}
221
[email protected]d4515eb2009-01-30 00:40:43222void InProcessBrowserTest::TearDown() {
223 // Reinstall testing browser process.
224 delete g_browser_process;
225 g_browser_process = new TestingBrowserProcess();
226
227 browser_shutdown::delete_resources_on_shutdown = true;
228
[email protected]eb1bd832010-05-18 20:39:58229#if defined(OS_WIN)
[email protected]d4515eb2009-01-30 00:40:43230 BrowserView::SetShowState(-1);
[email protected]108c2a12009-06-05 22:18:09231#endif
[email protected]d4515eb2009-01-30 00:40:43232}
233
[email protected]616381f02010-11-02 15:15:33234void InProcessBrowserTest::AddTabAtIndexToBrowser(
235 Browser* browser,
236 int index,
237 const GURL& url,
238 PageTransition::Type transition) {
239 browser::NavigateParams params(browser, url, transition);
240 params.tabstrip_index = index;
241 params.disposition = NEW_FOREGROUND_TAB;
242 browser::Navigate(&params);
243}
244
245void InProcessBrowserTest::AddTabAtIndex(
246 int index,
247 const GURL& url,
248 PageTransition::Type transition) {
249 AddTabAtIndexToBrowser(browser(), index, url, transition);
250}
251
[email protected]fadc607b62011-02-07 17:55:50252bool InProcessBrowserTest::SetUpUserDataDirectory() {
253 return true;
254}
255
[email protected]d4515eb2009-01-30 00:40:43256// Creates a browser with a single tab (about:blank), waits for the tab to
257// finish loading and shows the browser.
258Browser* InProcessBrowserTest::CreateBrowser(Profile* profile) {
259 Browser* browser = Browser::Create(profile);
[email protected]e1c10f182010-09-30 08:53:06260 InitializeBrowser(browser);
261 return browser;
262}
[email protected]d4515eb2009-01-30 00:40:43263
[email protected]46f979d2011-01-10 17:08:44264Browser* InProcessBrowserTest::CreateIncognitoBrowser() {
265 // Create a new browser with using the incognito profile.
266 Browser* incognito =
267 Browser::Create(browser()->profile()->GetOffTheRecordProfile());
268 InitializeBrowser(incognito);
269 return incognito;
270}
271
[email protected]e1c10f182010-09-30 08:53:06272Browser* InProcessBrowserTest::CreateBrowserForPopup(Profile* profile) {
[email protected]1b74d2122010-10-06 16:49:16273 Browser* browser = Browser::CreateForType(Browser::TYPE_POPUP, profile);
[email protected]e1c10f182010-09-30 08:53:06274 InitializeBrowser(browser);
[email protected]d4515eb2009-01-30 00:40:43275 return browser;
276}
277
[email protected]64f19312010-04-13 22:30:01278void InProcessBrowserTest::RunTestOnMainThreadLoop() {
[email protected]00d0ac22010-10-05 09:30:00279#if defined(OS_POSIX)
280 // Restore default signal handler for SIGTERM, so when the out-of-process
281 // test runner tries to terminate us, we don't catch it and possibly make it
282 // look like a success (http://crbug.com/57578).
283 signal(SIGTERM, SIG_DFL);
284#endif // defined(OS_POSIX)
285
[email protected]304a3172010-05-04 05:38:44286 // On Mac, without the following autorelease pool, code which is directly
287 // executed (as opposed to executed inside a message loop) would autorelease
288 // objects into a higher-level pool. This pool is not recycled in-sync with
289 // the message loops' pools and causes problems with code relying on
290 // deallocation via an autorelease pool (such as browser window closure and
291 // browser shutdown). To avoid this, the following pool is recycled after each
292 // time code is directly executed.
[email protected]c2818d42010-10-18 02:47:39293 base::mac::ScopedNSAutoreleasePool pool;
[email protected]304a3172010-05-04 05:38:44294
[email protected]64f19312010-04-13 22:30:01295 // Pump startup related events.
296 MessageLoopForUI::current()->RunAllPending();
297
298 // In the long term it would be great if we could use a TestingProfile
299 // here and only enable services you want tested, but that requires all
300 // consumers of Profile to handle NULL services.
301 Profile* profile = ProfileManager::GetDefaultProfile();
302 if (!profile) {
303 // We should only be able to get here if the profile already exists and
304 // has been created.
305 NOTREACHED();
306 return;
307 }
[email protected]304a3172010-05-04 05:38:44308 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01309
[email protected]0c7d74f2010-10-11 11:55:26310 BrowserThread::PostTask(
311 BrowserThread::IO, FROM_HERE,
[email protected]64f19312010-04-13 22:30:01312 NewRunnableFunction(chrome_browser_net::SetUrlRequestMocksEnabled, true));
313
314 browser_ = CreateBrowser(profile);
[email protected]304a3172010-05-04 05:38:44315 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01316
[email protected]64f19312010-04-13 22:30:01317 // Pump any pending events that were created as a result of creating a
318 // browser.
319 MessageLoopForUI::current()->RunAllPending();
320
[email protected]28dabab72011-01-05 03:31:26321 SetUpOnMainThread();
322 pool.Recycle();
323
[email protected]64f19312010-04-13 22:30:01324 RunTestOnMainThread();
[email protected]304a3172010-05-04 05:38:44325 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01326
327 CleanUpOnMainThread();
[email protected]304a3172010-05-04 05:38:44328 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01329
330 QuitBrowsers();
[email protected]304a3172010-05-04 05:38:44331 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01332}
333
334void InProcessBrowserTest::QuitBrowsers() {
335 if (BrowserList::size() == 0)
336 return;
337
338 // Invoke CloseAllBrowsersAndExit on a running message loop.
339 // CloseAllBrowsersAndExit exits the message loop after everything has been
340 // shut down properly.
341 MessageLoopForUI::current()->PostTask(
342 FROM_HERE,
343 NewRunnableFunction(&BrowserList::CloseAllBrowsersAndExit));
344 ui_test_utils::RunMessageLoop();
345}