blob: 7986608b1224b1f2f8b67e485d17db3933dea469 [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"
16#include "chrome/browser/browser_shutdown.h"
[email protected]c4ff4952010-01-08 19:12:4717#include "chrome/browser/intranet_redirect_detector.h"
[email protected]0ac83682010-01-22 17:46:2718#include "chrome/browser/io_thread.h"
[email protected]cec4a272009-07-31 21:55:0319#include "chrome/browser/net/url_request_mock_util.h"
[email protected]8ecad5e2010-12-02 21:18:3320#include "chrome/browser/profiles/profile.h"
21#include "chrome/browser/profiles/profile_manager.h"
[email protected]c848d3d92010-09-16 21:57:4522#include "chrome/browser/tabs/tab_strip_model.h"
[email protected]f46be6e2010-11-16 03:52:3223#include "chrome/browser/ui/browser.h"
[email protected]6768ac02011-04-06 17:41:0424#include "chrome/browser/ui/browser_list.h"
[email protected]339d6dd2010-11-12 00:41:5825#include "chrome/browser/ui/browser_navigator.h"
[email protected]00070c732011-04-09 15:31:3326#include "chrome/browser/ui/browser_window.h"
[email protected]d4515eb2009-01-30 00:40:4327#include "chrome/common/chrome_constants.h"
28#include "chrome/common/chrome_paths.h"
29#include "chrome/common/chrome_switches.h"
[email protected]0750b1442010-11-02 21:59:3730#include "chrome/common/logging_chrome.h"
[email protected]e0d481582009-09-15 21:06:2531#include "chrome/common/url_constants.h"
[email protected]aecb6ca2011-07-29 22:56:1432#include "chrome/test/base/test_launcher_utils.h"
[email protected]bf9257742011-08-11 21:01:1533#include "chrome/test/base/testing_browser_process.h"
[email protected]af44e7fb2011-07-29 18:32:3234#include "chrome/test/base/ui_test_utils.h"
[email protected]1bda97552011-03-01 20:11:5235#include "content/browser/browser_thread.h"
36#include "content/browser/renderer_host/render_process_host.h"
37#include "content/browser/tab_contents/tab_contents.h"
[email protected]432115822011-07-10 15:52:2738#include "content/common/content_notification_types.h"
[email protected]415c2cd2011-03-11 21:56:1139#include "content/common/main_function_params.h"
[email protected]a77e4bc2011-06-29 02:06:2840#include "content/renderer/mock_content_renderer_client.h"
[email protected]c4ff4952010-01-08 19:12:4741#include "net/base/mock_host_resolver.h"
[email protected]3985ba82010-07-29 21:44:1242#include "net/test/test_server.h"
[email protected]d4515eb2009-01-30 00:40:4343#include "sandbox/src/dep.h"
44
[email protected]7fac8882010-11-15 19:52:5245#if defined(OS_MACOSX)
[email protected]0378bf42011-01-01 18:20:1446#include "base/mac/mac_util.h"
[email protected]7e15d352011-07-04 04:18:4147#include "base/system_monitor/system_monitor.h"
[email protected]7fac8882010-11-15 19:52:5248#endif
49
50#if defined(OS_WIN)
[email protected]f353bed2011-03-08 18:40:3951#include "chrome/browser/ui/views/frame/browser_frame_win.h"
[email protected]7fac8882010-11-15 19:52:5252#endif
53
[email protected]e2e2411a2011-04-12 20:56:2854#if defined(OS_CHROMEOS)
55#include "chrome/browser/chromeos/audio_handler.h"
56#endif
57
[email protected]d4515eb2009-01-30 00:40:4358extern int BrowserMain(const MainFunctionParams&);
59
[email protected]711a353a2010-12-08 22:18:3760const char kUnitTestShowWindows[] = "show-windows";
[email protected]d4515eb2009-01-30 00:40:4361
[email protected]ddf8a4b02010-03-22 23:08:3062// Passed as value of kTestType.
63static const char kBrowserTestType[] = "browser";
64
[email protected]8bcdec92009-02-25 16:15:1865InProcessBrowserTest::InProcessBrowserTest()
66 : browser_(NULL),
67 show_window_(false),
[email protected]56cdae32009-03-12 19:58:2068 dom_automation_enabled_(false),
[email protected]06cc083a2011-03-01 02:28:4269 tab_closeable_state_watcher_enabled_(false) {
[email protected]7fac8882010-11-15 19:52:5270#if defined(OS_MACOSX)
[email protected]0378bf42011-01-01 18:20:1471 base::mac::SetOverrideAmIBundled(true);
[email protected]7e15d352011-07-04 04:18:4172 base::SystemMonitor::AllocateSystemIOPorts();
[email protected]7fac8882010-11-15 19:52:5273#endif
74
75 // Before we run the browser, we have to hack the path to the exe to match
76 // what it would be if Chrome was running, because it is used to fork renderer
77 // processes, on Linux at least (failure to do so will cause a browser_test to
78 // be run instead of a renderer).
79 FilePath chrome_path;
80 CHECK(PathService::Get(base::FILE_EXE, &chrome_path));
81 chrome_path = chrome_path.DirName();
[email protected]7fac8882010-11-15 19:52:5282 chrome_path = chrome_path.Append(chrome::kBrowserProcessExecutablePath);
[email protected]7fac8882010-11-15 19:52:5283 CHECK(PathService::Override(base::FILE_EXE, chrome_path));
84
85 test_server_.reset(new net::TestServer(
86 net::TestServer::TYPE_HTTP,
87 FilePath(FILE_PATH_LITERAL("chrome/test/data"))));
[email protected]d4515eb2009-01-30 00:40:4388}
89
[email protected]c4ff4952010-01-08 19:12:4790InProcessBrowserTest::~InProcessBrowserTest() {
91}
92
[email protected]d4515eb2009-01-30 00:40:4393void InProcessBrowserTest::SetUp() {
[email protected]fc82ccf02010-10-15 18:12:4794 // Create a temporary user data directory if required.
95 ASSERT_TRUE(CreateUserDataDirectory())
96 << "Could not create user data directory.";
[email protected]4a44bc32010-05-28 22:22:4497
[email protected]583844c2011-08-27 00:38:3598 // Undo TestingBrowserProcess creation in ChromeTestSuite.
99 // TODO(phajdan.jr): Extract a smaller test suite so we don't need this.
100 DCHECK(g_browser_process);
101 delete g_browser_process;
102 g_browser_process = NULL;
[email protected]298883bc2010-04-30 14:50:58103
[email protected]470f7a52010-09-23 20:20:38104 // Allow subclasses the opportunity to make changes to the default user data
105 // dir before running any tests.
[email protected]fc82ccf02010-10-15 18:12:47106 ASSERT_TRUE(SetUpUserDataDirectory())
107 << "Could not set up user data directory.";
[email protected]d4515eb2009-01-30 00:40:43108
109 // Don't delete the resources when BrowserMain returns. Many ui classes
110 // cache SkBitmaps in a static field so that if we delete the resource
111 // bundle we'll crash.
112 browser_shutdown::delete_resources_on_shutdown = false;
113
[email protected]06cc083a2011-03-01 02:28:42114 CommandLine* command_line = CommandLine::ForCurrentProcess();
115 // Allow subclasses to change the command line before running any tests.
[email protected]9665fa62009-04-13 22:15:29116 SetUpCommandLine(command_line);
[email protected]03c79d502010-11-16 00:38:26117 // Add command line arguments that are used by all InProcessBrowserTests.
118 PrepareTestCommandLine(command_line);
[email protected]9665fa62009-04-13 22:15:29119
[email protected]15fd0df2011-04-29 16:00:16120 // Single-process mode is not set in BrowserMain, so process it explicitly,
121 // and set up renderer.
122 if (command_line->HasSwitch(switches::kSingleProcess)) {
[email protected]8bcdec92009-02-25 16:15:18123 RenderProcessHost::set_run_renderer_in_process(true);
[email protected]a77e4bc2011-06-29 02:06:28124 single_process_renderer_client_.reset(
125 new content::MockContentRendererClient);
[email protected]15fd0df2011-04-29 16:00:16126 content::GetContentClient()->set_renderer(
127 single_process_renderer_client_.get());
128 }
[email protected]8bcdec92009-02-25 16:15:18129
[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_)
[email protected]f353bed2011-03-08 18:40:39168 BrowserFrameWin::SetShowState(SW_HIDE);
[email protected]03c79d502010-11-16 00:38:26169#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() {
[email protected]b7c64d62011-08-11 00:08:04223 DCHECK(!g_browser_process);
[email protected]d4515eb2009-01-30 00:40:43224
225 browser_shutdown::delete_resources_on_shutdown = true;
226
[email protected]eb1bd832010-05-18 20:39:58227#if defined(OS_WIN)
[email protected]f353bed2011-03-08 18:40:39228 BrowserFrameWin::SetShowState(-1);
[email protected]108c2a12009-06-05 22:18:09229#endif
[email protected]d4515eb2009-01-30 00:40:43230}
231
[email protected]616381f02010-11-02 15:15:33232void InProcessBrowserTest::AddTabAtIndexToBrowser(
233 Browser* browser,
234 int index,
235 const GURL& url,
236 PageTransition::Type transition) {
237 browser::NavigateParams params(browser, url, transition);
238 params.tabstrip_index = index;
239 params.disposition = NEW_FOREGROUND_TAB;
240 browser::Navigate(&params);
241}
242
243void InProcessBrowserTest::AddTabAtIndex(
244 int index,
245 const GURL& url,
246 PageTransition::Type transition) {
247 AddTabAtIndexToBrowser(browser(), index, url, transition);
248}
249
[email protected]fadc607b62011-02-07 17:55:50250bool InProcessBrowserTest::SetUpUserDataDirectory() {
251 return true;
252}
253
[email protected]d4515eb2009-01-30 00:40:43254// Creates a browser with a single tab (about:blank), waits for the tab to
255// finish loading and shows the browser.
256Browser* InProcessBrowserTest::CreateBrowser(Profile* profile) {
257 Browser* browser = Browser::Create(profile);
[email protected]de4943f2011-07-28 16:25:14258 AddBlankTabAndShow(browser);
[email protected]e1c10f182010-09-30 08:53:06259 return browser;
260}
[email protected]d4515eb2009-01-30 00:40:43261
[email protected]46f979d2011-01-10 17:08:44262Browser* InProcessBrowserTest::CreateIncognitoBrowser() {
263 // Create a new browser with using the incognito profile.
264 Browser* incognito =
265 Browser::Create(browser()->profile()->GetOffTheRecordProfile());
[email protected]de4943f2011-07-28 16:25:14266 AddBlankTabAndShow(incognito);
[email protected]46f979d2011-01-10 17:08:44267 return incognito;
268}
269
[email protected]e1c10f182010-09-30 08:53:06270Browser* InProcessBrowserTest::CreateBrowserForPopup(Profile* profile) {
[email protected]1b74d2122010-10-06 16:49:16271 Browser* browser = Browser::CreateForType(Browser::TYPE_POPUP, profile);
[email protected]de4943f2011-07-28 16:25:14272 AddBlankTabAndShow(browser);
[email protected]d4515eb2009-01-30 00:40:43273 return browser;
274}
275
[email protected]de4943f2011-07-28 16:25:14276void InProcessBrowserTest::AddBlankTabAndShow(Browser* browser) {
[email protected]3114db2c2011-09-12 20:09:05277 ui_test_utils::WindowedNotificationObserver observer(
278 content::NOTIFICATION_LOAD_STOP,
279 NotificationService::AllSources());
[email protected]de4943f2011-07-28 16:25:14280 browser->AddSelectedTabWithURL(
281 GURL(chrome::kAboutBlankURL), PageTransition::START_PAGE);
[email protected]3114db2c2011-09-12 20:09:05282 observer.Wait();
[email protected]de4943f2011-07-28 16:25:14283
284 browser->window()->Show();
285}
286
[email protected]b25e61d2011-08-23 09:02:01287#if defined(OS_POSIX)
288// On SIGTERM (sent by the runner on timeouts), dump a stack trace (to make
289// debugging easier) and also exit with a known error code (so that the test
290// framework considers this a failure -- http://crbug.com/57578).
291static void DumpStackTraceSignalHandler(int signal) {
292 base::debug::StackTrace().PrintBacktrace();
293 _exit(128 + signal);
294}
295#endif // defined(OS_POSIX)
296
[email protected]64f19312010-04-13 22:30:01297void InProcessBrowserTest::RunTestOnMainThreadLoop() {
[email protected]00d0ac22010-10-05 09:30:00298#if defined(OS_POSIX)
[email protected]b25e61d2011-08-23 09:02:01299 signal(SIGTERM, DumpStackTraceSignalHandler);
[email protected]00d0ac22010-10-05 09:30:00300#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
[email protected]bc63a072011-06-28 21:12:57354 // Invoke CloseAllBrowsersAndMayExit on a running message loop.
355 // CloseAllBrowsersAndMayExit exits the message loop after everything has been
[email protected]64f19312010-04-13 22:30:01356 // shut down properly.
357 MessageLoopForUI::current()->PostTask(
358 FROM_HERE,
[email protected]bc63a072011-06-28 21:12:57359 NewRunnableFunction(&BrowserList::AttemptExit));
[email protected]64f19312010-04-13 22:30:01360 ui_test_utils::RunMessageLoop();
361}