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
38namespace {
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.)
54class 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.
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
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.
92  bool select_file_dialog_seen() { return select_file_dialog_seen_; }
93
94  // Wait for whatever state was specified in the constructor.
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.
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
112  virtual void OnDownloadUpdated(DownloadItem* download) {
113    if (download->state() == download_finished_state_)
114      DownloadInFinalState(download);
115  }
116
117  virtual void OnDownloadOpened(DownloadItem* download) {}
118
119  // DownloadManager::Observer
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
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.
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
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.
231class DownloadsFlushObserver
232    : public DownloadManager::Observer,
233      public DownloadItem::Observer,
234      public base::RefCountedThreadSafe<DownloadsFlushObserver> {
235 public:
236  explicit DownloadsFlushObserver(DownloadManager* download_manager)
237      : download_manager_(download_manager),
238        waiting_for_zero_inprogress_(true) { }
239
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.
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.
253  virtual void OnDownloadUpdated(DownloadItem* download) {
254    // No change in DownloadItem set on manager.
255    CheckDownloadsInProgress(false);
256  }
257  virtual void OnDownloadOpened(DownloadItem* download) {}
258
259 protected:
260  friend class base::RefCountedThreadSafe<DownloadsFlushObserver>;
261
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.
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
315  void PingFileThread(int cycle) {
316    BrowserThread::PostTask(
317        BrowserThread::IO, FROM_HERE,
318        NewRunnableMethod(this, &DownloadsFlushObserver::PingIOThread,
319                          cycle));
320  }
321
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.
345class CancelTestDataCollector
346    : public base::RefCountedThreadSafe<CancelTestDataCollector> {
347 public:
348  CancelTestDataCollector()
349      : resource_dispatcher_host_(
350          g_browser_process->resource_dispatcher_host()),
351        rdh_pending_requests_(0),
352        dfm_pending_downloads_(0) { }
353
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
362  int rdh_pending_requests() { return rdh_pending_requests_; }
363  int dfm_pending_downloads() { return dfm_pending_downloads_; }
364
365 protected:
366  friend class base::RefCountedThreadSafe<CancelTestDataCollector>;
367
368  virtual ~CancelTestDataCollector() {}
369
370 private:
371
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
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
396class 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.
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).
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).
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.
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
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.
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.
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.
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.
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.
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
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
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.
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
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.
688class DownloadsHistoryDataCollector {
689 public:
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
708  bool GetDownloadsHistoryEntry(DownloadCreateInfo* result) {
709    DCHECK(result);
710    *result = result_;
711    return result_valid_;
712  }
713
714 private:
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.
743IN_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.
760IN_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.
786IN_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.
804IN_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.
825IN_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.
845IN_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.
887IN_PROC_BROWSER_TEST_F(DownloadTest, UnknownSize) {
888  ASSERT_TRUE(RunSizeTest(browser(), SIZE_TEST_TYPE_UNKNOWN,
889                          "32.0 KB - ", "100% - "));
890}
891
892IN_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.
901IN_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.
954IN_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.
975IN_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.
1003IN_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.
1035IN_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.
1077IN_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.
1110IN_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
1145IN_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
1207IN_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.
1266IN_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