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