Update V8 to version 4.7.52.
[chromium-blink-merge.git] / chrome / test / base / in_process_browser_test.cc
blob5b83e3b544deefeb6b39b50cb1fb1bfa839e1f0d
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/location.h"
15 #include "base/path_service.h"
16 #include "base/single_thread_task_runner.h"
17 #include "base/strings/string_number_conversions.h"
18 #include "base/test/test_file_util.h"
19 #include "base/thread_task_runner_handle.h"
20 #include "base/threading/non_thread_safe.h"
21 #include "chrome/browser/after_startup_task_utils.h"
22 #include "chrome/browser/browser_process.h"
23 #include "chrome/browser/chrome_notification_types.h"
24 #include "chrome/browser/devtools/devtools_window.h"
25 #include "chrome/browser/lifetime/application_lifetime.h"
26 #include "chrome/browser/net/net_error_tab_helper.h"
27 #include "chrome/browser/profiles/profile.h"
28 #include "chrome/browser/profiles/profile_manager.h"
29 #include "chrome/browser/ui/browser.h"
30 #include "chrome/browser/ui/browser_commands.h"
31 #include "chrome/browser/ui/browser_finder.h"
32 #include "chrome/browser/ui/browser_list.h"
33 #include "chrome/browser/ui/browser_list_observer.h"
34 #include "chrome/browser/ui/browser_navigator.h"
35 #include "chrome/browser/ui/browser_tabstrip.h"
36 #include "chrome/browser/ui/browser_window.h"
37 #include "chrome/browser/ui/host_desktop.h"
38 #include "chrome/browser/ui/tabs/tab_strip_model.h"
39 #include "chrome/common/chrome_constants.h"
40 #include "chrome/common/chrome_paths.h"
41 #include "chrome/common/chrome_switches.h"
42 #include "chrome/common/logging_chrome.h"
43 #include "chrome/common/url_constants.h"
44 #include "chrome/renderer/chrome_content_renderer_client.h"
45 #include "chrome/test/base/chrome_test_suite.h"
46 #include "chrome/test/base/test_launcher_utils.h"
47 #include "chrome/test/base/test_switches.h"
48 #include "chrome/test/base/testing_browser_process.h"
49 #include "components/google/core/browser/google_util.h"
50 #include "components/os_crypt/os_crypt.h"
51 #include "content/public/browser/devtools_agent_host.h"
52 #include "content/public/browser/notification_service.h"
53 #include "content/public/browser/notification_types.h"
54 #include "content/public/test/browser_test_utils.h"
55 #include "content/public/test/test_launcher.h"
56 #include "content/public/test/test_navigation_observer.h"
57 #include "net/test/embedded_test_server/embedded_test_server.h"
58 #include "net/test/spawned_test_server/spawned_test_server.h"
60 #if defined(OS_MACOSX)
61 #include "base/mac/scoped_nsautorelease_pool.h"
62 #include "chrome/test/base/scoped_bundle_swizzler_mac.h"
63 #endif
65 #if defined(OS_WIN)
66 #include "base/win/scoped_com_initializer.h"
67 #include "base/win/windows_version.h"
68 #include "ui/base/win/atl_module.h"
69 #include "win8/test/metro_registration_helper.h"
70 #include "win8/test/test_registrar_constants.h"
71 #endif
73 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
74 #include "chrome/browser/captive_portal/captive_portal_service.h"
75 #endif
77 #if !defined(OS_ANDROID) && !defined(OS_IOS)
78 #include "components/storage_monitor/test_storage_monitor.h"
79 #endif
81 #if defined(OS_CHROMEOS)
82 #include "chrome/browser/chromeos/input_method/input_method_configuration.h"
83 #endif
85 namespace {
87 // Passed as value of kTestType.
88 const char kBrowserTestType[] = "browser";
90 // A BrowserListObserver that makes sure that all browsers created are on the
91 // |allowed_desktop_|.
92 class SingleDesktopTestObserver : public chrome::BrowserListObserver,
93 public base::NonThreadSafe {
94 public:
95 explicit SingleDesktopTestObserver(chrome::HostDesktopType allowed_desktop);
96 ~SingleDesktopTestObserver() override;
98 // chrome::BrowserListObserver:
99 void OnBrowserAdded(Browser* browser) override;
101 private:
102 chrome::HostDesktopType allowed_desktop_;
104 DISALLOW_COPY_AND_ASSIGN(SingleDesktopTestObserver);
107 SingleDesktopTestObserver::SingleDesktopTestObserver(
108 chrome::HostDesktopType allowed_desktop)
109 : allowed_desktop_(allowed_desktop) {
110 BrowserList::AddObserver(this);
113 SingleDesktopTestObserver::~SingleDesktopTestObserver() {
114 BrowserList::RemoveObserver(this);
117 void SingleDesktopTestObserver::OnBrowserAdded(Browser* browser) {
118 CHECK(CalledOnValidThread());
119 CHECK_EQ(browser->host_desktop_type(), allowed_desktop_);
122 } // namespace
124 // Library used for testing accessibility.
125 const base::FilePath::CharType kAXSTesting[] =
126 FILE_PATH_LITERAL("third_party/accessibility-audit/axs_testing.js");
127 // JavaScript snippet to configure and run the accessibility audit.
128 const char kAccessibilityTestString[] =
129 "var config = new axs.AuditConfiguration();"
130 "/* Disable warning about rules that cannot be checked. */"
131 "config.showUnsupportedRulesWarning = false;"
132 "config.auditRulesToIgnore = ["
133 " /*"
134 " * The 'elements with meaningful background image' accessibility"
135 " * audit (AX_IMAGE_01) does not apply, since Chrome doesn't"
136 " * disable background images in high-contrast mode like some"
137 " * browsers do."
138 " */"
139 " 'elementsWithMeaningfulBackgroundImage',"
140 " /*"
141 " * Most WebUI pages are inside an IFrame, so the 'web page should"
142 " * have a title that describes topic or purpose' test (AX_TITLE_01)"
143 " * generally does not apply."
144 " */"
145 " 'pageWithoutTitle',"
146 " /*"
147 " * Enable when crbug.com/267035 is fixed."
148 " * Until then it's just noise."
149 " */"
150 " 'lowContrastElements'"
151 "];"
152 "var result = axs.Audit.run(config);"
153 "var error = '';"
154 "for (var i = 0; i < result.length; ++i) {"
155 " if (result[i].result == axs.constants.AuditResult.FAIL) {"
156 " error = axs.Audit.createReport(result);"
157 " break;"
158 " }"
160 "domAutomationController.send(error);";
162 InProcessBrowserTest::InProcessBrowserTest()
163 : browser_(NULL),
164 exit_when_last_browser_closes_(true),
165 open_about_blank_on_browser_launch_(true),
166 multi_desktop_test_(false),
167 run_accessibility_checks_for_test_case_(false)
168 #if defined(OS_MACOSX)
169 , autorelease_pool_(NULL)
170 #endif // OS_MACOSX
172 #if defined(OS_MACOSX)
173 // TODO(phajdan.jr): Make browser_tests self-contained on Mac, remove this.
174 // Before we run the browser, we have to hack the path to the exe to match
175 // what it would be if Chrome was running, because it is used to fork renderer
176 // processes, on Linux at least (failure to do so will cause a browser_test to
177 // be run instead of a renderer).
178 base::FilePath chrome_path;
179 CHECK(PathService::Get(base::FILE_EXE, &chrome_path));
180 chrome_path = chrome_path.DirName();
181 chrome_path = chrome_path.Append(chrome::kBrowserProcessExecutablePath);
182 CHECK(PathService::Override(base::FILE_EXE, chrome_path));
183 #endif // defined(OS_MACOSX)
185 CreateTestServer(base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
186 base::FilePath src_dir;
187 CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &src_dir));
188 base::FilePath test_data_dir = src_dir.AppendASCII("chrome/test/data");
189 embedded_test_server()->ServeFilesFromDirectory(test_data_dir);
191 // chrome::DIR_TEST_DATA isn't going to be setup until after we call
192 // ContentMain. However that is after tests' constructors or SetUp methods,
193 // which sometimes need it. So just override it.
194 CHECK(PathService::Override(chrome::DIR_TEST_DATA, test_data_dir));
196 #if defined(OS_MACOSX)
197 bundle_swizzler_.reset(new ScopedBundleSwizzlerMac);
198 #endif
201 InProcessBrowserTest::~InProcessBrowserTest() {
204 void InProcessBrowserTest::SetUp() {
205 // Browser tests will create their own g_browser_process later.
206 DCHECK(!g_browser_process);
208 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
210 // Auto-reload breaks many browser tests, which assume error pages won't be
211 // reloaded out from under them. Tests that expect or desire this behavior can
212 // append switches::kEnableOfflineAutoReload, which will override the disable
213 // here.
214 command_line->AppendSwitch(switches::kDisableOfflineAutoReload);
216 // Allow subclasses to change the command line before running any tests.
217 SetUpCommandLine(command_line);
218 // Add command line arguments that are used by all InProcessBrowserTests.
219 PrepareTestCommandLine(command_line);
221 // Create a temporary user data directory if required.
222 ASSERT_TRUE(CreateUserDataDirectory())
223 << "Could not create user data directory.";
225 // Allow subclasses the opportunity to make changes to the default user data
226 // dir before running any tests.
227 ASSERT_TRUE(SetUpUserDataDirectory())
228 << "Could not set up user data directory.";
230 #if defined(OS_CHROMEOS)
231 // Make sure that the log directory exists.
232 base::FilePath log_dir = logging::GetSessionLogFile(*command_line).DirName();
233 base::CreateDirectory(log_dir);
234 // Disable IME extension loading to avoid many browser tests failures.
235 chromeos::input_method::DisableExtensionLoading();
236 #endif // defined(OS_CHROMEOS)
238 #if defined(OS_MACOSX)
239 // Always use the MockKeychain if OS encription is used (which is when
240 // anything sensitive gets stored, including Cookies). Without this,
241 // many tests will hang waiting for a user to approve KeyChain access.
242 OSCrypt::UseMockKeychain(true);
243 #endif
245 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
246 CaptivePortalService::set_state_for_testing(
247 CaptivePortalService::DISABLED_FOR_TESTING);
248 #endif
250 chrome_browser_net::NetErrorTabHelper::set_state_for_testing(
251 chrome_browser_net::NetErrorTabHelper::TESTING_FORCE_DISABLED);
253 google_util::SetMockLinkDoctorBaseURLForTesting();
255 #if defined(OS_WIN)
256 base::win::Version version = base::win::GetVersion();
257 // Although Ash officially is only supported for users on Win7+, we still run
258 // ash_unittests on Vista builders, so we still need to initialize COM.
259 if (version >= base::win::VERSION_VISTA &&
260 base::CommandLine::ForCurrentProcess()->HasSwitch(
261 switches::kAshBrowserTests)) {
262 com_initializer_.reset(new base::win::ScopedCOMInitializer());
263 ui::win::CreateATLModuleIfNeeded();
264 if (version >= base::win::VERSION_WIN8)
265 ASSERT_TRUE(win8::MakeTestDefaultBrowserSynchronously());
267 #endif
269 BrowserTestBase::SetUp();
272 void InProcessBrowserTest::PrepareTestCommandLine(
273 base::CommandLine* command_line) {
274 // Propagate commandline settings from test_launcher_utils.
275 test_launcher_utils::PrepareBrowserCommandLineForTests(command_line);
277 // This is a Browser test.
278 command_line->AppendSwitchASCII(switches::kTestType, kBrowserTestType);
280 #if defined(OS_WIN)
281 if (command_line->HasSwitch(switches::kAshBrowserTests)) {
282 command_line->AppendSwitchNative(switches::kViewerLaunchViaAppId,
283 win8::test::kDefaultTestAppUserModelId);
284 // Ash already launches with a single browser opened, add kSilentLaunch to
285 // make sure StartupBrowserCreator doesn't attempt to launch a browser on
286 // the native desktop on startup.
287 command_line->AppendSwitch(switches::kSilentLaunch);
289 #endif
291 #if defined(OS_MACOSX)
292 // Explicitly set the path of the binary used for child processes, otherwise
293 // they'll try to use browser_tests which doesn't contain ChromeMain.
294 base::FilePath subprocess_path;
295 PathService::Get(base::FILE_EXE, &subprocess_path);
296 // Recreate the real environment, run the helper within the app bundle.
297 subprocess_path = subprocess_path.DirName().DirName();
298 DCHECK_EQ(subprocess_path.BaseName().value(), "Contents");
299 subprocess_path =
300 subprocess_path.Append("Versions").Append(chrome::kChromeVersion);
301 subprocess_path =
302 subprocess_path.Append(chrome::kHelperProcessExecutablePath);
303 command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
304 subprocess_path);
305 #endif
307 // TODO(pkotwicz): Investigate if we can remove this switch.
308 if (exit_when_last_browser_closes_)
309 command_line->AppendSwitch(switches::kDisableZeroBrowsersOpenForTests);
311 if (open_about_blank_on_browser_launch_ && command_line->GetArgs().empty())
312 command_line->AppendArg(url::kAboutBlankURL);
315 bool InProcessBrowserTest::RunAccessibilityChecks(std::string* error_message) {
316 if (!browser()) {
317 *error_message = "browser is NULL";
318 return false;
320 auto tab_strip = browser()->tab_strip_model();
321 if (!tab_strip) {
322 *error_message = "tab_strip is NULL";
323 return false;
325 auto web_contents = tab_strip->GetActiveWebContents();
326 if (!web_contents) {
327 *error_message = "web_contents is NULL";
328 return false;
330 auto focused_frame = web_contents->GetFocusedFrame();
331 if (!focused_frame) {
332 *error_message = "focused_frame is NULL";
333 return false;
336 // Load accessibility library.
337 base::FilePath src_dir;
338 if (!PathService::Get(base::DIR_SOURCE_ROOT, &src_dir)) {
339 *error_message = "PathService::Get failed";
340 return false;
342 base::FilePath script_path = src_dir.Append(kAXSTesting);
343 std::string script;
344 if (!base::ReadFileToString(script_path, &script)) {
345 *error_message = "Could not read accessibility library";
346 return false;
348 if (!content::ExecuteScript(web_contents, script)) {
349 *error_message = "Failed to load accessibility library";
350 return false;
353 // Run accessibility audit.
354 if (!content::ExecuteScriptAndExtractString(focused_frame,
355 kAccessibilityTestString,
356 error_message)) {
357 *error_message = "Failed to run accessibility audit";
358 return false;
361 // Test result should be empty if there are no errors.
362 return error_message->empty();
365 bool InProcessBrowserTest::CreateUserDataDirectory() {
366 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
367 base::FilePath user_data_dir =
368 command_line->GetSwitchValuePath(switches::kUserDataDir);
369 if (user_data_dir.empty()) {
370 if (temp_user_data_dir_.CreateUniqueTempDir() &&
371 temp_user_data_dir_.IsValid()) {
372 user_data_dir = temp_user_data_dir_.path();
373 } else {
374 LOG(ERROR) << "Could not create temporary user data directory \""
375 << temp_user_data_dir_.path().value() << "\".";
376 return false;
379 return test_launcher_utils::OverrideUserDataDir(user_data_dir);
382 void InProcessBrowserTest::TearDown() {
383 DCHECK(!g_browser_process);
384 #if defined(OS_WIN)
385 com_initializer_.reset();
386 #endif
387 BrowserTestBase::TearDown();
390 void InProcessBrowserTest::CloseBrowserSynchronously(Browser* browser) {
391 content::WindowedNotificationObserver observer(
392 chrome::NOTIFICATION_BROWSER_CLOSED,
393 content::Source<Browser>(browser));
394 CloseBrowserAsynchronously(browser);
395 observer.Wait();
398 void InProcessBrowserTest::CloseBrowserAsynchronously(Browser* browser) {
399 browser->window()->Close();
400 #if defined(OS_MACOSX)
401 // BrowserWindowController depends on the auto release pool being recycled
402 // in the message loop to delete itself.
403 AutoreleasePool()->Recycle();
404 #endif
407 void InProcessBrowserTest::CloseAllBrowsers() {
408 chrome::CloseAllBrowsers();
409 #if defined(OS_MACOSX)
410 // BrowserWindowController depends on the auto release pool being recycled
411 // in the message loop to delete itself.
412 AutoreleasePool()->Recycle();
413 #endif
416 // TODO(alexmos): This function should expose success of the underlying
417 // navigation to tests, which should make sure navigations succeed when
418 // appropriate. See https://crbug.com/425335
419 void InProcessBrowserTest::AddTabAtIndexToBrowser(
420 Browser* browser,
421 int index,
422 const GURL& url,
423 ui::PageTransition transition,
424 bool check_navigation_success) {
425 chrome::NavigateParams params(browser, url, transition);
426 params.tabstrip_index = index;
427 params.disposition = NEW_FOREGROUND_TAB;
428 chrome::Navigate(&params);
430 if (check_navigation_success)
431 content::WaitForLoadStop(params.target_contents);
432 else
433 content::WaitForLoadStopWithoutSuccessCheck(params.target_contents);
436 void InProcessBrowserTest::AddTabAtIndex(
437 int index,
438 const GURL& url,
439 ui::PageTransition transition) {
440 AddTabAtIndexToBrowser(browser(), index, url, transition, true);
443 bool InProcessBrowserTest::SetUpUserDataDirectory() {
444 return true;
447 #if !defined(OS_MACOSX)
448 void InProcessBrowserTest::OpenDevToolsWindow(
449 content::WebContents* web_contents) {
450 ASSERT_FALSE(content::DevToolsAgentHost::HasFor(web_contents));
451 DevToolsWindow::OpenDevToolsWindow(web_contents);
452 ASSERT_TRUE(content::DevToolsAgentHost::HasFor(web_contents));
455 Browser* InProcessBrowserTest::OpenURLOffTheRecord(Profile* profile,
456 const GURL& url) {
457 chrome::HostDesktopType active_desktop = chrome::GetActiveDesktop();
458 chrome::OpenURLOffTheRecord(profile, url, active_desktop);
459 Browser* browser = chrome::FindTabbedBrowser(
460 profile->GetOffTheRecordProfile(), false, active_desktop);
461 content::TestNavigationObserver observer(
462 browser->tab_strip_model()->GetActiveWebContents());
463 observer.Wait();
464 return browser;
467 // Creates a browser with a single tab (about:blank), waits for the tab to
468 // finish loading and shows the browser.
469 Browser* InProcessBrowserTest::CreateBrowser(Profile* profile) {
470 Browser* browser = new Browser(
471 Browser::CreateParams(profile, chrome::GetActiveDesktop()));
472 AddBlankTabAndShow(browser);
473 return browser;
476 Browser* InProcessBrowserTest::CreateIncognitoBrowser() {
477 // Create a new browser with using the incognito profile.
478 Browser* incognito = new Browser(
479 Browser::CreateParams(browser()->profile()->GetOffTheRecordProfile(),
480 chrome::GetActiveDesktop()));
481 AddBlankTabAndShow(incognito);
482 return incognito;
485 Browser* InProcessBrowserTest::CreateBrowserForPopup(Profile* profile) {
486 Browser* browser =
487 new Browser(Browser::CreateParams(Browser::TYPE_POPUP, profile,
488 chrome::GetActiveDesktop()));
489 AddBlankTabAndShow(browser);
490 return browser;
493 Browser* InProcessBrowserTest::CreateBrowserForApp(
494 const std::string& app_name,
495 Profile* profile) {
496 Browser* browser = new Browser(
497 Browser::CreateParams::CreateForApp(
498 app_name, false /* trusted_source */, gfx::Rect(), profile,
499 chrome::GetActiveDesktop()));
500 AddBlankTabAndShow(browser);
501 return browser;
503 #endif // !defined(OS_MACOSX)
505 void InProcessBrowserTest::AddBlankTabAndShow(Browser* browser) {
506 content::WindowedNotificationObserver observer(
507 content::NOTIFICATION_LOAD_STOP,
508 content::NotificationService::AllSources());
509 chrome::AddSelectedTabWithURL(browser,
510 GURL(url::kAboutBlankURL),
511 ui::PAGE_TRANSITION_AUTO_TOPLEVEL);
512 observer.Wait();
514 browser->window()->Show();
517 #if !defined(OS_MACOSX)
518 base::CommandLine InProcessBrowserTest::GetCommandLineForRelaunch() {
519 base::CommandLine new_command_line(
520 base::CommandLine::ForCurrentProcess()->GetProgram());
521 base::CommandLine::SwitchMap switches =
522 base::CommandLine::ForCurrentProcess()->GetSwitches();
523 switches.erase(switches::kUserDataDir);
524 switches.erase(content::kSingleProcessTestsFlag);
525 switches.erase(switches::kSingleProcess);
526 new_command_line.AppendSwitch(content::kLaunchAsBrowser);
528 base::FilePath user_data_dir;
529 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
530 new_command_line.AppendSwitchPath(switches::kUserDataDir, user_data_dir);
532 for (base::CommandLine::SwitchMap::const_iterator iter = switches.begin();
533 iter != switches.end(); ++iter) {
534 new_command_line.AppendSwitchNative((*iter).first, (*iter).second);
536 return new_command_line;
538 #endif
540 void InProcessBrowserTest::RunTestOnMainThreadLoop() {
541 AfterStartupTaskUtils::SetBrowserStartupIsComplete();
543 // Pump startup related events.
544 content::RunAllPendingInMessageLoop();
546 chrome::HostDesktopType active_desktop = chrome::GetActiveDesktop();
547 // Self-adds/removes itself from the BrowserList observers.
548 scoped_ptr<SingleDesktopTestObserver> single_desktop_test_observer;
549 if (!multi_desktop_test_) {
550 single_desktop_test_observer.reset(
551 new SingleDesktopTestObserver(active_desktop));
554 const BrowserList* active_browser_list =
555 BrowserList::GetInstance(active_desktop);
556 if (!active_browser_list->empty()) {
557 browser_ = active_browser_list->get(0);
558 #if defined(USE_ASH)
559 // There are cases where windows get created maximized by default.
560 if (browser_->window()->IsMaximized())
561 browser_->window()->Restore();
562 #endif
563 content::WaitForLoadStop(
564 browser_->tab_strip_model()->GetActiveWebContents());
567 #if !defined(OS_ANDROID) && !defined(OS_IOS)
568 // Do not use the real StorageMonitor for tests, which introduces another
569 // source of variability and potential slowness.
570 ASSERT_TRUE(storage_monitor::TestStorageMonitor::CreateForBrowserTests());
571 #endif
573 #if defined(OS_MACOSX)
574 // On Mac, without the following autorelease pool, code which is directly
575 // executed (as opposed to executed inside a message loop) would autorelease
576 // objects into a higher-level pool. This pool is not recycled in-sync with
577 // the message loops' pools and causes problems with code relying on
578 // deallocation via an autorelease pool (such as browser window closure and
579 // browser shutdown). To avoid this, the following pool is recycled after each
580 // time code is directly executed.
581 autorelease_pool_ = new base::mac::ScopedNSAutoreleasePool;
582 #endif
584 // Pump any pending events that were created as a result of creating a
585 // browser.
586 content::RunAllPendingInMessageLoop();
588 // run_accessibility_checks_for_test_case_ must be set before calling
589 // SetUpOnMainThread or RunTestOnMainThread so that one or all tests can
590 // enable/disable the accessibility audit.
591 run_accessibility_checks_for_test_case_ = false;
593 SetUpOnMainThread();
594 #if defined(OS_MACOSX)
595 autorelease_pool_->Recycle();
596 #endif
598 if (!HasFatalFailure())
599 RunTestOnMainThread();
600 #if defined(OS_MACOSX)
601 autorelease_pool_->Recycle();
602 #endif
604 if (run_accessibility_checks_for_test_case_) {
605 std::string error_message;
606 EXPECT_TRUE(RunAccessibilityChecks(&error_message));
607 EXPECT_EQ("", error_message);
610 // Invoke cleanup and quit even if there are failures. This is similar to
611 // gtest in that it invokes TearDown even if Setup fails.
612 TearDownOnMainThread();
613 #if defined(OS_MACOSX)
614 autorelease_pool_->Recycle();
615 #endif
617 // Sometimes tests leave Quit tasks in the MessageLoop (for shame), so let's
618 // run all pending messages here to avoid preempting the QuitBrowsers tasks.
619 // TODO(jbates) Once crbug.com/134753 is fixed, this can be removed because it
620 // will not be possible to post Quit tasks.
621 content::RunAllPendingInMessageLoop();
623 QuitBrowsers();
624 // All BrowserLists should be empty at this point.
625 for (chrome::HostDesktopType t = chrome::HOST_DESKTOP_TYPE_FIRST;
626 t < chrome::HOST_DESKTOP_TYPE_COUNT;
627 t = static_cast<chrome::HostDesktopType>(t + 1)) {
628 CHECK(BrowserList::GetInstance(t)->empty()) << t;
632 void InProcessBrowserTest::QuitBrowsers() {
633 if (chrome::GetTotalBrowserCount() == 0) {
634 chrome::NotifyAppTerminating();
635 return;
638 // Invoke AttemptExit on a running message loop.
639 // AttemptExit exits the message loop after everything has been
640 // shut down properly.
641 base::ThreadTaskRunnerHandle::Get()->PostTask(
642 FROM_HERE, base::Bind(&chrome::AttemptExit));
643 content::RunMessageLoop();
645 #if defined(OS_MACOSX)
646 // chrome::AttemptExit() will attempt to close all browsers by deleting
647 // their tab contents. The last tab contents being removed triggers closing of
648 // the browser window.
650 // On the Mac, this eventually reaches
651 // -[BrowserWindowController windowWillClose:], which will post a deferred
652 // -autorelease on itself to ultimately destroy the Browser object. The line
653 // below is necessary to pump these pending messages to ensure all Browsers
654 // get deleted.
655 content::RunAllPendingInMessageLoop();
656 delete autorelease_pool_;
657 autorelease_pool_ = NULL;
658 #endif