Merge html-office-public repo into src
[chromium-blink-merge.git] / chrome / test / base / in_process_browser_test.cc
blob5b01038eb80b7beadf7ddb349b1ddfaca63c81aa
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/test/base/in_process_browser_test.h"
7 #include "base/auto_reset.h"
8 #include "base/basictypes.h"
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/files/file_path.h"
12 #include "base/files/file_util.h"
13 #include "base/lazy_instance.h"
14 #include "base/path_service.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/test/test_file_util.h"
17 #include "base/threading/non_thread_safe.h"
18 #include "chrome/browser/browser_process.h"
19 #include "chrome/browser/lifetime/application_lifetime.h"
20 #include "chrome/browser/net/net_error_tab_helper.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/profiles/profile_manager.h"
23 #include "chrome/browser/ui/browser.h"
24 #include "chrome/browser/ui/browser_finder.h"
25 #include "chrome/browser/ui/browser_list.h"
26 #include "chrome/browser/ui/browser_list_observer.h"
27 #include "chrome/browser/ui/browser_navigator.h"
28 #include "chrome/browser/ui/browser_tabstrip.h"
29 #include "chrome/browser/ui/browser_window.h"
30 #include "chrome/browser/ui/host_desktop.h"
31 #include "chrome/browser/ui/tabs/tab_strip_model.h"
32 #include "chrome/common/chrome_constants.h"
33 #include "chrome/common/chrome_paths.h"
34 #include "chrome/common/chrome_switches.h"
35 #include "chrome/common/logging_chrome.h"
36 #include "chrome/common/url_constants.h"
37 #include "chrome/renderer/chrome_content_renderer_client.h"
38 #include "chrome/test/base/chrome_test_suite.h"
39 #include "chrome/test/base/test_launcher_utils.h"
40 #include "chrome/test/base/test_switches.h"
41 #include "chrome/test/base/testing_browser_process.h"
42 #include "components/google/core/browser/google_util.h"
43 #include "components/os_crypt/os_crypt.h"
44 #include "content/public/browser/notification_service.h"
45 #include "content/public/browser/notification_types.h"
46 #include "content/public/test/browser_test_utils.h"
47 #include "content/public/test/test_launcher.h"
48 #include "content/public/test/test_navigation_observer.h"
49 #include "net/test/embedded_test_server/embedded_test_server.h"
50 #include "net/test/spawned_test_server/spawned_test_server.h"
52 #if defined(OS_MACOSX)
53 #include "base/mac/scoped_nsautorelease_pool.h"
54 #endif
56 #if defined(OS_WIN)
57 #include "base/win/scoped_com_initializer.h"
58 #include "base/win/windows_version.h"
59 #include "ui/base/win/atl_module.h"
60 #include "win8/test/metro_registration_helper.h"
61 #include "win8/test/test_registrar_constants.h"
62 #endif
64 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
65 #include "chrome/browser/captive_portal/captive_portal_service.h"
66 #endif
68 #if !defined(OS_ANDROID) && !defined(OS_IOS)
69 #include "components/storage_monitor/test_storage_monitor.h"
70 #endif
72 #if defined(OS_CHROMEOS)
73 #include "chrome/browser/chromeos/input_method/input_method_configuration.h"
74 #endif
76 namespace {
78 // Passed as value of kTestType.
79 const char kBrowserTestType[] = "browser";
81 // A BrowserListObserver that makes sure that all browsers created are on the
82 // |allowed_desktop_|.
83 class SingleDesktopTestObserver : public chrome::BrowserListObserver,
84 public base::NonThreadSafe {
85 public:
86 explicit SingleDesktopTestObserver(chrome::HostDesktopType allowed_desktop);
87 ~SingleDesktopTestObserver() override;
89 // chrome::BrowserListObserver:
90 void OnBrowserAdded(Browser* browser) override;
92 private:
93 chrome::HostDesktopType allowed_desktop_;
95 DISALLOW_COPY_AND_ASSIGN(SingleDesktopTestObserver);
98 SingleDesktopTestObserver::SingleDesktopTestObserver(
99 chrome::HostDesktopType allowed_desktop)
100 : allowed_desktop_(allowed_desktop) {
101 BrowserList::AddObserver(this);
104 SingleDesktopTestObserver::~SingleDesktopTestObserver() {
105 BrowserList::RemoveObserver(this);
108 void SingleDesktopTestObserver::OnBrowserAdded(Browser* browser) {
109 CHECK(CalledOnValidThread());
110 CHECK_EQ(browser->host_desktop_type(), allowed_desktop_);
113 } // namespace
115 InProcessBrowserTest::InProcessBrowserTest()
116 : browser_(NULL),
117 exit_when_last_browser_closes_(true),
118 open_about_blank_on_browser_launch_(true),
119 multi_desktop_test_(false)
120 #if defined(OS_MACOSX)
121 , autorelease_pool_(NULL)
122 #endif // OS_MACOSX
124 #if defined(OS_MACOSX)
125 // TODO(phajdan.jr): Make browser_tests self-contained on Mac, remove this.
126 // Before we run the browser, we have to hack the path to the exe to match
127 // what it would be if Chrome was running, because it is used to fork renderer
128 // processes, on Linux at least (failure to do so will cause a browser_test to
129 // be run instead of a renderer).
130 base::FilePath chrome_path;
131 CHECK(PathService::Get(base::FILE_EXE, &chrome_path));
132 chrome_path = chrome_path.DirName();
133 chrome_path = chrome_path.Append(chrome::kBrowserProcessExecutablePath);
134 CHECK(PathService::Override(base::FILE_EXE, chrome_path));
135 #endif // defined(OS_MACOSX)
137 CreateTestServer(base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
138 base::FilePath src_dir;
139 CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &src_dir));
140 base::FilePath test_data_dir = src_dir.AppendASCII("chrome/test/data");
141 embedded_test_server()->ServeFilesFromDirectory(test_data_dir);
143 // chrome::DIR_TEST_DATA isn't going to be setup until after we call
144 // ContentMain. However that is after tests' constructors or SetUp methods,
145 // which sometimes need it. So just override it.
146 CHECK(PathService::Override(chrome::DIR_TEST_DATA, test_data_dir));
149 InProcessBrowserTest::~InProcessBrowserTest() {
152 void InProcessBrowserTest::SetUp() {
153 // Browser tests will create their own g_browser_process later.
154 DCHECK(!g_browser_process);
156 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
158 // Auto-reload breaks many browser tests, which assume error pages won't be
159 // reloaded out from under them. Tests that expect or desire this behavior can
160 // append switches::kEnableOfflineAutoReload, which will override the disable
161 // here.
162 command_line->AppendSwitch(switches::kDisableOfflineAutoReload);
164 // Allow subclasses to change the command line before running any tests.
165 SetUpCommandLine(command_line);
166 // Add command line arguments that are used by all InProcessBrowserTests.
167 PrepareTestCommandLine(command_line);
169 // Create a temporary user data directory if required.
170 ASSERT_TRUE(CreateUserDataDirectory())
171 << "Could not create user data directory.";
173 // Allow subclasses the opportunity to make changes to the default user data
174 // dir before running any tests.
175 ASSERT_TRUE(SetUpUserDataDirectory())
176 << "Could not set up user data directory.";
178 #if defined(OS_CHROMEOS)
179 // Make sure that the log directory exists.
180 base::FilePath log_dir = logging::GetSessionLogFile(*command_line).DirName();
181 base::CreateDirectory(log_dir);
182 // Disable IME extension loading to avoid many browser tests failures.
183 chromeos::input_method::DisableExtensionLoading();
184 #endif // defined(OS_CHROMEOS)
186 #if defined(OS_MACOSX)
187 // Always use the MockKeychain if OS encription is used (which is when
188 // anything sensitive gets stored, including Cookies). Without this,
189 // many tests will hang waiting for a user to approve KeyChain access.
190 OSCrypt::UseMockKeychain(true);
191 #endif
193 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
194 CaptivePortalService::set_state_for_testing(
195 CaptivePortalService::DISABLED_FOR_TESTING);
196 #endif
198 chrome_browser_net::NetErrorTabHelper::set_state_for_testing(
199 chrome_browser_net::NetErrorTabHelper::TESTING_FORCE_DISABLED);
201 google_util::SetMockLinkDoctorBaseURLForTesting();
203 #if defined(OS_WIN)
204 base::win::Version version = base::win::GetVersion();
205 // Although Ash officially is only supported for users on Win7+, we still run
206 // ash_unittests on Vista builders, so we still need to initialize COM.
207 if (version >= base::win::VERSION_VISTA &&
208 base::CommandLine::ForCurrentProcess()->HasSwitch(
209 switches::kAshBrowserTests)) {
210 com_initializer_.reset(new base::win::ScopedCOMInitializer());
211 ui::win::CreateATLModuleIfNeeded();
212 if (version >= base::win::VERSION_WIN8)
213 ASSERT_TRUE(win8::MakeTestDefaultBrowserSynchronously());
215 #endif
217 BrowserTestBase::SetUp();
220 void InProcessBrowserTest::PrepareTestCommandLine(
221 base::CommandLine* command_line) {
222 // Propagate commandline settings from test_launcher_utils.
223 test_launcher_utils::PrepareBrowserCommandLineForTests(command_line);
225 // This is a Browser test.
226 command_line->AppendSwitchASCII(switches::kTestType, kBrowserTestType);
228 #if defined(OS_WIN)
229 if (command_line->HasSwitch(switches::kAshBrowserTests)) {
230 command_line->AppendSwitchNative(switches::kViewerLaunchViaAppId,
231 win8::test::kDefaultTestAppUserModelId);
232 // Ash already launches with a single browser opened, add kSilentLaunch to
233 // make sure StartupBrowserCreator doesn't attempt to launch a browser on
234 // the native desktop on startup.
235 command_line->AppendSwitch(switches::kSilentLaunch);
237 #endif
239 #if defined(OS_MACOSX)
240 // Explicitly set the path of the binary used for child processes, otherwise
241 // they'll try to use browser_tests which doesn't contain ChromeMain.
242 base::FilePath subprocess_path;
243 PathService::Get(base::FILE_EXE, &subprocess_path);
244 // Recreate the real environment, run the helper within the app bundle.
245 subprocess_path = subprocess_path.DirName().DirName();
246 DCHECK_EQ(subprocess_path.BaseName().value(), "Contents");
247 subprocess_path =
248 subprocess_path.Append("Versions").Append(chrome::kChromeVersion);
249 subprocess_path =
250 subprocess_path.Append(chrome::kHelperProcessExecutablePath);
251 command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
252 subprocess_path);
253 #endif
255 // TODO(pkotwicz): Investigate if we can remove this switch.
256 if (exit_when_last_browser_closes_)
257 command_line->AppendSwitch(switches::kDisableZeroBrowsersOpenForTests);
259 if (open_about_blank_on_browser_launch_ && command_line->GetArgs().empty())
260 command_line->AppendArg(url::kAboutBlankURL);
263 bool InProcessBrowserTest::CreateUserDataDirectory() {
264 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
265 base::FilePath user_data_dir =
266 command_line->GetSwitchValuePath(switches::kUserDataDir);
267 if (user_data_dir.empty()) {
268 if (temp_user_data_dir_.CreateUniqueTempDir() &&
269 temp_user_data_dir_.IsValid()) {
270 user_data_dir = temp_user_data_dir_.path();
271 } else {
272 LOG(ERROR) << "Could not create temporary user data directory \""
273 << temp_user_data_dir_.path().value() << "\".";
274 return false;
277 return test_launcher_utils::OverrideUserDataDir(user_data_dir);
280 void InProcessBrowserTest::TearDown() {
281 DCHECK(!g_browser_process);
282 #if defined(OS_WIN)
283 com_initializer_.reset();
284 #endif
285 BrowserTestBase::TearDown();
288 // TODO(alexmos): This function should expose success of the underlying
289 // navigation to tests, which should make sure navigations succeed when
290 // appropriate. See https://crbug.com/425335
291 void InProcessBrowserTest::AddTabAtIndexToBrowser(
292 Browser* browser,
293 int index,
294 const GURL& url,
295 ui::PageTransition transition,
296 bool check_navigation_success) {
297 chrome::NavigateParams params(browser, url, transition);
298 params.tabstrip_index = index;
299 params.disposition = NEW_FOREGROUND_TAB;
300 chrome::Navigate(&params);
302 if (check_navigation_success)
303 content::WaitForLoadStop(params.target_contents);
304 else
305 content::WaitForLoadStopWithoutSuccessCheck(params.target_contents);
308 void InProcessBrowserTest::AddTabAtIndex(
309 int index,
310 const GURL& url,
311 ui::PageTransition transition) {
312 AddTabAtIndexToBrowser(browser(), index, url, transition, true);
315 bool InProcessBrowserTest::SetUpUserDataDirectory() {
316 return true;
319 // Creates a browser with a single tab (about:blank), waits for the tab to
320 // finish loading and shows the browser.
321 Browser* InProcessBrowserTest::CreateBrowser(Profile* profile) {
322 Browser* browser = new Browser(
323 Browser::CreateParams(profile, chrome::GetActiveDesktop()));
324 AddBlankTabAndShow(browser);
325 return browser;
328 Browser* InProcessBrowserTest::CreateIncognitoBrowser() {
329 // Create a new browser with using the incognito profile.
330 Browser* incognito = new Browser(
331 Browser::CreateParams(browser()->profile()->GetOffTheRecordProfile(),
332 chrome::GetActiveDesktop()));
333 AddBlankTabAndShow(incognito);
334 return incognito;
337 Browser* InProcessBrowserTest::CreateBrowserForPopup(Profile* profile) {
338 Browser* browser =
339 new Browser(Browser::CreateParams(Browser::TYPE_POPUP, profile,
340 chrome::GetActiveDesktop()));
341 AddBlankTabAndShow(browser);
342 return browser;
345 Browser* InProcessBrowserTest::CreateBrowserForApp(
346 const std::string& app_name,
347 Profile* profile) {
348 Browser* browser = new Browser(
349 Browser::CreateParams::CreateForApp(
350 app_name, false /* trusted_source */, gfx::Rect(), profile,
351 chrome::GetActiveDesktop()));
352 AddBlankTabAndShow(browser);
353 return browser;
356 void InProcessBrowserTest::AddBlankTabAndShow(Browser* browser) {
357 content::WindowedNotificationObserver observer(
358 content::NOTIFICATION_LOAD_STOP,
359 content::NotificationService::AllSources());
360 chrome::AddSelectedTabWithURL(browser,
361 GURL(url::kAboutBlankURL),
362 ui::PAGE_TRANSITION_AUTO_TOPLEVEL);
363 observer.Wait();
365 browser->window()->Show();
368 #if !defined(OS_MACOSX)
369 base::CommandLine InProcessBrowserTest::GetCommandLineForRelaunch() {
370 base::CommandLine new_command_line(
371 base::CommandLine::ForCurrentProcess()->GetProgram());
372 base::CommandLine::SwitchMap switches =
373 base::CommandLine::ForCurrentProcess()->GetSwitches();
374 switches.erase(switches::kUserDataDir);
375 switches.erase(content::kSingleProcessTestsFlag);
376 switches.erase(switches::kSingleProcess);
377 new_command_line.AppendSwitch(content::kLaunchAsBrowser);
379 base::FilePath user_data_dir;
380 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
381 new_command_line.AppendSwitchPath(switches::kUserDataDir, user_data_dir);
383 for (base::CommandLine::SwitchMap::const_iterator iter = switches.begin();
384 iter != switches.end(); ++iter) {
385 new_command_line.AppendSwitchNative((*iter).first, (*iter).second);
387 return new_command_line;
389 #endif
391 void InProcessBrowserTest::RunTestOnMainThreadLoop() {
392 // Pump startup related events.
393 content::RunAllPendingInMessageLoop();
395 chrome::HostDesktopType active_desktop = chrome::GetActiveDesktop();
396 // Self-adds/removes itself from the BrowserList observers.
397 scoped_ptr<SingleDesktopTestObserver> single_desktop_test_observer;
398 if (!multi_desktop_test_) {
399 single_desktop_test_observer.reset(
400 new SingleDesktopTestObserver(active_desktop));
403 const BrowserList* active_browser_list =
404 BrowserList::GetInstance(active_desktop);
405 if (!active_browser_list->empty()) {
406 browser_ = active_browser_list->get(0);
407 #if defined(USE_ASH)
408 // There are cases where windows get created maximized by default.
409 if (browser_->window()->IsMaximized())
410 browser_->window()->Restore();
411 #endif
412 content::WaitForLoadStop(
413 browser_->tab_strip_model()->GetActiveWebContents());
416 #if !defined(OS_ANDROID) && !defined(OS_IOS)
417 // Do not use the real StorageMonitor for tests, which introduces another
418 // source of variability and potential slowness.
419 ASSERT_TRUE(storage_monitor::TestStorageMonitor::CreateForBrowserTests());
420 #endif
422 #if defined(OS_MACOSX)
423 // On Mac, without the following autorelease pool, code which is directly
424 // executed (as opposed to executed inside a message loop) would autorelease
425 // objects into a higher-level pool. This pool is not recycled in-sync with
426 // the message loops' pools and causes problems with code relying on
427 // deallocation via an autorelease pool (such as browser window closure and
428 // browser shutdown). To avoid this, the following pool is recycled after each
429 // time code is directly executed.
430 autorelease_pool_ = new base::mac::ScopedNSAutoreleasePool;
431 #endif
433 // Pump any pending events that were created as a result of creating a
434 // browser.
435 content::RunAllPendingInMessageLoop();
437 SetUpOnMainThread();
438 #if defined(OS_MACOSX)
439 autorelease_pool_->Recycle();
440 #endif
442 if (!HasFatalFailure())
443 RunTestOnMainThread();
444 #if defined(OS_MACOSX)
445 autorelease_pool_->Recycle();
446 #endif
448 // Invoke cleanup and quit even if there are failures. This is similar to
449 // gtest in that it invokes TearDown even if Setup fails.
450 TearDownOnMainThread();
451 #if defined(OS_MACOSX)
452 autorelease_pool_->Recycle();
453 #endif
455 // Sometimes tests leave Quit tasks in the MessageLoop (for shame), so let's
456 // run all pending messages here to avoid preempting the QuitBrowsers tasks.
457 // TODO(jbates) Once crbug.com/134753 is fixed, this can be removed because it
458 // will not be possible to post Quit tasks.
459 content::RunAllPendingInMessageLoop();
461 QuitBrowsers();
462 // All BrowserLists should be empty at this point.
463 for (chrome::HostDesktopType t = chrome::HOST_DESKTOP_TYPE_FIRST;
464 t < chrome::HOST_DESKTOP_TYPE_COUNT;
465 t = static_cast<chrome::HostDesktopType>(t + 1)) {
466 CHECK(BrowserList::GetInstance(t)->empty()) << t;
470 void InProcessBrowserTest::QuitBrowsers() {
471 if (chrome::GetTotalBrowserCount() == 0) {
472 chrome::NotifyAppTerminating();
473 return;
476 // Invoke AttemptExit on a running message loop.
477 // AttemptExit exits the message loop after everything has been
478 // shut down properly.
479 base::MessageLoopForUI::current()->PostTask(FROM_HERE,
480 base::Bind(&chrome::AttemptExit));
481 content::RunMessageLoop();
483 #if defined(OS_MACOSX)
484 // chrome::AttemptExit() will attempt to close all browsers by deleting
485 // their tab contents. The last tab contents being removed triggers closing of
486 // the browser window.
488 // On the Mac, this eventually reaches
489 // -[BrowserWindowController windowWillClose:], which will post a deferred
490 // -autorelease on itself to ultimately destroy the Browser object. The line
491 // below is necessary to pump these pending messages to ensure all Browsers
492 // get deleted.
493 content::RunAllPendingInMessageLoop();
494 delete autorelease_pool_;
495 autorelease_pool_ = NULL;
496 #endif