Home | History | Annotate | Download | only in download
      1 // Copyright (c) 2012 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/bind.h"
      6 #include "base/bind_helpers.h"
      7 #include "base/command_line.h"
      8 #include "base/file_util.h"
      9 #include "base/files/file_path.h"
     10 #include "base/files/scoped_temp_dir.h"
     11 #include "base/path_service.h"
     12 #include "base/prefs/pref_member.h"
     13 #include "base/prefs/pref_service.h"
     14 #include "base/test/test_file_util.h"
     15 #include "chrome/app/chrome_command_ids.h"
     16 #include "chrome/browser/download/chrome_download_manager_delegate.h"
     17 #include "chrome/browser/download/download_history.h"
     18 #include "chrome/browser/download/download_prefs.h"
     19 #include "chrome/browser/download/download_service.h"
     20 #include "chrome/browser/download/download_service_factory.h"
     21 #include "chrome/browser/download/save_package_file_picker.h"
     22 #include "chrome/browser/history/download_row.h"
     23 #include "chrome/browser/net/url_request_mock_util.h"
     24 #include "chrome/browser/profiles/profile.h"
     25 #include "chrome/browser/ui/browser.h"
     26 #include "chrome/browser/ui/browser_commands.h"
     27 #include "chrome/browser/ui/browser_window.h"
     28 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     29 #include "chrome/common/chrome_paths.h"
     30 #include "chrome/common/chrome_switches.h"
     31 #include "chrome/common/pref_names.h"
     32 #include "chrome/common/url_constants.h"
     33 #include "chrome/test/base/in_process_browser_test.h"
     34 #include "chrome/test/base/ui_test_utils.h"
     35 #include "content/public/browser/download_item.h"
     36 #include "content/public/browser/download_manager.h"
     37 #include "content/public/browser/notification_service.h"
     38 #include "content/public/browser/notification_types.h"
     39 #include "content/public/browser/web_contents.h"
     40 #include "content/public/test/test_utils.h"
     41 #include "content/test/net/url_request_mock_http_job.h"
     42 #include "testing/gtest/include/gtest/gtest.h"
     43 
     44 using content::BrowserContext;
     45 using content::BrowserThread;
     46 using content::DownloadItem;
     47 using content::DownloadManager;
     48 using content::URLRequestMockHTTPJob;
     49 using content::WebContents;
     50 
     51 namespace {
     52 
     53 // Waits for an item record in the downloads database to match |filter|. See
     54 // DownloadStoredProperly() below for an example filter.
     55 class DownloadPersistedObserver : public DownloadHistory::Observer {
     56  public:
     57   typedef base::Callback<bool(
     58       DownloadItem* item,
     59       const history::DownloadRow&)> PersistedFilter;
     60 
     61   DownloadPersistedObserver(Profile* profile, const PersistedFilter& filter)
     62     : profile_(profile),
     63       filter_(filter),
     64       waiting_(false),
     65       persisted_(false) {
     66     DownloadServiceFactory::GetForBrowserContext(profile_)->
     67       GetDownloadHistory()->AddObserver(this);
     68   }
     69 
     70   virtual ~DownloadPersistedObserver() {
     71     DownloadService* service = DownloadServiceFactory::GetForBrowserContext(
     72         profile_);
     73     if (service && service->GetDownloadHistory())
     74       service->GetDownloadHistory()->RemoveObserver(this);
     75   }
     76 
     77   bool WaitForPersisted() {
     78     if (persisted_)
     79       return true;
     80     waiting_ = true;
     81     content::RunMessageLoop();
     82     waiting_ = false;
     83     return persisted_;
     84   }
     85 
     86   virtual void OnDownloadStored(DownloadItem* item,
     87                                 const history::DownloadRow& info) OVERRIDE {
     88     persisted_ = persisted_ || filter_.Run(item, info);
     89     if (persisted_ && waiting_)
     90       base::MessageLoopForUI::current()->Quit();
     91   }
     92 
     93  private:
     94   Profile* profile_;
     95   DownloadItem* item_;
     96   PersistedFilter filter_;
     97   bool waiting_;
     98   bool persisted_;
     99 
    100   DISALLOW_COPY_AND_ASSIGN(DownloadPersistedObserver);
    101 };
    102 
    103 // Waits for an item record to be removed from the downloads database.
    104 class DownloadRemovedObserver : public DownloadPersistedObserver {
    105  public:
    106   DownloadRemovedObserver(Profile* profile, int32 download_id)
    107       : DownloadPersistedObserver(profile, PersistedFilter()),
    108         removed_(false),
    109         waiting_(false),
    110         download_id_(download_id) {
    111   }
    112   virtual ~DownloadRemovedObserver() {}
    113 
    114   bool WaitForRemoved() {
    115     if (removed_)
    116       return true;
    117     waiting_ = true;
    118     content::RunMessageLoop();
    119     waiting_ = false;
    120     return removed_;
    121   }
    122 
    123   virtual void OnDownloadStored(DownloadItem* item,
    124                                 const history::DownloadRow& info) OVERRIDE {
    125   }
    126 
    127   virtual void OnDownloadsRemoved(const DownloadHistory::IdSet& ids) OVERRIDE {
    128     removed_ = ids.find(download_id_) != ids.end();
    129     if (removed_ && waiting_)
    130       base::MessageLoopForUI::current()->Quit();
    131   }
    132 
    133  private:
    134   bool removed_;
    135   bool waiting_;
    136   int32 download_id_;
    137 
    138   DISALLOW_COPY_AND_ASSIGN(DownloadRemovedObserver);
    139 };
    140 
    141 bool DownloadStoredProperly(
    142     const GURL& expected_url,
    143     const base::FilePath& expected_path,
    144     int64 num_files,
    145     DownloadItem::DownloadState expected_state,
    146     DownloadItem* item,
    147     const history::DownloadRow& info) {
    148   // This function may be called multiple times for a given test. Returning
    149   // false doesn't necessarily mean that the test has failed or will fail, it
    150   // might just mean that the test hasn't passed yet.
    151   if (info.target_path != expected_path) {
    152     VLOG(20) << __FUNCTION__ << " " << info.target_path.value()
    153              << " != " << expected_path.value();
    154     return false;
    155   }
    156   if (info.url_chain.size() != 1u) {
    157     VLOG(20) << __FUNCTION__ << " " << info.url_chain.size()
    158              << " != 1";
    159     return false;
    160   }
    161   if (info.url_chain[0] != expected_url) {
    162     VLOG(20) << __FUNCTION__ << " " << info.url_chain[0].spec()
    163              << " != " << expected_url.spec();
    164     return false;
    165   }
    166   if ((num_files >= 0) && (info.received_bytes != num_files)) {
    167     VLOG(20) << __FUNCTION__ << " " << num_files
    168              << " != " << info.received_bytes;
    169     return false;
    170   }
    171   if (info.state != expected_state) {
    172     VLOG(20) << __FUNCTION__ << " " << info.state
    173              << " != " << expected_state;
    174     return false;
    175   }
    176   return true;
    177 }
    178 
    179 const base::FilePath::CharType kTestDir[] = FILE_PATH_LITERAL("save_page");
    180 
    181 static const char kAppendedExtension[] =
    182 #if defined(OS_WIN)
    183     ".htm";
    184 #else
    185     ".html";
    186 #endif
    187 
    188 // Loosely based on logic in DownloadTestObserver.
    189 class DownloadItemCreatedObserver : public DownloadManager::Observer {
    190  public:
    191   explicit DownloadItemCreatedObserver(DownloadManager* manager)
    192       : waiting_(false), manager_(manager) {
    193     manager->AddObserver(this);
    194   }
    195 
    196   virtual ~DownloadItemCreatedObserver() {
    197     if (manager_)
    198       manager_->RemoveObserver(this);
    199   }
    200 
    201   // Wait for the first download item created after object creation.
    202   // Note that this class provides no protection against the download
    203   // being destroyed between creation and return of WaitForNewDownloadItem();
    204   // the caller must guarantee that in some other fashion.
    205   void WaitForDownloadItem(std::vector<DownloadItem*>* items_seen) {
    206     if (!manager_) {
    207       // The manager went away before we were asked to wait; return
    208       // what we have, even if it's null.
    209       *items_seen = items_seen_;
    210       return;
    211     }
    212 
    213     if (items_seen_.empty()) {
    214       waiting_ = true;
    215       content::RunMessageLoop();
    216       waiting_ = false;
    217     }
    218 
    219     *items_seen = items_seen_;
    220     return;
    221   }
    222 
    223  private:
    224   // DownloadManager::Observer
    225   virtual void OnDownloadCreated(
    226       DownloadManager* manager, DownloadItem* item) OVERRIDE {
    227     DCHECK_EQ(manager, manager_);
    228     items_seen_.push_back(item);
    229 
    230     if (waiting_)
    231       base::MessageLoopForUI::current()->Quit();
    232   }
    233 
    234   virtual void ManagerGoingDown(DownloadManager* manager) OVERRIDE {
    235     manager_->RemoveObserver(this);
    236     manager_ = NULL;
    237     if (waiting_)
    238       base::MessageLoopForUI::current()->Quit();
    239   }
    240 
    241   bool waiting_;
    242   DownloadManager* manager_;
    243   std::vector<DownloadItem*> items_seen_;
    244 
    245   DISALLOW_COPY_AND_ASSIGN(DownloadItemCreatedObserver);
    246 };
    247 
    248 class SavePackageFinishedObserver : public content::DownloadManager::Observer {
    249  public:
    250   SavePackageFinishedObserver(content::DownloadManager* manager,
    251                               const base::Closure& callback)
    252       : download_manager_(manager),
    253         callback_(callback) {
    254     download_manager_->AddObserver(this);
    255   }
    256 
    257   virtual ~SavePackageFinishedObserver() {
    258     if (download_manager_)
    259       download_manager_->RemoveObserver(this);
    260   }
    261 
    262   // DownloadManager::Observer:
    263   virtual void OnSavePackageSuccessfullyFinished(
    264       content::DownloadManager* manager, content::DownloadItem* item) OVERRIDE {
    265     callback_.Run();
    266   }
    267   virtual void ManagerGoingDown(content::DownloadManager* manager) OVERRIDE {
    268     download_manager_->RemoveObserver(this);
    269     download_manager_ = NULL;
    270   }
    271 
    272  private:
    273   content::DownloadManager* download_manager_;
    274   base::Closure callback_;
    275 
    276   DISALLOW_COPY_AND_ASSIGN(SavePackageFinishedObserver);
    277 };
    278 
    279 class SavePageBrowserTest : public InProcessBrowserTest {
    280  public:
    281   SavePageBrowserTest() {}
    282   virtual ~SavePageBrowserTest();
    283 
    284  protected:
    285   virtual void SetUp() OVERRIDE {
    286     ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir_));
    287     ASSERT_TRUE(save_dir_.CreateUniqueTempDir());
    288     InProcessBrowserTest::SetUp();
    289   }
    290 
    291   virtual void SetUpOnMainThread() OVERRIDE {
    292     browser()->profile()->GetPrefs()->SetFilePath(
    293         prefs::kDownloadDefaultDirectory, save_dir_.path());
    294     browser()->profile()->GetPrefs()->SetFilePath(
    295         prefs::kSaveFileDefaultDirectory, save_dir_.path());
    296     BrowserThread::PostTask(
    297         BrowserThread::IO, FROM_HERE,
    298         base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
    299   }
    300 
    301   GURL NavigateToMockURL(const std::string& prefix) {
    302     GURL url = URLRequestMockHTTPJob::GetMockUrl(
    303         base::FilePath(kTestDir).AppendASCII(prefix + ".htm"));
    304     ui_test_utils::NavigateToURL(browser(), url);
    305     return url;
    306   }
    307 
    308   // Returns full paths of destination file and directory.
    309   void GetDestinationPaths(const std::string& prefix,
    310                 base::FilePath* full_file_name,
    311                 base::FilePath* dir) {
    312     *full_file_name = save_dir_.path().AppendASCII(prefix + ".htm");
    313     *dir = save_dir_.path().AppendASCII(prefix + "_files");
    314   }
    315 
    316   WebContents* GetCurrentTab(Browser* browser) const {
    317     WebContents* current_tab =
    318         browser->tab_strip_model()->GetActiveWebContents();
    319     EXPECT_TRUE(current_tab);
    320     return current_tab;
    321   }
    322 
    323   // Returns true if and when there was a single download created, and its url
    324   // is |expected_url|.
    325   bool VerifySavePackageExpectations(
    326       Browser* browser,
    327       const GURL& expected_url) const {
    328     // Generally, there should only be one download item created
    329     // in all of these tests.  If it's already here, grab it; if not,
    330     // wait for it to show up.
    331     std::vector<DownloadItem*> items;
    332     DownloadManager* manager(
    333         BrowserContext::GetDownloadManager(browser->profile()));
    334     manager->GetAllDownloads(&items);
    335     if (items.size() == 0u) {
    336       DownloadItemCreatedObserver(manager).WaitForDownloadItem(&items);
    337     }
    338 
    339     EXPECT_EQ(1u, items.size());
    340     if (1u != items.size())
    341       return false;
    342     DownloadItem* download_item(items[0]);
    343 
    344     return (expected_url == download_item->GetOriginalUrl());
    345   }
    346 
    347   // Note on synchronization:
    348   //
    349   // For each Save Page As operation, we create a corresponding shell
    350   // DownloadItem to display progress to the user.  That DownloadItem goes
    351   // through its own state transitions, including being persisted out to the
    352   // history database, and the download shelf is not shown until after the
    353   // persistence occurs.  Save Package completion (and marking the DownloadItem
    354   // as completed) occurs asynchronously from persistence.  Thus if we want to
    355   // examine either UI state or DB state, we need to wait until both the save
    356   // package operation is complete and the relevant download item has been
    357   // persisted.
    358 
    359   DownloadManager* GetDownloadManager() const {
    360     DownloadManager* download_manager =
    361         BrowserContext::GetDownloadManager(browser()->profile());
    362     EXPECT_TRUE(download_manager);
    363     return download_manager;
    364   }
    365 
    366   // Path to directory containing test data.
    367   base::FilePath test_dir_;
    368 
    369   // Temporary directory we will save pages to.
    370   base::ScopedTempDir save_dir_;
    371 
    372  private:
    373   DISALLOW_COPY_AND_ASSIGN(SavePageBrowserTest);
    374 };
    375 
    376 SavePageBrowserTest::~SavePageBrowserTest() {
    377 }
    378 
    379 // Disabled on Windows due to flakiness. http://crbug.com/162323
    380 #if defined(OS_WIN)
    381 #define MAYBE_SaveHTMLOnly DISABLED_SaveHTMLOnly
    382 #else
    383 #define MAYBE_SaveHTMLOnly SaveHTMLOnly
    384 #endif
    385 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_SaveHTMLOnly) {
    386   GURL url = NavigateToMockURL("a");
    387 
    388   base::FilePath full_file_name, dir;
    389   GetDestinationPaths("a", &full_file_name, &dir);
    390   DownloadPersistedObserver persisted(browser()->profile(), base::Bind(
    391       &DownloadStoredProperly, url, full_file_name, 1,
    392       DownloadItem::COMPLETE));
    393   scoped_refptr<content::MessageLoopRunner> loop_runner(
    394       new content::MessageLoopRunner);
    395   SavePackageFinishedObserver observer(
    396       content::BrowserContext::GetDownloadManager(browser()->profile()),
    397       loop_runner->QuitClosure());
    398   ASSERT_TRUE(GetCurrentTab(browser())->SavePage(full_file_name, dir,
    399                                         content::SAVE_PAGE_TYPE_AS_ONLY_HTML));
    400   loop_runner->Run();
    401   ASSERT_TRUE(VerifySavePackageExpectations(browser(), url));
    402   persisted.WaitForPersisted();
    403   EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
    404   EXPECT_TRUE(base::PathExists(full_file_name));
    405   EXPECT_FALSE(base::PathExists(dir));
    406   EXPECT_TRUE(base::ContentsEqual(test_dir_.Append(base::FilePath(
    407       kTestDir)).Append(FILE_PATH_LITERAL("a.htm")), full_file_name));
    408 }
    409 
    410 // http://crbug.com/162323
    411 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, DISABLED_SaveHTMLOnlyCancel) {
    412   GURL url = NavigateToMockURL("a");
    413   DownloadManager* manager(GetDownloadManager());
    414   std::vector<DownloadItem*> downloads;
    415   manager->GetAllDownloads(&downloads);
    416   ASSERT_EQ(0u, downloads.size());
    417 
    418   base::FilePath full_file_name, dir;
    419   GetDestinationPaths("a", &full_file_name, &dir);
    420   DownloadItemCreatedObserver creation_observer(manager);
    421   DownloadPersistedObserver persisted(browser()->profile(), base::Bind(
    422       &DownloadStoredProperly, url, full_file_name, -1,
    423       DownloadItem::CANCELLED));
    424   // -1 to disable number of files check; we don't update after cancel, and
    425   // we don't know when the single file completed in relationship to
    426   // the cancel.
    427 
    428   ASSERT_TRUE(GetCurrentTab(browser())->SavePage(full_file_name, dir,
    429                                         content::SAVE_PAGE_TYPE_AS_ONLY_HTML));
    430   std::vector<DownloadItem*> items;
    431   creation_observer.WaitForDownloadItem(&items);
    432   ASSERT_EQ(1UL, items.size());
    433   ASSERT_EQ(url.spec(), items[0]->GetOriginalUrl().spec());
    434   items[0]->Cancel(true);
    435   // TODO(rdsmith): Fix DII::Cancel() to actually cancel the save package.
    436   // Currently it's ignored.
    437 
    438   persisted.WaitForPersisted();
    439 
    440   EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
    441 
    442   // TODO(benjhayden): Figure out how to safely wait for SavePackage's finished
    443   // notification, then expect the contents of the downloaded file.
    444 }
    445 
    446 class DelayingDownloadManagerDelegate : public ChromeDownloadManagerDelegate {
    447  public:
    448   explicit DelayingDownloadManagerDelegate(Profile* profile)
    449     : ChromeDownloadManagerDelegate(profile) {
    450   }
    451   virtual ~DelayingDownloadManagerDelegate() {}
    452 
    453   virtual bool ShouldCompleteDownload(
    454       content::DownloadItem* item,
    455       const base::Closure& user_complete_callback) OVERRIDE {
    456     return false;
    457   }
    458 
    459  private:
    460   DISALLOW_COPY_AND_ASSIGN(DelayingDownloadManagerDelegate);
    461 };
    462 
    463 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SaveHTMLOnlyTabDestroy) {
    464   GURL url = NavigateToMockURL("a");
    465   scoped_ptr<DelayingDownloadManagerDelegate> delaying_delegate(
    466       new DelayingDownloadManagerDelegate(browser()->profile()));
    467   delaying_delegate->GetDownloadIdReceiverCallback().Run(
    468       content::DownloadItem::kInvalidId + 1);
    469   DownloadServiceFactory::GetForBrowserContext(browser()->profile())->
    470       SetDownloadManagerDelegateForTesting(
    471           delaying_delegate.PassAs<ChromeDownloadManagerDelegate>());
    472   DownloadManager* manager(GetDownloadManager());
    473   std::vector<DownloadItem*> downloads;
    474   manager->GetAllDownloads(&downloads);
    475   ASSERT_EQ(0u, downloads.size());
    476 
    477   base::FilePath full_file_name, dir;
    478   GetDestinationPaths("a", &full_file_name, &dir);
    479   DownloadItemCreatedObserver creation_observer(manager);
    480   ASSERT_TRUE(GetCurrentTab(browser())->SavePage(full_file_name, dir,
    481                                         content::SAVE_PAGE_TYPE_AS_ONLY_HTML));
    482   std::vector<DownloadItem*> items;
    483   creation_observer.WaitForDownloadItem(&items);
    484   ASSERT_TRUE(items.size() == 1);
    485 
    486   // Close the tab; does this cancel the download?
    487   GetCurrentTab(browser())->Close();
    488   EXPECT_EQ(DownloadItem::CANCELLED, items[0]->GetState());
    489 
    490   EXPECT_FALSE(base::PathExists(full_file_name));
    491   EXPECT_FALSE(base::PathExists(dir));
    492 }
    493 
    494 // Disabled on Windows due to flakiness. http://crbug.com/162323
    495 #if defined(OS_WIN)
    496 #define MAYBE_SaveViewSourceHTMLOnly DISABLED_SaveViewSourceHTMLOnly
    497 #else
    498 #define MAYBE_SaveViewSourceHTMLOnly SaveViewSourceHTMLOnly
    499 #endif
    500 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_SaveViewSourceHTMLOnly) {
    501   base::FilePath file_name(FILE_PATH_LITERAL("a.htm"));
    502   GURL view_source_url = URLRequestMockHTTPJob::GetMockViewSourceUrl(
    503       base::FilePath(kTestDir).Append(file_name));
    504   GURL actual_page_url = URLRequestMockHTTPJob::GetMockUrl(
    505       base::FilePath(kTestDir).Append(file_name));
    506   ui_test_utils::NavigateToURL(browser(), view_source_url);
    507 
    508   base::FilePath full_file_name, dir;
    509   GetDestinationPaths("a", &full_file_name, &dir);
    510   DownloadPersistedObserver persisted(browser()->profile(), base::Bind(
    511       &DownloadStoredProperly, actual_page_url, full_file_name, 1,
    512       DownloadItem::COMPLETE));
    513   scoped_refptr<content::MessageLoopRunner> loop_runner(
    514       new content::MessageLoopRunner);
    515   SavePackageFinishedObserver observer(
    516       content::BrowserContext::GetDownloadManager(browser()->profile()),
    517       loop_runner->QuitClosure());
    518   ASSERT_TRUE(GetCurrentTab(browser())->SavePage(full_file_name, dir,
    519                                         content::SAVE_PAGE_TYPE_AS_ONLY_HTML));
    520   loop_runner->Run();
    521   ASSERT_TRUE(VerifySavePackageExpectations(browser(), actual_page_url));
    522   persisted.WaitForPersisted();
    523 
    524   EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
    525 
    526   EXPECT_TRUE(base::PathExists(full_file_name));
    527   EXPECT_FALSE(base::PathExists(dir));
    528   EXPECT_TRUE(base::ContentsEqual(
    529       test_dir_.Append(base::FilePath(kTestDir)).Append(file_name),
    530       full_file_name));
    531 }
    532 
    533 // Disabled on Windows due to flakiness. http://crbug.com/162323
    534 #if defined(OS_WIN)
    535 #define MAYBE_SaveCompleteHTML DISABLED_SaveCompleteHTML
    536 #else
    537 #define MAYBE_SaveCompleteHTML SaveCompleteHTML
    538 #endif
    539 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_SaveCompleteHTML) {
    540   GURL url = NavigateToMockURL("b");
    541 
    542   base::FilePath full_file_name, dir;
    543   GetDestinationPaths("b", &full_file_name, &dir);
    544   DownloadPersistedObserver persisted(browser()->profile(), base::Bind(
    545       &DownloadStoredProperly, url, full_file_name, 3,
    546       DownloadItem::COMPLETE));
    547   scoped_refptr<content::MessageLoopRunner> loop_runner(
    548       new content::MessageLoopRunner);
    549   SavePackageFinishedObserver observer(
    550       content::BrowserContext::GetDownloadManager(browser()->profile()),
    551       loop_runner->QuitClosure());
    552   ASSERT_TRUE(GetCurrentTab(browser())->SavePage(
    553       full_file_name, dir, content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML));
    554   loop_runner->Run();
    555   ASSERT_TRUE(VerifySavePackageExpectations(browser(), url));
    556   persisted.WaitForPersisted();
    557 
    558   EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
    559 
    560   EXPECT_TRUE(base::PathExists(full_file_name));
    561   EXPECT_TRUE(base::PathExists(dir));
    562   EXPECT_TRUE(base::TextContentsEqual(
    563       test_dir_.Append(base::FilePath(kTestDir)).AppendASCII("b.saved1.htm"),
    564       full_file_name));
    565   EXPECT_TRUE(base::ContentsEqual(
    566       test_dir_.Append(base::FilePath(kTestDir)).AppendASCII("1.png"),
    567       dir.AppendASCII("1.png")));
    568   EXPECT_TRUE(base::ContentsEqual(
    569       test_dir_.Append(base::FilePath(kTestDir)).AppendASCII("1.css"),
    570       dir.AppendASCII("1.css")));
    571 }
    572 
    573 // Invoke a save page during the initial navigation.
    574 // (Regression test for http://crbug.com/156538).
    575 // Disabled on Windows due to flakiness. http://crbug.com/162323
    576 #if defined(OS_WIN)
    577 #define MAYBE_SaveDuringInitialNavigationIncognito DISABLED_SaveDuringInitialNavigationIncognito
    578 #else
    579 #define MAYBE_SaveDuringInitialNavigationIncognito SaveDuringInitialNavigationIncognito
    580 #endif
    581 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest,
    582                        MAYBE_SaveDuringInitialNavigationIncognito) {
    583   // Open an Incognito window.
    584   Browser* incognito = CreateIncognitoBrowser();  // Waits.
    585   ASSERT_TRUE(incognito);
    586 
    587   // Create a download item creation waiter on that window.
    588   DownloadItemCreatedObserver creation_observer(
    589       BrowserContext::GetDownloadManager(incognito->profile()));
    590 
    591   // Navigate, unblocking with new tab.
    592   GURL url = URLRequestMockHTTPJob::GetMockUrl(
    593       base::FilePath(kTestDir).AppendASCII("b.htm"));
    594   NavigateToURLWithDisposition(incognito, url, NEW_FOREGROUND_TAB,
    595                                ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
    596 
    597   // Save the page before completion.
    598   base::FilePath full_file_name, dir;
    599   GetDestinationPaths("b", &full_file_name, &dir);
    600   scoped_refptr<content::MessageLoopRunner> loop_runner(
    601       new content::MessageLoopRunner);
    602   SavePackageFinishedObserver observer(
    603       content::BrowserContext::GetDownloadManager(incognito->profile()),
    604       loop_runner->QuitClosure());
    605   ASSERT_TRUE(GetCurrentTab(incognito)->SavePage(
    606       full_file_name, dir, content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML));
    607 
    608   loop_runner->Run();
    609   ASSERT_TRUE(VerifySavePackageExpectations(incognito, url));
    610 
    611   // Confirm download shelf is visible.
    612   EXPECT_TRUE(incognito->window()->IsDownloadShelfVisible());
    613 
    614   // We can't check more than this because SavePackage is racing with
    615   // the page load.  If the page load won the race, then SavePackage
    616   // might have completed. If the page load lost the race, then
    617   // SavePackage will cancel because there aren't any resources to
    618   // save.
    619 }
    620 
    621 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, NoSave) {
    622   ui_test_utils::NavigateToURL(browser(), GURL(content::kAboutBlankURL));
    623   EXPECT_FALSE(chrome::CanSavePage(browser()));
    624 }
    625 
    626 // Disabled on Windows due to flakiness. http://crbug.com/162323
    627 #if defined(OS_WIN)
    628 #define MAYBE_FileNameFromPageTitle DISABLED_FileNameFromPageTitle
    629 #else
    630 #define MAYBE_FileNameFromPageTitle FileNameFromPageTitle
    631 #endif
    632 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_FileNameFromPageTitle) {
    633   GURL url = NavigateToMockURL("b");
    634 
    635   base::FilePath full_file_name = save_dir_.path().AppendASCII(
    636       std::string("Test page for saving page feature") + kAppendedExtension);
    637   base::FilePath dir = save_dir_.path().AppendASCII(
    638       "Test page for saving page feature_files");
    639   DownloadPersistedObserver persisted(browser()->profile(), base::Bind(
    640       &DownloadStoredProperly, url, full_file_name, 3,
    641       DownloadItem::COMPLETE));
    642   scoped_refptr<content::MessageLoopRunner> loop_runner(
    643       new content::MessageLoopRunner);
    644   SavePackageFinishedObserver observer(
    645       content::BrowserContext::GetDownloadManager(browser()->profile()),
    646       loop_runner->QuitClosure());
    647   ASSERT_TRUE(GetCurrentTab(browser())->SavePage(
    648       full_file_name, dir, content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML));
    649 
    650   loop_runner->Run();
    651   ASSERT_TRUE(VerifySavePackageExpectations(browser(), url));
    652   persisted.WaitForPersisted();
    653 
    654   EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
    655 
    656   EXPECT_TRUE(base::PathExists(full_file_name));
    657   EXPECT_TRUE(base::PathExists(dir));
    658   EXPECT_TRUE(base::TextContentsEqual(
    659       test_dir_.Append(base::FilePath(kTestDir)).AppendASCII("b.saved2.htm"),
    660       full_file_name));
    661   EXPECT_TRUE(base::ContentsEqual(
    662       test_dir_.Append(base::FilePath(kTestDir)).AppendASCII("1.png"),
    663       dir.AppendASCII("1.png")));
    664   EXPECT_TRUE(base::ContentsEqual(
    665       test_dir_.Append(base::FilePath(kTestDir)).AppendASCII("1.css"),
    666       dir.AppendASCII("1.css")));
    667 }
    668 
    669 // Disabled on Windows due to flakiness. http://crbug.com/162323
    670 #if defined(OS_WIN)
    671 #define MAYBE_RemoveFromList DISABLED_RemoveFromList
    672 #else
    673 #define MAYBE_RemoveFromList RemoveFromList
    674 #endif
    675 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, MAYBE_RemoveFromList) {
    676   GURL url = NavigateToMockURL("a");
    677 
    678   base::FilePath full_file_name, dir;
    679   GetDestinationPaths("a", &full_file_name, &dir);
    680   DownloadPersistedObserver persisted(browser()->profile(), base::Bind(
    681       &DownloadStoredProperly, url, full_file_name, 1,
    682       DownloadItem::COMPLETE));
    683   scoped_refptr<content::MessageLoopRunner> loop_runner(
    684       new content::MessageLoopRunner);
    685   SavePackageFinishedObserver observer(
    686       content::BrowserContext::GetDownloadManager(browser()->profile()),
    687       loop_runner->QuitClosure());
    688   ASSERT_TRUE(GetCurrentTab(browser())->SavePage(full_file_name, dir,
    689                                         content::SAVE_PAGE_TYPE_AS_ONLY_HTML));
    690 
    691   loop_runner->Run();
    692   ASSERT_TRUE(VerifySavePackageExpectations(browser(), url));
    693   persisted.WaitForPersisted();
    694 
    695   EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
    696 
    697   DownloadManager* manager(GetDownloadManager());
    698   std::vector<DownloadItem*> downloads;
    699   manager->GetAllDownloads(&downloads);
    700   ASSERT_EQ(1UL, downloads.size());
    701   DownloadRemovedObserver removed(browser()->profile(), downloads[0]->GetId());
    702 
    703   EXPECT_EQ(manager->RemoveAllDownloads(), 1);
    704 
    705   removed.WaitForRemoved();
    706 
    707   EXPECT_TRUE(base::PathExists(full_file_name));
    708   EXPECT_FALSE(base::PathExists(dir));
    709   EXPECT_TRUE(base::ContentsEqual(test_dir_.Append(base::FilePath(
    710       kTestDir)).Append(FILE_PATH_LITERAL("a.htm")), full_file_name));
    711 }
    712 
    713 // This tests that a webpage with the title "test.exe" is saved as
    714 // "test.exe.htm".
    715 // We probably don't care to handle this on Linux or Mac.
    716 #if defined(OS_WIN)
    717 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, CleanFilenameFromPageTitle) {
    718   const base::FilePath file_name(FILE_PATH_LITERAL("c.htm"));
    719   base::FilePath download_dir =
    720       DownloadPrefs::FromDownloadManager(GetDownloadManager())->
    721           DownloadPath();
    722   base::FilePath full_file_name =
    723       download_dir.AppendASCII(std::string("test.exe") + kAppendedExtension);
    724   base::FilePath dir = download_dir.AppendASCII("test.exe_files");
    725 
    726   EXPECT_FALSE(base::PathExists(full_file_name));
    727   GURL url = URLRequestMockHTTPJob::GetMockUrl(
    728       base::FilePath(kTestDir).Append(file_name));
    729   ui_test_utils::NavigateToURL(browser(), url);
    730 
    731   SavePackageFilePicker::SetShouldPromptUser(false);
    732   scoped_refptr<content::MessageLoopRunner> loop_runner(
    733       new content::MessageLoopRunner);
    734   SavePackageFinishedObserver observer(
    735       content::BrowserContext::GetDownloadManager(browser()->profile()),
    736       loop_runner->QuitClosure());
    737   chrome::SavePage(browser());
    738   loop_runner->Run();
    739 
    740   EXPECT_TRUE(base::PathExists(full_file_name));
    741 
    742   EXPECT_TRUE(file_util::DieFileDie(full_file_name, false));
    743   EXPECT_TRUE(file_util::DieFileDie(dir, true));
    744 }
    745 #endif
    746 
    747 class SavePageAsMHTMLBrowserTest : public SavePageBrowserTest {
    748  public:
    749   SavePageAsMHTMLBrowserTest() {}
    750   virtual ~SavePageAsMHTMLBrowserTest();
    751   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    752     command_line->AppendSwitch(switches::kSavePageAsMHTML);
    753   }
    754 
    755  private:
    756   DISALLOW_COPY_AND_ASSIGN(SavePageAsMHTMLBrowserTest);
    757 };
    758 
    759 SavePageAsMHTMLBrowserTest::~SavePageAsMHTMLBrowserTest() {
    760 }
    761 
    762 IN_PROC_BROWSER_TEST_F(SavePageAsMHTMLBrowserTest, SavePageAsMHTML) {
    763   static const int64 kFileSizeMin = 2758;
    764   GURL url = NavigateToMockURL("b");
    765   base::FilePath download_dir = DownloadPrefs::FromDownloadManager(
    766       GetDownloadManager())->DownloadPath();
    767   base::FilePath full_file_name = download_dir.AppendASCII(std::string(
    768       "Test page for saving page feature.mhtml"));
    769   SavePackageFilePicker::SetShouldPromptUser(false);
    770   DownloadPersistedObserver persisted(browser()->profile(), base::Bind(
    771       &DownloadStoredProperly, url, full_file_name, -1,
    772       DownloadItem::COMPLETE));
    773   scoped_refptr<content::MessageLoopRunner> loop_runner(
    774       new content::MessageLoopRunner);
    775   SavePackageFinishedObserver observer(
    776       content::BrowserContext::GetDownloadManager(browser()->profile()),
    777       loop_runner->QuitClosure());
    778   chrome::SavePage(browser());
    779   loop_runner->Run();
    780   ASSERT_TRUE(VerifySavePackageExpectations(browser(), url));
    781   persisted.WaitForPersisted();
    782 
    783   ASSERT_TRUE(base::PathExists(full_file_name));
    784   int64 actual_file_size = -1;
    785   EXPECT_TRUE(base::GetFileSize(full_file_name, &actual_file_size));
    786   EXPECT_LE(kFileSizeMin, actual_file_size);
    787 }
    788 
    789 IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SavePageBrowserTest_NonMHTML) {
    790   SavePackageFilePicker::SetShouldPromptUser(false);
    791   GURL url("data:text/plain,foo");
    792   ui_test_utils::NavigateToURL(browser(), url);
    793   scoped_refptr<content::MessageLoopRunner> loop_runner(
    794       new content::MessageLoopRunner);
    795   SavePackageFinishedObserver observer(
    796       content::BrowserContext::GetDownloadManager(browser()->profile()),
    797       loop_runner->QuitClosure());
    798   chrome::SavePage(browser());
    799   loop_runner->Run();
    800   base::FilePath download_dir = DownloadPrefs::FromDownloadManager(
    801       GetDownloadManager())->DownloadPath();
    802   base::FilePath filename = download_dir.AppendASCII("dataurl.txt");
    803   ASSERT_TRUE(base::PathExists(filename));
    804   std::string contents;
    805   EXPECT_TRUE(base::ReadFileToString(filename, &contents));
    806   EXPECT_EQ("foo", contents);
    807 }
    808 
    809 }  // namespace
    810 
    811