// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file contains download browser tests that are known to be runnable
// in a pure content context.  Over time tests should be migrated here.

#include "base/command_line.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/byte_stream.h"
#include "content/browser/download/download_file_factory.h"
#include "content/browser/download/download_file_impl.h"
#include "content/browser/download/download_item_impl.h"
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/download/download_resource_handler.h"
#include "content/browser/plugin_service_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/power_save_blocker.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/webplugininfo.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/download_test_observer.h"
#include "content/public/test/test_file_error_injector.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_browser_context.h"
#include "content/shell/browser/shell_download_manager_delegate.h"
#include "content/shell/browser/shell_network_delegate.h"
#include "content/test/content_browser_test.h"
#include "content/test/content_browser_test_utils.h"
#include "content/test/net/url_request_mock_http_job.h"
#include "content/test/net/url_request_slow_download_job.h"
#include "net/test/spawned_test_server/spawned_test_server.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"

using ::testing::_;
using ::testing::AllOf;
using ::testing::Field;
using ::testing::InSequence;
using ::testing::Property;
using ::testing::Return;
using ::testing::StrictMock;

namespace content {

namespace {

class MockDownloadItemObserver : public DownloadItem::Observer {
 public:
  MockDownloadItemObserver() {}
  virtual ~MockDownloadItemObserver() {}

  MOCK_METHOD1(OnDownloadUpdated, void(DownloadItem*));
  MOCK_METHOD1(OnDownloadOpened, void(DownloadItem*));
  MOCK_METHOD1(OnDownloadRemoved, void(DownloadItem*));
  MOCK_METHOD1(OnDownloadDestroyed, void(DownloadItem*));
};

class MockDownloadManagerObserver : public DownloadManager::Observer {
 public:
  MockDownloadManagerObserver(DownloadManager* manager) {
    manager_ = manager;
    manager->AddObserver(this);
  }
  virtual ~MockDownloadManagerObserver() {
    if (manager_)
      manager_->RemoveObserver(this);
  }

  MOCK_METHOD2(OnDownloadCreated, void(DownloadManager*, DownloadItem*));
  MOCK_METHOD1(ModelChanged, void(DownloadManager*));
  void ManagerGoingDown(DownloadManager* manager) {
    DCHECK_EQ(manager_, manager);
    MockManagerGoingDown(manager);

    manager_->RemoveObserver(this);
    manager_ = NULL;
  }

  MOCK_METHOD1(MockManagerGoingDown, void(DownloadManager*));
 private:
  DownloadManager* manager_;
};

class DownloadFileWithDelayFactory;

static DownloadManagerImpl* DownloadManagerForShell(Shell* shell) {
  // We're in a content_browsertest; we know that the DownloadManager
  // is a DownloadManagerImpl.
  return static_cast<DownloadManagerImpl*>(
      BrowserContext::GetDownloadManager(
          shell->web_contents()->GetBrowserContext()));
}

class DownloadFileWithDelay : public DownloadFileImpl {
 public:
  DownloadFileWithDelay(
      scoped_ptr<DownloadSaveInfo> save_info,
      const base::FilePath& default_download_directory,
      const GURL& url,
      const GURL& referrer_url,
      bool calculate_hash,
      scoped_ptr<ByteStreamReader> stream,
      const net::BoundNetLog& bound_net_log,
      scoped_ptr<PowerSaveBlocker> power_save_blocker,
      base::WeakPtr<DownloadDestinationObserver> observer,
      base::WeakPtr<DownloadFileWithDelayFactory> owner);

  virtual ~DownloadFileWithDelay();

  // Wraps DownloadFileImpl::Rename* and intercepts the return callback,
  // storing it in the factory that produced this object for later
  // retrieval.
  virtual void RenameAndUniquify(
      const base::FilePath& full_path,
      const RenameCompletionCallback& callback) OVERRIDE;
  virtual void RenameAndAnnotate(
      const base::FilePath& full_path,
      const RenameCompletionCallback& callback) OVERRIDE;

 private:
  static void RenameCallbackWrapper(
      const base::WeakPtr<DownloadFileWithDelayFactory>& factory,
      const RenameCompletionCallback& original_callback,
      DownloadInterruptReason reason,
      const base::FilePath& path);

  // This variable may only be read on the FILE thread, and may only be
  // indirected through (e.g. methods on DownloadFileWithDelayFactory called)
  // on the UI thread.  This is because after construction,
  // DownloadFileWithDelay lives on the file thread, but
  // DownloadFileWithDelayFactory is purely a UI thread object.
  base::WeakPtr<DownloadFileWithDelayFactory> owner_;

  DISALLOW_COPY_AND_ASSIGN(DownloadFileWithDelay);
};

// All routines on this class must be called on the UI thread.
class DownloadFileWithDelayFactory : public DownloadFileFactory {
 public:
  DownloadFileWithDelayFactory();
  virtual ~DownloadFileWithDelayFactory();

  // DownloadFileFactory interface.
  virtual DownloadFile* CreateFile(
      scoped_ptr<DownloadSaveInfo> save_info,
      const base::FilePath& default_download_directory,
      const GURL& url,
      const GURL& referrer_url,
      bool calculate_hash,
      scoped_ptr<ByteStreamReader> stream,
      const net::BoundNetLog& bound_net_log,
      base::WeakPtr<DownloadDestinationObserver> observer) OVERRIDE;

  void AddRenameCallback(base::Closure callback);
  void GetAllRenameCallbacks(std::vector<base::Closure>* results);

  // Do not return until GetAllRenameCallbacks() will return a non-empty list.
  void WaitForSomeCallback();

 private:
  base::WeakPtrFactory<DownloadFileWithDelayFactory> weak_ptr_factory_;
  std::vector<base::Closure> rename_callbacks_;
  bool waiting_;

  DISALLOW_COPY_AND_ASSIGN(DownloadFileWithDelayFactory);
};

DownloadFileWithDelay::DownloadFileWithDelay(
    scoped_ptr<DownloadSaveInfo> save_info,
    const base::FilePath& default_download_directory,
    const GURL& url,
    const GURL& referrer_url,
    bool calculate_hash,
    scoped_ptr<ByteStreamReader> stream,
    const net::BoundNetLog& bound_net_log,
    scoped_ptr<PowerSaveBlocker> power_save_blocker,
    base::WeakPtr<DownloadDestinationObserver> observer,
    base::WeakPtr<DownloadFileWithDelayFactory> owner)
    : DownloadFileImpl(
        save_info.Pass(), default_download_directory, url, referrer_url,
        calculate_hash, stream.Pass(), bound_net_log,
        power_save_blocker.Pass(), observer),
      owner_(owner) {}

DownloadFileWithDelay::~DownloadFileWithDelay() {}

void DownloadFileWithDelay::RenameAndUniquify(
    const base::FilePath& full_path,
    const RenameCompletionCallback& callback) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  DownloadFileImpl::RenameAndUniquify(
      full_path, base::Bind(DownloadFileWithDelay::RenameCallbackWrapper,
                            owner_, callback));
}

void DownloadFileWithDelay::RenameAndAnnotate(
    const base::FilePath& full_path, const RenameCompletionCallback& callback) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
  DownloadFileImpl::RenameAndAnnotate(
      full_path, base::Bind(DownloadFileWithDelay::RenameCallbackWrapper,
                            owner_, callback));
}

// static
void DownloadFileWithDelay::RenameCallbackWrapper(
    const base::WeakPtr<DownloadFileWithDelayFactory>& factory,
    const RenameCompletionCallback& original_callback,
    DownloadInterruptReason reason,
    const base::FilePath& path) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  if (!factory)
    return;
  factory->AddRenameCallback(base::Bind(original_callback, reason, path));
}

DownloadFileWithDelayFactory::DownloadFileWithDelayFactory()
    : weak_ptr_factory_(this),
      waiting_(false) {}
DownloadFileWithDelayFactory::~DownloadFileWithDelayFactory() {}

DownloadFile* DownloadFileWithDelayFactory::CreateFile(
    scoped_ptr<DownloadSaveInfo> save_info,
    const base::FilePath& default_download_directory,
    const GURL& url,
    const GURL& referrer_url,
    bool calculate_hash,
    scoped_ptr<ByteStreamReader> stream,
    const net::BoundNetLog& bound_net_log,
    base::WeakPtr<DownloadDestinationObserver> observer) {
  scoped_ptr<PowerSaveBlocker> psb(
      PowerSaveBlocker::Create(
          PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
          "Download in progress"));
  return new DownloadFileWithDelay(
      save_info.Pass(), default_download_directory, url, referrer_url,
      calculate_hash, stream.Pass(), bound_net_log,
      psb.Pass(), observer, weak_ptr_factory_.GetWeakPtr());
}

void DownloadFileWithDelayFactory::AddRenameCallback(base::Closure callback) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  rename_callbacks_.push_back(callback);
  if (waiting_)
    base::MessageLoopForUI::current()->Quit();
}

void DownloadFileWithDelayFactory::GetAllRenameCallbacks(
    std::vector<base::Closure>* results) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  results->swap(rename_callbacks_);
}

void DownloadFileWithDelayFactory::WaitForSomeCallback() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  if (rename_callbacks_.empty()) {
    waiting_ = true;
    RunMessageLoop();
    waiting_ = false;
  }
}

class CountingDownloadFile : public DownloadFileImpl {
 public:
  CountingDownloadFile(
    scoped_ptr<DownloadSaveInfo> save_info,
    const base::FilePath& default_downloads_directory,
    const GURL& url,
    const GURL& referrer_url,
    bool calculate_hash,
    scoped_ptr<ByteStreamReader> stream,
    const net::BoundNetLog& bound_net_log,
    scoped_ptr<PowerSaveBlocker> power_save_blocker,
    base::WeakPtr<DownloadDestinationObserver> observer)
      : DownloadFileImpl(save_info.Pass(), default_downloads_directory,
                         url, referrer_url, calculate_hash,
                         stream.Pass(), bound_net_log,
                         power_save_blocker.Pass(), observer) {}

  virtual ~CountingDownloadFile() {
    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
    active_files_--;
  }

  virtual void Initialize(const InitializeCallback& callback) OVERRIDE {
    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
    active_files_++;
    return DownloadFileImpl::Initialize(callback);
  }

  static void GetNumberActiveFiles(int* result) {
    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
    *result = active_files_;
  }

  // Can be called on any thread, and will block (running message loop)
  // until data is returned.
  static int GetNumberActiveFilesFromFileThread() {
    int result = -1;
    BrowserThread::PostTaskAndReply(
        BrowserThread::FILE,
        FROM_HERE,
        base::Bind(&CountingDownloadFile::GetNumberActiveFiles, &result),
        base::MessageLoop::current()->QuitClosure());
    base::MessageLoop::current()->Run();
    DCHECK_NE(-1, result);
    return result;
  }

 private:
  static int active_files_;
};

int CountingDownloadFile::active_files_ = 0;

class CountingDownloadFileFactory : public DownloadFileFactory {
 public:
  CountingDownloadFileFactory() {}
  virtual ~CountingDownloadFileFactory() {}

  // DownloadFileFactory interface.
  virtual DownloadFile* CreateFile(
    scoped_ptr<DownloadSaveInfo> save_info,
    const base::FilePath& default_downloads_directory,
    const GURL& url,
    const GURL& referrer_url,
    bool calculate_hash,
    scoped_ptr<ByteStreamReader> stream,
    const net::BoundNetLog& bound_net_log,
    base::WeakPtr<DownloadDestinationObserver> observer) OVERRIDE {
    scoped_ptr<PowerSaveBlocker> psb(
        PowerSaveBlocker::Create(
            PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
            "Download in progress"));
    return new CountingDownloadFile(
        save_info.Pass(), default_downloads_directory, url, referrer_url,
        calculate_hash, stream.Pass(), bound_net_log,
        psb.Pass(), observer);
  }
};

class TestShellDownloadManagerDelegate : public ShellDownloadManagerDelegate {
 public:
  TestShellDownloadManagerDelegate()
      : delay_download_open_(false) {}

  virtual bool ShouldOpenDownload(
      DownloadItem* item,
      const DownloadOpenDelayedCallback& callback) OVERRIDE {
    if (delay_download_open_) {
      delayed_callbacks_.push_back(callback);
      return false;
    }
    return true;
  }

  void SetDelayedOpen(bool delay) {
    delay_download_open_ = delay;
  }

  void GetDelayedCallbacks(
      std::vector<DownloadOpenDelayedCallback>* callbacks) {
    callbacks->swap(delayed_callbacks_);
  }
 private:
  virtual ~TestShellDownloadManagerDelegate() {}

  bool delay_download_open_;
  std::vector<DownloadOpenDelayedCallback> delayed_callbacks_;
};

// Record all state transitions and byte counts on the observed download.
class RecordingDownloadObserver : DownloadItem::Observer {
 public:
  struct RecordStruct {
    DownloadItem::DownloadState state;
    int bytes_received;
  };

  typedef std::vector<RecordStruct> RecordVector;

  RecordingDownloadObserver(DownloadItem* download)
      : download_(download) {
    last_state_.state = download->GetState();
    last_state_.bytes_received = download->GetReceivedBytes();
    download_->AddObserver(this);
  }

  virtual ~RecordingDownloadObserver() {
    RemoveObserver();
  }

  void CompareToExpectedRecord(const RecordStruct expected[], size_t size) {
    EXPECT_EQ(size, record_.size());
    int min = size > record_.size() ? record_.size() : size;
    for (int i = 0; i < min; ++i) {
      EXPECT_EQ(expected[i].state, record_[i].state) << "Iteration " << i;
      EXPECT_EQ(expected[i].bytes_received, record_[i].bytes_received)
          << "Iteration " << i;
    }
  }

 private:
  virtual void OnDownloadUpdated(DownloadItem* download) OVERRIDE {
    DCHECK_EQ(download_, download);
    DownloadItem::DownloadState state = download->GetState();
    int bytes = download->GetReceivedBytes();
    if (last_state_.state != state || last_state_.bytes_received > bytes) {
      last_state_.state = state;
      last_state_.bytes_received = bytes;
      record_.push_back(last_state_);
    }
  }

  virtual void OnDownloadDestroyed(DownloadItem* download) OVERRIDE {
    DCHECK_EQ(download_, download);
    RemoveObserver();
  }

  void RemoveObserver() {
    if (download_) {
      download_->RemoveObserver(this);
      download_ = NULL;
    }
  }

  DownloadItem* download_;
  RecordStruct last_state_;
  RecordVector record_;
};

// Get the next created download.
class DownloadCreateObserver : DownloadManager::Observer {
 public:
  DownloadCreateObserver(DownloadManager* manager)
      : manager_(manager),
        item_(NULL),
        waiting_(false) {
    manager_->AddObserver(this);
  }

  virtual ~DownloadCreateObserver() {
    if (manager_)
      manager_->RemoveObserver(this);
    manager_ = NULL;
  }

  virtual void ManagerGoingDown(DownloadManager* manager) OVERRIDE {
    DCHECK_EQ(manager_, manager);
    manager_->RemoveObserver(this);
    manager_ = NULL;
  }

  virtual void OnDownloadCreated(DownloadManager* manager,
                                 DownloadItem* download) OVERRIDE {
    if (!item_)
      item_ = download;

    if (waiting_)
      base::MessageLoopForUI::current()->Quit();
  }

  DownloadItem* WaitForFinished() {
    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    if (!item_) {
      waiting_ = true;
      RunMessageLoop();
      waiting_ = false;
    }
    return item_;
  }

 private:
  DownloadManager* manager_;
  DownloadItem* item_;
  bool waiting_;
};


// Filter for waiting for a certain number of bytes.
bool DataReceivedFilter(int number_of_bytes, DownloadItem* download) {
  return download->GetReceivedBytes() >= number_of_bytes;
}

// Filter for download completion.
bool DownloadCompleteFilter(DownloadItem* download) {
  return download->GetState() == DownloadItem::COMPLETE;
}

// Filter for saving the size of the download when the first IN_PROGRESS
// is hit.
bool InitialSizeFilter(int* download_size, DownloadItem* download) {
  if (download->GetState() != DownloadItem::IN_PROGRESS)
    return false;

  *download_size = download->GetReceivedBytes();
  return true;
}

}  // namespace

class DownloadContentTest : public ContentBrowserTest {
 protected:
  // An initial send from a website of at least this size will not be
  // help up by buffering in the underlying downloads ByteStream data
  // transfer.  This is important because on resumption tests we wait
  // until we've gotten the data we expect before allowing the test server
  // to send its reset, to get around hard close semantics on the Windows
  // socket layer implementation.
  int GetSafeBufferChunk() const {
    return (DownloadResourceHandler::kDownloadByteStreamSize /
       ByteStreamWriter::kFractionBufferBeforeSending) + 1;
  }

  virtual void SetUpOnMainThread() OVERRIDE {
    ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir());

    TestShellDownloadManagerDelegate* delegate =
        new TestShellDownloadManagerDelegate();
    delegate->SetDownloadBehaviorForTesting(downloads_directory_.path());
    DownloadManager* manager = DownloadManagerForShell(shell());
    manager->SetDelegate(delegate);
    delegate->SetDownloadManager(manager);

    BrowserThread::PostTask(
        BrowserThread::IO, FROM_HERE,
        base::Bind(&URLRequestSlowDownloadJob::AddUrlHandler));
    base::FilePath mock_base(GetTestFilePath("download", ""));
    BrowserThread::PostTask(
        BrowserThread::IO, FROM_HERE,
        base::Bind(&URLRequestMockHTTPJob::AddUrlHandler, mock_base));
  }

  TestShellDownloadManagerDelegate* GetDownloadManagerDelegate(
      DownloadManager* manager) {
    return static_cast<TestShellDownloadManagerDelegate*>(
        manager->GetDelegate());
  }

  // Create a DownloadTestObserverTerminal that will wait for the
  // specified number of downloads to finish.
  DownloadTestObserver* CreateWaiter(
      Shell* shell, int num_downloads) {
    DownloadManager* download_manager = DownloadManagerForShell(shell);
    return new DownloadTestObserverTerminal(download_manager, num_downloads,
        DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
  }

  // Create a DownloadTestObserverInProgress that will wait for the
  // specified number of downloads to start.
  DownloadCreateObserver* CreateInProgressWaiter(
      Shell* shell, int num_downloads) {
    DownloadManager* download_manager = DownloadManagerForShell(shell);
    return new DownloadCreateObserver(download_manager);
  }

  DownloadTestObserver* CreateInterruptedWaiter(
      Shell* shell, int num_downloads) {
    DownloadManager* download_manager = DownloadManagerForShell(shell);
    return new DownloadTestObserverInterrupted(download_manager, num_downloads,
        DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
  }

  // Note: Cannot be used with other alternative DownloadFileFactorys
  void SetupEnsureNoPendingDownloads() {
    DownloadManagerForShell(shell())->SetDownloadFileFactoryForTesting(
        scoped_ptr<DownloadFileFactory>(
            new CountingDownloadFileFactory()).Pass());
  }

  bool EnsureNoPendingDownloads() {
    bool result = true;
    BrowserThread::PostTask(
        BrowserThread::IO, FROM_HERE,
        base::Bind(&EnsureNoPendingDownloadJobsOnIO, &result));
    base::MessageLoop::current()->Run();
    return result &&
           (CountingDownloadFile::GetNumberActiveFilesFromFileThread() == 0);
  }

  void DownloadAndWait(Shell* shell, const GURL& url,
                       DownloadItem::DownloadState expected_terminal_state) {
    scoped_ptr<DownloadTestObserver> observer(CreateWaiter(shell, 1));
    NavigateToURL(shell, url);
    observer->WaitForFinished();
    EXPECT_EQ(1u, observer->NumDownloadsSeenInState(expected_terminal_state));
  }

  // Checks that |path| is has |file_size| bytes, and matches the |value|
  // string.
  bool VerifyFile(const base::FilePath& path,
                  const std::string& value,
                  const int64 file_size) {
    std::string file_contents;

    bool read = base::ReadFileToString(path, &file_contents);
    EXPECT_TRUE(read) << "Failed reading file: " << path.value() << std::endl;
    if (!read)
      return false;  // Couldn't read the file.

    // Note: we don't handle really large files (more than size_t can hold)
    // so we will fail in that case.
    size_t expected_size = static_cast<size_t>(file_size);

    // Check the size.
    EXPECT_EQ(expected_size, file_contents.size());
    if (expected_size != file_contents.size())
      return false;

    // Check the contents.
    EXPECT_EQ(value, file_contents);
    if (memcmp(file_contents.c_str(), value.c_str(), expected_size) != 0)
      return false;

    return true;
  }

  // Start a download and return the item.
  DownloadItem* StartDownloadAndReturnItem(GURL url) {
    scoped_ptr<DownloadCreateObserver> observer(
        CreateInProgressWaiter(shell(), 1));
    NavigateToURL(shell(), url);
    observer->WaitForFinished();
    std::vector<DownloadItem*> downloads;
    DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
    EXPECT_EQ(1u, downloads.size());
    if (1u != downloads.size())
      return NULL;
    return downloads[0];
  }

  // Wait for data
  void WaitForData(DownloadItem* download, int size) {
    DownloadUpdatedObserver data_observer(
        download, base::Bind(&DataReceivedFilter, size));
    data_observer.WaitForEvent();
    ASSERT_EQ(size, download->GetReceivedBytes());
    ASSERT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
  }

  // Tell the test server to release a pending RST and confirm
  // that the interrupt is received properly (for download resumption
  // testing).
  void ReleaseRSTAndConfirmInterruptForResume(DownloadItem* download) {
    scoped_ptr<DownloadTestObserver> rst_observer(
        CreateInterruptedWaiter(shell(), 1));
    NavigateToURL(shell(), test_server()->GetURL("download-finish"));
    rst_observer->WaitForFinished();
    EXPECT_EQ(DownloadItem::INTERRUPTED, download->GetState());
  }

  // Confirm file status expected for the given location in a stream
  // provided by the resume test server.
  void ConfirmFileStatusForResume(
      DownloadItem* download, bool file_exists,
      int received_bytes, int total_bytes,
      const base::FilePath& expected_filename) {
    // expected_filename is only known if the file exists.
    ASSERT_EQ(file_exists, !expected_filename.empty());
    EXPECT_EQ(received_bytes, download->GetReceivedBytes());
    EXPECT_EQ(total_bytes, download->GetTotalBytes());
    EXPECT_EQ(expected_filename.value(),
              download->GetFullPath().BaseName().value());
    EXPECT_EQ(file_exists,
              (!download->GetFullPath().empty() &&
               base::PathExists(download->GetFullPath())));

    if (file_exists) {
      std::string file_contents;
      EXPECT_TRUE(base::ReadFileToString(
          download->GetFullPath(), &file_contents));

      ASSERT_EQ(static_cast<size_t>(received_bytes), file_contents.size());
      for (int i = 0; i < received_bytes; ++i) {
        EXPECT_EQ(static_cast<char>((i * 2 + 15) % 256), file_contents[i])
            << "File contents diverged at position " << i
            << " for " << expected_filename.value();

        if (static_cast<char>((i * 2 + 15) % 256) != file_contents[i])
          return;
      }
    }
  }

 private:
  static void EnsureNoPendingDownloadJobsOnIO(bool* result) {
    if (URLRequestSlowDownloadJob::NumberOutstandingRequests())
      *result = false;
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure());
  }

  // Location of the downloads directory for these tests
  base::ScopedTempDir downloads_directory_;
};

IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadCancelled) {
  SetupEnsureNoPendingDownloads();

  // Create a download, wait until it's started, and confirm
  // we're in the expected state.
  scoped_ptr<DownloadCreateObserver> observer(
      CreateInProgressWaiter(shell(), 1));
  NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl));
  observer->WaitForFinished();

  std::vector<DownloadItem*> downloads;
  DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
  ASSERT_EQ(1u, downloads.size());
  ASSERT_EQ(DownloadItem::IN_PROGRESS, downloads[0]->GetState());

  // Cancel the download and wait for download system quiesce.
  downloads[0]->Cancel(true);
  scoped_refptr<DownloadTestFlushObserver> flush_observer(
      new DownloadTestFlushObserver(DownloadManagerForShell(shell())));
  flush_observer->WaitForFlush();

  // Get the important info from other threads and check it.
  EXPECT_TRUE(EnsureNoPendingDownloads());
}

// Check that downloading multiple (in this case, 2) files does not result in
// corrupted files.
IN_PROC_BROWSER_TEST_F(DownloadContentTest, MultiDownload) {
  SetupEnsureNoPendingDownloads();

  // Create a download, wait until it's started, and confirm
  // we're in the expected state.
  scoped_ptr<DownloadCreateObserver> observer1(
      CreateInProgressWaiter(shell(), 1));
  NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl));
  observer1->WaitForFinished();

  std::vector<DownloadItem*> downloads;
  DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
  ASSERT_EQ(1u, downloads.size());
  ASSERT_EQ(DownloadItem::IN_PROGRESS, downloads[0]->GetState());
  DownloadItem* download1 = downloads[0];  // The only download.

  // Start the second download and wait until it's done.
  base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
  GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
  // Download the file and wait.
  DownloadAndWait(shell(), url, DownloadItem::COMPLETE);

  // Should now have 2 items on the manager.
  downloads.clear();
  DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
  ASSERT_EQ(2u, downloads.size());
  // We don't know the order of the downloads.
  DownloadItem* download2 = downloads[(download1 == downloads[0]) ? 1 : 0];

  ASSERT_EQ(DownloadItem::IN_PROGRESS, download1->GetState());
  ASSERT_EQ(DownloadItem::COMPLETE, download2->GetState());

  // Allow the first request to finish.
  scoped_ptr<DownloadTestObserver> observer2(CreateWaiter(shell(), 1));
  NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kFinishDownloadUrl));
  observer2->WaitForFinished();  // Wait for the third request.
  EXPECT_EQ(1u, observer2->NumDownloadsSeenInState(DownloadItem::COMPLETE));

  // Get the important info from other threads and check it.
  EXPECT_TRUE(EnsureNoPendingDownloads());

  // The |DownloadItem|s should now be done and have the final file names.
  // Verify that the files have the expected data and size.
  // |file1| should be full of '*'s, and |file2| should be the same as the
  // source file.
  base::FilePath file1(download1->GetTargetFilePath());
  size_t file_size1 = URLRequestSlowDownloadJob::kFirstDownloadSize +
                      URLRequestSlowDownloadJob::kSecondDownloadSize;
  std::string expected_contents(file_size1, '*');
  ASSERT_TRUE(VerifyFile(file1, expected_contents, file_size1));

  base::FilePath file2(download2->GetTargetFilePath());
  ASSERT_TRUE(base::ContentsEqual(
      file2, GetTestFilePath("download", "download-test.lib")));
}

#if defined(ENABLE_PLUGINS)
// Content served with a MIME type of application/octet-stream should be
// downloaded even when a plugin can be found that handles the file type.
IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadOctetStream) {
  const base::FilePath::CharType kTestFilePath[] =
      FILE_PATH_LITERAL("octet-stream.abc");
  const char kTestPluginName[] = "TestPlugin";
  const char kTestMimeType[] = "application/x-test-mime-type";
  const char kTestFileType[] = "abc";

  WebPluginInfo plugin_info;
  plugin_info.name = base::ASCIIToUTF16(kTestPluginName);
  plugin_info.mime_types.push_back(
      WebPluginMimeType(kTestMimeType, kTestFileType, ""));
  PluginServiceImpl::GetInstance()->RegisterInternalPlugin(plugin_info, false);

  // The following is served with a Content-Type of application/octet-stream.
  GURL url(URLRequestMockHTTPJob::GetMockUrl(base::FilePath(kTestFilePath)));
  DownloadAndWait(shell(), url, DownloadItem::COMPLETE);
}
#endif

// Try to cancel just before we release the download file, by delaying final
// rename callback.
IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelAtFinalRename) {
  // Setup new factory.
  DownloadFileWithDelayFactory* file_factory =
      new DownloadFileWithDelayFactory();
  DownloadManagerImpl* download_manager(DownloadManagerForShell(shell()));
  download_manager->SetDownloadFileFactoryForTesting(
      scoped_ptr<DownloadFileFactory>(file_factory).Pass());

  // Create a download
  base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
  NavigateToURL(shell(), URLRequestMockHTTPJob::GetMockUrl(file));

  // Wait until the first (intermediate file) rename and execute the callback.
  file_factory->WaitForSomeCallback();
  std::vector<base::Closure> callbacks;
  file_factory->GetAllRenameCallbacks(&callbacks);
  ASSERT_EQ(1u, callbacks.size());
  callbacks[0].Run();
  callbacks.clear();

  // Wait until the second (final) rename callback is posted.
  file_factory->WaitForSomeCallback();
  file_factory->GetAllRenameCallbacks(&callbacks);
  ASSERT_EQ(1u, callbacks.size());

  // Cancel it.
  std::vector<DownloadItem*> items;
  download_manager->GetAllDownloads(&items);
  ASSERT_EQ(1u, items.size());
  items[0]->Cancel(true);
  RunAllPendingInMessageLoop();

  // Check state.
  EXPECT_EQ(DownloadItem::CANCELLED, items[0]->GetState());

  // Run final rename callback.
  callbacks[0].Run();
  callbacks.clear();

  // Check state.
  EXPECT_EQ(DownloadItem::CANCELLED, items[0]->GetState());
}

// Try to cancel just after we release the download file, by delaying
// in ShouldOpenDownload.
IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelAtRelease) {
  DownloadManagerImpl* download_manager(DownloadManagerForShell(shell()));

  // Mark delegate for delayed open.
  GetDownloadManagerDelegate(download_manager)->SetDelayedOpen(true);

  // Setup new factory.
  DownloadFileWithDelayFactory* file_factory =
      new DownloadFileWithDelayFactory();
  download_manager->SetDownloadFileFactoryForTesting(
      scoped_ptr<DownloadFileFactory>(file_factory).Pass());

  // Create a download
  base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
  NavigateToURL(shell(), URLRequestMockHTTPJob::GetMockUrl(file));

  // Wait until the first (intermediate file) rename and execute the callback.
  file_factory->WaitForSomeCallback();
  std::vector<base::Closure> callbacks;
  file_factory->GetAllRenameCallbacks(&callbacks);
  ASSERT_EQ(1u, callbacks.size());
  callbacks[0].Run();
  callbacks.clear();

  // Wait until the second (final) rename callback is posted.
  file_factory->WaitForSomeCallback();
  file_factory->GetAllRenameCallbacks(&callbacks);
  ASSERT_EQ(1u, callbacks.size());

  // Call it.
  callbacks[0].Run();
  callbacks.clear();

  // Confirm download still IN_PROGRESS (internal state COMPLETING).
  std::vector<DownloadItem*> items;
  download_manager->GetAllDownloads(&items);
  EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());

  // Cancel the download; confirm cancel fails.
  ASSERT_EQ(1u, items.size());
  items[0]->Cancel(true);
  EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());

  // Need to complete open test.
  std::vector<DownloadOpenDelayedCallback> delayed_callbacks;
  GetDownloadManagerDelegate(download_manager)->GetDelayedCallbacks(
      &delayed_callbacks);
  ASSERT_EQ(1u, delayed_callbacks.size());
  delayed_callbacks[0].Run(true);

  // *Now* the download should be complete.
  EXPECT_EQ(DownloadItem::COMPLETE, items[0]->GetState());
}

// Try to shutdown with a download in progress to make sure shutdown path
// works properly.
IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownInProgress) {
  // Create a download that won't complete.
  scoped_ptr<DownloadCreateObserver> observer(
      CreateInProgressWaiter(shell(), 1));
  NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl));
  observer->WaitForFinished();

  // Get the item.
  std::vector<DownloadItem*> items;
  DownloadManagerForShell(shell())->GetAllDownloads(&items);
  ASSERT_EQ(1u, items.size());
  EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());

  // Shutdown the download manager and make sure we get the right
  // notifications in the right order.
  StrictMock<MockDownloadItemObserver> item_observer;
  items[0]->AddObserver(&item_observer);
  MockDownloadManagerObserver manager_observer(
      DownloadManagerForShell(shell()));
  // Don't care about ModelChanged() events.
  EXPECT_CALL(manager_observer, ModelChanged(_))
      .WillRepeatedly(Return());
  {
    InSequence notifications;

    EXPECT_CALL(manager_observer, MockManagerGoingDown(
        DownloadManagerForShell(shell())))
        .WillOnce(Return());
    EXPECT_CALL(item_observer, OnDownloadUpdated(
        AllOf(items[0],
              Property(&DownloadItem::GetState, DownloadItem::CANCELLED))))
        .WillOnce(Return());
    EXPECT_CALL(item_observer, OnDownloadDestroyed(items[0]))
        .WillOnce(Return());
  }
  DownloadManagerForShell(shell())->Shutdown();
  items.clear();
}

// Try to shutdown just after we release the download file, by delaying
// release.
IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownAtRelease) {
  DownloadManagerImpl* download_manager(DownloadManagerForShell(shell()));

  // Mark delegate for delayed open.
  GetDownloadManagerDelegate(download_manager)->SetDelayedOpen(true);

  // Setup new factory.
  DownloadFileWithDelayFactory* file_factory =
      new DownloadFileWithDelayFactory();
  download_manager->SetDownloadFileFactoryForTesting(
      scoped_ptr<DownloadFileFactory>(file_factory).Pass());

  // Create a download
  base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
  NavigateToURL(shell(), URLRequestMockHTTPJob::GetMockUrl(file));

  // Wait until the first (intermediate file) rename and execute the callback.
  file_factory->WaitForSomeCallback();
  std::vector<base::Closure> callbacks;
  file_factory->GetAllRenameCallbacks(&callbacks);
  ASSERT_EQ(1u, callbacks.size());
  callbacks[0].Run();
  callbacks.clear();

  // Wait until the second (final) rename callback is posted.
  file_factory->WaitForSomeCallback();
  file_factory->GetAllRenameCallbacks(&callbacks);
  ASSERT_EQ(1u, callbacks.size());

  // Call it.
  callbacks[0].Run();
  callbacks.clear();

  // Confirm download isn't complete yet.
  std::vector<DownloadItem*> items;
  DownloadManagerForShell(shell())->GetAllDownloads(&items);
  EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());

  // Cancel the download; confirm cancel fails anyway.
  ASSERT_EQ(1u, items.size());
  items[0]->Cancel(true);
  EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
  RunAllPendingInMessageLoop();
  EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());

  MockDownloadItemObserver observer;
  items[0]->AddObserver(&observer);
  EXPECT_CALL(observer, OnDownloadDestroyed(items[0]));

  // Shutdown the download manager.  Mostly this is confirming a lack of
  // crashes.
  DownloadManagerForShell(shell())->Shutdown();
}

IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeInterruptedDownload) {
  CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kEnableDownloadResumption);
  ASSERT_TRUE(test_server()->Start());

  GURL url = test_server()->GetURL(
      base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
                   GetSafeBufferChunk() * 3, GetSafeBufferChunk()));

  MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell()));
  EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);

  DownloadItem* download(StartDownloadAndReturnItem(url));
  WaitForData(download, GetSafeBufferChunk());
  ::testing::Mock::VerifyAndClearExpectations(&dm_observer);

  // Confirm resumption while in progress doesn't do anything.
  download->Resume();
  ASSERT_EQ(GetSafeBufferChunk(), download->GetReceivedBytes());
  ASSERT_EQ(DownloadItem::IN_PROGRESS, download->GetState());

  // Tell the server to send the RST and confirm the interrupt happens.
  ReleaseRSTAndConfirmInterruptForResume(download);
  ConfirmFileStatusForResume(
      download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
      base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));

  // Resume, confirming received bytes on resumption is correct.
  // Make sure no creation calls are included.
  EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(0);
  int initial_size = 0;
  DownloadUpdatedObserver initial_size_observer(
      download, base::Bind(&InitialSizeFilter, &initial_size));
  download->Resume();
  initial_size_observer.WaitForEvent();
  EXPECT_EQ(GetSafeBufferChunk(), initial_size);
  ::testing::Mock::VerifyAndClearExpectations(&dm_observer);

  // and wait for expected data.
  WaitForData(download, GetSafeBufferChunk() * 2);

  // Tell the server to send the RST and confirm the interrupt happens.
  ReleaseRSTAndConfirmInterruptForResume(download);
  ConfirmFileStatusForResume(
      download, true, GetSafeBufferChunk() * 2, GetSafeBufferChunk() * 3,
      base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));

  // Resume and wait for completion.
  DownloadUpdatedObserver completion_observer(
      download, base::Bind(DownloadCompleteFilter));
  download->Resume();
  completion_observer.WaitForEvent();

  ConfirmFileStatusForResume(
      download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
      base::FilePath(FILE_PATH_LITERAL("rangereset")));

  // Confirm resumption while complete doesn't do anything.
  download->Resume();
  ASSERT_EQ(GetSafeBufferChunk() * 3, download->GetReceivedBytes());
  ASSERT_EQ(DownloadItem::COMPLETE, download->GetState());
  RunAllPendingInMessageLoop();
  ASSERT_EQ(GetSafeBufferChunk() * 3, download->GetReceivedBytes());
  ASSERT_EQ(DownloadItem::COMPLETE, download->GetState());
}

// Confirm restart fallback happens if a range request is bounced.
IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeInterruptedDownloadNoRange) {
  CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kEnableDownloadResumption);
  ASSERT_TRUE(test_server()->Start());

  // Auto-restart if server doesn't handle ranges.
  GURL url = test_server()->GetURL(
      base::StringPrintf(
          // First download hits an RST, rest don't, no ranges.
          "rangereset?size=%d&rst_boundary=%d&"
          "token=NoRange&rst_limit=1&bounce_range",
          GetSafeBufferChunk() * 3, GetSafeBufferChunk()));

  // Start the download and wait for first data chunk.
  DownloadItem* download(StartDownloadAndReturnItem(url));
  WaitForData(download, GetSafeBufferChunk());

  RecordingDownloadObserver recorder(download);

  ReleaseRSTAndConfirmInterruptForResume(download);
  ConfirmFileStatusForResume(
      download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
      base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));

  DownloadUpdatedObserver completion_observer(
      download, base::Bind(DownloadCompleteFilter));
  download->Resume();
  completion_observer.WaitForEvent();

  ConfirmFileStatusForResume(
      download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
      base::FilePath(FILE_PATH_LITERAL("rangereset")));

  static const RecordingDownloadObserver::RecordStruct expected_record[] = {
    // Result of RST
    {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
    // Starting continuation
    {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()},
    // Notification of receiving whole file.
    {DownloadItem::IN_PROGRESS, 0},
    // Completion.
    {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
  };

  recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
}

// Confirm restart fallback happens if a precondition is failed.
IN_PROC_BROWSER_TEST_F(DownloadContentTest,
                       ResumeInterruptedDownloadBadPrecondition) {
  CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kEnableDownloadResumption);
  ASSERT_TRUE(test_server()->Start());

  GURL url = test_server()->GetURL(base::StringPrintf(
      // First download hits an RST, rest don't, precondition fail.
      "rangereset?size=%d&rst_boundary=%d&"
      "token=BadPrecondition&rst_limit=1&fail_precondition=2",
      GetSafeBufferChunk() * 3,
      GetSafeBufferChunk()));

  // Start the download and wait for first data chunk.
  DownloadItem* download(StartDownloadAndReturnItem(url));
  WaitForData(download, GetSafeBufferChunk());

  RecordingDownloadObserver recorder(download);

  ReleaseRSTAndConfirmInterruptForResume(download);
  ConfirmFileStatusForResume(
      download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
      base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
  EXPECT_EQ("BadPrecondition2", download->GetETag());

  DownloadUpdatedObserver completion_observer(
      download, base::Bind(DownloadCompleteFilter));
  download->Resume();
  completion_observer.WaitForEvent();

  ConfirmFileStatusForResume(
      download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
      base::FilePath(FILE_PATH_LITERAL("rangereset")));
  EXPECT_EQ("BadPrecondition0", download->GetETag());

  static const RecordingDownloadObserver::RecordStruct expected_record[] = {
    // Result of RST
    {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
    // Starting continuation
    {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()},
    // Server precondition fail.
    {DownloadItem::INTERRUPTED, 0},
    // Notification of successful restart.
    {DownloadItem::IN_PROGRESS, 0},
    // Completion.
    {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
  };

  recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
}

// Confirm we don't try to resume if we don't have a verifier.
IN_PROC_BROWSER_TEST_F(DownloadContentTest,
                       ResumeInterruptedDownloadNoVerifiers) {
  CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kEnableDownloadResumption);
  ASSERT_TRUE(test_server()->Start());

  GURL url = test_server()->GetURL(
      base::StringPrintf(
          // First download hits an RST, rest don't, no verifiers.
          "rangereset?size=%d&rst_boundary=%d&"
          "token=NoRange&rst_limit=1&no_verifiers",
          GetSafeBufferChunk() * 3, GetSafeBufferChunk()));

  // Start the download and wait for first data chunk.
  DownloadItem* download(StartDownloadAndReturnItem(url));
  WaitForData(download, GetSafeBufferChunk());

  RecordingDownloadObserver recorder(download);

  ReleaseRSTAndConfirmInterruptForResume(download);
  ConfirmFileStatusForResume(
      download, false, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
      base::FilePath());

  DownloadUpdatedObserver completion_observer(
      download, base::Bind(DownloadCompleteFilter));
  download->Resume();
  completion_observer.WaitForEvent();

  ConfirmFileStatusForResume(
      download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
      base::FilePath(FILE_PATH_LITERAL("rangereset")));

  static const RecordingDownloadObserver::RecordStruct expected_record[] = {
    // Result of RST
    {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
    // Restart for lack of verifiers
    {DownloadItem::IN_PROGRESS, 0},
    // Completion.
    {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
  };

  recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
}

IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithDeletedFile) {
  CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kEnableDownloadResumption);
  ASSERT_TRUE(test_server()->Start());

  GURL url = test_server()->GetURL(
      base::StringPrintf(
          // First download hits an RST, rest don't
          "rangereset?size=%d&rst_boundary=%d&"
          "token=NoRange&rst_limit=1",
          GetSafeBufferChunk() * 3, GetSafeBufferChunk()));

  // Start the download and wait for first data chunk.
  DownloadItem* download(StartDownloadAndReturnItem(url));
  WaitForData(download, GetSafeBufferChunk());

  RecordingDownloadObserver recorder(download);

  ReleaseRSTAndConfirmInterruptForResume(download);
  ConfirmFileStatusForResume(
      download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
      base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));

  // Delete the intermediate file.
  base::DeleteFile(download->GetFullPath(), false);

  DownloadUpdatedObserver completion_observer(
      download, base::Bind(DownloadCompleteFilter));
  download->Resume();
  completion_observer.WaitForEvent();

  ConfirmFileStatusForResume(
      download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
      base::FilePath(FILE_PATH_LITERAL("rangereset")));

  static const RecordingDownloadObserver::RecordStruct expected_record[] = {
    // Result of RST
    {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
    // Starting continuation
    {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()},
    // Error because file isn't there.
    {DownloadItem::INTERRUPTED, 0},
    // Restart.
    {DownloadItem::IN_PROGRESS, 0},
    // Completion.
    {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
  };

  recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
}

IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithFileInitError) {
  CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kEnableDownloadResumption);
  base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
  GURL url(URLRequestMockHTTPJob::GetMockUrl(file));

  // Setup the error injector.
  scoped_refptr<TestFileErrorInjector> injector(
      TestFileErrorInjector::Create(DownloadManagerForShell(shell())));

  TestFileErrorInjector::FileErrorInfo err = {
    url.spec(),
    TestFileErrorInjector::FILE_OPERATION_INITIALIZE,
    0,
    DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
  };
  injector->AddError(err);
  injector->InjectErrors();

  // Start and watch for interrupt.
  scoped_ptr<DownloadTestObserver> int_observer(
      CreateInterruptedWaiter(shell(), 1));
  DownloadItem* download(StartDownloadAndReturnItem(url));
  int_observer->WaitForFinished();
  ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState());
  EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE,
            download->GetLastReason());
  EXPECT_EQ(0, download->GetReceivedBytes());
  EXPECT_TRUE(download->GetFullPath().empty());
  EXPECT_TRUE(download->GetTargetFilePath().empty());

  // We need to make sure that any cross-thread downloads communication has
  // quiesced before clearing and injecting the new errors, as the
  // InjectErrors() routine alters the currently in use download file
  // factory, which is a file thread object.
  RunAllPendingInMessageLoop(BrowserThread::FILE);
  RunAllPendingInMessageLoop();

  // Clear the old errors list.
  injector->ClearErrors();
  injector->InjectErrors();

  // Resume and watch completion.
  DownloadUpdatedObserver completion_observer(
      download, base::Bind(DownloadCompleteFilter));
  download->Resume();
  completion_observer.WaitForEvent();
  EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE);
}

IN_PROC_BROWSER_TEST_F(DownloadContentTest,
                       ResumeWithFileIntermediateRenameError) {
  CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kEnableDownloadResumption);
  base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
  GURL url(URLRequestMockHTTPJob::GetMockUrl(file));

  // Setup the error injector.
  scoped_refptr<TestFileErrorInjector> injector(
      TestFileErrorInjector::Create(DownloadManagerForShell(shell())));

  TestFileErrorInjector::FileErrorInfo err = {
    url.spec(),
    TestFileErrorInjector::FILE_OPERATION_RENAME_UNIQUIFY,
    0,
    DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
  };
  injector->AddError(err);
  injector->InjectErrors();

  // Start and watch for interrupt.
  scoped_ptr<DownloadTestObserver> int_observer(
      CreateInterruptedWaiter(shell(), 1));
  DownloadItem* download(StartDownloadAndReturnItem(url));
  int_observer->WaitForFinished();
  ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState());
  EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE,
            download->GetLastReason());
  EXPECT_TRUE(download->GetFullPath().empty());
  // Target path will have been set after file name determination. GetFullPath()
  // being empty is sufficient to signal that filename determination needs to be
  // redone.
  EXPECT_FALSE(download->GetTargetFilePath().empty());

  // We need to make sure that any cross-thread downloads communication has
  // quiesced before clearing and injecting the new errors, as the
  // InjectErrors() routine alters the currently in use download file
  // factory, which is a file thread object.
  RunAllPendingInMessageLoop(BrowserThread::FILE);
  RunAllPendingInMessageLoop();

  // Clear the old errors list.
  injector->ClearErrors();
  injector->InjectErrors();

  // Resume and watch completion.
  DownloadUpdatedObserver completion_observer(
      download, base::Bind(DownloadCompleteFilter));
  download->Resume();
  completion_observer.WaitForEvent();
  EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE);
}

IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithFileFinalRenameError) {
  CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kEnableDownloadResumption);
  base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
  GURL url(URLRequestMockHTTPJob::GetMockUrl(file));

  // Setup the error injector.
  scoped_refptr<TestFileErrorInjector> injector(
      TestFileErrorInjector::Create(DownloadManagerForShell(shell())));

  DownloadManagerForShell(shell())->RemoveAllDownloads();
  TestFileErrorInjector::FileErrorInfo err = {
    url.spec(),
    TestFileErrorInjector::FILE_OPERATION_RENAME_ANNOTATE,
    0,
    DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
  };
  injector->AddError(err);
  injector->InjectErrors();

  // Start and watch for interrupt.
  scoped_ptr<DownloadTestObserver> int_observer(
      CreateInterruptedWaiter(shell(), 1));
  DownloadItem* download(StartDownloadAndReturnItem(url));
  int_observer->WaitForFinished();
  ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState());
  EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE,
            download->GetLastReason());
  EXPECT_TRUE(download->GetFullPath().empty());
  // Target path should still be intact.
  EXPECT_FALSE(download->GetTargetFilePath().empty());

  // We need to make sure that any cross-thread downloads communication has
  // quiesced before clearing and injecting the new errors, as the
  // InjectErrors() routine alters the currently in use download file
  // factory, which is a file thread object.
  RunAllPendingInMessageLoop(BrowserThread::FILE);
  RunAllPendingInMessageLoop();

  // Clear the old errors list.
  injector->ClearErrors();
  injector->InjectErrors();

  // Resume and watch completion.
  DownloadUpdatedObserver completion_observer(
      download, base::Bind(DownloadCompleteFilter));
  download->Resume();
  completion_observer.WaitForEvent();
  EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE);
}

// An interrupted download should remove the intermediate file when it is
// cancelled.
IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelInterruptedDownload) {
  CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kEnableDownloadResumption);
  ASSERT_TRUE(test_server()->Start());

  GURL url1 = test_server()->GetURL(
      base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
                         GetSafeBufferChunk() * 3, GetSafeBufferChunk()));

  DownloadItem* download(StartDownloadAndReturnItem(url1));
  WaitForData(download, GetSafeBufferChunk());

  ReleaseRSTAndConfirmInterruptForResume(download);
  ConfirmFileStatusForResume(
      download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
      base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));

  base::FilePath intermediate_path(download->GetFullPath());
  ASSERT_FALSE(intermediate_path.empty());
  EXPECT_TRUE(base::PathExists(intermediate_path));

  download->Cancel(true /* user_cancel */);
  RunAllPendingInMessageLoop(BrowserThread::FILE);
  RunAllPendingInMessageLoop();

  // The intermediate file should now be gone.
  EXPECT_FALSE(base::PathExists(intermediate_path));
  EXPECT_TRUE(download->GetFullPath().empty());
}

IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveDownload) {
  CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kEnableDownloadResumption);
  ASSERT_TRUE(test_server()->Start());

  // An interrupted download should remove the intermediate file when it is
  // removed.
  {
    GURL url1 = test_server()->GetURL(
        base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
                           GetSafeBufferChunk() * 3, GetSafeBufferChunk()));

    DownloadItem* download(StartDownloadAndReturnItem(url1));
    WaitForData(download, GetSafeBufferChunk());
    ReleaseRSTAndConfirmInterruptForResume(download);
    ConfirmFileStatusForResume(
        download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
        base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));

    base::FilePath intermediate_path(download->GetFullPath());
    ASSERT_FALSE(intermediate_path.empty());
    EXPECT_TRUE(base::PathExists(intermediate_path));

    download->Remove();
    RunAllPendingInMessageLoop(BrowserThread::FILE);
    RunAllPendingInMessageLoop();

    // The intermediate file should now be gone.
    EXPECT_FALSE(base::PathExists(intermediate_path));
  }

  // A completed download shouldn't delete the downloaded file when it is
  // removed.
  {
    // Start the second download and wait until it's done.
    base::FilePath file2(FILE_PATH_LITERAL("download-test.lib"));
    GURL url2(URLRequestMockHTTPJob::GetMockUrl(file2));
    scoped_ptr<DownloadTestObserver> completion_observer(
        CreateWaiter(shell(), 1));
    DownloadItem* download(StartDownloadAndReturnItem(url2));
    completion_observer->WaitForFinished();

    // The target path should exist.
    base::FilePath target_path(download->GetTargetFilePath());
    EXPECT_TRUE(base::PathExists(target_path));
    download->Remove();
    RunAllPendingInMessageLoop(BrowserThread::FILE);
    RunAllPendingInMessageLoop();

    // The file should still exist.
    EXPECT_TRUE(base::PathExists(target_path));
  }
}

IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveResumingDownload) {
  SetupEnsureNoPendingDownloads();
  CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kEnableDownloadResumption);
  ASSERT_TRUE(test_server()->Start());

  GURL url = test_server()->GetURL(
      base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
                         GetSafeBufferChunk() * 3, GetSafeBufferChunk()));

  MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell()));
  EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);

  DownloadItem* download(StartDownloadAndReturnItem(url));
  WaitForData(download, GetSafeBufferChunk());
  ::testing::Mock::VerifyAndClearExpectations(&dm_observer);

  // Tell the server to send the RST and confirm the interrupt happens.
  ReleaseRSTAndConfirmInterruptForResume(download);
  ConfirmFileStatusForResume(
      download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
      base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));

  base::FilePath intermediate_path(download->GetFullPath());
  ASSERT_FALSE(intermediate_path.empty());
  EXPECT_TRUE(base::PathExists(intermediate_path));

  // Resume and remove download. We expect only a single OnDownloadCreated()
  // call, and that's for the second download created below.
  EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
  download->Resume();
  download->Remove();

  // The intermediate file should now be gone.
  RunAllPendingInMessageLoop(BrowserThread::FILE);
  RunAllPendingInMessageLoop();
  EXPECT_FALSE(base::PathExists(intermediate_path));

  // Start the second download and wait until it's done. The test server is
  // single threaded. The response to this download request should follow the
  // response to the previous resumption request.
  GURL url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x"));
  DownloadAndWait(shell(), url2, DownloadItem::COMPLETE);

  EXPECT_TRUE(EnsureNoPendingDownloads());
}

IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelResumingDownload) {
  SetupEnsureNoPendingDownloads();
  CommandLine::ForCurrentProcess()->AppendSwitch(
      switches::kEnableDownloadResumption);
  ASSERT_TRUE(test_server()->Start());

  GURL url = test_server()->GetURL(
      base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
                         GetSafeBufferChunk() * 3, GetSafeBufferChunk()));

  MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell()));
  EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);

  DownloadItem* download(StartDownloadAndReturnItem(url));
  WaitForData(download, GetSafeBufferChunk());
  ::testing::Mock::VerifyAndClearExpectations(&dm_observer);

  // Tell the server to send the RST and confirm the interrupt happens.
  ReleaseRSTAndConfirmInterruptForResume(download);
  ConfirmFileStatusForResume(
      download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
      base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));

  base::FilePath intermediate_path(download->GetFullPath());
  ASSERT_FALSE(intermediate_path.empty());
  EXPECT_TRUE(base::PathExists(intermediate_path));

  // Resume and cancel download. We expect only a single OnDownloadCreated()
  // call, and that's for the second download created below.
  EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
  download->Resume();
  download->Cancel(true);

  // The intermediate file should now be gone.
  RunAllPendingInMessageLoop(BrowserThread::FILE);
  RunAllPendingInMessageLoop();
  EXPECT_FALSE(base::PathExists(intermediate_path));
  EXPECT_TRUE(download->GetFullPath().empty());

  // Start the second download and wait until it's done. The test server is
  // single threaded. The response to this download request should follow the
  // response to the previous resumption request.
  GURL url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x"));
  DownloadAndWait(shell(), url2, DownloadItem::COMPLETE);

  EXPECT_TRUE(EnsureNoPendingDownloads());
}

// Check that the cookie policy is correctly updated when downloading a file
// that redirects cross origin.
IN_PROC_BROWSER_TEST_F(DownloadContentTest, CookiePolicy) {
  ASSERT_TRUE(test_server()->Start());
  net::HostPortPair host_port = test_server()->host_port_pair();
  DCHECK_EQ(host_port.host(), std::string("127.0.0.1"));

  // Block third-party cookies.
  ShellNetworkDelegate::SetAcceptAllCookies(false);

  // |url| redirects to a different origin |download| which tries to set a
  // cookie.
  std::string download(base::StringPrintf(
      "http://localhost:%d/set-cookie?A=B", host_port.port()));
  GURL url(test_server()->GetURL("server-redirect?" + download));

  // Download the file.
  SetupEnsureNoPendingDownloads();
  scoped_ptr<DownloadUrlParameters> dl_params(
      DownloadUrlParameters::FromWebContents(shell()->web_contents(), url));
  scoped_ptr<DownloadTestObserver> observer(CreateWaiter(shell(), 1));
  DownloadManagerForShell(shell())->DownloadUrl(dl_params.Pass());
  observer->WaitForFinished();

  // Get the important info from other threads and check it.
  EXPECT_TRUE(EnsureNoPendingDownloads());

  std::vector<DownloadItem*> downloads;
  DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
  ASSERT_EQ(1u, downloads.size());
  ASSERT_EQ(DownloadItem::COMPLETE, downloads[0]->GetState());

  // Check that the cookies were correctly set.
  EXPECT_EQ("A=B",
            content::GetCookies(shell()->web_contents()->GetBrowserContext(),
                                GURL(download)));
}

}  // namespace content
