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/file_util.h"
10 #include "base/files/file_path.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "content/browser/byte_stream.h"
15 #include "content/browser/download/download_file_factory.h"
16 #include "content/browser/download/download_file_impl.h"
17 #include "content/browser/download/download_item_impl.h"
18 #include "content/browser/download/download_manager_impl.h"
19 #include "content/browser/download/download_resource_handler.h"
20 #include "content/browser/plugin_service_impl.h"
21 #include "content/browser/web_contents/web_contents_impl.h"
22 #include "content/public/browser/power_save_blocker.h"
23 #include "content/public/common/content_switches.h"
24 #include "content/public/common/webplugininfo.h"
25 #include "content/public/test/browser_test_utils.h"
26 #include "content/public/test/download_test_observer.h"
27 #include "content/public/test/test_file_error_injector.h"
28 #include "content/public/test/test_utils.h"
29 #include "content/shell/browser/shell.h"
30 #include "content/shell/browser/shell_browser_context.h"
31 #include "content/shell/browser/shell_download_manager_delegate.h"
32 #include "content/shell/browser/shell_network_delegate.h"
33 #include "content/test/content_browser_test.h"
34 #include "content/test/content_browser_test_utils.h"
35 #include "content/test/net/url_request_mock_http_job.h"
36 #include "content/test/net/url_request_slow_download_job.h"
37 #include "net/test/spawned_test_server/spawned_test_server.h"
38 #include "testing/gmock/include/gmock/gmock.h"
39 #include "testing/gtest/include/gtest/gtest.h"
43 using ::testing::AllOf
;
44 using ::testing::Field
;
45 using ::testing::InSequence
;
46 using ::testing::Property
;
47 using ::testing::Return
;
48 using ::testing::StrictMock
;
54 class MockDownloadItemObserver
: public DownloadItem::Observer
{
56 MockDownloadItemObserver() {}
57 virtual ~MockDownloadItemObserver() {}
59 MOCK_METHOD1(OnDownloadUpdated
, void(DownloadItem
*));
60 MOCK_METHOD1(OnDownloadOpened
, void(DownloadItem
*));
61 MOCK_METHOD1(OnDownloadRemoved
, void(DownloadItem
*));
62 MOCK_METHOD1(OnDownloadDestroyed
, void(DownloadItem
*));
65 class MockDownloadManagerObserver
: public DownloadManager::Observer
{
67 MockDownloadManagerObserver(DownloadManager
* manager
) {
69 manager
->AddObserver(this);
71 virtual ~MockDownloadManagerObserver() {
73 manager_
->RemoveObserver(this);
76 MOCK_METHOD2(OnDownloadCreated
, void(DownloadManager
*, DownloadItem
*));
77 MOCK_METHOD1(ModelChanged
, void(DownloadManager
*));
78 void ManagerGoingDown(DownloadManager
* manager
) {
79 DCHECK_EQ(manager_
, manager
);
80 MockManagerGoingDown(manager
);
82 manager_
->RemoveObserver(this);
86 MOCK_METHOD1(MockManagerGoingDown
, void(DownloadManager
*));
88 DownloadManager
* manager_
;
91 class DownloadFileWithDelayFactory
;
93 static DownloadManagerImpl
* DownloadManagerForShell(Shell
* shell
) {
94 // We're in a content_browsertest; we know that the DownloadManager
95 // is a DownloadManagerImpl.
96 return static_cast<DownloadManagerImpl
*>(
97 BrowserContext::GetDownloadManager(
98 shell
->web_contents()->GetBrowserContext()));
101 class DownloadFileWithDelay
: public DownloadFileImpl
{
103 DownloadFileWithDelay(
104 scoped_ptr
<DownloadSaveInfo
> save_info
,
105 const base::FilePath
& default_download_directory
,
107 const GURL
& referrer_url
,
109 scoped_ptr
<ByteStreamReader
> stream
,
110 const net::BoundNetLog
& bound_net_log
,
111 scoped_ptr
<PowerSaveBlocker
> power_save_blocker
,
112 base::WeakPtr
<DownloadDestinationObserver
> observer
,
113 base::WeakPtr
<DownloadFileWithDelayFactory
> owner
);
115 virtual ~DownloadFileWithDelay();
117 // Wraps DownloadFileImpl::Rename* and intercepts the return callback,
118 // storing it in the factory that produced this object for later
120 virtual void RenameAndUniquify(
121 const base::FilePath
& full_path
,
122 const RenameCompletionCallback
& callback
) OVERRIDE
;
123 virtual void RenameAndAnnotate(
124 const base::FilePath
& full_path
,
125 const RenameCompletionCallback
& callback
) OVERRIDE
;
128 static void RenameCallbackWrapper(
129 const base::WeakPtr
<DownloadFileWithDelayFactory
>& factory
,
130 const RenameCompletionCallback
& original_callback
,
131 DownloadInterruptReason reason
,
132 const base::FilePath
& path
);
134 // This variable may only be read on the FILE thread, and may only be
135 // indirected through (e.g. methods on DownloadFileWithDelayFactory called)
136 // on the UI thread. This is because after construction,
137 // DownloadFileWithDelay lives on the file thread, but
138 // DownloadFileWithDelayFactory is purely a UI thread object.
139 base::WeakPtr
<DownloadFileWithDelayFactory
> owner_
;
141 DISALLOW_COPY_AND_ASSIGN(DownloadFileWithDelay
);
144 // All routines on this class must be called on the UI thread.
145 class DownloadFileWithDelayFactory
: public DownloadFileFactory
{
147 DownloadFileWithDelayFactory();
148 virtual ~DownloadFileWithDelayFactory();
150 // DownloadFileFactory interface.
151 virtual DownloadFile
* CreateFile(
152 scoped_ptr
<DownloadSaveInfo
> save_info
,
153 const base::FilePath
& default_download_directory
,
155 const GURL
& referrer_url
,
157 scoped_ptr
<ByteStreamReader
> stream
,
158 const net::BoundNetLog
& bound_net_log
,
159 base::WeakPtr
<DownloadDestinationObserver
> observer
) OVERRIDE
;
161 void AddRenameCallback(base::Closure callback
);
162 void GetAllRenameCallbacks(std::vector
<base::Closure
>* results
);
164 // Do not return until GetAllRenameCallbacks() will return a non-empty list.
165 void WaitForSomeCallback();
168 base::WeakPtrFactory
<DownloadFileWithDelayFactory
> weak_ptr_factory_
;
169 std::vector
<base::Closure
> rename_callbacks_
;
172 DISALLOW_COPY_AND_ASSIGN(DownloadFileWithDelayFactory
);
175 DownloadFileWithDelay::DownloadFileWithDelay(
176 scoped_ptr
<DownloadSaveInfo
> save_info
,
177 const base::FilePath
& default_download_directory
,
179 const GURL
& referrer_url
,
181 scoped_ptr
<ByteStreamReader
> stream
,
182 const net::BoundNetLog
& bound_net_log
,
183 scoped_ptr
<PowerSaveBlocker
> power_save_blocker
,
184 base::WeakPtr
<DownloadDestinationObserver
> observer
,
185 base::WeakPtr
<DownloadFileWithDelayFactory
> owner
)
187 save_info
.Pass(), default_download_directory
, url
, referrer_url
,
188 calculate_hash
, stream
.Pass(), bound_net_log
,
189 power_save_blocker
.Pass(), observer
),
192 DownloadFileWithDelay::~DownloadFileWithDelay() {}
194 void DownloadFileWithDelay::RenameAndUniquify(
195 const base::FilePath
& full_path
,
196 const RenameCompletionCallback
& callback
) {
197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
198 DownloadFileImpl::RenameAndUniquify(
199 full_path
, base::Bind(DownloadFileWithDelay::RenameCallbackWrapper
,
203 void DownloadFileWithDelay::RenameAndAnnotate(
204 const base::FilePath
& full_path
, const RenameCompletionCallback
& callback
) {
205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
206 DownloadFileImpl::RenameAndAnnotate(
207 full_path
, base::Bind(DownloadFileWithDelay::RenameCallbackWrapper
,
212 void DownloadFileWithDelay::RenameCallbackWrapper(
213 const base::WeakPtr
<DownloadFileWithDelayFactory
>& factory
,
214 const RenameCompletionCallback
& original_callback
,
215 DownloadInterruptReason reason
,
216 const base::FilePath
& path
) {
217 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
220 factory
->AddRenameCallback(base::Bind(original_callback
, reason
, path
));
223 DownloadFileWithDelayFactory::DownloadFileWithDelayFactory()
224 : weak_ptr_factory_(this),
226 DownloadFileWithDelayFactory::~DownloadFileWithDelayFactory() {}
228 DownloadFile
* DownloadFileWithDelayFactory::CreateFile(
229 scoped_ptr
<DownloadSaveInfo
> save_info
,
230 const base::FilePath
& default_download_directory
,
232 const GURL
& referrer_url
,
234 scoped_ptr
<ByteStreamReader
> stream
,
235 const net::BoundNetLog
& bound_net_log
,
236 base::WeakPtr
<DownloadDestinationObserver
> observer
) {
237 scoped_ptr
<PowerSaveBlocker
> psb(
238 PowerSaveBlocker::Create(
239 PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension
,
240 "Download in progress"));
241 return new DownloadFileWithDelay(
242 save_info
.Pass(), default_download_directory
, url
, referrer_url
,
243 calculate_hash
, stream
.Pass(), bound_net_log
,
244 psb
.Pass(), observer
, weak_ptr_factory_
.GetWeakPtr());
247 void DownloadFileWithDelayFactory::AddRenameCallback(base::Closure callback
) {
248 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
249 rename_callbacks_
.push_back(callback
);
251 base::MessageLoopForUI::current()->Quit();
254 void DownloadFileWithDelayFactory::GetAllRenameCallbacks(
255 std::vector
<base::Closure
>* results
) {
256 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
257 results
->swap(rename_callbacks_
);
260 void DownloadFileWithDelayFactory::WaitForSomeCallback() {
261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
263 if (rename_callbacks_
.empty()) {
270 class CountingDownloadFile
: public DownloadFileImpl
{
272 CountingDownloadFile(
273 scoped_ptr
<DownloadSaveInfo
> save_info
,
274 const base::FilePath
& default_downloads_directory
,
276 const GURL
& referrer_url
,
278 scoped_ptr
<ByteStreamReader
> stream
,
279 const net::BoundNetLog
& bound_net_log
,
280 scoped_ptr
<PowerSaveBlocker
> power_save_blocker
,
281 base::WeakPtr
<DownloadDestinationObserver
> observer
)
282 : DownloadFileImpl(save_info
.Pass(), default_downloads_directory
,
283 url
, referrer_url
, calculate_hash
,
284 stream
.Pass(), bound_net_log
,
285 power_save_blocker
.Pass(), observer
) {}
287 virtual ~CountingDownloadFile() {
288 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
292 virtual void Initialize(const InitializeCallback
& callback
) OVERRIDE
{
293 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
295 return DownloadFileImpl::Initialize(callback
);
298 static void GetNumberActiveFiles(int* result
) {
299 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
300 *result
= active_files_
;
303 // Can be called on any thread, and will block (running message loop)
304 // until data is returned.
305 static int GetNumberActiveFilesFromFileThread() {
307 BrowserThread::PostTaskAndReply(
310 base::Bind(&CountingDownloadFile::GetNumberActiveFiles
, &result
),
311 base::MessageLoop::current()->QuitClosure());
312 base::MessageLoop::current()->Run();
313 DCHECK_NE(-1, result
);
318 static int active_files_
;
321 int CountingDownloadFile::active_files_
= 0;
323 class CountingDownloadFileFactory
: public DownloadFileFactory
{
325 CountingDownloadFileFactory() {}
326 virtual ~CountingDownloadFileFactory() {}
328 // DownloadFileFactory interface.
329 virtual DownloadFile
* CreateFile(
330 scoped_ptr
<DownloadSaveInfo
> save_info
,
331 const base::FilePath
& default_downloads_directory
,
333 const GURL
& referrer_url
,
335 scoped_ptr
<ByteStreamReader
> stream
,
336 const net::BoundNetLog
& bound_net_log
,
337 base::WeakPtr
<DownloadDestinationObserver
> observer
) OVERRIDE
{
338 scoped_ptr
<PowerSaveBlocker
> psb(
339 PowerSaveBlocker::Create(
340 PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension
,
341 "Download in progress"));
342 return new CountingDownloadFile(
343 save_info
.Pass(), default_downloads_directory
, url
, referrer_url
,
344 calculate_hash
, stream
.Pass(), bound_net_log
,
345 psb
.Pass(), observer
);
349 class TestShellDownloadManagerDelegate
: public ShellDownloadManagerDelegate
{
351 TestShellDownloadManagerDelegate()
352 : delay_download_open_(false) {}
353 virtual ~TestShellDownloadManagerDelegate() {}
355 virtual bool ShouldOpenDownload(
357 const DownloadOpenDelayedCallback
& callback
) OVERRIDE
{
358 if (delay_download_open_
) {
359 delayed_callbacks_
.push_back(callback
);
365 void SetDelayedOpen(bool delay
) {
366 delay_download_open_
= delay
;
369 void GetDelayedCallbacks(
370 std::vector
<DownloadOpenDelayedCallback
>* callbacks
) {
371 callbacks
->swap(delayed_callbacks_
);
374 bool delay_download_open_
;
375 std::vector
<DownloadOpenDelayedCallback
> delayed_callbacks_
;
378 // Record all state transitions and byte counts on the observed download.
379 class RecordingDownloadObserver
: DownloadItem::Observer
{
381 struct RecordStruct
{
382 DownloadItem::DownloadState state
;
386 typedef std::vector
<RecordStruct
> RecordVector
;
388 RecordingDownloadObserver(DownloadItem
* download
)
389 : download_(download
) {
390 last_state_
.state
= download
->GetState();
391 last_state_
.bytes_received
= download
->GetReceivedBytes();
392 download_
->AddObserver(this);
395 virtual ~RecordingDownloadObserver() {
399 void CompareToExpectedRecord(const RecordStruct expected
[], size_t size
) {
400 EXPECT_EQ(size
, record_
.size());
401 int min
= size
> record_
.size() ? record_
.size() : size
;
402 for (int i
= 0; i
< min
; ++i
) {
403 EXPECT_EQ(expected
[i
].state
, record_
[i
].state
) << "Iteration " << i
;
404 EXPECT_EQ(expected
[i
].bytes_received
, record_
[i
].bytes_received
)
405 << "Iteration " << i
;
410 virtual void OnDownloadUpdated(DownloadItem
* download
) OVERRIDE
{
411 DCHECK_EQ(download_
, download
);
412 DownloadItem::DownloadState state
= download
->GetState();
413 int bytes
= download
->GetReceivedBytes();
414 if (last_state_
.state
!= state
|| last_state_
.bytes_received
> bytes
) {
415 last_state_
.state
= state
;
416 last_state_
.bytes_received
= bytes
;
417 record_
.push_back(last_state_
);
421 virtual void OnDownloadDestroyed(DownloadItem
* download
) OVERRIDE
{
422 DCHECK_EQ(download_
, download
);
426 void RemoveObserver() {
428 download_
->RemoveObserver(this);
433 DownloadItem
* download_
;
434 RecordStruct last_state_
;
435 RecordVector record_
;
438 // Get the next created download.
439 class DownloadCreateObserver
: DownloadManager::Observer
{
441 DownloadCreateObserver(DownloadManager
* manager
)
445 manager_
->AddObserver(this);
448 virtual ~DownloadCreateObserver() {
450 manager_
->RemoveObserver(this);
454 virtual void ManagerGoingDown(DownloadManager
* manager
) OVERRIDE
{
455 DCHECK_EQ(manager_
, manager
);
456 manager_
->RemoveObserver(this);
460 virtual void OnDownloadCreated(DownloadManager
* manager
,
461 DownloadItem
* download
) OVERRIDE
{
466 base::MessageLoopForUI::current()->Quit();
469 DownloadItem
* WaitForFinished() {
470 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
480 DownloadManager
* manager_
;
486 // Filter for waiting for a certain number of bytes.
487 bool DataReceivedFilter(int number_of_bytes
, DownloadItem
* download
) {
488 return download
->GetReceivedBytes() >= number_of_bytes
;
491 // Filter for download completion.
492 bool DownloadCompleteFilter(DownloadItem
* download
) {
493 return download
->GetState() == DownloadItem::COMPLETE
;
496 // Filter for saving the size of the download when the first IN_PROGRESS
498 bool InitialSizeFilter(int* download_size
, DownloadItem
* download
) {
499 if (download
->GetState() != DownloadItem::IN_PROGRESS
)
502 *download_size
= download
->GetReceivedBytes();
508 class DownloadContentTest
: public ContentBrowserTest
{
510 // An initial send from a website of at least this size will not be
511 // help up by buffering in the underlying downloads ByteStream data
512 // transfer. This is important because on resumption tests we wait
513 // until we've gotten the data we expect before allowing the test server
514 // to send its reset, to get around hard close semantics on the Windows
515 // socket layer implementation.
516 int GetSafeBufferChunk() const {
517 return (DownloadResourceHandler::kDownloadByteStreamSize
/
518 ByteStreamWriter::kFractionBufferBeforeSending
) + 1;
521 virtual void SetUpOnMainThread() OVERRIDE
{
522 ASSERT_TRUE(downloads_directory_
.CreateUniqueTempDir());
524 test_delegate_
.reset(new TestShellDownloadManagerDelegate());
525 test_delegate_
->SetDownloadBehaviorForTesting(downloads_directory_
.path());
526 DownloadManager
* manager
= DownloadManagerForShell(shell());
527 manager
->GetDelegate()->Shutdown();
528 manager
->SetDelegate(test_delegate_
.get());
529 test_delegate_
->SetDownloadManager(manager
);
531 BrowserThread::PostTask(
532 BrowserThread::IO
, FROM_HERE
,
533 base::Bind(&URLRequestSlowDownloadJob::AddUrlHandler
));
534 base::FilePath
mock_base(GetTestFilePath("download", ""));
535 BrowserThread::PostTask(
536 BrowserThread::IO
, FROM_HERE
,
537 base::Bind(&URLRequestMockHTTPJob::AddUrlHandler
, mock_base
));
540 TestShellDownloadManagerDelegate
* GetDownloadManagerDelegate() {
541 return test_delegate_
.get();
544 // Create a DownloadTestObserverTerminal that will wait for the
545 // specified number of downloads to finish.
546 DownloadTestObserver
* CreateWaiter(
547 Shell
* shell
, int num_downloads
) {
548 DownloadManager
* download_manager
= DownloadManagerForShell(shell
);
549 return new DownloadTestObserverTerminal(download_manager
, num_downloads
,
550 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL
);
553 // Create a DownloadTestObserverInProgress that will wait for the
554 // specified number of downloads to start.
555 DownloadCreateObserver
* CreateInProgressWaiter(
556 Shell
* shell
, int num_downloads
) {
557 DownloadManager
* download_manager
= DownloadManagerForShell(shell
);
558 return new DownloadCreateObserver(download_manager
);
561 DownloadTestObserver
* CreateInterruptedWaiter(
562 Shell
* shell
, int num_downloads
) {
563 DownloadManager
* download_manager
= DownloadManagerForShell(shell
);
564 return new DownloadTestObserverInterrupted(download_manager
, num_downloads
,
565 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL
);
568 // Note: Cannot be used with other alternative DownloadFileFactorys
569 void SetupEnsureNoPendingDownloads() {
570 DownloadManagerForShell(shell())->SetDownloadFileFactoryForTesting(
571 scoped_ptr
<DownloadFileFactory
>(
572 new CountingDownloadFileFactory()).Pass());
575 bool EnsureNoPendingDownloads() {
577 BrowserThread::PostTask(
578 BrowserThread::IO
, FROM_HERE
,
579 base::Bind(&EnsureNoPendingDownloadJobsOnIO
, &result
));
580 base::MessageLoop::current()->Run();
582 (CountingDownloadFile::GetNumberActiveFilesFromFileThread() == 0);
585 void DownloadAndWait(Shell
* shell
, const GURL
& url
,
586 DownloadItem::DownloadState expected_terminal_state
) {
587 scoped_ptr
<DownloadTestObserver
> observer(CreateWaiter(shell
, 1));
588 NavigateToURL(shell
, url
);
589 observer
->WaitForFinished();
590 EXPECT_EQ(1u, observer
->NumDownloadsSeenInState(expected_terminal_state
));
593 // Checks that |path| is has |file_size| bytes, and matches the |value|
595 bool VerifyFile(const base::FilePath
& path
,
596 const std::string
& value
,
597 const int64 file_size
) {
598 std::string file_contents
;
600 bool read
= base::ReadFileToString(path
, &file_contents
);
601 EXPECT_TRUE(read
) << "Failed reading file: " << path
.value() << std::endl
;
603 return false; // Couldn't read the file.
605 // Note: we don't handle really large files (more than size_t can hold)
606 // so we will fail in that case.
607 size_t expected_size
= static_cast<size_t>(file_size
);
610 EXPECT_EQ(expected_size
, file_contents
.size());
611 if (expected_size
!= file_contents
.size())
614 // Check the contents.
615 EXPECT_EQ(value
, file_contents
);
616 if (memcmp(file_contents
.c_str(), value
.c_str(), expected_size
) != 0)
622 // Start a download and return the item.
623 DownloadItem
* StartDownloadAndReturnItem(GURL url
) {
624 scoped_ptr
<DownloadCreateObserver
> observer(
625 CreateInProgressWaiter(shell(), 1));
626 NavigateToURL(shell(), url
);
627 observer
->WaitForFinished();
628 std::vector
<DownloadItem
*> downloads
;
629 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
630 EXPECT_EQ(1u, downloads
.size());
631 if (1u != downloads
.size())
637 void WaitForData(DownloadItem
* download
, int size
) {
638 DownloadUpdatedObserver
data_observer(
639 download
, base::Bind(&DataReceivedFilter
, size
));
640 data_observer
.WaitForEvent();
641 ASSERT_EQ(size
, download
->GetReceivedBytes());
642 ASSERT_EQ(DownloadItem::IN_PROGRESS
, download
->GetState());
645 // Tell the test server to release a pending RST and confirm
646 // that the interrupt is received properly (for download resumption
648 void ReleaseRSTAndConfirmInterruptForResume(DownloadItem
* download
) {
649 scoped_ptr
<DownloadTestObserver
> rst_observer(
650 CreateInterruptedWaiter(shell(), 1));
651 NavigateToURL(shell(), test_server()->GetURL("download-finish"));
652 rst_observer
->WaitForFinished();
653 EXPECT_EQ(DownloadItem::INTERRUPTED
, download
->GetState());
656 // Confirm file status expected for the given location in a stream
657 // provided by the resume test server.
658 void ConfirmFileStatusForResume(
659 DownloadItem
* download
, bool file_exists
,
660 int received_bytes
, int total_bytes
,
661 const base::FilePath
& expected_filename
) {
662 // expected_filename is only known if the file exists.
663 ASSERT_EQ(file_exists
, !expected_filename
.empty());
664 EXPECT_EQ(received_bytes
, download
->GetReceivedBytes());
665 EXPECT_EQ(total_bytes
, download
->GetTotalBytes());
666 EXPECT_EQ(expected_filename
.value(),
667 download
->GetFullPath().BaseName().value());
668 EXPECT_EQ(file_exists
,
669 (!download
->GetFullPath().empty() &&
670 base::PathExists(download
->GetFullPath())));
673 std::string file_contents
;
674 EXPECT_TRUE(base::ReadFileToString(
675 download
->GetFullPath(), &file_contents
));
677 ASSERT_EQ(static_cast<size_t>(received_bytes
), file_contents
.size());
678 for (int i
= 0; i
< received_bytes
; ++i
) {
679 EXPECT_EQ(static_cast<char>((i
* 2 + 15) % 256), file_contents
[i
])
680 << "File contents diverged at position " << i
681 << " for " << expected_filename
.value();
683 if (static_cast<char>((i
* 2 + 15) % 256) != file_contents
[i
])
690 static void EnsureNoPendingDownloadJobsOnIO(bool* result
) {
691 if (URLRequestSlowDownloadJob::NumberOutstandingRequests())
693 BrowserThread::PostTask(
694 BrowserThread::UI
, FROM_HERE
, base::MessageLoop::QuitClosure());
697 // Location of the downloads directory for these tests
698 base::ScopedTempDir downloads_directory_
;
699 scoped_ptr
<TestShellDownloadManagerDelegate
> test_delegate_
;
702 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, DownloadCancelled
) {
703 SetupEnsureNoPendingDownloads();
705 // Create a download, wait until it's started, and confirm
706 // we're in the expected state.
707 scoped_ptr
<DownloadCreateObserver
> observer(
708 CreateInProgressWaiter(shell(), 1));
709 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl
));
710 observer
->WaitForFinished();
712 std::vector
<DownloadItem
*> downloads
;
713 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
714 ASSERT_EQ(1u, downloads
.size());
715 ASSERT_EQ(DownloadItem::IN_PROGRESS
, downloads
[0]->GetState());
717 // Cancel the download and wait for download system quiesce.
718 downloads
[0]->Cancel(true);
719 scoped_refptr
<DownloadTestFlushObserver
> flush_observer(
720 new DownloadTestFlushObserver(DownloadManagerForShell(shell())));
721 flush_observer
->WaitForFlush();
723 // Get the important info from other threads and check it.
724 EXPECT_TRUE(EnsureNoPendingDownloads());
727 // Check that downloading multiple (in this case, 2) files does not result in
729 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, MultiDownload
) {
730 SetupEnsureNoPendingDownloads();
732 // Create a download, wait until it's started, and confirm
733 // we're in the expected state.
734 scoped_ptr
<DownloadCreateObserver
> observer1(
735 CreateInProgressWaiter(shell(), 1));
736 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl
));
737 observer1
->WaitForFinished();
739 std::vector
<DownloadItem
*> downloads
;
740 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
741 ASSERT_EQ(1u, downloads
.size());
742 ASSERT_EQ(DownloadItem::IN_PROGRESS
, downloads
[0]->GetState());
743 DownloadItem
* download1
= downloads
[0]; // The only download.
745 // Start the second download and wait until it's done.
746 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
747 GURL
url(URLRequestMockHTTPJob::GetMockUrl(file
));
748 // Download the file and wait.
749 DownloadAndWait(shell(), url
, DownloadItem::COMPLETE
);
751 // Should now have 2 items on the manager.
753 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
754 ASSERT_EQ(2u, downloads
.size());
755 // We don't know the order of the downloads.
756 DownloadItem
* download2
= downloads
[(download1
== downloads
[0]) ? 1 : 0];
758 ASSERT_EQ(DownloadItem::IN_PROGRESS
, download1
->GetState());
759 ASSERT_EQ(DownloadItem::COMPLETE
, download2
->GetState());
761 // Allow the first request to finish.
762 scoped_ptr
<DownloadTestObserver
> observer2(CreateWaiter(shell(), 1));
763 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kFinishDownloadUrl
));
764 observer2
->WaitForFinished(); // Wait for the third request.
765 EXPECT_EQ(1u, observer2
->NumDownloadsSeenInState(DownloadItem::COMPLETE
));
767 // Get the important info from other threads and check it.
768 EXPECT_TRUE(EnsureNoPendingDownloads());
770 // The |DownloadItem|s should now be done and have the final file names.
771 // Verify that the files have the expected data and size.
772 // |file1| should be full of '*'s, and |file2| should be the same as the
774 base::FilePath
file1(download1
->GetTargetFilePath());
775 size_t file_size1
= URLRequestSlowDownloadJob::kFirstDownloadSize
+
776 URLRequestSlowDownloadJob::kSecondDownloadSize
;
777 std::string
expected_contents(file_size1
, '*');
778 ASSERT_TRUE(VerifyFile(file1
, expected_contents
, file_size1
));
780 base::FilePath
file2(download2
->GetTargetFilePath());
781 ASSERT_TRUE(base::ContentsEqual(
782 file2
, GetTestFilePath("download", "download-test.lib")));
785 #if defined(ENABLE_PLUGINS)
786 // Content served with a MIME type of application/octet-stream should be
787 // downloaded even when a plugin can be found that handles the file type.
788 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, DownloadOctetStream
) {
789 const base::FilePath::CharType kTestFilePath
[] =
790 FILE_PATH_LITERAL("octet-stream.abc");
791 const char kTestPluginName
[] = "TestPlugin";
792 const char kTestMimeType
[] = "application/x-test-mime-type";
793 const char kTestFileType
[] = "abc";
795 WebPluginInfo plugin_info
;
796 plugin_info
.name
= base::ASCIIToUTF16(kTestPluginName
);
797 plugin_info
.mime_types
.push_back(
798 WebPluginMimeType(kTestMimeType
, kTestFileType
, ""));
799 PluginServiceImpl::GetInstance()->RegisterInternalPlugin(plugin_info
, false);
801 // The following is served with a Content-Type of application/octet-stream.
802 GURL
url(URLRequestMockHTTPJob::GetMockUrl(base::FilePath(kTestFilePath
)));
803 DownloadAndWait(shell(), url
, DownloadItem::COMPLETE
);
807 // Try to cancel just before we release the download file, by delaying final
809 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, CancelAtFinalRename
) {
810 // Setup new factory.
811 DownloadFileWithDelayFactory
* file_factory
=
812 new DownloadFileWithDelayFactory();
813 DownloadManagerImpl
* download_manager(DownloadManagerForShell(shell()));
814 download_manager
->SetDownloadFileFactoryForTesting(
815 scoped_ptr
<DownloadFileFactory
>(file_factory
).Pass());
818 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
819 NavigateToURL(shell(), URLRequestMockHTTPJob::GetMockUrl(file
));
821 // Wait until the first (intermediate file) rename and execute the callback.
822 file_factory
->WaitForSomeCallback();
823 std::vector
<base::Closure
> callbacks
;
824 file_factory
->GetAllRenameCallbacks(&callbacks
);
825 ASSERT_EQ(1u, callbacks
.size());
829 // Wait until the second (final) rename callback is posted.
830 file_factory
->WaitForSomeCallback();
831 file_factory
->GetAllRenameCallbacks(&callbacks
);
832 ASSERT_EQ(1u, callbacks
.size());
835 std::vector
<DownloadItem
*> items
;
836 download_manager
->GetAllDownloads(&items
);
837 ASSERT_EQ(1u, items
.size());
838 items
[0]->Cancel(true);
839 RunAllPendingInMessageLoop();
842 EXPECT_EQ(DownloadItem::CANCELLED
, items
[0]->GetState());
844 // Run final rename callback.
849 EXPECT_EQ(DownloadItem::CANCELLED
, items
[0]->GetState());
852 // Try to cancel just after we release the download file, by delaying
853 // in ShouldOpenDownload.
854 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, CancelAtRelease
) {
855 DownloadManagerImpl
* download_manager(DownloadManagerForShell(shell()));
857 // Mark delegate for delayed open.
858 GetDownloadManagerDelegate()->SetDelayedOpen(true);
860 // Setup new factory.
861 DownloadFileWithDelayFactory
* file_factory
=
862 new DownloadFileWithDelayFactory();
863 download_manager
->SetDownloadFileFactoryForTesting(
864 scoped_ptr
<DownloadFileFactory
>(file_factory
).Pass());
867 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
868 NavigateToURL(shell(), URLRequestMockHTTPJob::GetMockUrl(file
));
870 // Wait until the first (intermediate file) rename and execute the callback.
871 file_factory
->WaitForSomeCallback();
872 std::vector
<base::Closure
> callbacks
;
873 file_factory
->GetAllRenameCallbacks(&callbacks
);
874 ASSERT_EQ(1u, callbacks
.size());
878 // Wait until the second (final) rename callback is posted.
879 file_factory
->WaitForSomeCallback();
880 file_factory
->GetAllRenameCallbacks(&callbacks
);
881 ASSERT_EQ(1u, callbacks
.size());
887 // Confirm download still IN_PROGRESS (internal state COMPLETING).
888 std::vector
<DownloadItem
*> items
;
889 download_manager
->GetAllDownloads(&items
);
890 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
892 // Cancel the download; confirm cancel fails.
893 ASSERT_EQ(1u, items
.size());
894 items
[0]->Cancel(true);
895 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
897 // Need to complete open test.
898 std::vector
<DownloadOpenDelayedCallback
> delayed_callbacks
;
899 GetDownloadManagerDelegate()->GetDelayedCallbacks(
901 ASSERT_EQ(1u, delayed_callbacks
.size());
902 delayed_callbacks
[0].Run(true);
904 // *Now* the download should be complete.
905 EXPECT_EQ(DownloadItem::COMPLETE
, items
[0]->GetState());
908 // Try to shutdown with a download in progress to make sure shutdown path
910 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ShutdownInProgress
) {
911 // Create a download that won't complete.
912 scoped_ptr
<DownloadCreateObserver
> observer(
913 CreateInProgressWaiter(shell(), 1));
914 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl
));
915 observer
->WaitForFinished();
918 std::vector
<DownloadItem
*> items
;
919 DownloadManagerForShell(shell())->GetAllDownloads(&items
);
920 ASSERT_EQ(1u, items
.size());
921 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
923 // Shutdown the download manager and make sure we get the right
924 // notifications in the right order.
925 StrictMock
<MockDownloadItemObserver
> item_observer
;
926 items
[0]->AddObserver(&item_observer
);
927 MockDownloadManagerObserver
manager_observer(
928 DownloadManagerForShell(shell()));
929 // Don't care about ModelChanged() events.
930 EXPECT_CALL(manager_observer
, ModelChanged(_
))
931 .WillRepeatedly(Return());
933 InSequence notifications
;
935 EXPECT_CALL(manager_observer
, MockManagerGoingDown(
936 DownloadManagerForShell(shell())))
938 EXPECT_CALL(item_observer
, OnDownloadUpdated(
940 Property(&DownloadItem::GetState
, DownloadItem::CANCELLED
))))
942 EXPECT_CALL(item_observer
, OnDownloadDestroyed(items
[0]))
945 DownloadManagerForShell(shell())->Shutdown();
949 // Try to shutdown just after we release the download file, by delaying
951 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ShutdownAtRelease
) {
952 DownloadManagerImpl
* download_manager(DownloadManagerForShell(shell()));
954 // Mark delegate for delayed open.
955 GetDownloadManagerDelegate()->SetDelayedOpen(true);
957 // Setup new factory.
958 DownloadFileWithDelayFactory
* file_factory
=
959 new DownloadFileWithDelayFactory();
960 download_manager
->SetDownloadFileFactoryForTesting(
961 scoped_ptr
<DownloadFileFactory
>(file_factory
).Pass());
964 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
965 NavigateToURL(shell(), URLRequestMockHTTPJob::GetMockUrl(file
));
967 // Wait until the first (intermediate file) rename and execute the callback.
968 file_factory
->WaitForSomeCallback();
969 std::vector
<base::Closure
> callbacks
;
970 file_factory
->GetAllRenameCallbacks(&callbacks
);
971 ASSERT_EQ(1u, callbacks
.size());
975 // Wait until the second (final) rename callback is posted.
976 file_factory
->WaitForSomeCallback();
977 file_factory
->GetAllRenameCallbacks(&callbacks
);
978 ASSERT_EQ(1u, callbacks
.size());
984 // Confirm download isn't complete yet.
985 std::vector
<DownloadItem
*> items
;
986 DownloadManagerForShell(shell())->GetAllDownloads(&items
);
987 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
989 // Cancel the download; confirm cancel fails anyway.
990 ASSERT_EQ(1u, items
.size());
991 items
[0]->Cancel(true);
992 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
993 RunAllPendingInMessageLoop();
994 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
996 MockDownloadItemObserver observer
;
997 items
[0]->AddObserver(&observer
);
998 EXPECT_CALL(observer
, OnDownloadDestroyed(items
[0]));
1000 // Shutdown the download manager. Mostly this is confirming a lack of
1002 DownloadManagerForShell(shell())->Shutdown();
1005 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ResumeInterruptedDownload
) {
1006 CommandLine::ForCurrentProcess()->AppendSwitch(
1007 switches::kEnableDownloadResumption
);
1008 ASSERT_TRUE(test_server()->Start());
1010 GURL url
= test_server()->GetURL(
1011 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1012 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1014 MockDownloadManagerObserver
dm_observer(DownloadManagerForShell(shell()));
1015 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(1);
1017 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1018 WaitForData(download
, GetSafeBufferChunk());
1019 ::testing::Mock::VerifyAndClearExpectations(&dm_observer
);
1021 // Confirm resumption while in progress doesn't do anything.
1023 ASSERT_EQ(GetSafeBufferChunk(), download
->GetReceivedBytes());
1024 ASSERT_EQ(DownloadItem::IN_PROGRESS
, download
->GetState());
1026 // Tell the server to send the RST and confirm the interrupt happens.
1027 ReleaseRSTAndConfirmInterruptForResume(download
);
1028 ConfirmFileStatusForResume(
1029 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1030 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1032 // Resume, confirming received bytes on resumption is correct.
1033 // Make sure no creation calls are included.
1034 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(0);
1035 int initial_size
= 0;
1036 DownloadUpdatedObserver
initial_size_observer(
1037 download
, base::Bind(&InitialSizeFilter
, &initial_size
));
1039 initial_size_observer
.WaitForEvent();
1040 EXPECT_EQ(GetSafeBufferChunk(), initial_size
);
1041 ::testing::Mock::VerifyAndClearExpectations(&dm_observer
);
1043 // and wait for expected data.
1044 WaitForData(download
, GetSafeBufferChunk() * 2);
1046 // Tell the server to send the RST and confirm the interrupt happens.
1047 ReleaseRSTAndConfirmInterruptForResume(download
);
1048 ConfirmFileStatusForResume(
1049 download
, true, GetSafeBufferChunk() * 2, GetSafeBufferChunk() * 3,
1050 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1052 // Resume and wait for completion.
1053 DownloadUpdatedObserver
completion_observer(
1054 download
, base::Bind(DownloadCompleteFilter
));
1056 completion_observer
.WaitForEvent();
1058 ConfirmFileStatusForResume(
1059 download
, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1060 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1062 // Confirm resumption while complete doesn't do anything.
1064 ASSERT_EQ(GetSafeBufferChunk() * 3, download
->GetReceivedBytes());
1065 ASSERT_EQ(DownloadItem::COMPLETE
, download
->GetState());
1066 RunAllPendingInMessageLoop();
1067 ASSERT_EQ(GetSafeBufferChunk() * 3, download
->GetReceivedBytes());
1068 ASSERT_EQ(DownloadItem::COMPLETE
, download
->GetState());
1071 // Confirm restart fallback happens if a range request is bounced.
1072 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ResumeInterruptedDownloadNoRange
) {
1073 CommandLine::ForCurrentProcess()->AppendSwitch(
1074 switches::kEnableDownloadResumption
);
1075 ASSERT_TRUE(test_server()->Start());
1077 // Auto-restart if server doesn't handle ranges.
1078 GURL url
= test_server()->GetURL(
1080 // First download hits an RST, rest don't, no ranges.
1081 "rangereset?size=%d&rst_boundary=%d&"
1082 "token=NoRange&rst_limit=1&bounce_range",
1083 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1085 // Start the download and wait for first data chunk.
1086 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1087 WaitForData(download
, GetSafeBufferChunk());
1089 RecordingDownloadObserver
recorder(download
);
1091 ReleaseRSTAndConfirmInterruptForResume(download
);
1092 ConfirmFileStatusForResume(
1093 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1094 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1096 DownloadUpdatedObserver
completion_observer(
1097 download
, base::Bind(DownloadCompleteFilter
));
1099 completion_observer
.WaitForEvent();
1101 ConfirmFileStatusForResume(
1102 download
, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1103 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1105 static const RecordingDownloadObserver::RecordStruct expected_record
[] = {
1107 {DownloadItem::INTERRUPTED
, GetSafeBufferChunk()},
1108 // Starting continuation
1109 {DownloadItem::IN_PROGRESS
, GetSafeBufferChunk()},
1110 // Notification of receiving whole file.
1111 {DownloadItem::IN_PROGRESS
, 0},
1113 {DownloadItem::COMPLETE
, GetSafeBufferChunk() * 3},
1116 recorder
.CompareToExpectedRecord(expected_record
, arraysize(expected_record
));
1119 // Confirm restart fallback happens if a precondition is failed.
1120 IN_PROC_BROWSER_TEST_F(DownloadContentTest
,
1121 ResumeInterruptedDownloadBadPrecondition
) {
1122 CommandLine::ForCurrentProcess()->AppendSwitch(
1123 switches::kEnableDownloadResumption
);
1124 ASSERT_TRUE(test_server()->Start());
1126 GURL url
= test_server()->GetURL(base::StringPrintf(
1127 // First download hits an RST, rest don't, precondition fail.
1128 "rangereset?size=%d&rst_boundary=%d&"
1129 "token=BadPrecondition&rst_limit=1&fail_precondition=2",
1130 GetSafeBufferChunk() * 3,
1131 GetSafeBufferChunk()));
1133 // Start the download and wait for first data chunk.
1134 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1135 WaitForData(download
, GetSafeBufferChunk());
1137 RecordingDownloadObserver
recorder(download
);
1139 ReleaseRSTAndConfirmInterruptForResume(download
);
1140 ConfirmFileStatusForResume(
1141 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1142 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1143 EXPECT_EQ("BadPrecondition2", download
->GetETag());
1145 DownloadUpdatedObserver
completion_observer(
1146 download
, base::Bind(DownloadCompleteFilter
));
1148 completion_observer
.WaitForEvent();
1150 ConfirmFileStatusForResume(
1151 download
, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1152 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1153 EXPECT_EQ("BadPrecondition0", download
->GetETag());
1155 static const RecordingDownloadObserver::RecordStruct expected_record
[] = {
1157 {DownloadItem::INTERRUPTED
, GetSafeBufferChunk()},
1158 // Starting continuation
1159 {DownloadItem::IN_PROGRESS
, GetSafeBufferChunk()},
1160 // Server precondition fail.
1161 {DownloadItem::INTERRUPTED
, 0},
1162 // Notification of successful restart.
1163 {DownloadItem::IN_PROGRESS
, 0},
1165 {DownloadItem::COMPLETE
, GetSafeBufferChunk() * 3},
1168 recorder
.CompareToExpectedRecord(expected_record
, arraysize(expected_record
));
1171 // Confirm we don't try to resume if we don't have a verifier.
1172 IN_PROC_BROWSER_TEST_F(DownloadContentTest
,
1173 ResumeInterruptedDownloadNoVerifiers
) {
1174 CommandLine::ForCurrentProcess()->AppendSwitch(
1175 switches::kEnableDownloadResumption
);
1176 ASSERT_TRUE(test_server()->Start());
1178 GURL url
= test_server()->GetURL(
1180 // First download hits an RST, rest don't, no verifiers.
1181 "rangereset?size=%d&rst_boundary=%d&"
1182 "token=NoRange&rst_limit=1&no_verifiers",
1183 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1185 // Start the download and wait for first data chunk.
1186 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1187 WaitForData(download
, GetSafeBufferChunk());
1189 RecordingDownloadObserver
recorder(download
);
1191 ReleaseRSTAndConfirmInterruptForResume(download
);
1192 ConfirmFileStatusForResume(
1193 download
, false, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1196 DownloadUpdatedObserver
completion_observer(
1197 download
, base::Bind(DownloadCompleteFilter
));
1199 completion_observer
.WaitForEvent();
1201 ConfirmFileStatusForResume(
1202 download
, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1203 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1205 static const RecordingDownloadObserver::RecordStruct expected_record
[] = {
1207 {DownloadItem::INTERRUPTED
, GetSafeBufferChunk()},
1208 // Restart for lack of verifiers
1209 {DownloadItem::IN_PROGRESS
, 0},
1211 {DownloadItem::COMPLETE
, GetSafeBufferChunk() * 3},
1214 recorder
.CompareToExpectedRecord(expected_record
, arraysize(expected_record
));
1217 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ResumeWithDeletedFile
) {
1218 CommandLine::ForCurrentProcess()->AppendSwitch(
1219 switches::kEnableDownloadResumption
);
1220 ASSERT_TRUE(test_server()->Start());
1222 GURL url
= test_server()->GetURL(
1224 // First download hits an RST, rest don't
1225 "rangereset?size=%d&rst_boundary=%d&"
1226 "token=NoRange&rst_limit=1",
1227 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1229 // Start the download and wait for first data chunk.
1230 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1231 WaitForData(download
, GetSafeBufferChunk());
1233 RecordingDownloadObserver
recorder(download
);
1235 ReleaseRSTAndConfirmInterruptForResume(download
);
1236 ConfirmFileStatusForResume(
1237 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1238 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1240 // Delete the intermediate file.
1241 base::DeleteFile(download
->GetFullPath(), false);
1243 DownloadUpdatedObserver
completion_observer(
1244 download
, base::Bind(DownloadCompleteFilter
));
1246 completion_observer
.WaitForEvent();
1248 ConfirmFileStatusForResume(
1249 download
, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1250 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1252 static const RecordingDownloadObserver::RecordStruct expected_record
[] = {
1254 {DownloadItem::INTERRUPTED
, GetSafeBufferChunk()},
1255 // Starting continuation
1256 {DownloadItem::IN_PROGRESS
, GetSafeBufferChunk()},
1257 // Error because file isn't there.
1258 {DownloadItem::INTERRUPTED
, 0},
1260 {DownloadItem::IN_PROGRESS
, 0},
1262 {DownloadItem::COMPLETE
, GetSafeBufferChunk() * 3},
1265 recorder
.CompareToExpectedRecord(expected_record
, arraysize(expected_record
));
1268 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ResumeWithFileInitError
) {
1269 CommandLine::ForCurrentProcess()->AppendSwitch(
1270 switches::kEnableDownloadResumption
);
1271 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
1272 GURL
url(URLRequestMockHTTPJob::GetMockUrl(file
));
1274 // Setup the error injector.
1275 scoped_refptr
<TestFileErrorInjector
> injector(
1276 TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
1278 TestFileErrorInjector::FileErrorInfo err
= {
1280 TestFileErrorInjector::FILE_OPERATION_INITIALIZE
,
1282 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
1284 injector
->AddError(err
);
1285 injector
->InjectErrors();
1287 // Start and watch for interrupt.
1288 scoped_ptr
<DownloadTestObserver
> int_observer(
1289 CreateInterruptedWaiter(shell(), 1));
1290 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1291 int_observer
->WaitForFinished();
1292 ASSERT_EQ(DownloadItem::INTERRUPTED
, download
->GetState());
1293 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
,
1294 download
->GetLastReason());
1295 EXPECT_EQ(0, download
->GetReceivedBytes());
1296 EXPECT_TRUE(download
->GetFullPath().empty());
1297 EXPECT_TRUE(download
->GetTargetFilePath().empty());
1299 // We need to make sure that any cross-thread downloads communication has
1300 // quiesced before clearing and injecting the new errors, as the
1301 // InjectErrors() routine alters the currently in use download file
1302 // factory, which is a file thread object.
1303 RunAllPendingInMessageLoop(BrowserThread::FILE);
1304 RunAllPendingInMessageLoop();
1306 // Clear the old errors list.
1307 injector
->ClearErrors();
1308 injector
->InjectErrors();
1310 // Resume and watch completion.
1311 DownloadUpdatedObserver
completion_observer(
1312 download
, base::Bind(DownloadCompleteFilter
));
1314 completion_observer
.WaitForEvent();
1315 EXPECT_EQ(download
->GetState(), DownloadItem::COMPLETE
);
1318 IN_PROC_BROWSER_TEST_F(DownloadContentTest
,
1319 ResumeWithFileIntermediateRenameError
) {
1320 CommandLine::ForCurrentProcess()->AppendSwitch(
1321 switches::kEnableDownloadResumption
);
1322 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
1323 GURL
url(URLRequestMockHTTPJob::GetMockUrl(file
));
1325 // Setup the error injector.
1326 scoped_refptr
<TestFileErrorInjector
> injector(
1327 TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
1329 TestFileErrorInjector::FileErrorInfo err
= {
1331 TestFileErrorInjector::FILE_OPERATION_RENAME_UNIQUIFY
,
1333 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
1335 injector
->AddError(err
);
1336 injector
->InjectErrors();
1338 // Start and watch for interrupt.
1339 scoped_ptr
<DownloadTestObserver
> int_observer(
1340 CreateInterruptedWaiter(shell(), 1));
1341 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1342 int_observer
->WaitForFinished();
1343 ASSERT_EQ(DownloadItem::INTERRUPTED
, download
->GetState());
1344 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
,
1345 download
->GetLastReason());
1346 EXPECT_TRUE(download
->GetFullPath().empty());
1347 // Target path will have been set after file name determination. GetFullPath()
1348 // being empty is sufficient to signal that filename determination needs to be
1350 EXPECT_FALSE(download
->GetTargetFilePath().empty());
1352 // We need to make sure that any cross-thread downloads communication has
1353 // quiesced before clearing and injecting the new errors, as the
1354 // InjectErrors() routine alters the currently in use download file
1355 // factory, which is a file thread object.
1356 RunAllPendingInMessageLoop(BrowserThread::FILE);
1357 RunAllPendingInMessageLoop();
1359 // Clear the old errors list.
1360 injector
->ClearErrors();
1361 injector
->InjectErrors();
1363 // Resume and watch completion.
1364 DownloadUpdatedObserver
completion_observer(
1365 download
, base::Bind(DownloadCompleteFilter
));
1367 completion_observer
.WaitForEvent();
1368 EXPECT_EQ(download
->GetState(), DownloadItem::COMPLETE
);
1371 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ResumeWithFileFinalRenameError
) {
1372 CommandLine::ForCurrentProcess()->AppendSwitch(
1373 switches::kEnableDownloadResumption
);
1374 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
1375 GURL
url(URLRequestMockHTTPJob::GetMockUrl(file
));
1377 // Setup the error injector.
1378 scoped_refptr
<TestFileErrorInjector
> injector(
1379 TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
1381 DownloadManagerForShell(shell())->RemoveAllDownloads();
1382 TestFileErrorInjector::FileErrorInfo err
= {
1384 TestFileErrorInjector::FILE_OPERATION_RENAME_ANNOTATE
,
1386 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
1388 injector
->AddError(err
);
1389 injector
->InjectErrors();
1391 // Start and watch for interrupt.
1392 scoped_ptr
<DownloadTestObserver
> int_observer(
1393 CreateInterruptedWaiter(shell(), 1));
1394 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1395 int_observer
->WaitForFinished();
1396 ASSERT_EQ(DownloadItem::INTERRUPTED
, download
->GetState());
1397 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
,
1398 download
->GetLastReason());
1399 EXPECT_TRUE(download
->GetFullPath().empty());
1400 // Target path should still be intact.
1401 EXPECT_FALSE(download
->GetTargetFilePath().empty());
1403 // We need to make sure that any cross-thread downloads communication has
1404 // quiesced before clearing and injecting the new errors, as the
1405 // InjectErrors() routine alters the currently in use download file
1406 // factory, which is a file thread object.
1407 RunAllPendingInMessageLoop(BrowserThread::FILE);
1408 RunAllPendingInMessageLoop();
1410 // Clear the old errors list.
1411 injector
->ClearErrors();
1412 injector
->InjectErrors();
1414 // Resume and watch completion.
1415 DownloadUpdatedObserver
completion_observer(
1416 download
, base::Bind(DownloadCompleteFilter
));
1418 completion_observer
.WaitForEvent();
1419 EXPECT_EQ(download
->GetState(), DownloadItem::COMPLETE
);
1422 // An interrupted download should remove the intermediate file when it is
1424 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, CancelInterruptedDownload
) {
1425 CommandLine::ForCurrentProcess()->AppendSwitch(
1426 switches::kEnableDownloadResumption
);
1427 ASSERT_TRUE(test_server()->Start());
1429 GURL url1
= test_server()->GetURL(
1430 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1431 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1433 DownloadItem
* download(StartDownloadAndReturnItem(url1
));
1434 WaitForData(download
, GetSafeBufferChunk());
1436 ReleaseRSTAndConfirmInterruptForResume(download
);
1437 ConfirmFileStatusForResume(
1438 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1439 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1441 base::FilePath
intermediate_path(download
->GetFullPath());
1442 ASSERT_FALSE(intermediate_path
.empty());
1443 EXPECT_TRUE(base::PathExists(intermediate_path
));
1445 download
->Cancel(true /* user_cancel */);
1446 RunAllPendingInMessageLoop(BrowserThread::FILE);
1447 RunAllPendingInMessageLoop();
1449 // The intermediate file should now be gone.
1450 EXPECT_FALSE(base::PathExists(intermediate_path
));
1451 EXPECT_TRUE(download
->GetFullPath().empty());
1454 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, RemoveDownload
) {
1455 CommandLine::ForCurrentProcess()->AppendSwitch(
1456 switches::kEnableDownloadResumption
);
1457 ASSERT_TRUE(test_server()->Start());
1459 // An interrupted download should remove the intermediate file when it is
1462 GURL url1
= test_server()->GetURL(
1463 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1464 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1466 DownloadItem
* download(StartDownloadAndReturnItem(url1
));
1467 WaitForData(download
, GetSafeBufferChunk());
1468 ReleaseRSTAndConfirmInterruptForResume(download
);
1469 ConfirmFileStatusForResume(
1470 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1471 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1473 base::FilePath
intermediate_path(download
->GetFullPath());
1474 ASSERT_FALSE(intermediate_path
.empty());
1475 EXPECT_TRUE(base::PathExists(intermediate_path
));
1478 RunAllPendingInMessageLoop(BrowserThread::FILE);
1479 RunAllPendingInMessageLoop();
1481 // The intermediate file should now be gone.
1482 EXPECT_FALSE(base::PathExists(intermediate_path
));
1485 // A completed download shouldn't delete the downloaded file when it is
1488 // Start the second download and wait until it's done.
1489 base::FilePath
file2(FILE_PATH_LITERAL("download-test.lib"));
1490 GURL
url2(URLRequestMockHTTPJob::GetMockUrl(file2
));
1491 scoped_ptr
<DownloadTestObserver
> completion_observer(
1492 CreateWaiter(shell(), 1));
1493 DownloadItem
* download(StartDownloadAndReturnItem(url2
));
1494 completion_observer
->WaitForFinished();
1496 // The target path should exist.
1497 base::FilePath
target_path(download
->GetTargetFilePath());
1498 EXPECT_TRUE(base::PathExists(target_path
));
1500 RunAllPendingInMessageLoop(BrowserThread::FILE);
1501 RunAllPendingInMessageLoop();
1503 // The file should still exist.
1504 EXPECT_TRUE(base::PathExists(target_path
));
1508 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, RemoveResumingDownload
) {
1509 SetupEnsureNoPendingDownloads();
1510 CommandLine::ForCurrentProcess()->AppendSwitch(
1511 switches::kEnableDownloadResumption
);
1512 ASSERT_TRUE(test_server()->Start());
1514 GURL url
= test_server()->GetURL(
1515 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1516 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1518 MockDownloadManagerObserver
dm_observer(DownloadManagerForShell(shell()));
1519 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(1);
1521 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1522 WaitForData(download
, GetSafeBufferChunk());
1523 ::testing::Mock::VerifyAndClearExpectations(&dm_observer
);
1525 // Tell the server to send the RST and confirm the interrupt happens.
1526 ReleaseRSTAndConfirmInterruptForResume(download
);
1527 ConfirmFileStatusForResume(
1528 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1529 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1531 base::FilePath
intermediate_path(download
->GetFullPath());
1532 ASSERT_FALSE(intermediate_path
.empty());
1533 EXPECT_TRUE(base::PathExists(intermediate_path
));
1535 // Resume and remove download. We expect only a single OnDownloadCreated()
1536 // call, and that's for the second download created below.
1537 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(1);
1541 // The intermediate file should now be gone.
1542 RunAllPendingInMessageLoop(BrowserThread::FILE);
1543 RunAllPendingInMessageLoop();
1544 EXPECT_FALSE(base::PathExists(intermediate_path
));
1546 // Start the second download and wait until it's done. The test server is
1547 // single threaded. The response to this download request should follow the
1548 // response to the previous resumption request.
1549 GURL
url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x"));
1550 DownloadAndWait(shell(), url2
, DownloadItem::COMPLETE
);
1552 EXPECT_TRUE(EnsureNoPendingDownloads());
1555 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, CancelResumingDownload
) {
1556 SetupEnsureNoPendingDownloads();
1557 CommandLine::ForCurrentProcess()->AppendSwitch(
1558 switches::kEnableDownloadResumption
);
1559 ASSERT_TRUE(test_server()->Start());
1561 GURL url
= test_server()->GetURL(
1562 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1563 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1565 MockDownloadManagerObserver
dm_observer(DownloadManagerForShell(shell()));
1566 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(1);
1568 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1569 WaitForData(download
, GetSafeBufferChunk());
1570 ::testing::Mock::VerifyAndClearExpectations(&dm_observer
);
1572 // Tell the server to send the RST and confirm the interrupt happens.
1573 ReleaseRSTAndConfirmInterruptForResume(download
);
1574 ConfirmFileStatusForResume(
1575 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1576 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1578 base::FilePath
intermediate_path(download
->GetFullPath());
1579 ASSERT_FALSE(intermediate_path
.empty());
1580 EXPECT_TRUE(base::PathExists(intermediate_path
));
1582 // Resume and cancel download. We expect only a single OnDownloadCreated()
1583 // call, and that's for the second download created below.
1584 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(1);
1586 download
->Cancel(true);
1588 // The intermediate file should now be gone.
1589 RunAllPendingInMessageLoop(BrowserThread::FILE);
1590 RunAllPendingInMessageLoop();
1591 EXPECT_FALSE(base::PathExists(intermediate_path
));
1592 EXPECT_TRUE(download
->GetFullPath().empty());
1594 // Start the second download and wait until it's done. The test server is
1595 // single threaded. The response to this download request should follow the
1596 // response to the previous resumption request.
1597 GURL
url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x"));
1598 DownloadAndWait(shell(), url2
, DownloadItem::COMPLETE
);
1600 EXPECT_TRUE(EnsureNoPendingDownloads());
1603 // Check that the cookie policy is correctly updated when downloading a file
1604 // that redirects cross origin.
1605 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, CookiePolicy
) {
1606 ASSERT_TRUE(test_server()->Start());
1607 net::HostPortPair host_port
= test_server()->host_port_pair();
1608 DCHECK_EQ(host_port
.host(), std::string("127.0.0.1"));
1610 // Block third-party cookies.
1611 ShellNetworkDelegate::SetAcceptAllCookies(false);
1613 // |url| redirects to a different origin |download| which tries to set a
1615 std::string
download(base::StringPrintf(
1616 "http://localhost:%d/set-cookie?A=B", host_port
.port()));
1617 GURL
url(test_server()->GetURL("server-redirect?" + download
));
1619 // Download the file.
1620 SetupEnsureNoPendingDownloads();
1621 scoped_ptr
<DownloadUrlParameters
> dl_params(
1622 DownloadUrlParameters::FromWebContents(shell()->web_contents(), url
));
1623 scoped_ptr
<DownloadTestObserver
> observer(CreateWaiter(shell(), 1));
1624 DownloadManagerForShell(shell())->DownloadUrl(dl_params
.Pass());
1625 observer
->WaitForFinished();
1627 // Get the important info from other threads and check it.
1628 EXPECT_TRUE(EnsureNoPendingDownloads());
1630 std::vector
<DownloadItem
*> downloads
;
1631 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
1632 ASSERT_EQ(1u, downloads
.size());
1633 ASSERT_EQ(DownloadItem::COMPLETE
, downloads
[0]->GetState());
1635 // Check that the cookies were correctly set.
1637 content::GetCookies(shell()->web_contents()->GetBrowserContext(),
1641 } // namespace content