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

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: Parallel view cleanup to gtk. Created 9 years, 5 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
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/stringprintf.h"
7 #include "chrome/browser/browser_process.h"
8 #include "chrome/browser/download/download_item.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/common/pref_names.h"
16 #include "chrome/test/in_process_browser_test.h"
17 #include "chrome/test/ui_test_utils.h"
18 #include "content/browser/net/url_request_slow_download_job.h"
19 #include "content/browser/tab_contents/tab_contents.h"
20 #include "content/common/page_transition_types.h"
21 #include "content/common/url_constants.h"
22
23 class BrowserCloseTest : public InProcessBrowserTest {
24 protected:
25 // Create a second profile to work within multi-profile.
26 Profile* CreateSecondProfile() {
27 if (!second_profile_data_dir_.CreateUniqueTempDir())
28 return NULL;
29
30 return g_browser_process->profile_manager()->GetProfile(
31 second_profile_data_dir_.path());
32 }
33
34 // Create |num_downloads| number of downloads that are stalled
35 // (will quickly get to a place where the server won't
36 // provide any more data) so that we can test closing the
37 // browser with active downloads.
38 void CreateStalledDownloads(Browser* browser, int num_downloads) {
39 GURL url(URLRequestSlowDownloadJob::kKnownSizeUrl);
40
41 if (num_downloads == 0)
42 return;
43
44 // Setup an observer waiting for the given number of downloads
45 // to get to IN_PROGRESS.
46 DownloadManager* download_manager =
47 browser->profile()->GetDownloadManager();
48 scoped_ptr<DownloadTestObserver> observer(
49 new DownloadTestObserver(
50 download_manager, num_downloads,
51 DownloadItem::IN_PROGRESS,
52 true, // Bail on select file
53 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL));
54
55 // Set of that number of downloads.
56 while (num_downloads--)
57 ui_test_utils::NavigateToURLWithDisposition(
58 browser, url, NEW_BACKGROUND_TAB,
59 ui_test_utils::BROWSER_TEST_NONE);
60
61 // Wait for them.
62 observer->WaitForFinished();
63 }
64
65 // All all downloads created in CreateStalledDownloads() to
66 // complete, and block in this routine until they do complete.
67 void CompleteAllDownloads(Browser* browser) {
68 GURL finish_url(URLRequestSlowDownloadJob::kFinishDownloadUrl);
69 ui_test_utils::NavigateToURL(browser, finish_url);
70
71 // Go through and, for every single profile, wait until there are
72 // no active downloads on that download manager.
73 std::vector<Profile*> profiles(
74 g_browser_process->profile_manager()->GetLoadedProfiles());
75 for (std::vector<Profile*>::const_iterator pit = profiles.begin();
76 pit != profiles.end(); ++pit) {
77 if ((*pit)->HasCreatedDownloadManager()) {
78 DownloadManager *mgr = (*pit)->GetDownloadManager();
79 scoped_refptr<DownloadTestFlushObserver> observer(
80 new DownloadTestFlushObserver(mgr));
81 observer->WaitForFlush();
82 }
83 }
84 }
85
86 // Create a Browser (with associated window) on the specified profile.
87 Browser* CreateBrowserOnProfile(Profile* profile) {
88 Browser* new_browser = Browser::Create(profile);
89 new_browser->AddSelectedTabWithURL(GURL(chrome::kAboutBlankURL),
90 PageTransition::START_PAGE);
91 ui_test_utils::WaitForNavigation(
92 &new_browser->GetSelectedTabContents()->controller());
93 new_browser->window()->Show();
94 return new_browser;
95 }
96
97 // Adjust the number of browsers and associated windows up or down
98 // to |num_windows|. This routine assumes that there is only a single
99 // browser associated with the profile on entry. |*base_browser| contains
100 // this browser, and the profile is derived from that browser. On output,
101 // if |*base_browser| was destroyed (because |num_windows == 0|), NULL
102 // is assigned to that memory location.
103 bool AdjustBrowsersOnProfile(Browser** base_browser, int num_windows) {
104 int num_downloads_blocking;
105 if (num_windows == 0) {
106 if (Browser::DOWNLOAD_CLOSE_OK !=
107 (*base_browser)->OkToCloseWithInProgressDownloads(
108 &num_downloads_blocking))
109 return false;
110 (*base_browser)->window()->Close();
111 *base_browser = 0;
112 return true;
113 }
114
115 // num_windows > 0
116 Profile* profile((*base_browser)->profile());
117 for (int w = 1; w < num_windows; w++) {
118 CreateBrowserOnProfile(profile);
119 }
120 return true;
121 }
122
123 ScopedTempDir second_profile_data_dir_;
124 };
125
126 struct DownloadsCloseCheckCase {
127 std::string DebugString() const;
128
129 // Input
130 struct {
131 struct {
132 int windows;
133 int downloads;
134 } regular;
135 struct {
136 int windows;
137 int downloads;
138 } incognito;
139 } profile_a;
140
141 struct {
142 struct {
143 int windows;
144 int downloads;
145 } regular;
146 struct {
147 int windows;
148 int downloads;
149 } incognito;
150 } profile_b;
151
152 // We always probe a window in profile A.
153 enum { REGULAR = 0, INCOGNITO = 1 } window_to_probe;
154
155 // Output
156 Browser::DownloadClosePreventionType type;
157
158 // Unchecked if type == DOWNLOAD_CLOSE_OK.
159 int num_blocking;
160 };
161
162 std::string DownloadsCloseCheckCase::DebugString() const {
163 std::string result;
164 result += "Case: {";
165 if (profile_a.regular.windows || profile_a.regular.downloads)
166 result += base::StringPrintf("Regular profile A: (%d w, %d d), ",
167 profile_a.regular.windows,
168 profile_a.regular.downloads);
169 if (profile_a.incognito.windows || profile_a.incognito.downloads)
170 result += base::StringPrintf("Incognito profile A: (%d w, %d d), ",
171 profile_a.incognito.windows,
172 profile_a.incognito.downloads);
173 if (profile_b.regular.windows || profile_b.regular.downloads)
174 result += base::StringPrintf("Regular profile B: (%d w, %d d), ",
175 profile_b.regular.windows,
176 profile_b.regular.downloads);
177 if (profile_b.incognito.windows || profile_b.incognito.downloads)
178 result += base::StringPrintf("Incognito profile B: (%d w, %d d), ",
179 profile_b.incognito.windows,
180 profile_b.incognito.downloads);
181 result += (window_to_probe == REGULAR ? "Probe regular" :
182 window_to_probe == INCOGNITO ? "Probe incognito" :
183 "Probe unknown");
184 result += "} -> ";
185 if (type == Browser::DOWNLOAD_CLOSE_OK) {
186 result += "No warning";
187 } else {
188 result += base::StringPrintf(
189 "%s (%d downloads) warning",
190 (type == Browser::DOWNLOAD_CLOSE_BROWSER_SHUTDOWN ? "Browser shutdown" :
191 type == Browser::DOWNLOAD_CLOSE_LAST_WINDOW_IN_INCOGNITO_PROFILE ?
192 "Incognito close" : "Unknown"),
193 num_blocking);
194 }
195 return result;
196 }
197
198 static const DownloadsCloseCheckCase download_close_check_cases[] = {
199 // Top level nesting is {profile_a, profile_b}
200 // Second level nesting is {regular, incognito
201 // Third level (inner) nesting is {windows, downloads}
202
203 // Last window (incognito) triggers browser close warning.
204 {{{0, 0}, {1, 1}}, {{0, 0}, {0, 0}}, DownloadsCloseCheckCase::INCOGNITO,
205 Browser::DOWNLOAD_CLOSE_BROWSER_SHUTDOWN, 1},
206
207 // Last incognito window triggers incognito close warning.
208 {{{1, 0}, {1, 1}}, {{0, 0}, {0, 0}}, DownloadsCloseCheckCase::INCOGNITO,
209 Browser::DOWNLOAD_CLOSE_LAST_WINDOW_IN_INCOGNITO_PROFILE, 1},
210
211 // Last incognito window with no downloads triggers no warning.
212 {{{0, 0}, {1, 0}}, {{0, 0}, {0, 0}}, DownloadsCloseCheckCase::INCOGNITO,
213 Browser::DOWNLOAD_CLOSE_OK},
214
215 // Last incognito window with window+download on another incognito profile
216 // triggers no warning.
217 {{{0, 0}, {1, 0}}, {{0, 0}, {1, 1}}, DownloadsCloseCheckCase::INCOGNITO,
218 Browser::DOWNLOAD_CLOSE_OK},
219
220 // Non-last incognito window triggers no warning.
221 {{{0, 0}, {2, 1}}, {{0, 0}, {0, 0}}, DownloadsCloseCheckCase::INCOGNITO,
222 Browser::DOWNLOAD_CLOSE_OK},
223
224 // Non-last regular window triggers no warning.
225 {{{2, 1}, {0, 0}}, {{0, 0}, {0, 0}}, DownloadsCloseCheckCase::REGULAR,
226 Browser::DOWNLOAD_CLOSE_OK},
227
228 // Last regular window triggers browser close.
229 {{{1, 1}, {0, 0}}, {{0, 0}, {0, 0}}, DownloadsCloseCheckCase::REGULAR,
230 Browser::DOWNLOAD_CLOSE_BROWSER_SHUTDOWN, 1},
231
232 // Last regular window triggers browser close for download on different
233 // profile.
234 {{{1, 0}, {0, 0}}, {{0, 1}, {0, 0}}, DownloadsCloseCheckCase::REGULAR,
235 Browser::DOWNLOAD_CLOSE_BROWSER_SHUTDOWN, 1},
236
237 // Last regular window triggers no warning if incognito
238 // active (http://crbug.com/61257).
239 {{{1, 0}, {1, 1}}, {{0, 0}, {0, 0}}, DownloadsCloseCheckCase::REGULAR,
240 Browser::DOWNLOAD_CLOSE_OK},
241
242 // Last regular window triggers no warning if other profile window active.
243 {{{1, 1}, {0, 0}}, {{1, 0}, {0, 0}}, DownloadsCloseCheckCase::REGULAR,
244 Browser::DOWNLOAD_CLOSE_OK},
245
246 // Last regular window triggers no warning if other incognito window
247 // active.
248 {{{1, 0}, {0, 0}}, {{0, 0}, {1, 1}}, DownloadsCloseCheckCase::REGULAR,
249 Browser::DOWNLOAD_CLOSE_OK},
250
251 // Last regular window triggers no warning if incognito active.
252 {{{1, 1}, {1, 0}}, {{0, 0}, {0, 0}}, DownloadsCloseCheckCase::REGULAR,
253 Browser::DOWNLOAD_CLOSE_OK},
254
255 // Test plural for regular.
256 {{{1, 2}, {0, 0}}, {{0, 0}, {0, 0}}, DownloadsCloseCheckCase::REGULAR,
257 Browser::DOWNLOAD_CLOSE_BROWSER_SHUTDOWN, 2},
258
259 // Test plural for incognito.
260 {{{1, 0}, {1, 2}}, {{0, 0}, {0, 0}}, DownloadsCloseCheckCase::INCOGNITO,
261 Browser::DOWNLOAD_CLOSE_LAST_WINDOW_IN_INCOGNITO_PROFILE, 2},
262 };
263
264 IN_PROC_BROWSER_TEST_F(BrowserCloseTest, DownloadsCloseCheck) {
265 Profile* profile_a = browser()->profile();
266 Profile* profile_b = CreateSecondProfile();
267 ASSERT_TRUE(profile_b);
268
269 ScopedTempDir profile_a_dir;
270 ASSERT_TRUE(profile_a_dir.CreateUniqueTempDir());
271 profile_a->GetPrefs()->SetFilePath(
272 prefs::kDownloadDefaultDirectory,
273 profile_a_dir.path());
274 ScopedTempDir profile_b_dir;
275 ASSERT_TRUE(profile_b_dir.CreateUniqueTempDir());
276 profile_b->GetPrefs()->SetFilePath(
277 prefs::kDownloadDefaultDirectory,
278 profile_b_dir.path());
279
280 for (size_t i = 0; i < arraysize(download_close_check_cases); ++i) {
281 const DownloadsCloseCheckCase& check_case(download_close_check_cases[i]);
282
283 // Loop invariant; so that we don't actually try and close the browser,
284 // we always enter the loop with a single browser window open on the
285 // main profile. That means we need to exit the loop the same way.
286 // So we setup everything except for the profile_a regular, and then
287 // flip the bit on the main window.
288 // Note that this means that browser() is unreliable in the context
289 // of this function; we'll be killing that main window and recreating
290 // it fairly frequently.
291
292 ASSERT_EQ(1u, BrowserList::size()) << "Case: " << i;
293 Browser* entry_browser = *BrowserList::begin();
294 ASSERT_EQ(profile_a, entry_browser->profile()) << "Case: " << i;
295 ASSERT_EQ(0, g_browser_process->profile_manager()->TotalDownloadCount())
296 << "Case: " << i;
297
298 Profile* profile_a_incognito = profile_a->GetOffTheRecordProfile();
299 Profile* profile_b_incognito = profile_b->GetOffTheRecordProfile();
300
301 // For simplicty of coding, we create a window on each profile so that
302 // we can easily create downloads, then we destroy or create windows
303 // as necessary.
304 Browser* browser_a_regular(CreateBrowserOnProfile(profile_a));
305 Browser* browser_a_incognito(CreateBrowserOnProfile(profile_a_incognito));
306 Browser* browser_b_regular(CreateBrowserOnProfile(profile_b));
307 Browser* browser_b_incognito(CreateBrowserOnProfile(profile_b_incognito));
308
309 // Kill our entry browser.
310 entry_browser->window()->Close();
311 entry_browser = NULL;
312
313 // Create all downloads needed.
314 CreateStalledDownloads(
315 browser_a_regular, check_case.profile_a.regular.downloads);
316 CreateStalledDownloads(
317 browser_a_incognito, check_case.profile_a.incognito.downloads);
318 CreateStalledDownloads(
319 browser_b_regular, check_case.profile_b.regular.downloads);
320 CreateStalledDownloads(
321 browser_b_incognito, check_case.profile_b.incognito.downloads);
322
323 // Adjust the windows
324 ASSERT_TRUE(AdjustBrowsersOnProfile(
325 &browser_a_regular, check_case.profile_a.regular.windows));
326 ASSERT_TRUE(AdjustBrowsersOnProfile(
327 &browser_a_incognito, check_case.profile_a.incognito.windows));
328 ASSERT_TRUE(AdjustBrowsersOnProfile(
329 &browser_b_regular, check_case.profile_b.regular.windows));
330 ASSERT_TRUE(AdjustBrowsersOnProfile(
331 &browser_b_incognito, check_case.profile_b.incognito.windows));
332 ui_test_utils::RunAllPendingInMessageLoop();
333
334 // All that work, for this one little test.
335 ASSERT_TRUE((check_case.window_to_probe ==
336 DownloadsCloseCheckCase::REGULAR) ||
337 (check_case.window_to_probe ==
338 DownloadsCloseCheckCase::INCOGNITO));
339
340 int num_downloads_blocking;
341 Browser* browser_to_probe =
342 (check_case.window_to_probe == DownloadsCloseCheckCase::REGULAR ?
343 browser_a_regular :
344 browser_a_incognito);
345 Browser::DownloadClosePreventionType type =
346 browser_to_probe->OkToCloseWithInProgressDownloads(
347 &num_downloads_blocking);
348 EXPECT_EQ(check_case.type, type) << check_case.DebugString();
349 if (check_case.type != Browser::DOWNLOAD_CLOSE_OK)
350 EXPECT_EQ(check_case.num_blocking, num_downloads_blocking)
351 << check_case.DebugString();
352
353 // Release all the downloads.
354 CompleteAllDownloads(browser_to_probe);
355
356 // Create a new main window and kill everything else.
357 entry_browser = CreateBrowserOnProfile(profile_a);
358 for (BrowserList::const_iterator bit = BrowserList::begin();
359 bit != BrowserList::end(); ++bit) {
360 if ((*bit) != entry_browser) {
361 ASSERT_TRUE((*bit)->window());
362 (*bit)->window()->Close();
363 }
364 }
365 ui_test_utils::RunAllPendingInMessageLoop();
366 }
367 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698