15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file contains download browser tests that are known to be runnable
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in a pure content context.  Over time tests should be migrated here.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/command_line.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/scoped_temp_dir.h"
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/memory/ref_counted.h"
137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/strings/stringprintf.h"
14a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/strings/utf_string_conversions.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/threading/platform_thread.h"
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/time/time.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/byte_stream.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/download/download_file_factory.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/download/download_file_impl.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/download/download_item_impl.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/download/download_manager_impl.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/download/download_resource_handler.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/web_contents/web_contents_impl.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/power_save_blocker.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/content_switches.h"
26a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "content/public/common/webplugininfo.h"
273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "content/public/test/browser_test_utils.h"
28effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "content/public/test/content_browser_test.h"
29effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "content/public/test/content_browser_test_utils.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/download_test_observer.h"
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/test/test_file_error_injector.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_utils.h"
333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "content/shell/browser/shell.h"
343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "content/shell/browser/shell_browser_context.h"
353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "content/shell/browser/shell_download_manager_delegate.h"
363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "content/shell/browser/shell_network_delegate.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/test/net/url_request_slow_download_job.h"
385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "net/test/embedded_test_server/embedded_test_server.h"
395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "net/test/embedded_test_server/http_request.h"
405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "net/test/embedded_test_server/http_response.h"
41b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "net/test/spawned_test_server/spawned_test_server.h"
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/test/url_request/url_request_mock_http_job.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(ENABLE_PLUGINS)
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/browser/plugin_service_impl.h"
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing ::net::test_server::EmbeddedTestServer;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::AllOf;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Field;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::InSequence;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Property;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::Return;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ::testing::StrictMock;
585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing ::testing::_;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockDownloadItemObserver : public DownloadItem::Observer {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockDownloadItemObserver() {}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MockDownloadItemObserver() {}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOCK_METHOD1(OnDownloadUpdated, void(DownloadItem*));
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOCK_METHOD1(OnDownloadOpened, void(DownloadItem*));
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOCK_METHOD1(OnDownloadRemoved, void(DownloadItem*));
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOCK_METHOD1(OnDownloadDestroyed, void(DownloadItem*));
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockDownloadManagerObserver : public DownloadManager::Observer {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockDownloadManagerObserver(DownloadManager* manager) {
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    manager_ = manager;
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    manager->AddObserver(this);
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~MockDownloadManagerObserver() {
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (manager_)
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      manager_->RemoveObserver(this);
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOCK_METHOD2(OnDownloadCreated, void(DownloadManager*, DownloadItem*));
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MOCK_METHOD1(ModelChanged, void(DownloadManager*));
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void ManagerGoingDown(DownloadManager* manager) {
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK_EQ(manager_, manager);
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    MockManagerGoingDown(manager);
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    manager_->RemoveObserver(this);
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    manager_ = NULL;
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MOCK_METHOD1(MockManagerGoingDown, void(DownloadManager*));
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DownloadManager* manager_;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DownloadFileWithDelayFactory;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static DownloadManagerImpl* DownloadManagerForShell(Shell* shell) {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We're in a content_browsertest; we know that the DownloadManager
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is a DownloadManagerImpl.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<DownloadManagerImpl*>(
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserContext::GetDownloadManager(
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          shell->web_contents()->GetBrowserContext()));
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DownloadFileWithDelay : public DownloadFileImpl {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadFileWithDelay(
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_ptr<DownloadSaveInfo> save_info,
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::FilePath& default_download_directory,
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& url,
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& referrer_url,
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool calculate_hash,
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_ptr<ByteStreamReader> stream,
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const net::BoundNetLog& bound_net_log,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_ptr<PowerSaveBlocker> power_save_blocker,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::WeakPtr<DownloadDestinationObserver> observer,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::WeakPtr<DownloadFileWithDelayFactory> owner);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~DownloadFileWithDelay();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wraps DownloadFileImpl::Rename* and intercepts the return callback,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // storing it in the factory that produced this object for later
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // retrieval.
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RenameAndUniquify(
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::FilePath& full_path,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const RenameCompletionCallback& callback) OVERRIDE;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void RenameAndAnnotate(
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::FilePath& full_path,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const RenameCompletionCallback& callback) OVERRIDE;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void RenameCallbackWrapper(
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      const base::WeakPtr<DownloadFileWithDelayFactory>& factory,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const RenameCompletionCallback& original_callback,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DownloadInterruptReason reason,
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::FilePath& path);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This variable may only be read on the FILE thread, and may only be
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // indirected through (e.g. methods on DownloadFileWithDelayFactory called)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on the UI thread.  This is because after construction,
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // DownloadFileWithDelay lives on the file thread, but
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // DownloadFileWithDelayFactory is purely a UI thread object.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtr<DownloadFileWithDelayFactory> owner_;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DownloadFileWithDelay);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All routines on this class must be called on the UI thread.
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DownloadFileWithDelayFactory : public DownloadFileFactory {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadFileWithDelayFactory();
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~DownloadFileWithDelayFactory();
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // DownloadFileFactory interface.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual DownloadFile* CreateFile(
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_ptr<DownloadSaveInfo> save_info,
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::FilePath& default_download_directory,
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& url,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& referrer_url,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool calculate_hash,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_ptr<ByteStreamReader> stream,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const net::BoundNetLog& bound_net_log,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::WeakPtr<DownloadDestinationObserver> observer) OVERRIDE;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AddRenameCallback(base::Closure callback);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void GetAllRenameCallbacks(std::vector<base::Closure>* results);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do not return until GetAllRenameCallbacks() will return a non-empty list.
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void WaitForSomeCallback();
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtrFactory<DownloadFileWithDelayFactory> weak_ptr_factory_;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<base::Closure> rename_callbacks_;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool waiting_;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DownloadFileWithDelayFactory);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DownloadFileWithDelay::DownloadFileWithDelay(
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<DownloadSaveInfo> save_info,
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& default_download_directory,
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& referrer_url,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool calculate_hash,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<ByteStreamReader> stream,
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::BoundNetLog& bound_net_log,
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<PowerSaveBlocker> power_save_blocker,
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::WeakPtr<DownloadDestinationObserver> observer,
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::WeakPtr<DownloadFileWithDelayFactory> owner)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : DownloadFileImpl(
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        save_info.Pass(), default_download_directory, url, referrer_url,
198a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        calculate_hash, stream.Pass(), bound_net_log, observer),
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      owner_(owner) {}
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DownloadFileWithDelay::~DownloadFileWithDelay() {}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadFileWithDelay::RenameAndUniquify(
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& full_path,
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const RenameCompletionCallback& callback) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadFileImpl::RenameAndUniquify(
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      full_path, base::Bind(DownloadFileWithDelay::RenameCallbackWrapper,
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            owner_, callback));
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadFileWithDelay::RenameAndAnnotate(
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& full_path, const RenameCompletionCallback& callback) {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadFileImpl::RenameAndAnnotate(
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      full_path, base::Bind(DownloadFileWithDelay::RenameCallbackWrapper,
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            owner_, callback));
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadFileWithDelay::RenameCallbackWrapper(
222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const base::WeakPtr<DownloadFileWithDelayFactory>& factory,
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const RenameCompletionCallback& original_callback,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DownloadInterruptReason reason,
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& path) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!factory)
228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  factory->AddRenameCallback(base::Bind(original_callback, reason, path));
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DownloadFileWithDelayFactory::DownloadFileWithDelayFactory()
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : weak_ptr_factory_(this),
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      waiting_(false) {}
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DownloadFileWithDelayFactory::~DownloadFileWithDelayFactory() {}
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DownloadFile* DownloadFileWithDelayFactory::CreateFile(
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<DownloadSaveInfo> save_info,
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& default_download_directory,
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& referrer_url,
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool calculate_hash,
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<ByteStreamReader> stream,
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::BoundNetLog& bound_net_log,
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::WeakPtr<DownloadDestinationObserver> observer) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<PowerSaveBlocker> psb(
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      PowerSaveBlocker::Create(
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "Download in progress"));
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new DownloadFileWithDelay(
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      save_info.Pass(), default_download_directory, url, referrer_url,
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      calculate_hash, stream.Pass(), bound_net_log,
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      psb.Pass(), observer, weak_ptr_factory_.GetWeakPtr());
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadFileWithDelayFactory::AddRenameCallback(base::Closure callback) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rename_callbacks_.push_back(callback);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (waiting_)
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoopForUI::current()->Quit();
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadFileWithDelayFactory::GetAllRenameCallbacks(
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<base::Closure>* results) {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  results->swap(rename_callbacks_);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadFileWithDelayFactory::WaitForSomeCallback() {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rename_callbacks_.empty()) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    waiting_ = true;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RunMessageLoop();
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    waiting_ = false;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CountingDownloadFile : public DownloadFileImpl {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CountingDownloadFile(
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<DownloadSaveInfo> save_info,
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& default_downloads_directory,
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& referrer_url,
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool calculate_hash,
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<ByteStreamReader> stream,
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::BoundNetLog& bound_net_log,
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<PowerSaveBlocker> power_save_blocker,
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::WeakPtr<DownloadDestinationObserver> observer)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : DownloadFileImpl(save_info.Pass(), default_downloads_directory,
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         url, referrer_url, calculate_hash,
293a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                         stream.Pass(), bound_net_log, observer) {}
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~CountingDownloadFile() {
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    active_files_--;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Initialize(const InitializeCallback& callback) OVERRIDE {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    active_files_++;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return DownloadFileImpl::Initialize(callback);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void GetNumberActiveFiles(int* result) {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *result = active_files_;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Can be called on any thread, and will block (running message loop)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // until data is returned.
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static int GetNumberActiveFilesFromFileThread() {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int result = -1;
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    BrowserThread::PostTaskAndReply(
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        BrowserThread::FILE,
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        FROM_HERE,
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&CountingDownloadFile::GetNumberActiveFiles, &result),
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::MessageLoop::current()->QuitClosure());
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoop::current()->Run();
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_NE(-1, result);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static int active_files_;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int CountingDownloadFile::active_files_ = 0;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CountingDownloadFileFactory : public DownloadFileFactory {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CountingDownloadFileFactory() {}
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~CountingDownloadFileFactory() {}
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // DownloadFileFactory interface.
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual DownloadFile* CreateFile(
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<DownloadSaveInfo> save_info,
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& default_downloads_directory,
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& referrer_url,
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool calculate_hash,
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<ByteStreamReader> stream,
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::BoundNetLog& bound_net_log,
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::WeakPtr<DownloadDestinationObserver> observer) OVERRIDE {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<PowerSaveBlocker> psb(
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        PowerSaveBlocker::Create(
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "Download in progress"));
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new CountingDownloadFile(
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        save_info.Pass(), default_downloads_directory, url, referrer_url,
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        calculate_hash, stream.Pass(), bound_net_log,
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        psb.Pass(), observer);
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestShellDownloadManagerDelegate : public ShellDownloadManagerDelegate {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestShellDownloadManagerDelegate()
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : delay_download_open_(false) {}
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  virtual ~TestShellDownloadManagerDelegate() {}
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool ShouldOpenDownload(
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DownloadItem* item,
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const DownloadOpenDelayedCallback& callback) OVERRIDE {
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delay_download_open_) {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delayed_callbacks_.push_back(callback);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetDelayedOpen(bool delay) {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delay_download_open_ = delay;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void GetDelayedCallbacks(
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::vector<DownloadOpenDelayedCallback>* callbacks) {
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    callbacks->swap(delayed_callbacks_);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool delay_download_open_;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<DownloadOpenDelayedCallback> delayed_callbacks_;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Record all state transitions and byte counts on the observed download.
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class RecordingDownloadObserver : DownloadItem::Observer {
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  struct RecordStruct {
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DownloadItem::DownloadState state;
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int bytes_received;
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef std::vector<RecordStruct> RecordVector;
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RecordingDownloadObserver(DownloadItem* download)
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : download_(download) {
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    last_state_.state = download->GetState();
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    last_state_.bytes_received = download->GetReceivedBytes();
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    download_->AddObserver(this);
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~RecordingDownloadObserver() {
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RemoveObserver();
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void CompareToExpectedRecord(const RecordStruct expected[], size_t size) {
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(size, record_.size());
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int min = size > record_.size() ? record_.size() : size;
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int i = 0; i < min; ++i) {
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EXPECT_EQ(expected[i].state, record_[i].state) << "Iteration " << i;
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      EXPECT_EQ(expected[i].bytes_received, record_[i].bytes_received)
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          << "Iteration " << i;
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnDownloadUpdated(DownloadItem* download) OVERRIDE {
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_EQ(download_, download);
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DownloadItem::DownloadState state = download->GetState();
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int bytes = download->GetReceivedBytes();
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (last_state_.state != state || last_state_.bytes_received > bytes) {
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      last_state_.state = state;
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      last_state_.bytes_received = bytes;
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      record_.push_back(last_state_);
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnDownloadDestroyed(DownloadItem* download) OVERRIDE {
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_EQ(download_, download);
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RemoveObserver();
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void RemoveObserver() {
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (download_) {
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download_->RemoveObserver(this);
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download_ = NULL;
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadItem* download_;
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RecordStruct last_state_;
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RecordVector record_;
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Get the next created download.
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class DownloadCreateObserver : DownloadManager::Observer {
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadCreateObserver(DownloadManager* manager)
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : manager_(manager),
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        item_(NULL),
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        waiting_(false) {
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    manager_->AddObserver(this);
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual ~DownloadCreateObserver() {
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (manager_)
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      manager_->RemoveObserver(this);
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    manager_ = NULL;
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void ManagerGoingDown(DownloadManager* manager) OVERRIDE {
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_EQ(manager_, manager);
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    manager_->RemoveObserver(this);
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    manager_ = NULL;
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnDownloadCreated(DownloadManager* manager,
469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 DownloadItem* download) OVERRIDE {
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!item_)
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      item_ = download;
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (waiting_)
474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::MessageLoopForUI::current()->Quit();
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadItem* WaitForFinished() {
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!item_) {
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      waiting_ = true;
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RunMessageLoop();
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      waiting_ = false;
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return item_;
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadManager* manager_;
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadItem* item_;
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool waiting_;
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Filter for waiting for a certain number of bytes.
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DataReceivedFilter(int number_of_bytes, DownloadItem* download) {
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return download->GetReceivedBytes() >= number_of_bytes;
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Filter for download completion.
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DownloadCompleteFilter(DownloadItem* download) {
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return download->GetState() == DownloadItem::COMPLETE;
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Filter for saving the size of the download when the first IN_PROGRESS
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// is hit.
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool InitialSizeFilter(int* download_size, DownloadItem* download) {
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (download->GetState() != DownloadItem::IN_PROGRESS)
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *download_size = download->GetReceivedBytes();
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Request handler to be used with CreateRedirectHandler().
5155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuscoped_ptr<net::test_server::HttpResponse> HandleRequestAndSendRedirectResponse(
5165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const std::string& relative_url,
5175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const GURL& target_url,
5185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const net::test_server::HttpRequest& request) {
5195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<net::test_server::BasicHttpResponse> response;
5205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (request.relative_url == relative_url) {
5215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    response.reset(new net::test_server::BasicHttpResponse);
5225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    response->set_code(net::HTTP_FOUND);
5235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    response->AddCustomHeader("Location", target_url.spec());
5245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
5255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return response.PassAs<net::test_server::HttpResponse>();
5265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Creates a request handler for EmbeddedTestServer that responds with a HTTP
5295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// 302 redirect if the request URL matches |relative_url|.
5305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuEmbeddedTestServer::HandleRequestCallback CreateRedirectHandler(
5315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const std::string& relative_url,
5325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const GURL& target_url) {
5335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return base::Bind(
5345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      &HandleRequestAndSendRedirectResponse, relative_url, target_url);
5355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Request handler to be used with CreateBasicResponseHandler().
5385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuscoped_ptr<net::test_server::HttpResponse> HandleRequestAndSendBasicResponse(
5395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const std::string& relative_url,
5405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const std::string& content_type,
5415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const std::string& body,
5425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const net::test_server::HttpRequest& request) {
5435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<net::test_server::BasicHttpResponse> response;
5445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (request.relative_url == relative_url) {
5455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    response.reset(new net::test_server::BasicHttpResponse);
5465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    response->set_content_type(content_type);
5475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    response->set_content(body);
5485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
5495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return response.PassAs<net::test_server::HttpResponse>();
5505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Creates a request handler for an EmbeddedTestServer that response with an
5535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// HTTP 200 status code, a Content-Type header and a body.
5545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuEmbeddedTestServer::HandleRequestCallback CreateBasicResponseHandler(
5555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const std::string& relative_url,
5565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const std::string& content_type,
5575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const std::string& body) {
5585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return base::Bind(
5595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      &HandleRequestAndSendBasicResponse, relative_url, content_type, body);
5605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
5615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DownloadContentTest : public ContentBrowserTest {
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // An initial send from a website of at least this size will not be
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // help up by buffering in the underlying downloads ByteStream data
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // transfer.  This is important because on resumption tests we wait
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // until we've gotten the data we expect before allowing the test server
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to send its reset, to get around hard close semantics on the Windows
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // socket layer implementation.
5722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int GetSafeBufferChunk() const {
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return (DownloadResourceHandler::kDownloadByteStreamSize /
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ByteStreamWriter::kFractionBufferBeforeSending) + 1;
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUpOnMainThread() OVERRIDE {
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir());
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    test_delegate_.reset(new TestShellDownloadManagerDelegate());
5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    test_delegate_->SetDownloadBehaviorForTesting(downloads_directory_.path());
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DownloadManager* manager = DownloadManagerForShell(shell());
5835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    manager->GetDelegate()->Shutdown();
5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    manager->SetDelegate(test_delegate_.get());
5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    test_delegate_->SetDownloadManager(manager);
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserThread::IO, FROM_HERE,
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&URLRequestSlowDownloadJob::AddUrlHandler));
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath mock_base(GetTestFilePath("download", ""));
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(
5921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        BrowserThread::IO,
5931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        FROM_HERE,
5941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        base::Bind(
5951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            &net::URLRequestMockHTTPJob::AddUrlHandler,
5961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            mock_base,
5971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            make_scoped_refptr(content::BrowserThread::GetBlockingPool())));
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  TestShellDownloadManagerDelegate* GetDownloadManagerDelegate() {
6015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return test_delegate_.get();
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a DownloadTestObserverTerminal that will wait for the
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // specified number of downloads to finish.
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadTestObserver* CreateWaiter(
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Shell* shell, int num_downloads) {
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DownloadManager* download_manager = DownloadManagerForShell(shell);
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new DownloadTestObserverTerminal(download_manager, num_downloads,
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a DownloadTestObserverInProgress that will wait for the
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // specified number of downloads to start.
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadCreateObserver* CreateInProgressWaiter(
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Shell* shell, int num_downloads) {
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DownloadManager* download_manager = DownloadManagerForShell(shell);
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return new DownloadCreateObserver(download_manager);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
621eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DownloadTestObserver* CreateInterruptedWaiter(
622eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      Shell* shell, int num_downloads) {
623eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DownloadManager* download_manager = DownloadManagerForShell(shell);
624eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return new DownloadTestObserverInterrupted(download_manager, num_downloads,
625eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
626eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
627eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: Cannot be used with other alternative DownloadFileFactorys
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetupEnsureNoPendingDownloads() {
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DownloadManagerForShell(shell())->SetDownloadFileFactoryForTesting(
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        scoped_ptr<DownloadFileFactory>(
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            new CountingDownloadFileFactory()).Pass());
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool EnsureNoPendingDownloads() {
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool result = true;
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        BrowserThread::IO, FROM_HERE,
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&EnsureNoPendingDownloadJobsOnIO, &result));
640c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoop::current()->Run();
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result &&
642c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)           (CountingDownloadFile::GetNumberActiveFilesFromFileThread() == 0);
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void NavigateToURLAndWaitForDownload(
6465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      Shell* shell,
6475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      const GURL& url,
6485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      DownloadItem::DownloadState expected_terminal_state) {
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<DownloadTestObserver> observer(CreateWaiter(shell, 1));
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NavigateToURL(shell, url);
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observer->WaitForFinished();
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(1u, observer->NumDownloadsSeenInState(expected_terminal_state));
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Checks that |path| is has |file_size| bytes, and matches the |value|
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // string.
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool VerifyFile(const base::FilePath& path,
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  const std::string& value,
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  const int64 file_size) {
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string file_contents;
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
66258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    bool read = base::ReadFileToString(path, &file_contents);
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(read) << "Failed reading file: " << path.value() << std::endl;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!read)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;  // Couldn't read the file.
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note: we don't handle really large files (more than size_t can hold)
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // so we will fail in that case.
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t expected_size = static_cast<size_t>(file_size);
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check the size.
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(expected_size, file_contents.size());
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (expected_size != file_contents.size())
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check the contents.
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(value, file_contents);
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (memcmp(file_contents.c_str(), value.c_str(), expected_size) != 0)
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Start a download and return the item.
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadItem* StartDownloadAndReturnItem(GURL url) {
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<DownloadCreateObserver> observer(
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        CreateInProgressWaiter(shell(), 1));
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NavigateToURL(shell(), url);
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    observer->WaitForFinished();
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::vector<DownloadItem*> downloads;
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(1u, downloads.size());
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (1u != downloads.size())
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return NULL;
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return downloads[0];
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Wait for data
6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void WaitForData(DownloadItem* download, int size) {
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DownloadUpdatedObserver data_observer(
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        download, base::Bind(&DataReceivedFilter, size));
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    data_observer.WaitForEvent();
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_EQ(size, download->GetReceivedBytes());
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Tell the test server to release a pending RST and confirm
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // that the interrupt is received properly (for download resumption
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // testing).
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void ReleaseRSTAndConfirmInterruptForResume(DownloadItem* download) {
711eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    scoped_ptr<DownloadTestObserver> rst_observer(
712eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        CreateInterruptedWaiter(shell(), 1));
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NavigateToURL(shell(), test_server()->GetURL("download-finish"));
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    rst_observer->WaitForFinished();
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(DownloadItem::INTERRUPTED, download->GetState());
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Confirm file status expected for the given location in a stream
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // provided by the resume test server.
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void ConfirmFileStatusForResume(
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DownloadItem* download, bool file_exists,
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int received_bytes, int total_bytes,
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::FilePath& expected_filename) {
724a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // expected_filename is only known if the file exists.
725a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    ASSERT_EQ(file_exists, !expected_filename.empty());
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(received_bytes, download->GetReceivedBytes());
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(total_bytes, download->GetTotalBytes());
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(expected_filename.value(),
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              download->GetFullPath().BaseName().value());
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EXPECT_EQ(file_exists,
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              (!download->GetFullPath().empty() &&
7327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch               base::PathExists(download->GetFullPath())));
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (file_exists) {
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string file_contents;
73658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      EXPECT_TRUE(base::ReadFileToString(
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          download->GetFullPath(), &file_contents));
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ASSERT_EQ(static_cast<size_t>(received_bytes), file_contents.size());
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for (int i = 0; i < received_bytes; ++i) {
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        EXPECT_EQ(static_cast<char>((i * 2 + 15) % 256), file_contents[i])
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            << "File contents diverged at position " << i
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            << " for " << expected_filename.value();
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (static_cast<char>((i * 2 + 15) % 256) != file_contents[i])
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          return;
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void EnsureNoPendingDownloadJobsOnIO(bool* result) {
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (URLRequestSlowDownloadJob::NumberOutstandingRequests())
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *result = false;
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserThread::PostTask(
756c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure());
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Location of the downloads directory for these tests
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ScopedTempDir downloads_directory_;
7615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<TestShellDownloadManagerDelegate> test_delegate_;
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadCancelled) {
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetupEnsureNoPendingDownloads();
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a download, wait until it's started, and confirm
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we're in the expected state.
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<DownloadCreateObserver> observer(
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateInProgressWaiter(shell(), 1));
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl));
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer->WaitForFinished();
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<DownloadItem*> downloads;
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, downloads.size());
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(DownloadItem::IN_PROGRESS, downloads[0]->GetState());
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancel the download and wait for download system quiesce.
780868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  downloads[0]->Cancel(true);
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<DownloadTestFlushObserver> flush_observer(
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new DownloadTestFlushObserver(DownloadManagerForShell(shell())));
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  flush_observer->WaitForFlush();
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the important info from other threads and check it.
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(EnsureNoPendingDownloads());
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Check that downloading multiple (in this case, 2) files does not result in
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// corrupted files.
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(DownloadContentTest, MultiDownload) {
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetupEnsureNoPendingDownloads();
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a download, wait until it's started, and confirm
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we're in the expected state.
7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<DownloadCreateObserver> observer1(
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateInProgressWaiter(shell(), 1));
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl));
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer1->WaitForFinished();
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<DownloadItem*> downloads;
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, downloads.size());
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(DownloadItem::IN_PROGRESS, downloads[0]->GetState());
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadItem* download1 = downloads[0];  // The only download.
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start the second download and wait until it's done.
8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
8091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file));
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Download the file and wait.
8115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE);
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should now have 2 items on the manager.
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  downloads.clear();
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(2u, downloads.size());
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't know the order of the downloads.
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadItem* download2 = downloads[(download1 == downloads[0]) ? 1 : 0];
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(DownloadItem::IN_PROGRESS, download1->GetState());
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(DownloadItem::COMPLETE, download2->GetState());
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allow the first request to finish.
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<DownloadTestObserver> observer2(CreateWaiter(shell(), 1));
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kFinishDownloadUrl));
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer2->WaitForFinished();  // Wait for the third request.
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(1u, observer2->NumDownloadsSeenInState(DownloadItem::COMPLETE));
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the important info from other threads and check it.
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(EnsureNoPendingDownloads());
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The |DownloadItem|s should now be done and have the final file names.
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that the files have the expected data and size.
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |file1| should be full of '*'s, and |file2| should be the same as the
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // source file.
836b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::FilePath file1(download1->GetTargetFilePath());
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t file_size1 = URLRequestSlowDownloadJob::kFirstDownloadSize +
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      URLRequestSlowDownloadJob::kSecondDownloadSize;
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string expected_contents(file_size1, '*');
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(VerifyFile(file1, expected_contents, file_size1));
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
842b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::FilePath file2(download2->GetTargetFilePath());
8437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ASSERT_TRUE(base::ContentsEqual(
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      file2, GetTestFilePath("download", "download-test.lib")));
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
847a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#if defined(ENABLE_PLUGINS)
848a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch// Content served with a MIME type of application/octet-stream should be
849a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch// downloaded even when a plugin can be found that handles the file type.
850a3f7b4e666c476898878fa745f637129375cd889Ben MurdochIN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadOctetStream) {
851a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  const base::FilePath::CharType kTestFilePath[] =
852a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      FILE_PATH_LITERAL("octet-stream.abc");
853a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  const char kTestPluginName[] = "TestPlugin";
854a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  const char kTestMimeType[] = "application/x-test-mime-type";
855a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  const char kTestFileType[] = "abc";
856a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
857a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  WebPluginInfo plugin_info;
858a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  plugin_info.name = base::ASCIIToUTF16(kTestPluginName);
859a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  plugin_info.mime_types.push_back(
860a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch      WebPluginMimeType(kTestMimeType, kTestFileType, ""));
861a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  PluginServiceImpl::GetInstance()->RegisterInternalPlugin(plugin_info, false);
862a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
863a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch  // The following is served with a Content-Type of application/octet-stream.
8641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  GURL url(
8651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      net::URLRequestMockHTTPJob::GetMockUrl(base::FilePath(kTestFilePath)));
8665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE);
867a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch}
868a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#endif
869a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Try to cancel just before we release the download file, by delaying final
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// rename callback.
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelAtFinalRename) {
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Setup new factory.
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadFileWithDelayFactory* file_factory =
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new DownloadFileWithDelayFactory();
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadManagerImpl* download_manager(DownloadManagerForShell(shell()));
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  download_manager->SetDownloadFileFactoryForTesting(
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_ptr<DownloadFileFactory>(file_factory).Pass());
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a download
8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
8821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  NavigateToURL(shell(), net::URLRequestMockHTTPJob::GetMockUrl(file));
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait until the first (intermediate file) rename and execute the callback.
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_factory->WaitForSomeCallback();
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<base::Closure> callbacks;
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_factory->GetAllRenameCallbacks(&callbacks);
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, callbacks.size());
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callbacks[0].Run();
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callbacks.clear();
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait until the second (final) rename callback is posted.
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_factory->WaitForSomeCallback();
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_factory->GetAllRenameCallbacks(&callbacks);
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, callbacks.size());
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancel it.
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<DownloadItem*> items;
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  download_manager->GetAllDownloads(&items);
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, items.size());
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  items[0]->Cancel(true);
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunAllPendingInMessageLoop();
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check state.
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(DownloadItem::CANCELLED, items[0]->GetState());
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run final rename callback.
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callbacks[0].Run();
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callbacks.clear();
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check state.
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(DownloadItem::CANCELLED, items[0]->GetState());
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Try to cancel just after we release the download file, by delaying
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in ShouldOpenDownload.
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelAtRelease) {
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadManagerImpl* download_manager(DownloadManagerForShell(shell()));
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Mark delegate for delayed open.
9215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GetDownloadManagerDelegate()->SetDelayedOpen(true);
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Setup new factory.
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadFileWithDelayFactory* file_factory =
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new DownloadFileWithDelayFactory();
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  download_manager->SetDownloadFileFactoryForTesting(
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_ptr<DownloadFileFactory>(file_factory).Pass());
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a download
9302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
9311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  NavigateToURL(shell(), net::URLRequestMockHTTPJob::GetMockUrl(file));
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait until the first (intermediate file) rename and execute the callback.
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_factory->WaitForSomeCallback();
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<base::Closure> callbacks;
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_factory->GetAllRenameCallbacks(&callbacks);
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, callbacks.size());
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callbacks[0].Run();
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callbacks.clear();
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait until the second (final) rename callback is posted.
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_factory->WaitForSomeCallback();
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_factory->GetAllRenameCallbacks(&callbacks);
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, callbacks.size());
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Call it.
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callbacks[0].Run();
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callbacks.clear();
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Confirm download still IN_PROGRESS (internal state COMPLETING).
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<DownloadItem*> items;
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  download_manager->GetAllDownloads(&items);
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancel the download; confirm cancel fails.
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, items.size());
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  items[0]->Cancel(true);
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Need to complete open test.
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<DownloadOpenDelayedCallback> delayed_callbacks;
9625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GetDownloadManagerDelegate()->GetDelayedCallbacks(
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &delayed_callbacks);
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, delayed_callbacks.size());
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delayed_callbacks[0].Run(true);
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // *Now* the download should be complete.
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(DownloadItem::COMPLETE, items[0]->GetState());
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Try to shutdown with a download in progress to make sure shutdown path
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// works properly.
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownInProgress) {
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a download that won't complete.
9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<DownloadCreateObserver> observer(
9762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CreateInProgressWaiter(shell(), 1));
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl));
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer->WaitForFinished();
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the item.
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<DownloadItem*> items;
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadManagerForShell(shell())->GetAllDownloads(&items);
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, items.size());
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Shutdown the download manager and make sure we get the right
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // notifications in the right order.
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StrictMock<MockDownloadItemObserver> item_observer;
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  items[0]->AddObserver(&item_observer);
990c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockDownloadManagerObserver manager_observer(
991c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      DownloadManagerForShell(shell()));
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't care about ModelChanged() events.
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(manager_observer, ModelChanged(_))
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .WillRepeatedly(Return());
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InSequence notifications;
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
998c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    EXPECT_CALL(manager_observer, MockManagerGoingDown(
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DownloadManagerForShell(shell())))
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .WillOnce(Return());
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_CALL(item_observer, OnDownloadUpdated(
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AllOf(items[0],
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              Property(&DownloadItem::GetState, DownloadItem::CANCELLED))))
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .WillOnce(Return());
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_CALL(item_observer, OnDownloadDestroyed(items[0]))
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .WillOnce(Return());
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
10095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // See http://crbug.com/324525.  If we have a refcount release/post task
10105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // race, the second post will stall the IO thread long enough so that we'll
10115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // lose the race and crash.  The first stall is just to give the UI thread
10125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // a chance to get the second stall onto the IO thread queue after the cancel
10135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // message created by Shutdown and before the notification callback
10145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // created by the IO thread in canceling the request.
10155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
10165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          base::Bind(&base::PlatformThread::Sleep,
10175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     base::TimeDelta::FromMilliseconds(25)));
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadManagerForShell(shell())->Shutdown();
10195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
10205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          base::Bind(&base::PlatformThread::Sleep,
10215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                     base::TimeDelta::FromMilliseconds(25)));
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  items.clear();
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Try to shutdown just after we release the download file, by delaying
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// release.
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownAtRelease) {
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadManagerImpl* download_manager(DownloadManagerForShell(shell()));
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Mark delegate for delayed open.
10315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GetDownloadManagerDelegate()->SetDelayedOpen(true);
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Setup new factory.
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadFileWithDelayFactory* file_factory =
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new DownloadFileWithDelayFactory();
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  download_manager->SetDownloadFileFactoryForTesting(
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      scoped_ptr<DownloadFileFactory>(file_factory).Pass());
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a download
10402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
10411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  NavigateToURL(shell(), net::URLRequestMockHTTPJob::GetMockUrl(file));
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait until the first (intermediate file) rename and execute the callback.
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_factory->WaitForSomeCallback();
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<base::Closure> callbacks;
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_factory->GetAllRenameCallbacks(&callbacks);
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, callbacks.size());
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callbacks[0].Run();
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callbacks.clear();
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Wait until the second (final) rename callback is posted.
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_factory->WaitForSomeCallback();
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_factory->GetAllRenameCallbacks(&callbacks);
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, callbacks.size());
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Call it.
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callbacks[0].Run();
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  callbacks.clear();
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Confirm download isn't complete yet.
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<DownloadItem*> items;
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadManagerForShell(shell())->GetAllDownloads(&items);
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancel the download; confirm cancel fails anyway.
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(1u, items.size());
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  items[0]->Cancel(true);
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunAllPendingInMessageLoop();
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockDownloadItemObserver observer;
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  items[0]->AddObserver(&observer);
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(observer, OnDownloadDestroyed(items[0]));
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Shutdown the download manager.  Mostly this is confirming a lack of
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // crashes.
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadManagerForShell(shell())->Shutdown();
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeInterruptedDownload) {
10826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::CommandLine::ForCurrentProcess()->AppendSwitch(
10832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      switches::kEnableDownloadResumption);
10842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(test_server()->Start());
10852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url = test_server()->GetURL(
10872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
10882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
10892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1090c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell()));
1091c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
1092c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
10932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadItem* download(StartDownloadAndReturnItem(url));
10942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WaitForData(download, GetSafeBufferChunk());
1095c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ::testing::Mock::VerifyAndClearExpectations(&dm_observer);
10962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Confirm resumption while in progress doesn't do anything.
1098a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  download->Resume();
10992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(GetSafeBufferChunk(), download->GetReceivedBytes());
11002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
11012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Tell the server to send the RST and confirm the interrupt happens.
11032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseRSTAndConfirmInterruptForResume(download);
11042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ConfirmFileStatusForResume(
11052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
11062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
11072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Resume, confirming received bytes on resumption is correct.
1109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Make sure no creation calls are included.
1110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(0);
11112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int initial_size = 0;
11122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadUpdatedObserver initial_size_observer(
11132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download, base::Bind(&InitialSizeFilter, &initial_size));
1114a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  download->Resume();
11152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  initial_size_observer.WaitForEvent();
11162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(GetSafeBufferChunk(), initial_size);
1117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ::testing::Mock::VerifyAndClearExpectations(&dm_observer);
11182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // and wait for expected data.
11202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WaitForData(download, GetSafeBufferChunk() * 2);
11212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Tell the server to send the RST and confirm the interrupt happens.
11232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseRSTAndConfirmInterruptForResume(download);
11242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ConfirmFileStatusForResume(
11252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download, true, GetSafeBufferChunk() * 2, GetSafeBufferChunk() * 3,
11262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
11272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Resume and wait for completion.
11292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadUpdatedObserver completion_observer(
11302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download, base::Bind(DownloadCompleteFilter));
1131a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  download->Resume();
11322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  completion_observer.WaitForEvent();
11332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ConfirmFileStatusForResume(
11352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
11362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath(FILE_PATH_LITERAL("rangereset")));
11372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Confirm resumption while complete doesn't do anything.
1139a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  download->Resume();
11402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(GetSafeBufferChunk() * 3, download->GetReceivedBytes());
11412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(DownloadItem::COMPLETE, download->GetState());
11422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunAllPendingInMessageLoop();
11432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(GetSafeBufferChunk() * 3, download->GetReceivedBytes());
11442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(DownloadItem::COMPLETE, download->GetState());
11452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Confirm restart fallback happens if a range request is bounced.
11482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeInterruptedDownloadNoRange) {
11496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::CommandLine::ForCurrentProcess()->AppendSwitch(
11502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      switches::kEnableDownloadResumption);
11512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(test_server()->Start());
11522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Auto-restart if server doesn't handle ranges.
11542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url = test_server()->GetURL(
11552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::StringPrintf(
11562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // First download hits an RST, rest don't, no ranges.
11572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          "rangereset?size=%d&rst_boundary=%d&"
11582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          "token=NoRange&rst_limit=1&bounce_range",
11592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
11602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Start the download and wait for first data chunk.
11622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadItem* download(StartDownloadAndReturnItem(url));
11632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WaitForData(download, GetSafeBufferChunk());
11642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RecordingDownloadObserver recorder(download);
11662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseRSTAndConfirmInterruptForResume(download);
11682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ConfirmFileStatusForResume(
11692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
11702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
11712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadUpdatedObserver completion_observer(
11732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download, base::Bind(DownloadCompleteFilter));
1174a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  download->Resume();
11752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  completion_observer.WaitForEvent();
11762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ConfirmFileStatusForResume(
11782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
11792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath(FILE_PATH_LITERAL("rangereset")));
11802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const RecordingDownloadObserver::RecordStruct expected_record[] = {
11822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Result of RST
11832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
11842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Starting continuation
11852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()},
11862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Notification of receiving whole file.
11872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {DownloadItem::IN_PROGRESS, 0},
11882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Completion.
11892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
11902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
11912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
11932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Confirm restart fallback happens if a precondition is failed.
11962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(DownloadContentTest,
11972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       ResumeInterruptedDownloadBadPrecondition) {
11986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::CommandLine::ForCurrentProcess()->AppendSwitch(
11992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      switches::kEnableDownloadResumption);
12002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(test_server()->Start());
12012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GURL url = test_server()->GetURL(base::StringPrintf(
12035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // First download hits an RST, rest don't, precondition fail.
12045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "rangereset?size=%d&rst_boundary=%d&"
12055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "token=BadPrecondition&rst_limit=1&fail_precondition=2",
12065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GetSafeBufferChunk() * 3,
12075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GetSafeBufferChunk()));
12082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Start the download and wait for first data chunk.
12102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadItem* download(StartDownloadAndReturnItem(url));
12112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WaitForData(download, GetSafeBufferChunk());
12122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RecordingDownloadObserver recorder(download);
12142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseRSTAndConfirmInterruptForResume(download);
12162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ConfirmFileStatusForResume(
12172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
12182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
12195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ("BadPrecondition2", download->GetETag());
12202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadUpdatedObserver completion_observer(
12222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download, base::Bind(DownloadCompleteFilter));
1223a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  download->Resume();
12242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  completion_observer.WaitForEvent();
12252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ConfirmFileStatusForResume(
12272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
12282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath(FILE_PATH_LITERAL("rangereset")));
12295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EXPECT_EQ("BadPrecondition0", download->GetETag());
12302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const RecordingDownloadObserver::RecordStruct expected_record[] = {
12322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Result of RST
12332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
12342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Starting continuation
12352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()},
12362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Server precondition fail.
1237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    {DownloadItem::INTERRUPTED, 0},
12382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Notification of successful restart.
12392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {DownloadItem::IN_PROGRESS, 0},
12402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Completion.
12412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
12422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
12432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
12452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Confirm we don't try to resume if we don't have a verifier.
12482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(DownloadContentTest,
12492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       ResumeInterruptedDownloadNoVerifiers) {
12506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::CommandLine::ForCurrentProcess()->AppendSwitch(
12512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      switches::kEnableDownloadResumption);
12522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(test_server()->Start());
12532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url = test_server()->GetURL(
12552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::StringPrintf(
12562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // First download hits an RST, rest don't, no verifiers.
12572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          "rangereset?size=%d&rst_boundary=%d&"
12582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          "token=NoRange&rst_limit=1&no_verifiers",
12592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
12602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Start the download and wait for first data chunk.
12622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadItem* download(StartDownloadAndReturnItem(url));
12632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WaitForData(download, GetSafeBufferChunk());
12642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RecordingDownloadObserver recorder(download);
12662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseRSTAndConfirmInterruptForResume(download);
12682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ConfirmFileStatusForResume(
12692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download, false, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1270a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      base::FilePath());
12712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadUpdatedObserver completion_observer(
12732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download, base::Bind(DownloadCompleteFilter));
1274a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  download->Resume();
12752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  completion_observer.WaitForEvent();
12762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ConfirmFileStatusForResume(
12782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
12792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath(FILE_PATH_LITERAL("rangereset")));
12802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const RecordingDownloadObserver::RecordStruct expected_record[] = {
12822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Result of RST
12832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
12842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Restart for lack of verifiers
12852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {DownloadItem::IN_PROGRESS, 0},
12862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Completion.
12872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
12882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
12892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
12912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
12922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithDeletedFile) {
12946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::CommandLine::ForCurrentProcess()->AppendSwitch(
12952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      switches::kEnableDownloadResumption);
12962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(test_server()->Start());
12972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url = test_server()->GetURL(
12992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::StringPrintf(
13002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // First download hits an RST, rest don't
13012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          "rangereset?size=%d&rst_boundary=%d&"
13022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          "token=NoRange&rst_limit=1",
13032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
13042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Start the download and wait for first data chunk.
13062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadItem* download(StartDownloadAndReturnItem(url));
13072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WaitForData(download, GetSafeBufferChunk());
13082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RecordingDownloadObserver recorder(download);
13102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseRSTAndConfirmInterruptForResume(download);
13122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ConfirmFileStatusForResume(
13132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
13142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
13152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Delete the intermediate file.
13177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  base::DeleteFile(download->GetFullPath(), false);
13182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadUpdatedObserver completion_observer(
13202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download, base::Bind(DownloadCompleteFilter));
1321a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  download->Resume();
13222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  completion_observer.WaitForEvent();
13232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ConfirmFileStatusForResume(
13252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
13262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath(FILE_PATH_LITERAL("rangereset")));
13272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static const RecordingDownloadObserver::RecordStruct expected_record[] = {
13292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Result of RST
13302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
13312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Starting continuation
13322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()},
13332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Error because file isn't there.
1334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    {DownloadItem::INTERRUPTED, 0},
1335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Restart.
13362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {DownloadItem::IN_PROGRESS, 0},
13372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Completion.
13382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
13392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
13402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
13422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
13432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithFileInitError) {
13456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::CommandLine::ForCurrentProcess()->AppendSwitch(
13462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      switches::kEnableDownloadResumption);
13472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
13481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file));
13492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Setup the error injector.
13512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<TestFileErrorInjector> injector(
13522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
13532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestFileErrorInjector::FileErrorInfo err = {
13552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    url.spec(),
13562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TestFileErrorInjector::FILE_OPERATION_INITIALIZE,
13572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    0,
13582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
13592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
13602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  injector->AddError(err);
13612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  injector->InjectErrors();
13622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Start and watch for interrupt.
1364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<DownloadTestObserver> int_observer(
1365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateInterruptedWaiter(shell(), 1));
13662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadItem* download(StartDownloadAndReturnItem(url));
13672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int_observer->WaitForFinished();
13682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState());
13692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE,
13702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            download->GetLastReason());
13712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(0, download->GetReceivedBytes());
13722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(download->GetFullPath().empty());
13732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(download->GetTargetFilePath().empty());
13742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We need to make sure that any cross-thread downloads communication has
13762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // quiesced before clearing and injecting the new errors, as the
13772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // InjectErrors() routine alters the currently in use download file
13782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // factory, which is a file thread object.
13792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunAllPendingInMessageLoop(BrowserThread::FILE);
13802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunAllPendingInMessageLoop();
13812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Clear the old errors list.
13832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  injector->ClearErrors();
13842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  injector->InjectErrors();
13852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Resume and watch completion.
13872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadUpdatedObserver completion_observer(
13882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download, base::Bind(DownloadCompleteFilter));
1389a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  download->Resume();
13902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  completion_observer.WaitForEvent();
13912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE);
13922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
13932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(DownloadContentTest,
13952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       ResumeWithFileIntermediateRenameError) {
13966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::CommandLine::ForCurrentProcess()->AppendSwitch(
13972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      switches::kEnableDownloadResumption);
13982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
13991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file));
14002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Setup the error injector.
14022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<TestFileErrorInjector> injector(
14032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
14042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestFileErrorInjector::FileErrorInfo err = {
14062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    url.spec(),
14072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TestFileErrorInjector::FILE_OPERATION_RENAME_UNIQUIFY,
14082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    0,
14092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
14102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
14112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  injector->AddError(err);
14122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  injector->InjectErrors();
14132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Start and watch for interrupt.
1415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<DownloadTestObserver> int_observer(
1416eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateInterruptedWaiter(shell(), 1));
14172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadItem* download(StartDownloadAndReturnItem(url));
14182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int_observer->WaitForFinished();
14192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState());
14202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE,
14212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            download->GetLastReason());
14222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(download->GetFullPath().empty());
1423a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Target path will have been set after file name determination. GetFullPath()
1424a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // being empty is sufficient to signal that filename determination needs to be
1425a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // redone.
1426a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_FALSE(download->GetTargetFilePath().empty());
14272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We need to make sure that any cross-thread downloads communication has
14292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // quiesced before clearing and injecting the new errors, as the
14302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // InjectErrors() routine alters the currently in use download file
14312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // factory, which is a file thread object.
14322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunAllPendingInMessageLoop(BrowserThread::FILE);
14332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunAllPendingInMessageLoop();
14342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Clear the old errors list.
14362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  injector->ClearErrors();
14372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  injector->InjectErrors();
14382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Resume and watch completion.
14402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadUpdatedObserver completion_observer(
14412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download, base::Bind(DownloadCompleteFilter));
1442a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  download->Resume();
14432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  completion_observer.WaitForEvent();
14442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE);
14452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
14462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithFileFinalRenameError) {
14486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::CommandLine::ForCurrentProcess()->AppendSwitch(
14492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      switches::kEnableDownloadResumption);
14502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
14511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file));
14522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Setup the error injector.
14542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<TestFileErrorInjector> injector(
14552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
14562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadManagerForShell(shell())->RemoveAllDownloads();
14582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestFileErrorInjector::FileErrorInfo err = {
14592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    url.spec(),
14602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TestFileErrorInjector::FILE_OPERATION_RENAME_ANNOTATE,
14612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    0,
14622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
14632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
14642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  injector->AddError(err);
14652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  injector->InjectErrors();
14662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Start and watch for interrupt.
1468eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<DownloadTestObserver> int_observer(
1469eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      CreateInterruptedWaiter(shell(), 1));
14702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadItem* download(StartDownloadAndReturnItem(url));
14712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int_observer->WaitForFinished();
14722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState());
14732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE,
14742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            download->GetLastReason());
14752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(download->GetFullPath().empty());
1476a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Target path should still be intact.
1477a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  EXPECT_FALSE(download->GetTargetFilePath().empty());
14782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We need to make sure that any cross-thread downloads communication has
14802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // quiesced before clearing and injecting the new errors, as the
14812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // InjectErrors() routine alters the currently in use download file
14822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // factory, which is a file thread object.
14832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunAllPendingInMessageLoop(BrowserThread::FILE);
14842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RunAllPendingInMessageLoop();
14852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Clear the old errors list.
14872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  injector->ClearErrors();
14882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  injector->InjectErrors();
14892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Resume and watch completion.
14912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DownloadUpdatedObserver completion_observer(
14922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      download, base::Bind(DownloadCompleteFilter));
1493a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  download->Resume();
14942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  completion_observer.WaitForEvent();
14952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE);
14962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
14972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
149890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// An interrupted download should remove the intermediate file when it is
149990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// cancelled.
150090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelInterruptedDownload) {
15016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::CommandLine::ForCurrentProcess()->AppendSwitch(
150290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      switches::kEnableDownloadResumption);
150390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(test_server()->Start());
150490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
150590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  GURL url1 = test_server()->GetURL(
150690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
150790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
150890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
150990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DownloadItem* download(StartDownloadAndReturnItem(url1));
151090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WaitForData(download, GetSafeBufferChunk());
151190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
151290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ReleaseRSTAndConfirmInterruptForResume(download);
151390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ConfirmFileStatusForResume(
151490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
151590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
151690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
151790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::FilePath intermediate_path(download->GetFullPath());
151890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_FALSE(intermediate_path.empty());
15197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(base::PathExists(intermediate_path));
152090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
152190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  download->Cancel(true /* user_cancel */);
152290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RunAllPendingInMessageLoop(BrowserThread::FILE);
152390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RunAllPendingInMessageLoop();
152490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
152590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // The intermediate file should now be gone.
15267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(base::PathExists(intermediate_path));
152790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(download->GetFullPath().empty());
152890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
152990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
153090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveDownload) {
15316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::CommandLine::ForCurrentProcess()->AppendSwitch(
153290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      switches::kEnableDownloadResumption);
153390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(test_server()->Start());
153490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
153590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // An interrupted download should remove the intermediate file when it is
153690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // removed.
153790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  {
153890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    GURL url1 = test_server()->GetURL(
153990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
154090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                           GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
154190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
154290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DownloadItem* download(StartDownloadAndReturnItem(url1));
154390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    WaitForData(download, GetSafeBufferChunk());
154490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ReleaseRSTAndConfirmInterruptForResume(download);
154590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ConfirmFileStatusForResume(
154690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
154790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
154890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
154990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::FilePath intermediate_path(download->GetFullPath());
155090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ASSERT_FALSE(intermediate_path.empty());
15517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    EXPECT_TRUE(base::PathExists(intermediate_path));
155290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
155390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    download->Remove();
155490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RunAllPendingInMessageLoop(BrowserThread::FILE);
155590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RunAllPendingInMessageLoop();
155690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
155790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // The intermediate file should now be gone.
15587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    EXPECT_FALSE(base::PathExists(intermediate_path));
155990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
156090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
156190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // A completed download shouldn't delete the downloaded file when it is
156290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // removed.
156390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  {
156490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Start the second download and wait until it's done.
156590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::FilePath file2(FILE_PATH_LITERAL("download-test.lib"));
15661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    GURL url2(net::URLRequestMockHTTPJob::GetMockUrl(file2));
156790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    scoped_ptr<DownloadTestObserver> completion_observer(
156890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        CreateWaiter(shell(), 1));
156990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DownloadItem* download(StartDownloadAndReturnItem(url2));
157090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    completion_observer->WaitForFinished();
157190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
157290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // The target path should exist.
157390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::FilePath target_path(download->GetTargetFilePath());
15747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    EXPECT_TRUE(base::PathExists(target_path));
157590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    download->Remove();
157690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RunAllPendingInMessageLoop(BrowserThread::FILE);
157790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RunAllPendingInMessageLoop();
157890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
157990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // The file should still exist.
15807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    EXPECT_TRUE(base::PathExists(target_path));
158190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
158290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
158390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
158490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveResumingDownload) {
158590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetupEnsureNoPendingDownloads();
15866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::CommandLine::ForCurrentProcess()->AppendSwitch(
158790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      switches::kEnableDownloadResumption);
158890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(test_server()->Start());
158990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
159090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  GURL url = test_server()->GetURL(
159190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
159290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
159390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
159490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell()));
159590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
159690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
159790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DownloadItem* download(StartDownloadAndReturnItem(url));
159890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WaitForData(download, GetSafeBufferChunk());
159990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ::testing::Mock::VerifyAndClearExpectations(&dm_observer);
160090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
160190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Tell the server to send the RST and confirm the interrupt happens.
160290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ReleaseRSTAndConfirmInterruptForResume(download);
160390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ConfirmFileStatusForResume(
160490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
160590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
160690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
160790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::FilePath intermediate_path(download->GetFullPath());
160890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_FALSE(intermediate_path.empty());
16097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(base::PathExists(intermediate_path));
161090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
161190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Resume and remove download. We expect only a single OnDownloadCreated()
161290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // call, and that's for the second download created below.
161390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
161490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  download->Resume();
161590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  download->Remove();
161690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
161790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // The intermediate file should now be gone.
161890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RunAllPendingInMessageLoop(BrowserThread::FILE);
161990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RunAllPendingInMessageLoop();
16207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(base::PathExists(intermediate_path));
162190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
162290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Start the second download and wait until it's done. The test server is
162390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // single threaded. The response to this download request should follow the
162490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // response to the previous resumption request.
162590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  GURL url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x"));
16265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  NavigateToURLAndWaitForDownload(shell(), url2, DownloadItem::COMPLETE);
162790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
162890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(EnsureNoPendingDownloads());
162990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
163090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
163190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelResumingDownload) {
163290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SetupEnsureNoPendingDownloads();
16336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::CommandLine::ForCurrentProcess()->AppendSwitch(
163490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      switches::kEnableDownloadResumption);
163590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_TRUE(test_server()->Start());
163690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
163790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  GURL url = test_server()->GetURL(
163890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
163990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                         GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
164090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
164190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell()));
164290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
164390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
164490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DownloadItem* download(StartDownloadAndReturnItem(url));
164590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  WaitForData(download, GetSafeBufferChunk());
164690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ::testing::Mock::VerifyAndClearExpectations(&dm_observer);
164790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
164890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Tell the server to send the RST and confirm the interrupt happens.
164990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ReleaseRSTAndConfirmInterruptForResume(download);
165090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ConfirmFileStatusForResume(
165190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
165290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
165390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
165490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::FilePath intermediate_path(download->GetFullPath());
165590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_FALSE(intermediate_path.empty());
16567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_TRUE(base::PathExists(intermediate_path));
165790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
165890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Resume and cancel download. We expect only a single OnDownloadCreated()
165990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // call, and that's for the second download created below.
166090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
166190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  download->Resume();
1662868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  download->Cancel(true);
166390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
166490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // The intermediate file should now be gone.
166590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RunAllPendingInMessageLoop(BrowserThread::FILE);
166690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RunAllPendingInMessageLoop();
16677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  EXPECT_FALSE(base::PathExists(intermediate_path));
166890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(download->GetFullPath().empty());
166990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
167090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Start the second download and wait until it's done. The test server is
167190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // single threaded. The response to this download request should follow the
167290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // response to the previous resumption request.
167390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  GURL url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x"));
16745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  NavigateToURLAndWaitForDownload(shell(), url2, DownloadItem::COMPLETE);
167590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
167690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  EXPECT_TRUE(EnsureNoPendingDownloads());
167790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
167890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
16793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Check that the cookie policy is correctly updated when downloading a file
16803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// that redirects cross origin.
16813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(DownloadContentTest, CookiePolicy) {
16823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ASSERT_TRUE(test_server()->Start());
16833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  net::HostPortPair host_port = test_server()->host_port_pair();
16843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK_EQ(host_port.host(), std::string("127.0.0.1"));
16853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
16863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Block third-party cookies.
16873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ShellNetworkDelegate::SetAcceptAllCookies(false);
16883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
16893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // |url| redirects to a different origin |download| which tries to set a
16903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // cookie.
16913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::string download(base::StringPrintf(
16923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      "http://localhost:%d/set-cookie?A=B", host_port.port()));
16933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  GURL url(test_server()->GetURL("server-redirect?" + download));
16943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
16953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Download the file.
16963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  SetupEnsureNoPendingDownloads();
16973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<DownloadUrlParameters> dl_params(
16983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      DownloadUrlParameters::FromWebContents(shell()->web_contents(), url));
16993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  scoped_ptr<DownloadTestObserver> observer(CreateWaiter(shell(), 1));
17003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DownloadManagerForShell(shell())->DownloadUrl(dl_params.Pass());
17013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  observer->WaitForFinished();
17023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
17033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Get the important info from other threads and check it.
17043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_TRUE(EnsureNoPendingDownloads());
17053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
17063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  std::vector<DownloadItem*> downloads;
17073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
17083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ASSERT_EQ(1u, downloads.size());
17093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ASSERT_EQ(DownloadItem::COMPLETE, downloads[0]->GetState());
17103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
17113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Check that the cookies were correctly set.
17123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  EXPECT_EQ("A=B",
17133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            content::GetCookies(shell()->web_contents()->GetBrowserContext(),
17143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                GURL(download)));
17153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
17163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
17175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// A filename suggestion specified via a @download attribute should not be
17185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// effective if the final download URL is in another origin from the original
17195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// download URL.
17205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuIN_PROC_BROWSER_TEST_F(DownloadContentTest,
17215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                       DownloadAttributeCrossOriginRedirect) {
17225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EmbeddedTestServer origin_one;
17235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EmbeddedTestServer origin_two;
17245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ASSERT_TRUE(origin_one.InitializeAndWaitUntilReady());
17255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ASSERT_TRUE(origin_two.InitializeAndWaitUntilReady());
17265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
17275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // The download-attribute.html page contains an anchor element whose href is
17285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // set to the value of the query parameter (specified as |target| in the URL
17295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // below). The suggested filename for the anchor is 'suggested-filename'. When
17305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // the page is loaded, a script simulates a click on the anchor, triggering a
17315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // download of the target URL.
17325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  //
17335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // We construct two test servers; origin_one and origin_two. Once started, the
17345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // server URLs will differ by the port number. Therefore they will be in
17355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // different origins.
17365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  GURL download_url = origin_one.GetURL("/ping");
17375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  GURL referrer_url = origin_one.GetURL(
17385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      std::string("/download-attribute.html?target=") + download_url.spec());
17395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
17405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // <origin_one>/download-attribute.html initiates a download of
17415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // <origin_one>/ping, which redirects to <origin_two>/download.
17425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  origin_one.ServeFilesFromDirectory(GetTestFilePath("download", ""));
17435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  origin_one.RegisterRequestHandler(
17445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      CreateRedirectHandler("/ping", origin_two.GetURL("/download")));
17455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  origin_two.RegisterRequestHandler(CreateBasicResponseHandler(
17465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      "/download", "application/octet-stream", "Hello"));
17475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
17485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  NavigateToURLAndWaitForDownload(
17495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      shell(), referrer_url, DownloadItem::COMPLETE);
17505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
17515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  std::vector<DownloadItem*> downloads;
17525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
17535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ASSERT_EQ(1u, downloads.size());
17545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
17555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(FILE_PATH_LITERAL("download"),
17565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            downloads[0]->GetTargetFilePath().BaseName().value());
17575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ASSERT_TRUE(origin_one.ShutdownAndWaitUntilComplete());
17585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete());
17595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
17605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
17615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// A filename suggestion specified via a @download attribute should be effective
17625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// if the final download URL is in the same origin as the initial download URL.
17635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Test that this holds even if there are cross origin redirects in the middle
17645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// of the redirect chain.
17655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuIN_PROC_BROWSER_TEST_F(DownloadContentTest,
17665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                       DownloadAttributeSameOriginRedirect) {
17675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EmbeddedTestServer origin_one;
17685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EmbeddedTestServer origin_two;
17695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ASSERT_TRUE(origin_one.InitializeAndWaitUntilReady());
17705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ASSERT_TRUE(origin_two.InitializeAndWaitUntilReady());
17715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
17725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // The download-attribute.html page contains an anchor element whose href is
17735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // set to the value of the query parameter (specified as |target| in the URL
17745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // below). The suggested filename for the anchor is 'suggested-filename'. When
17755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // the page is loaded, a script simulates a click on the anchor, triggering a
17765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // download of the target URL.
17775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  //
17785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // We construct two test servers; origin_one and origin_two. Once started, the
17795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // server URLs will differ by the port number. Therefore they will be in
17805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // different origins.
17815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  GURL download_url = origin_one.GetURL("/ping");
17825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  GURL referrer_url = origin_one.GetURL(
17835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      std::string("/download-attribute.html?target=") + download_url.spec());
17845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  origin_one.ServeFilesFromDirectory(GetTestFilePath("download", ""));
17855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
17865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // <origin_one>/download-attribute.html initiates a download of
17875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // <origin_one>/ping, which redirects to <origin_two>/pong, and then finally
17885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // to <origin_one>/download.
17895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  origin_one.RegisterRequestHandler(
17905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      CreateRedirectHandler("/ping", origin_two.GetURL("/pong")));
17915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  origin_two.RegisterRequestHandler(
17925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      CreateRedirectHandler("/pong", origin_one.GetURL("/download")));
17935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  origin_one.RegisterRequestHandler(CreateBasicResponseHandler(
17945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      "/download", "application/octet-stream", "Hello"));
17955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
17965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  NavigateToURLAndWaitForDownload(
17975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      shell(), referrer_url, DownloadItem::COMPLETE);
17985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
17995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  std::vector<DownloadItem*> downloads;
18005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
18015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ASSERT_EQ(1u, downloads.size());
18025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
18035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(FILE_PATH_LITERAL("suggested-filename"),
18045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            downloads[0]->GetTargetFilePath().BaseName().value());
18055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ASSERT_TRUE(origin_one.ShutdownAndWaitUntilComplete());
18065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete());
18075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
18085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1809cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// The file empty.bin is served with a MIME type of application/octet-stream.
1810cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// The content body is empty. Make sure this case is handled properly and we
1811cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// don't regress on http://crbug.com/320394.
1812cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadGZipWithNoContent) {
1813cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EmbeddedTestServer test_server;
1814cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ASSERT_TRUE(test_server.InitializeAndWaitUntilReady());
1815cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1816cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  GURL url = test_server.GetURL("/empty.bin");
1817cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  test_server.ServeFilesFromDirectory(GetTestFilePath("download", ""));
1818cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1819cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE);
1820cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // That's it. This should work without crashing.
1821cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
1822cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
1824