blob: 43b105c28c82ab13c6e88a93427543862d70b886 [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]415c2cd2011-03-11 21:56:1136#include "content/common/main_function_params.h"
[email protected]a77e4bc2011-06-29 02:06:2837#include "content/renderer/mock_content_renderer_client.h"
[email protected]c4ff4952010-01-08 19:12:4738#include "net/base/mock_host_resolver.h"
[email protected]3985ba82010-07-29 21:44:1239#include "net/test/test_server.h"
[email protected]d4515eb2009-01-30 00:40:4340#include "sandbox/src/dep.h"
41
[email protected]7fac8882010-11-15 19:52:5242#if defined(OS_MACOSX)
[email protected]0378bf42011-01-01 18:20:1443#include "base/mac/mac_util.h"
[email protected]7e15d352011-07-04 04:18:4144#include "base/system_monitor/system_monitor.h"
[email protected]7fac8882010-11-15 19:52:5245#endif
46
[email protected]e2e2411a2011-04-12 20:56:2847#if defined(OS_CHROMEOS)
48#include "chrome/browser/chromeos/audio_handler.h"
49#endif
50
[email protected]d4515eb2009-01-30 00:40:4351extern int BrowserMain(const MainFunctionParams&);
52
[email protected]ddf8a4b02010-03-22 23:08:3053// Passed as value of kTestType.
54static const char kBrowserTestType[] = "browser";
55
[email protected]8bcdec92009-02-25 16:15:1856InProcessBrowserTest::InProcessBrowserTest()
57 : browser_(NULL),
58 show_window_(false),
[email protected]56cdae32009-03-12 19:58:2059 dom_automation_enabled_(false),
[email protected]06cc083a2011-03-01 02:28:4260 tab_closeable_state_watcher_enabled_(false) {
[email protected]7fac8882010-11-15 19:52:5261#if defined(OS_MACOSX)
[email protected]0378bf42011-01-01 18:20:1462 base::mac::SetOverrideAmIBundled(true);
[email protected]7e15d352011-07-04 04:18:4163 base::SystemMonitor::AllocateSystemIOPorts();
[email protected]7fac8882010-11-15 19:52:5264#endif
65
66 // Before we run the browser, we have to hack the path to the exe to match
67 // what it would be if Chrome was running, because it is used to fork renderer
68 // processes, on Linux at least (failure to do so will cause a browser_test to
69 // be run instead of a renderer).
70 FilePath chrome_path;
71 CHECK(PathService::Get(base::FILE_EXE, &chrome_path));
72 chrome_path = chrome_path.DirName();
[email protected]7fac8882010-11-15 19:52:5273 chrome_path = chrome_path.Append(chrome::kBrowserProcessExecutablePath);
[email protected]7fac8882010-11-15 19:52:5274 CHECK(PathService::Override(base::FILE_EXE, chrome_path));
75
76 test_server_.reset(new net::TestServer(
77 net::TestServer::TYPE_HTTP,
78 FilePath(FILE_PATH_LITERAL("chrome/test/data"))));
[email protected]d4515eb2009-01-30 00:40:4379}
80
[email protected]c4ff4952010-01-08 19:12:4781InProcessBrowserTest::~InProcessBrowserTest() {
82}
83
[email protected]d4515eb2009-01-30 00:40:4384void InProcessBrowserTest::SetUp() {
[email protected]fc82ccf02010-10-15 18:12:4785 // Create a temporary user data directory if required.
86 ASSERT_TRUE(CreateUserDataDirectory())
87 << "Could not create user data directory.";
[email protected]4a44bc32010-05-28 22:22:4488
[email protected]583844c2011-08-27 00:38:3589 // Undo TestingBrowserProcess creation in ChromeTestSuite.
90 // TODO(phajdan.jr): Extract a smaller test suite so we don't need this.
91 DCHECK(g_browser_process);
92 delete g_browser_process;
93 g_browser_process = NULL;
[email protected]298883bc2010-04-30 14:50:5894
[email protected]470f7a52010-09-23 20:20:3895 // Allow subclasses the opportunity to make changes to the default user data
96 // dir before running any tests.
[email protected]fc82ccf02010-10-15 18:12:4797 ASSERT_TRUE(SetUpUserDataDirectory())
98 << "Could not set up user data directory.";
[email protected]d4515eb2009-01-30 00:40:4399
[email protected]06cc083a2011-03-01 02:28:42100 CommandLine* command_line = CommandLine::ForCurrentProcess();
101 // Allow subclasses to change the command line before running any tests.
[email protected]9665fa62009-04-13 22:15:29102 SetUpCommandLine(command_line);
[email protected]03c79d502010-11-16 00:38:26103 // Add command line arguments that are used by all InProcessBrowserTests.
104 PrepareTestCommandLine(command_line);
[email protected]9665fa62009-04-13 22:15:29105
[email protected]15fd0df2011-04-29 16:00:16106 // Single-process mode is not set in BrowserMain, so process it explicitly,
107 // and set up renderer.
108 if (command_line->HasSwitch(switches::kSingleProcess)) {
[email protected]8bcdec92009-02-25 16:15:18109 RenderProcessHost::set_run_renderer_in_process(true);
[email protected]a77e4bc2011-06-29 02:06:28110 single_process_renderer_client_.reset(
111 new content::MockContentRendererClient);
[email protected]15fd0df2011-04-29 16:00:16112 content::GetContentClient()->set_renderer(
113 single_process_renderer_client_.get());
114 }
[email protected]8bcdec92009-02-25 16:15:18115
[email protected]02dbca0b2010-09-17 07:44:10116#if defined(OS_CHROMEOS)
[email protected]0750b1442010-11-02 21:59:37117 // Make sure that the log directory exists.
118 FilePath log_dir = logging::GetSessionLogFile(*command_line).DirName();
119 file_util::CreateDirectory(log_dir);
[email protected]02dbca0b2010-09-17 07:44:10120#endif // defined(OS_CHROMEOS)
121
[email protected]67770432011-09-21 18:12:32122 host_resolver_ = new net::RuleBasedHostResolverProc(NULL);
[email protected]c7ad50f2009-09-11 06:28:15123
124 // Something inside the browser does this lookup implicitly. Make it fail
125 // to avoid external dependency. It won't break the tests.
126 host_resolver_->AddSimulatedFailure("*.google.com");
127
128 // See http://en.wikipedia.org/wiki/Web_Proxy_Autodiscovery_Protocol
129 // We don't want the test code to use it.
130 host_resolver_->AddSimulatedFailure("wpad");
131
[email protected]b59ff372009-07-15 22:04:32132 net::ScopedDefaultHostResolverProc scoped_host_resolver_proc(
[email protected]c7ad50f2009-09-11 06:28:15133 host_resolver_.get());
[email protected]5c5de8c2009-09-23 17:11:26134
[email protected]67770432011-09-21 18:12:32135 SandboxInitWrapper sandbox_wrapper;
136 MainFunctionParams params(*command_line, sandbox_wrapper, NULL);
137 params.ui_task =
138 NewRunnableMethod(this, &InProcessBrowserTest::RunTestOnMainThreadLoop);
[email protected]60a782e2010-02-24 22:41:35139
[email protected]67770432011-09-21 18:12:32140 SetUpInProcessBrowserTestFixture();
[email protected]d4515eb2009-01-30 00:40:43141 BrowserMain(params);
[email protected]5c5de8c2009-09-23 17:11:26142 TearDownInProcessBrowserTestFixture();
[email protected]d4515eb2009-01-30 00:40:43143}
144
[email protected]06cc083a2011-03-01 02:28:42145void InProcessBrowserTest::PrepareTestCommandLine(CommandLine* command_line) {
[email protected]03c79d502010-11-16 00:38:26146 // Propagate commandline settings from test_launcher_utils.
147 test_launcher_utils::PrepareBrowserCommandLineForTests(command_line);
148
[email protected]03c79d502010-11-16 00:38:26149 if (dom_automation_enabled_)
150 command_line->AppendSwitch(switches::kDomAutomationController);
151
152 // This is a Browser test.
153 command_line->AppendSwitchASCII(switches::kTestType, kBrowserTestType);
154
155#if defined(OS_WIN)
156 // The Windows sandbox requires that the browser and child processes are the
157 // same binary. So we launch browser_process.exe which loads chrome.dll
158 command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
159 command_line->GetProgram());
160#else
161 // Explicitly set the path of the binary used for child processes, otherwise
162 // they'll try to use browser_tests which doesn't contain ChromeMain.
163 FilePath subprocess_path;
164 PathService::Get(base::FILE_EXE, &subprocess_path);
165#if defined(OS_MACOSX)
166 // Recreate the real environment, run the helper within the app bundle.
167 subprocess_path = subprocess_path.DirName().DirName();
168 DCHECK_EQ(subprocess_path.BaseName().value(), "Contents");
169 subprocess_path =
170 subprocess_path.Append("Versions").Append(chrome::kChromeVersion);
171 subprocess_path =
172 subprocess_path.Append(chrome::kHelperProcessExecutablePath);
173#endif
174 command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
175 subprocess_path);
176#endif
177
[email protected]7c8b20672011-02-11 21:18:01178 // If neccessary, disable TabCloseableStateWatcher.
[email protected]03c79d502010-11-16 00:38:26179 if (!tab_closeable_state_watcher_enabled_)
180 command_line->AppendSwitch(switches::kDisableTabCloseableStateWatcher);
181}
182
[email protected]fc82ccf02010-10-15 18:12:47183bool InProcessBrowserTest::CreateUserDataDirectory() {
[email protected]06cc083a2011-03-01 02:28:42184 CommandLine* command_line = CommandLine::ForCurrentProcess();
[email protected]fc82ccf02010-10-15 18:12:47185 FilePath user_data_dir =
186 command_line->GetSwitchValuePath(switches::kUserDataDir);
187 if (user_data_dir.empty()) {
188 if (temp_user_data_dir_.CreateUniqueTempDir() &&
189 temp_user_data_dir_.IsValid()) {
190 user_data_dir = temp_user_data_dir_.path();
191 } else {
192 LOG(ERROR) << "Could not create temporary user data directory \""
193 << temp_user_data_dir_.path().value() << "\".";
194 return false;
195 }
196 }
197 return test_launcher_utils::OverrideUserDataDir(user_data_dir);
198}
199
[email protected]d4515eb2009-01-30 00:40:43200void InProcessBrowserTest::TearDown() {
[email protected]b7c64d62011-08-11 00:08:04201 DCHECK(!g_browser_process);
[email protected]d4515eb2009-01-30 00:40:43202}
203
[email protected]616381f02010-11-02 15:15:33204void InProcessBrowserTest::AddTabAtIndexToBrowser(
205 Browser* browser,
206 int index,
207 const GURL& url,
208 PageTransition::Type transition) {
209 browser::NavigateParams params(browser, url, transition);
210 params.tabstrip_index = index;
211 params.disposition = NEW_FOREGROUND_TAB;
212 browser::Navigate(&params);
213}
214
215void InProcessBrowserTest::AddTabAtIndex(
216 int index,
217 const GURL& url,
218 PageTransition::Type transition) {
219 AddTabAtIndexToBrowser(browser(), index, url, transition);
220}
221
[email protected]fadc607b62011-02-07 17:55:50222bool InProcessBrowserTest::SetUpUserDataDirectory() {
223 return true;
224}
225
[email protected]d4515eb2009-01-30 00:40:43226// Creates a browser with a single tab (about:blank), waits for the tab to
227// finish loading and shows the browser.
228Browser* InProcessBrowserTest::CreateBrowser(Profile* profile) {
229 Browser* browser = Browser::Create(profile);
[email protected]de4943f2011-07-28 16:25:14230 AddBlankTabAndShow(browser);
[email protected]e1c10f182010-09-30 08:53:06231 return browser;
232}
[email protected]d4515eb2009-01-30 00:40:43233
[email protected]46f979d2011-01-10 17:08:44234Browser* InProcessBrowserTest::CreateIncognitoBrowser() {
235 // Create a new browser with using the incognito profile.
236 Browser* incognito =
237 Browser::Create(browser()->profile()->GetOffTheRecordProfile());
[email protected]de4943f2011-07-28 16:25:14238 AddBlankTabAndShow(incognito);
[email protected]46f979d2011-01-10 17:08:44239 return incognito;
240}
241
[email protected]e1c10f182010-09-30 08:53:06242Browser* InProcessBrowserTest::CreateBrowserForPopup(Profile* profile) {
[email protected]1b74d2122010-10-06 16:49:16243 Browser* browser = Browser::CreateForType(Browser::TYPE_POPUP, profile);
[email protected]de4943f2011-07-28 16:25:14244 AddBlankTabAndShow(browser);
[email protected]d4515eb2009-01-30 00:40:43245 return browser;
246}
247
[email protected]de4943f2011-07-28 16:25:14248void InProcessBrowserTest::AddBlankTabAndShow(Browser* browser) {
[email protected]3114db2c2011-09-12 20:09:05249 ui_test_utils::WindowedNotificationObserver observer(
250 content::NOTIFICATION_LOAD_STOP,
251 NotificationService::AllSources());
[email protected]de4943f2011-07-28 16:25:14252 browser->AddSelectedTabWithURL(
253 GURL(chrome::kAboutBlankURL), PageTransition::START_PAGE);
[email protected]3114db2c2011-09-12 20:09:05254 observer.Wait();
[email protected]de4943f2011-07-28 16:25:14255
[email protected]fab6ffb2011-09-22 18:35:34256 browser->window()->Show();
[email protected]de4943f2011-07-28 16:25:14257}
258
[email protected]b25e61d2011-08-23 09:02:01259#if defined(OS_POSIX)
260// On SIGTERM (sent by the runner on timeouts), dump a stack trace (to make
261// debugging easier) and also exit with a known error code (so that the test
262// framework considers this a failure -- http://crbug.com/57578).
263static void DumpStackTraceSignalHandler(int signal) {
264 base::debug::StackTrace().PrintBacktrace();
265 _exit(128 + signal);
266}
267#endif // defined(OS_POSIX)
268
[email protected]64f19312010-04-13 22:30:01269void InProcessBrowserTest::RunTestOnMainThreadLoop() {
[email protected]00d0ac22010-10-05 09:30:00270#if defined(OS_POSIX)
[email protected]b25e61d2011-08-23 09:02:01271 signal(SIGTERM, DumpStackTraceSignalHandler);
[email protected]00d0ac22010-10-05 09:30:00272#endif // defined(OS_POSIX)
273
[email protected]304a3172010-05-04 05:38:44274 // On Mac, without the following autorelease pool, code which is directly
275 // executed (as opposed to executed inside a message loop) would autorelease
276 // objects into a higher-level pool. This pool is not recycled in-sync with
277 // the message loops' pools and causes problems with code relying on
278 // deallocation via an autorelease pool (such as browser window closure and
279 // browser shutdown). To avoid this, the following pool is recycled after each
280 // time code is directly executed.
[email protected]c2818d42010-10-18 02:47:39281 base::mac::ScopedNSAutoreleasePool pool;
[email protected]304a3172010-05-04 05:38:44282
[email protected]64f19312010-04-13 22:30:01283 // Pump startup related events.
284 MessageLoopForUI::current()->RunAllPending();
[email protected]304a3172010-05-04 05:38:44285 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01286
[email protected]67770432011-09-21 18:12:32287 browser_ = CreateBrowser(ProfileManager::GetDefaultProfile());
[email protected]304a3172010-05-04 05:38:44288 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01289
[email protected]64f19312010-04-13 22:30:01290 // Pump any pending events that were created as a result of creating a
291 // browser.
292 MessageLoopForUI::current()->RunAllPending();
293
[email protected]28dabab72011-01-05 03:31:26294 SetUpOnMainThread();
295 pool.Recycle();
296
[email protected]64f19312010-04-13 22:30:01297 RunTestOnMainThread();
[email protected]304a3172010-05-04 05:38:44298 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01299
300 CleanUpOnMainThread();
[email protected]304a3172010-05-04 05:38:44301 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01302
303 QuitBrowsers();
[email protected]304a3172010-05-04 05:38:44304 pool.Recycle();
[email protected]64f19312010-04-13 22:30:01305}
306
307void InProcessBrowserTest::QuitBrowsers() {
308 if (BrowserList::size() == 0)
309 return;
310
[email protected]bc63a072011-06-28 21:12:57311 // Invoke CloseAllBrowsersAndMayExit on a running message loop.
312 // CloseAllBrowsersAndMayExit exits the message loop after everything has been
[email protected]64f19312010-04-13 22:30:01313 // shut down properly.
314 MessageLoopForUI::current()->PostTask(
315 FROM_HERE,
[email protected]bc63a072011-06-28 21:12:57316 NewRunnableFunction(&BrowserList::AttemptExit));
[email protected]64f19312010-04-13 22:30:01317 ui_test_utils::RunMessageLoop();
318}