Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / browser / download / download_browsertest.cc
blobf0ffbe3140624844781f1fd1c9fab1bcc6ea80d2
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.
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.
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 "net/test/embedded_test_server/embedded_test_server.h"
38 #include "net/test/embedded_test_server/http_request.h"
39 #include "net/test/embedded_test_server/http_response.h"
40 #include "net/test/spawned_test_server/spawned_test_server.h"
41 #include "net/test/url_request/url_request_mock_http_job.h"
42 #include "net/test/url_request/url_request_slow_download_job.h"
43 #include "testing/gmock/include/gmock/gmock.h"
44 #include "testing/gtest/include/gtest/gtest.h"
45 #include "url/gurl.h"
47 #if defined(ENABLE_PLUGINS)
48 #include "content/browser/plugin_service_impl.h"
49 #endif
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::_;
60 namespace content {
62 namespace {
64 class MockDownloadItemObserver : public DownloadItem::Observer {
65 public:
66 MockDownloadItemObserver() {}
67 virtual ~MockDownloadItemObserver() {}
69 MOCK_METHOD1(OnDownloadUpdated, void(DownloadItem*));
70 MOCK_METHOD1(OnDownloadOpened, void(DownloadItem*));
71 MOCK_METHOD1(OnDownloadRemoved, void(DownloadItem*));
72 MOCK_METHOD1(OnDownloadDestroyed, void(DownloadItem*));
75 class MockDownloadManagerObserver : public DownloadManager::Observer {
76 public:
77 MockDownloadManagerObserver(DownloadManager* manager) {
78 manager_ = manager;
79 manager->AddObserver(this);
81 virtual ~MockDownloadManagerObserver() {
82 if (manager_)
83 manager_->RemoveObserver(this);
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);
92 manager_->RemoveObserver(this);
93 manager_ = NULL;
96 MOCK_METHOD1(MockManagerGoingDown, void(DownloadManager*));
97 private:
98 DownloadManager* manager_;
101 class DownloadFileWithDelayFactory;
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()));
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);
125 ~DownloadFileWithDelay() override;
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;
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);
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_;
149 DISALLOW_COPY_AND_ASSIGN(DownloadFileWithDelay);
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;
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;
169 void AddRenameCallback(base::Closure callback);
170 void GetAllRenameCallbacks(std::vector<base::Closure>* results);
172 // Do not return until GetAllRenameCallbacks() will return a non-empty list.
173 void WaitForSomeCallback();
175 private:
176 std::vector<base::Closure> rename_callbacks_;
177 bool waiting_;
178 base::WeakPtrFactory<DownloadFileWithDelayFactory> weak_ptr_factory_;
180 DISALLOW_COPY_AND_ASSIGN(DownloadFileWithDelayFactory);
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) {}
199 DownloadFileWithDelay::~DownloadFileWithDelay() {}
201 void DownloadFileWithDelay::RenameAndUniquify(
202 const base::FilePath& full_path,
203 const RenameCompletionCallback& callback) {
204 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
205 DownloadFileImpl::RenameAndUniquify(
206 full_path, base::Bind(DownloadFileWithDelay::RenameCallbackWrapper,
207 owner_, callback));
210 void DownloadFileWithDelay::RenameAndAnnotate(
211 const base::FilePath& full_path, const RenameCompletionCallback& callback) {
212 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
213 DownloadFileImpl::RenameAndAnnotate(
214 full_path, base::Bind(DownloadFileWithDelay::RenameCallbackWrapper,
215 owner_, callback));
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_CURRENTLY_ON(BrowserThread::UI);
225 if (!factory)
226 return;
227 factory->AddRenameCallback(base::Bind(original_callback, reason, path));
230 DownloadFileWithDelayFactory::DownloadFileWithDelayFactory()
231 : waiting_(false),
232 weak_ptr_factory_(this) {}
234 DownloadFileWithDelayFactory::~DownloadFileWithDelayFactory() {}
236 DownloadFile* DownloadFileWithDelayFactory::CreateFile(
237 scoped_ptr<DownloadSaveInfo> save_info,
238 const base::FilePath& default_download_directory,
239 const GURL& url,
240 const GURL& referrer_url,
241 bool calculate_hash,
242 scoped_ptr<ByteStreamReader> stream,
243 const net::BoundNetLog& bound_net_log,
244 base::WeakPtr<DownloadDestinationObserver> observer) {
245 scoped_ptr<PowerSaveBlocker> psb(PowerSaveBlocker::Create(
246 PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
247 PowerSaveBlocker::kReasonOther, "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());
254 void DownloadFileWithDelayFactory::AddRenameCallback(base::Closure callback) {
255 DCHECK_CURRENTLY_ON(BrowserThread::UI);
256 rename_callbacks_.push_back(callback);
257 if (waiting_)
258 base::MessageLoopForUI::current()->Quit();
261 void DownloadFileWithDelayFactory::GetAllRenameCallbacks(
262 std::vector<base::Closure>* results) {
263 DCHECK_CURRENTLY_ON(BrowserThread::UI);
264 results->swap(rename_callbacks_);
267 void DownloadFileWithDelayFactory::WaitForSomeCallback() {
268 DCHECK_CURRENTLY_ON(BrowserThread::UI);
270 if (rename_callbacks_.empty()) {
271 waiting_ = true;
272 RunMessageLoop();
273 waiting_ = false;
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) {}
293 ~CountingDownloadFile() override {
294 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
295 active_files_--;
298 void Initialize(const InitializeCallback& callback) override {
299 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
300 active_files_++;
301 return DownloadFileImpl::Initialize(callback);
304 static void GetNumberActiveFiles(int* result) {
305 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
306 *result = active_files_;
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;
323 private:
324 static int active_files_;
327 int CountingDownloadFile::active_files_ = 0;
329 class CountingDownloadFileFactory : public DownloadFileFactory {
330 public:
331 CountingDownloadFileFactory() {}
332 ~CountingDownloadFileFactory() override {}
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(PowerSaveBlocker::Create(
345 PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
346 PowerSaveBlocker::kReasonOther, "Download in progress"));
347 return new CountingDownloadFile(
348 save_info.Pass(), default_downloads_directory, url, referrer_url,
349 calculate_hash, stream.Pass(), bound_net_log,
350 psb.Pass(), observer);
354 class TestShellDownloadManagerDelegate : public ShellDownloadManagerDelegate {
355 public:
356 TestShellDownloadManagerDelegate()
357 : delay_download_open_(false) {}
358 ~TestShellDownloadManagerDelegate() override {}
360 bool ShouldOpenDownload(
361 DownloadItem* item,
362 const DownloadOpenDelayedCallback& callback) override {
363 if (delay_download_open_) {
364 delayed_callbacks_.push_back(callback);
365 return false;
367 return true;
370 void SetDelayedOpen(bool delay) {
371 delay_download_open_ = delay;
374 void GetDelayedCallbacks(
375 std::vector<DownloadOpenDelayedCallback>* callbacks) {
376 callbacks->swap(delayed_callbacks_);
378 private:
379 bool delay_download_open_;
380 std::vector<DownloadOpenDelayedCallback> delayed_callbacks_;
383 // Record all state transitions and byte counts on the observed download.
384 class RecordingDownloadObserver : DownloadItem::Observer {
385 public:
386 struct RecordStruct {
387 DownloadItem::DownloadState state;
388 int bytes_received;
391 typedef std::vector<RecordStruct> RecordVector;
393 RecordingDownloadObserver(DownloadItem* download)
394 : download_(download) {
395 last_state_.state = download->GetState();
396 last_state_.bytes_received = download->GetReceivedBytes();
397 download_->AddObserver(this);
400 ~RecordingDownloadObserver() override { RemoveObserver(); }
402 void CompareToExpectedRecord(const RecordStruct expected[], size_t size) {
403 EXPECT_EQ(size, record_.size());
404 int min = size > record_.size() ? record_.size() : size;
405 for (int i = 0; i < min; ++i) {
406 EXPECT_EQ(expected[i].state, record_[i].state) << "Iteration " << i;
407 EXPECT_EQ(expected[i].bytes_received, record_[i].bytes_received)
408 << "Iteration " << i;
412 private:
413 void OnDownloadUpdated(DownloadItem* download) override {
414 DCHECK_EQ(download_, download);
415 DownloadItem::DownloadState state = download->GetState();
416 int bytes = download->GetReceivedBytes();
417 if (last_state_.state != state || last_state_.bytes_received > bytes) {
418 last_state_.state = state;
419 last_state_.bytes_received = bytes;
420 record_.push_back(last_state_);
424 void OnDownloadDestroyed(DownloadItem* download) override {
425 DCHECK_EQ(download_, download);
426 RemoveObserver();
429 void RemoveObserver() {
430 if (download_) {
431 download_->RemoveObserver(this);
432 download_ = NULL;
436 DownloadItem* download_;
437 RecordStruct last_state_;
438 RecordVector record_;
441 // Get the next created download.
442 class DownloadCreateObserver : DownloadManager::Observer {
443 public:
444 DownloadCreateObserver(DownloadManager* manager)
445 : manager_(manager),
446 item_(NULL),
447 waiting_(false) {
448 manager_->AddObserver(this);
451 ~DownloadCreateObserver() override {
452 if (manager_)
453 manager_->RemoveObserver(this);
454 manager_ = NULL;
457 void ManagerGoingDown(DownloadManager* manager) override {
458 DCHECK_EQ(manager_, manager);
459 manager_->RemoveObserver(this);
460 manager_ = NULL;
463 void OnDownloadCreated(DownloadManager* manager,
464 DownloadItem* download) override {
465 if (!item_)
466 item_ = download;
468 if (waiting_)
469 base::MessageLoopForUI::current()->Quit();
472 DownloadItem* WaitForFinished() {
473 DCHECK_CURRENTLY_ON(BrowserThread::UI);
474 if (!item_) {
475 waiting_ = true;
476 RunMessageLoop();
477 waiting_ = false;
479 return item_;
482 private:
483 DownloadManager* manager_;
484 DownloadItem* item_;
485 bool waiting_;
489 // Filter for waiting for a certain number of bytes.
490 bool DataReceivedFilter(int number_of_bytes, DownloadItem* download) {
491 return download->GetReceivedBytes() >= number_of_bytes;
494 // Filter for download completion.
495 bool DownloadCompleteFilter(DownloadItem* download) {
496 return download->GetState() == DownloadItem::COMPLETE;
499 // Filter for saving the size of the download when the first IN_PROGRESS
500 // is hit.
501 bool InitialSizeFilter(int* download_size, DownloadItem* download) {
502 if (download->GetState() != DownloadItem::IN_PROGRESS)
503 return false;
505 *download_size = download->GetReceivedBytes();
506 return true;
509 // Request handler to be used with CreateRedirectHandler().
510 scoped_ptr<net::test_server::HttpResponse> HandleRequestAndSendRedirectResponse(
511 const std::string& relative_url,
512 const GURL& target_url,
513 const net::test_server::HttpRequest& request) {
514 scoped_ptr<net::test_server::BasicHttpResponse> response;
515 if (request.relative_url == relative_url) {
516 response.reset(new net::test_server::BasicHttpResponse);
517 response->set_code(net::HTTP_FOUND);
518 response->AddCustomHeader("Location", target_url.spec());
520 return response.Pass();
523 // Creates a request handler for EmbeddedTestServer that responds with a HTTP
524 // 302 redirect if the request URL matches |relative_url|.
525 EmbeddedTestServer::HandleRequestCallback CreateRedirectHandler(
526 const std::string& relative_url,
527 const GURL& target_url) {
528 return base::Bind(
529 &HandleRequestAndSendRedirectResponse, relative_url, target_url);
532 // Request handler to be used with CreateBasicResponseHandler().
533 scoped_ptr<net::test_server::HttpResponse> HandleRequestAndSendBasicResponse(
534 const std::string& relative_url,
535 const std::string& content_type,
536 const std::string& body,
537 const net::test_server::HttpRequest& request) {
538 scoped_ptr<net::test_server::BasicHttpResponse> response;
539 if (request.relative_url == relative_url) {
540 response.reset(new net::test_server::BasicHttpResponse);
541 response->set_content_type(content_type);
542 response->set_content(body);
544 return response.Pass();
547 // Creates a request handler for an EmbeddedTestServer that response with an
548 // HTTP 200 status code, a Content-Type header and a body.
549 EmbeddedTestServer::HandleRequestCallback CreateBasicResponseHandler(
550 const std::string& relative_url,
551 const std::string& content_type,
552 const std::string& body) {
553 return base::Bind(
554 &HandleRequestAndSendBasicResponse, relative_url, content_type, body);
557 } // namespace
559 class DownloadContentTest : public ContentBrowserTest {
560 protected:
561 // An initial send from a website of at least this size will not be
562 // help up by buffering in the underlying downloads ByteStream data
563 // transfer. This is important because on resumption tests we wait
564 // until we've gotten the data we expect before allowing the test server
565 // to send its reset, to get around hard close semantics on the Windows
566 // socket layer implementation.
567 int GetSafeBufferChunk() const {
568 return (DownloadResourceHandler::kDownloadByteStreamSize /
569 ByteStreamWriter::kFractionBufferBeforeSending) + 1;
572 void SetUpOnMainThread() override {
573 ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir());
575 test_delegate_.reset(new TestShellDownloadManagerDelegate());
576 test_delegate_->SetDownloadBehaviorForTesting(downloads_directory_.path());
577 DownloadManager* manager = DownloadManagerForShell(shell());
578 manager->GetDelegate()->Shutdown();
579 manager->SetDelegate(test_delegate_.get());
580 test_delegate_->SetDownloadManager(manager);
582 BrowserThread::PostTask(
583 BrowserThread::IO, FROM_HERE,
584 base::Bind(&net::URLRequestSlowDownloadJob::AddUrlHandler));
585 base::FilePath mock_base(GetTestFilePath("download", ""));
586 BrowserThread::PostTask(
587 BrowserThread::IO, FROM_HERE,
588 base::Bind(
589 &net::URLRequestMockHTTPJob::AddUrlHandlers, mock_base,
590 make_scoped_refptr(content::BrowserThread::GetBlockingPool())));
593 TestShellDownloadManagerDelegate* GetDownloadManagerDelegate() {
594 return test_delegate_.get();
597 // Create a DownloadTestObserverTerminal that will wait for the
598 // specified number of downloads to finish.
599 DownloadTestObserver* CreateWaiter(
600 Shell* shell, int num_downloads) {
601 DownloadManager* download_manager = DownloadManagerForShell(shell);
602 return new DownloadTestObserverTerminal(download_manager, num_downloads,
603 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
606 // Create a DownloadTestObserverInProgress that will wait for the
607 // specified number of downloads to start.
608 DownloadCreateObserver* CreateInProgressWaiter(
609 Shell* shell, int num_downloads) {
610 DownloadManager* download_manager = DownloadManagerForShell(shell);
611 return new DownloadCreateObserver(download_manager);
614 DownloadTestObserver* CreateInterruptedWaiter(
615 Shell* shell, int num_downloads) {
616 DownloadManager* download_manager = DownloadManagerForShell(shell);
617 return new DownloadTestObserverInterrupted(download_manager, num_downloads,
618 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
621 // Note: Cannot be used with other alternative DownloadFileFactorys
622 void SetupEnsureNoPendingDownloads() {
623 DownloadManagerForShell(shell())->SetDownloadFileFactoryForTesting(
624 scoped_ptr<DownloadFileFactory>(
625 new CountingDownloadFileFactory()).Pass());
628 bool EnsureNoPendingDownloads() {
629 bool result = true;
630 BrowserThread::PostTask(
631 BrowserThread::IO, FROM_HERE,
632 base::Bind(&EnsureNoPendingDownloadJobsOnIO, &result));
633 base::MessageLoop::current()->Run();
634 return result &&
635 (CountingDownloadFile::GetNumberActiveFilesFromFileThread() == 0);
638 void NavigateToURLAndWaitForDownload(
639 Shell* shell,
640 const GURL& url,
641 DownloadItem::DownloadState expected_terminal_state) {
642 scoped_ptr<DownloadTestObserver> observer(CreateWaiter(shell, 1));
643 NavigateToURL(shell, url);
644 observer->WaitForFinished();
645 EXPECT_EQ(1u, observer->NumDownloadsSeenInState(expected_terminal_state));
648 // Checks that |path| is has |file_size| bytes, and matches the |value|
649 // string.
650 bool VerifyFile(const base::FilePath& path,
651 const std::string& value,
652 const int64 file_size) {
653 std::string file_contents;
655 bool read = base::ReadFileToString(path, &file_contents);
656 EXPECT_TRUE(read) << "Failed reading file: " << path.value() << std::endl;
657 if (!read)
658 return false; // Couldn't read the file.
660 // Note: we don't handle really large files (more than size_t can hold)
661 // so we will fail in that case.
662 size_t expected_size = static_cast<size_t>(file_size);
664 // Check the size.
665 EXPECT_EQ(expected_size, file_contents.size());
666 if (expected_size != file_contents.size())
667 return false;
669 // Check the contents.
670 EXPECT_EQ(value, file_contents);
671 if (memcmp(file_contents.c_str(), value.c_str(), expected_size) != 0)
672 return false;
674 return true;
677 // Start a download and return the item.
678 DownloadItem* StartDownloadAndReturnItem(GURL url) {
679 scoped_ptr<DownloadCreateObserver> observer(
680 CreateInProgressWaiter(shell(), 1));
681 NavigateToURL(shell(), url);
682 observer->WaitForFinished();
683 std::vector<DownloadItem*> downloads;
684 DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
685 EXPECT_EQ(1u, downloads.size());
686 if (1u != downloads.size())
687 return NULL;
688 return downloads[0];
691 // Wait for data
692 void WaitForData(DownloadItem* download, int size) {
693 DownloadUpdatedObserver data_observer(
694 download, base::Bind(&DataReceivedFilter, size));
695 data_observer.WaitForEvent();
696 ASSERT_EQ(size, download->GetReceivedBytes());
697 ASSERT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
700 // Tell the test server to release a pending RST and confirm
701 // that the interrupt is received properly (for download resumption
702 // testing).
703 void ReleaseRSTAndConfirmInterruptForResume(DownloadItem* download) {
704 scoped_ptr<DownloadTestObserver> rst_observer(
705 CreateInterruptedWaiter(shell(), 1));
706 NavigateToURL(shell(), test_server()->GetURL("download-finish"));
707 rst_observer->WaitForFinished();
708 EXPECT_EQ(DownloadItem::INTERRUPTED, download->GetState());
711 // Confirm file status expected for the given location in a stream
712 // provided by the resume test server.
713 void ConfirmFileStatusForResume(
714 DownloadItem* download, bool file_exists,
715 int received_bytes, int total_bytes,
716 const base::FilePath& expected_filename) {
717 // expected_filename is only known if the file exists.
718 ASSERT_EQ(file_exists, !expected_filename.empty());
719 EXPECT_EQ(received_bytes, download->GetReceivedBytes());
720 EXPECT_EQ(total_bytes, download->GetTotalBytes());
721 EXPECT_EQ(expected_filename.value(),
722 download->GetFullPath().BaseName().value());
723 EXPECT_EQ(file_exists,
724 (!download->GetFullPath().empty() &&
725 base::PathExists(download->GetFullPath())));
727 if (file_exists) {
728 std::string file_contents;
729 EXPECT_TRUE(base::ReadFileToString(
730 download->GetFullPath(), &file_contents));
732 ASSERT_EQ(static_cast<size_t>(received_bytes), file_contents.size());
733 for (int i = 0; i < received_bytes; ++i) {
734 EXPECT_EQ(static_cast<char>((i * 2 + 15) % 256), file_contents[i])
735 << "File contents diverged at position " << i
736 << " for " << expected_filename.value();
738 if (static_cast<char>((i * 2 + 15) % 256) != file_contents[i])
739 return;
744 private:
745 static void EnsureNoPendingDownloadJobsOnIO(bool* result) {
746 if (net::URLRequestSlowDownloadJob::NumberOutstandingRequests())
747 *result = false;
748 BrowserThread::PostTask(
749 BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure());
752 // Location of the downloads directory for these tests
753 base::ScopedTempDir downloads_directory_;
754 scoped_ptr<TestShellDownloadManagerDelegate> test_delegate_;
757 IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadCancelled) {
758 SetupEnsureNoPendingDownloads();
760 // Create a download, wait until it's started, and confirm
761 // we're in the expected state.
762 scoped_ptr<DownloadCreateObserver> observer(
763 CreateInProgressWaiter(shell(), 1));
764 NavigateToURL(shell(), GURL(net::URLRequestSlowDownloadJob::kUnknownSizeUrl));
765 observer->WaitForFinished();
767 std::vector<DownloadItem*> downloads;
768 DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
769 ASSERT_EQ(1u, downloads.size());
770 ASSERT_EQ(DownloadItem::IN_PROGRESS, downloads[0]->GetState());
772 // Cancel the download and wait for download system quiesce.
773 downloads[0]->Cancel(true);
774 scoped_refptr<DownloadTestFlushObserver> flush_observer(
775 new DownloadTestFlushObserver(DownloadManagerForShell(shell())));
776 flush_observer->WaitForFlush();
778 // Get the important info from other threads and check it.
779 EXPECT_TRUE(EnsureNoPendingDownloads());
782 // Check that downloading multiple (in this case, 2) files does not result in
783 // corrupted files.
784 IN_PROC_BROWSER_TEST_F(DownloadContentTest, MultiDownload) {
785 SetupEnsureNoPendingDownloads();
787 // Create a download, wait until it's started, and confirm
788 // we're in the expected state.
789 scoped_ptr<DownloadCreateObserver> observer1(
790 CreateInProgressWaiter(shell(), 1));
791 NavigateToURL(shell(), GURL(net::URLRequestSlowDownloadJob::kUnknownSizeUrl));
792 observer1->WaitForFinished();
794 std::vector<DownloadItem*> downloads;
795 DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
796 ASSERT_EQ(1u, downloads.size());
797 ASSERT_EQ(DownloadItem::IN_PROGRESS, downloads[0]->GetState());
798 DownloadItem* download1 = downloads[0]; // The only download.
800 // Start the second download and wait until it's done.
801 base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
802 GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file));
803 // Download the file and wait.
804 NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE);
806 // Should now have 2 items on the manager.
807 downloads.clear();
808 DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
809 ASSERT_EQ(2u, downloads.size());
810 // We don't know the order of the downloads.
811 DownloadItem* download2 = downloads[(download1 == downloads[0]) ? 1 : 0];
813 ASSERT_EQ(DownloadItem::IN_PROGRESS, download1->GetState());
814 ASSERT_EQ(DownloadItem::COMPLETE, download2->GetState());
816 // Allow the first request to finish.
817 scoped_ptr<DownloadTestObserver> observer2(CreateWaiter(shell(), 1));
818 NavigateToURL(shell(),
819 GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl));
820 observer2->WaitForFinished(); // Wait for the third request.
821 EXPECT_EQ(1u, observer2->NumDownloadsSeenInState(DownloadItem::COMPLETE));
823 // Get the important info from other threads and check it.
824 EXPECT_TRUE(EnsureNoPendingDownloads());
826 // The |DownloadItem|s should now be done and have the final file names.
827 // Verify that the files have the expected data and size.
828 // |file1| should be full of '*'s, and |file2| should be the same as the
829 // source file.
830 base::FilePath file1(download1->GetTargetFilePath());
831 size_t file_size1 = net::URLRequestSlowDownloadJob::kFirstDownloadSize +
832 net::URLRequestSlowDownloadJob::kSecondDownloadSize;
833 std::string expected_contents(file_size1, '*');
834 ASSERT_TRUE(VerifyFile(file1, expected_contents, file_size1));
836 base::FilePath file2(download2->GetTargetFilePath());
837 ASSERT_TRUE(base::ContentsEqual(
838 file2, GetTestFilePath("download", "download-test.lib")));
841 #if defined(ENABLE_PLUGINS)
842 // Content served with a MIME type of application/octet-stream should be
843 // downloaded even when a plugin can be found that handles the file type.
844 IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadOctetStream) {
845 const base::FilePath::CharType kTestFilePath[] =
846 FILE_PATH_LITERAL("octet-stream.abc");
847 const char kTestPluginName[] = "TestPlugin";
848 const char kTestMimeType[] = "application/x-test-mime-type";
849 const char kTestFileType[] = "abc";
851 WebPluginInfo plugin_info;
852 plugin_info.name = base::ASCIIToUTF16(kTestPluginName);
853 plugin_info.mime_types.push_back(
854 WebPluginMimeType(kTestMimeType, kTestFileType, ""));
855 plugin_info.type = WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS;
856 PluginServiceImpl::GetInstance()->RegisterInternalPlugin(plugin_info, false);
858 // The following is served with a Content-Type of application/octet-stream.
859 GURL url(
860 net::URLRequestMockHTTPJob::GetMockUrl(base::FilePath(kTestFilePath)));
861 NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE);
863 #endif
865 // Try to cancel just before we release the download file, by delaying final
866 // rename callback.
867 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelAtFinalRename) {
868 // Setup new factory.
869 DownloadFileWithDelayFactory* file_factory =
870 new DownloadFileWithDelayFactory();
871 DownloadManagerImpl* download_manager(DownloadManagerForShell(shell()));
872 download_manager->SetDownloadFileFactoryForTesting(
873 scoped_ptr<DownloadFileFactory>(file_factory).Pass());
875 // Create a download
876 base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
877 NavigateToURL(shell(), net::URLRequestMockHTTPJob::GetMockUrl(file));
879 // Wait until the first (intermediate file) rename and execute the callback.
880 file_factory->WaitForSomeCallback();
881 std::vector<base::Closure> callbacks;
882 file_factory->GetAllRenameCallbacks(&callbacks);
883 ASSERT_EQ(1u, callbacks.size());
884 callbacks[0].Run();
885 callbacks.clear();
887 // Wait until the second (final) rename callback is posted.
888 file_factory->WaitForSomeCallback();
889 file_factory->GetAllRenameCallbacks(&callbacks);
890 ASSERT_EQ(1u, callbacks.size());
892 // Cancel it.
893 std::vector<DownloadItem*> items;
894 download_manager->GetAllDownloads(&items);
895 ASSERT_EQ(1u, items.size());
896 items[0]->Cancel(true);
897 RunAllPendingInMessageLoop();
899 // Check state.
900 EXPECT_EQ(DownloadItem::CANCELLED, items[0]->GetState());
902 // Run final rename callback.
903 callbacks[0].Run();
904 callbacks.clear();
906 // Check state.
907 EXPECT_EQ(DownloadItem::CANCELLED, items[0]->GetState());
910 // Try to cancel just after we release the download file, by delaying
911 // in ShouldOpenDownload.
912 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelAtRelease) {
913 DownloadManagerImpl* download_manager(DownloadManagerForShell(shell()));
915 // Mark delegate for delayed open.
916 GetDownloadManagerDelegate()->SetDelayedOpen(true);
918 // Setup new factory.
919 DownloadFileWithDelayFactory* file_factory =
920 new DownloadFileWithDelayFactory();
921 download_manager->SetDownloadFileFactoryForTesting(
922 scoped_ptr<DownloadFileFactory>(file_factory).Pass());
924 // Create a download
925 base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
926 NavigateToURL(shell(), net::URLRequestMockHTTPJob::GetMockUrl(file));
928 // Wait until the first (intermediate file) rename and execute the callback.
929 file_factory->WaitForSomeCallback();
930 std::vector<base::Closure> callbacks;
931 file_factory->GetAllRenameCallbacks(&callbacks);
932 ASSERT_EQ(1u, callbacks.size());
933 callbacks[0].Run();
934 callbacks.clear();
936 // Wait until the second (final) rename callback is posted.
937 file_factory->WaitForSomeCallback();
938 file_factory->GetAllRenameCallbacks(&callbacks);
939 ASSERT_EQ(1u, callbacks.size());
941 // Call it.
942 callbacks[0].Run();
943 callbacks.clear();
945 // Confirm download still IN_PROGRESS (internal state COMPLETING).
946 std::vector<DownloadItem*> items;
947 download_manager->GetAllDownloads(&items);
948 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
950 // Cancel the download; confirm cancel fails.
951 ASSERT_EQ(1u, items.size());
952 items[0]->Cancel(true);
953 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
955 // Need to complete open test.
956 std::vector<DownloadOpenDelayedCallback> delayed_callbacks;
957 GetDownloadManagerDelegate()->GetDelayedCallbacks(
958 &delayed_callbacks);
959 ASSERT_EQ(1u, delayed_callbacks.size());
960 delayed_callbacks[0].Run(true);
962 // *Now* the download should be complete.
963 EXPECT_EQ(DownloadItem::COMPLETE, items[0]->GetState());
966 // Try to shutdown with a download in progress to make sure shutdown path
967 // works properly.
968 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownInProgress) {
969 // Create a download that won't complete.
970 scoped_ptr<DownloadCreateObserver> observer(
971 CreateInProgressWaiter(shell(), 1));
972 NavigateToURL(shell(), GURL(net::URLRequestSlowDownloadJob::kUnknownSizeUrl));
973 observer->WaitForFinished();
975 // Get the item.
976 std::vector<DownloadItem*> items;
977 DownloadManagerForShell(shell())->GetAllDownloads(&items);
978 ASSERT_EQ(1u, items.size());
979 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
981 // Shutdown the download manager and make sure we get the right
982 // notifications in the right order.
983 StrictMock<MockDownloadItemObserver> item_observer;
984 items[0]->AddObserver(&item_observer);
985 MockDownloadManagerObserver manager_observer(
986 DownloadManagerForShell(shell()));
987 // Don't care about ModelChanged() events.
988 EXPECT_CALL(manager_observer, ModelChanged(_))
989 .WillRepeatedly(Return());
991 InSequence notifications;
993 EXPECT_CALL(manager_observer, MockManagerGoingDown(
994 DownloadManagerForShell(shell())))
995 .WillOnce(Return());
996 EXPECT_CALL(item_observer, OnDownloadUpdated(
997 AllOf(items[0],
998 Property(&DownloadItem::GetState, DownloadItem::CANCELLED))))
999 .WillOnce(Return());
1000 EXPECT_CALL(item_observer, OnDownloadDestroyed(items[0]))
1001 .WillOnce(Return());
1004 // See http://crbug.com/324525. If we have a refcount release/post task
1005 // race, the second post will stall the IO thread long enough so that we'll
1006 // lose the race and crash. The first stall is just to give the UI thread
1007 // a chance to get the second stall onto the IO thread queue after the cancel
1008 // message created by Shutdown and before the notification callback
1009 // created by the IO thread in canceling the request.
1010 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
1011 base::Bind(&base::PlatformThread::Sleep,
1012 base::TimeDelta::FromMilliseconds(25)));
1013 DownloadManagerForShell(shell())->Shutdown();
1014 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
1015 base::Bind(&base::PlatformThread::Sleep,
1016 base::TimeDelta::FromMilliseconds(25)));
1017 items.clear();
1020 // Try to shutdown just after we release the download file, by delaying
1021 // release.
1022 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownAtRelease) {
1023 DownloadManagerImpl* download_manager(DownloadManagerForShell(shell()));
1025 // Mark delegate for delayed open.
1026 GetDownloadManagerDelegate()->SetDelayedOpen(true);
1028 // Setup new factory.
1029 DownloadFileWithDelayFactory* file_factory =
1030 new DownloadFileWithDelayFactory();
1031 download_manager->SetDownloadFileFactoryForTesting(
1032 scoped_ptr<DownloadFileFactory>(file_factory).Pass());
1034 // Create a download
1035 base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
1036 NavigateToURL(shell(), net::URLRequestMockHTTPJob::GetMockUrl(file));
1038 // Wait until the first (intermediate file) rename and execute the callback.
1039 file_factory->WaitForSomeCallback();
1040 std::vector<base::Closure> callbacks;
1041 file_factory->GetAllRenameCallbacks(&callbacks);
1042 ASSERT_EQ(1u, callbacks.size());
1043 callbacks[0].Run();
1044 callbacks.clear();
1046 // Wait until the second (final) rename callback is posted.
1047 file_factory->WaitForSomeCallback();
1048 file_factory->GetAllRenameCallbacks(&callbacks);
1049 ASSERT_EQ(1u, callbacks.size());
1051 // Call it.
1052 callbacks[0].Run();
1053 callbacks.clear();
1055 // Confirm download isn't complete yet.
1056 std::vector<DownloadItem*> items;
1057 DownloadManagerForShell(shell())->GetAllDownloads(&items);
1058 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
1060 // Cancel the download; confirm cancel fails anyway.
1061 ASSERT_EQ(1u, items.size());
1062 items[0]->Cancel(true);
1063 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
1064 RunAllPendingInMessageLoop();
1065 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
1067 MockDownloadItemObserver observer;
1068 items[0]->AddObserver(&observer);
1069 EXPECT_CALL(observer, OnDownloadDestroyed(items[0]));
1071 // Shutdown the download manager. Mostly this is confirming a lack of
1072 // crashes.
1073 DownloadManagerForShell(shell())->Shutdown();
1076 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeInterruptedDownload) {
1077 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1078 switches::kEnableDownloadResumption);
1079 ASSERT_TRUE(test_server()->Start());
1081 GURL url = test_server()->GetURL(
1082 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1083 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1085 MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell()));
1086 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
1088 DownloadItem* download(StartDownloadAndReturnItem(url));
1089 WaitForData(download, GetSafeBufferChunk());
1090 ::testing::Mock::VerifyAndClearExpectations(&dm_observer);
1092 // Confirm resumption while in progress doesn't do anything.
1093 download->Resume();
1094 ASSERT_EQ(GetSafeBufferChunk(), download->GetReceivedBytes());
1095 ASSERT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
1097 // Tell the server to send the RST and confirm the interrupt happens.
1098 ReleaseRSTAndConfirmInterruptForResume(download);
1099 ConfirmFileStatusForResume(
1100 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1101 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1103 // Resume, confirming received bytes on resumption is correct.
1104 // Make sure no creation calls are included.
1105 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(0);
1106 int initial_size = 0;
1107 DownloadUpdatedObserver initial_size_observer(
1108 download, base::Bind(&InitialSizeFilter, &initial_size));
1109 download->Resume();
1110 initial_size_observer.WaitForEvent();
1111 EXPECT_EQ(GetSafeBufferChunk(), initial_size);
1112 ::testing::Mock::VerifyAndClearExpectations(&dm_observer);
1114 // and wait for expected data.
1115 WaitForData(download, GetSafeBufferChunk() * 2);
1117 // Tell the server to send the RST and confirm the interrupt happens.
1118 ReleaseRSTAndConfirmInterruptForResume(download);
1119 ConfirmFileStatusForResume(
1120 download, true, GetSafeBufferChunk() * 2, GetSafeBufferChunk() * 3,
1121 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1123 // Resume and wait for completion.
1124 DownloadUpdatedObserver completion_observer(
1125 download, base::Bind(DownloadCompleteFilter));
1126 download->Resume();
1127 completion_observer.WaitForEvent();
1129 ConfirmFileStatusForResume(
1130 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1131 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1133 // Confirm resumption while complete doesn't do anything.
1134 download->Resume();
1135 ASSERT_EQ(GetSafeBufferChunk() * 3, download->GetReceivedBytes());
1136 ASSERT_EQ(DownloadItem::COMPLETE, download->GetState());
1137 RunAllPendingInMessageLoop();
1138 ASSERT_EQ(GetSafeBufferChunk() * 3, download->GetReceivedBytes());
1139 ASSERT_EQ(DownloadItem::COMPLETE, download->GetState());
1142 // Confirm restart fallback happens if a range request is bounced.
1143 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeInterruptedDownloadNoRange) {
1144 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1145 switches::kEnableDownloadResumption);
1146 ASSERT_TRUE(test_server()->Start());
1148 // Auto-restart if server doesn't handle ranges.
1149 GURL url = test_server()->GetURL(
1150 base::StringPrintf(
1151 // First download hits an RST, rest don't, no ranges.
1152 "rangereset?size=%d&rst_boundary=%d&"
1153 "token=NoRange&rst_limit=1&bounce_range",
1154 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1156 // Start the download and wait for first data chunk.
1157 DownloadItem* download(StartDownloadAndReturnItem(url));
1158 WaitForData(download, GetSafeBufferChunk());
1160 RecordingDownloadObserver recorder(download);
1162 ReleaseRSTAndConfirmInterruptForResume(download);
1163 ConfirmFileStatusForResume(
1164 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1165 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1167 DownloadUpdatedObserver completion_observer(
1168 download, base::Bind(DownloadCompleteFilter));
1169 download->Resume();
1170 completion_observer.WaitForEvent();
1172 ConfirmFileStatusForResume(
1173 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1174 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1176 static const RecordingDownloadObserver::RecordStruct expected_record[] = {
1177 // Result of RST
1178 {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
1179 // Starting continuation
1180 {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()},
1181 // Notification of receiving whole file.
1182 {DownloadItem::IN_PROGRESS, 0},
1183 // Completion.
1184 {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
1187 recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
1190 // Confirm restart fallback happens if a precondition is failed.
1191 IN_PROC_BROWSER_TEST_F(DownloadContentTest,
1192 ResumeInterruptedDownloadBadPrecondition) {
1193 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1194 switches::kEnableDownloadResumption);
1195 ASSERT_TRUE(test_server()->Start());
1197 GURL url = test_server()->GetURL(base::StringPrintf(
1198 // First download hits an RST, rest don't, precondition fail.
1199 "rangereset?size=%d&rst_boundary=%d&"
1200 "token=BadPrecondition&rst_limit=1&fail_precondition=2",
1201 GetSafeBufferChunk() * 3,
1202 GetSafeBufferChunk()));
1204 // Start the download and wait for first data chunk.
1205 DownloadItem* download(StartDownloadAndReturnItem(url));
1206 WaitForData(download, GetSafeBufferChunk());
1208 RecordingDownloadObserver recorder(download);
1210 ReleaseRSTAndConfirmInterruptForResume(download);
1211 ConfirmFileStatusForResume(
1212 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1213 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1214 EXPECT_EQ("BadPrecondition2", download->GetETag());
1216 DownloadUpdatedObserver completion_observer(
1217 download, base::Bind(DownloadCompleteFilter));
1218 download->Resume();
1219 completion_observer.WaitForEvent();
1221 ConfirmFileStatusForResume(
1222 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1223 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1224 EXPECT_EQ("BadPrecondition0", download->GetETag());
1226 static const RecordingDownloadObserver::RecordStruct expected_record[] = {
1227 // Result of RST
1228 {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
1229 // Starting continuation
1230 {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()},
1231 // Server precondition fail.
1232 {DownloadItem::INTERRUPTED, 0},
1233 // Notification of successful restart.
1234 {DownloadItem::IN_PROGRESS, 0},
1235 // Completion.
1236 {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
1239 recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
1242 // Confirm we don't try to resume if we don't have a verifier.
1243 IN_PROC_BROWSER_TEST_F(DownloadContentTest,
1244 ResumeInterruptedDownloadNoVerifiers) {
1245 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1246 switches::kEnableDownloadResumption);
1247 ASSERT_TRUE(test_server()->Start());
1249 GURL url = test_server()->GetURL(
1250 base::StringPrintf(
1251 // First download hits an RST, rest don't, no verifiers.
1252 "rangereset?size=%d&rst_boundary=%d&"
1253 "token=NoRange&rst_limit=1&no_verifiers",
1254 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1256 // Start the download and wait for first data chunk.
1257 DownloadItem* download(StartDownloadAndReturnItem(url));
1258 WaitForData(download, GetSafeBufferChunk());
1260 RecordingDownloadObserver recorder(download);
1262 ReleaseRSTAndConfirmInterruptForResume(download);
1263 ConfirmFileStatusForResume(
1264 download, false, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1265 base::FilePath());
1267 DownloadUpdatedObserver completion_observer(
1268 download, base::Bind(DownloadCompleteFilter));
1269 download->Resume();
1270 completion_observer.WaitForEvent();
1272 ConfirmFileStatusForResume(
1273 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1274 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1276 static const RecordingDownloadObserver::RecordStruct expected_record[] = {
1277 // Result of RST
1278 {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
1279 // Restart for lack of verifiers
1280 {DownloadItem::IN_PROGRESS, 0},
1281 // Completion.
1282 {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
1285 recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
1288 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithDeletedFile) {
1289 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1290 switches::kEnableDownloadResumption);
1291 ASSERT_TRUE(test_server()->Start());
1293 GURL url = test_server()->GetURL(
1294 base::StringPrintf(
1295 // First download hits an RST, rest don't
1296 "rangereset?size=%d&rst_boundary=%d&"
1297 "token=NoRange&rst_limit=1",
1298 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1300 // Start the download and wait for first data chunk.
1301 DownloadItem* download(StartDownloadAndReturnItem(url));
1302 WaitForData(download, GetSafeBufferChunk());
1304 RecordingDownloadObserver recorder(download);
1306 ReleaseRSTAndConfirmInterruptForResume(download);
1307 ConfirmFileStatusForResume(
1308 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1309 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1311 // Delete the intermediate file.
1312 base::DeleteFile(download->GetFullPath(), false);
1314 DownloadUpdatedObserver completion_observer(
1315 download, base::Bind(DownloadCompleteFilter));
1316 download->Resume();
1317 completion_observer.WaitForEvent();
1319 ConfirmFileStatusForResume(
1320 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1321 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1323 static const RecordingDownloadObserver::RecordStruct expected_record[] = {
1324 // Result of RST
1325 {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
1326 // Starting continuation
1327 {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()},
1328 // Error because file isn't there.
1329 {DownloadItem::INTERRUPTED, 0},
1330 // Restart.
1331 {DownloadItem::IN_PROGRESS, 0},
1332 // Completion.
1333 {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
1336 recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
1339 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithFileInitError) {
1340 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1341 switches::kEnableDownloadResumption);
1342 base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
1343 GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file));
1345 // Setup the error injector.
1346 scoped_refptr<TestFileErrorInjector> injector(
1347 TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
1349 TestFileErrorInjector::FileErrorInfo err = {
1350 url.spec(),
1351 TestFileErrorInjector::FILE_OPERATION_INITIALIZE,
1353 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
1355 injector->AddError(err);
1356 injector->InjectErrors();
1358 // Start and watch for interrupt.
1359 scoped_ptr<DownloadTestObserver> int_observer(
1360 CreateInterruptedWaiter(shell(), 1));
1361 DownloadItem* download(StartDownloadAndReturnItem(url));
1362 int_observer->WaitForFinished();
1363 ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState());
1364 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE,
1365 download->GetLastReason());
1366 EXPECT_EQ(0, download->GetReceivedBytes());
1367 EXPECT_TRUE(download->GetFullPath().empty());
1368 EXPECT_TRUE(download->GetTargetFilePath().empty());
1370 // We need to make sure that any cross-thread downloads communication has
1371 // quiesced before clearing and injecting the new errors, as the
1372 // InjectErrors() routine alters the currently in use download file
1373 // factory, which is a file thread object.
1374 RunAllPendingInMessageLoop(BrowserThread::FILE);
1375 RunAllPendingInMessageLoop();
1377 // Clear the old errors list.
1378 injector->ClearErrors();
1379 injector->InjectErrors();
1381 // Resume and watch completion.
1382 DownloadUpdatedObserver completion_observer(
1383 download, base::Bind(DownloadCompleteFilter));
1384 download->Resume();
1385 completion_observer.WaitForEvent();
1386 EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE);
1389 IN_PROC_BROWSER_TEST_F(DownloadContentTest,
1390 ResumeWithFileIntermediateRenameError) {
1391 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1392 switches::kEnableDownloadResumption);
1393 base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
1394 GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file));
1396 // Setup the error injector.
1397 scoped_refptr<TestFileErrorInjector> injector(
1398 TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
1400 TestFileErrorInjector::FileErrorInfo err = {
1401 url.spec(),
1402 TestFileErrorInjector::FILE_OPERATION_RENAME_UNIQUIFY,
1404 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
1406 injector->AddError(err);
1407 injector->InjectErrors();
1409 // Start and watch for interrupt.
1410 scoped_ptr<DownloadTestObserver> int_observer(
1411 CreateInterruptedWaiter(shell(), 1));
1412 DownloadItem* download(StartDownloadAndReturnItem(url));
1413 int_observer->WaitForFinished();
1414 ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState());
1415 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE,
1416 download->GetLastReason());
1417 EXPECT_TRUE(download->GetFullPath().empty());
1418 // Target path will have been set after file name determination. GetFullPath()
1419 // being empty is sufficient to signal that filename determination needs to be
1420 // redone.
1421 EXPECT_FALSE(download->GetTargetFilePath().empty());
1423 // We need to make sure that any cross-thread downloads communication has
1424 // quiesced before clearing and injecting the new errors, as the
1425 // InjectErrors() routine alters the currently in use download file
1426 // factory, which is a file thread object.
1427 RunAllPendingInMessageLoop(BrowserThread::FILE);
1428 RunAllPendingInMessageLoop();
1430 // Clear the old errors list.
1431 injector->ClearErrors();
1432 injector->InjectErrors();
1434 // Resume and watch completion.
1435 DownloadUpdatedObserver completion_observer(
1436 download, base::Bind(DownloadCompleteFilter));
1437 download->Resume();
1438 completion_observer.WaitForEvent();
1439 EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE);
1442 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithFileFinalRenameError) {
1443 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1444 switches::kEnableDownloadResumption);
1445 base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
1446 GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file));
1448 // Setup the error injector.
1449 scoped_refptr<TestFileErrorInjector> injector(
1450 TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
1452 DownloadManagerForShell(shell())->RemoveAllDownloads();
1453 TestFileErrorInjector::FileErrorInfo err = {
1454 url.spec(),
1455 TestFileErrorInjector::FILE_OPERATION_RENAME_ANNOTATE,
1457 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
1459 injector->AddError(err);
1460 injector->InjectErrors();
1462 // Start and watch for interrupt.
1463 scoped_ptr<DownloadTestObserver> int_observer(
1464 CreateInterruptedWaiter(shell(), 1));
1465 DownloadItem* download(StartDownloadAndReturnItem(url));
1466 int_observer->WaitForFinished();
1467 ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState());
1468 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE,
1469 download->GetLastReason());
1470 EXPECT_TRUE(download->GetFullPath().empty());
1471 // Target path should still be intact.
1472 EXPECT_FALSE(download->GetTargetFilePath().empty());
1474 // We need to make sure that any cross-thread downloads communication has
1475 // quiesced before clearing and injecting the new errors, as the
1476 // InjectErrors() routine alters the currently in use download file
1477 // factory, which is a file thread object.
1478 RunAllPendingInMessageLoop(BrowserThread::FILE);
1479 RunAllPendingInMessageLoop();
1481 // Clear the old errors list.
1482 injector->ClearErrors();
1483 injector->InjectErrors();
1485 // Resume and watch completion.
1486 DownloadUpdatedObserver completion_observer(
1487 download, base::Bind(DownloadCompleteFilter));
1488 download->Resume();
1489 completion_observer.WaitForEvent();
1490 EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE);
1493 // An interrupted download should remove the intermediate file when it is
1494 // cancelled.
1495 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelInterruptedDownload) {
1496 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1497 switches::kEnableDownloadResumption);
1498 ASSERT_TRUE(test_server()->Start());
1500 GURL url1 = test_server()->GetURL(
1501 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1502 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1504 DownloadItem* download(StartDownloadAndReturnItem(url1));
1505 WaitForData(download, GetSafeBufferChunk());
1507 ReleaseRSTAndConfirmInterruptForResume(download);
1508 ConfirmFileStatusForResume(
1509 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1510 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1512 base::FilePath intermediate_path(download->GetFullPath());
1513 ASSERT_FALSE(intermediate_path.empty());
1514 EXPECT_TRUE(base::PathExists(intermediate_path));
1516 download->Cancel(true /* user_cancel */);
1517 RunAllPendingInMessageLoop(BrowserThread::FILE);
1518 RunAllPendingInMessageLoop();
1520 // The intermediate file should now be gone.
1521 EXPECT_FALSE(base::PathExists(intermediate_path));
1522 EXPECT_TRUE(download->GetFullPath().empty());
1525 IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveDownload) {
1526 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1527 switches::kEnableDownloadResumption);
1528 ASSERT_TRUE(test_server()->Start());
1530 // An interrupted download should remove the intermediate file when it is
1531 // removed.
1533 GURL url1 = test_server()->GetURL(
1534 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1535 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1537 DownloadItem* download(StartDownloadAndReturnItem(url1));
1538 WaitForData(download, GetSafeBufferChunk());
1539 ReleaseRSTAndConfirmInterruptForResume(download);
1540 ConfirmFileStatusForResume(
1541 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1542 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1544 base::FilePath intermediate_path(download->GetFullPath());
1545 ASSERT_FALSE(intermediate_path.empty());
1546 EXPECT_TRUE(base::PathExists(intermediate_path));
1548 download->Remove();
1549 RunAllPendingInMessageLoop(BrowserThread::FILE);
1550 RunAllPendingInMessageLoop();
1552 // The intermediate file should now be gone.
1553 EXPECT_FALSE(base::PathExists(intermediate_path));
1556 // A completed download shouldn't delete the downloaded file when it is
1557 // removed.
1559 // Start the second download and wait until it's done.
1560 base::FilePath file2(FILE_PATH_LITERAL("download-test.lib"));
1561 GURL url2(net::URLRequestMockHTTPJob::GetMockUrl(file2));
1562 scoped_ptr<DownloadTestObserver> completion_observer(
1563 CreateWaiter(shell(), 1));
1564 DownloadItem* download(StartDownloadAndReturnItem(url2));
1565 completion_observer->WaitForFinished();
1567 // The target path should exist.
1568 base::FilePath target_path(download->GetTargetFilePath());
1569 EXPECT_TRUE(base::PathExists(target_path));
1570 download->Remove();
1571 RunAllPendingInMessageLoop(BrowserThread::FILE);
1572 RunAllPendingInMessageLoop();
1574 // The file should still exist.
1575 EXPECT_TRUE(base::PathExists(target_path));
1579 IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveResumingDownload) {
1580 SetupEnsureNoPendingDownloads();
1581 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1582 switches::kEnableDownloadResumption);
1583 ASSERT_TRUE(test_server()->Start());
1585 GURL url = test_server()->GetURL(
1586 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1587 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1589 MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell()));
1590 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
1592 DownloadItem* download(StartDownloadAndReturnItem(url));
1593 WaitForData(download, GetSafeBufferChunk());
1594 ::testing::Mock::VerifyAndClearExpectations(&dm_observer);
1596 // Tell the server to send the RST and confirm the interrupt happens.
1597 ReleaseRSTAndConfirmInterruptForResume(download);
1598 ConfirmFileStatusForResume(
1599 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1600 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1602 base::FilePath intermediate_path(download->GetFullPath());
1603 ASSERT_FALSE(intermediate_path.empty());
1604 EXPECT_TRUE(base::PathExists(intermediate_path));
1606 // Resume and remove download. We expect only a single OnDownloadCreated()
1607 // call, and that's for the second download created below.
1608 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
1609 download->Resume();
1610 download->Remove();
1612 // The intermediate file should now be gone.
1613 RunAllPendingInMessageLoop(BrowserThread::FILE);
1614 RunAllPendingInMessageLoop();
1615 EXPECT_FALSE(base::PathExists(intermediate_path));
1617 // Start the second download and wait until it's done. The test server is
1618 // single threaded. The response to this download request should follow the
1619 // response to the previous resumption request.
1620 GURL url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x"));
1621 NavigateToURLAndWaitForDownload(shell(), url2, DownloadItem::COMPLETE);
1623 EXPECT_TRUE(EnsureNoPendingDownloads());
1626 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelResumingDownload) {
1627 SetupEnsureNoPendingDownloads();
1628 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1629 switches::kEnableDownloadResumption);
1630 ASSERT_TRUE(test_server()->Start());
1632 GURL url = test_server()->GetURL(
1633 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1634 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1636 MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell()));
1637 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
1639 DownloadItem* download(StartDownloadAndReturnItem(url));
1640 WaitForData(download, GetSafeBufferChunk());
1641 ::testing::Mock::VerifyAndClearExpectations(&dm_observer);
1643 // Tell the server to send the RST and confirm the interrupt happens.
1644 ReleaseRSTAndConfirmInterruptForResume(download);
1645 ConfirmFileStatusForResume(
1646 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1647 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1649 base::FilePath intermediate_path(download->GetFullPath());
1650 ASSERT_FALSE(intermediate_path.empty());
1651 EXPECT_TRUE(base::PathExists(intermediate_path));
1653 // Resume and cancel download. We expect only a single OnDownloadCreated()
1654 // call, and that's for the second download created below.
1655 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
1656 download->Resume();
1657 download->Cancel(true);
1659 // The intermediate file should now be gone.
1660 RunAllPendingInMessageLoop(BrowserThread::FILE);
1661 RunAllPendingInMessageLoop();
1662 EXPECT_FALSE(base::PathExists(intermediate_path));
1663 EXPECT_TRUE(download->GetFullPath().empty());
1665 // Start the second download and wait until it's done. The test server is
1666 // single threaded. The response to this download request should follow the
1667 // response to the previous resumption request.
1668 GURL url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x"));
1669 NavigateToURLAndWaitForDownload(shell(), url2, DownloadItem::COMPLETE);
1671 EXPECT_TRUE(EnsureNoPendingDownloads());
1674 // Check that the cookie policy is correctly updated when downloading a file
1675 // that redirects cross origin.
1676 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CookiePolicy) {
1677 ASSERT_TRUE(test_server()->Start());
1678 net::HostPortPair host_port = test_server()->host_port_pair();
1679 DCHECK_EQ(host_port.host(), std::string("127.0.0.1"));
1681 // Block third-party cookies.
1682 ShellNetworkDelegate::SetAcceptAllCookies(false);
1684 // |url| redirects to a different origin |download| which tries to set a
1685 // cookie.
1686 std::string download(base::StringPrintf(
1687 "http://localhost:%d/set-cookie?A=B", host_port.port()));
1688 GURL url(test_server()->GetURL("server-redirect?" + download));
1690 // Download the file.
1691 SetupEnsureNoPendingDownloads();
1692 scoped_ptr<DownloadUrlParameters> dl_params(
1693 DownloadUrlParameters::FromWebContents(shell()->web_contents(), url));
1694 scoped_ptr<DownloadTestObserver> observer(CreateWaiter(shell(), 1));
1695 DownloadManagerForShell(shell())->DownloadUrl(dl_params.Pass());
1696 observer->WaitForFinished();
1698 // Get the important info from other threads and check it.
1699 EXPECT_TRUE(EnsureNoPendingDownloads());
1701 std::vector<DownloadItem*> downloads;
1702 DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
1703 ASSERT_EQ(1u, downloads.size());
1704 ASSERT_EQ(DownloadItem::COMPLETE, downloads[0]->GetState());
1706 // Check that the cookies were correctly set.
1707 EXPECT_EQ("A=B",
1708 content::GetCookies(shell()->web_contents()->GetBrowserContext(),
1709 GURL(download)));
1712 // A filename suggestion specified via a @download attribute should not be
1713 // effective if the final download URL is in another origin from the original
1714 // download URL.
1715 IN_PROC_BROWSER_TEST_F(DownloadContentTest,
1716 DownloadAttributeCrossOriginRedirect) {
1717 EmbeddedTestServer origin_one;
1718 EmbeddedTestServer origin_two;
1719 ASSERT_TRUE(origin_one.InitializeAndWaitUntilReady());
1720 ASSERT_TRUE(origin_two.InitializeAndWaitUntilReady());
1722 // The download-attribute.html page contains an anchor element whose href is
1723 // set to the value of the query parameter (specified as |target| in the URL
1724 // below). The suggested filename for the anchor is 'suggested-filename'. When
1725 // the page is loaded, a script simulates a click on the anchor, triggering a
1726 // download of the target URL.
1728 // We construct two test servers; origin_one and origin_two. Once started, the
1729 // server URLs will differ by the port number. Therefore they will be in
1730 // different origins.
1731 GURL download_url = origin_one.GetURL("/ping");
1732 GURL referrer_url = origin_one.GetURL(
1733 std::string("/download-attribute.html?target=") + download_url.spec());
1735 // <origin_one>/download-attribute.html initiates a download of
1736 // <origin_one>/ping, which redirects to <origin_two>/download.
1737 origin_one.ServeFilesFromDirectory(GetTestFilePath("download", ""));
1738 origin_one.RegisterRequestHandler(
1739 CreateRedirectHandler("/ping", origin_two.GetURL("/download")));
1740 origin_two.RegisterRequestHandler(CreateBasicResponseHandler(
1741 "/download", "application/octet-stream", "Hello"));
1743 NavigateToURLAndWaitForDownload(
1744 shell(), referrer_url, DownloadItem::COMPLETE);
1746 std::vector<DownloadItem*> downloads;
1747 DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
1748 ASSERT_EQ(1u, downloads.size());
1750 EXPECT_EQ(FILE_PATH_LITERAL("download"),
1751 downloads[0]->GetTargetFilePath().BaseName().value());
1752 ASSERT_TRUE(origin_one.ShutdownAndWaitUntilComplete());
1753 ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete());
1756 // A filename suggestion specified via a @download attribute should be effective
1757 // if the final download URL is in the same origin as the initial download URL.
1758 // Test that this holds even if there are cross origin redirects in the middle
1759 // of the redirect chain.
1760 IN_PROC_BROWSER_TEST_F(DownloadContentTest,
1761 DownloadAttributeSameOriginRedirect) {
1762 EmbeddedTestServer origin_one;
1763 EmbeddedTestServer origin_two;
1764 ASSERT_TRUE(origin_one.InitializeAndWaitUntilReady());
1765 ASSERT_TRUE(origin_two.InitializeAndWaitUntilReady());
1767 // The download-attribute.html page contains an anchor element whose href is
1768 // set to the value of the query parameter (specified as |target| in the URL
1769 // below). The suggested filename for the anchor is 'suggested-filename'. When
1770 // the page is loaded, a script simulates a click on the anchor, triggering a
1771 // download of the target URL.
1773 // We construct two test servers; origin_one and origin_two. Once started, the
1774 // server URLs will differ by the port number. Therefore they will be in
1775 // different origins.
1776 GURL download_url = origin_one.GetURL("/ping");
1777 GURL referrer_url = origin_one.GetURL(
1778 std::string("/download-attribute.html?target=") + download_url.spec());
1779 origin_one.ServeFilesFromDirectory(GetTestFilePath("download", ""));
1781 // <origin_one>/download-attribute.html initiates a download of
1782 // <origin_one>/ping, which redirects to <origin_two>/pong, and then finally
1783 // to <origin_one>/download.
1784 origin_one.RegisterRequestHandler(
1785 CreateRedirectHandler("/ping", origin_two.GetURL("/pong")));
1786 origin_two.RegisterRequestHandler(
1787 CreateRedirectHandler("/pong", origin_one.GetURL("/download")));
1788 origin_one.RegisterRequestHandler(CreateBasicResponseHandler(
1789 "/download", "application/octet-stream", "Hello"));
1791 NavigateToURLAndWaitForDownload(
1792 shell(), referrer_url, DownloadItem::COMPLETE);
1794 std::vector<DownloadItem*> downloads;
1795 DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
1796 ASSERT_EQ(1u, downloads.size());
1798 EXPECT_EQ(FILE_PATH_LITERAL("suggested-filename"),
1799 downloads[0]->GetTargetFilePath().BaseName().value());
1800 ASSERT_TRUE(origin_one.ShutdownAndWaitUntilComplete());
1801 ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete());
1804 // The file empty.bin is served with a MIME type of application/octet-stream.
1805 // The content body is empty. Make sure this case is handled properly and we
1806 // don't regress on http://crbug.com/320394.
1807 IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadGZipWithNoContent) {
1808 EmbeddedTestServer test_server;
1809 ASSERT_TRUE(test_server.InitializeAndWaitUntilReady());
1811 GURL url = test_server.GetURL("/empty.bin");
1812 test_server.ServeFilesFromDirectory(GetTestFilePath("download", ""));
1814 NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE);
1815 // That's it. This should work without crashing.
1818 } // namespace content