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

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

Powered by Google App Engine
This is Rietveld 408576698