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 "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"
47 #if defined(ENABLE_PLUGINS)
48 #include "content/browser/plugin_service_impl.h"
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;
64 class MockDownloadItemObserver : public DownloadItem::Observer {
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 {
77 MockDownloadManagerObserver(DownloadManager* manager) {
79 manager->AddObserver(this);
81 virtual ~MockDownloadManagerObserver() {
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);
96 MOCK_METHOD1(MockManagerGoingDown, void(DownloadManager*));
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 {
113 DownloadFileWithDelay(
114 scoped_ptr<DownloadSaveInfo> save_info,
115 const base::FilePath& default_download_directory,
117 const GURL& referrer_url,
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 virtual ~DownloadFileWithDelay();
127 // Wraps DownloadFileImpl::Rename* and intercepts the return callback,
128 // storing it in the factory that produced this object for later
130 virtual void RenameAndUniquify(
131 const base::FilePath& full_path,
132 const RenameCompletionCallback& callback) OVERRIDE;
133 virtual void RenameAndAnnotate(
134 const base::FilePath& full_path,
135 const RenameCompletionCallback& callback) OVERRIDE;
138 static void RenameCallbackWrapper(
139 const base::WeakPtr<DownloadFileWithDelayFactory>& factory,
140 const RenameCompletionCallback& original_callback,
141 DownloadInterruptReason reason,
142 const base::FilePath& path);
144 // This variable may only be read on the FILE thread, and may only be
145 // indirected through (e.g. methods on DownloadFileWithDelayFactory called)
146 // on the UI thread. This is because after construction,
147 // DownloadFileWithDelay lives on the file thread, but
148 // DownloadFileWithDelayFactory is purely a UI thread object.
149 base::WeakPtr<DownloadFileWithDelayFactory> owner_;
151 DISALLOW_COPY_AND_ASSIGN(DownloadFileWithDelay);
154 // All routines on this class must be called on the UI thread.
155 class DownloadFileWithDelayFactory : public DownloadFileFactory {
157 DownloadFileWithDelayFactory();
158 virtual ~DownloadFileWithDelayFactory();
160 // DownloadFileFactory interface.
161 virtual DownloadFile* CreateFile(
162 scoped_ptr<DownloadSaveInfo> save_info,
163 const base::FilePath& default_download_directory,
165 const GURL& referrer_url,
167 scoped_ptr<ByteStreamReader> stream,
168 const net::BoundNetLog& bound_net_log,
169 base::WeakPtr<DownloadDestinationObserver> observer) OVERRIDE;
171 void AddRenameCallback(base::Closure callback);
172 void GetAllRenameCallbacks(std::vector<base::Closure>* results);
174 // Do not return until GetAllRenameCallbacks() will return a non-empty list.
175 void WaitForSomeCallback();
178 base::WeakPtrFactory<DownloadFileWithDelayFactory> weak_ptr_factory_;
179 std::vector<base::Closure> rename_callbacks_;
182 DISALLOW_COPY_AND_ASSIGN(DownloadFileWithDelayFactory);
185 DownloadFileWithDelay::DownloadFileWithDelay(
186 scoped_ptr<DownloadSaveInfo> save_info,
187 const base::FilePath& default_download_directory,
189 const GURL& referrer_url,
191 scoped_ptr<ByteStreamReader> stream,
192 const net::BoundNetLog& bound_net_log,
193 scoped_ptr<PowerSaveBlocker> power_save_blocker,
194 base::WeakPtr<DownloadDestinationObserver> observer,
195 base::WeakPtr<DownloadFileWithDelayFactory> owner)
197 save_info.Pass(), default_download_directory, url, referrer_url,
198 calculate_hash, stream.Pass(), bound_net_log, observer),
201 DownloadFileWithDelay::~DownloadFileWithDelay() {}
203 void DownloadFileWithDelay::RenameAndUniquify(
204 const base::FilePath& full_path,
205 const RenameCompletionCallback& callback) {
206 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
207 DownloadFileImpl::RenameAndUniquify(
208 full_path, base::Bind(DownloadFileWithDelay::RenameCallbackWrapper,
212 void DownloadFileWithDelay::RenameAndAnnotate(
213 const base::FilePath& full_path, const RenameCompletionCallback& callback) {
214 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
215 DownloadFileImpl::RenameAndAnnotate(
216 full_path, base::Bind(DownloadFileWithDelay::RenameCallbackWrapper,
221 void DownloadFileWithDelay::RenameCallbackWrapper(
222 const base::WeakPtr<DownloadFileWithDelayFactory>& factory,
223 const RenameCompletionCallback& original_callback,
224 DownloadInterruptReason reason,
225 const base::FilePath& path) {
226 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
229 factory->AddRenameCallback(base::Bind(original_callback, reason, path));
232 DownloadFileWithDelayFactory::DownloadFileWithDelayFactory()
233 : weak_ptr_factory_(this),
235 DownloadFileWithDelayFactory::~DownloadFileWithDelayFactory() {}
237 DownloadFile* DownloadFileWithDelayFactory::CreateFile(
238 scoped_ptr<DownloadSaveInfo> save_info,
239 const base::FilePath& default_download_directory,
241 const GURL& referrer_url,
243 scoped_ptr<ByteStreamReader> stream,
244 const net::BoundNetLog& bound_net_log,
245 base::WeakPtr<DownloadDestinationObserver> observer) {
246 scoped_ptr<PowerSaveBlocker> psb(
247 PowerSaveBlocker::Create(
248 PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
249 "Download in progress"));
250 return new DownloadFileWithDelay(
251 save_info.Pass(), default_download_directory, url, referrer_url,
252 calculate_hash, stream.Pass(), bound_net_log,
253 psb.Pass(), observer, weak_ptr_factory_.GetWeakPtr());
256 void DownloadFileWithDelayFactory::AddRenameCallback(base::Closure callback) {
257 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
258 rename_callbacks_.push_back(callback);
260 base::MessageLoopForUI::current()->Quit();
263 void DownloadFileWithDelayFactory::GetAllRenameCallbacks(
264 std::vector<base::Closure>* results) {
265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
266 results->swap(rename_callbacks_);
269 void DownloadFileWithDelayFactory::WaitForSomeCallback() {
270 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
272 if (rename_callbacks_.empty()) {
279 class CountingDownloadFile : public DownloadFileImpl {
281 CountingDownloadFile(
282 scoped_ptr<DownloadSaveInfo> save_info,
283 const base::FilePath& default_downloads_directory,
285 const GURL& referrer_url,
287 scoped_ptr<ByteStreamReader> stream,
288 const net::BoundNetLog& bound_net_log,
289 scoped_ptr<PowerSaveBlocker> power_save_blocker,
290 base::WeakPtr<DownloadDestinationObserver> observer)
291 : DownloadFileImpl(save_info.Pass(), default_downloads_directory,
292 url, referrer_url, calculate_hash,
293 stream.Pass(), bound_net_log, observer) {}
295 virtual ~CountingDownloadFile() {
296 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
300 virtual void Initialize(const InitializeCallback& callback) OVERRIDE {
301 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
303 return DownloadFileImpl::Initialize(callback);
306 static void GetNumberActiveFiles(int* result) {
307 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
308 *result = active_files_;
311 // Can be called on any thread, and will block (running message loop)
312 // until data is returned.
313 static int GetNumberActiveFilesFromFileThread() {
315 BrowserThread::PostTaskAndReply(
318 base::Bind(&CountingDownloadFile::GetNumberActiveFiles, &result),
319 base::MessageLoop::current()->QuitClosure());
320 base::MessageLoop::current()->Run();
321 DCHECK_NE(-1, result);
326 static int active_files_;
329 int CountingDownloadFile::active_files_ = 0;
331 class CountingDownloadFileFactory : public DownloadFileFactory {
333 CountingDownloadFileFactory() {}
334 virtual ~CountingDownloadFileFactory() {}
336 // DownloadFileFactory interface.
337 virtual DownloadFile* CreateFile(
338 scoped_ptr<DownloadSaveInfo> save_info,
339 const base::FilePath& default_downloads_directory,
341 const GURL& referrer_url,
343 scoped_ptr<ByteStreamReader> stream,
344 const net::BoundNetLog& bound_net_log,
345 base::WeakPtr<DownloadDestinationObserver> observer) OVERRIDE {
346 scoped_ptr<PowerSaveBlocker> psb(
347 PowerSaveBlocker::Create(
348 PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
349 "Download in progress"));
350 return new CountingDownloadFile(
351 save_info.Pass(), default_downloads_directory, url, referrer_url,
352 calculate_hash, stream.Pass(), bound_net_log,
353 psb.Pass(), observer);
357 class TestShellDownloadManagerDelegate : public ShellDownloadManagerDelegate {
359 TestShellDownloadManagerDelegate()
360 : delay_download_open_(false) {}
361 virtual ~TestShellDownloadManagerDelegate() {}
363 virtual bool ShouldOpenDownload(
365 const DownloadOpenDelayedCallback& callback) OVERRIDE {
366 if (delay_download_open_) {
367 delayed_callbacks_.push_back(callback);
373 void SetDelayedOpen(bool delay) {
374 delay_download_open_ = delay;
377 void GetDelayedCallbacks(
378 std::vector<DownloadOpenDelayedCallback>* callbacks) {
379 callbacks->swap(delayed_callbacks_);
382 bool delay_download_open_;
383 std::vector<DownloadOpenDelayedCallback> delayed_callbacks_;
386 // Record all state transitions and byte counts on the observed download.
387 class RecordingDownloadObserver : DownloadItem::Observer {
389 struct RecordStruct {
390 DownloadItem::DownloadState state;
394 typedef std::vector<RecordStruct> RecordVector;
396 RecordingDownloadObserver(DownloadItem* download)
397 : download_(download) {
398 last_state_.state = download->GetState();
399 last_state_.bytes_received = download->GetReceivedBytes();
400 download_->AddObserver(this);
403 virtual ~RecordingDownloadObserver() {
407 void CompareToExpectedRecord(const RecordStruct expected[], size_t size) {
408 EXPECT_EQ(size, record_.size());
409 int min = size > record_.size() ? record_.size() : size;
410 for (int i = 0; i < min; ++i) {
411 EXPECT_EQ(expected[i].state, record_[i].state) << "Iteration " << i;
412 EXPECT_EQ(expected[i].bytes_received, record_[i].bytes_received)
413 << "Iteration " << i;
418 virtual void OnDownloadUpdated(DownloadItem* download) OVERRIDE {
419 DCHECK_EQ(download_, download);
420 DownloadItem::DownloadState state = download->GetState();
421 int bytes = download->GetReceivedBytes();
422 if (last_state_.state != state || last_state_.bytes_received > bytes) {
423 last_state_.state = state;
424 last_state_.bytes_received = bytes;
425 record_.push_back(last_state_);
429 virtual void OnDownloadDestroyed(DownloadItem* download) OVERRIDE {
430 DCHECK_EQ(download_, download);
434 void RemoveObserver() {
436 download_->RemoveObserver(this);
441 DownloadItem* download_;
442 RecordStruct last_state_;
443 RecordVector record_;
446 // Get the next created download.
447 class DownloadCreateObserver : DownloadManager::Observer {
449 DownloadCreateObserver(DownloadManager* manager)
453 manager_->AddObserver(this);
456 virtual ~DownloadCreateObserver() {
458 manager_->RemoveObserver(this);
462 virtual void ManagerGoingDown(DownloadManager* manager) OVERRIDE {
463 DCHECK_EQ(manager_, manager);
464 manager_->RemoveObserver(this);
468 virtual void OnDownloadCreated(DownloadManager* manager,
469 DownloadItem* download) OVERRIDE {
474 base::MessageLoopForUI::current()->Quit();
477 DownloadItem* WaitForFinished() {
478 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
488 DownloadManager* manager_;
494 // Filter for waiting for a certain number of bytes.
495 bool DataReceivedFilter(int number_of_bytes, DownloadItem* download) {
496 return download->GetReceivedBytes() >= number_of_bytes;
499 // Filter for download completion.
500 bool DownloadCompleteFilter(DownloadItem* download) {
501 return download->GetState() == DownloadItem::COMPLETE;
504 // Filter for saving the size of the download when the first IN_PROGRESS
506 bool InitialSizeFilter(int* download_size, DownloadItem* download) {
507 if (download->GetState() != DownloadItem::IN_PROGRESS)
510 *download_size = download->GetReceivedBytes();
514 // Request handler to be used with CreateRedirectHandler().
515 scoped_ptr<net::test_server::HttpResponse> HandleRequestAndSendRedirectResponse(
516 const std::string& relative_url,
517 const GURL& target_url,
518 const net::test_server::HttpRequest& request) {
519 scoped_ptr<net::test_server::BasicHttpResponse> response;
520 if (request.relative_url == relative_url) {
521 response.reset(new net::test_server::BasicHttpResponse);
522 response->set_code(net::HTTP_FOUND);
523 response->AddCustomHeader("Location", target_url.spec());
525 return response.PassAs<net::test_server::HttpResponse>();
528 // Creates a request handler for EmbeddedTestServer that responds with a HTTP
529 // 302 redirect if the request URL matches |relative_url|.
530 EmbeddedTestServer::HandleRequestCallback CreateRedirectHandler(
531 const std::string& relative_url,
532 const GURL& target_url) {
534 &HandleRequestAndSendRedirectResponse, relative_url, target_url);
537 // Request handler to be used with CreateBasicResponseHandler().
538 scoped_ptr<net::test_server::HttpResponse> HandleRequestAndSendBasicResponse(
539 const std::string& relative_url,
540 const std::string& content_type,
541 const std::string& body,
542 const net::test_server::HttpRequest& request) {
543 scoped_ptr<net::test_server::BasicHttpResponse> response;
544 if (request.relative_url == relative_url) {
545 response.reset(new net::test_server::BasicHttpResponse);
546 response->set_content_type(content_type);
547 response->set_content(body);
549 return response.PassAs<net::test_server::HttpResponse>();
552 // Creates a request handler for an EmbeddedTestServer that response with an
553 // HTTP 200 status code, a Content-Type header and a body.
554 EmbeddedTestServer::HandleRequestCallback CreateBasicResponseHandler(
555 const std::string& relative_url,
556 const std::string& content_type,
557 const std::string& body) {
559 &HandleRequestAndSendBasicResponse, relative_url, content_type, body);
564 class DownloadContentTest : public ContentBrowserTest {
566 // An initial send from a website of at least this size will not be
567 // help up by buffering in the underlying downloads ByteStream data
568 // transfer. This is important because on resumption tests we wait
569 // until we've gotten the data we expect before allowing the test server
570 // to send its reset, to get around hard close semantics on the Windows
571 // socket layer implementation.
572 int GetSafeBufferChunk() const {
573 return (DownloadResourceHandler::kDownloadByteStreamSize /
574 ByteStreamWriter::kFractionBufferBeforeSending) + 1;
577 virtual void SetUpOnMainThread() OVERRIDE {
578 ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir());
580 test_delegate_.reset(new TestShellDownloadManagerDelegate());
581 test_delegate_->SetDownloadBehaviorForTesting(downloads_directory_.path());
582 DownloadManager* manager = DownloadManagerForShell(shell());
583 manager->GetDelegate()->Shutdown();
584 manager->SetDelegate(test_delegate_.get());
585 test_delegate_->SetDownloadManager(manager);
587 BrowserThread::PostTask(
588 BrowserThread::IO, FROM_HERE,
589 base::Bind(&URLRequestSlowDownloadJob::AddUrlHandler));
590 base::FilePath mock_base(GetTestFilePath("download", ""));
591 BrowserThread::PostTask(
595 &net::URLRequestMockHTTPJob::AddUrlHandler,
597 make_scoped_refptr(content::BrowserThread::GetBlockingPool())));
600 TestShellDownloadManagerDelegate* GetDownloadManagerDelegate() {
601 return test_delegate_.get();
604 // Create a DownloadTestObserverTerminal that will wait for the
605 // specified number of downloads to finish.
606 DownloadTestObserver* CreateWaiter(
607 Shell* shell, int num_downloads) {
608 DownloadManager* download_manager = DownloadManagerForShell(shell);
609 return new DownloadTestObserverTerminal(download_manager, num_downloads,
610 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
613 // Create a DownloadTestObserverInProgress that will wait for the
614 // specified number of downloads to start.
615 DownloadCreateObserver* CreateInProgressWaiter(
616 Shell* shell, int num_downloads) {
617 DownloadManager* download_manager = DownloadManagerForShell(shell);
618 return new DownloadCreateObserver(download_manager);
621 DownloadTestObserver* CreateInterruptedWaiter(
622 Shell* shell, int num_downloads) {
623 DownloadManager* download_manager = DownloadManagerForShell(shell);
624 return new DownloadTestObserverInterrupted(download_manager, num_downloads,
625 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
628 // Note: Cannot be used with other alternative DownloadFileFactorys
629 void SetupEnsureNoPendingDownloads() {
630 DownloadManagerForShell(shell())->SetDownloadFileFactoryForTesting(
631 scoped_ptr<DownloadFileFactory>(
632 new CountingDownloadFileFactory()).Pass());
635 bool EnsureNoPendingDownloads() {
637 BrowserThread::PostTask(
638 BrowserThread::IO, FROM_HERE,
639 base::Bind(&EnsureNoPendingDownloadJobsOnIO, &result));
640 base::MessageLoop::current()->Run();
642 (CountingDownloadFile::GetNumberActiveFilesFromFileThread() == 0);
645 void NavigateToURLAndWaitForDownload(
648 DownloadItem::DownloadState expected_terminal_state) {
649 scoped_ptr<DownloadTestObserver> observer(CreateWaiter(shell, 1));
650 NavigateToURL(shell, url);
651 observer->WaitForFinished();
652 EXPECT_EQ(1u, observer->NumDownloadsSeenInState(expected_terminal_state));
655 // Checks that |path| is has |file_size| bytes, and matches the |value|
657 bool VerifyFile(const base::FilePath& path,
658 const std::string& value,
659 const int64 file_size) {
660 std::string file_contents;
662 bool read = base::ReadFileToString(path, &file_contents);
663 EXPECT_TRUE(read) << "Failed reading file: " << path.value() << std::endl;
665 return false; // Couldn't read the file.
667 // Note: we don't handle really large files (more than size_t can hold)
668 // so we will fail in that case.
669 size_t expected_size = static_cast<size_t>(file_size);
672 EXPECT_EQ(expected_size, file_contents.size());
673 if (expected_size != file_contents.size())
676 // Check the contents.
677 EXPECT_EQ(value, file_contents);
678 if (memcmp(file_contents.c_str(), value.c_str(), expected_size) != 0)
684 // Start a download and return the item.
685 DownloadItem* StartDownloadAndReturnItem(GURL url) {
686 scoped_ptr<DownloadCreateObserver> observer(
687 CreateInProgressWaiter(shell(), 1));
688 NavigateToURL(shell(), url);
689 observer->WaitForFinished();
690 std::vector<DownloadItem*> downloads;
691 DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
692 EXPECT_EQ(1u, downloads.size());
693 if (1u != downloads.size())
699 void WaitForData(DownloadItem* download, int size) {
700 DownloadUpdatedObserver data_observer(
701 download, base::Bind(&DataReceivedFilter, size));
702 data_observer.WaitForEvent();
703 ASSERT_EQ(size, download->GetReceivedBytes());
704 ASSERT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
707 // Tell the test server to release a pending RST and confirm
708 // that the interrupt is received properly (for download resumption
710 void ReleaseRSTAndConfirmInterruptForResume(DownloadItem* download) {
711 scoped_ptr<DownloadTestObserver> rst_observer(
712 CreateInterruptedWaiter(shell(), 1));
713 NavigateToURL(shell(), test_server()->GetURL("download-finish"));
714 rst_observer->WaitForFinished();
715 EXPECT_EQ(DownloadItem::INTERRUPTED, download->GetState());
718 // Confirm file status expected for the given location in a stream
719 // provided by the resume test server.
720 void ConfirmFileStatusForResume(
721 DownloadItem* download, bool file_exists,
722 int received_bytes, int total_bytes,
723 const base::FilePath& expected_filename) {
724 // expected_filename is only known if the file exists.
725 ASSERT_EQ(file_exists, !expected_filename.empty());
726 EXPECT_EQ(received_bytes, download->GetReceivedBytes());
727 EXPECT_EQ(total_bytes, download->GetTotalBytes());
728 EXPECT_EQ(expected_filename.value(),
729 download->GetFullPath().BaseName().value());
730 EXPECT_EQ(file_exists,
731 (!download->GetFullPath().empty() &&
732 base::PathExists(download->GetFullPath())));
735 std::string file_contents;
736 EXPECT_TRUE(base::ReadFileToString(
737 download->GetFullPath(), &file_contents));
739 ASSERT_EQ(static_cast<size_t>(received_bytes), file_contents.size());
740 for (int i = 0; i < received_bytes; ++i) {
741 EXPECT_EQ(static_cast<char>((i * 2 + 15) % 256), file_contents[i])
742 << "File contents diverged at position " << i
743 << " for " << expected_filename.value();
745 if (static_cast<char>((i * 2 + 15) % 256) != file_contents[i])
752 static void EnsureNoPendingDownloadJobsOnIO(bool* result) {
753 if (URLRequestSlowDownloadJob::NumberOutstandingRequests())
755 BrowserThread::PostTask(
756 BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure());
759 // Location of the downloads directory for these tests
760 base::ScopedTempDir downloads_directory_;
761 scoped_ptr<TestShellDownloadManagerDelegate> test_delegate_;
764 IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadCancelled) {
765 SetupEnsureNoPendingDownloads();
767 // Create a download, wait until it's started, and confirm
768 // we're in the expected state.
769 scoped_ptr<DownloadCreateObserver> observer(
770 CreateInProgressWaiter(shell(), 1));
771 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl));
772 observer->WaitForFinished();
774 std::vector<DownloadItem*> downloads;
775 DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
776 ASSERT_EQ(1u, downloads.size());
777 ASSERT_EQ(DownloadItem::IN_PROGRESS, downloads[0]->GetState());
779 // Cancel the download and wait for download system quiesce.
780 downloads[0]->Cancel(true);
781 scoped_refptr<DownloadTestFlushObserver> flush_observer(
782 new DownloadTestFlushObserver(DownloadManagerForShell(shell())));
783 flush_observer->WaitForFlush();
785 // Get the important info from other threads and check it.
786 EXPECT_TRUE(EnsureNoPendingDownloads());
789 // Check that downloading multiple (in this case, 2) files does not result in
791 IN_PROC_BROWSER_TEST_F(DownloadContentTest, MultiDownload) {
792 SetupEnsureNoPendingDownloads();
794 // Create a download, wait until it's started, and confirm
795 // we're in the expected state.
796 scoped_ptr<DownloadCreateObserver> observer1(
797 CreateInProgressWaiter(shell(), 1));
798 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl));
799 observer1->WaitForFinished();
801 std::vector<DownloadItem*> downloads;
802 DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
803 ASSERT_EQ(1u, downloads.size());
804 ASSERT_EQ(DownloadItem::IN_PROGRESS, downloads[0]->GetState());
805 DownloadItem* download1 = downloads[0]; // The only download.
807 // Start the second download and wait until it's done.
808 base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
809 GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file));
810 // Download the file and wait.
811 NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE);
813 // Should now have 2 items on the manager.
815 DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
816 ASSERT_EQ(2u, downloads.size());
817 // We don't know the order of the downloads.
818 DownloadItem* download2 = downloads[(download1 == downloads[0]) ? 1 : 0];
820 ASSERT_EQ(DownloadItem::IN_PROGRESS, download1->GetState());
821 ASSERT_EQ(DownloadItem::COMPLETE, download2->GetState());
823 // Allow the first request to finish.
824 scoped_ptr<DownloadTestObserver> observer2(CreateWaiter(shell(), 1));
825 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kFinishDownloadUrl));
826 observer2->WaitForFinished(); // Wait for the third request.
827 EXPECT_EQ(1u, observer2->NumDownloadsSeenInState(DownloadItem::COMPLETE));
829 // Get the important info from other threads and check it.
830 EXPECT_TRUE(EnsureNoPendingDownloads());
832 // The |DownloadItem|s should now be done and have the final file names.
833 // Verify that the files have the expected data and size.
834 // |file1| should be full of '*'s, and |file2| should be the same as the
836 base::FilePath file1(download1->GetTargetFilePath());
837 size_t file_size1 = URLRequestSlowDownloadJob::kFirstDownloadSize +
838 URLRequestSlowDownloadJob::kSecondDownloadSize;
839 std::string expected_contents(file_size1, '*');
840 ASSERT_TRUE(VerifyFile(file1, expected_contents, file_size1));
842 base::FilePath file2(download2->GetTargetFilePath());
843 ASSERT_TRUE(base::ContentsEqual(
844 file2, GetTestFilePath("download", "download-test.lib")));
847 #if defined(ENABLE_PLUGINS)
848 // Content served with a MIME type of application/octet-stream should be
849 // downloaded even when a plugin can be found that handles the file type.
850 IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadOctetStream) {
851 const base::FilePath::CharType kTestFilePath[] =
852 FILE_PATH_LITERAL("octet-stream.abc");
853 const char kTestPluginName[] = "TestPlugin";
854 const char kTestMimeType[] = "application/x-test-mime-type";
855 const char kTestFileType[] = "abc";
857 WebPluginInfo plugin_info;
858 plugin_info.name = base::ASCIIToUTF16(kTestPluginName);
859 plugin_info.mime_types.push_back(
860 WebPluginMimeType(kTestMimeType, kTestFileType, ""));
861 PluginServiceImpl::GetInstance()->RegisterInternalPlugin(plugin_info, false);
863 // The following is served with a Content-Type of application/octet-stream.
865 net::URLRequestMockHTTPJob::GetMockUrl(base::FilePath(kTestFilePath)));
866 NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE);
870 // Try to cancel just before we release the download file, by delaying final
872 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelAtFinalRename) {
873 // Setup new factory.
874 DownloadFileWithDelayFactory* file_factory =
875 new DownloadFileWithDelayFactory();
876 DownloadManagerImpl* download_manager(DownloadManagerForShell(shell()));
877 download_manager->SetDownloadFileFactoryForTesting(
878 scoped_ptr<DownloadFileFactory>(file_factory).Pass());
881 base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
882 NavigateToURL(shell(), net::URLRequestMockHTTPJob::GetMockUrl(file));
884 // Wait until the first (intermediate file) rename and execute the callback.
885 file_factory->WaitForSomeCallback();
886 std::vector<base::Closure> callbacks;
887 file_factory->GetAllRenameCallbacks(&callbacks);
888 ASSERT_EQ(1u, callbacks.size());
892 // Wait until the second (final) rename callback is posted.
893 file_factory->WaitForSomeCallback();
894 file_factory->GetAllRenameCallbacks(&callbacks);
895 ASSERT_EQ(1u, callbacks.size());
898 std::vector<DownloadItem*> items;
899 download_manager->GetAllDownloads(&items);
900 ASSERT_EQ(1u, items.size());
901 items[0]->Cancel(true);
902 RunAllPendingInMessageLoop();
905 EXPECT_EQ(DownloadItem::CANCELLED, items[0]->GetState());
907 // Run final rename callback.
912 EXPECT_EQ(DownloadItem::CANCELLED, items[0]->GetState());
915 // Try to cancel just after we release the download file, by delaying
916 // in ShouldOpenDownload.
917 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelAtRelease) {
918 DownloadManagerImpl* download_manager(DownloadManagerForShell(shell()));
920 // Mark delegate for delayed open.
921 GetDownloadManagerDelegate()->SetDelayedOpen(true);
923 // Setup new factory.
924 DownloadFileWithDelayFactory* file_factory =
925 new DownloadFileWithDelayFactory();
926 download_manager->SetDownloadFileFactoryForTesting(
927 scoped_ptr<DownloadFileFactory>(file_factory).Pass());
930 base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
931 NavigateToURL(shell(), net::URLRequestMockHTTPJob::GetMockUrl(file));
933 // Wait until the first (intermediate file) rename and execute the callback.
934 file_factory->WaitForSomeCallback();
935 std::vector<base::Closure> callbacks;
936 file_factory->GetAllRenameCallbacks(&callbacks);
937 ASSERT_EQ(1u, callbacks.size());
941 // Wait until the second (final) rename callback is posted.
942 file_factory->WaitForSomeCallback();
943 file_factory->GetAllRenameCallbacks(&callbacks);
944 ASSERT_EQ(1u, callbacks.size());
950 // Confirm download still IN_PROGRESS (internal state COMPLETING).
951 std::vector<DownloadItem*> items;
952 download_manager->GetAllDownloads(&items);
953 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
955 // Cancel the download; confirm cancel fails.
956 ASSERT_EQ(1u, items.size());
957 items[0]->Cancel(true);
958 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
960 // Need to complete open test.
961 std::vector<DownloadOpenDelayedCallback> delayed_callbacks;
962 GetDownloadManagerDelegate()->GetDelayedCallbacks(
964 ASSERT_EQ(1u, delayed_callbacks.size());
965 delayed_callbacks[0].Run(true);
967 // *Now* the download should be complete.
968 EXPECT_EQ(DownloadItem::COMPLETE, items[0]->GetState());
971 // Try to shutdown with a download in progress to make sure shutdown path
973 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownInProgress) {
974 // Create a download that won't complete.
975 scoped_ptr<DownloadCreateObserver> observer(
976 CreateInProgressWaiter(shell(), 1));
977 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl));
978 observer->WaitForFinished();
981 std::vector<DownloadItem*> items;
982 DownloadManagerForShell(shell())->GetAllDownloads(&items);
983 ASSERT_EQ(1u, items.size());
984 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
986 // Shutdown the download manager and make sure we get the right
987 // notifications in the right order.
988 StrictMock<MockDownloadItemObserver> item_observer;
989 items[0]->AddObserver(&item_observer);
990 MockDownloadManagerObserver manager_observer(
991 DownloadManagerForShell(shell()));
992 // Don't care about ModelChanged() events.
993 EXPECT_CALL(manager_observer, ModelChanged(_))
994 .WillRepeatedly(Return());
996 InSequence notifications;
998 EXPECT_CALL(manager_observer, MockManagerGoingDown(
999 DownloadManagerForShell(shell())))
1000 .WillOnce(Return());
1001 EXPECT_CALL(item_observer, OnDownloadUpdated(
1003 Property(&DownloadItem::GetState, DownloadItem::CANCELLED))))
1004 .WillOnce(Return());
1005 EXPECT_CALL(item_observer, OnDownloadDestroyed(items[0]))
1006 .WillOnce(Return());
1009 // See http://crbug.com/324525. If we have a refcount release/post task
1010 // race, the second post will stall the IO thread long enough so that we'll
1011 // lose the race and crash. The first stall is just to give the UI thread
1012 // a chance to get the second stall onto the IO thread queue after the cancel
1013 // message created by Shutdown and before the notification callback
1014 // created by the IO thread in canceling the request.
1015 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
1016 base::Bind(&base::PlatformThread::Sleep,
1017 base::TimeDelta::FromMilliseconds(25)));
1018 DownloadManagerForShell(shell())->Shutdown();
1019 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
1020 base::Bind(&base::PlatformThread::Sleep,
1021 base::TimeDelta::FromMilliseconds(25)));
1025 // Try to shutdown just after we release the download file, by delaying
1027 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownAtRelease) {
1028 DownloadManagerImpl* download_manager(DownloadManagerForShell(shell()));
1030 // Mark delegate for delayed open.
1031 GetDownloadManagerDelegate()->SetDelayedOpen(true);
1033 // Setup new factory.
1034 DownloadFileWithDelayFactory* file_factory =
1035 new DownloadFileWithDelayFactory();
1036 download_manager->SetDownloadFileFactoryForTesting(
1037 scoped_ptr<DownloadFileFactory>(file_factory).Pass());
1039 // Create a download
1040 base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
1041 NavigateToURL(shell(), net::URLRequestMockHTTPJob::GetMockUrl(file));
1043 // Wait until the first (intermediate file) rename and execute the callback.
1044 file_factory->WaitForSomeCallback();
1045 std::vector<base::Closure> callbacks;
1046 file_factory->GetAllRenameCallbacks(&callbacks);
1047 ASSERT_EQ(1u, callbacks.size());
1051 // Wait until the second (final) rename callback is posted.
1052 file_factory->WaitForSomeCallback();
1053 file_factory->GetAllRenameCallbacks(&callbacks);
1054 ASSERT_EQ(1u, callbacks.size());
1060 // Confirm download isn't complete yet.
1061 std::vector<DownloadItem*> items;
1062 DownloadManagerForShell(shell())->GetAllDownloads(&items);
1063 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
1065 // Cancel the download; confirm cancel fails anyway.
1066 ASSERT_EQ(1u, items.size());
1067 items[0]->Cancel(true);
1068 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
1069 RunAllPendingInMessageLoop();
1070 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
1072 MockDownloadItemObserver observer;
1073 items[0]->AddObserver(&observer);
1074 EXPECT_CALL(observer, OnDownloadDestroyed(items[0]));
1076 // Shutdown the download manager. Mostly this is confirming a lack of
1078 DownloadManagerForShell(shell())->Shutdown();
1081 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeInterruptedDownload) {
1082 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1083 switches::kEnableDownloadResumption);
1084 ASSERT_TRUE(test_server()->Start());
1086 GURL url = test_server()->GetURL(
1087 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1088 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1090 MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell()));
1091 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
1093 DownloadItem* download(StartDownloadAndReturnItem(url));
1094 WaitForData(download, GetSafeBufferChunk());
1095 ::testing::Mock::VerifyAndClearExpectations(&dm_observer);
1097 // Confirm resumption while in progress doesn't do anything.
1099 ASSERT_EQ(GetSafeBufferChunk(), download->GetReceivedBytes());
1100 ASSERT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
1102 // Tell the server to send the RST and confirm the interrupt happens.
1103 ReleaseRSTAndConfirmInterruptForResume(download);
1104 ConfirmFileStatusForResume(
1105 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1106 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1108 // Resume, confirming received bytes on resumption is correct.
1109 // Make sure no creation calls are included.
1110 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(0);
1111 int initial_size = 0;
1112 DownloadUpdatedObserver initial_size_observer(
1113 download, base::Bind(&InitialSizeFilter, &initial_size));
1115 initial_size_observer.WaitForEvent();
1116 EXPECT_EQ(GetSafeBufferChunk(), initial_size);
1117 ::testing::Mock::VerifyAndClearExpectations(&dm_observer);
1119 // and wait for expected data.
1120 WaitForData(download, GetSafeBufferChunk() * 2);
1122 // Tell the server to send the RST and confirm the interrupt happens.
1123 ReleaseRSTAndConfirmInterruptForResume(download);
1124 ConfirmFileStatusForResume(
1125 download, true, GetSafeBufferChunk() * 2, GetSafeBufferChunk() * 3,
1126 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1128 // Resume and wait for completion.
1129 DownloadUpdatedObserver completion_observer(
1130 download, base::Bind(DownloadCompleteFilter));
1132 completion_observer.WaitForEvent();
1134 ConfirmFileStatusForResume(
1135 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1136 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1138 // Confirm resumption while complete doesn't do anything.
1140 ASSERT_EQ(GetSafeBufferChunk() * 3, download->GetReceivedBytes());
1141 ASSERT_EQ(DownloadItem::COMPLETE, download->GetState());
1142 RunAllPendingInMessageLoop();
1143 ASSERT_EQ(GetSafeBufferChunk() * 3, download->GetReceivedBytes());
1144 ASSERT_EQ(DownloadItem::COMPLETE, download->GetState());
1147 // Confirm restart fallback happens if a range request is bounced.
1148 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeInterruptedDownloadNoRange) {
1149 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1150 switches::kEnableDownloadResumption);
1151 ASSERT_TRUE(test_server()->Start());
1153 // Auto-restart if server doesn't handle ranges.
1154 GURL url = test_server()->GetURL(
1156 // First download hits an RST, rest don't, no ranges.
1157 "rangereset?size=%d&rst_boundary=%d&"
1158 "token=NoRange&rst_limit=1&bounce_range",
1159 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1161 // Start the download and wait for first data chunk.
1162 DownloadItem* download(StartDownloadAndReturnItem(url));
1163 WaitForData(download, GetSafeBufferChunk());
1165 RecordingDownloadObserver recorder(download);
1167 ReleaseRSTAndConfirmInterruptForResume(download);
1168 ConfirmFileStatusForResume(
1169 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1170 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1172 DownloadUpdatedObserver completion_observer(
1173 download, base::Bind(DownloadCompleteFilter));
1175 completion_observer.WaitForEvent();
1177 ConfirmFileStatusForResume(
1178 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1179 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1181 static const RecordingDownloadObserver::RecordStruct expected_record[] = {
1183 {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
1184 // Starting continuation
1185 {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()},
1186 // Notification of receiving whole file.
1187 {DownloadItem::IN_PROGRESS, 0},
1189 {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
1192 recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
1195 // Confirm restart fallback happens if a precondition is failed.
1196 IN_PROC_BROWSER_TEST_F(DownloadContentTest,
1197 ResumeInterruptedDownloadBadPrecondition) {
1198 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1199 switches::kEnableDownloadResumption);
1200 ASSERT_TRUE(test_server()->Start());
1202 GURL url = test_server()->GetURL(base::StringPrintf(
1203 // First download hits an RST, rest don't, precondition fail.
1204 "rangereset?size=%d&rst_boundary=%d&"
1205 "token=BadPrecondition&rst_limit=1&fail_precondition=2",
1206 GetSafeBufferChunk() * 3,
1207 GetSafeBufferChunk()));
1209 // Start the download and wait for first data chunk.
1210 DownloadItem* download(StartDownloadAndReturnItem(url));
1211 WaitForData(download, GetSafeBufferChunk());
1213 RecordingDownloadObserver recorder(download);
1215 ReleaseRSTAndConfirmInterruptForResume(download);
1216 ConfirmFileStatusForResume(
1217 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1218 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1219 EXPECT_EQ("BadPrecondition2", download->GetETag());
1221 DownloadUpdatedObserver completion_observer(
1222 download, base::Bind(DownloadCompleteFilter));
1224 completion_observer.WaitForEvent();
1226 ConfirmFileStatusForResume(
1227 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1228 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1229 EXPECT_EQ("BadPrecondition0", download->GetETag());
1231 static const RecordingDownloadObserver::RecordStruct expected_record[] = {
1233 {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
1234 // Starting continuation
1235 {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()},
1236 // Server precondition fail.
1237 {DownloadItem::INTERRUPTED, 0},
1238 // Notification of successful restart.
1239 {DownloadItem::IN_PROGRESS, 0},
1241 {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
1244 recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
1247 // Confirm we don't try to resume if we don't have a verifier.
1248 IN_PROC_BROWSER_TEST_F(DownloadContentTest,
1249 ResumeInterruptedDownloadNoVerifiers) {
1250 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1251 switches::kEnableDownloadResumption);
1252 ASSERT_TRUE(test_server()->Start());
1254 GURL url = test_server()->GetURL(
1256 // First download hits an RST, rest don't, no verifiers.
1257 "rangereset?size=%d&rst_boundary=%d&"
1258 "token=NoRange&rst_limit=1&no_verifiers",
1259 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1261 // Start the download and wait for first data chunk.
1262 DownloadItem* download(StartDownloadAndReturnItem(url));
1263 WaitForData(download, GetSafeBufferChunk());
1265 RecordingDownloadObserver recorder(download);
1267 ReleaseRSTAndConfirmInterruptForResume(download);
1268 ConfirmFileStatusForResume(
1269 download, false, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1272 DownloadUpdatedObserver completion_observer(
1273 download, base::Bind(DownloadCompleteFilter));
1275 completion_observer.WaitForEvent();
1277 ConfirmFileStatusForResume(
1278 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1279 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1281 static const RecordingDownloadObserver::RecordStruct expected_record[] = {
1283 {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
1284 // Restart for lack of verifiers
1285 {DownloadItem::IN_PROGRESS, 0},
1287 {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
1290 recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
1293 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithDeletedFile) {
1294 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1295 switches::kEnableDownloadResumption);
1296 ASSERT_TRUE(test_server()->Start());
1298 GURL url = test_server()->GetURL(
1300 // First download hits an RST, rest don't
1301 "rangereset?size=%d&rst_boundary=%d&"
1302 "token=NoRange&rst_limit=1",
1303 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1305 // Start the download and wait for first data chunk.
1306 DownloadItem* download(StartDownloadAndReturnItem(url));
1307 WaitForData(download, GetSafeBufferChunk());
1309 RecordingDownloadObserver recorder(download);
1311 ReleaseRSTAndConfirmInterruptForResume(download);
1312 ConfirmFileStatusForResume(
1313 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1314 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1316 // Delete the intermediate file.
1317 base::DeleteFile(download->GetFullPath(), false);
1319 DownloadUpdatedObserver completion_observer(
1320 download, base::Bind(DownloadCompleteFilter));
1322 completion_observer.WaitForEvent();
1324 ConfirmFileStatusForResume(
1325 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1326 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1328 static const RecordingDownloadObserver::RecordStruct expected_record[] = {
1330 {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
1331 // Starting continuation
1332 {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()},
1333 // Error because file isn't there.
1334 {DownloadItem::INTERRUPTED, 0},
1336 {DownloadItem::IN_PROGRESS, 0},
1338 {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
1341 recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
1344 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithFileInitError) {
1345 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1346 switches::kEnableDownloadResumption);
1347 base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
1348 GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file));
1350 // Setup the error injector.
1351 scoped_refptr<TestFileErrorInjector> injector(
1352 TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
1354 TestFileErrorInjector::FileErrorInfo err = {
1356 TestFileErrorInjector::FILE_OPERATION_INITIALIZE,
1358 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
1360 injector->AddError(err);
1361 injector->InjectErrors();
1363 // Start and watch for interrupt.
1364 scoped_ptr<DownloadTestObserver> int_observer(
1365 CreateInterruptedWaiter(shell(), 1));
1366 DownloadItem* download(StartDownloadAndReturnItem(url));
1367 int_observer->WaitForFinished();
1368 ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState());
1369 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE,
1370 download->GetLastReason());
1371 EXPECT_EQ(0, download->GetReceivedBytes());
1372 EXPECT_TRUE(download->GetFullPath().empty());
1373 EXPECT_TRUE(download->GetTargetFilePath().empty());
1375 // We need to make sure that any cross-thread downloads communication has
1376 // quiesced before clearing and injecting the new errors, as the
1377 // InjectErrors() routine alters the currently in use download file
1378 // factory, which is a file thread object.
1379 RunAllPendingInMessageLoop(BrowserThread::FILE);
1380 RunAllPendingInMessageLoop();
1382 // Clear the old errors list.
1383 injector->ClearErrors();
1384 injector->InjectErrors();
1386 // Resume and watch completion.
1387 DownloadUpdatedObserver completion_observer(
1388 download, base::Bind(DownloadCompleteFilter));
1390 completion_observer.WaitForEvent();
1391 EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE);
1394 IN_PROC_BROWSER_TEST_F(DownloadContentTest,
1395 ResumeWithFileIntermediateRenameError) {
1396 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1397 switches::kEnableDownloadResumption);
1398 base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
1399 GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file));
1401 // Setup the error injector.
1402 scoped_refptr<TestFileErrorInjector> injector(
1403 TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
1405 TestFileErrorInjector::FileErrorInfo err = {
1407 TestFileErrorInjector::FILE_OPERATION_RENAME_UNIQUIFY,
1409 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
1411 injector->AddError(err);
1412 injector->InjectErrors();
1414 // Start and watch for interrupt.
1415 scoped_ptr<DownloadTestObserver> int_observer(
1416 CreateInterruptedWaiter(shell(), 1));
1417 DownloadItem* download(StartDownloadAndReturnItem(url));
1418 int_observer->WaitForFinished();
1419 ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState());
1420 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE,
1421 download->GetLastReason());
1422 EXPECT_TRUE(download->GetFullPath().empty());
1423 // Target path will have been set after file name determination. GetFullPath()
1424 // being empty is sufficient to signal that filename determination needs to be
1426 EXPECT_FALSE(download->GetTargetFilePath().empty());
1428 // We need to make sure that any cross-thread downloads communication has
1429 // quiesced before clearing and injecting the new errors, as the
1430 // InjectErrors() routine alters the currently in use download file
1431 // factory, which is a file thread object.
1432 RunAllPendingInMessageLoop(BrowserThread::FILE);
1433 RunAllPendingInMessageLoop();
1435 // Clear the old errors list.
1436 injector->ClearErrors();
1437 injector->InjectErrors();
1439 // Resume and watch completion.
1440 DownloadUpdatedObserver completion_observer(
1441 download, base::Bind(DownloadCompleteFilter));
1443 completion_observer.WaitForEvent();
1444 EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE);
1447 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithFileFinalRenameError) {
1448 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1449 switches::kEnableDownloadResumption);
1450 base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
1451 GURL url(net::URLRequestMockHTTPJob::GetMockUrl(file));
1453 // Setup the error injector.
1454 scoped_refptr<TestFileErrorInjector> injector(
1455 TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
1457 DownloadManagerForShell(shell())->RemoveAllDownloads();
1458 TestFileErrorInjector::FileErrorInfo err = {
1460 TestFileErrorInjector::FILE_OPERATION_RENAME_ANNOTATE,
1462 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
1464 injector->AddError(err);
1465 injector->InjectErrors();
1467 // Start and watch for interrupt.
1468 scoped_ptr<DownloadTestObserver> int_observer(
1469 CreateInterruptedWaiter(shell(), 1));
1470 DownloadItem* download(StartDownloadAndReturnItem(url));
1471 int_observer->WaitForFinished();
1472 ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState());
1473 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE,
1474 download->GetLastReason());
1475 EXPECT_TRUE(download->GetFullPath().empty());
1476 // Target path should still be intact.
1477 EXPECT_FALSE(download->GetTargetFilePath().empty());
1479 // We need to make sure that any cross-thread downloads communication has
1480 // quiesced before clearing and injecting the new errors, as the
1481 // InjectErrors() routine alters the currently in use download file
1482 // factory, which is a file thread object.
1483 RunAllPendingInMessageLoop(BrowserThread::FILE);
1484 RunAllPendingInMessageLoop();
1486 // Clear the old errors list.
1487 injector->ClearErrors();
1488 injector->InjectErrors();
1490 // Resume and watch completion.
1491 DownloadUpdatedObserver completion_observer(
1492 download, base::Bind(DownloadCompleteFilter));
1494 completion_observer.WaitForEvent();
1495 EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE);
1498 // An interrupted download should remove the intermediate file when it is
1500 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelInterruptedDownload) {
1501 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1502 switches::kEnableDownloadResumption);
1503 ASSERT_TRUE(test_server()->Start());
1505 GURL url1 = test_server()->GetURL(
1506 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1507 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1509 DownloadItem* download(StartDownloadAndReturnItem(url1));
1510 WaitForData(download, GetSafeBufferChunk());
1512 ReleaseRSTAndConfirmInterruptForResume(download);
1513 ConfirmFileStatusForResume(
1514 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1515 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1517 base::FilePath intermediate_path(download->GetFullPath());
1518 ASSERT_FALSE(intermediate_path.empty());
1519 EXPECT_TRUE(base::PathExists(intermediate_path));
1521 download->Cancel(true /* user_cancel */);
1522 RunAllPendingInMessageLoop(BrowserThread::FILE);
1523 RunAllPendingInMessageLoop();
1525 // The intermediate file should now be gone.
1526 EXPECT_FALSE(base::PathExists(intermediate_path));
1527 EXPECT_TRUE(download->GetFullPath().empty());
1530 IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveDownload) {
1531 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1532 switches::kEnableDownloadResumption);
1533 ASSERT_TRUE(test_server()->Start());
1535 // An interrupted download should remove the intermediate file when it is
1538 GURL url1 = test_server()->GetURL(
1539 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1540 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1542 DownloadItem* download(StartDownloadAndReturnItem(url1));
1543 WaitForData(download, GetSafeBufferChunk());
1544 ReleaseRSTAndConfirmInterruptForResume(download);
1545 ConfirmFileStatusForResume(
1546 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1547 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1549 base::FilePath intermediate_path(download->GetFullPath());
1550 ASSERT_FALSE(intermediate_path.empty());
1551 EXPECT_TRUE(base::PathExists(intermediate_path));
1554 RunAllPendingInMessageLoop(BrowserThread::FILE);
1555 RunAllPendingInMessageLoop();
1557 // The intermediate file should now be gone.
1558 EXPECT_FALSE(base::PathExists(intermediate_path));
1561 // A completed download shouldn't delete the downloaded file when it is
1564 // Start the second download and wait until it's done.
1565 base::FilePath file2(FILE_PATH_LITERAL("download-test.lib"));
1566 GURL url2(net::URLRequestMockHTTPJob::GetMockUrl(file2));
1567 scoped_ptr<DownloadTestObserver> completion_observer(
1568 CreateWaiter(shell(), 1));
1569 DownloadItem* download(StartDownloadAndReturnItem(url2));
1570 completion_observer->WaitForFinished();
1572 // The target path should exist.
1573 base::FilePath target_path(download->GetTargetFilePath());
1574 EXPECT_TRUE(base::PathExists(target_path));
1576 RunAllPendingInMessageLoop(BrowserThread::FILE);
1577 RunAllPendingInMessageLoop();
1579 // The file should still exist.
1580 EXPECT_TRUE(base::PathExists(target_path));
1584 IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveResumingDownload) {
1585 SetupEnsureNoPendingDownloads();
1586 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1587 switches::kEnableDownloadResumption);
1588 ASSERT_TRUE(test_server()->Start());
1590 GURL url = test_server()->GetURL(
1591 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1592 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1594 MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell()));
1595 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
1597 DownloadItem* download(StartDownloadAndReturnItem(url));
1598 WaitForData(download, GetSafeBufferChunk());
1599 ::testing::Mock::VerifyAndClearExpectations(&dm_observer);
1601 // Tell the server to send the RST and confirm the interrupt happens.
1602 ReleaseRSTAndConfirmInterruptForResume(download);
1603 ConfirmFileStatusForResume(
1604 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1605 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1607 base::FilePath intermediate_path(download->GetFullPath());
1608 ASSERT_FALSE(intermediate_path.empty());
1609 EXPECT_TRUE(base::PathExists(intermediate_path));
1611 // Resume and remove download. We expect only a single OnDownloadCreated()
1612 // call, and that's for the second download created below.
1613 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
1617 // The intermediate file should now be gone.
1618 RunAllPendingInMessageLoop(BrowserThread::FILE);
1619 RunAllPendingInMessageLoop();
1620 EXPECT_FALSE(base::PathExists(intermediate_path));
1622 // Start the second download and wait until it's done. The test server is
1623 // single threaded. The response to this download request should follow the
1624 // response to the previous resumption request.
1625 GURL url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x"));
1626 NavigateToURLAndWaitForDownload(shell(), url2, DownloadItem::COMPLETE);
1628 EXPECT_TRUE(EnsureNoPendingDownloads());
1631 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelResumingDownload) {
1632 SetupEnsureNoPendingDownloads();
1633 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1634 switches::kEnableDownloadResumption);
1635 ASSERT_TRUE(test_server()->Start());
1637 GURL url = test_server()->GetURL(
1638 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1639 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1641 MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell()));
1642 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
1644 DownloadItem* download(StartDownloadAndReturnItem(url));
1645 WaitForData(download, GetSafeBufferChunk());
1646 ::testing::Mock::VerifyAndClearExpectations(&dm_observer);
1648 // Tell the server to send the RST and confirm the interrupt happens.
1649 ReleaseRSTAndConfirmInterruptForResume(download);
1650 ConfirmFileStatusForResume(
1651 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1652 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1654 base::FilePath intermediate_path(download->GetFullPath());
1655 ASSERT_FALSE(intermediate_path.empty());
1656 EXPECT_TRUE(base::PathExists(intermediate_path));
1658 // Resume and cancel download. We expect only a single OnDownloadCreated()
1659 // call, and that's for the second download created below.
1660 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
1662 download->Cancel(true);
1664 // The intermediate file should now be gone.
1665 RunAllPendingInMessageLoop(BrowserThread::FILE);
1666 RunAllPendingInMessageLoop();
1667 EXPECT_FALSE(base::PathExists(intermediate_path));
1668 EXPECT_TRUE(download->GetFullPath().empty());
1670 // Start the second download and wait until it's done. The test server is
1671 // single threaded. The response to this download request should follow the
1672 // response to the previous resumption request.
1673 GURL url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x"));
1674 NavigateToURLAndWaitForDownload(shell(), url2, DownloadItem::COMPLETE);
1676 EXPECT_TRUE(EnsureNoPendingDownloads());
1679 // Check that the cookie policy is correctly updated when downloading a file
1680 // that redirects cross origin.
1681 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CookiePolicy) {
1682 ASSERT_TRUE(test_server()->Start());
1683 net::HostPortPair host_port = test_server()->host_port_pair();
1684 DCHECK_EQ(host_port.host(), std::string("127.0.0.1"));
1686 // Block third-party cookies.
1687 ShellNetworkDelegate::SetAcceptAllCookies(false);
1689 // |url| redirects to a different origin |download| which tries to set a
1691 std::string download(base::StringPrintf(
1692 "http://localhost:%d/set-cookie?A=B", host_port.port()));
1693 GURL url(test_server()->GetURL("server-redirect?" + download));
1695 // Download the file.
1696 SetupEnsureNoPendingDownloads();
1697 scoped_ptr<DownloadUrlParameters> dl_params(
1698 DownloadUrlParameters::FromWebContents(shell()->web_contents(), url));
1699 scoped_ptr<DownloadTestObserver> observer(CreateWaiter(shell(), 1));
1700 DownloadManagerForShell(shell())->DownloadUrl(dl_params.Pass());
1701 observer->WaitForFinished();
1703 // Get the important info from other threads and check it.
1704 EXPECT_TRUE(EnsureNoPendingDownloads());
1706 std::vector<DownloadItem*> downloads;
1707 DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
1708 ASSERT_EQ(1u, downloads.size());
1709 ASSERT_EQ(DownloadItem::COMPLETE, downloads[0]->GetState());
1711 // Check that the cookies were correctly set.
1713 content::GetCookies(shell()->web_contents()->GetBrowserContext(),
1717 // A filename suggestion specified via a @download attribute should not be
1718 // effective if the final download URL is in another origin from the original
1720 IN_PROC_BROWSER_TEST_F(DownloadContentTest,
1721 DownloadAttributeCrossOriginRedirect) {
1722 EmbeddedTestServer origin_one;
1723 EmbeddedTestServer origin_two;
1724 ASSERT_TRUE(origin_one.InitializeAndWaitUntilReady());
1725 ASSERT_TRUE(origin_two.InitializeAndWaitUntilReady());
1727 // The download-attribute.html page contains an anchor element whose href is
1728 // set to the value of the query parameter (specified as |target| in the URL
1729 // below). The suggested filename for the anchor is 'suggested-filename'. When
1730 // the page is loaded, a script simulates a click on the anchor, triggering a
1731 // download of the target URL.
1733 // We construct two test servers; origin_one and origin_two. Once started, the
1734 // server URLs will differ by the port number. Therefore they will be in
1735 // different origins.
1736 GURL download_url = origin_one.GetURL("/ping");
1737 GURL referrer_url = origin_one.GetURL(
1738 std::string("/download-attribute.html?target=") + download_url.spec());
1740 // <origin_one>/download-attribute.html initiates a download of
1741 // <origin_one>/ping, which redirects to <origin_two>/download.
1742 origin_one.ServeFilesFromDirectory(GetTestFilePath("download", ""));
1743 origin_one.RegisterRequestHandler(
1744 CreateRedirectHandler("/ping", origin_two.GetURL("/download")));
1745 origin_two.RegisterRequestHandler(CreateBasicResponseHandler(
1746 "/download", "application/octet-stream", "Hello"));
1748 NavigateToURLAndWaitForDownload(
1749 shell(), referrer_url, DownloadItem::COMPLETE);
1751 std::vector<DownloadItem*> downloads;
1752 DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
1753 ASSERT_EQ(1u, downloads.size());
1755 EXPECT_EQ(FILE_PATH_LITERAL("download"),
1756 downloads[0]->GetTargetFilePath().BaseName().value());
1757 ASSERT_TRUE(origin_one.ShutdownAndWaitUntilComplete());
1758 ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete());
1761 // A filename suggestion specified via a @download attribute should be effective
1762 // if the final download URL is in the same origin as the initial download URL.
1763 // Test that this holds even if there are cross origin redirects in the middle
1764 // of the redirect chain.
1765 IN_PROC_BROWSER_TEST_F(DownloadContentTest,
1766 DownloadAttributeSameOriginRedirect) {
1767 EmbeddedTestServer origin_one;
1768 EmbeddedTestServer origin_two;
1769 ASSERT_TRUE(origin_one.InitializeAndWaitUntilReady());
1770 ASSERT_TRUE(origin_two.InitializeAndWaitUntilReady());
1772 // The download-attribute.html page contains an anchor element whose href is
1773 // set to the value of the query parameter (specified as |target| in the URL
1774 // below). The suggested filename for the anchor is 'suggested-filename'. When
1775 // the page is loaded, a script simulates a click on the anchor, triggering a
1776 // download of the target URL.
1778 // We construct two test servers; origin_one and origin_two. Once started, the
1779 // server URLs will differ by the port number. Therefore they will be in
1780 // different origins.
1781 GURL download_url = origin_one.GetURL("/ping");
1782 GURL referrer_url = origin_one.GetURL(
1783 std::string("/download-attribute.html?target=") + download_url.spec());
1784 origin_one.ServeFilesFromDirectory(GetTestFilePath("download", ""));
1786 // <origin_one>/download-attribute.html initiates a download of
1787 // <origin_one>/ping, which redirects to <origin_two>/pong, and then finally
1788 // to <origin_one>/download.
1789 origin_one.RegisterRequestHandler(
1790 CreateRedirectHandler("/ping", origin_two.GetURL("/pong")));
1791 origin_two.RegisterRequestHandler(
1792 CreateRedirectHandler("/pong", origin_one.GetURL("/download")));
1793 origin_one.RegisterRequestHandler(CreateBasicResponseHandler(
1794 "/download", "application/octet-stream", "Hello"));
1796 NavigateToURLAndWaitForDownload(
1797 shell(), referrer_url, DownloadItem::COMPLETE);
1799 std::vector<DownloadItem*> downloads;
1800 DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
1801 ASSERT_EQ(1u, downloads.size());
1803 EXPECT_EQ(FILE_PATH_LITERAL("suggested-filename"),
1804 downloads[0]->GetTargetFilePath().BaseName().value());
1805 ASSERT_TRUE(origin_one.ShutdownAndWaitUntilComplete());
1806 ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete());
1809 // The file empty.bin is served with a MIME type of application/octet-stream.
1810 // The content body is empty. Make sure this case is handled properly and we
1811 // don't regress on http://crbug.com/320394.
1812 IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadGZipWithNoContent) {
1813 EmbeddedTestServer test_server;
1814 ASSERT_TRUE(test_server.InitializeAndWaitUntilReady());
1816 GURL url = test_server.GetURL("/empty.bin");
1817 test_server.ServeFilesFromDirectory(GetTestFilePath("download", ""));
1819 NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE);
1820 // That's it. This should work without crashing.
1823 } // namespace content