• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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