blob: 08dd200ed67faa68ef14d97712f37499c089cbd0 [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]d4515eb2009-01-30 00:40:437#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]d4515eb2009-01-30 00:40:4314#include "chrome/browser/browser.h"
[email protected]b6e38ef2009-06-16 00:43:2315#include "chrome/browser/browser_list.h"
[email protected]d4515eb2009-01-30 00:40:4316#include "chrome/browser/browser_process.h"
17#include "chrome/browser/browser_shutdown.h"
[email protected]8281e48e2010-10-12 18:54:4918#include "chrome/browser/browser_thread.h"
[email protected]108c2a12009-06-05 22:18:0919#include "chrome/browser/browser_window.h"
[email protected]c4ff4952010-01-08 19:12:4720#include "chrome/browser/intranet_redirect_detector.h"
[email protected]0ac83682010-01-22 17:46:2721#include "chrome/browser/io_thread.h"
[email protected]cec4a272009-07-31 21:55:0322#include "chrome/browser/net/url_request_mock_util.h"
[email protected]d4515eb2009-01-30 00:40:4323#include "chrome/browser/profile.h"
24#include "chrome/browser/profile_manager.h"
[email protected]8bcdec92009-02-25 16:15:1825#include "chrome/browser/renderer_host/render_process_host.h"
[email protected]5c238752009-06-13 10:29:0726#include "chrome/browser/tab_contents/tab_contents.h"
[email protected]c848d3d92010-09-16 21:57:4527#include "chrome/browser/tabs/tab_strip_model.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_registrar.h"
35#include "chrome/common/notification_type.h"
[email protected]e0d481582009-09-15 21:06:2536#include "chrome/common/url_constants.h"
[email protected]470f7a52010-09-23 20:20:3837#include "chrome/test/test_launcher_utils.h"
[email protected]d4515eb2009-01-30 00:40:4338#include "chrome/test/testing_browser_process.h"
39#include "chrome/test/ui_test_utils.h"
[email protected]c4ff4952010-01-08 19:12:4740#include "net/base/mock_host_resolver.h"
[email protected]3985ba82010-07-29 21:44:1241#include "net/test/test_server.h"
[email protected]d4515eb2009-01-30 00:40:4342#include "sandbox/src/dep.h"
43
[email protected]02dbca0b2010-09-17 07:44:1044#if defined(OS_CHROMEOS)
45#include "chrome/browser/chromeos/cros/cros_library.h"
46#endif // defined(OS_CHROMEOS)
47
[email protected]7fac8882010-11-15 19:52:5248#if defined(OS_MACOSX)
49#include "base/mac_util.h"
50#endif
51
52#if defined(OS_WIN)
53#include "chrome/browser/views/frame/browser_view.h"
54#endif
55
[email protected]e1c10f182010-09-30 08:53:0656namespace {
57
58void InitializeBrowser(Browser* browser) {
[email protected]cecc93a2010-10-05 15:58:5559 browser->AddSelectedTabWithURL(GURL(chrome::kAboutBlankURL),
60 PageTransition::START_PAGE);
[email protected]e1c10f182010-09-30 08:53:0661
62 // Wait for the page to finish loading.
63 ui_test_utils::WaitForNavigation(
64 &browser->GetSelectedTabContents()->controller());
65
66 browser->window()->Show();
67}
68
69} // namespace
70
[email protected]d4515eb2009-01-30 00:40:4371extern int BrowserMain(const MainFunctionParams&);
72
73const wchar_t kUnitTestShowWindows[] = L"show-windows";
74
[email protected]ddf8a4b02010-03-22 23:08:3075// Passed as value of kTestType.
76static const char kBrowserTestType[] = "browser";
77
[email protected]8bcdec92009-02-25 16:15:1878InProcessBrowserTest::InProcessBrowserTest()
79 : browser_(NULL),
[email protected]8bcdec92009-02-25 16:15:1880 show_window_(false),
[email protected]56cdae32009-03-12 19:58:2081 dom_automation_enabled_(false),
[email protected]0b4d3382010-07-14 16:13:0482 tab_closeable_state_watcher_enabled_(false),
[email protected]4b614a62010-10-06 15:33:1083 original_single_process_(false) {
[email protected]7fac8882010-11-15 19:52:5284#if defined(OS_MACOSX)
85 mac_util::SetOverrideAmIBundled(true);
86#endif
87
88 // Before we run the browser, we have to hack the path to the exe to match
89 // what it would be if Chrome was running, because it is used to fork renderer
90 // processes, on Linux at least (failure to do so will cause a browser_test to
91 // be run instead of a renderer).
92 FilePath chrome_path;
93 CHECK(PathService::Get(base::FILE_EXE, &chrome_path));
94 chrome_path = chrome_path.DirName();
95#if defined(OS_WIN)
96 chrome_path = chrome_path.Append(chrome::kBrowserProcessExecutablePath);
97#elif defined(OS_POSIX)
98 chrome_path = chrome_path.Append(
99 WideToASCII(chrome::kBrowserProcessExecutablePath));
100#endif
101 CHECK(PathService::Override(base::FILE_EXE, chrome_path));
102
103 test_server_.reset(new net::TestServer(
104 net::TestServer::TYPE_HTTP,
105 FilePath(FILE_PATH_LITERAL("chrome/test/data"))));
[email protected]d4515eb2009-01-30 00:40:43106}
107
[email protected]c4ff4952010-01-08 19:12:47108InProcessBrowserTest::~InProcessBrowserTest() {
109}
110
[email protected]d4515eb2009-01-30 00:40:43111void InProcessBrowserTest::SetUp() {
[email protected]470f7a52010-09-23 20:20:38112 // Remember the command line. Normally this doesn't matter, because the test
113 // harness creates a new process for each test, but when the test harness is
114 // running in single process mode, we can't let one test's command-line
115 // changes (e.g. enabling DOM automation) affect other tests.
116 // TODO(phajdan.jr): This save/restore logic is unnecessary. Remove it.
117 CommandLine* command_line = CommandLine::ForCurrentProcessMutable();
118 original_command_line_.reset(new CommandLine(*command_line));
[email protected]d4515eb2009-01-30 00:40:43119
[email protected]fc82ccf02010-10-15 18:12:47120 // Create a temporary user data directory if required.
121 ASSERT_TRUE(CreateUserDataDirectory())
122 << "Could not create user data directory.";
[email protected]4a44bc32010-05-28 22:22:44123
[email protected]d4515eb2009-01-30 00:40:43124 // The unit test suite creates a testingbrowser, but we want the real thing.
125 // Delete the current one. We'll install the testing one in TearDown.
126 delete g_browser_process;
[email protected]298883bc2010-04-30 14:50:58127 g_browser_process = NULL;
128
[email protected]470f7a52010-09-23 20:20:38129 // Allow subclasses the opportunity to make changes to the default user data
130 // dir before running any tests.
[email protected]fc82ccf02010-10-15 18:12:47131 ASSERT_TRUE(SetUpUserDataDirectory())
132 << "Could not set up user data directory.";
[email protected]d4515eb2009-01-30 00:40:43133
134 // Don't delete the resources when BrowserMain returns. Many ui classes
135 // cache SkBitmaps in a static field so that if we delete the resource
136 // bundle we'll crash.
137 browser_shutdown::delete_resources_on_shutdown = false;
138
[email protected]470f7a52010-09-23 20:20:38139 // Allow subclasses the opportunity to make changes to the command line before
140 // running any tests.
[email protected]9665fa62009-04-13 22:15:29141 SetUpCommandLine(command_line);
[email protected]03c79d502010-11-16 00:38:26142 // Add command line arguments that are used by all InProcessBrowserTests.
143 PrepareTestCommandLine(command_line);
[email protected]9665fa62009-04-13 22:15:29144
[email protected]03c79d502010-11-16 00:38:26145 // Save the single process mode state before it was reset in this test. This
146 // state will be recovered in TearDown(). Single-process mode is not set in
147 // BrowserMain so it needs to be processed explicitly.
[email protected]56cdae32009-03-12 19:58:20148 original_single_process_ = RenderProcessHost::run_renderer_in_process();
[email protected]8bcdec92009-02-25 16:15:18149 if (command_line->HasSwitch(switches::kSingleProcess))
150 RenderProcessHost::set_run_renderer_in_process(true);
151
[email protected]02dbca0b2010-09-17 07:44:10152#if defined(OS_CHROMEOS)
153 chromeos::CrosLibrary::Get()->GetTestApi()->SetUseStubImpl();
[email protected]0750b1442010-11-02 21:59:37154
155 // Make sure that the log directory exists.
156 FilePath log_dir = logging::GetSessionLogFile(*command_line).DirName();
157 file_util::CreateDirectory(log_dir);
[email protected]02dbca0b2010-09-17 07:44:10158#endif // defined(OS_CHROMEOS)
159
[email protected]d4515eb2009-01-30 00:40:43160 SandboxInitWrapper sandbox_wrapper;
[email protected]7c321082009-02-09 15:35:47161 MainFunctionParams params(*command_line, sandbox_wrapper, NULL);
[email protected]d4515eb2009-01-30 00:40:43162 params.ui_task =
163 NewRunnableMethod(this, &InProcessBrowserTest::RunTestOnMainThreadLoop);
[email protected]13324ed2009-04-03 05:14:19164
[email protected]c4ff4952010-01-08 19:12:47165 host_resolver_ = new net::RuleBasedHostResolverProc(
166 new IntranetRedirectHostResolverProc(NULL));
[email protected]c7ad50f2009-09-11 06:28:15167
168 // Something inside the browser does this lookup implicitly. Make it fail
169 // to avoid external dependency. It won't break the tests.
170 host_resolver_->AddSimulatedFailure("*.google.com");
171
172 // See http://en.wikipedia.org/wiki/Web_Proxy_Autodiscovery_Protocol
173 // We don't want the test code to use it.
174 host_resolver_->AddSimulatedFailure("wpad");
175
[email protected]b59ff372009-07-15 22:04:32176 net::ScopedDefaultHostResolverProc scoped_host_resolver_proc(
[email protected]c7ad50f2009-09-11 06:28:15177 host_resolver_.get());
[email protected]5c5de8c2009-09-23 17:11:26178
179 SetUpInProcessBrowserTestFixture();
[email protected]60a782e2010-02-24 22:41:35180
[email protected]d4515eb2009-01-30 00:40:43181 BrowserMain(params);
[email protected]5c5de8c2009-09-23 17:11:26182 TearDownInProcessBrowserTestFixture();
[email protected]d4515eb2009-01-30 00:40:43183}
184
[email protected]03c79d502010-11-16 00:38:26185void InProcessBrowserTest::PrepareTestCommandLine(
186 CommandLine* command_line) {
187 // Propagate commandline settings from test_launcher_utils.
188 test_launcher_utils::PrepareBrowserCommandLineForTests(command_line);
189
190#if defined(OS_WIN)
191 // Hide windows on show.
192 if (!command_line->HasSwitch(kUnitTestShowWindows) && !show_window_)
193 BrowserView::SetShowState(SW_HIDE);
194#endif
195
196 if (dom_automation_enabled_)
197 command_line->AppendSwitch(switches::kDomAutomationController);
198
199 // This is a Browser test.
200 command_line->AppendSwitchASCII(switches::kTestType, kBrowserTestType);
201
202#if defined(OS_WIN)
203 // The Windows sandbox requires that the browser and child processes are the
204 // same binary. So we launch browser_process.exe which loads chrome.dll
205 command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
206 command_line->GetProgram());
207#else
208 // Explicitly set the path of the binary used for child processes, otherwise
209 // they'll try to use browser_tests which doesn't contain ChromeMain.
210 FilePath subprocess_path;
211 PathService::Get(base::FILE_EXE, &subprocess_path);
212#if defined(OS_MACOSX)
213 // Recreate the real environment, run the helper within the app bundle.
214 subprocess_path = subprocess_path.DirName().DirName();
215 DCHECK_EQ(subprocess_path.BaseName().value(), "Contents");
216 subprocess_path =
217 subprocess_path.Append("Versions").Append(chrome::kChromeVersion);
218 subprocess_path =
219 subprocess_path.Append(chrome::kHelperProcessExecutablePath);
220#endif
221 command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
222 subprocess_path);
223#endif
224
225 // If ncecessary, disable TabCloseableStateWatcher.
226 if (!tab_closeable_state_watcher_enabled_)
227 command_line->AppendSwitch(switches::kDisableTabCloseableStateWatcher);
228}
229
[email protected]fc82ccf02010-10-15 18:12:47230bool InProcessBrowserTest::CreateUserDataDirectory() {
231 CommandLine* command_line = CommandLine::ForCurrentProcessMutable();
232 FilePath user_data_dir =
233 command_line->GetSwitchValuePath(switches::kUserDataDir);
234 if (user_data_dir.empty()) {
235 if (temp_user_data_dir_.CreateUniqueTempDir() &&
236 temp_user_data_dir_.IsValid()) {
237 user_data_dir = temp_user_data_dir_.path();
238 } else {
239 LOG(ERROR) << "Could not create temporary user data directory \""
240 << temp_user_data_dir_.path().value() << "\".";
241 return false;
242 }
243 }
244 return test_launcher_utils::OverrideUserDataDir(user_data_dir);
245}
246
[email protected]d4515eb2009-01-30 00:40:43247void InProcessBrowserTest::TearDown() {
248 // Reinstall testing browser process.
249 delete g_browser_process;
250 g_browser_process = new TestingBrowserProcess();
251
252 browser_shutdown::delete_resources_on_shutdown = true;
253
[email protected]eb1bd832010-05-18 20:39:58254#if defined(OS_WIN)
[email protected]d4515eb2009-01-30 00:40:43255 BrowserView::SetShowState(-1);
[email protected]108c2a12009-06-05 22:18:09256#endif
[email protected]56cdae32009-03-12 19:58:20257
258 *CommandLine::ForCurrentProcessMutable() = *original_command_line_;
259 RenderProcessHost::set_run_renderer_in_process(original_single_process_);
[email protected]d4515eb2009-01-30 00:40:43260}
261
[email protected]616381f02010-11-02 15:15:33262void InProcessBrowserTest::AddTabAtIndexToBrowser(
263 Browser* browser,
264 int index,
265 const GURL& url,
266 PageTransition::Type transition) {
267 browser::NavigateParams params(browser, url, transition);
268 params.tabstrip_index = index;
269 params.disposition = NEW_FOREGROUND_TAB;
270 browser::Navigate(&params);
271}
272
273void InProcessBrowserTest::AddTabAtIndex(
274 int index,
275 const GURL& url,
276 PageTransition::Type transition) {
277 AddTabAtIndexToBrowser(browser(), index, url, transition);
278}
279
[email protected]d4515eb2009-01-30 00:40:43280// Creates a browser with a single tab (about:blank), waits for the tab to
281// finish loading and shows the browser.
282Browser* InProcessBrowserTest::CreateBrowser(Profile* profile) {
283 Browser* browser = Browser::Create(profile);
[email protected]e1c10f182010-09-30 08:53:06284 InitializeBrowser(browser);
285 return browser;
286}
[email protected]d4515eb2009-01-30 00:40:43287
[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
337 RunTestOnMainThread();
[email protected]304a3172010-05-04 05:38:44338 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01339
340 CleanUpOnMainThread();
[email protected]304a3172010-05-04 05:38:44341 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01342
343 QuitBrowsers();
[email protected]304a3172010-05-04 05:38:44344 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01345}
346
347void InProcessBrowserTest::QuitBrowsers() {
348 if (BrowserList::size() == 0)
349 return;
350
351 // Invoke CloseAllBrowsersAndExit on a running message loop.
352 // CloseAllBrowsersAndExit exits the message loop after everything has been
353 // shut down properly.
354 MessageLoopForUI::current()->PostTask(
355 FROM_HERE,
356 NewRunnableFunction(&BrowserList::CloseAllBrowsersAndExit));
357 ui_test_utils::RunMessageLoop();
358}