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/file_path.h"
6 #include "base/file_util.h"
7 #include "base/memory/ref_counted.h"
8 #include "base/memory/scoped_temp_dir.h"
9 #include "base/path_service.h"
10 #include "base/test/test_file_util.h"
11 #include "base/utf_string_conversions.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/download/download_item.h"
14 #include "chrome/browser/download/download_file_manager.h"
15 #include "chrome/browser/download/download_manager.h"
16 #include "chrome/browser/download/download_prefs.h"
17 #include "chrome/browser/download/download_shelf.h"
18 #include "chrome/browser/history/download_create_info.h"
19 #include "chrome/browser/history/history.h"
20 #include "chrome/browser/net/url_request_mock_http_job.h"
21 #include "chrome/browser/net/url_request_slow_download_job.h"
22 #include "chrome/browser/prefs/pref_service.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/ui/browser.h"
25 #include "chrome/browser/ui/browser_list.h"
26 #include "chrome/browser/ui/browser_window.h"
27 #include "chrome/common/chrome_paths.h"
28 #include "chrome/common/pref_names.h"
29 #include "chrome/common/url_constants.h"
30 #include "chrome/test/in_process_browser_test.h"
31 #include "chrome/test/ui_test_utils.h"
32 #include "content/browser/cancelable_request.h"
33 #include "content/browser/renderer_host/resource_dispatcher_host.h"
34 #include "content/common/page_transition_types.h"
35 #include "net/base/net_util.h"
36 #include "testing/gtest/include/gtest/gtest.h"
37
38 namespace {
39
40 // Variation of DownloadsCompleteObserver from ui_test_utils.cc; the
41 // specifically targeted download tests need finer granularity on waiting.
42 // Construction of this class defines a system state, based on some number
43 // of downloads being seen in a particular state + other events that
44 // may occur in the download system. That state will be recorded if it
45 // occurs at any point after construction. When that state occurs, the class
46 // is considered finished. Callers may either probe for the finished state, or
47 // wait on it.
48 //
49 // TODO(rdsmith): Detect manager going down, remove pointer to
50 // DownloadManager, transition to finished. (For right now we
51 // just use a scoped_refptr<> to keep it around, but that may cause
52 // timeouts on waiting if a DownloadManager::Shutdown() occurs which
53 // cancels our in-progress downloads.)
54 class DownloadsObserver : public DownloadManager::Observer,
55 public DownloadItem::Observer {
56 public:
57 // Create an object that will be considered finished when |wait_count|
58 // download items have entered state |download_finished_state|.
59 // If |finish_on_select_file| is true, the object will also be
60 // considered finished if the DownloadManager raises a
61 // SelectFileDialogDisplayed() notification.
62
63 // TODO(rdsmith): Add option of "dangerous accept/reject dialog" as
64 // a unblocking event; if that shows up when you aren't expecting it,
65 // it'll result in a hang/timeout as we'll never get to final rename.
66 // This probably means rewriting the interface to take a list of events
67 // to treat as completion events.
DownloadsObserver(DownloadManager * download_manager,size_t wait_count,DownloadItem::DownloadState download_finished_state,bool finish_on_select_file)68 DownloadsObserver(DownloadManager* download_manager,
69 size_t wait_count,
70 DownloadItem::DownloadState download_finished_state,
71 bool finish_on_select_file)
72 : download_manager_(download_manager),
73 wait_count_(wait_count),
74 finished_downloads_at_construction_(0),
75 waiting_(false),
76 download_finished_state_(download_finished_state),
77 finish_on_select_file_(finish_on_select_file),
78 select_file_dialog_seen_(false) {
79 download_manager_->AddObserver(this); // Will call initial ModelChanged().
80 finished_downloads_at_construction_ = finished_downloads_.size();
81 }
82
~DownloadsObserver()83 ~DownloadsObserver() {
84 std::set<DownloadItem*>::iterator it = downloads_observed_.begin();
85 for (; it != downloads_observed_.end(); ++it) {
86 (*it)->RemoveObserver(this);
87 }
88 download_manager_->RemoveObserver(this);
89 }
90
91 // State accessors.
select_file_dialog_seen()92 bool select_file_dialog_seen() { return select_file_dialog_seen_; }
93
94 // Wait for whatever state was specified in the constructor.
WaitForFinished()95 void WaitForFinished() {
96 if (!IsFinished()) {
97 waiting_ = true;
98 ui_test_utils::RunMessageLoop();
99 waiting_ = false;
100 }
101 }
102
103 // Return true if everything's happened that we're configured for.
IsFinished()104 bool IsFinished() {
105 if (finished_downloads_.size() - finished_downloads_at_construction_
106 >= wait_count_)
107 return true;
108 return (finish_on_select_file_ && select_file_dialog_seen_);
109 }
110
111 // DownloadItem::Observer
OnDownloadUpdated(DownloadItem * download)112 virtual void OnDownloadUpdated(DownloadItem* download) {
113 if (download->state() == download_finished_state_)
114 DownloadInFinalState(download);
115 }
116
OnDownloadOpened(DownloadItem * download)117 virtual void OnDownloadOpened(DownloadItem* download) {}
118
119 // DownloadManager::Observer
ModelChanged()120 virtual void ModelChanged() {
121 // Regenerate DownloadItem observers. If there are any download items
122 // in our final state, note them in |finished_downloads_|
123 // (done by |OnDownloadUpdated()|).
124 std::vector<DownloadItem*> downloads;
125 download_manager_->SearchDownloads(string16(), &downloads);
126
127 std::vector<DownloadItem*>::iterator it = downloads.begin();
128 for (; it != downloads.end(); ++it) {
129 OnDownloadUpdated(*it); // Safe to call multiple times; checks state.
130
131 std::set<DownloadItem*>::const_iterator
132 finished_it(finished_downloads_.find(*it));
133 std::set<DownloadItem*>::iterator
134 observed_it(downloads_observed_.find(*it));
135
136 // If it isn't finished and we're aren't observing it, start.
137 if (finished_it == finished_downloads_.end() &&
138 observed_it == downloads_observed_.end()) {
139 (*it)->AddObserver(this);
140 downloads_observed_.insert(*it);
141 continue;
142 }
143
144 // If it is finished and we are observing it, stop.
145 if (finished_it != finished_downloads_.end() &&
146 observed_it != downloads_observed_.end()) {
147 (*it)->RemoveObserver(this);
148 downloads_observed_.erase(observed_it);
149 continue;
150 }
151 }
152 }
153
SelectFileDialogDisplayed(int32)154 virtual void SelectFileDialogDisplayed(int32 /* id */) {
155 select_file_dialog_seen_ = true;
156 SignalIfFinished();
157 }
158
159 private:
160 // Called when we know that a download item is in a final state.
161 // Note that this is not the same as it first transitioning in to the
162 // final state; multiple notifications may occur once the item is in
163 // that state. So we keep our own track of transitions into final.
DownloadInFinalState(DownloadItem * download)164 void DownloadInFinalState(DownloadItem* download) {
165 if (finished_downloads_.find(download) != finished_downloads_.end()) {
166 // We've already seen terminal state on this download.
167 return;
168 }
169
170 // Record the transition.
171 finished_downloads_.insert(download);
172
173 SignalIfFinished();
174 }
175
SignalIfFinished()176 void SignalIfFinished() {
177 if (waiting_ && IsFinished())
178 MessageLoopForUI::current()->Quit();
179 }
180
181 // The observed download manager.
182 scoped_refptr<DownloadManager> download_manager_;
183
184 // The set of DownloadItem's that have transitioned to their finished state
185 // since construction of this object. When the size of this array
186 // reaches wait_count_, we're done.
187 std::set<DownloadItem*> finished_downloads_;
188
189 // The set of DownloadItem's we are currently observing. Generally there
190 // won't be any overlap with the above; once we see the final state
191 // on a DownloadItem, we'll stop observing it.
192 std::set<DownloadItem*> downloads_observed_;
193
194 // The number of downloads to wait on completing.
195 size_t wait_count_;
196
197 // The number of downloads entered in final state in initial
198 // ModelChanged(). We use |finished_downloads_| to track the incoming
199 // transitions to final state we should ignore, and to track the
200 // number of final state transitions that occurred between
201 // construction and return from wait. But some downloads may be in our
202 // final state (and thus be entered into |finished_downloads_|) when we
203 // construct this class. We don't want to count those in our transition
204 // to finished.
205 int finished_downloads_at_construction_;
206
207 // Whether an internal message loop has been started and must be quit upon
208 // all downloads completing.
209 bool waiting_;
210
211 // The state on which to consider the DownloadItem finished.
212 DownloadItem::DownloadState download_finished_state_;
213
214 // True if we should transition the DownloadsObserver to finished if
215 // the select file dialog comes up.
216 bool finish_on_select_file_;
217
218 // True if we've seen the select file dialog.
219 bool select_file_dialog_seen_;
220
221 DISALLOW_COPY_AND_ASSIGN(DownloadsObserver);
222 };
223
224 // WaitForFlush() returns after:
225 // * There are no IN_PROGRESS download items remaining on the
226 // DownloadManager.
227 // * There have been two round trip messages through the file and
228 // IO threads.
229 // This almost certainly means that a Download cancel has propagated through
230 // the system.
231 class DownloadsFlushObserver
232 : public DownloadManager::Observer,
233 public DownloadItem::Observer,
234 public base::RefCountedThreadSafe<DownloadsFlushObserver> {
235 public:
DownloadsFlushObserver(DownloadManager * download_manager)236 explicit DownloadsFlushObserver(DownloadManager* download_manager)
237 : download_manager_(download_manager),
238 waiting_for_zero_inprogress_(true) { }
239
WaitForFlush()240 void WaitForFlush() {
241 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
242 download_manager_->AddObserver(this);
243 ui_test_utils::RunMessageLoop();
244 }
245
246 // DownloadsManager observer methods.
ModelChanged()247 virtual void ModelChanged() {
248 // Model has changed, so there may be more DownloadItems to observe.
249 CheckDownloadsInProgress(true);
250 }
251
252 // DownloadItem observer methods.
OnDownloadUpdated(DownloadItem * download)253 virtual void OnDownloadUpdated(DownloadItem* download) {
254 // No change in DownloadItem set on manager.
255 CheckDownloadsInProgress(false);
256 }
OnDownloadOpened(DownloadItem * download)257 virtual void OnDownloadOpened(DownloadItem* download) {}
258
259 protected:
260 friend class base::RefCountedThreadSafe<DownloadsFlushObserver>;
261
~DownloadsFlushObserver()262 virtual ~DownloadsFlushObserver() {
263 download_manager_->RemoveObserver(this);
264 for (std::set<DownloadItem*>::iterator it = downloads_observed_.begin();
265 it != downloads_observed_.end(); ++it) {
266 (*it)->RemoveObserver(this);
267 }
268 }
269
270 private:
271 // If we're waiting for that flush point, check the number
272 // of downloads in the IN_PROGRESS state and take appropriate
273 // action. If requested, also observes all downloads while iterating.
CheckDownloadsInProgress(bool observe_downloads)274 void CheckDownloadsInProgress(bool observe_downloads) {
275 if (waiting_for_zero_inprogress_) {
276 int count = 0;
277
278 std::vector<DownloadItem*> downloads;
279 download_manager_->SearchDownloads(string16(), &downloads);
280 std::vector<DownloadItem*>::iterator it = downloads.begin();
281 for (; it != downloads.end(); ++it) {
282 if ((*it)->state() == DownloadItem::IN_PROGRESS)
283 count++;
284 if (observe_downloads) {
285 if (downloads_observed_.find(*it) == downloads_observed_.end()) {
286 (*it)->AddObserver(this);
287 }
288 // Download items are forever, and we don't want to make
289 // assumptions about future state transitions, so once we
290 // start observing them, we don't stop until destruction.
291 }
292 }
293
294 if (count == 0) {
295 waiting_for_zero_inprogress_ = false;
296 // Stop observing DownloadItems. We maintain the observation
297 // of DownloadManager so that we don't have to independently track
298 // whether we are observing it for conditional destruction.
299 for (std::set<DownloadItem*>::iterator it = downloads_observed_.begin();
300 it != downloads_observed_.end(); ++it) {
301 (*it)->RemoveObserver(this);
302 }
303 downloads_observed_.clear();
304
305 // Trigger next step. We need to go past the IO thread twice, as
306 // there's a self-task posting in the IO thread cancel path.
307 BrowserThread::PostTask(
308 BrowserThread::FILE, FROM_HERE,
309 NewRunnableMethod(this,
310 &DownloadsFlushObserver::PingFileThread, 2));
311 }
312 }
313 }
314
PingFileThread(int cycle)315 void PingFileThread(int cycle) {
316 BrowserThread::PostTask(
317 BrowserThread::IO, FROM_HERE,
318 NewRunnableMethod(this, &DownloadsFlushObserver::PingIOThread,
319 cycle));
320 }
321
PingIOThread(int cycle)322 void PingIOThread(int cycle) {
323 if (--cycle) {
324 BrowserThread::PostTask(
325 BrowserThread::UI, FROM_HERE,
326 NewRunnableMethod(this, &DownloadsFlushObserver::PingFileThread,
327 cycle));
328 } else {
329 BrowserThread::PostTask(
330 BrowserThread::UI, FROM_HERE, new MessageLoop::QuitTask());
331 }
332 }
333
334 DownloadManager* download_manager_;
335 std::set<DownloadItem*> downloads_observed_;
336 bool waiting_for_zero_inprogress_;
337
338 DISALLOW_COPY_AND_ASSIGN(DownloadsFlushObserver);
339 };
340
341 // Collect the information from FILE and IO threads needed for the Cancel
342 // Test, specifically the number of outstanding requests on the
343 // ResourceDispatcherHost and the number of pending downloads on the
344 // DownloadFileManager.
345 class CancelTestDataCollector
346 : public base::RefCountedThreadSafe<CancelTestDataCollector> {
347 public:
CancelTestDataCollector()348 CancelTestDataCollector()
349 : resource_dispatcher_host_(
350 g_browser_process->resource_dispatcher_host()),
351 rdh_pending_requests_(0),
352 dfm_pending_downloads_(0) { }
353
WaitForDataCollected()354 void WaitForDataCollected() {
355 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
356 BrowserThread::PostTask(
357 BrowserThread::IO, FROM_HERE,
358 NewRunnableMethod(this, &CancelTestDataCollector::IOInfoCollector));
359 ui_test_utils::RunMessageLoop();
360 }
361
rdh_pending_requests()362 int rdh_pending_requests() { return rdh_pending_requests_; }
dfm_pending_downloads()363 int dfm_pending_downloads() { return dfm_pending_downloads_; }
364
365 protected:
366 friend class base::RefCountedThreadSafe<CancelTestDataCollector>;
367
~CancelTestDataCollector()368 virtual ~CancelTestDataCollector() {}
369
370 private:
371
IOInfoCollector()372 void IOInfoCollector() {
373 download_file_manager_ = resource_dispatcher_host_->download_file_manager();
374 rdh_pending_requests_ = resource_dispatcher_host_->pending_requests();
375 BrowserThread::PostTask(
376 BrowserThread::FILE, FROM_HERE,
377 NewRunnableMethod(this, &CancelTestDataCollector::FileInfoCollector));
378 }
379
FileInfoCollector()380 void FileInfoCollector() {
381 dfm_pending_downloads_ = download_file_manager_->NumberOfActiveDownloads();
382 BrowserThread::PostTask(
383 BrowserThread::UI, FROM_HERE, new MessageLoop::QuitTask());
384 }
385
386 ResourceDispatcherHost* resource_dispatcher_host_;
387 DownloadFileManager* download_file_manager_;
388 int rdh_pending_requests_;
389 int dfm_pending_downloads_;
390
391 DISALLOW_COPY_AND_ASSIGN(CancelTestDataCollector);
392 };
393
394 } // namespace
395
396 class DownloadTest : public InProcessBrowserTest {
397 public:
398 enum SelectExpectation {
399 EXPECT_NO_SELECT_DIALOG = -1,
400 EXPECT_NOTHING,
401 EXPECT_SELECT_DIALOG
402 };
403
404 // Returning false indicates a failure of the setup, and should be asserted
405 // in the caller.
InitialSetup(bool prompt_for_download)406 virtual bool InitialSetup(bool prompt_for_download) {
407 bool have_test_dir = PathService::Get(chrome::DIR_TEST_DATA, &test_dir_);
408 EXPECT_TRUE(have_test_dir);
409 if (!have_test_dir)
410 return false;
411
412 // Sanity check default values for window / tab count and shelf visibility.
413 int window_count = BrowserList::size();
414 EXPECT_EQ(1, window_count);
415 EXPECT_EQ(1, browser()->tab_count());
416 bool is_shelf_visible = browser()->window()->IsDownloadShelfVisible();
417 EXPECT_FALSE(is_shelf_visible);
418
419 // Set up the temporary download folder.
420 bool created_downloads_dir = CreateAndSetDownloadsDirectory(browser());
421 EXPECT_TRUE(created_downloads_dir);
422 if (!created_downloads_dir)
423 return false;
424 browser()->profile()->GetPrefs()->SetBoolean(prefs::kPromptForDownload,
425 prompt_for_download);
426
427 return true;
428 }
429
430 protected:
431
432 enum SizeTestType {
433 SIZE_TEST_TYPE_KNOWN,
434 SIZE_TEST_TYPE_UNKNOWN,
435 };
436
437 // Location of the file source (the place from which it is downloaded).
OriginFile(FilePath file)438 FilePath OriginFile(FilePath file) {
439 return test_dir_.Append(file);
440 }
441
442 // Location of the file destination (place to which it is downloaded).
DestinationFile(Browser * browser,FilePath file)443 FilePath DestinationFile(Browser* browser, FilePath file) {
444 return GetDownloadDirectory(browser).Append(file);
445 }
446
447 // Must be called after browser creation. Creates a temporary
448 // directory for downloads that is auto-deleted on destruction.
449 // Returning false indicates a failure of the function, and should be asserted
450 // in the caller.
CreateAndSetDownloadsDirectory(Browser * browser)451 bool CreateAndSetDownloadsDirectory(Browser* browser) {
452 if (!browser)
453 return false;
454
455 if (!downloads_directory_.CreateUniqueTempDir())
456 return false;
457
458 browser->profile()->GetPrefs()->SetFilePath(
459 prefs::kDownloadDefaultDirectory,
460 downloads_directory_.path());
461
462 return true;
463 }
464
GetDownloadDirectory(Browser * browser)465 FilePath GetDownloadDirectory(Browser* browser) {
466 DownloadManager* download_mananger =
467 browser->profile()->GetDownloadManager();
468 return download_mananger->download_prefs()->download_path();
469 }
470
471 // Create a DownloadsObserver that will wait for the
472 // specified number of downloads to finish.
CreateWaiter(Browser * browser,int num_downloads)473 DownloadsObserver* CreateWaiter(Browser* browser, int num_downloads) {
474 DownloadManager* download_manager =
475 browser->profile()->GetDownloadManager();
476 return new DownloadsObserver(
477 download_manager, num_downloads,
478 DownloadItem::COMPLETE, // Really done
479 true); // Bail on select file
480 }
481
482 // Create a DownloadsObserver that will wait for the
483 // specified number of downloads to start.
CreateInProgressWaiter(Browser * browser,int num_downloads)484 DownloadsObserver* CreateInProgressWaiter(Browser* browser,
485 int num_downloads) {
486 DownloadManager* download_manager =
487 browser->profile()->GetDownloadManager();
488 return new DownloadsObserver(
489 download_manager, num_downloads,
490 DownloadItem::IN_PROGRESS, // Has started
491 true); // Bail on select file
492 }
493
494 // Download |url|, then wait for the download to finish.
495 // |disposition| indicates where the navigation occurs (current tab, new
496 // foreground tab, etc).
497 // |expectation| indicates whether or not a Select File dialog should be
498 // open when the download is finished, or if we don't care.
499 // If the dialog appears, the routine exits. The only effect |expectation|
500 // has is whether or not the test succeeds.
501 // |browser_test_flags| indicate what to wait for, and is an OR of 0 or more
502 // values in the ui_test_utils::BrowserTestWaitFlags enum.
DownloadAndWaitWithDisposition(Browser * browser,const GURL & url,WindowOpenDisposition disposition,SelectExpectation expectation,int browser_test_flags)503 void DownloadAndWaitWithDisposition(Browser* browser,
504 const GURL& url,
505 WindowOpenDisposition disposition,
506 SelectExpectation expectation,
507 int browser_test_flags) {
508 // Setup notification, navigate, and block.
509 scoped_ptr<DownloadsObserver> observer(CreateWaiter(browser, 1));
510 // This call will block until the condition specified by
511 // |browser_test_flags|, but will not wait for the download to finish.
512 ui_test_utils::NavigateToURLWithDisposition(browser,
513 url,
514 disposition,
515 browser_test_flags);
516 // Waits for the download to complete.
517 observer->WaitForFinished();
518
519 // If specified, check the state of the select file dialog.
520 if (expectation != EXPECT_NOTHING) {
521 EXPECT_EQ(expectation == EXPECT_SELECT_DIALOG,
522 observer->select_file_dialog_seen());
523 }
524 }
525
526 // Download a file in the current tab, then wait for the download to finish.
DownloadAndWait(Browser * browser,const GURL & url,SelectExpectation expectation)527 void DownloadAndWait(Browser* browser,
528 const GURL& url,
529 SelectExpectation expectation) {
530 DownloadAndWaitWithDisposition(
531 browser,
532 url,
533 CURRENT_TAB,
534 expectation,
535 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
536 }
537
538 // Should only be called when the download is known to have finished
539 // (in error or not).
540 // Returning false indicates a failure of the function, and should be asserted
541 // in the caller.
CheckDownload(Browser * browser,const FilePath & downloaded_filename,const FilePath & origin_filename)542 bool CheckDownload(Browser* browser,
543 const FilePath& downloaded_filename,
544 const FilePath& origin_filename) {
545 // Find the path to which the data will be downloaded.
546 FilePath downloaded_file(DestinationFile(browser, downloaded_filename));
547
548 // Find the origin path (from which the data comes).
549 FilePath origin_file(OriginFile(origin_filename));
550 bool origin_file_exists = file_util::PathExists(origin_file);
551 EXPECT_TRUE(origin_file_exists);
552 if (!origin_file_exists)
553 return false;
554
555 // Confirm the downloaded data file exists.
556 bool downloaded_file_exists = file_util::PathExists(downloaded_file);
557 EXPECT_TRUE(downloaded_file_exists);
558 if (!downloaded_file_exists)
559 return false;
560
561 int64 origin_file_size = 0;
562 int64 downloaded_file_size = 0;
563 EXPECT_TRUE(file_util::GetFileSize(origin_file, &origin_file_size));
564 EXPECT_TRUE(file_util::GetFileSize(downloaded_file, &downloaded_file_size));
565 EXPECT_EQ(origin_file_size, downloaded_file_size);
566 EXPECT_TRUE(file_util::ContentsEqual(downloaded_file, origin_file));
567
568 // Delete the downloaded copy of the file.
569 bool downloaded_file_deleted =
570 file_util::DieFileDie(downloaded_file, false);
571 EXPECT_TRUE(downloaded_file_deleted);
572 return downloaded_file_deleted;
573 }
574
RunSizeTest(Browser * browser,SizeTestType type,const std::string & partial_indication,const std::string & total_indication)575 bool RunSizeTest(Browser* browser,
576 SizeTestType type,
577 const std::string& partial_indication,
578 const std::string& total_indication) {
579 if (!InitialSetup(false))
580 return false;
581
582 EXPECT_TRUE(type == SIZE_TEST_TYPE_UNKNOWN || type == SIZE_TEST_TYPE_KNOWN);
583 if (type != SIZE_TEST_TYPE_KNOWN && type != SIZE_TEST_TYPE_UNKNOWN)
584 return false;
585 GURL url(type == SIZE_TEST_TYPE_KNOWN ?
586 URLRequestSlowDownloadJob::kKnownSizeUrl :
587 URLRequestSlowDownloadJob::kUnknownSizeUrl);
588
589 // TODO(ahendrickson) -- |expected_title_in_progress| and
590 // |expected_title_finished| need to be checked.
591 FilePath filename;
592 net::FileURLToFilePath(url, &filename);
593 string16 expected_title_in_progress(
594 ASCIIToUTF16(partial_indication) + filename.LossyDisplayName());
595 string16 expected_title_finished(
596 ASCIIToUTF16(total_indication) + filename.LossyDisplayName());
597
598 // Download a partial web page in a background tab and wait.
599 // The mock system will not complete until it gets a special URL.
600 scoped_ptr<DownloadsObserver> observer(CreateWaiter(browser, 1));
601 ui_test_utils::NavigateToURL(browser, url);
602
603 // TODO(ahendrickson): check download status text before downloading.
604 // Need to:
605 // - Add a member function to the |DownloadShelf| interface class, that
606 // indicates how many members it has.
607 // - Add a member function to |DownloadShelf| to get the status text
608 // of a given member (for example, via the name in |DownloadItemView|'s
609 // GetAccessibleState() member function), by index.
610 // - Iterate over browser->window()->GetDownloadShelf()'s members
611 // to see if any match the status text we want. Start with the last one.
612
613 // Allow the request to finish. We do this by loading a second URL in a
614 // separate tab.
615 GURL finish_url(URLRequestSlowDownloadJob::kFinishDownloadUrl);
616 ui_test_utils::NavigateToURLWithDisposition(
617 browser,
618 finish_url,
619 NEW_FOREGROUND_TAB,
620 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
621 observer->WaitForFinished();
622
623 EXPECT_EQ(2, browser->tab_count());
624
625 // TODO(ahendrickson): check download status text after downloading.
626
627 // Make sure the download shelf is showing.
628 EXPECT_TRUE(IsDownloadUIVisible(browser));
629
630 FilePath basefilename(filename.BaseName());
631 net::FileURLToFilePath(url, &filename);
632 FilePath download_path = downloads_directory_.path().Append(basefilename);
633
634 bool downloaded_path_exists = file_util::PathExists(download_path);
635 EXPECT_TRUE(downloaded_path_exists);
636 if (!downloaded_path_exists)
637 return false;
638
639 // Delete the file we just downloaded.
640 EXPECT_TRUE(file_util::DieFileDie(download_path, true));
641 EXPECT_FALSE(file_util::PathExists(download_path));
642
643 return true;
644 }
645
GetDownloads(Browser * browser,std::vector<DownloadItem * > * downloads)646 void GetDownloads(Browser* browser, std::vector<DownloadItem*>* downloads) {
647 DCHECK(downloads);
648 DownloadManager* manager = browser->profile()->GetDownloadManager();
649 manager->SearchDownloads(string16(), downloads);
650 }
651
652 // Figure out if the appropriate download visibility was done. A
653 // utility function to support ChromeOS variations. On ChromeOS
654 // a webui panel is used instead of the download shelf; the
655 // test for TYPE_APP_PANEL detects this type of panel.
IsDownloadUIVisible(Browser * browser)656 static bool IsDownloadUIVisible(Browser* browser) {
657 #if defined(OS_CHROMEOS)
658 for (BrowserList::const_iterator it = BrowserList::begin();
659 it != BrowserList::end(); ++it) {
660 if ((*it)->type() == Browser::TYPE_APP_PANEL) {
661 return true;
662 }
663 }
664 return false;
665 #else
666 return browser->window()->IsDownloadShelfVisible();
667 #endif
668 }
669
ExpectWindowCountAfterDownload(size_t expected)670 static void ExpectWindowCountAfterDownload(size_t expected) {
671 #if defined(OS_CHROMEOS)
672 // On ChromeOS, a download panel is created to display
673 // download information, and this counts as a window.
674 expected++;
675 #endif
676 EXPECT_EQ(expected, BrowserList::size());
677 }
678
679 private:
680 // Location of the test data.
681 FilePath test_dir_;
682
683 // Location of the downloads directory for these tests
684 ScopedTempDir downloads_directory_;
685 };
686
687 // Get History Information.
688 class DownloadsHistoryDataCollector {
689 public:
DownloadsHistoryDataCollector(int64 download_db_handle,DownloadManager * manager)690 explicit DownloadsHistoryDataCollector(int64 download_db_handle,
691 DownloadManager* manager)
692 : result_valid_(false),
693 download_db_handle_(download_db_handle) {
694 HistoryService* hs =
695 manager->profile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
696 DCHECK(hs);
697 hs->QueryDownloads(
698 &callback_consumer_,
699 NewCallback(this,
700 &DownloadsHistoryDataCollector::OnQueryDownloadsComplete));
701
702 // Cannot complete immediately because the history backend runs on a
703 // separate thread, so we can assume that the RunMessageLoop below will
704 // be exited by the Quit in OnQueryDownloadsComplete.
705 ui_test_utils::RunMessageLoop();
706 }
707
GetDownloadsHistoryEntry(DownloadCreateInfo * result)708 bool GetDownloadsHistoryEntry(DownloadCreateInfo* result) {
709 DCHECK(result);
710 *result = result_;
711 return result_valid_;
712 }
713
714 private:
OnQueryDownloadsComplete(std::vector<DownloadCreateInfo> * entries)715 void OnQueryDownloadsComplete(
716 std::vector<DownloadCreateInfo>* entries) {
717 result_valid_ = false;
718 for (std::vector<DownloadCreateInfo>::const_iterator it = entries->begin();
719 it != entries->end(); ++it) {
720 if (it->db_handle == download_db_handle_) {
721 result_ = *it;
722 result_valid_ = true;
723 }
724 }
725 MessageLoopForUI::current()->Quit();
726 }
727
728 DownloadCreateInfo result_;
729 bool result_valid_;
730 int64 download_db_handle_;
731 CancelableRequestConsumer callback_consumer_;
732
733 DISALLOW_COPY_AND_ASSIGN(DownloadsHistoryDataCollector);
734 };
735
736 // NOTES:
737 //
738 // Files for these tests are found in DIR_TEST_DATA (currently
739 // "chrome\test\data\", see chrome_paths.cc).
740 // Mock responses have extension .mock-http-headers appended to the file name.
741
742 // Download a file due to the associated MIME type.
IN_PROC_BROWSER_TEST_F(DownloadTest,DownloadMimeType)743 IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadMimeType) {
744 ASSERT_TRUE(InitialSetup(false));
745 FilePath file(FILE_PATH_LITERAL("download-test1.lib"));
746 GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
747
748 // Download the file and wait. We do not expect the Select File dialog.
749 DownloadAndWait(browser(), url, EXPECT_NO_SELECT_DIALOG);
750
751 // Check state.
752 EXPECT_EQ(1, browser()->tab_count());
753 CheckDownload(browser(), file, file);
754 EXPECT_TRUE(IsDownloadUIVisible(browser()));
755 }
756
757 #if defined(OS_WIN)
758 // Download a file and confirm that the zone identifier (on windows)
759 // is set to internet.
IN_PROC_BROWSER_TEST_F(DownloadTest,CheckInternetZone)760 IN_PROC_BROWSER_TEST_F(DownloadTest, CheckInternetZone) {
761 ASSERT_TRUE(InitialSetup(false));
762 FilePath file(FILE_PATH_LITERAL("download-test1.lib"));
763 GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
764
765 // Download the file and wait. We do not expect the Select File dialog.
766 DownloadAndWait(browser(), url, EXPECT_NO_SELECT_DIALOG);
767
768 // Check state. Special file state must be checked before CheckDownload,
769 // as CheckDownload will delete the output file.
770 EXPECT_EQ(1, browser()->tab_count());
771 FilePath downloaded_file(DestinationFile(browser(), file));
772 if (file_util::VolumeSupportsADS(downloaded_file))
773 EXPECT_TRUE(file_util::HasInternetZoneIdentifier(downloaded_file));
774 CheckDownload(browser(), file, file);
775 EXPECT_TRUE(IsDownloadUIVisible(browser()));
776 }
777 #endif
778
779 // Put up a Select File dialog when the file is downloaded, due to its MIME
780 // type.
781 //
782 // This test runs correctly, but leaves behind turds in the test user's
783 // download directory because of http://crbug.com/62099. No big loss; it
784 // was primarily confirming DownloadsObserver wait on select file dialog
785 // functionality anyway.
IN_PROC_BROWSER_TEST_F(DownloadTest,DISABLED_DownloadMimeTypeSelect)786 IN_PROC_BROWSER_TEST_F(DownloadTest, DISABLED_DownloadMimeTypeSelect) {
787 ASSERT_TRUE(InitialSetup(true));
788 FilePath file(FILE_PATH_LITERAL("download-test1.lib"));
789 GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
790
791 // Download the file and wait. We expect the Select File dialog to appear
792 // due to the MIME type.
793 DownloadAndWait(browser(), url, EXPECT_SELECT_DIALOG);
794
795 // Check state.
796 EXPECT_EQ(1, browser()->tab_count());
797 // Since we exited while the Select File dialog was visible, there should not
798 // be anything in the download shelf and so it should not be visible.
799 EXPECT_FALSE(IsDownloadUIVisible(browser()));
800 }
801
802 // Access a file with a viewable mime-type, verify that a download
803 // did not initiate.
IN_PROC_BROWSER_TEST_F(DownloadTest,NoDownload)804 IN_PROC_BROWSER_TEST_F(DownloadTest, NoDownload) {
805 ASSERT_TRUE(InitialSetup(false));
806 FilePath file(FILE_PATH_LITERAL("download-test2.html"));
807 GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
808 FilePath file_path(DestinationFile(browser(), file));
809
810 // Open a web page and wait.
811 ui_test_utils::NavigateToURL(browser(), url);
812
813 // Check that we did not download the web page.
814 EXPECT_FALSE(file_util::PathExists(file_path));
815
816 // Check state.
817 EXPECT_EQ(1, browser()->tab_count());
818 EXPECT_FALSE(IsDownloadUIVisible(browser()));
819 }
820
821 // Download a 0-size file with a content-disposition header, verify that the
822 // download tab opened and the file exists as the filename specified in the
823 // header. This also ensures we properly handle empty file downloads.
824 // The download shelf should be visible in the current tab.
IN_PROC_BROWSER_TEST_F(DownloadTest,ContentDisposition)825 IN_PROC_BROWSER_TEST_F(DownloadTest, ContentDisposition) {
826 ASSERT_TRUE(InitialSetup(false));
827 FilePath file(FILE_PATH_LITERAL("download-test3.gif"));
828 GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
829 FilePath download_file(FILE_PATH_LITERAL("download-test3-attachment.gif"));
830
831 // Download a file and wait.
832 DownloadAndWait(browser(), url, EXPECT_NO_SELECT_DIALOG);
833
834 CheckDownload(browser(), download_file, file);
835
836 // Check state.
837 EXPECT_EQ(1, browser()->tab_count());
838 EXPECT_TRUE(IsDownloadUIVisible(browser()));
839 }
840
841 #if !defined(OS_CHROMEOS) // Download shelf is not per-window on ChromeOS.
842 // Test that the download shelf is per-window by starting a download in one
843 // tab, opening a second tab, closing the shelf, going back to the first tab,
844 // and checking that the shelf is closed.
IN_PROC_BROWSER_TEST_F(DownloadTest,PerWindowShelf)845 IN_PROC_BROWSER_TEST_F(DownloadTest, PerWindowShelf) {
846 ASSERT_TRUE(InitialSetup(false));
847 FilePath file(FILE_PATH_LITERAL("download-test3.gif"));
848 GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
849 FilePath download_file(FILE_PATH_LITERAL("download-test3-attachment.gif"));
850
851 // Download a file and wait.
852 DownloadAndWait(browser(), url, EXPECT_NO_SELECT_DIALOG);
853
854 CheckDownload(browser(), download_file, file);
855
856 // Check state.
857 EXPECT_EQ(1, browser()->tab_count());
858 EXPECT_TRUE(IsDownloadUIVisible(browser()));
859
860 // Open a second tab and wait.
861 EXPECT_NE(static_cast<TabContentsWrapper*>(NULL),
862 browser()->AddSelectedTabWithURL(GURL(), PageTransition::TYPED));
863 EXPECT_EQ(2, browser()->tab_count());
864 EXPECT_TRUE(IsDownloadUIVisible(browser()));
865
866 // Hide the download shelf.
867 browser()->window()->GetDownloadShelf()->Close();
868 EXPECT_FALSE(IsDownloadUIVisible(browser()));
869
870 // Go to the first tab.
871 browser()->ActivateTabAt(0, true);
872 EXPECT_EQ(2, browser()->tab_count());
873
874 // The download shelf should not be visible.
875 EXPECT_FALSE(IsDownloadUIVisible(browser()));
876 }
877 #endif // !OS_CHROMEOS
878
879 // UnknownSize and KnownSize are tests which depend on
880 // URLRequestSlowDownloadJob to serve content in a certain way. Data will be
881 // sent in two chunks where the first chunk is 35K and the second chunk is 10K.
882 // The test will first attempt to download a file; but the server will "pause"
883 // in the middle until the server receives a second request for
884 // "download-finish". At that time, the download will finish.
885 // These tests don't currently test much due to holes in |RunSizeTest()|. See
886 // comments in that routine for details.
IN_PROC_BROWSER_TEST_F(DownloadTest,UnknownSize)887 IN_PROC_BROWSER_TEST_F(DownloadTest, UnknownSize) {
888 ASSERT_TRUE(RunSizeTest(browser(), SIZE_TEST_TYPE_UNKNOWN,
889 "32.0 KB - ", "100% - "));
890 }
891
IN_PROC_BROWSER_TEST_F(DownloadTest,KnownSize)892 IN_PROC_BROWSER_TEST_F(DownloadTest, KnownSize) {
893 ASSERT_TRUE(RunSizeTest(browser(), SIZE_TEST_TYPE_KNOWN,
894 "71% - ", "100% - "));
895 }
896
897 // Test that when downloading an item in Incognito mode, we don't crash when
898 // closing the last Incognito window (http://crbug.com/13983).
899 // Also check that the download shelf is not visible after closing the
900 // Incognito window.
IN_PROC_BROWSER_TEST_F(DownloadTest,IncognitoDownload)901 IN_PROC_BROWSER_TEST_F(DownloadTest, IncognitoDownload) {
902 ASSERT_TRUE(InitialSetup(false));
903
904 // Open an Incognito window.
905 Browser* incognito = CreateIncognitoBrowser(); // Waits.
906 ASSERT_TRUE(incognito);
907 int window_count = BrowserList::size();
908 EXPECT_EQ(2, window_count);
909
910 // Download a file in the Incognito window and wait.
911 CreateAndSetDownloadsDirectory(incognito);
912 FilePath file(FILE_PATH_LITERAL("download-test1.lib"));
913 GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
914 // Since |incognito| is a separate browser, we have to set it up explicitly.
915 incognito->profile()->GetPrefs()->SetBoolean(prefs::kPromptForDownload,
916 false);
917 DownloadAndWait(incognito, url, EXPECT_NO_SELECT_DIALOG);
918
919 // We should still have 2 windows.
920 ExpectWindowCountAfterDownload(2);
921
922 // Verify that the download shelf is showing for the Incognito window.
923 bool is_shelf_visible = IsDownloadUIVisible(incognito);
924 EXPECT_TRUE(is_shelf_visible);
925
926 // Close the Incognito window and don't crash.
927 incognito->CloseWindow();
928 #if !defined(OS_MACOSX)
929 // On Mac OS X, the UI window close is delayed until the outermost
930 // message loop runs. So it isn't possible to get a BROWSER_CLOSED
931 // notification inside of a test.
932 ui_test_utils::WaitForNotificationFrom(NotificationType::BROWSER_CLOSED,
933 Source<Browser>(incognito));
934
935 ExpectWindowCountAfterDownload(1);
936 #endif
937
938 // Verify that the regular window does not have a download shelf.
939 is_shelf_visible = IsDownloadUIVisible(browser());
940
941 #if defined(OS_CHROMEOS)
942 // On ChromeOS it's a popup rather than a download shelf, and it sticks
943 // around.
944 EXPECT_TRUE(is_shelf_visible);
945 #else
946 EXPECT_FALSE(is_shelf_visible);
947 #endif
948
949 CheckDownload(browser(), file, file);
950 }
951
952 // Navigate to a new background page, but don't download. Confirm that the
953 // download shelf is not visible and that we have two tabs.
IN_PROC_BROWSER_TEST_F(DownloadTest,DontCloseNewTab1)954 IN_PROC_BROWSER_TEST_F(DownloadTest, DontCloseNewTab1) {
955 ASSERT_TRUE(InitialSetup(false));
956 // Because it's an HTML link, it should open a web page rather than
957 // downloading.
958 FilePath file1(FILE_PATH_LITERAL("download-test2.html"));
959 GURL url(URLRequestMockHTTPJob::GetMockUrl(file1));
960
961 // Open a web page and wait.
962 ui_test_utils::NavigateToURLWithDisposition(
963 browser(),
964 url,
965 NEW_BACKGROUND_TAB,
966 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
967
968 // We should have two tabs now.
969 EXPECT_EQ(2, browser()->tab_count());
970 EXPECT_FALSE(IsDownloadUIVisible(browser()));
971 }
972
973 // Download a file in a background tab. Verify that the tab is closed
974 // automatically, and that the download shelf is visible in the current tab.
IN_PROC_BROWSER_TEST_F(DownloadTest,CloseNewTab1)975 IN_PROC_BROWSER_TEST_F(DownloadTest, CloseNewTab1) {
976 ASSERT_TRUE(InitialSetup(false));
977
978 // Download a file in a new background tab and wait. The tab is automatically
979 // closed when the download begins.
980 FilePath file(FILE_PATH_LITERAL("download-test1.lib"));
981 GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
982 DownloadAndWaitWithDisposition(
983 browser(),
984 url,
985 NEW_BACKGROUND_TAB,
986 EXPECT_NO_SELECT_DIALOG,
987 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
988
989 // When the download finishes, we should still have one tab.
990 EXPECT_TRUE(IsDownloadUIVisible(browser()));
991 EXPECT_EQ(1, browser()->tab_count());
992
993 CheckDownload(browser(), file, file);
994 }
995
996 // Open a web page in the current tab, then download a file in another tab via
997 // a Javascript call.
998 // Verify that we have 2 tabs, and the download shelf is visible in the current
999 // tab.
1000 //
1001 // The download_page1.html page contains an openNew() function that opens a
1002 // tab and then downloads download-test1.lib.
IN_PROC_BROWSER_TEST_F(DownloadTest,DontCloseNewTab2)1003 IN_PROC_BROWSER_TEST_F(DownloadTest, DontCloseNewTab2) {
1004 ASSERT_TRUE(InitialSetup(false));
1005 // Because it's an HTML link, it should open a web page rather than
1006 // downloading.
1007 FilePath file1(FILE_PATH_LITERAL("download_page1.html"));
1008 GURL url(URLRequestMockHTTPJob::GetMockUrl(file1));
1009
1010 // Open a web page and wait.
1011 ui_test_utils::NavigateToURL(browser(), url);
1012
1013 // Download a file in a new tab and wait (via Javascript).
1014 FilePath file(FILE_PATH_LITERAL("download-test1.lib"));
1015 DownloadAndWaitWithDisposition(browser(),
1016 GURL("javascript:openNew()"),
1017 CURRENT_TAB,
1018 EXPECT_NO_SELECT_DIALOG,
1019 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
1020
1021 // When the download finishes, we should have two tabs.
1022 EXPECT_TRUE(IsDownloadUIVisible(browser()));
1023 EXPECT_EQ(2, browser()->tab_count());
1024
1025 CheckDownload(browser(), file, file);
1026 }
1027
1028 // Open a web page in the current tab, open another tab via a Javascript call,
1029 // then download a file in the new tab.
1030 // Verify that we have 2 tabs, and the download shelf is visible in the current
1031 // tab.
1032 //
1033 // The download_page2.html page contains an openNew() function that opens a
1034 // tab.
IN_PROC_BROWSER_TEST_F(DownloadTest,DontCloseNewTab3)1035 IN_PROC_BROWSER_TEST_F(DownloadTest, DontCloseNewTab3) {
1036 ASSERT_TRUE(InitialSetup(false));
1037 // Because it's an HTML link, it should open a web page rather than
1038 // downloading.
1039 FilePath file1(FILE_PATH_LITERAL("download_page2.html"));
1040 GURL url1(URLRequestMockHTTPJob::GetMockUrl(file1));
1041
1042 // Open a web page and wait.
1043 ui_test_utils::NavigateToURL(browser(), url1);
1044
1045 // Open a new tab and wait.
1046 ui_test_utils::NavigateToURLWithDisposition(
1047 browser(),
1048 GURL("javascript:openNew()"),
1049 CURRENT_TAB,
1050 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
1051
1052 EXPECT_EQ(2, browser()->tab_count());
1053
1054 // Download a file and wait.
1055 FilePath file(FILE_PATH_LITERAL("download-test1.lib"));
1056 GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
1057 DownloadAndWaitWithDisposition(browser(),
1058 url,
1059 CURRENT_TAB,
1060 EXPECT_NO_SELECT_DIALOG,
1061 ui_test_utils::BROWSER_TEST_NONE);
1062
1063 // When the download finishes, we should have two tabs.
1064 EXPECT_TRUE(IsDownloadUIVisible(browser()));
1065 EXPECT_EQ(2, browser()->tab_count());
1066
1067 CheckDownload(browser(), file, file);
1068 }
1069
1070 // Open a web page in the current tab, then download a file via Javascript,
1071 // which will do so in a temporary tab.
1072 // Verify that we have 1 tab, and the download shelf is visible.
1073 //
1074 // The download_page3.html page contains an openNew() function that opens a
1075 // tab with download-test1.lib in the URL. When the URL is determined to be
1076 // a download, the tab is closed automatically.
IN_PROC_BROWSER_TEST_F(DownloadTest,CloseNewTab2)1077 IN_PROC_BROWSER_TEST_F(DownloadTest, CloseNewTab2) {
1078 ASSERT_TRUE(InitialSetup(false));
1079 // Because it's an HTML link, it should open a web page rather than
1080 // downloading.
1081 FilePath file1(FILE_PATH_LITERAL("download_page3.html"));
1082 GURL url(URLRequestMockHTTPJob::GetMockUrl(file1));
1083
1084 // Open a web page and wait.
1085 ui_test_utils::NavigateToURL(browser(), url);
1086
1087 // Download a file and wait.
1088 // The file to download is "download-test1.lib".
1089 FilePath file(FILE_PATH_LITERAL("download-test1.lib"));
1090 DownloadAndWaitWithDisposition(browser(),
1091 GURL("javascript:openNew()"),
1092 CURRENT_TAB,
1093 EXPECT_NO_SELECT_DIALOG,
1094 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
1095
1096 // When the download finishes, we should still have one tab.
1097 EXPECT_TRUE(IsDownloadUIVisible(browser()));
1098 EXPECT_EQ(1, browser()->tab_count());
1099
1100 CheckDownload(browser(), file, file);
1101 }
1102
1103 // Open a web page in the current tab, then call Javascript via a button to
1104 // download a file in a new tab, which is closed automatically when the
1105 // download begins.
1106 // Verify that we have 1 tab, and the download shelf is visible.
1107 //
1108 // The download_page4.html page contains a form with download-test1.lib as the
1109 // action.
IN_PROC_BROWSER_TEST_F(DownloadTest,CloseNewTab3)1110 IN_PROC_BROWSER_TEST_F(DownloadTest, CloseNewTab3) {
1111 ASSERT_TRUE(InitialSetup(false));
1112 // Because it's an HTML link, it should open a web page rather than
1113 // downloading.
1114 FilePath file1(FILE_PATH_LITERAL("download_page4.html"));
1115 GURL url(URLRequestMockHTTPJob::GetMockUrl(file1));
1116
1117 // Open a web page and wait.
1118 ui_test_utils::NavigateToURL(browser(), url);
1119
1120 // Download a file in a new tab and wait. The tab will automatically close
1121 // when the download begins.
1122 // The file to download is "download-test1.lib".
1123 FilePath file(FILE_PATH_LITERAL("download-test1.lib"));
1124 DownloadAndWaitWithDisposition(
1125 browser(),
1126 GURL("javascript:document.getElementById('form').submit()"),
1127 CURRENT_TAB,
1128 EXPECT_NO_SELECT_DIALOG,
1129 ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
1130
1131 // When the download finishes, we should still have one tab.
1132 EXPECT_TRUE(IsDownloadUIVisible(browser()));
1133 EXPECT_EQ(1, browser()->tab_count());
1134
1135 CheckDownload(browser(), file, file);
1136 }
1137
1138 // Download a file in a new window.
1139 // Verify that we have 2 windows, and the download shelf is not visible in the
1140 // first window, but is visible in the second window.
1141 // Close the new window.
1142 // Verify that we have 1 window, and the download shelf is not visible.
1143 //
1144 // Regression test for http://crbug.com/44454
IN_PROC_BROWSER_TEST_F(DownloadTest,NewWindow)1145 IN_PROC_BROWSER_TEST_F(DownloadTest, NewWindow) {
1146 ASSERT_TRUE(InitialSetup(false));
1147 FilePath file(FILE_PATH_LITERAL("download-test1.lib"));
1148 GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
1149 #if !defined(OS_MACOSX)
1150 // See below.
1151 Browser* first_browser = browser();
1152 #endif
1153
1154 // Download a file in a new window and wait.
1155 DownloadAndWaitWithDisposition(browser(),
1156 url,
1157 NEW_WINDOW,
1158 EXPECT_NO_SELECT_DIALOG,
1159 ui_test_utils::BROWSER_TEST_NONE);
1160
1161 // When the download finishes, the download shelf SHOULD NOT be visible in
1162 // the first window.
1163 ExpectWindowCountAfterDownload(2);
1164 EXPECT_EQ(1, browser()->tab_count());
1165 #if defined(OS_CHROMEOS)
1166 // Except on chromeos the download UI isn't window-specific.
1167 EXPECT_TRUE(IsDownloadUIVisible(browser()));
1168 #else
1169 EXPECT_FALSE(IsDownloadUIVisible(browser()));
1170 #endif
1171
1172 // The download shelf SHOULD be visible in the second window.
1173 std::set<Browser*> original_browsers;
1174 original_browsers.insert(browser());
1175 Browser* download_browser =
1176 ui_test_utils::GetBrowserNotInSet(original_browsers);
1177 ASSERT_TRUE(download_browser != NULL);
1178 EXPECT_NE(download_browser, browser());
1179 EXPECT_EQ(1, download_browser->tab_count());
1180 EXPECT_TRUE(IsDownloadUIVisible(download_browser));
1181
1182 // Close the new window.
1183 download_browser->CloseWindow();
1184 #if !defined(OS_MACOSX)
1185 // On Mac OS X, the UI window close is delayed until the outermost
1186 // message loop runs. So it isn't possible to get a BROWSER_CLOSED
1187 // notification inside of a test.
1188 ui_test_utils::WaitForNotificationFrom(NotificationType::BROWSER_CLOSED,
1189 Source<Browser>(download_browser));
1190 EXPECT_EQ(first_browser, browser());
1191 ExpectWindowCountAfterDownload(1);
1192 #endif
1193
1194 EXPECT_EQ(1, browser()->tab_count());
1195 #if defined(OS_CHROMEOS)
1196 // On ChromeOS the popup sticks around.
1197 EXPECT_TRUE(IsDownloadUIVisible(browser()));
1198 #else
1199 // Otherwise, the download shelf should not be visible in the
1200 // remaining window.
1201 EXPECT_FALSE(IsDownloadUIVisible(browser()));
1202 #endif
1203
1204 CheckDownload(browser(), file, file);
1205 }
1206
IN_PROC_BROWSER_TEST_F(DownloadTest,DownloadCancelled)1207 IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadCancelled) {
1208 ASSERT_TRUE(InitialSetup(false));
1209 EXPECT_EQ(1, browser()->tab_count());
1210
1211 // TODO(rdsmith): Fragile code warning! The code below relies on the
1212 // DownloadsObserver only finishing when the new download has reached
1213 // the state of being entered into the history and being user-visible
1214 // (that's what's required for the Remove to be valid and for the
1215 // download shelf to be visible). By the pure semantics of
1216 // DownloadsObserver, that's not guaranteed; DownloadItems are created
1217 // in the IN_PROGRESS state and made known to the DownloadManager
1218 // immediately, so any ModelChanged event on the DownloadManager after
1219 // navigation would allow the observer to return. However, the only
1220 // ModelChanged() event the code will currently fire is in
1221 // OnCreateDownloadEntryComplete, at which point the download item will
1222 // be in the state we need.
1223 // The right way to fix this is to create finer grained states on the
1224 // DownloadItem, and wait for the state that indicates the item has been
1225 // entered in the history and made visible in the UI.
1226
1227 // Create a download, wait until it's started, and confirm
1228 // we're in the expected state.
1229 scoped_ptr<DownloadsObserver> observer(CreateInProgressWaiter(browser(), 1));
1230 ui_test_utils::NavigateToURL(
1231 browser(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl));
1232 observer->WaitForFinished();
1233
1234 std::vector<DownloadItem*> downloads;
1235 browser()->profile()->GetDownloadManager()->SearchDownloads(
1236 string16(), &downloads);
1237 ASSERT_EQ(1u, downloads.size());
1238 ASSERT_EQ(DownloadItem::IN_PROGRESS, downloads[0]->state());
1239 EXPECT_TRUE(IsDownloadUIVisible(browser()));
1240
1241 // Cancel the download and wait for download system quiesce.
1242 downloads[0]->Delete(DownloadItem::DELETE_DUE_TO_USER_DISCARD);
1243 scoped_refptr<DownloadsFlushObserver> flush_observer(
1244 new DownloadsFlushObserver(browser()->profile()->GetDownloadManager()));
1245 flush_observer->WaitForFlush();
1246
1247 // Get the important info from other threads and check it.
1248 scoped_refptr<CancelTestDataCollector> info(new CancelTestDataCollector());
1249 info->WaitForDataCollected();
1250 EXPECT_EQ(0, info->rdh_pending_requests());
1251 EXPECT_EQ(0, info->dfm_pending_downloads());
1252
1253 // Using "DownloadItem::Remove" follows the discard dangerous download path,
1254 // which completely removes the browser from the shelf and closes the shelf
1255 // if it was there.
1256 #if defined(OS_CHROMEOS)
1257 // Except under ChromeOS in which case if we've brought up the file
1258 // picker panel, it stays.
1259 EXPECT_TRUE(IsDownloadUIVisible(browser()));
1260 #else
1261 EXPECT_FALSE(IsDownloadUIVisible(browser()));
1262 #endif
1263 }
1264
1265 // Confirm a download makes it into the history properly.
IN_PROC_BROWSER_TEST_F(DownloadTest,DownloadHistoryCheck)1266 IN_PROC_BROWSER_TEST_F(DownloadTest, DownloadHistoryCheck) {
1267 ASSERT_TRUE(InitialSetup(false));
1268 FilePath file(FILE_PATH_LITERAL("download-test1.lib"));
1269 GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
1270 FilePath origin_file(OriginFile(file));
1271 int64 origin_size;
1272 file_util::GetFileSize(origin_file, &origin_size);
1273
1274 // Download the file and wait. We do not expect the Select File dialog.
1275 DownloadAndWait(browser(), url, EXPECT_NO_SELECT_DIALOG);
1276
1277 // Get details of what downloads have just happened.
1278 std::vector<DownloadItem*> downloads;
1279 GetDownloads(browser(), &downloads);
1280 ASSERT_EQ(1u, downloads.size());
1281 int64 db_handle = downloads[0]->db_handle();
1282
1283 // Check state.
1284 EXPECT_EQ(1, browser()->tab_count());
1285 CheckDownload(browser(), file, file);
1286 EXPECT_TRUE(IsDownloadUIVisible(browser()));
1287
1288 // Check history results.
1289 DownloadsHistoryDataCollector history_collector(
1290 db_handle,
1291 browser()->profile()->GetDownloadManager());
1292 DownloadCreateInfo info;
1293 EXPECT_TRUE(history_collector.GetDownloadsHistoryEntry(&info)) << db_handle;
1294 EXPECT_EQ(file, info.path.BaseName());
1295 EXPECT_EQ(url, info.url());
1296 // Ignore start_time.
1297 EXPECT_EQ(origin_size, info.received_bytes);
1298 EXPECT_EQ(origin_size, info.total_bytes);
1299 EXPECT_EQ(DownloadItem::COMPLETE, info.state);
1300 }
1301