Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1067)

Side by Side Diff: chrome/browser/ui/browser_close_browsertest.cc

Issue 7466033: Fix warning prompting on closing a window that will cancel downloads. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixing trybot failures (chromeos specifically). Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/ui/browser.cc ('k') | chrome/browser/ui/browser_list.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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.
4
5 #include "base/logging.h"
6 #include "base/path_service.h"
7 #include "base/stringprintf.h"
8 #include "chrome/browser/browser_process.h"
9 #include "chrome/browser/download/download_test_observer.h"
10 #include "chrome/browser/prefs/pref_service.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/profiles/profile_manager.h"
13 #include "chrome/browser/ui/browser.h"
14 #include "chrome/browser/ui/browser_window.h"
15 #include "chrome/browser/ui/webui/active_downloads_ui.h"
16 #include "chrome/common/chrome_paths.h"
17 #include "chrome/common/pref_names.h"
18 #include "chrome/test/base/in_process_browser_test.h"
19 #include "chrome/test/base/ui_test_utils.h"
20 #include "content/browser/download/download_item.h"
21 #include "content/browser/net/url_request_slow_download_job.h"
22 #include "content/browser/tab_contents/tab_contents.h"
23 #include "content/common/page_transition_types.h"
24 #include "content/common/url_constants.h"
25
26 class BrowserCloseTest : public InProcessBrowserTest {
27 public:
28 // Structure defining test cases for DownloadsCloseCheck.
29 struct DownloadsCloseCheckCase {
30 std::string DebugString() const;
31
32 // Input
33 struct {
achuithb 2011/08/29 17:19:10 Isn't struct profile_a {} more readable than struc
Randy Smith (Not in Mondays) 2011/10/13 20:06:04 Sure, but it doesn't mean the same thing. In the
34 struct {
35 int windows;
36 int downloads;
37 } regular;
38 struct {
39 int windows;
40 int downloads;
41 } incognito;
42 } profile_a;
43
44 struct {
45 struct {
46 int windows;
47 int downloads;
48 } regular;
49 struct {
50 int windows;
51 int downloads;
52 } incognito;
53 } profile_b;
54
55 // We always probe a window in profile A.
56 enum { REGULAR = 0, INCOGNITO = 1 } window_to_probe;
57
58 // Output
59 Browser::DownloadClosePreventionType type;
60
61 // Unchecked if type == DOWNLOAD_CLOSE_OK.
62 int num_blocking;
63 };
64
65 protected:
66 // Create a second profile to work within multi-profile.
67 Profile* CreateSecondProfile() {
68 FilePath user_data_dir;
69 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
70
71 if (!second_profile_data_dir_.CreateUniqueTempDirUnderPath(user_data_dir))
72 return NULL;
73
74 return g_browser_process->profile_manager()->GetProfile(
75 second_profile_data_dir_.path());
76 }
77
78 // Create |num_downloads| number of downloads that are stalled
79 // (will quickly get to a place where the server won't
80 // provide any more data) so that we can test closing the
81 // browser with active downloads.
82 void CreateStalledDownloads(Browser* browser, int num_downloads) {
83 GURL url(URLRequestSlowDownloadJob::kKnownSizeUrl);
84
85 if (num_downloads == 0)
86 return;
87
88 // Setup an observer waiting for the given number of downloads
89 // to get to IN_PROGRESS.
90 DownloadManager* download_manager =
91 browser->profile()->GetDownloadManager();
92 scoped_ptr<DownloadTestObserver> observer(
93 new DownloadTestObserver(
94 download_manager, num_downloads,
95 DownloadItem::IN_PROGRESS,
96 true, // Bail on select file
achuithb 2011/08/29 17:19:10 nits: 2 space between comment and code? period at
Randy Smith (Not in Mondays) 2011/10/13 20:06:04 Done.
97 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL));
98
99 // Set of that number of downloads.
100 while (num_downloads--)
101 ui_test_utils::NavigateToURLWithDisposition(
102 browser, url, NEW_BACKGROUND_TAB,
103 ui_test_utils::BROWSER_TEST_NONE);
104
105 // Wait for them.
106 observer->WaitForFinished();
107 }
108
109 // All all downloads created in CreateStalledDownloads() to
110 // complete, and block in this routine until they do complete.
111 void CompleteAllDownloads(Browser* browser) {
112 GURL finish_url(URLRequestSlowDownloadJob::kFinishDownloadUrl);
113 ui_test_utils::NavigateToURL(browser, finish_url);
114
115 // Go through and, for every single profile, wait until there are
116 // no active downloads on that download manager.
117 std::vector<Profile*> profiles(
118 g_browser_process->profile_manager()->GetLoadedProfiles());
119 for (std::vector<Profile*>::const_iterator pit = profiles.begin();
120 pit != profiles.end(); ++pit) {
121 if ((*pit)->HasCreatedDownloadManager()) {
122 DownloadManager *mgr = (*pit)->GetDownloadManager();
123 scoped_refptr<DownloadTestFlushObserver> observer(
124 new DownloadTestFlushObserver(mgr));
125 observer->WaitForFlush();
126 }
127 }
128 }
129
130 // Create a Browser (with associated window) on the specified profile.
131 Browser* CreateBrowserOnProfile(Profile* profile) {
132 Browser* new_browser = Browser::Create(profile);
133 new_browser->AddSelectedTabWithURL(GURL(chrome::kAboutBlankURL),
134 PageTransition::START_PAGE);
135 ui_test_utils::WaitForNavigation(
136 &new_browser->GetSelectedTabContents()->controller());
137 new_browser->window()->Show();
138 return new_browser;
139 }
140
141 // Adjust the number of browsers and associated windows up or down
142 // to |num_windows|. This routine assumes that there is only a single
143 // browser associated with the profile on entry. |*base_browser| contains
144 // this browser, and the profile is derived from that browser. On output,
145 // if |*base_browser| was destroyed (because |num_windows == 0|), NULL
146 // is assigned to that memory location.
147 bool AdjustBrowsersOnProfile(Browser** base_browser, int num_windows) {
148 int num_downloads_blocking;
149 if (num_windows == 0) {
150 if (Browser::DOWNLOAD_CLOSE_OK !=
151 (*base_browser)->OkToCloseWithInProgressDownloads(
152 &num_downloads_blocking))
153 return false;
154 (*base_browser)->window()->Close();
155 *base_browser = 0;
156 return true;
157 }
158
159 // num_windows > 0
160 Profile* profile((*base_browser)->profile());
161 for (int w = 1; w < num_windows; w++) {
achuithb 2011/08/29 17:19:10 nit: ++w
Randy Smith (Not in Mondays) 2011/10/13 20:06:04 Done.
162 CreateBrowserOnProfile(profile);
163 }
164 return true;
165 }
166
167 // Test a specific DownloadsCloseCheckCase. Returns false if
168 // an assertion has failed and the test should be aborted.
169 bool CheckDownloadsClose(const DownloadsCloseCheckCase& check_case,
170 Profile* profile_a,
171 Profile* profile_b) {
172 // Test invariant: so that we don't actually try and close the browser,
173 // we always enter the function with a single browser window open on the
174 // main profile. That means we need to exit the function the same way.
175 // So we setup everything except for the profile_a regular, and then
176 // flip the bit on the main window.
177 // Note that this means that browser() is unreliable in the context
178 // of this function or its callers; we'll be killing that main window
179 // and recreating it fairly frequently.
180
181 #if 0
achuithb 2011/08/29 17:19:10 I'm assuming you're working on fixing this?
Randy Smith (Not in Mondays) 2011/10/13 20:06:04 Yep. It's gone now.
182 #if !defined(OS_MACOSX)
183 // Window closes are delayed until the outer run loop on the mac.
184 EXPECT_EQ(1u, BrowserList::size()) << "Case: " << check_case.DebugString();
185 if (BrowserList::size() != 1u)
186 return false;
187 #endif
188 #endif
189
190 Browser* entry_browser = *BrowserList::begin();
191 EXPECT_EQ(profile_a, entry_browser->profile()) << "Case: "
192 << check_case.DebugString();
193 if (profile_a != entry_browser->profile())
194 return false;
195 int total_download_count =
196 g_browser_process->profile_manager()->TotalDownloadCount();
197 EXPECT_EQ(0, g_browser_process->profile_manager()->TotalDownloadCount())
198 << "Case: " << check_case.DebugString();
199 if (0 != total_download_count)
200 return false;
201
202 Profile* profile_a_incognito = profile_a->GetOffTheRecordProfile();
203 Profile* profile_b_incognito = profile_b->GetOffTheRecordProfile();
204
205 // For simplicty of coding, we create a window on each profile so that
206 // we can easily create downloads, then we destroy or create windows
207 // as necessary.
208 Browser* browser_a_regular(CreateBrowserOnProfile(profile_a));
209 Browser* browser_a_incognito(CreateBrowserOnProfile(profile_a_incognito));
210 Browser* browser_b_regular(CreateBrowserOnProfile(profile_b));
211 Browser* browser_b_incognito(CreateBrowserOnProfile(profile_b_incognito));
212
213 // Kill our entry browser.
214 entry_browser->window()->Close();
215 entry_browser = NULL;
216
217 // Create all downloads needed.
218 CreateStalledDownloads(
219 browser_a_regular, check_case.profile_a.regular.downloads);
220 CreateStalledDownloads(
221 browser_a_incognito, check_case.profile_a.incognito.downloads);
222 CreateStalledDownloads(
223 browser_b_regular, check_case.profile_b.regular.downloads);
224 CreateStalledDownloads(
225 browser_b_incognito, check_case.profile_b.incognito.downloads);
226
227 // Adjust the windows
228 Browser** browsers[] = {
229 &browser_a_regular, &browser_a_incognito,
230 &browser_b_regular, &browser_b_incognito
231 };
232 int window_counts[] = {
233 check_case.profile_a.regular.windows,
234 check_case.profile_a.incognito.windows,
235 check_case.profile_b.regular.windows,
236 check_case.profile_b.incognito.windows,
237 };
238 for (size_t i = 0; i < arraysize(browsers); i++) {
achuithb 2011/08/29 17:19:10 nit: ++i
Randy Smith (Not in Mondays) 2011/10/13 20:06:04 Done.
239 bool result = AdjustBrowsersOnProfile(browsers[i], window_counts[i]);
240 EXPECT_TRUE(result);
241 if (!result)
242 return false;
243 }
244
245 #if defined(OS_CHROMEOS)
246 // Get rid of downloads panel on ChromeOS
247 Browser* panel = ActiveDownloadsUI::GetPopup();
248 if (panel)
249 panel->CloseWindow();
250 ui_test_utils::RunAllPendingInMessageLoop();
251 #endif
252
253 // All that work, for this one little test.
254 EXPECT_TRUE((check_case.window_to_probe ==
255 DownloadsCloseCheckCase::REGULAR) ||
256 (check_case.window_to_probe ==
257 DownloadsCloseCheckCase::INCOGNITO));
258 if (!((check_case.window_to_probe ==
259 DownloadsCloseCheckCase::REGULAR) ||
260 (check_case.window_to_probe ==
261 DownloadsCloseCheckCase::INCOGNITO)))
262 return false;
263
264 int num_downloads_blocking;
265 Browser* browser_to_probe =
266 (check_case.window_to_probe == DownloadsCloseCheckCase::REGULAR ?
267 browser_a_regular :
268 browser_a_incognito);
269 Browser::DownloadClosePreventionType type =
270 browser_to_probe->OkToCloseWithInProgressDownloads(
271 &num_downloads_blocking);
272 EXPECT_EQ(check_case.type, type) << check_case.DebugString();
273 if (check_case.type != Browser::DOWNLOAD_CLOSE_OK)
274 EXPECT_EQ(check_case.num_blocking, num_downloads_blocking)
275 << check_case.DebugString();
276
277 // Release all the downloads.
278 CompleteAllDownloads(browser_to_probe);
279
280 // Create a new main window and kill everything else.
281 entry_browser = CreateBrowserOnProfile(profile_a);
282 for (BrowserList::const_iterator bit = BrowserList::begin();
283 bit != BrowserList::end(); ++bit) {
284 if ((*bit) != entry_browser) {
285 EXPECT_TRUE((*bit)->window());
286 if (!(*bit)->window())
287 return false;
288 (*bit)->window()->Close();
289 }
290 }
291 ui_test_utils::RunAllPendingInMessageLoop();
292
293 return true;
294 }
295
296 ScopedTempDir second_profile_data_dir_;
297 };
298
299 std::string BrowserCloseTest::DownloadsCloseCheckCase::DebugString() const {
300 std::string result;
301 result += "Case: {";
302 if (profile_a.regular.windows || profile_a.regular.downloads)
303 result += base::StringPrintf("Regular profile A: (%d w, %d d), ",
304 profile_a.regular.windows,
305 profile_a.regular.downloads);
306 if (profile_a.incognito.windows || profile_a.incognito.downloads)
307 result += base::StringPrintf("Incognito profile A: (%d w, %d d), ",
308 profile_a.incognito.windows,
309 profile_a.incognito.downloads);
310 if (profile_b.regular.windows || profile_b.regular.downloads)
311 result += base::StringPrintf("Regular profile B: (%d w, %d d), ",
312 profile_b.regular.windows,
313 profile_b.regular.downloads);
314 if (profile_b.incognito.windows || profile_b.incognito.downloads)
315 result += base::StringPrintf("Incognito profile B: (%d w, %d d), ",
316 profile_b.incognito.windows,
317 profile_b.incognito.downloads);
318 result += (window_to_probe == REGULAR ? "Probe regular" :
319 window_to_probe == INCOGNITO ? "Probe incognito" :
320 "Probe unknown");
321 result += "} -> ";
322 if (type == Browser::DOWNLOAD_CLOSE_OK) {
323 result += "No warning";
324 } else {
325 result += base::StringPrintf(
326 "%s (%d downloads) warning",
327 (type == Browser::DOWNLOAD_CLOSE_BROWSER_SHUTDOWN ? "Browser shutdown" :
328 type == Browser::DOWNLOAD_CLOSE_LAST_WINDOW_IN_INCOGNITO_PROFILE ?
329 "Incognito close" : "Unknown"),
330 num_blocking);
331 }
332 return result;
333 }
334
335 static const BrowserCloseTest::DownloadsCloseCheckCase
336 download_close_check_cases[] = {
337 // Top level nesting is {profile_a, profile_b}
338 // Second level nesting is {regular, incognito
339 // Third level (inner) nesting is {windows, downloads}
340
341 // Last window (incognito) triggers browser close warning.
342 {{{0, 0}, {1, 1}}, {{0, 0}, {0, 0}},
343 BrowserCloseTest::DownloadsCloseCheckCase::INCOGNITO,
344 Browser::DOWNLOAD_CLOSE_BROWSER_SHUTDOWN, 1},
345
346 // Last incognito window triggers incognito close warning.
347 {{{1, 0}, {1, 1}}, {{0, 0}, {0, 0}},
348 BrowserCloseTest::DownloadsCloseCheckCase::INCOGNITO,
349 Browser::DOWNLOAD_CLOSE_LAST_WINDOW_IN_INCOGNITO_PROFILE, 1},
350
351 // Last incognito window with no downloads triggers no warning.
352 {{{0, 0}, {1, 0}}, {{0, 0}, {0, 0}},
353 BrowserCloseTest::DownloadsCloseCheckCase::INCOGNITO,
354 Browser::DOWNLOAD_CLOSE_OK},
355
356 // Last incognito window with window+download on another incognito profile
357 // triggers no warning.
358 {{{0, 0}, {1, 0}}, {{0, 0}, {1, 1}},
359 BrowserCloseTest::DownloadsCloseCheckCase::INCOGNITO,
360 Browser::DOWNLOAD_CLOSE_OK},
361
362 // Non-last incognito window triggers no warning.
363 {{{0, 0}, {2, 1}}, {{0, 0}, {0, 0}},
364 BrowserCloseTest::DownloadsCloseCheckCase::INCOGNITO,
365 Browser::DOWNLOAD_CLOSE_OK},
366
367 // Non-last regular window triggers no warning.
368 {{{2, 1}, {0, 0}}, {{0, 0}, {0, 0}},
369 BrowserCloseTest::DownloadsCloseCheckCase::REGULAR,
370 Browser::DOWNLOAD_CLOSE_OK},
371
372 // Last regular window triggers browser close.
373 {{{1, 1}, {0, 0}}, {{0, 0}, {0, 0}},
374 BrowserCloseTest::DownloadsCloseCheckCase::REGULAR,
375 Browser::DOWNLOAD_CLOSE_BROWSER_SHUTDOWN, 1},
376
377 // Last regular window triggers browser close for download on different
378 // profile.
379 {{{1, 0}, {0, 0}}, {{0, 1}, {0, 0}},
380 BrowserCloseTest::DownloadsCloseCheckCase::REGULAR,
381 Browser::DOWNLOAD_CLOSE_BROWSER_SHUTDOWN, 1},
382
383 // Last regular window triggers no warning if incognito
384 // active (http://crbug.com/61257).
385 {{{1, 0}, {1, 1}}, {{0, 0}, {0, 0}},
386 BrowserCloseTest::DownloadsCloseCheckCase::REGULAR,
387 Browser::DOWNLOAD_CLOSE_OK},
388
389 // Last regular window triggers no warning if other profile window active.
390 {{{1, 1}, {0, 0}}, {{1, 0}, {0, 0}},
391 BrowserCloseTest::DownloadsCloseCheckCase::REGULAR,
392 Browser::DOWNLOAD_CLOSE_OK},
393
394 // Last regular window triggers no warning if other incognito window
395 // active.
396 {{{1, 0}, {0, 0}}, {{0, 0}, {1, 1}},
397 BrowserCloseTest::DownloadsCloseCheckCase::REGULAR,
398 Browser::DOWNLOAD_CLOSE_OK},
399
400 // Last regular window triggers no warning if incognito active.
401 {{{1, 1}, {1, 0}}, {{0, 0}, {0, 0}},
402 BrowserCloseTest::DownloadsCloseCheckCase::REGULAR,
403 Browser::DOWNLOAD_CLOSE_OK},
404
405 // Test plural for regular.
406 {{{1, 2}, {0, 0}}, {{0, 0}, {0, 0}},
407 BrowserCloseTest::DownloadsCloseCheckCase::REGULAR,
408 Browser::DOWNLOAD_CLOSE_BROWSER_SHUTDOWN, 2},
409
410 // Test plural for incognito.
411 {{{1, 0}, {1, 2}}, {{0, 0}, {0, 0}},
412 BrowserCloseTest::DownloadsCloseCheckCase::INCOGNITO,
413 Browser::DOWNLOAD_CLOSE_LAST_WINDOW_IN_INCOGNITO_PROFILE, 2},
414 };
415
416
417 // The following test is split into three chunks to reduce the chance
418 // of hitting the 25s timeout.
419
420 IN_PROC_BROWSER_TEST_F(BrowserCloseTest, DownloadsCloseCheck_0) {
421 Profile* profile_a = browser()->profile();
achuithb 2011/08/29 17:19:10 Any reason to not pull out the boiler-plate in Dow
Randy Smith (Not in Mondays) 2011/10/13 20:06:04 Nope; hadn't gotten to it. Done.
422 Profile* profile_b = CreateSecondProfile();
423 ASSERT_TRUE(profile_b);
424
425 ScopedTempDir profile_a_dir;
426 ASSERT_TRUE(profile_a_dir.CreateUniqueTempDir());
427 profile_a->GetPrefs()->SetFilePath(
428 prefs::kDownloadDefaultDirectory,
429 profile_a_dir.path());
430 ScopedTempDir profile_b_dir;
431 ASSERT_TRUE(profile_b_dir.CreateUniqueTempDir());
432 profile_b->GetPrefs()->SetFilePath(
433 prefs::kDownloadDefaultDirectory,
434 profile_b_dir.path());
435
436 for (size_t i = 0; i < arraysize(download_close_check_cases) / 3; ++i) {
437 const DownloadsCloseCheckCase& check_case(download_close_check_cases[i]);
438 ASSERT_TRUE(CheckDownloadsClose(check_case, profile_a, profile_b));
439 }
440 }
441
442 IN_PROC_BROWSER_TEST_F(BrowserCloseTest, DownloadsCloseCheck_1) {
443 Profile* profile_a = browser()->profile();
444 Profile* profile_b = CreateSecondProfile();
445 ASSERT_TRUE(profile_b);
446
447 ScopedTempDir profile_a_dir;
448 ASSERT_TRUE(profile_a_dir.CreateUniqueTempDir());
449 profile_a->GetPrefs()->SetFilePath(
450 prefs::kDownloadDefaultDirectory,
451 profile_a_dir.path());
452 ScopedTempDir profile_b_dir;
453 ASSERT_TRUE(profile_b_dir.CreateUniqueTempDir());
454 profile_b->GetPrefs()->SetFilePath(
455 prefs::kDownloadDefaultDirectory,
456 profile_b_dir.path());
457
458 for (size_t i = arraysize(download_close_check_cases) / 3;
459 i < 2 * arraysize(download_close_check_cases) / 3; ++i) {
460 const DownloadsCloseCheckCase& check_case(download_close_check_cases[i]);
461 ASSERT_TRUE(CheckDownloadsClose(check_case, profile_a, profile_b));
462 }
463 }
464
465 IN_PROC_BROWSER_TEST_F(BrowserCloseTest, DownloadsCloseCheck_2) {
466 Profile* profile_a = browser()->profile();
467 Profile* profile_b = CreateSecondProfile();
468 ASSERT_TRUE(profile_b);
469
470 ScopedTempDir profile_a_dir;
471 ASSERT_TRUE(profile_a_dir.CreateUniqueTempDir());
472 profile_a->GetPrefs()->SetFilePath(
473 prefs::kDownloadDefaultDirectory,
474 profile_a_dir.path());
475 ScopedTempDir profile_b_dir;
476 ASSERT_TRUE(profile_b_dir.CreateUniqueTempDir());
477 profile_b->GetPrefs()->SetFilePath(
478 prefs::kDownloadDefaultDirectory,
479 profile_b_dir.path());
480
481 for (size_t i = 2 * arraysize(download_close_check_cases) / 3;
482 i < arraysize(download_close_check_cases); ++i) {
483 const DownloadsCloseCheckCase& check_case(download_close_check_cases[i]);
484 ASSERT_TRUE(CheckDownloadsClose(check_case, profile_a, profile_b));
485 }
486 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/browser.cc ('k') | chrome/browser/ui/browser_list.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698