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