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