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 // This file contains download browser tests that are known to be runnable
      6 // in a pure content context.  Over time tests should be migrated here.
      7 
      8 #include "base/command_line.h"
      9 #include "base/files/file_path.h"
     10 #include "base/files/file_util.h"
     11 #include "base/files/scoped_temp_dir.h"
     12 #include "base/memory/ref_counted.h"
     13 #include "base/strings/stringprintf.h"
     14 #include "base/strings/utf_string_conversions.h"
     15 #include "base/threading/platform_thread.h"
     16 #include "base/time/time.h"
     17 #include "content/browser/byte_stream.h"
     18 #include "content/browser/download/download_file_factory.h"
     19 #include "content/browser/download/download_file_impl.h"
     20 #include "content/browser/download/download_item_impl.h"
     21 #include "content/browser/download/download_manager_impl.h"
     22 #include "content/browser/download/download_resource_handler.h"
     23 #include "content/browser/web_contents/web_contents_impl.h"
     24 #include "content/public/browser/power_save_blocker.h"
     25 #include "content/public/common/content_switches.h"
     26 #include "content/public/common/webplugininfo.h"
     27 #include "content/public/test/browser_test_utils.h"
     28 #include "content/public/test/content_browser_test.h"
     29 #include "content/public/test/content_browser_test_utils.h"
     30 #include "content/public/test/download_test_observer.h"
     31 #include "content/public/test/test_file_error_injector.h"
     32 #include "content/public/test/test_utils.h"
     33 #include "content/shell/browser/shell.h"
     34 #include "content/shell/browser/shell_browser_context.h"
     35 #include "content/shell/browser/shell_download_manager_delegate.h"
     36 #include "content/shell/browser/shell_network_delegate.h"
     37 #include "content/test/net/url_request_slow_download_job.h"
     38 #include "net/test/embedded_test_server/embedded_test_server.h"
     39 #include "net/test/embedded_test_server/http_request.h"
     40 #include "net/test/embedded_test_server/http_response.h"
     41 #include "net/test/spawned_test_server/spawned_test_server.h"
     42 #include "net/test/url_request/url_request_mock_http_job.h"
     43 #include "testing/gmock/include/gmock/gmock.h"
     44 #include "testing/gtest/include/gtest/gtest.h"
     45 #include "url/gurl.h"
     46 
     47 #if defined(ENABLE_PLUGINS)
     48 #include "content/browser/plugin_service_impl.h"
     49 #endif
     50 
     51 using ::net::test_server::EmbeddedTestServer;
     52 using ::testing::AllOf;
     53 using ::testing::Field;
     54 using ::testing::InSequence;
     55 using ::testing::Property;
     56 using ::testing::Return;
     57 using ::testing::StrictMock;
     58 using ::testing::_;
     59 
     60 namespace content {
     61 
     62 namespace {
     63 
     64 class MockDownloadItemObserver : public DownloadItem::Observer {
     65  public:
     66   MockDownloadItemObserver() {}
     67   virtual ~MockDownloadItemObserver() {}
     68 
     69   MOCK_METHOD1(OnDownloadUpdated, void(DownloadItem*));
     70   MOCK_METHOD1(OnDownloadOpened, void(DownloadItem*));
     71   MOCK_METHOD1(OnDownloadRemoved, void(DownloadItem*));
     72   MOCK_METHOD1(OnDownloadDestroyed, void(DownloadItem*));
     73 };
     74 
     75 class MockDownloadManagerObserver : public DownloadManager::Observer {
     76  public:
     77   MockDownloadManagerObserver(DownloadManager* manager) {
     78     manager_ = manager;
     79     manager->AddObserver(this);
     80   }
     81   virtual ~MockDownloadManagerObserver() {
     82     if (manager_)
     83       manager_->RemoveObserver(this);
     84   }
     85 
     86   MOCK_METHOD2(OnDownloadCreated, void(DownloadManager*, DownloadItem*));
     87   MOCK_METHOD1(ModelChanged, void(DownloadManager*));
     88   void ManagerGoingDown(DownloadManager* manager) {
     89     DCHECK_EQ(manager_, manager);
     90     MockManagerGoingDown(manager);
     91 
     92     manager_->RemoveObserver(this);
     93     manager_ = NULL;
     94   }
     95 
     96   MOCK_METHOD1(MockManagerGoingDown, void(DownloadManager*));
     97  private:
     98   DownloadManager* manager_;
     99 };
    100 
    101 class DownloadFileWithDelayFactory;
    102 
    103 static DownloadManagerImpl* DownloadManagerForShell(Shell* shell) {
    104   // We're in a content_browsertest; we know that the DownloadManager
    105   // is a DownloadManagerImpl.
    106   return static_cast<DownloadManagerImpl*>(
    107       BrowserContext::GetDownloadManager(
    108           shell->web_contents()->GetBrowserContext()));
    109 }
    110 
    111 class DownloadFileWithDelay : public DownloadFileImpl {
    112  public:
    113   DownloadFileWithDelay(
    114       scoped_ptr<DownloadSaveInfo> save_info,
    115       const base::FilePath& default_download_directory,
    116       const GURL& url,
    117       const GURL& referrer_url,
    118       bool calculate_hash,
    119       scoped_ptr<ByteStreamReader> stream,
    120       const net::BoundNetLog& bound_net_log,
    121       scoped_ptr<PowerSaveBlocker> power_save_blocker,
    122       base::WeakPtr<DownloadDestinationObserver> observer,
    123       base::WeakPtr<DownloadFileWithDelayFactory> owner);
    124 
    125   virtual ~DownloadFileWithDelay();
    126 
    127   // Wraps DownloadFileImpl::Rename* and intercepts the return callback,
    128   // storing it in the factory that produced this object for later
    129   // retrieval.
    130   virtual void RenameAndUniquify(
    131       const base::FilePath& full_path,
    132       const RenameCompletionCallback& callback) OVERRIDE;
    133   virtual void RenameAndAnnotate(
    134       const base::FilePath& full_path,
    135       const RenameCompletionCallback& callback) OVERRIDE;
    136 
    137  private:
    138   static void RenameCallbackWrapper(
    139       const base::WeakPtr<DownloadFileWithDelayFactory>& factory,
    140       const RenameCompletionCallback& original_callback,
    141       DownloadInterruptReason reason,
    142       const base::FilePath& path);
    143 
    144   // This variable may only be read on the FILE thread, and may only be
    145   // indirected through (e.g. methods on DownloadFileWithDelayFactory called)
    146   // on the UI thread.  This is because after construction,
    147   // DownloadFileWithDelay lives on the file thread, but
    148   // DownloadFileWithDelayFactory is purely a UI thread object.
    149   base::WeakPtr<DownloadFileWithDelayFactory> owner_;
    150 
    151   DISALLOW_COPY_AND_ASSIGN(DownloadFileWithDelay);
    152 };
    153 
    154 // All routines on this class must be called on the UI thread.
    155 class DownloadFileWithDelayFactory : public DownloadFileFactory {
    156  public:
    157   DownloadFileWithDelayFactory();
    158   virtual ~DownloadFileWithDelayFactory();
    159 
    160   // DownloadFileFactory interface.
    161   virtual DownloadFile* CreateFile(
    162       scoped_ptr<DownloadSaveInfo> save_info,
    163       const base::FilePath& default_download_directory,
    164       const GURL& url,
    165       const GURL& referrer_url,
    166       bool calculate_hash,
    167       scoped_ptr<ByteStreamReader> stream,
    168       const net::BoundNetLog& bound_net_log,
    169       base::WeakPtr<DownloadDestinationObserver> observer) OVERRIDE;
    170 
    171   void AddRenameCallback(base::Closure callback);
    172   void GetAllRenameCallbacks(std::vector<base::Closure>* results);
    173 
    174   // Do not return until GetAllRenameCallbacks() will return a non-empty list.
    175   void WaitForSomeCallback();
    176 
    177  private:
    178   base::WeakPtrFactory<DownloadFileWithDelayFactory> weak_ptr_factory_;
    179   std::vector<base::Closure> rename_callbacks_;
    180   bool waiting_;
    181 
    182   DISALLOW_COPY_AND_ASSIGN(DownloadFileWithDelayFactory);
    183 };
    184 
    185 DownloadFileWithDelay::DownloadFileWithDelay(
    186     scoped_ptr<DownloadSaveInfo> save_info,
    187     const base::FilePath& default_download_directory,
    188     const GURL& url,
    189     const GURL& referrer_url,
    190     bool calculate_hash,
    191     scoped_ptr<ByteStreamReader> stream,
    192     const net::BoundNetLog& bound_net_log,
    193     scoped_ptr<PowerSaveBlocker> power_save_blocker,
    194     base::WeakPtr<DownloadDestinationObserver> observer,
    195     base::WeakPtr<DownloadFileWithDelayFactory> owner)
    196     : DownloadFileImpl(
    197         save_info.Pass(), default_download_directory, url, referrer_url,
    198         calculate_hash, stream.Pass(), bound_net_log, observer),
    199       owner_(owner) {}
    200 
    201 DownloadFileWithDelay::~DownloadFileWithDelay() {}
    202 
    203 void DownloadFileWithDelay::RenameAndUniquify(
    204     const base::FilePath& full_path,
    205     const RenameCompletionCallback& callback) {
    206   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
    207   DownloadFileImpl::RenameAndUniquify(
    208       full_path, base::Bind(DownloadFileWithDelay::RenameCallbackWrapper,
    209                             owner_, callback));
    210 }
    211 
    212 void DownloadFileWithDelay::RenameAndAnnotate(
    213     const base::FilePath& full_path, const RenameCompletionCallback& callback) {
    214   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
    215   DownloadFileImpl::RenameAndAnnotate(
    216       full_path, base::Bind(DownloadFileWithDelay::RenameCallbackWrapper,
    217                             owner_, callback));
    218 }
    219 
    220 // static
    221 void DownloadFileWithDelay::RenameCallbackWrapper(
    222     const base::WeakPtr<DownloadFileWithDelayFactory>& factory,
    223     const RenameCompletionCallback& original_callback,
    224     DownloadInterruptReason reason,
    225     const base::FilePath& path) {
    226   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    227   if (!factory)
    228     return;
    229   factory->AddRenameCallback(base::Bind(original_callback, reason, path));
    230 }
    231 
    232 DownloadFileWithDelayFactory::DownloadFileWithDelayFactory()
    233     : weak_ptr_factory_(this),
    234       waiting_(false) {}
    235 DownloadFileWithDelayFactory::~DownloadFileWithDelayFactory() {}
    236 
    237 DownloadFile* DownloadFileWithDelayFactory::CreateFile(
    238     scoped_ptr<DownloadSaveInfo> save_info,
    239     const base::FilePath& default_download_directory,
    240     const GURL& url,
    241     const GURL& referrer_url,
    242     bool calculate_hash,
    243     scoped_ptr<ByteStreamReader> stream,
    244     const net::BoundNetLog& bound_net_log,
    245     base::WeakPtr<DownloadDestinationObserver> observer) {
    246   scoped_ptr<PowerSaveBlocker> psb(
    247       PowerSaveBlocker::Create(
    248           PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
    249           "Download in progress"));
    250   return new DownloadFileWithDelay(
    251       save_info.Pass(), default_download_directory, url, referrer_url,
    252       calculate_hash, stream.Pass(), bound_net_log,
    253       psb.Pass(), observer, weak_ptr_factory_.GetWeakPtr());
    254 }
    255 
    256 void DownloadFileWithDelayFactory::AddRenameCallback(base::Closure callback) {
    257   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    258   rename_callbacks_.push_back(callback);
    259   if (waiting_)
    260     base::MessageLoopForUI::current()->Quit();
    261 }
    262 
    263 void DownloadFileWithDelayFactory::GetAllRenameCallbacks(
    264     std::vector<base::Closure>* results) {
    265   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    266   results->swap(rename_callbacks_);
    267 }
    268 
    269 void DownloadFileWithDelayFactory::WaitForSomeCallback() {
    270   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    271 
    272   if (rename_callbacks_.empty()) {
    273     waiting_ = true;
    274     RunMessageLoop();
    275     waiting_ = false;
    276   }
    277 }
    278 
    279 class CountingDownloadFile : public DownloadFileImpl {
    280  public:
    281   CountingDownloadFile(
    282     scoped_ptr<DownloadSaveInfo> save_info,
    283     const base::FilePath& default_downloads_directory,
    284     const GURL& url,
    285     const GURL& referrer_url,
    286     bool calculate_hash,
    287     scoped_ptr<ByteStreamReader> stream,
    288     const net::BoundNetLog& bound_net_log,
    289     scoped_ptr<PowerSaveBlocker> power_save_blocker,
    290     base::WeakPtr<DownloadDestinationObserver> observer)
    291       : DownloadFileImpl(save_info.Pass(), default_downloads_directory,
    292                          url, referrer_url, calculate_hash,
    293                          stream.Pass(), bound_net_log, observer) {}
    294 
    295   virtual ~CountingDownloadFile() {
    296     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
    297     active_files_--;
    298   }
    299 
    300   virtual void Initialize(const InitializeCallback& callback) OVERRIDE {
    301     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
    302     active_files_++;
    303     return DownloadFileImpl::Initialize(callback);
    304   }
    305 
    306   static void GetNumberActiveFiles(int* result) {
    307     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
    308     *result = active_files_;
    309   }
    310 
    311   // Can be called on any thread, and will block (running message loop)
    312   // until data is returned.
    313   static int GetNumberActiveFilesFromFileThread() {
    314     int result = -1;
    315     BrowserThread::PostTaskAndReply(
    316         BrowserThread::FILE,
    317         FROM_HERE,
    318         base::Bind(&CountingDownloadFile::GetNumberActiveFiles, &result),
    319         base::MessageLoop::current()->QuitClosure());
    320     base::MessageLoop::current()->Run();
    321     DCHECK_NE(-1, result);
    322     return result;
    323   }
    324 
    325  private:
    326   static int active_files_;
    327 };
    328 
    329 int CountingDownloadFile::active_files_ = 0;
    330 
    331 class CountingDownloadFileFactory : public DownloadFileFactory {
    332  public:
    333   CountingDownloadFileFactory() {}
    334   virtual ~CountingDownloadFileFactory() {}
    335 
    336   // DownloadFileFactory interface.
    337   virtual DownloadFile* CreateFile(
    338     scoped_ptr<DownloadSaveInfo> save_info,
    339     const base::FilePath& default_downloads_directory,
    340     const GURL& url,
    341     const GURL& referrer_url,
    342     bool calculate_hash,
    343     scoped_ptr<ByteStreamReader> stream,
    344     const net::BoundNetLog& bound_net_log,
    345     base::WeakPtr<DownloadDestinationObserver> observer) OVERRIDE {
    346     scoped_ptr<PowerSaveBlocker> psb(
    347         PowerSaveBlocker::Create(
    348             PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
    349             "Download in progress"));
    350     return new CountingDownloadFile(
    351         save_info.Pass(), default_downloads_directory, url, referrer_url,
    352         calculate_hash, stream.Pass(), bound_net_log,
    353         psb.Pass(), observer);
    354   }
    355 };
    356 
    357 class TestShellDownloadManagerDelegate : public ShellDownloadManagerDelegate {
    358  public:
    359   TestShellDownloadManagerDelegate()
    360       : delay_download_open_(false) {}
    361   virtual ~TestShellDownloadManagerDelegate() {}
    362 
    363   virtual bool ShouldOpenDownload(
    364       DownloadItem* item,
    365       const DownloadOpenDelayedCallback& callback) OVERRIDE {
    366     if (delay_download_open_) {
    367       delayed_callbacks_.push_back(callback);
    368       return false;
    369     }
    370     return true;
    371   }
    372 
    373   void SetDelayedOpen(bool delay) {
    374     delay_download_open_ = delay;
    375   }
    376 
    377   void GetDelayedCallbacks(
    378       std::vector<DownloadOpenDelayedCallback>* callbacks) {
    379     callbacks->swap(delayed_callbacks_);
    380   }
    381  private:
    382   bool delay_download_open_;
    383   std::vector<DownloadOpenDelayedCallback> delayed_callbacks_;
    384 };
    385 
    386 // Record all state transitions and byte counts on the observed download.
    387 class RecordingDownloadObserver : DownloadItem::Observer {
    388  public:
    389   struct RecordStruct {
    390     DownloadItem::DownloadState state;
    391     int bytes_received;
    392   };
    393 
    394   typedef std::vector<RecordStruct> RecordVector;
    395 
    396   RecordingDownloadObserver(DownloadItem* download)
    397       : download_(download) {
    398     last_state_.state = download->GetState();
    399     last_state_.bytes_received = download->GetReceivedBytes();
    400     download_->AddObserver(this);
    401   }
    402 
    403   virtual ~RecordingDownloadObserver() {
    404     RemoveObserver();
    405   }
    406 
    407   void CompareToExpectedRecord(const RecordStruct expected[], size_t size) {
    408     EXPECT_EQ(size, record_.size());
    409     int min = size > record_.size() ? record_.size() : size;
    410     for (int i = 0; i < min; ++i) {
    411       EXPECT_EQ(expected[i].state, record_[i].state) << "Iteration " << i;
    412       EXPECT_EQ(expected[i].bytes_received, record_[i].bytes_received)
    413           << "Iteration " << i;
    414     }
    415   }
    416 
    417  private:
    418   virtual void OnDownloadUpdated(DownloadItem* download) OVERRIDE {
    419     DCHECK_EQ(download_, download);
    420     DownloadItem::DownloadState state = download->GetState();
    421     int bytes = download->GetReceivedBytes();
    422     if (last_state_.state != state || last_state_.bytes_received > bytes) {
    423       last_state_.state = state;
    424       last_state_.bytes_received = bytes;
    425       record_.push_back(last_state_);
    426     }
    427   }
    428 
    429   virtual void OnDownloadDestroyed(DownloadItem* download) OVERRIDE {
    430     DCHECK_EQ(download_, download);
    431     RemoveObserver();
    432   }
    433 
    434   void RemoveObserver() {
    435     if (download_) {
    436       download_->RemoveObserver(this);
    437       download_ = NULL;
    438     }
    439   }
    440 
    441   DownloadItem* download_;
    442   RecordStruct last_state_;
    443   RecordVector record_;
    444 };
    445 
    446 // Get the next created download.
    447 class DownloadCreateObserver : DownloadManager::Observer {
    448  public:
    449   DownloadCreateObserver(DownloadManager* manager)
    450       : manager_(manager),
    451         item_(NULL),
    452         waiting_(false) {
    453     manager_->AddObserver(this);
    454   }
    455 
    456   virtual ~DownloadCreateObserver() {
    457     if (manager_)
    458       manager_->RemoveObserver(this);
    459     manager_ = NULL;
    460   }
    461 
    462   virtual void ManagerGoingDown(DownloadManager* manager) OVERRIDE {
    463     DCHECK_EQ(manager_, manager);
    464     manager_->RemoveObserver(this);
    465     manager_ = NULL;
    466   }
    467 
    468   virtual void OnDownloadCreated(DownloadManager* manager,
    469                                  DownloadItem* download) OVERRIDE {
    470     if (!item_)
    471       item_ = download;
    472 
    473     if (waiting_)
    474       base::MessageLoopForUI::current()->Quit();
    475   }
    476 
    477   DownloadItem* WaitForFinished() {
    478     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    479     if (!item_) {
    480       waiting_ = true;
    481       RunMessageLoop();
    482       waiting_ = false;
    483     }
    484     return item_;
    485   }
    486 
    487  private:
    488   DownloadManager* manager_;
    489   DownloadItem* item_;
    490   bool waiting_;
    491 };
    492 
    493 
    494 // Filter for waiting for a certain number of bytes.
    495 bool DataReceivedFilter(int number_of_bytes, DownloadItem* download) {
    496   return download->GetReceivedBytes() >= number_of_bytes;
    497 }
    498 
    499 // Filter for download completion.
    500 bool DownloadCompleteFilter(DownloadItem* download) {
    501   return download->GetState() == DownloadItem::COMPLETE;
    502 }
    503 
    504 // Filter for saving the size of the download when the first IN_PROGRESS
    505 // is hit.
    506 bool InitialSizeFilter(int* download_size, DownloadItem* download) {
    507   if (download->GetState() != DownloadItem::IN_PROGRESS)
    508     return false;
    509 
    510   *download_size = download->GetReceivedBytes();
    511   return true;
    512 }
    513 
    514 // Request handler to be used with CreateRedirectHandler().
    515 scoped_ptr<net::test_server::HttpResponse> HandleRequestAndSendRedirectResponse(
    516     const std::string& relative_url,
    517     const GURL& target_url,
    518     const net::test_server::HttpRequest& request) {
    519   scoped_ptr<net::test_server::BasicHttpResponse> response;
    520   if (request.relative_url == relative_url) {
    521     response.reset(new net::test_server::BasicHttpResponse);
    522     response->set_code(net::HTTP_FOUND);
    523     response->AddCustomHeader("Location", target_url.spec());
    524   }
    525   return response.PassAs<net::test_server::HttpResponse>();
    526 }
    527 
    528 // Creates a request handler for EmbeddedTestServer that responds with a HTTP
    529 // 302 redirect if the request URL matches |relative_url|.
    530 EmbeddedTestServer::HandleRequestCallback CreateRedirectHandler(
    531     const std::string& relative_url,
    532     const GURL& target_url) {
    533   return base::Bind(
    534       &HandleRequestAndSendRedirectResponse, relative_url, target_url);
    535 }
    536 
    537 // Request handler to be used with CreateBasicResponseHandler().
    538 scoped_ptr<net::test_server::HttpResponse> HandleRequestAndSendBasicResponse(
    539     const std::string& relative_url,
    540     const std::string& content_type,
    541     const std::string& body,
    542     const net::test_server::HttpRequest& request) {
    543   scoped_ptr<net::test_server::BasicHttpResponse> response;
    544   if (request.relative_url == relative_url) {
    545     response.reset(new net::test_server::BasicHttpResponse);
    546     response->set_content_type(content_type);
    547     response->set_content(body);
    548   }
    549   return response.PassAs<net::test_server::HttpResponse>();
    550 }
    551 
    552 // Creates a request handler for an EmbeddedTestServer that response with an
    553 // HTTP 200 status code, a Content-Type header and a body.
    554 EmbeddedTestServer::HandleRequestCallback CreateBasicResponseHandler(
    555     const std::string& relative_url,
    556     const std::string& content_type,
    557     const std::string& body) {
    558   return base::Bind(
    559       &HandleRequestAndSendBasicResponse, relative_url, content_type, body);
    560 }
    561 
    562 }  // namespace
    563 
    564 class DownloadContentTest : public ContentBrowserTest {
    565  protected:
    566   // An initial send from a website of at least this size will not be
    567   // help up by buffering in the underlying downloads ByteStream data
    568   // transfer.  This is important because on resumption tests we wait
    569   // until we've gotten the data we expect before allowing the test server
    570   // to send its reset, to get around hard close semantics on the Windows
    571   // socket layer implementation.
    572   int GetSafeBufferChunk() const {
    573     return (DownloadResourceHandler::kDownloadByteStreamSize /
    574        ByteStreamWriter::kFractionBufferBeforeSending) + 1;
    575   }
    576 
    577   virtual void SetUpOnMainThread() OVERRIDE {
    578     ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir());
    579 
    580     test_delegate_.reset(new TestShellDownloadManagerDelegate());
    581     test_delegate_->SetDownloadBehaviorForTesting(downloads_directory_.path());
    582     DownloadManager* manager = DownloadManagerForShell(shell());
    583     manager->GetDelegate()->Shutdown();
    584     manager->SetDelegate(test_delegate_.get());
    585     test_delegate_->SetDownloadManager(manager);
    586 
    587     BrowserThread::PostTask(
    588         BrowserThread::IO, FROM_HERE,
    589         base::Bind(&URLRequestSlowDownloadJob::AddUrlHandler));
    590     base::FilePath mock_base(GetTestFilePath("download", ""));
    591     BrowserThread::PostTask(
    592         BrowserThread::IO,
    593         FROM_HERE,
    594         base::Bind(
    595             &net::URLRequestMockHTTPJob::AddUrlHandler,
    596             mock_base,
    597             make_scoped_refptr(content::BrowserThread::GetBlockingPool())));
    598   }
    599 
    600   TestShellDownloadManagerDelegate* GetDownloadManagerDelegate() {
    601     return test_delegate_.get();
    602   }
    603 
    604   // Create a DownloadTestObserverTerminal that will wait for the
    605   // specified number of downloads to finish.
    606   DownloadTestObserver* CreateWaiter(
    607       Shell* shell, int num_downloads) {
    608     DownloadManager* download_manager = DownloadManagerForShell(shell);
    609     return new DownloadTestObserverTerminal(download_manager, num_downloads,
    610         DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
    611   }
    612 
    613   // Create a DownloadTestObserverInProgress that will wait for the
    614   // specified number of downloads to start.
    615   DownloadCreateObserver* CreateInProgressWaiter(
    616       Shell* shell, int num_downloads) {
    617     DownloadManager* download_manager = DownloadManagerForShell(shell);
    618     return new DownloadCreateObserver(download_manager);
    619   }
    620 
    621   DownloadTestObserver* CreateInterruptedWaiter(
    622       Shell* shell, int num_downloads) {
    623     DownloadManager* download_manager = DownloadManagerForShell(shell);
    624     return new DownloadTestObserverInterrupted(download_manager, num_downloads,
    625         DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
    626   }
    627 
    628   // Note: Cannot be used with other alternative DownloadFileFactorys
    629   void SetupEnsureNoPendingDownloads() {
    630     DownloadManagerForShell(shell())->SetDownloadFileFactoryForTesting(
    631         scoped_ptr<DownloadFileFactory>(
    632             new CountingDownloadFileFactory()).Pass());
    633   }
    634 
    635   bool EnsureNoPendingDownloads() {
    636     bool result = true;
    637     BrowserThread::PostTask(
    638         BrowserThread::IO, FROM_HERE,
    639         base::Bind(&EnsureNoPendingDownloadJobsOnIO, &result));
    640     base::MessageLoop::current()->Run();
    641     return result &&
    642            (CountingDownloadFile::GetNumberActiveFilesFromFileThread() == 0);
    643   }
    644 
    645   void NavigateToURLAndWaitForDownload(
    646       Shell* shell,
    647       const GURL& url,
    648       DownloadItem::DownloadState expected_terminal_state) {
    649     scoped_ptr<DownloadTestObserver> observer(CreateWaiter(shell, 1));
    650     NavigateToURL(shell, url);
    651     observer->WaitForFinished();
    652     EXPECT_EQ(1u, observer->NumDownloadsSeenInState(expected_terminal_state));
    653   }
    654 
    655   // Checks that |path| is has |file_size| bytes, and matches the |value|
    656   // string.
    657   bool VerifyFile(const base::FilePath& path,
    658                   const std::string& value,
    659                   const int64 file_size) {
    660     std::string file_contents;
    661 
    662     bool read = base::ReadFileToString(path, &file_contents);
    663     EXPECT_TRUE(read) << "Failed reading file: " << path.value() << std::endl;
    664     if (!read)
    665       return false;  // Couldn't read the file.
    666 
    667     // Note: we don't handle really large files (more than size_t can hold)
    668     // so we will fail in that case.
    669     size_t expected_size = static_cast<size_t>(file_size);
    670 
    671     // Check the size.
    672     EXPECT_EQ(expected_size, file_contents.size());
    673     if (expected_size != file_contents.size())
    674       return false;
    675 
    676     // Check the contents.
    677     EXPECT_EQ(value, file_contents);
    678     if (memcmp(file_contents.c_str(), value.c_str(), expected_size) != 0)
    679       return false;
    680 
    681     return true;
    682   }
    683 
    684   // Start a download and return the item.
    685   DownloadItem* StartDownloadAndReturnItem(GURL url) {
    686     scoped_ptr<DownloadCreateObserver> observer(
    687         CreateInProgressWaiter(shell(), 1));
    688     NavigateToURL(shell(), url);
    689     observer->WaitForFinished();
    690     std::vector<DownloadItem*> downloads;
    691     DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
    692     EXPECT_EQ(1u, downloads.size());
    693     if (1u != downloads.size())
    694       return NULL;
    695     return downloads[0];
    696   }
    697 
    698   // Wait for data
    699   void WaitForData(DownloadItem* download, int size) {
    700     DownloadUpdatedObserver data_observer(
    701         download, base::Bind(&DataReceivedFilter, size));
    702     data_observer.WaitForEvent();
    703     ASSERT_EQ(size, download->GetReceivedBytes());
    704     ASSERT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
    705   }
    706 
    707   // Tell the test server to release a pending RST and confirm
    708   // that the interrupt is received properly (for download resumption
    709   // testing).
    710   void ReleaseRSTAndConfirmInterruptForResume(DownloadItem* download) {
    711     scoped_ptr<DownloadTestObserver> rst_observer(
    712         CreateInterruptedWaiter(shell(), 1));
    713     NavigateToURL(shell(), test_server()->GetURL("download-finish"));
    714     rst_observer->WaitForFinished();
    715     EXPECT_EQ(DownloadItem::INTERRUPTED, download->GetState());
    716   }
    717 
    718   // Confirm file status expected for the given location in a stream
    719   // provided by the resume test server.
    720   void ConfirmFileStatusForResume(
    721       DownloadItem* download, bool file_exists,
    722       int received_bytes, int total_bytes,
    723       const base::FilePath& expected_filename) {
    724     // expected_filename is only known if the file exists.
    725     ASSERT_EQ(file_exists, !expected_filename.empty());
    726     EXPECT_EQ(received_bytes, download->GetReceivedBytes());
    727     EXPECT_EQ(total_bytes, download->GetTotalBytes());
    728     EXPECT_EQ(expected_filename.value(),
    729               download->GetFullPath().BaseName().value());
    730     EXPECT_EQ(file_exists,
    731               (!download->GetFullPath().empty() &&
    732                base::PathExists(download->GetFullPath())));
    733 
    734     if (file_exists) {
    735       std::string file_contents;
    736       EXPECT_TRUE(base::ReadFileToString(
    737           download->GetFullPath(), &file_contents));
    738 
    739       ASSERT_EQ(static_cast<size_t>(received_bytes), file_contents.size());
    740       for (int i = 0; i < received_bytes; ++i) {
    741         EXPECT_EQ(static_cast<char>((i * 2 + 15) % 256), file_contents[i])
    742             << "File contents diverged at position " << i
    743             << " for " << expected_filename.value();
    744 
    745         if (static_cast<char>((i * 2 + 15) % 256) != file_contents[i])
    746           return;
    747       }
    748     }
    749   }
    750 
    751  private:
    752   static void EnsureNoPendingDownloadJobsOnIO(bool* result) {
    753     if (URLRequestSlowDownloadJob::NumberOutstandingRequests())
    754       *result = false;
    755     BrowserThread::PostTask(
    756         BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure());
    757   }
    758 
    759   // Location of the downloads directory for these tests
    760   base::ScopedTempDir downloads_directory_;
    761   scoped_ptr<TestShellDownloadManagerDelegate> test_delegate_;
    762 };
    763 
    764 IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadCancelled) {
    765   SetupEnsureNoPendingDownloads();
    766 
    767   // Create a download, wait until it's started, and confirm
    768   // we're in the expected state.
    769   scoped_ptr<DownloadCreateObserver> observer(
    770       CreateInProgressWaiter(shell(), 1));
    771   NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl));
    772   observer->WaitForFinished();
    773 
    774   std::vector<DownloadItem*> downloads;
    775   DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
    776   ASSERT_EQ(1u, downloads.size());
    777   ASSERT_EQ(DownloadItem::IN_PROGRESS, downloads[0]->GetState());
    778 
    779   // Cancel the download and wait for download system quiesce.
    780   downloads[0]->Cancel(true);
    781   scoped_refptr<DownloadTestFlushObserver> flush_observer(
    782       new DownloadTestFlushObserver(DownloadManagerForShell(shell())));
    783   flush_observer->WaitForFlush();
    784 
    785   // Get the important info from other threads and check it.
    786   EXPECT_TRUE(EnsureNoPendingDownloads());
    787 }
    788 
    789 // Check that downloading multiple (in this case, 2) files does not result in
    790 // corrupted files.
    791 IN_PROC_BROWSER_TEST_F(DownloadContentTest, MultiDownload) {
    792   SetupEnsureNoPendingDownloads();
    793 
    794   // Create a download, wait until it's started, and confirm
    795   // we're in the expected state.
    796   scoped_ptr<DownloadCreateObserver> observer1(
    797       CreateInProgressWaiter(shell(), 1));
    798   NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl));
    799   observer1->WaitForFinished();
    800 
    801   std::vector<DownloadItem*> downloads;
    802   DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
    803   ASSERT_EQ(1u, downloads.size());
    804   ASSERT_EQ(DownloadItem::IN_PROGRESS, downloads[0]->GetState());
    805   DownloadItem* download1 = downloads[0];  // The only download.
    806 
    807   // Start the second download and wait until it's done.
    808   base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
    809   GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file));
    810   // Download the file and wait.
    811   NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE);
    812 
    813   // Should now have 2 items on the manager.
    814   downloads.clear();
    815   DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
    816   ASSERT_EQ(2u, downloads.size());
    817   // We don't know the order of the downloads.
    818   DownloadItem* download2 = downloads[(download1 == downloads[0]) ? 1 : 0];
    819 
    820   ASSERT_EQ(DownloadItem::IN_PROGRESS, download1->GetState());
    821   ASSERT_EQ(DownloadItem::COMPLETE, download2->GetState());
    822 
    823   // Allow the first request to finish.
    824   scoped_ptr<DownloadTestObserver> observer2(CreateWaiter(shell(), 1));
    825   NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kFinishDownloadUrl));
    826   observer2->WaitForFinished();  // Wait for the third request.
    827   EXPECT_EQ(1u, observer2->NumDownloadsSeenInState(DownloadItem::COMPLETE));
    828 
    829   // Get the important info from other threads and check it.
    830   EXPECT_TRUE(EnsureNoPendingDownloads());
    831 
    832   // The |DownloadItem|s should now be done and have the final file names.
    833   // Verify that the files have the expected data and size.
    834   // |file1| should be full of '*'s, and |file2| should be the same as the
    835   // source file.
    836   base::FilePath file1(download1->GetTargetFilePath());
    837   size_t file_size1 = URLRequestSlowDownloadJob::kFirstDownloadSize +
    838                       URLRequestSlowDownloadJob::kSecondDownloadSize;
    839   std::string expected_contents(file_size1, '*');
    840   ASSERT_TRUE(VerifyFile(file1, expected_contents, file_size1));
    841 
    842   base::FilePath file2(download2->GetTargetFilePath());
    843   ASSERT_TRUE(base::ContentsEqual(
    844       file2, GetTestFilePath("download", "download-test.lib")));
    845 }
    846 
    847 #if defined(ENABLE_PLUGINS)
    848 // Content served with a MIME type of application/octet-stream should be
    849 // downloaded even when a plugin can be found that handles the file type.
    850 IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadOctetStream) {
    851   const base::FilePath::CharType kTestFilePath[] =
    852       FILE_PATH_LITERAL("octet-stream.abc");
    853   const char kTestPluginName[] = "TestPlugin";
    854   const char kTestMimeType[] = "application/x-test-mime-type";
    855   const char kTestFileType[] = "abc";
    856 
    857   WebPluginInfo plugin_info;
    858   plugin_info.name = base::ASCIIToUTF16(kTestPluginName);
    859   plugin_info.mime_types.push_back(
    860       WebPluginMimeType(kTestMimeType, kTestFileType, ""));
    861   PluginServiceImpl::GetInstance()->RegisterInternalPlugin(plugin_info, false);
    862 
    863   // The following is served with a Content-Type of application/octet-stream.
    864   GURL url(
    865       net::URLRequestMockHTTPJob::GetMockUrl(base::FilePath(kTestFilePath)));
    866   NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE);
    867 }
    868 #endif
    869 
    870 // Try to cancel just before we release the download file, by delaying final
    871 // rename callback.
    872 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelAtFinalRename) {
    873   // Setup new factory.
    874   DownloadFileWithDelayFactory* file_factory =
    875       new DownloadFileWithDelayFactory();
    876   DownloadManagerImpl* download_manager(DownloadManagerForShell(shell()));
    877   download_manager->SetDownloadFileFactoryForTesting(
    878       scoped_ptr<DownloadFileFactory>(file_factory).Pass());
    879 
    880   // Create a download
    881   base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
    882   NavigateToURL(shell(), net::URLRequestMockHTTPJob::GetMockUrl(file));
    883 
    884   // Wait until the first (intermediate file) rename and execute the callback.
    885   file_factory->WaitForSomeCallback();
    886   std::vector<base::Closure> callbacks;
    887   file_factory->GetAllRenameCallbacks(&callbacks);
    888   ASSERT_EQ(1u, callbacks.size());
    889   callbacks[0].Run();
    890   callbacks.clear();
    891 
    892   // Wait until the second (final) rename callback is posted.
    893   file_factory->WaitForSomeCallback();
    894   file_factory->GetAllRenameCallbacks(&callbacks);
    895   ASSERT_EQ(1u, callbacks.size());
    896 
    897   // Cancel it.
    898   std::vector<DownloadItem*> items;
    899   download_manager->GetAllDownloads(&items);
    900   ASSERT_EQ(1u, items.size());
    901   items[0]->Cancel(true);
    902   RunAllPendingInMessageLoop();
    903 
    904   // Check state.
    905   EXPECT_EQ(DownloadItem::CANCELLED, items[0]->GetState());
    906 
    907   // Run final rename callback.
    908   callbacks[0].Run();
    909   callbacks.clear();
    910 
    911   // Check state.
    912   EXPECT_EQ(DownloadItem::CANCELLED, items[0]->GetState());
    913 }
    914 
    915 // Try to cancel just after we release the download file, by delaying
    916 // in ShouldOpenDownload.
    917 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelAtRelease) {
    918   DownloadManagerImpl* download_manager(DownloadManagerForShell(shell()));
    919 
    920   // Mark delegate for delayed open.
    921   GetDownloadManagerDelegate()->SetDelayedOpen(true);
    922 
    923   // Setup new factory.
    924   DownloadFileWithDelayFactory* file_factory =
    925       new DownloadFileWithDelayFactory();
    926   download_manager->SetDownloadFileFactoryForTesting(
    927       scoped_ptr<DownloadFileFactory>(file_factory).Pass());
    928 
    929   // Create a download
    930   base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
    931   NavigateToURL(shell(), net::URLRequestMockHTTPJob::GetMockUrl(file));
    932 
    933   // Wait until the first (intermediate file) rename and execute the callback.
    934   file_factory->WaitForSomeCallback();
    935   std::vector<base::Closure> callbacks;
    936   file_factory->GetAllRenameCallbacks(&callbacks);
    937   ASSERT_EQ(1u, callbacks.size());
    938   callbacks[0].Run();
    939   callbacks.clear();
    940 
    941   // Wait until the second (final) rename callback is posted.
    942   file_factory->WaitForSomeCallback();
    943   file_factory->GetAllRenameCallbacks(&callbacks);
    944   ASSERT_EQ(1u, callbacks.size());
    945 
    946   // Call it.
    947   callbacks[0].Run();
    948   callbacks.clear();
    949 
    950   // Confirm download still IN_PROGRESS (internal state COMPLETING).
    951   std::vector<DownloadItem*> items;
    952   download_manager->GetAllDownloads(&items);
    953   EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
    954 
    955   // Cancel the download; confirm cancel fails.
    956   ASSERT_EQ(1u, items.size());
    957   items[0]->Cancel(true);
    958   EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
    959 
    960   // Need to complete open test.
    961   std::vector<DownloadOpenDelayedCallback> delayed_callbacks;
    962   GetDownloadManagerDelegate()->GetDelayedCallbacks(
    963       &delayed_callbacks);
    964   ASSERT_EQ(1u, delayed_callbacks.size());
    965   delayed_callbacks[0].Run(true);
    966 
    967   // *Now* the download should be complete.
    968   EXPECT_EQ(DownloadItem::COMPLETE, items[0]->GetState());
    969 }
    970 
    971 // Try to shutdown with a download in progress to make sure shutdown path
    972 // works properly.
    973 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownInProgress) {
    974   // Create a download that won't complete.
    975   scoped_ptr<DownloadCreateObserver> observer(
    976       CreateInProgressWaiter(shell(), 1));
    977   NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl));
    978   observer->WaitForFinished();
    979 
    980   // Get the item.
    981   std::vector<DownloadItem*> items;
    982   DownloadManagerForShell(shell())->GetAllDownloads(&items);
    983   ASSERT_EQ(1u, items.size());
    984   EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
    985 
    986   // Shutdown the download manager and make sure we get the right
    987   // notifications in the right order.
    988   StrictMock<MockDownloadItemObserver> item_observer;
    989   items[0]->AddObserver(&item_observer);
    990   MockDownloadManagerObserver manager_observer(
    991       DownloadManagerForShell(shell()));
    992   // Don't care about ModelChanged() events.
    993   EXPECT_CALL(manager_observer, ModelChanged(_))
    994       .WillRepeatedly(Return());
    995   {
    996     InSequence notifications;
    997 
    998     EXPECT_CALL(manager_observer, MockManagerGoingDown(
    999         DownloadManagerForShell(shell())))
   1000         .WillOnce(Return());
   1001     EXPECT_CALL(item_observer, OnDownloadUpdated(
   1002         AllOf(items[0],
   1003               Property(&DownloadItem::GetState, DownloadItem::CANCELLED))))
   1004         .WillOnce(Return());
   1005     EXPECT_CALL(item_observer, OnDownloadDestroyed(items[0]))
   1006         .WillOnce(Return());
   1007   }
   1008 
   1009   // See http://crbug.com/324525.  If we have a refcount release/post task
   1010   // race, the second post will stall the IO thread long enough so that we'll
   1011   // lose the race and crash.  The first stall is just to give the UI thread
   1012   // a chance to get the second stall onto the IO thread queue after the cancel
   1013   // message created by Shutdown and before the notification callback
   1014   // created by the IO thread in canceling the request.
   1015   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
   1016                           base::Bind(&base::PlatformThread::Sleep,
   1017                                      base::TimeDelta::FromMilliseconds(25)));
   1018   DownloadManagerForShell(shell())->Shutdown();
   1019   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
   1020                           base::Bind(&base::PlatformThread::Sleep,
   1021                                      base::TimeDelta::FromMilliseconds(25)));
   1022   items.clear();
   1023 }
   1024 
   1025 // Try to shutdown just after we release the download file, by delaying
   1026 // release.
   1027 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownAtRelease) {
   1028   DownloadManagerImpl* download_manager(DownloadManagerForShell(shell()));
   1029 
   1030   // Mark delegate for delayed open.
   1031   GetDownloadManagerDelegate()->SetDelayedOpen(true);
   1032 
   1033   // Setup new factory.
   1034   DownloadFileWithDelayFactory* file_factory =
   1035       new DownloadFileWithDelayFactory();
   1036   download_manager->SetDownloadFileFactoryForTesting(
   1037       scoped_ptr<DownloadFileFactory>(file_factory).Pass());
   1038 
   1039   // Create a download
   1040   base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
   1041   NavigateToURL(shell(), net::URLRequestMockHTTPJob::GetMockUrl(file));
   1042 
   1043   // Wait until the first (intermediate file) rename and execute the callback.
   1044   file_factory->WaitForSomeCallback();
   1045   std::vector<base::Closure> callbacks;
   1046   file_factory->GetAllRenameCallbacks(&callbacks);
   1047   ASSERT_EQ(1u, callbacks.size());
   1048   callbacks[0].Run();
   1049   callbacks.clear();
   1050 
   1051   // Wait until the second (final) rename callback is posted.
   1052   file_factory->WaitForSomeCallback();
   1053   file_factory->GetAllRenameCallbacks(&callbacks);
   1054   ASSERT_EQ(1u, callbacks.size());
   1055 
   1056   // Call it.
   1057   callbacks[0].Run();
   1058   callbacks.clear();
   1059 
   1060   // Confirm download isn't complete yet.
   1061   std::vector<DownloadItem*> items;
   1062   DownloadManagerForShell(shell())->GetAllDownloads(&items);
   1063   EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
   1064 
   1065   // Cancel the download; confirm cancel fails anyway.
   1066   ASSERT_EQ(1u, items.size());
   1067   items[0]->Cancel(true);
   1068   EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
   1069   RunAllPendingInMessageLoop();
   1070   EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
   1071 
   1072   MockDownloadItemObserver observer;
   1073   items[0]->AddObserver(&observer);
   1074   EXPECT_CALL(observer, OnDownloadDestroyed(items[0]));
   1075 
   1076   // Shutdown the download manager.  Mostly this is confirming a lack of
   1077   // crashes.
   1078   DownloadManagerForShell(shell())->Shutdown();
   1079 }
   1080 
   1081 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeInterruptedDownload) {
   1082   base::CommandLine::ForCurrentProcess()->AppendSwitch(
   1083       switches::kEnableDownloadResumption);
   1084   ASSERT_TRUE(test_server()->Start());
   1085 
   1086   GURL url = test_server()->GetURL(
   1087       base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
   1088                    GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
   1089 
   1090   MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell()));
   1091   EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
   1092 
   1093   DownloadItem* download(StartDownloadAndReturnItem(url));
   1094   WaitForData(download, GetSafeBufferChunk());
   1095   ::testing::Mock::VerifyAndClearExpectations(&dm_observer);
   1096 
   1097   // Confirm resumption while in progress doesn't do anything.
   1098   download->Resume();
   1099   ASSERT_EQ(GetSafeBufferChunk(), download->GetReceivedBytes());
   1100   ASSERT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
   1101 
   1102   // Tell the server to send the RST and confirm the interrupt happens.
   1103   ReleaseRSTAndConfirmInterruptForResume(download);
   1104   ConfirmFileStatusForResume(
   1105       download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
   1106       base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
   1107 
   1108   // Resume, confirming received bytes on resumption is correct.
   1109   // Make sure no creation calls are included.
   1110   EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(0);
   1111   int initial_size = 0;
   1112   DownloadUpdatedObserver initial_size_observer(
   1113       download, base::Bind(&InitialSizeFilter, &initial_size));
   1114   download->Resume();
   1115   initial_size_observer.WaitForEvent();
   1116   EXPECT_EQ(GetSafeBufferChunk(), initial_size);
   1117   ::testing::Mock::VerifyAndClearExpectations(&dm_observer);
   1118 
   1119   // and wait for expected data.
   1120   WaitForData(download, GetSafeBufferChunk() * 2);
   1121 
   1122   // Tell the server to send the RST and confirm the interrupt happens.
   1123   ReleaseRSTAndConfirmInterruptForResume(download);
   1124   ConfirmFileStatusForResume(
   1125       download, true, GetSafeBufferChunk() * 2, GetSafeBufferChunk() * 3,
   1126       base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
   1127 
   1128   // Resume and wait for completion.
   1129   DownloadUpdatedObserver completion_observer(
   1130       download, base::Bind(DownloadCompleteFilter));
   1131   download->Resume();
   1132   completion_observer.WaitForEvent();
   1133 
   1134   ConfirmFileStatusForResume(
   1135       download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
   1136       base::FilePath(FILE_PATH_LITERAL("rangereset")));
   1137 
   1138   // Confirm resumption while complete doesn't do anything.
   1139   download->Resume();
   1140   ASSERT_EQ(GetSafeBufferChunk() * 3, download->GetReceivedBytes());
   1141   ASSERT_EQ(DownloadItem::COMPLETE, download->GetState());
   1142   RunAllPendingInMessageLoop();
   1143   ASSERT_EQ(GetSafeBufferChunk() * 3, download->GetReceivedBytes());
   1144   ASSERT_EQ(DownloadItem::COMPLETE, download->GetState());
   1145 }
   1146 
   1147 // Confirm restart fallback happens if a range request is bounced.
   1148 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeInterruptedDownloadNoRange) {
   1149   base::CommandLine::ForCurrentProcess()->AppendSwitch(
   1150       switches::kEnableDownloadResumption);
   1151   ASSERT_TRUE(test_server()->Start());
   1152 
   1153   // Auto-restart if server doesn't handle ranges.
   1154   GURL url = test_server()->GetURL(
   1155       base::StringPrintf(
   1156           // First download hits an RST, rest don't, no ranges.
   1157           "rangereset?size=%d&rst_boundary=%d&"
   1158           "token=NoRange&rst_limit=1&bounce_range",
   1159           GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
   1160 
   1161   // Start the download and wait for first data chunk.
   1162   DownloadItem* download(StartDownloadAndReturnItem(url));
   1163   WaitForData(download, GetSafeBufferChunk());
   1164 
   1165   RecordingDownloadObserver recorder(download);
   1166 
   1167   ReleaseRSTAndConfirmInterruptForResume(download);
   1168   ConfirmFileStatusForResume(
   1169       download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
   1170       base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
   1171 
   1172   DownloadUpdatedObserver completion_observer(
   1173       download, base::Bind(DownloadCompleteFilter));
   1174   download->Resume();
   1175   completion_observer.WaitForEvent();
   1176 
   1177   ConfirmFileStatusForResume(
   1178       download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
   1179       base::FilePath(FILE_PATH_LITERAL("rangereset")));
   1180 
   1181   static const RecordingDownloadObserver::RecordStruct expected_record[] = {
   1182     // Result of RST
   1183     {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
   1184     // Starting continuation
   1185     {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()},
   1186     // Notification of receiving whole file.
   1187     {DownloadItem::IN_PROGRESS, 0},
   1188     // Completion.
   1189     {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
   1190   };
   1191 
   1192   recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
   1193 }
   1194 
   1195 // Confirm restart fallback happens if a precondition is failed.
   1196 IN_PROC_BROWSER_TEST_F(DownloadContentTest,
   1197                        ResumeInterruptedDownloadBadPrecondition) {
   1198   base::CommandLine::ForCurrentProcess()->AppendSwitch(
   1199       switches::kEnableDownloadResumption);
   1200   ASSERT_TRUE(test_server()->Start());
   1201 
   1202   GURL url = test_server()->GetURL(base::StringPrintf(
   1203       // First download hits an RST, rest don't, precondition fail.
   1204       "rangereset?size=%d&rst_boundary=%d&"
   1205       "token=BadPrecondition&rst_limit=1&fail_precondition=2",
   1206       GetSafeBufferChunk() * 3,
   1207       GetSafeBufferChunk()));
   1208 
   1209   // Start the download and wait for first data chunk.
   1210   DownloadItem* download(StartDownloadAndReturnItem(url));
   1211   WaitForData(download, GetSafeBufferChunk());
   1212 
   1213   RecordingDownloadObserver recorder(download);
   1214 
   1215   ReleaseRSTAndConfirmInterruptForResume(download);
   1216   ConfirmFileStatusForResume(
   1217       download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
   1218       base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
   1219   EXPECT_EQ("BadPrecondition2", download->GetETag());
   1220 
   1221   DownloadUpdatedObserver completion_observer(
   1222       download, base::Bind(DownloadCompleteFilter));
   1223   download->Resume();
   1224   completion_observer.WaitForEvent();
   1225 
   1226   ConfirmFileStatusForResume(
   1227       download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
   1228       base::FilePath(FILE_PATH_LITERAL("rangereset")));
   1229   EXPECT_EQ("BadPrecondition0", download->GetETag());
   1230 
   1231   static const RecordingDownloadObserver::RecordStruct expected_record[] = {
   1232     // Result of RST
   1233     {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
   1234     // Starting continuation
   1235     {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()},
   1236     // Server precondition fail.
   1237     {DownloadItem::INTERRUPTED, 0},
   1238     // Notification of successful restart.
   1239     {DownloadItem::IN_PROGRESS, 0},
   1240     // Completion.
   1241     {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
   1242   };
   1243 
   1244   recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
   1245 }
   1246 
   1247 // Confirm we don't try to resume if we don't have a verifier.
   1248 IN_PROC_BROWSER_TEST_F(DownloadContentTest,
   1249                        ResumeInterruptedDownloadNoVerifiers) {
   1250   base::CommandLine::ForCurrentProcess()->AppendSwitch(
   1251       switches::kEnableDownloadResumption);
   1252   ASSERT_TRUE(test_server()->Start());
   1253 
   1254   GURL url = test_server()->GetURL(
   1255       base::StringPrintf(
   1256           // First download hits an RST, rest don't, no verifiers.
   1257           "rangereset?size=%d&rst_boundary=%d&"
   1258           "token=NoRange&rst_limit=1&no_verifiers",
   1259           GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
   1260 
   1261   // Start the download and wait for first data chunk.
   1262   DownloadItem* download(StartDownloadAndReturnItem(url));
   1263   WaitForData(download, GetSafeBufferChunk());
   1264 
   1265   RecordingDownloadObserver recorder(download);
   1266 
   1267   ReleaseRSTAndConfirmInterruptForResume(download);
   1268   ConfirmFileStatusForResume(
   1269       download, false, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
   1270       base::FilePath());
   1271 
   1272   DownloadUpdatedObserver completion_observer(
   1273       download, base::Bind(DownloadCompleteFilter));
   1274   download->Resume();
   1275   completion_observer.WaitForEvent();
   1276 
   1277   ConfirmFileStatusForResume(
   1278       download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
   1279       base::FilePath(FILE_PATH_LITERAL("rangereset")));
   1280 
   1281   static const RecordingDownloadObserver::RecordStruct expected_record[] = {
   1282     // Result of RST
   1283     {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
   1284     // Restart for lack of verifiers
   1285     {DownloadItem::IN_PROGRESS, 0},
   1286     // Completion.
   1287     {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
   1288   };
   1289 
   1290   recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
   1291 }
   1292 
   1293 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithDeletedFile) {
   1294   base::CommandLine::ForCurrentProcess()->AppendSwitch(
   1295       switches::kEnableDownloadResumption);
   1296   ASSERT_TRUE(test_server()->Start());
   1297 
   1298   GURL url = test_server()->GetURL(
   1299       base::StringPrintf(
   1300           // First download hits an RST, rest don't
   1301           "rangereset?size=%d&rst_boundary=%d&"
   1302           "token=NoRange&rst_limit=1",
   1303           GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
   1304 
   1305   // Start the download and wait for first data chunk.
   1306   DownloadItem* download(StartDownloadAndReturnItem(url));
   1307   WaitForData(download, GetSafeBufferChunk());
   1308 
   1309   RecordingDownloadObserver recorder(download);
   1310 
   1311   ReleaseRSTAndConfirmInterruptForResume(download);
   1312   ConfirmFileStatusForResume(
   1313       download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
   1314       base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
   1315 
   1316   // Delete the intermediate file.
   1317   base::DeleteFile(download->GetFullPath(), false);
   1318 
   1319   DownloadUpdatedObserver completion_observer(
   1320       download, base::Bind(DownloadCompleteFilter));
   1321   download->Resume();
   1322   completion_observer.WaitForEvent();
   1323 
   1324   ConfirmFileStatusForResume(
   1325       download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
   1326       base::FilePath(FILE_PATH_LITERAL("rangereset")));
   1327 
   1328   static const RecordingDownloadObserver::RecordStruct expected_record[] = {
   1329     // Result of RST
   1330     {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
   1331     // Starting continuation
   1332     {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()},
   1333     // Error because file isn't there.
   1334     {DownloadItem::INTERRUPTED, 0},
   1335     // Restart.
   1336     {DownloadItem::IN_PROGRESS, 0},
   1337     // Completion.
   1338     {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
   1339   };
   1340 
   1341   recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
   1342 }
   1343 
   1344 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithFileInitError) {
   1345   base::CommandLine::ForCurrentProcess()->AppendSwitch(
   1346       switches::kEnableDownloadResumption);
   1347   base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
   1348   GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file));
   1349 
   1350   // Setup the error injector.
   1351   scoped_refptr<TestFileErrorInjector> injector(
   1352       TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
   1353 
   1354   TestFileErrorInjector::FileErrorInfo err = {
   1355     url.spec(),
   1356     TestFileErrorInjector::FILE_OPERATION_INITIALIZE,
   1357     0,
   1358     DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
   1359   };
   1360   injector->AddError(err);
   1361   injector->InjectErrors();
   1362 
   1363   // Start and watch for interrupt.
   1364   scoped_ptr<DownloadTestObserver> int_observer(
   1365       CreateInterruptedWaiter(shell(), 1));
   1366   DownloadItem* download(StartDownloadAndReturnItem(url));
   1367   int_observer->WaitForFinished();
   1368   ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState());
   1369   EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE,
   1370             download->GetLastReason());
   1371   EXPECT_EQ(0, download->GetReceivedBytes());
   1372   EXPECT_TRUE(download->GetFullPath().empty());
   1373   EXPECT_TRUE(download->GetTargetFilePath().empty());
   1374 
   1375   // We need to make sure that any cross-thread downloads communication has
   1376   // quiesced before clearing and injecting the new errors, as the
   1377   // InjectErrors() routine alters the currently in use download file
   1378   // factory, which is a file thread object.
   1379   RunAllPendingInMessageLoop(BrowserThread::FILE);
   1380   RunAllPendingInMessageLoop();
   1381 
   1382   // Clear the old errors list.
   1383   injector->ClearErrors();
   1384   injector->InjectErrors();
   1385 
   1386   // Resume and watch completion.
   1387   DownloadUpdatedObserver completion_observer(
   1388       download, base::Bind(DownloadCompleteFilter));
   1389   download->Resume();
   1390   completion_observer.WaitForEvent();
   1391   EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE);
   1392 }
   1393 
   1394 IN_PROC_BROWSER_TEST_F(DownloadContentTest,
   1395                        ResumeWithFileIntermediateRenameError) {
   1396   base::CommandLine::ForCurrentProcess()->AppendSwitch(
   1397       switches::kEnableDownloadResumption);
   1398   base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
   1399   GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file));
   1400 
   1401   // Setup the error injector.
   1402   scoped_refptr<TestFileErrorInjector> injector(
   1403       TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
   1404 
   1405   TestFileErrorInjector::FileErrorInfo err = {
   1406     url.spec(),
   1407     TestFileErrorInjector::FILE_OPERATION_RENAME_UNIQUIFY,
   1408     0,
   1409     DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
   1410   };
   1411   injector->AddError(err);
   1412   injector->InjectErrors();
   1413 
   1414   // Start and watch for interrupt.
   1415   scoped_ptr<DownloadTestObserver> int_observer(
   1416       CreateInterruptedWaiter(shell(), 1));
   1417   DownloadItem* download(StartDownloadAndReturnItem(url));
   1418   int_observer->WaitForFinished();
   1419   ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState());
   1420   EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE,
   1421             download->GetLastReason());
   1422   EXPECT_TRUE(download->GetFullPath().empty());
   1423   // Target path will have been set after file name determination. GetFullPath()
   1424   // being empty is sufficient to signal that filename determination needs to be
   1425   // redone.
   1426   EXPECT_FALSE(download->GetTargetFilePath().empty());
   1427 
   1428   // We need to make sure that any cross-thread downloads communication has
   1429   // quiesced before clearing and injecting the new errors, as the
   1430   // InjectErrors() routine alters the currently in use download file
   1431   // factory, which is a file thread object.
   1432   RunAllPendingInMessageLoop(BrowserThread::FILE);
   1433   RunAllPendingInMessageLoop();
   1434 
   1435   // Clear the old errors list.
   1436   injector->ClearErrors();
   1437   injector->InjectErrors();
   1438 
   1439   // Resume and watch completion.
   1440   DownloadUpdatedObserver completion_observer(
   1441       download, base::Bind(DownloadCompleteFilter));
   1442   download->Resume();
   1443   completion_observer.WaitForEvent();
   1444   EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE);
   1445 }
   1446 
   1447 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithFileFinalRenameError) {
   1448   base::CommandLine::ForCurrentProcess()->AppendSwitch(
   1449       switches::kEnableDownloadResumption);
   1450   base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
   1451   GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file));
   1452 
   1453   // Setup the error injector.
   1454   scoped_refptr<TestFileErrorInjector> injector(
   1455       TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
   1456 
   1457   DownloadManagerForShell(shell())->RemoveAllDownloads();
   1458   TestFileErrorInjector::FileErrorInfo err = {
   1459     url.spec(),
   1460     TestFileErrorInjector::FILE_OPERATION_RENAME_ANNOTATE,
   1461     0,
   1462     DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
   1463   };
   1464   injector->AddError(err);
   1465   injector->InjectErrors();
   1466 
   1467   // Start and watch for interrupt.
   1468   scoped_ptr<DownloadTestObserver> int_observer(
   1469       CreateInterruptedWaiter(shell(), 1));
   1470   DownloadItem* download(StartDownloadAndReturnItem(url));
   1471   int_observer->WaitForFinished();
   1472   ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState());
   1473   EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE,
   1474             download->GetLastReason());
   1475   EXPECT_TRUE(download->GetFullPath().empty());
   1476   // Target path should still be intact.
   1477   EXPECT_FALSE(download->GetTargetFilePath().empty());
   1478 
   1479   // We need to make sure that any cross-thread downloads communication has
   1480   // quiesced before clearing and injecting the new errors, as the
   1481   // InjectErrors() routine alters the currently in use download file
   1482   // factory, which is a file thread object.
   1483   RunAllPendingInMessageLoop(BrowserThread::FILE);
   1484   RunAllPendingInMessageLoop();
   1485 
   1486   // Clear the old errors list.
   1487   injector->ClearErrors();
   1488   injector->InjectErrors();
   1489 
   1490   // Resume and watch completion.
   1491   DownloadUpdatedObserver completion_observer(
   1492       download, base::Bind(DownloadCompleteFilter));
   1493   download->Resume();
   1494   completion_observer.WaitForEvent();
   1495   EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE);
   1496 }
   1497 
   1498 // An interrupted download should remove the intermediate file when it is
   1499 // cancelled.
   1500 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelInterruptedDownload) {
   1501   base::CommandLine::ForCurrentProcess()->AppendSwitch(
   1502       switches::kEnableDownloadResumption);
   1503   ASSERT_TRUE(test_server()->Start());
   1504 
   1505   GURL url1 = test_server()->GetURL(
   1506       base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
   1507                          GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
   1508 
   1509   DownloadItem* download(StartDownloadAndReturnItem(url1));
   1510   WaitForData(download, GetSafeBufferChunk());
   1511 
   1512   ReleaseRSTAndConfirmInterruptForResume(download);
   1513   ConfirmFileStatusForResume(
   1514       download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
   1515       base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
   1516 
   1517   base::FilePath intermediate_path(download->GetFullPath());
   1518   ASSERT_FALSE(intermediate_path.empty());
   1519   EXPECT_TRUE(base::PathExists(intermediate_path));
   1520 
   1521   download->Cancel(true /* user_cancel */);
   1522   RunAllPendingInMessageLoop(BrowserThread::FILE);
   1523   RunAllPendingInMessageLoop();
   1524 
   1525   // The intermediate file should now be gone.
   1526   EXPECT_FALSE(base::PathExists(intermediate_path));
   1527   EXPECT_TRUE(download->GetFullPath().empty());
   1528 }
   1529 
   1530 IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveDownload) {
   1531   base::CommandLine::ForCurrentProcess()->AppendSwitch(
   1532       switches::kEnableDownloadResumption);
   1533   ASSERT_TRUE(test_server()->Start());
   1534 
   1535   // An interrupted download should remove the intermediate file when it is
   1536   // removed.
   1537   {
   1538     GURL url1 = test_server()->GetURL(
   1539         base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
   1540                            GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
   1541 
   1542     DownloadItem* download(StartDownloadAndReturnItem(url1));
   1543     WaitForData(download, GetSafeBufferChunk());
   1544     ReleaseRSTAndConfirmInterruptForResume(download);
   1545     ConfirmFileStatusForResume(
   1546         download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
   1547         base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
   1548 
   1549     base::FilePath intermediate_path(download->GetFullPath());
   1550     ASSERT_FALSE(intermediate_path.empty());
   1551     EXPECT_TRUE(base::PathExists(intermediate_path));
   1552 
   1553     download->Remove();
   1554     RunAllPendingInMessageLoop(BrowserThread::FILE);
   1555     RunAllPendingInMessageLoop();
   1556 
   1557     // The intermediate file should now be gone.
   1558     EXPECT_FALSE(base::PathExists(intermediate_path));
   1559   }
   1560 
   1561   // A completed download shouldn't delete the downloaded file when it is
   1562   // removed.
   1563   {
   1564     // Start the second download and wait until it's done.
   1565     base::FilePath file2(FILE_PATH_LITERAL("download-test.lib"));
   1566     GURL url2(net::URLRequestMockHTTPJob::GetMockUrl(file2));
   1567     scoped_ptr<DownloadTestObserver> completion_observer(
   1568         CreateWaiter(shell(), 1));
   1569     DownloadItem* download(StartDownloadAndReturnItem(url2));
   1570     completion_observer->WaitForFinished();
   1571 
   1572     // The target path should exist.
   1573     base::FilePath target_path(download->GetTargetFilePath());
   1574     EXPECT_TRUE(base::PathExists(target_path));
   1575     download->Remove();
   1576     RunAllPendingInMessageLoop(BrowserThread::FILE);
   1577     RunAllPendingInMessageLoop();
   1578 
   1579     // The file should still exist.
   1580     EXPECT_TRUE(base::PathExists(target_path));
   1581   }
   1582 }
   1583 
   1584 IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveResumingDownload) {
   1585   SetupEnsureNoPendingDownloads();
   1586   base::CommandLine::ForCurrentProcess()->AppendSwitch(
   1587       switches::kEnableDownloadResumption);
   1588   ASSERT_TRUE(test_server()->Start());
   1589 
   1590   GURL url = test_server()->GetURL(
   1591       base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
   1592                          GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
   1593 
   1594   MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell()));
   1595   EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
   1596 
   1597   DownloadItem* download(StartDownloadAndReturnItem(url));
   1598   WaitForData(download, GetSafeBufferChunk());
   1599   ::testing::Mock::VerifyAndClearExpectations(&dm_observer);
   1600 
   1601   // Tell the server to send the RST and confirm the interrupt happens.
   1602   ReleaseRSTAndConfirmInterruptForResume(download);
   1603   ConfirmFileStatusForResume(
   1604       download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
   1605       base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
   1606 
   1607   base::FilePath intermediate_path(download->GetFullPath());
   1608   ASSERT_FALSE(intermediate_path.empty());
   1609   EXPECT_TRUE(base::PathExists(intermediate_path));
   1610 
   1611   // Resume and remove download. We expect only a single OnDownloadCreated()
   1612   // call, and that's for the second download created below.
   1613   EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
   1614   download->Resume();
   1615   download->Remove();
   1616 
   1617   // The intermediate file should now be gone.
   1618   RunAllPendingInMessageLoop(BrowserThread::FILE);
   1619   RunAllPendingInMessageLoop();
   1620   EXPECT_FALSE(base::PathExists(intermediate_path));
   1621 
   1622   // Start the second download and wait until it's done. The test server is
   1623   // single threaded. The response to this download request should follow the
   1624   // response to the previous resumption request.
   1625   GURL url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x"));
   1626   NavigateToURLAndWaitForDownload(shell(), url2, DownloadItem::COMPLETE);
   1627 
   1628   EXPECT_TRUE(EnsureNoPendingDownloads());
   1629 }
   1630 
   1631 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelResumingDownload) {
   1632   SetupEnsureNoPendingDownloads();
   1633   base::CommandLine::ForCurrentProcess()->AppendSwitch(
   1634       switches::kEnableDownloadResumption);
   1635   ASSERT_TRUE(test_server()->Start());
   1636 
   1637   GURL url = test_server()->GetURL(
   1638       base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
   1639                          GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
   1640 
   1641   MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell()));
   1642   EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
   1643 
   1644   DownloadItem* download(StartDownloadAndReturnItem(url));
   1645   WaitForData(download, GetSafeBufferChunk());
   1646   ::testing::Mock::VerifyAndClearExpectations(&dm_observer);
   1647 
   1648   // Tell the server to send the RST and confirm the interrupt happens.
   1649   ReleaseRSTAndConfirmInterruptForResume(download);
   1650   ConfirmFileStatusForResume(
   1651       download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
   1652       base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
   1653 
   1654   base::FilePath intermediate_path(download->GetFullPath());
   1655   ASSERT_FALSE(intermediate_path.empty());
   1656   EXPECT_TRUE(base::PathExists(intermediate_path));
   1657 
   1658   // Resume and cancel download. We expect only a single OnDownloadCreated()
   1659   // call, and that's for the second download created below.
   1660   EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
   1661   download->Resume();
   1662   download->Cancel(true);
   1663 
   1664   // The intermediate file should now be gone.
   1665   RunAllPendingInMessageLoop(BrowserThread::FILE);
   1666   RunAllPendingInMessageLoop();
   1667   EXPECT_FALSE(base::PathExists(intermediate_path));
   1668   EXPECT_TRUE(download->GetFullPath().empty());
   1669 
   1670   // Start the second download and wait until it's done. The test server is
   1671   // single threaded. The response to this download request should follow the
   1672   // response to the previous resumption request.
   1673   GURL url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x"));
   1674   NavigateToURLAndWaitForDownload(shell(), url2, DownloadItem::COMPLETE);
   1675 
   1676   EXPECT_TRUE(EnsureNoPendingDownloads());
   1677 }
   1678 
   1679 // Check that the cookie policy is correctly updated when downloading a file
   1680 // that redirects cross origin.
   1681 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CookiePolicy) {
   1682   ASSERT_TRUE(test_server()->Start());
   1683   net::HostPortPair host_port = test_server()->host_port_pair();
   1684   DCHECK_EQ(host_port.host(), std::string("127.0.0.1"));
   1685 
   1686   // Block third-party cookies.
   1687   ShellNetworkDelegate::SetAcceptAllCookies(false);
   1688 
   1689   // |url| redirects to a different origin |download| which tries to set a
   1690   // cookie.
   1691   std::string download(base::StringPrintf(
   1692       "http://localhost:%d/set-cookie?A=B", host_port.port()));
   1693   GURL url(test_server()->GetURL("server-redirect?" + download));
   1694 
   1695   // Download the file.
   1696   SetupEnsureNoPendingDownloads();
   1697   scoped_ptr<DownloadUrlParameters> dl_params(
   1698       DownloadUrlParameters::FromWebContents(shell()->web_contents(), url));
   1699   scoped_ptr<DownloadTestObserver> observer(CreateWaiter(shell(), 1));
   1700   DownloadManagerForShell(shell())->DownloadUrl(dl_params.Pass());
   1701   observer->WaitForFinished();
   1702 
   1703   // Get the important info from other threads and check it.
   1704   EXPECT_TRUE(EnsureNoPendingDownloads());
   1705 
   1706   std::vector<DownloadItem*> downloads;
   1707   DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
   1708   ASSERT_EQ(1u, downloads.size());
   1709   ASSERT_EQ(DownloadItem::COMPLETE, downloads[0]->GetState());
   1710 
   1711   // Check that the cookies were correctly set.
   1712   EXPECT_EQ("A=B",
   1713             content::GetCookies(shell()->web_contents()->GetBrowserContext(),
   1714                                 GURL(download)));
   1715 }
   1716 
   1717 // A filename suggestion specified via a @download attribute should not be
   1718 // effective if the final download URL is in another origin from the original
   1719 // download URL.
   1720 IN_PROC_BROWSER_TEST_F(DownloadContentTest,
   1721                        DownloadAttributeCrossOriginRedirect) {
   1722   EmbeddedTestServer origin_one;
   1723   EmbeddedTestServer origin_two;
   1724   ASSERT_TRUE(origin_one.InitializeAndWaitUntilReady());
   1725   ASSERT_TRUE(origin_two.InitializeAndWaitUntilReady());
   1726 
   1727   // The download-attribute.html page contains an anchor element whose href is
   1728   // set to the value of the query parameter (specified as |target| in the URL
   1729   // below). The suggested filename for the anchor is 'suggested-filename'. When
   1730   // the page is loaded, a script simulates a click on the anchor, triggering a
   1731   // download of the target URL.
   1732   //
   1733   // We construct two test servers; origin_one and origin_two. Once started, the
   1734   // server URLs will differ by the port number. Therefore they will be in
   1735   // different origins.
   1736   GURL download_url = origin_one.GetURL("/ping");
   1737   GURL referrer_url = origin_one.GetURL(
   1738       std::string("/download-attribute.html?target=") + download_url.spec());
   1739 
   1740   // <origin_one>/download-attribute.html initiates a download of
   1741   // <origin_one>/ping, which redirects to <origin_two>/download.
   1742   origin_one.ServeFilesFromDirectory(GetTestFilePath("download", ""));
   1743   origin_one.RegisterRequestHandler(
   1744       CreateRedirectHandler("/ping", origin_two.GetURL("/download")));
   1745   origin_two.RegisterRequestHandler(CreateBasicResponseHandler(
   1746       "/download", "application/octet-stream", "Hello"));
   1747 
   1748   NavigateToURLAndWaitForDownload(
   1749       shell(), referrer_url, DownloadItem::COMPLETE);
   1750 
   1751   std::vector<DownloadItem*> downloads;
   1752   DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
   1753   ASSERT_EQ(1u, downloads.size());
   1754 
   1755   EXPECT_EQ(FILE_PATH_LITERAL("download"),
   1756             downloads[0]->GetTargetFilePath().BaseName().value());
   1757   ASSERT_TRUE(origin_one.ShutdownAndWaitUntilComplete());
   1758   ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete());
   1759 }
   1760 
   1761 // A filename suggestion specified via a @download attribute should be effective
   1762 // if the final download URL is in the same origin as the initial download URL.
   1763 // Test that this holds even if there are cross origin redirects in the middle
   1764 // of the redirect chain.
   1765 IN_PROC_BROWSER_TEST_F(DownloadContentTest,
   1766                        DownloadAttributeSameOriginRedirect) {
   1767   EmbeddedTestServer origin_one;
   1768   EmbeddedTestServer origin_two;
   1769   ASSERT_TRUE(origin_one.InitializeAndWaitUntilReady());
   1770   ASSERT_TRUE(origin_two.InitializeAndWaitUntilReady());
   1771 
   1772   // The download-attribute.html page contains an anchor element whose href is
   1773   // set to the value of the query parameter (specified as |target| in the URL
   1774   // below). The suggested filename for the anchor is 'suggested-filename'. When
   1775   // the page is loaded, a script simulates a click on the anchor, triggering a
   1776   // download of the target URL.
   1777   //
   1778   // We construct two test servers; origin_one and origin_two. Once started, the
   1779   // server URLs will differ by the port number. Therefore they will be in
   1780   // different origins.
   1781   GURL download_url = origin_one.GetURL("/ping");
   1782   GURL referrer_url = origin_one.GetURL(
   1783       std::string("/download-attribute.html?target=") + download_url.spec());
   1784   origin_one.ServeFilesFromDirectory(GetTestFilePath("download", ""));
   1785 
   1786   // <origin_one>/download-attribute.html initiates a download of
   1787   // <origin_one>/ping, which redirects to <origin_two>/pong, and then finally
   1788   // to <origin_one>/download.
   1789   origin_one.RegisterRequestHandler(
   1790       CreateRedirectHandler("/ping", origin_two.GetURL("/pong")));
   1791   origin_two.RegisterRequestHandler(
   1792       CreateRedirectHandler("/pong", origin_one.GetURL("/download")));
   1793   origin_one.RegisterRequestHandler(CreateBasicResponseHandler(
   1794       "/download", "application/octet-stream", "Hello"));
   1795 
   1796   NavigateToURLAndWaitForDownload(
   1797       shell(), referrer_url, DownloadItem::COMPLETE);
   1798 
   1799   std::vector<DownloadItem*> downloads;
   1800   DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
   1801   ASSERT_EQ(1u, downloads.size());
   1802 
   1803   EXPECT_EQ(FILE_PATH_LITERAL("suggested-filename"),
   1804             downloads[0]->GetTargetFilePath().BaseName().value());
   1805   ASSERT_TRUE(origin_one.ShutdownAndWaitUntilComplete());
   1806   ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete());
   1807 }
   1808 
   1809 // The file empty.bin is served with a MIME type of application/octet-stream.
   1810 // The content body is empty. Make sure this case is handled properly and we
   1811 // don't regress on http://crbug.com/320394.
   1812 IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadGZipWithNoContent) {
   1813   EmbeddedTestServer test_server;
   1814   ASSERT_TRUE(test_server.InitializeAndWaitUntilReady());
   1815 
   1816   GURL url = test_server.GetURL("/empty.bin");
   1817   test_server.ServeFilesFromDirectory(GetTestFilePath("download", ""));
   1818 
   1819   NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE);
   1820   // That's it. This should work without crashing.
   1821 }
   1822 
   1823 }  // namespace content
   1824