Move about://-related constants from //content to //url
[chromium-blink-merge.git] / chrome / browser / ui / browser_close_browsertest.cc
blob23fa01d5c104ef10385f86d13b892b3c8cc9732b
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 "base/command_line.h"
6 #include "base/logging.h"
7 #include "base/path_service.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/strings/stringprintf.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/download/download_service.h"
12 #include "chrome/browser/download/download_service_factory.h"
13 #include "chrome/browser/download/download_test_file_activity_observer.h"
14 #include "chrome/browser/net/url_request_mock_util.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/profiles/profile_manager.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/browser_iterator.h"
19 #include "chrome/browser/ui/browser_tabstrip.h"
20 #include "chrome/browser/ui/browser_window.h"
21 #include "chrome/browser/ui/host_desktop.h"
22 #include "chrome/browser/ui/tabs/tab_strip_model.h"
23 #include "chrome/common/chrome_paths.h"
24 #include "chrome/common/pref_names.h"
25 #include "chrome/common/url_constants.h"
26 #include "chrome/test/base/in_process_browser_test.h"
27 #include "chrome/test/base/ui_test_utils.h"
28 #include "content/public/browser/download_item.h"
29 #include "content/public/common/page_transition_types.h"
30 #include "content/public/test/browser_test_utils.h"
31 #include "content/public/test/download_test_observer.h"
32 #include "content/test/net/url_request_slow_download_job.h"
34 using content::BrowserContext;
35 using content::BrowserThread;
36 using content::DownloadItem;
37 using content::DownloadManager;
38 using content::URLRequestSlowDownloadJob;
40 class BrowserCloseTest : public InProcessBrowserTest {
41 public:
42 // Structure defining test cases for DownloadsCloseCheck.
43 struct DownloadsCloseCheckCase {
44 std::string DebugString() const;
46 // Input
47 struct {
48 struct {
49 int windows;
50 int downloads;
51 } regular;
52 struct {
53 int windows;
54 int downloads;
55 } incognito;
56 } profile_a;
58 struct {
59 struct {
60 int windows;
61 int downloads;
62 } regular;
63 struct {
64 int windows;
65 int downloads;
66 } incognito;
67 } profile_b;
69 // We always probe a window in profile A.
70 enum { REGULAR = 0, INCOGNITO = 1 } window_to_probe;
72 // Output
73 Browser::DownloadClosePreventionType type;
75 // Unchecked if type == DOWNLOAD_CLOSE_OK.
76 int num_blocking;
79 protected:
80 virtual void SetUpOnMainThread() OVERRIDE {
81 BrowserThread::PostTask(
82 BrowserThread::IO, FROM_HERE,
83 base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
86 // Create a second profile to work within multi-profile.
87 Profile* CreateSecondProfile() {
88 base::FilePath user_data_dir;
89 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
91 if (!second_profile_data_dir_.CreateUniqueTempDirUnderPath(user_data_dir))
92 return NULL;
94 Profile* second_profile =
95 g_browser_process->profile_manager()->GetProfile(
96 second_profile_data_dir_.path());
97 if (!second_profile)
98 return NULL;
100 bool result = second_profile_downloads_dir_.CreateUniqueTempDir();
101 if (!result)
102 return NULL;
103 second_profile->GetPrefs()->SetFilePath(
104 prefs::kDownloadDefaultDirectory,
105 second_profile_downloads_dir_.path());
107 return second_profile;
110 // Create |num_downloads| number of downloads that are stalled
111 // (will quickly get to a place where the server won't
112 // provide any more data) so that we can test closing the
113 // browser with active downloads.
114 void CreateStalledDownloads(Browser* browser, int num_downloads) {
115 GURL url(URLRequestSlowDownloadJob::kKnownSizeUrl);
117 if (num_downloads == 0)
118 return;
120 // Setup an observer waiting for the given number of downloads
121 // to get to IN_PROGRESS.
122 DownloadManager* download_manager =
123 BrowserContext::GetDownloadManager(browser->profile());
124 scoped_ptr<content::DownloadTestObserver> observer(
125 new content::DownloadTestObserverInProgress(download_manager,
126 num_downloads));
128 // Set of that number of downloads.
129 size_t count_downloads = num_downloads;
130 while (num_downloads--)
131 ui_test_utils::NavigateToURLWithDisposition(
132 browser, url, NEW_BACKGROUND_TAB,
133 ui_test_utils::BROWSER_TEST_NONE);
135 // Wait for them.
136 observer->WaitForFinished();
137 EXPECT_EQ(count_downloads,
138 observer->NumDownloadsSeenInState(DownloadItem::IN_PROGRESS));
141 // All all downloads created in CreateStalledDownloads() to
142 // complete, and block in this routine until they do complete.
143 void CompleteAllDownloads(Browser* browser) {
144 GURL finish_url(URLRequestSlowDownloadJob::kFinishDownloadUrl);
145 ui_test_utils::NavigateToURL(browser, finish_url);
147 // Go through and, for every single profile, wait until there are
148 // no active downloads on that download manager.
149 std::vector<Profile*> profiles(
150 g_browser_process->profile_manager()->GetLoadedProfiles());
151 for (std::vector<Profile*>::const_iterator pit = profiles.begin();
152 pit != profiles.end(); ++pit) {
153 DownloadService* download_service =
154 DownloadServiceFactory::GetForBrowserContext(*pit);
155 if (download_service->HasCreatedDownloadManager()) {
156 DownloadManager *mgr = BrowserContext::GetDownloadManager(*pit);
157 scoped_refptr<content::DownloadTestFlushObserver> observer(
158 new content::DownloadTestFlushObserver(mgr));
159 observer->WaitForFlush();
161 if ((*pit)->HasOffTheRecordProfile()) {
162 DownloadService* incognito_download_service =
163 DownloadServiceFactory::GetForBrowserContext(
164 (*pit)->GetOffTheRecordProfile());
165 if (incognito_download_service->HasCreatedDownloadManager()) {
166 DownloadManager *mgr = BrowserContext::GetDownloadManager(
167 (*pit)->GetOffTheRecordProfile());
168 scoped_refptr<content::DownloadTestFlushObserver> observer(
169 new content::DownloadTestFlushObserver(mgr));
170 observer->WaitForFlush();
176 // Create a Browser (with associated window) on the specified profile.
177 Browser* CreateBrowserOnProfile(Profile* profile,
178 chrome::HostDesktopType host_desktop_type) {
179 Browser* new_browser =
180 new Browser(Browser::CreateParams(profile, host_desktop_type));
181 chrome::AddSelectedTabWithURL(new_browser,
182 GURL(url::kAboutBlankURL),
183 content::PAGE_TRANSITION_AUTO_TOPLEVEL);
184 content::WaitForLoadStop(
185 new_browser->tab_strip_model()->GetActiveWebContents());
186 new_browser->window()->Show();
187 return new_browser;
190 // Adjust the number of browsers and associated windows up or down
191 // to |num_windows|. This routine assumes that there is only a single
192 // browser associated with the profile on entry. |*base_browser| contains
193 // this browser, and the profile is derived from that browser. On output,
194 // if |*base_browser| was destroyed (because |num_windows == 0|), NULL
195 // is assigned to that memory location.
196 bool AdjustBrowsersOnProfile(Browser** base_browser, int num_windows) {
197 int num_downloads_blocking;
198 if (num_windows == 0) {
199 if (Browser::DOWNLOAD_CLOSE_OK !=
200 (*base_browser)->OkToCloseWithInProgressDownloads(
201 &num_downloads_blocking))
202 return false;
203 (*base_browser)->window()->Close();
204 *base_browser = 0;
205 return true;
208 // num_windows > 0
209 Profile* profile((*base_browser)->profile());
210 chrome::HostDesktopType host_desktop_type =
211 (*base_browser)->host_desktop_type();
212 for (int w = 1; w < num_windows; ++w) {
213 CreateBrowserOnProfile(profile, host_desktop_type);
215 return true;
218 int TotalUnclosedBrowsers() {
219 int count = 0;
220 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
221 if (!it->IsAttemptingToCloseBrowser())
222 count++;
224 return count;
227 // Note that this is invalid to call if TotalUnclosedBrowsers() == 0.
228 Browser* FirstUnclosedBrowser() {
229 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
230 if (!it->IsAttemptingToCloseBrowser())
231 return *it;
233 return NULL;
236 bool SetupForDownloadCloseCheck() {
237 first_profile_ = browser()->profile();
239 bool result = first_profile_downloads_dir_.CreateUniqueTempDir();
240 EXPECT_TRUE(result);
241 if (!result) return false;
242 first_profile_->GetPrefs()->SetFilePath(
243 prefs::kDownloadDefaultDirectory,
244 first_profile_downloads_dir_.path());
246 second_profile_ = CreateSecondProfile();
247 EXPECT_TRUE(second_profile_);
248 if (!second_profile_) return false;
250 DownloadTestFileActivityObserver(first_profile_) .EnableFileChooser(false);
251 DownloadTestFileActivityObserver(second_profile_).EnableFileChooser(false);
252 return true;
255 // Test a specific DownloadsCloseCheckCase. Returns false if
256 // an assertion has failed and the test should be aborted.
257 bool ExecuteDownloadCloseCheckCase(size_t i) {
258 const DownloadsCloseCheckCase& check_case(download_close_check_cases[i]);
259 SCOPED_TRACE(testing::Message() << "Case" << i
260 << ": " << check_case.DebugString());
262 // Test invariant: so that we don't actually try and close the browser,
263 // we always enter the function with a single browser window open on the
264 // main profile. That means we need to exit the function the same way.
265 // So we setup everything except for the |first_profile_| regular, and then
266 // flip the bit on the main window.
267 // Note that this means that browser() is unreliable in the context
268 // of this function or its callers; we'll be killing that main window
269 // and recreating it fairly frequently.
270 int unclosed_browsers = TotalUnclosedBrowsers();
271 EXPECT_EQ(1, unclosed_browsers);
272 if (1 != unclosed_browsers)
273 return false;
275 Browser* entry_browser = FirstUnclosedBrowser();
276 EXPECT_EQ(first_profile_, entry_browser->profile());
277 if (first_profile_ != entry_browser->profile())
278 return false;
279 int total_download_count =
280 DownloadService::NonMaliciousDownloadCountAllProfiles();
281 EXPECT_EQ(0, total_download_count);
282 if (0 != total_download_count)
283 return false;
284 Profile* first_profile_incognito = first_profile_->GetOffTheRecordProfile();
285 Profile* second_profile_incognito =
286 second_profile_->GetOffTheRecordProfile();
287 DownloadTestFileActivityObserver(first_profile_incognito)
288 .EnableFileChooser(false);
289 DownloadTestFileActivityObserver(second_profile_incognito)
290 .EnableFileChooser(false);
292 // For simplicty of coding, we create a window on each profile so that
293 // we can easily create downloads, then we destroy or create windows
294 // as necessary.
295 chrome::HostDesktopType host_desktop_type =
296 entry_browser->host_desktop_type();
297 Browser* browser_a_regular(CreateBrowserOnProfile(first_profile_,
298 host_desktop_type));
299 Browser* browser_a_incognito(
300 CreateBrowserOnProfile(first_profile_incognito, host_desktop_type));
301 Browser* browser_b_regular(CreateBrowserOnProfile(second_profile_,
302 host_desktop_type));
303 Browser* browser_b_incognito(
304 CreateBrowserOnProfile(second_profile_incognito, host_desktop_type));
306 // Kill our entry browser.
307 entry_browser->window()->Close();
308 entry_browser = NULL;
310 // Create all downloads needed.
311 CreateStalledDownloads(
312 browser_a_regular, check_case.profile_a.regular.downloads);
313 CreateStalledDownloads(
314 browser_a_incognito, check_case.profile_a.incognito.downloads);
315 CreateStalledDownloads(
316 browser_b_regular, check_case.profile_b.regular.downloads);
317 CreateStalledDownloads(
318 browser_b_incognito, check_case.profile_b.incognito.downloads);
320 // Adjust the windows
321 Browser** browsers[] = {
322 &browser_a_regular, &browser_a_incognito,
323 &browser_b_regular, &browser_b_incognito
325 int window_counts[] = {
326 check_case.profile_a.regular.windows,
327 check_case.profile_a.incognito.windows,
328 check_case.profile_b.regular.windows,
329 check_case.profile_b.incognito.windows,
331 for (size_t j = 0; j < arraysize(browsers); ++j) {
332 bool result = AdjustBrowsersOnProfile(browsers[j], window_counts[j]);
333 EXPECT_TRUE(result);
334 if (!result)
335 return false;
337 content::RunAllPendingInMessageLoop();
339 // All that work, for this one little test.
340 EXPECT_TRUE((check_case.window_to_probe ==
341 DownloadsCloseCheckCase::REGULAR) ||
342 (check_case.window_to_probe ==
343 DownloadsCloseCheckCase::INCOGNITO));
344 if (!((check_case.window_to_probe ==
345 DownloadsCloseCheckCase::REGULAR) ||
346 (check_case.window_to_probe ==
347 DownloadsCloseCheckCase::INCOGNITO)))
348 return false;
350 int num_downloads_blocking;
351 Browser* browser_to_probe =
352 (check_case.window_to_probe == DownloadsCloseCheckCase::REGULAR ?
353 browser_a_regular :
354 browser_a_incognito);
355 Browser::DownloadClosePreventionType type =
356 browser_to_probe->OkToCloseWithInProgressDownloads(
357 &num_downloads_blocking);
358 EXPECT_EQ(check_case.type, type);
359 if (type != Browser::DOWNLOAD_CLOSE_OK)
360 EXPECT_EQ(check_case.num_blocking, num_downloads_blocking);
362 // Release all the downloads.
363 CompleteAllDownloads(browser_to_probe);
365 // Create a new main window and kill everything else.
366 entry_browser = CreateBrowserOnProfile(first_profile_, host_desktop_type);
367 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
368 if ((*it) != entry_browser) {
369 if (!it->window()) {
370 ADD_FAILURE();
371 return false;
373 it->window()->Close();
376 content::RunAllPendingInMessageLoop();
378 return true;
381 static const DownloadsCloseCheckCase download_close_check_cases[];
383 // DownloadCloseCheck variables.
384 Profile* first_profile_;
385 Profile* second_profile_;
387 base::ScopedTempDir first_profile_downloads_dir_;
388 base::ScopedTempDir second_profile_data_dir_;
389 base::ScopedTempDir second_profile_downloads_dir_;
392 const BrowserCloseTest::DownloadsCloseCheckCase
393 BrowserCloseTest::download_close_check_cases[] = {
394 // Top level nesting is {profile_a, profile_b}
395 // Second level nesting is {regular, incognito
396 // Third level (inner) nesting is {windows, downloads}
398 // Last window (incognito) triggers browser close warning.
399 {{{0, 0}, {1, 1}}, {{0, 0}, {0, 0}},
400 BrowserCloseTest::DownloadsCloseCheckCase::INCOGNITO,
401 Browser::DOWNLOAD_CLOSE_BROWSER_SHUTDOWN, 1},
403 // Last incognito window triggers incognito close warning.
404 {{{1, 0}, {1, 1}}, {{0, 0}, {0, 0}},
405 BrowserCloseTest::DownloadsCloseCheckCase::INCOGNITO,
406 Browser::DOWNLOAD_CLOSE_LAST_WINDOW_IN_INCOGNITO_PROFILE, 1},
408 // Last incognito window with no downloads triggers no warning.
409 {{{0, 0}, {1, 0}}, {{0, 0}, {0, 0}},
410 BrowserCloseTest::DownloadsCloseCheckCase::INCOGNITO,
411 Browser::DOWNLOAD_CLOSE_OK},
413 // Last incognito window with window+download on another incognito profile
414 // triggers no warning.
415 {{{0, 0}, {1, 0}}, {{0, 0}, {1, 1}},
416 BrowserCloseTest::DownloadsCloseCheckCase::INCOGNITO,
417 Browser::DOWNLOAD_CLOSE_OK},
419 // Non-last incognito window triggers no warning.
420 {{{0, 0}, {2, 1}}, {{0, 0}, {0, 0}},
421 BrowserCloseTest::DownloadsCloseCheckCase::INCOGNITO,
422 Browser::DOWNLOAD_CLOSE_OK},
424 // Non-last regular window triggers no warning.
425 {{{2, 1}, {0, 0}}, {{0, 0}, {0, 0}},
426 BrowserCloseTest::DownloadsCloseCheckCase::REGULAR,
427 Browser::DOWNLOAD_CLOSE_OK},
429 // Last regular window triggers browser close.
430 {{{1, 1}, {0, 0}}, {{0, 0}, {0, 0}},
431 BrowserCloseTest::DownloadsCloseCheckCase::REGULAR,
432 Browser::DOWNLOAD_CLOSE_BROWSER_SHUTDOWN, 1},
434 // Last regular window triggers browser close for download on different
435 // profile.
436 {{{1, 0}, {0, 0}}, {{0, 1}, {0, 0}},
437 BrowserCloseTest::DownloadsCloseCheckCase::REGULAR,
438 Browser::DOWNLOAD_CLOSE_BROWSER_SHUTDOWN, 1},
440 // Last regular window triggers no warning if incognito
441 // active (http://crbug.com/61257).
442 {{{1, 0}, {1, 1}}, {{0, 0}, {0, 0}},
443 BrowserCloseTest::DownloadsCloseCheckCase::REGULAR,
444 Browser::DOWNLOAD_CLOSE_OK},
446 // Last regular window triggers no warning if other profile window active.
447 {{{1, 1}, {0, 0}}, {{1, 0}, {0, 0}},
448 BrowserCloseTest::DownloadsCloseCheckCase::REGULAR,
449 Browser::DOWNLOAD_CLOSE_OK},
451 // Last regular window triggers no warning if other incognito window
452 // active.
453 {{{1, 0}, {0, 0}}, {{0, 0}, {1, 1}},
454 BrowserCloseTest::DownloadsCloseCheckCase::REGULAR,
455 Browser::DOWNLOAD_CLOSE_OK},
457 // Last regular window triggers no warning if incognito active.
458 {{{1, 1}, {1, 0}}, {{0, 0}, {0, 0}},
459 BrowserCloseTest::DownloadsCloseCheckCase::REGULAR,
460 Browser::DOWNLOAD_CLOSE_OK},
462 // Test plural for regular.
463 {{{1, 2}, {0, 0}}, {{0, 0}, {0, 0}},
464 BrowserCloseTest::DownloadsCloseCheckCase::REGULAR,
465 Browser::DOWNLOAD_CLOSE_BROWSER_SHUTDOWN, 2},
467 // Test plural for incognito.
468 {{{1, 0}, {1, 2}}, {{0, 0}, {0, 0}},
469 BrowserCloseTest::DownloadsCloseCheckCase::INCOGNITO,
470 Browser::DOWNLOAD_CLOSE_LAST_WINDOW_IN_INCOGNITO_PROFILE, 2},
473 std::string BrowserCloseTest::DownloadsCloseCheckCase::DebugString() const {
474 std::string result;
475 result += "{";
476 if (profile_a.regular.windows || profile_a.regular.downloads)
477 result += base::StringPrintf("Regular profile A: (%d w, %d d), ",
478 profile_a.regular.windows,
479 profile_a.regular.downloads);
480 if (profile_a.incognito.windows || profile_a.incognito.downloads)
481 result += base::StringPrintf("Incognito profile A: (%d w, %d d), ",
482 profile_a.incognito.windows,
483 profile_a.incognito.downloads);
484 if (profile_b.regular.windows || profile_b.regular.downloads)
485 result += base::StringPrintf("Regular profile B: (%d w, %d d), ",
486 profile_b.regular.windows,
487 profile_b.regular.downloads);
488 if (profile_b.incognito.windows || profile_b.incognito.downloads)
489 result += base::StringPrintf("Incognito profile B: (%d w, %d d), ",
490 profile_b.incognito.windows,
491 profile_b.incognito.downloads);
492 result += (window_to_probe == REGULAR ? "Probe regular" :
493 window_to_probe == INCOGNITO ? "Probe incognito" :
494 "Probe unknown");
495 result += "} -> ";
496 if (type == Browser::DOWNLOAD_CLOSE_OK) {
497 result += "No warning";
498 } else {
499 result += base::StringPrintf(
500 "%s (%d downloads) warning",
501 (type == Browser::DOWNLOAD_CLOSE_BROWSER_SHUTDOWN ? "Browser shutdown" :
502 type == Browser::DOWNLOAD_CLOSE_LAST_WINDOW_IN_INCOGNITO_PROFILE ?
503 "Incognito close" : "Unknown"),
504 num_blocking);
506 return result;
509 // The following test is split into six chunks to reduce the chance
510 // of hitting the 25s timeout.
512 // This test is timing out very often under AddressSanitizer.
513 // http://crbug.com/111914 and http://crbug.com/103371.
514 // Crashing on Linux. http://crbug.com/100566
515 // Timing out on XP debug. http://crbug.com/111914
516 // Timing out, http://crbug.com/159449 .
518 #define MAYBE_DownloadsCloseCheck_0 DISABLED_DownloadsCloseCheck_0
519 #define MAYBE_DownloadsCloseCheck_1 DISABLED_DownloadsCloseCheck_1
520 #define MAYBE_DownloadsCloseCheck_2 DISABLED_DownloadsCloseCheck_2
521 #define MAYBE_DownloadsCloseCheck_3 DISABLED_DownloadsCloseCheck_3
522 #define MAYBE_DownloadsCloseCheck_4 DISABLED_DownloadsCloseCheck_4
523 #define MAYBE_DownloadsCloseCheck_5 DISABLED_DownloadsCloseCheck_5
525 IN_PROC_BROWSER_TEST_F(BrowserCloseTest, MAYBE_DownloadsCloseCheck_0) {
526 ASSERT_TRUE(SetupForDownloadCloseCheck());
527 for (size_t i = 0; i < arraysize(download_close_check_cases) / 6; ++i) {
528 ExecuteDownloadCloseCheckCase(i);
532 IN_PROC_BROWSER_TEST_F(BrowserCloseTest, MAYBE_DownloadsCloseCheck_1) {
533 ASSERT_TRUE(SetupForDownloadCloseCheck());
534 for (size_t i = arraysize(download_close_check_cases) / 6;
535 i < 2 * arraysize(download_close_check_cases) / 6; ++i) {
536 ExecuteDownloadCloseCheckCase(i);
540 IN_PROC_BROWSER_TEST_F(BrowserCloseTest, MAYBE_DownloadsCloseCheck_2) {
541 ASSERT_TRUE(SetupForDownloadCloseCheck());
542 for (size_t i = 2 * arraysize(download_close_check_cases) / 6;
543 i < 3 * arraysize(download_close_check_cases) / 6; ++i) {
544 ExecuteDownloadCloseCheckCase(i);
548 IN_PROC_BROWSER_TEST_F(BrowserCloseTest, MAYBE_DownloadsCloseCheck_3) {
549 ASSERT_TRUE(SetupForDownloadCloseCheck());
550 for (size_t i = 3 * arraysize(download_close_check_cases) / 6;
551 i < 4 * arraysize(download_close_check_cases) / 6; ++i) {
552 ExecuteDownloadCloseCheckCase(i);
556 IN_PROC_BROWSER_TEST_F(BrowserCloseTest, MAYBE_DownloadsCloseCheck_4) {
557 ASSERT_TRUE(SetupForDownloadCloseCheck());
558 for (size_t i = 4 * arraysize(download_close_check_cases) / 6;
559 i < 5 * arraysize(download_close_check_cases) / 6; ++i) {
560 ExecuteDownloadCloseCheckCase(i);
564 IN_PROC_BROWSER_TEST_F(BrowserCloseTest, MAYBE_DownloadsCloseCheck_5) {
565 ASSERT_TRUE(SetupForDownloadCloseCheck());
566 for (size_t i = 5 * arraysize(download_close_check_cases) / 6;
567 i < 6 * arraysize(download_close_check_cases) / 6; ++i) {
568 ExecuteDownloadCloseCheckCase(i);