Implement nacl_irt_memory for non-sfi mode.
[chromium-blink-merge.git] / chrome / test / base / in_process_browser_test.cc
blobb33e73bdbdf73f9dfe941684071514ea2af50345
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/file_util.h"
12 #include "base/files/file_path.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/google/google_util.h"
20 #include "chrome/browser/io_thread.h"
21 #include "chrome/browser/lifetime/application_lifetime.h"
22 #include "chrome/browser/net/net_error_tab_helper.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/profiles/profile_manager.h"
25 #include "chrome/browser/ui/browser.h"
26 #include "chrome/browser/ui/browser_finder.h"
27 #include "chrome/browser/ui/browser_list.h"
28 #include "chrome/browser/ui/browser_list_observer.h"
29 #include "chrome/browser/ui/browser_navigator.h"
30 #include "chrome/browser/ui/browser_tabstrip.h"
31 #include "chrome/browser/ui/browser_window.h"
32 #include "chrome/browser/ui/host_desktop.h"
33 #include "chrome/browser/ui/tabs/tab_strip_model.h"
34 #include "chrome/common/chrome_constants.h"
35 #include "chrome/common/chrome_paths.h"
36 #include "chrome/common/chrome_switches.h"
37 #include "chrome/common/logging_chrome.h"
38 #include "chrome/common/url_constants.h"
39 #include "chrome/renderer/chrome_content_renderer_client.h"
40 #include "chrome/test/base/chrome_test_suite.h"
41 #include "chrome/test/base/test_launcher_utils.h"
42 #include "chrome/test/base/test_switches.h"
43 #include "chrome/test/base/testing_browser_process.h"
44 #include "chrome/test/base/ui_test_utils.h"
45 #include "content/public/browser/notification_service.h"
46 #include "content/public/browser/notification_types.h"
47 #include "content/public/test/browser_test_utils.h"
48 #include "content/public/test/test_browser_thread.h"
49 #include "content/public/test/test_launcher.h"
50 #include "content/public/test/test_navigation_observer.h"
51 #include "net/test/embedded_test_server/embedded_test_server.h"
52 #include "net/test/spawned_test_server/spawned_test_server.h"
54 #if defined(OS_MACOSX)
55 #include "base/mac/scoped_nsautorelease_pool.h"
56 #endif
58 #if defined(OS_WIN) && defined(USE_AURA)
59 #include "base/win/scoped_com_initializer.h"
60 #include "base/win/windows_version.h"
61 #include "ui/base/win/atl_module.h"
62 #include "win8/test/metro_registration_helper.h"
63 #include "win8/test/test_registrar_constants.h"
64 #endif
66 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
67 #include "chrome/browser/captive_portal/captive_portal_service.h"
68 #endif
70 #if !defined(OS_ANDROID) && !defined(OS_IOS)
71 #include "chrome/browser/storage_monitor/test_storage_monitor.h"
72 #endif
74 namespace {
76 // Passed as value of kTestType.
77 const char kBrowserTestType[] = "browser";
79 // Used when running in single-process mode.
80 base::LazyInstance<ChromeContentRendererClient>::Leaky
81 g_chrome_content_renderer_client = LAZY_INSTANCE_INITIALIZER;
83 // A BrowserListObserver that makes sure that all browsers created are on the
84 // |allowed_desktop_|.
85 class SingleDesktopTestObserver : public chrome::BrowserListObserver,
86 public base::NonThreadSafe {
87 public:
88 explicit SingleDesktopTestObserver(chrome::HostDesktopType allowed_desktop);
89 virtual ~SingleDesktopTestObserver();
91 // chrome::BrowserListObserver:
92 virtual void OnBrowserAdded(Browser* browser) OVERRIDE;
94 private:
95 chrome::HostDesktopType allowed_desktop_;
97 DISALLOW_COPY_AND_ASSIGN(SingleDesktopTestObserver);
100 SingleDesktopTestObserver::SingleDesktopTestObserver(
101 chrome::HostDesktopType allowed_desktop)
102 : allowed_desktop_(allowed_desktop) {
103 BrowserList::AddObserver(this);
106 SingleDesktopTestObserver::~SingleDesktopTestObserver() {
107 BrowserList::RemoveObserver(this);
110 void SingleDesktopTestObserver::OnBrowserAdded(Browser* browser) {
111 CHECK(CalledOnValidThread());
112 CHECK_EQ(browser->host_desktop_type(), allowed_desktop_);
115 } // namespace
117 InProcessBrowserTest::InProcessBrowserTest()
118 : browser_(NULL),
119 exit_when_last_browser_closes_(true),
120 multi_desktop_test_(false)
121 #if defined(OS_MACOSX)
122 , autorelease_pool_(NULL)
123 #endif // OS_MACOSX
125 #if defined(OS_MACOSX)
126 // TODO(phajdan.jr): Make browser_tests self-contained on Mac, remove this.
127 // Before we run the browser, we have to hack the path to the exe to match
128 // what it would be if Chrome was running, because it is used to fork renderer
129 // processes, on Linux at least (failure to do so will cause a browser_test to
130 // be run instead of a renderer).
131 base::FilePath chrome_path;
132 CHECK(PathService::Get(base::FILE_EXE, &chrome_path));
133 chrome_path = chrome_path.DirName();
134 chrome_path = chrome_path.Append(chrome::kBrowserProcessExecutablePath);
135 CHECK(PathService::Override(base::FILE_EXE, chrome_path));
136 #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 embedded_test_server()->ServeFilesFromDirectory(
141 src_dir.AppendASCII("chrome/test/data"));
144 InProcessBrowserTest::~InProcessBrowserTest() {
147 void InProcessBrowserTest::SetUp() {
148 // Browser tests will create their own g_browser_process later.
149 DCHECK(!g_browser_process);
151 CommandLine* command_line = CommandLine::ForCurrentProcess();
152 // Allow subclasses to change the command line before running any tests.
153 SetUpCommandLine(command_line);
154 // Add command line arguments that are used by all InProcessBrowserTests.
155 PrepareTestCommandLine(command_line);
157 // Create a temporary user data directory if required.
158 ASSERT_TRUE(CreateUserDataDirectory())
159 << "Could not create user data directory.";
161 // Allow subclasses the opportunity to make changes to the default user data
162 // dir before running any tests.
163 ASSERT_TRUE(SetUpUserDataDirectory())
164 << "Could not set up user data directory.";
166 // Single-process mode is not set in BrowserMain, so process it explicitly,
167 // and set up renderer.
168 if (command_line->HasSwitch(switches::kSingleProcess)) {
169 content::SetRendererClientForTesting(
170 g_chrome_content_renderer_client.Pointer());
173 #if defined(OS_CHROMEOS)
174 // Make sure that the log directory exists.
175 base::FilePath log_dir = logging::GetSessionLogFile(*command_line).DirName();
176 base::CreateDirectory(log_dir);
177 #endif // defined(OS_CHROMEOS)
179 #if defined(OS_MACOSX)
180 // On Mac, without the following autorelease pool, code which is directly
181 // executed (as opposed to executed inside a message loop) would autorelease
182 // objects into a higher-level pool. This pool is not recycled in-sync with
183 // the message loops' pools and causes problems with code relying on
184 // deallocation via an autorelease pool (such as browser window closure and
185 // browser shutdown). To avoid this, the following pool is recycled after each
186 // time code is directly executed.
187 autorelease_pool_ = new base::mac::ScopedNSAutoreleasePool;
188 #endif
190 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
191 captive_portal::CaptivePortalService::set_state_for_testing(
192 captive_portal::CaptivePortalService::DISABLED_FOR_TESTING);
193 #endif
195 chrome_browser_net::NetErrorTabHelper::set_state_for_testing(
196 chrome_browser_net::NetErrorTabHelper::TESTING_FORCE_DISABLED);
198 google_util::SetMockLinkDoctorBaseURLForTesting();
200 #if defined(OS_WIN) && defined(USE_AURA)
201 if (base::win::GetVersion() >= base::win::VERSION_WIN8 &&
202 CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) {
203 com_initializer_.reset(new base::win::ScopedCOMInitializer());
204 ui::win::CreateATLModuleIfNeeded();
205 ASSERT_TRUE(win8::MakeTestDefaultBrowserSynchronously());
207 #endif
209 BrowserTestBase::SetUp();
212 void InProcessBrowserTest::PrepareTestCommandLine(CommandLine* command_line) {
213 // Propagate commandline settings from test_launcher_utils.
214 test_launcher_utils::PrepareBrowserCommandLineForTests(command_line);
216 // This is a Browser test.
217 command_line->AppendSwitchASCII(switches::kTestType, kBrowserTestType);
219 #if defined(OS_WIN) && defined(USE_AURA)
220 if (command_line->HasSwitch(switches::kAshBrowserTests)) {
221 command_line->AppendSwitchNative(switches::kViewerLaunchViaAppId,
222 win8::test::kDefaultTestAppUserModelId);
223 // Ash already launches with a single browser opened, add kSilentLaunch to
224 // make sure StartupBrowserCreator doesn't attempt to launch a browser on
225 // the native desktop on startup.
226 command_line->AppendSwitch(switches::kSilentLaunch);
228 #endif
230 #if defined(OS_MACOSX)
231 // Explicitly set the path of the binary used for child processes, otherwise
232 // they'll try to use browser_tests which doesn't contain ChromeMain.
233 base::FilePath subprocess_path;
234 PathService::Get(base::FILE_EXE, &subprocess_path);
235 // Recreate the real environment, run the helper within the app bundle.
236 subprocess_path = subprocess_path.DirName().DirName();
237 DCHECK_EQ(subprocess_path.BaseName().value(), "Contents");
238 subprocess_path =
239 subprocess_path.Append("Versions").Append(chrome::kChromeVersion);
240 subprocess_path =
241 subprocess_path.Append(chrome::kHelperProcessExecutablePath);
242 command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
243 subprocess_path);
244 #endif
246 // TODO(pkotwicz): Investigate if we can remove this switch.
247 if (exit_when_last_browser_closes_)
248 command_line->AppendSwitch(switches::kDisableZeroBrowsersOpenForTests);
250 if (command_line->GetArgs().empty())
251 command_line->AppendArg(content::kAboutBlankURL);
254 bool InProcessBrowserTest::CreateUserDataDirectory() {
255 CommandLine* command_line = CommandLine::ForCurrentProcess();
256 base::FilePath user_data_dir =
257 command_line->GetSwitchValuePath(switches::kUserDataDir);
258 if (user_data_dir.empty()) {
259 if (temp_user_data_dir_.CreateUniqueTempDir() &&
260 temp_user_data_dir_.IsValid()) {
261 user_data_dir = temp_user_data_dir_.path();
262 } else {
263 LOG(ERROR) << "Could not create temporary user data directory \""
264 << temp_user_data_dir_.path().value() << "\".";
265 return false;
268 return test_launcher_utils::OverrideUserDataDir(user_data_dir);
271 void InProcessBrowserTest::TearDown() {
272 DCHECK(!g_browser_process);
273 #if defined(OS_WIN) && defined(USE_AURA)
274 com_initializer_.reset();
275 #endif
276 BrowserTestBase::TearDown();
279 void InProcessBrowserTest::AddTabAtIndexToBrowser(
280 Browser* browser,
281 int index,
282 const GURL& url,
283 content::PageTransition transition) {
284 chrome::NavigateParams params(browser, url, transition);
285 params.tabstrip_index = index;
286 params.disposition = NEW_FOREGROUND_TAB;
287 chrome::Navigate(&params);
289 content::WaitForLoadStop(params.target_contents);
292 void InProcessBrowserTest::AddTabAtIndex(
293 int index,
294 const GURL& url,
295 content::PageTransition transition) {
296 AddTabAtIndexToBrowser(browser(), index, url, transition);
299 bool InProcessBrowserTest::SetUpUserDataDirectory() {
300 return true;
303 // Creates a browser with a single tab (about:blank), waits for the tab to
304 // finish loading and shows the browser.
305 Browser* InProcessBrowserTest::CreateBrowser(Profile* profile) {
306 Browser* browser = new Browser(
307 Browser::CreateParams(profile, chrome::GetActiveDesktop()));
308 AddBlankTabAndShow(browser);
309 return browser;
312 Browser* InProcessBrowserTest::CreateIncognitoBrowser() {
313 // Create a new browser with using the incognito profile.
314 Browser* incognito = new Browser(
315 Browser::CreateParams(browser()->profile()->GetOffTheRecordProfile(),
316 chrome::GetActiveDesktop()));
317 AddBlankTabAndShow(incognito);
318 return incognito;
321 Browser* InProcessBrowserTest::CreateBrowserForPopup(Profile* profile) {
322 Browser* browser =
323 new Browser(Browser::CreateParams(Browser::TYPE_POPUP, profile,
324 chrome::GetActiveDesktop()));
325 AddBlankTabAndShow(browser);
326 return browser;
329 Browser* InProcessBrowserTest::CreateBrowserForApp(
330 const std::string& app_name,
331 Profile* profile) {
332 Browser* browser = new Browser(
333 Browser::CreateParams::CreateForApp(
334 Browser::TYPE_POPUP, app_name, gfx::Rect(), profile,
335 chrome::GetActiveDesktop()));
336 AddBlankTabAndShow(browser);
337 return browser;
340 void InProcessBrowserTest::AddBlankTabAndShow(Browser* browser) {
341 content::WindowedNotificationObserver observer(
342 content::NOTIFICATION_LOAD_STOP,
343 content::NotificationService::AllSources());
344 chrome::AddSelectedTabWithURL(browser, GURL(content::kAboutBlankURL),
345 content::PAGE_TRANSITION_AUTO_TOPLEVEL);
346 observer.Wait();
348 browser->window()->Show();
351 #if !defined(OS_MACOSX)
352 CommandLine InProcessBrowserTest::GetCommandLineForRelaunch() {
353 CommandLine new_command_line(CommandLine::ForCurrentProcess()->GetProgram());
354 CommandLine::SwitchMap switches =
355 CommandLine::ForCurrentProcess()->GetSwitches();
356 switches.erase(switches::kUserDataDir);
357 switches.erase(content::kSingleProcessTestsFlag);
358 switches.erase(switches::kSingleProcess);
359 new_command_line.AppendSwitch(content::kLaunchAsBrowser);
361 base::FilePath user_data_dir;
362 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
363 new_command_line.AppendSwitchPath(switches::kUserDataDir, user_data_dir);
365 for (CommandLine::SwitchMap::const_iterator iter = switches.begin();
366 iter != switches.end(); ++iter) {
367 new_command_line.AppendSwitchNative((*iter).first, (*iter).second);
369 return new_command_line;
371 #endif
373 void InProcessBrowserTest::RunTestOnMainThreadLoop() {
374 // Pump startup related events.
375 content::RunAllPendingInMessageLoop();
377 #if defined(OS_MACOSX)
378 autorelease_pool_->Recycle();
379 #endif
381 chrome::HostDesktopType active_desktop = chrome::GetActiveDesktop();
382 // Self-adds/removes itself from the BrowserList observers.
383 scoped_ptr<SingleDesktopTestObserver> single_desktop_test_observer;
384 if (!multi_desktop_test_) {
385 single_desktop_test_observer.reset(
386 new SingleDesktopTestObserver(active_desktop));
389 const BrowserList* active_browser_list =
390 BrowserList::GetInstance(active_desktop);
391 if (!active_browser_list->empty()) {
392 browser_ = active_browser_list->get(0);
393 #if defined(USE_ASH)
394 // There are cases where windows get created maximized by default.
395 if (browser_->window()->IsMaximized())
396 browser_->window()->Restore();
397 #endif
398 content::WaitForLoadStop(
399 browser_->tab_strip_model()->GetActiveWebContents());
402 #if !defined(OS_ANDROID) && !defined(OS_IOS)
403 // Do not use the real StorageMonitor for tests, which introduces another
404 // source of variability and potential slowness.
405 ASSERT_TRUE(TestStorageMonitor::CreateForBrowserTests());
406 #endif
408 // Pump any pending events that were created as a result of creating a
409 // browser.
410 content::RunAllPendingInMessageLoop();
412 SetUpOnMainThread();
413 #if defined(OS_MACOSX)
414 autorelease_pool_->Recycle();
415 #endif
417 if (!HasFatalFailure())
418 RunTestOnMainThread();
419 #if defined(OS_MACOSX)
420 autorelease_pool_->Recycle();
421 #endif
423 // Invoke cleanup and quit even if there are failures. This is similar to
424 // gtest in that it invokes TearDown even if Setup fails.
425 CleanUpOnMainThread();
426 #if defined(OS_MACOSX)
427 autorelease_pool_->Recycle();
428 #endif
430 // Sometimes tests leave Quit tasks in the MessageLoop (for shame), so let's
431 // run all pending messages here to avoid preempting the QuitBrowsers tasks.
432 // TODO(jbates) Once crbug.com/134753 is fixed, this can be removed because it
433 // will not be possible to post Quit tasks.
434 content::RunAllPendingInMessageLoop();
436 QuitBrowsers();
437 // All BrowserLists should be empty at this point.
438 for (chrome::HostDesktopType t = chrome::HOST_DESKTOP_TYPE_FIRST;
439 t < chrome::HOST_DESKTOP_TYPE_COUNT;
440 t = static_cast<chrome::HostDesktopType>(t + 1)) {
441 CHECK(BrowserList::GetInstance(t)->empty()) << t;
445 void InProcessBrowserTest::QuitBrowsers() {
446 if (chrome::GetTotalBrowserCount() == 0) {
447 chrome::NotifyAppTerminating();
448 return;
451 // Invoke AttemptExit on a running message loop.
452 // AttemptExit exits the message loop after everything has been
453 // shut down properly.
454 base::MessageLoopForUI::current()->PostTask(FROM_HERE,
455 base::Bind(&chrome::AttemptExit));
456 content::RunMessageLoop();
458 #if defined(OS_MACOSX)
459 // chrome::AttemptExit() will attempt to close all browsers by deleting
460 // their tab contents. The last tab contents being removed triggers closing of
461 // the browser window.
463 // On the Mac, this eventually reaches
464 // -[BrowserWindowController windowWillClose:], which will post a deferred
465 // -autorelease on itself to ultimately destroy the Browser object. The line
466 // below is necessary to pump these pending messages to ensure all Browsers
467 // get deleted.
468 content::RunAllPendingInMessageLoop();
469 delete autorelease_pool_;
470 autorelease_pool_ = NULL;
471 #endif