blob: b351355fafbc7dc76dcb3304f373f1195fff8bcb [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
[email protected]af44e7fb2011-07-29 18:32:325#include "chrome/test/base/in_process_browser_test.h"
[email protected]d4515eb2009-01-30 00:40:436
7#include "base/command_line.h"
[email protected]b25e61d2011-08-23 09:02:018#include "base/debug/stack_trace.h"
[email protected]d8412052009-04-21 22:01:019#include "base/file_path.h"
[email protected]d4515eb2009-01-30 00:40:4310#include "base/file_util.h"
[email protected]c2818d42010-10-18 02:47:3911#include "base/mac/scoped_nsautorelease_pool.h"
[email protected]d4515eb2009-01-30 00:40:4312#include "base/path_service.h"
[email protected]528c56d2010-07-30 19:28:4413#include "base/string_number_conversions.h"
[email protected]fb895c62009-10-09 18:20:3014#include "base/test/test_file_util.h"
[email protected]d4515eb2009-01-30 00:40:4315#include "chrome/browser/browser_process.h"
[email protected]0ac83682010-01-22 17:46:2716#include "chrome/browser/io_thread.h"
[email protected]8ecad5e2010-12-02 21:18:3317#include "chrome/browser/profiles/profile.h"
18#include "chrome/browser/profiles/profile_manager.h"
[email protected]c848d3d92010-09-16 21:57:4519#include "chrome/browser/tabs/tab_strip_model.h"
[email protected]f46be6e2010-11-16 03:52:3220#include "chrome/browser/ui/browser.h"
[email protected]6768ac02011-04-06 17:41:0421#include "chrome/browser/ui/browser_list.h"
[email protected]339d6dd2010-11-12 00:41:5822#include "chrome/browser/ui/browser_navigator.h"
[email protected]00070c732011-04-09 15:31:3323#include "chrome/browser/ui/browser_window.h"
[email protected]d4515eb2009-01-30 00:40:4324#include "chrome/common/chrome_constants.h"
25#include "chrome/common/chrome_paths.h"
26#include "chrome/common/chrome_switches.h"
[email protected]0750b1442010-11-02 21:59:3727#include "chrome/common/logging_chrome.h"
[email protected]e0d481582009-09-15 21:06:2528#include "chrome/common/url_constants.h"
[email protected]aecb6ca2011-07-29 22:56:1429#include "chrome/test/base/test_launcher_utils.h"
[email protected]bf9257742011-08-11 21:01:1530#include "chrome/test/base/testing_browser_process.h"
[email protected]af44e7fb2011-07-29 18:32:3231#include "chrome/test/base/ui_test_utils.h"
[email protected]1bda97552011-03-01 20:11:5232#include "content/browser/browser_thread.h"
33#include "content/browser/renderer_host/render_process_host.h"
34#include "content/browser/tab_contents/tab_contents.h"
[email protected]432115822011-07-10 15:52:2735#include "content/common/content_notification_types.h"
[email protected]a77e4bc2011-06-29 02:06:2836#include "content/renderer/mock_content_renderer_client.h"
[email protected]c4ff4952010-01-08 19:12:4737#include "net/base/mock_host_resolver.h"
[email protected]3985ba82010-07-29 21:44:1238#include "net/test/test_server.h"
[email protected]7fac8882010-11-15 19:52:5239
[email protected]e2e2411a2011-04-12 20:56:2840#if defined(OS_CHROMEOS)
41#include "chrome/browser/chromeos/audio_handler.h"
42#endif
43
[email protected]ddf8a4b02010-03-22 23:08:3044// Passed as value of kTestType.
45static const char kBrowserTestType[] = "browser";
46
[email protected]8bcdec92009-02-25 16:15:1847InProcessBrowserTest::InProcessBrowserTest()
48 : browser_(NULL),
49 show_window_(false),
[email protected]56cdae32009-03-12 19:58:2050 dom_automation_enabled_(false),
[email protected]06cc083a2011-03-01 02:28:4251 tab_closeable_state_watcher_enabled_(false) {
[email protected]86671a32011-10-06 21:15:2052#if defined(OS_MACOSX)
53 // TODO(phajdan.jr): Make browser_tests self-contained on Mac, remove this.
[email protected]7fac8882010-11-15 19:52:5254 // Before we run the browser, we have to hack the path to the exe to match
55 // what it would be if Chrome was running, because it is used to fork renderer
56 // processes, on Linux at least (failure to do so will cause a browser_test to
57 // be run instead of a renderer).
58 FilePath chrome_path;
59 CHECK(PathService::Get(base::FILE_EXE, &chrome_path));
60 chrome_path = chrome_path.DirName();
[email protected]7fac8882010-11-15 19:52:5261 chrome_path = chrome_path.Append(chrome::kBrowserProcessExecutablePath);
[email protected]7fac8882010-11-15 19:52:5262 CHECK(PathService::Override(base::FILE_EXE, chrome_path));
[email protected]86671a32011-10-06 21:15:2063#endif // defined(OS_MACOSX)
[email protected]7fac8882010-11-15 19:52:5264
65 test_server_.reset(new net::TestServer(
66 net::TestServer::TYPE_HTTP,
67 FilePath(FILE_PATH_LITERAL("chrome/test/data"))));
[email protected]d4515eb2009-01-30 00:40:4368}
69
[email protected]c4ff4952010-01-08 19:12:4770InProcessBrowserTest::~InProcessBrowserTest() {
71}
72
[email protected]d4515eb2009-01-30 00:40:4373void InProcessBrowserTest::SetUp() {
[email protected]fc82ccf02010-10-15 18:12:4774 // Create a temporary user data directory if required.
75 ASSERT_TRUE(CreateUserDataDirectory())
76 << "Could not create user data directory.";
[email protected]4a44bc32010-05-28 22:22:4477
[email protected]583844c2011-08-27 00:38:3578 // Undo TestingBrowserProcess creation in ChromeTestSuite.
79 // TODO(phajdan.jr): Extract a smaller test suite so we don't need this.
80 DCHECK(g_browser_process);
81 delete g_browser_process;
82 g_browser_process = NULL;
[email protected]298883bc2010-04-30 14:50:5883
[email protected]470f7a52010-09-23 20:20:3884 // Allow subclasses the opportunity to make changes to the default user data
85 // dir before running any tests.
[email protected]fc82ccf02010-10-15 18:12:4786 ASSERT_TRUE(SetUpUserDataDirectory())
87 << "Could not set up user data directory.";
[email protected]d4515eb2009-01-30 00:40:4388
[email protected]06cc083a2011-03-01 02:28:4289 CommandLine* command_line = CommandLine::ForCurrentProcess();
90 // Allow subclasses to change the command line before running any tests.
[email protected]9665fa62009-04-13 22:15:2991 SetUpCommandLine(command_line);
[email protected]03c79d502010-11-16 00:38:2692 // Add command line arguments that are used by all InProcessBrowserTests.
93 PrepareTestCommandLine(command_line);
[email protected]9665fa62009-04-13 22:15:2994
[email protected]15fd0df2011-04-29 16:00:1695 // Single-process mode is not set in BrowserMain, so process it explicitly,
96 // and set up renderer.
97 if (command_line->HasSwitch(switches::kSingleProcess)) {
[email protected]8bcdec92009-02-25 16:15:1898 RenderProcessHost::set_run_renderer_in_process(true);
[email protected]a77e4bc2011-06-29 02:06:2899 single_process_renderer_client_.reset(
100 new content::MockContentRendererClient);
[email protected]15fd0df2011-04-29 16:00:16101 content::GetContentClient()->set_renderer(
102 single_process_renderer_client_.get());
103 }
[email protected]8bcdec92009-02-25 16:15:18104
[email protected]02dbca0b2010-09-17 07:44:10105#if defined(OS_CHROMEOS)
[email protected]0750b1442010-11-02 21:59:37106 // Make sure that the log directory exists.
107 FilePath log_dir = logging::GetSessionLogFile(*command_line).DirName();
108 file_util::CreateDirectory(log_dir);
[email protected]02dbca0b2010-09-17 07:44:10109#endif // defined(OS_CHROMEOS)
110
[email protected]67770432011-09-21 18:12:32111 host_resolver_ = new net::RuleBasedHostResolverProc(NULL);
[email protected]c7ad50f2009-09-11 06:28:15112
113 // Something inside the browser does this lookup implicitly. Make it fail
114 // to avoid external dependency. It won't break the tests.
115 host_resolver_->AddSimulatedFailure("*.google.com");
116
117 // See http://en.wikipedia.org/wiki/Web_Proxy_Autodiscovery_Protocol
118 // We don't want the test code to use it.
119 host_resolver_->AddSimulatedFailure("wpad");
120
[email protected]b59ff372009-07-15 22:04:32121 net::ScopedDefaultHostResolverProc scoped_host_resolver_proc(
[email protected]c7ad50f2009-09-11 06:28:15122 host_resolver_.get());
[email protected]5c5de8c2009-09-23 17:11:26123
[email protected]bb36d822011-09-30 20:55:09124 BrowserTestBase::SetUp();
[email protected]d4515eb2009-01-30 00:40:43125}
126
[email protected]06cc083a2011-03-01 02:28:42127void InProcessBrowserTest::PrepareTestCommandLine(CommandLine* command_line) {
[email protected]03c79d502010-11-16 00:38:26128 // Propagate commandline settings from test_launcher_utils.
129 test_launcher_utils::PrepareBrowserCommandLineForTests(command_line);
130
[email protected]03c79d502010-11-16 00:38:26131 if (dom_automation_enabled_)
132 command_line->AppendSwitch(switches::kDomAutomationController);
133
134 // This is a Browser test.
135 command_line->AppendSwitchASCII(switches::kTestType, kBrowserTestType);
136
137#if defined(OS_WIN)
138 // The Windows sandbox requires that the browser and child processes are the
139 // same binary. So we launch browser_process.exe which loads chrome.dll
140 command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
141 command_line->GetProgram());
142#else
143 // Explicitly set the path of the binary used for child processes, otherwise
144 // they'll try to use browser_tests which doesn't contain ChromeMain.
145 FilePath subprocess_path;
146 PathService::Get(base::FILE_EXE, &subprocess_path);
147#if defined(OS_MACOSX)
148 // Recreate the real environment, run the helper within the app bundle.
149 subprocess_path = subprocess_path.DirName().DirName();
150 DCHECK_EQ(subprocess_path.BaseName().value(), "Contents");
151 subprocess_path =
152 subprocess_path.Append("Versions").Append(chrome::kChromeVersion);
153 subprocess_path =
154 subprocess_path.Append(chrome::kHelperProcessExecutablePath);
155#endif
156 command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
157 subprocess_path);
158#endif
159
[email protected]7c8b20672011-02-11 21:18:01160 // If neccessary, disable TabCloseableStateWatcher.
[email protected]03c79d502010-11-16 00:38:26161 if (!tab_closeable_state_watcher_enabled_)
162 command_line->AppendSwitch(switches::kDisableTabCloseableStateWatcher);
163}
164
[email protected]fc82ccf02010-10-15 18:12:47165bool InProcessBrowserTest::CreateUserDataDirectory() {
[email protected]06cc083a2011-03-01 02:28:42166 CommandLine* command_line = CommandLine::ForCurrentProcess();
[email protected]fc82ccf02010-10-15 18:12:47167 FilePath user_data_dir =
168 command_line->GetSwitchValuePath(switches::kUserDataDir);
169 if (user_data_dir.empty()) {
170 if (temp_user_data_dir_.CreateUniqueTempDir() &&
171 temp_user_data_dir_.IsValid()) {
172 user_data_dir = temp_user_data_dir_.path();
173 } else {
174 LOG(ERROR) << "Could not create temporary user data directory \""
175 << temp_user_data_dir_.path().value() << "\".";
176 return false;
177 }
178 }
179 return test_launcher_utils::OverrideUserDataDir(user_data_dir);
180}
181
[email protected]d4515eb2009-01-30 00:40:43182void InProcessBrowserTest::TearDown() {
[email protected]b7c64d62011-08-11 00:08:04183 DCHECK(!g_browser_process);
[email protected]bb36d822011-09-30 20:55:09184 BrowserTestBase::TearDown();
[email protected]d4515eb2009-01-30 00:40:43185}
186
[email protected]616381f02010-11-02 15:15:33187void InProcessBrowserTest::AddTabAtIndexToBrowser(
188 Browser* browser,
189 int index,
190 const GURL& url,
[email protected]2905f742011-10-13 03:51:58191 content::PageTransition transition) {
[email protected]616381f02010-11-02 15:15:33192 browser::NavigateParams params(browser, url, transition);
193 params.tabstrip_index = index;
194 params.disposition = NEW_FOREGROUND_TAB;
195 browser::Navigate(&params);
196}
197
198void InProcessBrowserTest::AddTabAtIndex(
199 int index,
200 const GURL& url,
[email protected]2905f742011-10-13 03:51:58201 content::PageTransition transition) {
[email protected]616381f02010-11-02 15:15:33202 AddTabAtIndexToBrowser(browser(), index, url, transition);
203}
204
[email protected]fadc607b62011-02-07 17:55:50205bool InProcessBrowserTest::SetUpUserDataDirectory() {
206 return true;
207}
208
[email protected]d4515eb2009-01-30 00:40:43209// Creates a browser with a single tab (about:blank), waits for the tab to
210// finish loading and shows the browser.
211Browser* InProcessBrowserTest::CreateBrowser(Profile* profile) {
212 Browser* browser = Browser::Create(profile);
[email protected]de4943f2011-07-28 16:25:14213 AddBlankTabAndShow(browser);
[email protected]e1c10f182010-09-30 08:53:06214 return browser;
215}
[email protected]d4515eb2009-01-30 00:40:43216
[email protected]46f979d2011-01-10 17:08:44217Browser* InProcessBrowserTest::CreateIncognitoBrowser() {
218 // Create a new browser with using the incognito profile.
219 Browser* incognito =
220 Browser::Create(browser()->profile()->GetOffTheRecordProfile());
[email protected]de4943f2011-07-28 16:25:14221 AddBlankTabAndShow(incognito);
[email protected]46f979d2011-01-10 17:08:44222 return incognito;
223}
224
[email protected]e1c10f182010-09-30 08:53:06225Browser* InProcessBrowserTest::CreateBrowserForPopup(Profile* profile) {
[email protected]1b74d2122010-10-06 16:49:16226 Browser* browser = Browser::CreateForType(Browser::TYPE_POPUP, profile);
[email protected]de4943f2011-07-28 16:25:14227 AddBlankTabAndShow(browser);
[email protected]d4515eb2009-01-30 00:40:43228 return browser;
229}
230
[email protected]de4943f2011-07-28 16:25:14231void InProcessBrowserTest::AddBlankTabAndShow(Browser* browser) {
[email protected]3114db2c2011-09-12 20:09:05232 ui_test_utils::WindowedNotificationObserver observer(
233 content::NOTIFICATION_LOAD_STOP,
234 NotificationService::AllSources());
[email protected]de4943f2011-07-28 16:25:14235 browser->AddSelectedTabWithURL(
[email protected]2905f742011-10-13 03:51:58236 GURL(chrome::kAboutBlankURL), content::PAGE_TRANSITION_START_PAGE);
[email protected]3114db2c2011-09-12 20:09:05237 observer.Wait();
[email protected]de4943f2011-07-28 16:25:14238
[email protected]fab6ffb2011-09-22 18:35:34239 browser->window()->Show();
[email protected]de4943f2011-07-28 16:25:14240}
241
[email protected]b25e61d2011-08-23 09:02:01242#if defined(OS_POSIX)
243// On SIGTERM (sent by the runner on timeouts), dump a stack trace (to make
244// debugging easier) and also exit with a known error code (so that the test
245// framework considers this a failure -- http://crbug.com/57578).
246static void DumpStackTraceSignalHandler(int signal) {
247 base::debug::StackTrace().PrintBacktrace();
248 _exit(128 + signal);
249}
250#endif // defined(OS_POSIX)
251
[email protected]64f19312010-04-13 22:30:01252void InProcessBrowserTest::RunTestOnMainThreadLoop() {
[email protected]00d0ac22010-10-05 09:30:00253#if defined(OS_POSIX)
[email protected]b25e61d2011-08-23 09:02:01254 signal(SIGTERM, DumpStackTraceSignalHandler);
[email protected]00d0ac22010-10-05 09:30:00255#endif // defined(OS_POSIX)
256
[email protected]304a3172010-05-04 05:38:44257 // On Mac, without the following autorelease pool, code which is directly
258 // executed (as opposed to executed inside a message loop) would autorelease
259 // objects into a higher-level pool. This pool is not recycled in-sync with
260 // the message loops' pools and causes problems with code relying on
261 // deallocation via an autorelease pool (such as browser window closure and
262 // browser shutdown). To avoid this, the following pool is recycled after each
263 // time code is directly executed.
[email protected]c2818d42010-10-18 02:47:39264 base::mac::ScopedNSAutoreleasePool pool;
[email protected]304a3172010-05-04 05:38:44265
[email protected]64f19312010-04-13 22:30:01266 // Pump startup related events.
267 MessageLoopForUI::current()->RunAllPending();
[email protected]304a3172010-05-04 05:38:44268 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01269
[email protected]67770432011-09-21 18:12:32270 browser_ = CreateBrowser(ProfileManager::GetDefaultProfile());
[email protected]304a3172010-05-04 05:38:44271 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01272
[email protected]64f19312010-04-13 22:30:01273 // Pump any pending events that were created as a result of creating a
274 // browser.
275 MessageLoopForUI::current()->RunAllPending();
276
[email protected]28dabab72011-01-05 03:31:26277 SetUpOnMainThread();
278 pool.Recycle();
279
[email protected]64f19312010-04-13 22:30:01280 RunTestOnMainThread();
[email protected]304a3172010-05-04 05:38:44281 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01282
283 CleanUpOnMainThread();
[email protected]304a3172010-05-04 05:38:44284 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01285
286 QuitBrowsers();
[email protected]304a3172010-05-04 05:38:44287 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01288}
289
290void InProcessBrowserTest::QuitBrowsers() {
291 if (BrowserList::size() == 0)
292 return;
293
[email protected]bc63a072011-06-28 21:12:57294 // Invoke CloseAllBrowsersAndMayExit on a running message loop.
295 // CloseAllBrowsersAndMayExit exits the message loop after everything has been
[email protected]64f19312010-04-13 22:30:01296 // shut down properly.
297 MessageLoopForUI::current()->PostTask(
298 FROM_HERE,
[email protected]bc63a072011-06-28 21:12:57299 NewRunnableFunction(&BrowserList::AttemptExit));
[email protected]64f19312010-04-13 22:30:01300 ui_test_utils::RunMessageLoop();
301}