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 "base/threading/platform_thread.h"
15 #include "base/time/time.h"
16 #include "content/browser/byte_stream.h"
17 #include "content/browser/download/download_file_factory.h"
18 #include "content/browser/download/download_file_impl.h"
19 #include "content/browser/download/download_item_impl.h"
20 #include "content/browser/download/download_manager_impl.h"
21 #include "content/browser/download/download_resource_handler.h"
22 #include "content/browser/plugin_service_impl.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_mock_http_job.h"
38 #include "content/test/net/url_request_slow_download_job.h"
39 #include "net/test/spawned_test_server/spawned_test_server.h"
40 #include "testing/gmock/include/gmock/gmock.h"
41 #include "testing/gtest/include/gtest/gtest.h"
45 using ::testing::AllOf
;
46 using ::testing::Field
;
47 using ::testing::InSequence
;
48 using ::testing::Property
;
49 using ::testing::Return
;
50 using ::testing::StrictMock
;
56 class MockDownloadItemObserver
: public DownloadItem::Observer
{
58 MockDownloadItemObserver() {}
59 virtual ~MockDownloadItemObserver() {}
61 MOCK_METHOD1(OnDownloadUpdated
, void(DownloadItem
*));
62 MOCK_METHOD1(OnDownloadOpened
, void(DownloadItem
*));
63 MOCK_METHOD1(OnDownloadRemoved
, void(DownloadItem
*));
64 MOCK_METHOD1(OnDownloadDestroyed
, void(DownloadItem
*));
67 class MockDownloadManagerObserver
: public DownloadManager::Observer
{
69 MockDownloadManagerObserver(DownloadManager
* manager
) {
71 manager
->AddObserver(this);
73 virtual ~MockDownloadManagerObserver() {
75 manager_
->RemoveObserver(this);
78 MOCK_METHOD2(OnDownloadCreated
, void(DownloadManager
*, DownloadItem
*));
79 MOCK_METHOD1(ModelChanged
, void(DownloadManager
*));
80 void ManagerGoingDown(DownloadManager
* manager
) {
81 DCHECK_EQ(manager_
, manager
);
82 MockManagerGoingDown(manager
);
84 manager_
->RemoveObserver(this);
88 MOCK_METHOD1(MockManagerGoingDown
, void(DownloadManager
*));
90 DownloadManager
* manager_
;
93 class DownloadFileWithDelayFactory
;
95 static DownloadManagerImpl
* DownloadManagerForShell(Shell
* shell
) {
96 // We're in a content_browsertest; we know that the DownloadManager
97 // is a DownloadManagerImpl.
98 return static_cast<DownloadManagerImpl
*>(
99 BrowserContext::GetDownloadManager(
100 shell
->web_contents()->GetBrowserContext()));
103 class DownloadFileWithDelay
: public DownloadFileImpl
{
105 DownloadFileWithDelay(
106 scoped_ptr
<DownloadSaveInfo
> save_info
,
107 const base::FilePath
& default_download_directory
,
109 const GURL
& referrer_url
,
111 scoped_ptr
<ByteStreamReader
> stream
,
112 const net::BoundNetLog
& bound_net_log
,
113 scoped_ptr
<PowerSaveBlocker
> power_save_blocker
,
114 base::WeakPtr
<DownloadDestinationObserver
> observer
,
115 base::WeakPtr
<DownloadFileWithDelayFactory
> owner
);
117 virtual ~DownloadFileWithDelay();
119 // Wraps DownloadFileImpl::Rename* and intercepts the return callback,
120 // storing it in the factory that produced this object for later
122 virtual void RenameAndUniquify(
123 const base::FilePath
& full_path
,
124 const RenameCompletionCallback
& callback
) OVERRIDE
;
125 virtual void RenameAndAnnotate(
126 const base::FilePath
& full_path
,
127 const RenameCompletionCallback
& callback
) OVERRIDE
;
130 static void RenameCallbackWrapper(
131 const base::WeakPtr
<DownloadFileWithDelayFactory
>& factory
,
132 const RenameCompletionCallback
& original_callback
,
133 DownloadInterruptReason reason
,
134 const base::FilePath
& path
);
136 // This variable may only be read on the FILE thread, and may only be
137 // indirected through (e.g. methods on DownloadFileWithDelayFactory called)
138 // on the UI thread. This is because after construction,
139 // DownloadFileWithDelay lives on the file thread, but
140 // DownloadFileWithDelayFactory is purely a UI thread object.
141 base::WeakPtr
<DownloadFileWithDelayFactory
> owner_
;
143 DISALLOW_COPY_AND_ASSIGN(DownloadFileWithDelay
);
146 // All routines on this class must be called on the UI thread.
147 class DownloadFileWithDelayFactory
: public DownloadFileFactory
{
149 DownloadFileWithDelayFactory();
150 virtual ~DownloadFileWithDelayFactory();
152 // DownloadFileFactory interface.
153 virtual DownloadFile
* CreateFile(
154 scoped_ptr
<DownloadSaveInfo
> save_info
,
155 const base::FilePath
& default_download_directory
,
157 const GURL
& referrer_url
,
159 scoped_ptr
<ByteStreamReader
> stream
,
160 const net::BoundNetLog
& bound_net_log
,
161 base::WeakPtr
<DownloadDestinationObserver
> observer
) OVERRIDE
;
163 void AddRenameCallback(base::Closure callback
);
164 void GetAllRenameCallbacks(std::vector
<base::Closure
>* results
);
166 // Do not return until GetAllRenameCallbacks() will return a non-empty list.
167 void WaitForSomeCallback();
170 base::WeakPtrFactory
<DownloadFileWithDelayFactory
> weak_ptr_factory_
;
171 std::vector
<base::Closure
> rename_callbacks_
;
174 DISALLOW_COPY_AND_ASSIGN(DownloadFileWithDelayFactory
);
177 DownloadFileWithDelay::DownloadFileWithDelay(
178 scoped_ptr
<DownloadSaveInfo
> save_info
,
179 const base::FilePath
& default_download_directory
,
181 const GURL
& referrer_url
,
183 scoped_ptr
<ByteStreamReader
> stream
,
184 const net::BoundNetLog
& bound_net_log
,
185 scoped_ptr
<PowerSaveBlocker
> power_save_blocker
,
186 base::WeakPtr
<DownloadDestinationObserver
> observer
,
187 base::WeakPtr
<DownloadFileWithDelayFactory
> owner
)
189 save_info
.Pass(), default_download_directory
, url
, referrer_url
,
190 calculate_hash
, stream
.Pass(), bound_net_log
,
191 power_save_blocker
.Pass(), observer
),
194 DownloadFileWithDelay::~DownloadFileWithDelay() {}
196 void DownloadFileWithDelay::RenameAndUniquify(
197 const base::FilePath
& full_path
,
198 const RenameCompletionCallback
& callback
) {
199 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
200 DownloadFileImpl::RenameAndUniquify(
201 full_path
, base::Bind(DownloadFileWithDelay::RenameCallbackWrapper
,
205 void DownloadFileWithDelay::RenameAndAnnotate(
206 const base::FilePath
& full_path
, const RenameCompletionCallback
& callback
) {
207 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
208 DownloadFileImpl::RenameAndAnnotate(
209 full_path
, base::Bind(DownloadFileWithDelay::RenameCallbackWrapper
,
214 void DownloadFileWithDelay::RenameCallbackWrapper(
215 const base::WeakPtr
<DownloadFileWithDelayFactory
>& factory
,
216 const RenameCompletionCallback
& original_callback
,
217 DownloadInterruptReason reason
,
218 const base::FilePath
& path
) {
219 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
222 factory
->AddRenameCallback(base::Bind(original_callback
, reason
, path
));
225 DownloadFileWithDelayFactory::DownloadFileWithDelayFactory()
226 : weak_ptr_factory_(this),
228 DownloadFileWithDelayFactory::~DownloadFileWithDelayFactory() {}
230 DownloadFile
* DownloadFileWithDelayFactory::CreateFile(
231 scoped_ptr
<DownloadSaveInfo
> save_info
,
232 const base::FilePath
& default_download_directory
,
234 const GURL
& referrer_url
,
236 scoped_ptr
<ByteStreamReader
> stream
,
237 const net::BoundNetLog
& bound_net_log
,
238 base::WeakPtr
<DownloadDestinationObserver
> observer
) {
239 scoped_ptr
<PowerSaveBlocker
> psb(
240 PowerSaveBlocker::Create(
241 PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension
,
242 "Download in progress"));
243 return new DownloadFileWithDelay(
244 save_info
.Pass(), default_download_directory
, url
, referrer_url
,
245 calculate_hash
, stream
.Pass(), bound_net_log
,
246 psb
.Pass(), observer
, weak_ptr_factory_
.GetWeakPtr());
249 void DownloadFileWithDelayFactory::AddRenameCallback(base::Closure callback
) {
250 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
251 rename_callbacks_
.push_back(callback
);
253 base::MessageLoopForUI::current()->Quit();
256 void DownloadFileWithDelayFactory::GetAllRenameCallbacks(
257 std::vector
<base::Closure
>* results
) {
258 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
259 results
->swap(rename_callbacks_
);
262 void DownloadFileWithDelayFactory::WaitForSomeCallback() {
263 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
265 if (rename_callbacks_
.empty()) {
272 class CountingDownloadFile
: public DownloadFileImpl
{
274 CountingDownloadFile(
275 scoped_ptr
<DownloadSaveInfo
> save_info
,
276 const base::FilePath
& default_downloads_directory
,
278 const GURL
& referrer_url
,
280 scoped_ptr
<ByteStreamReader
> stream
,
281 const net::BoundNetLog
& bound_net_log
,
282 scoped_ptr
<PowerSaveBlocker
> power_save_blocker
,
283 base::WeakPtr
<DownloadDestinationObserver
> observer
)
284 : DownloadFileImpl(save_info
.Pass(), default_downloads_directory
,
285 url
, referrer_url
, calculate_hash
,
286 stream
.Pass(), bound_net_log
,
287 power_save_blocker
.Pass(), observer
) {}
289 virtual ~CountingDownloadFile() {
290 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
294 virtual void Initialize(const InitializeCallback
& callback
) OVERRIDE
{
295 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
297 return DownloadFileImpl::Initialize(callback
);
300 static void GetNumberActiveFiles(int* result
) {
301 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
302 *result
= active_files_
;
305 // Can be called on any thread, and will block (running message loop)
306 // until data is returned.
307 static int GetNumberActiveFilesFromFileThread() {
309 BrowserThread::PostTaskAndReply(
312 base::Bind(&CountingDownloadFile::GetNumberActiveFiles
, &result
),
313 base::MessageLoop::current()->QuitClosure());
314 base::MessageLoop::current()->Run();
315 DCHECK_NE(-1, result
);
320 static int active_files_
;
323 int CountingDownloadFile::active_files_
= 0;
325 class CountingDownloadFileFactory
: public DownloadFileFactory
{
327 CountingDownloadFileFactory() {}
328 virtual ~CountingDownloadFileFactory() {}
330 // DownloadFileFactory interface.
331 virtual DownloadFile
* CreateFile(
332 scoped_ptr
<DownloadSaveInfo
> save_info
,
333 const base::FilePath
& default_downloads_directory
,
335 const GURL
& referrer_url
,
337 scoped_ptr
<ByteStreamReader
> stream
,
338 const net::BoundNetLog
& bound_net_log
,
339 base::WeakPtr
<DownloadDestinationObserver
> observer
) OVERRIDE
{
340 scoped_ptr
<PowerSaveBlocker
> psb(
341 PowerSaveBlocker::Create(
342 PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension
,
343 "Download in progress"));
344 return new CountingDownloadFile(
345 save_info
.Pass(), default_downloads_directory
, url
, referrer_url
,
346 calculate_hash
, stream
.Pass(), bound_net_log
,
347 psb
.Pass(), observer
);
351 class TestShellDownloadManagerDelegate
: public ShellDownloadManagerDelegate
{
353 TestShellDownloadManagerDelegate()
354 : delay_download_open_(false) {}
355 virtual ~TestShellDownloadManagerDelegate() {}
357 virtual bool ShouldOpenDownload(
359 const DownloadOpenDelayedCallback
& callback
) OVERRIDE
{
360 if (delay_download_open_
) {
361 delayed_callbacks_
.push_back(callback
);
367 void SetDelayedOpen(bool delay
) {
368 delay_download_open_
= delay
;
371 void GetDelayedCallbacks(
372 std::vector
<DownloadOpenDelayedCallback
>* callbacks
) {
373 callbacks
->swap(delayed_callbacks_
);
376 bool delay_download_open_
;
377 std::vector
<DownloadOpenDelayedCallback
> delayed_callbacks_
;
380 // Record all state transitions and byte counts on the observed download.
381 class RecordingDownloadObserver
: DownloadItem::Observer
{
383 struct RecordStruct
{
384 DownloadItem::DownloadState state
;
388 typedef std::vector
<RecordStruct
> RecordVector
;
390 RecordingDownloadObserver(DownloadItem
* download
)
391 : download_(download
) {
392 last_state_
.state
= download
->GetState();
393 last_state_
.bytes_received
= download
->GetReceivedBytes();
394 download_
->AddObserver(this);
397 virtual ~RecordingDownloadObserver() {
401 void CompareToExpectedRecord(const RecordStruct expected
[], size_t size
) {
402 EXPECT_EQ(size
, record_
.size());
403 int min
= size
> record_
.size() ? record_
.size() : size
;
404 for (int i
= 0; i
< min
; ++i
) {
405 EXPECT_EQ(expected
[i
].state
, record_
[i
].state
) << "Iteration " << i
;
406 EXPECT_EQ(expected
[i
].bytes_received
, record_
[i
].bytes_received
)
407 << "Iteration " << i
;
412 virtual void OnDownloadUpdated(DownloadItem
* download
) OVERRIDE
{
413 DCHECK_EQ(download_
, download
);
414 DownloadItem::DownloadState state
= download
->GetState();
415 int bytes
= download
->GetReceivedBytes();
416 if (last_state_
.state
!= state
|| last_state_
.bytes_received
> bytes
) {
417 last_state_
.state
= state
;
418 last_state_
.bytes_received
= bytes
;
419 record_
.push_back(last_state_
);
423 virtual void OnDownloadDestroyed(DownloadItem
* download
) OVERRIDE
{
424 DCHECK_EQ(download_
, download
);
428 void RemoveObserver() {
430 download_
->RemoveObserver(this);
435 DownloadItem
* download_
;
436 RecordStruct last_state_
;
437 RecordVector record_
;
440 // Get the next created download.
441 class DownloadCreateObserver
: DownloadManager::Observer
{
443 DownloadCreateObserver(DownloadManager
* manager
)
447 manager_
->AddObserver(this);
450 virtual ~DownloadCreateObserver() {
452 manager_
->RemoveObserver(this);
456 virtual void ManagerGoingDown(DownloadManager
* manager
) OVERRIDE
{
457 DCHECK_EQ(manager_
, manager
);
458 manager_
->RemoveObserver(this);
462 virtual void OnDownloadCreated(DownloadManager
* manager
,
463 DownloadItem
* download
) OVERRIDE
{
468 base::MessageLoopForUI::current()->Quit();
471 DownloadItem
* WaitForFinished() {
472 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
482 DownloadManager
* manager_
;
488 // Filter for waiting for a certain number of bytes.
489 bool DataReceivedFilter(int number_of_bytes
, DownloadItem
* download
) {
490 return download
->GetReceivedBytes() >= number_of_bytes
;
493 // Filter for download completion.
494 bool DownloadCompleteFilter(DownloadItem
* download
) {
495 return download
->GetState() == DownloadItem::COMPLETE
;
498 // Filter for saving the size of the download when the first IN_PROGRESS
500 bool InitialSizeFilter(int* download_size
, DownloadItem
* download
) {
501 if (download
->GetState() != DownloadItem::IN_PROGRESS
)
504 *download_size
= download
->GetReceivedBytes();
510 class DownloadContentTest
: public ContentBrowserTest
{
512 // An initial send from a website of at least this size will not be
513 // help up by buffering in the underlying downloads ByteStream data
514 // transfer. This is important because on resumption tests we wait
515 // until we've gotten the data we expect before allowing the test server
516 // to send its reset, to get around hard close semantics on the Windows
517 // socket layer implementation.
518 int GetSafeBufferChunk() const {
519 return (DownloadResourceHandler::kDownloadByteStreamSize
/
520 ByteStreamWriter::kFractionBufferBeforeSending
) + 1;
523 virtual void SetUpOnMainThread() OVERRIDE
{
524 ASSERT_TRUE(downloads_directory_
.CreateUniqueTempDir());
526 test_delegate_
.reset(new TestShellDownloadManagerDelegate());
527 test_delegate_
->SetDownloadBehaviorForTesting(downloads_directory_
.path());
528 DownloadManager
* manager
= DownloadManagerForShell(shell());
529 manager
->GetDelegate()->Shutdown();
530 manager
->SetDelegate(test_delegate_
.get());
531 test_delegate_
->SetDownloadManager(manager
);
533 BrowserThread::PostTask(
534 BrowserThread::IO
, FROM_HERE
,
535 base::Bind(&URLRequestSlowDownloadJob::AddUrlHandler
));
536 base::FilePath
mock_base(GetTestFilePath("download", ""));
537 BrowserThread::PostTask(
538 BrowserThread::IO
, FROM_HERE
,
539 base::Bind(&URLRequestMockHTTPJob::AddUrlHandler
, mock_base
));
542 TestShellDownloadManagerDelegate
* GetDownloadManagerDelegate() {
543 return test_delegate_
.get();
546 // Create a DownloadTestObserverTerminal that will wait for the
547 // specified number of downloads to finish.
548 DownloadTestObserver
* CreateWaiter(
549 Shell
* shell
, int num_downloads
) {
550 DownloadManager
* download_manager
= DownloadManagerForShell(shell
);
551 return new DownloadTestObserverTerminal(download_manager
, num_downloads
,
552 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL
);
555 // Create a DownloadTestObserverInProgress that will wait for the
556 // specified number of downloads to start.
557 DownloadCreateObserver
* CreateInProgressWaiter(
558 Shell
* shell
, int num_downloads
) {
559 DownloadManager
* download_manager
= DownloadManagerForShell(shell
);
560 return new DownloadCreateObserver(download_manager
);
563 DownloadTestObserver
* CreateInterruptedWaiter(
564 Shell
* shell
, int num_downloads
) {
565 DownloadManager
* download_manager
= DownloadManagerForShell(shell
);
566 return new DownloadTestObserverInterrupted(download_manager
, num_downloads
,
567 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL
);
570 // Note: Cannot be used with other alternative DownloadFileFactorys
571 void SetupEnsureNoPendingDownloads() {
572 DownloadManagerForShell(shell())->SetDownloadFileFactoryForTesting(
573 scoped_ptr
<DownloadFileFactory
>(
574 new CountingDownloadFileFactory()).Pass());
577 bool EnsureNoPendingDownloads() {
579 BrowserThread::PostTask(
580 BrowserThread::IO
, FROM_HERE
,
581 base::Bind(&EnsureNoPendingDownloadJobsOnIO
, &result
));
582 base::MessageLoop::current()->Run();
584 (CountingDownloadFile::GetNumberActiveFilesFromFileThread() == 0);
587 void DownloadAndWait(Shell
* shell
, const GURL
& url
,
588 DownloadItem::DownloadState expected_terminal_state
) {
589 scoped_ptr
<DownloadTestObserver
> observer(CreateWaiter(shell
, 1));
590 NavigateToURL(shell
, url
);
591 observer
->WaitForFinished();
592 EXPECT_EQ(1u, observer
->NumDownloadsSeenInState(expected_terminal_state
));
595 // Checks that |path| is has |file_size| bytes, and matches the |value|
597 bool VerifyFile(const base::FilePath
& path
,
598 const std::string
& value
,
599 const int64 file_size
) {
600 std::string file_contents
;
602 bool read
= base::ReadFileToString(path
, &file_contents
);
603 EXPECT_TRUE(read
) << "Failed reading file: " << path
.value() << std::endl
;
605 return false; // Couldn't read the file.
607 // Note: we don't handle really large files (more than size_t can hold)
608 // so we will fail in that case.
609 size_t expected_size
= static_cast<size_t>(file_size
);
612 EXPECT_EQ(expected_size
, file_contents
.size());
613 if (expected_size
!= file_contents
.size())
616 // Check the contents.
617 EXPECT_EQ(value
, file_contents
);
618 if (memcmp(file_contents
.c_str(), value
.c_str(), expected_size
) != 0)
624 // Start a download and return the item.
625 DownloadItem
* StartDownloadAndReturnItem(GURL url
) {
626 scoped_ptr
<DownloadCreateObserver
> observer(
627 CreateInProgressWaiter(shell(), 1));
628 NavigateToURL(shell(), url
);
629 observer
->WaitForFinished();
630 std::vector
<DownloadItem
*> downloads
;
631 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
632 EXPECT_EQ(1u, downloads
.size());
633 if (1u != downloads
.size())
639 void WaitForData(DownloadItem
* download
, int size
) {
640 DownloadUpdatedObserver
data_observer(
641 download
, base::Bind(&DataReceivedFilter
, size
));
642 data_observer
.WaitForEvent();
643 ASSERT_EQ(size
, download
->GetReceivedBytes());
644 ASSERT_EQ(DownloadItem::IN_PROGRESS
, download
->GetState());
647 // Tell the test server to release a pending RST and confirm
648 // that the interrupt is received properly (for download resumption
650 void ReleaseRSTAndConfirmInterruptForResume(DownloadItem
* download
) {
651 scoped_ptr
<DownloadTestObserver
> rst_observer(
652 CreateInterruptedWaiter(shell(), 1));
653 NavigateToURL(shell(), test_server()->GetURL("download-finish"));
654 rst_observer
->WaitForFinished();
655 EXPECT_EQ(DownloadItem::INTERRUPTED
, download
->GetState());
658 // Confirm file status expected for the given location in a stream
659 // provided by the resume test server.
660 void ConfirmFileStatusForResume(
661 DownloadItem
* download
, bool file_exists
,
662 int received_bytes
, int total_bytes
,
663 const base::FilePath
& expected_filename
) {
664 // expected_filename is only known if the file exists.
665 ASSERT_EQ(file_exists
, !expected_filename
.empty());
666 EXPECT_EQ(received_bytes
, download
->GetReceivedBytes());
667 EXPECT_EQ(total_bytes
, download
->GetTotalBytes());
668 EXPECT_EQ(expected_filename
.value(),
669 download
->GetFullPath().BaseName().value());
670 EXPECT_EQ(file_exists
,
671 (!download
->GetFullPath().empty() &&
672 base::PathExists(download
->GetFullPath())));
675 std::string file_contents
;
676 EXPECT_TRUE(base::ReadFileToString(
677 download
->GetFullPath(), &file_contents
));
679 ASSERT_EQ(static_cast<size_t>(received_bytes
), file_contents
.size());
680 for (int i
= 0; i
< received_bytes
; ++i
) {
681 EXPECT_EQ(static_cast<char>((i
* 2 + 15) % 256), file_contents
[i
])
682 << "File contents diverged at position " << i
683 << " for " << expected_filename
.value();
685 if (static_cast<char>((i
* 2 + 15) % 256) != file_contents
[i
])
692 static void EnsureNoPendingDownloadJobsOnIO(bool* result
) {
693 if (URLRequestSlowDownloadJob::NumberOutstandingRequests())
695 BrowserThread::PostTask(
696 BrowserThread::UI
, FROM_HERE
, base::MessageLoop::QuitClosure());
699 // Location of the downloads directory for these tests
700 base::ScopedTempDir downloads_directory_
;
701 scoped_ptr
<TestShellDownloadManagerDelegate
> test_delegate_
;
704 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, DownloadCancelled
) {
705 SetupEnsureNoPendingDownloads();
707 // Create a download, wait until it's started, and confirm
708 // we're in the expected state.
709 scoped_ptr
<DownloadCreateObserver
> observer(
710 CreateInProgressWaiter(shell(), 1));
711 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl
));
712 observer
->WaitForFinished();
714 std::vector
<DownloadItem
*> downloads
;
715 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
716 ASSERT_EQ(1u, downloads
.size());
717 ASSERT_EQ(DownloadItem::IN_PROGRESS
, downloads
[0]->GetState());
719 // Cancel the download and wait for download system quiesce.
720 downloads
[0]->Cancel(true);
721 scoped_refptr
<DownloadTestFlushObserver
> flush_observer(
722 new DownloadTestFlushObserver(DownloadManagerForShell(shell())));
723 flush_observer
->WaitForFlush();
725 // Get the important info from other threads and check it.
726 EXPECT_TRUE(EnsureNoPendingDownloads());
729 // Check that downloading multiple (in this case, 2) files does not result in
731 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, MultiDownload
) {
732 SetupEnsureNoPendingDownloads();
734 // Create a download, wait until it's started, and confirm
735 // we're in the expected state.
736 scoped_ptr
<DownloadCreateObserver
> observer1(
737 CreateInProgressWaiter(shell(), 1));
738 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl
));
739 observer1
->WaitForFinished();
741 std::vector
<DownloadItem
*> downloads
;
742 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
743 ASSERT_EQ(1u, downloads
.size());
744 ASSERT_EQ(DownloadItem::IN_PROGRESS
, downloads
[0]->GetState());
745 DownloadItem
* download1
= downloads
[0]; // The only download.
747 // Start the second download and wait until it's done.
748 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
749 GURL
url(URLRequestMockHTTPJob::GetMockUrl(file
));
750 // Download the file and wait.
751 DownloadAndWait(shell(), url
, DownloadItem::COMPLETE
);
753 // Should now have 2 items on the manager.
755 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
756 ASSERT_EQ(2u, downloads
.size());
757 // We don't know the order of the downloads.
758 DownloadItem
* download2
= downloads
[(download1
== downloads
[0]) ? 1 : 0];
760 ASSERT_EQ(DownloadItem::IN_PROGRESS
, download1
->GetState());
761 ASSERT_EQ(DownloadItem::COMPLETE
, download2
->GetState());
763 // Allow the first request to finish.
764 scoped_ptr
<DownloadTestObserver
> observer2(CreateWaiter(shell(), 1));
765 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kFinishDownloadUrl
));
766 observer2
->WaitForFinished(); // Wait for the third request.
767 EXPECT_EQ(1u, observer2
->NumDownloadsSeenInState(DownloadItem::COMPLETE
));
769 // Get the important info from other threads and check it.
770 EXPECT_TRUE(EnsureNoPendingDownloads());
772 // The |DownloadItem|s should now be done and have the final file names.
773 // Verify that the files have the expected data and size.
774 // |file1| should be full of '*'s, and |file2| should be the same as the
776 base::FilePath
file1(download1
->GetTargetFilePath());
777 size_t file_size1
= URLRequestSlowDownloadJob::kFirstDownloadSize
+
778 URLRequestSlowDownloadJob::kSecondDownloadSize
;
779 std::string
expected_contents(file_size1
, '*');
780 ASSERT_TRUE(VerifyFile(file1
, expected_contents
, file_size1
));
782 base::FilePath
file2(download2
->GetTargetFilePath());
783 ASSERT_TRUE(base::ContentsEqual(
784 file2
, GetTestFilePath("download", "download-test.lib")));
787 #if defined(ENABLE_PLUGINS)
788 // Content served with a MIME type of application/octet-stream should be
789 // downloaded even when a plugin can be found that handles the file type.
790 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, DownloadOctetStream
) {
791 const base::FilePath::CharType kTestFilePath
[] =
792 FILE_PATH_LITERAL("octet-stream.abc");
793 const char kTestPluginName
[] = "TestPlugin";
794 const char kTestMimeType
[] = "application/x-test-mime-type";
795 const char kTestFileType
[] = "abc";
797 WebPluginInfo plugin_info
;
798 plugin_info
.name
= base::ASCIIToUTF16(kTestPluginName
);
799 plugin_info
.mime_types
.push_back(
800 WebPluginMimeType(kTestMimeType
, kTestFileType
, ""));
801 PluginServiceImpl::GetInstance()->RegisterInternalPlugin(plugin_info
, false);
803 // The following is served with a Content-Type of application/octet-stream.
804 GURL
url(URLRequestMockHTTPJob::GetMockUrl(base::FilePath(kTestFilePath
)));
805 DownloadAndWait(shell(), url
, DownloadItem::COMPLETE
);
809 // Try to cancel just before we release the download file, by delaying final
811 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, CancelAtFinalRename
) {
812 // Setup new factory.
813 DownloadFileWithDelayFactory
* file_factory
=
814 new DownloadFileWithDelayFactory();
815 DownloadManagerImpl
* download_manager(DownloadManagerForShell(shell()));
816 download_manager
->SetDownloadFileFactoryForTesting(
817 scoped_ptr
<DownloadFileFactory
>(file_factory
).Pass());
820 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
821 NavigateToURL(shell(), URLRequestMockHTTPJob::GetMockUrl(file
));
823 // Wait until the first (intermediate file) rename and execute the callback.
824 file_factory
->WaitForSomeCallback();
825 std::vector
<base::Closure
> callbacks
;
826 file_factory
->GetAllRenameCallbacks(&callbacks
);
827 ASSERT_EQ(1u, callbacks
.size());
831 // Wait until the second (final) rename callback is posted.
832 file_factory
->WaitForSomeCallback();
833 file_factory
->GetAllRenameCallbacks(&callbacks
);
834 ASSERT_EQ(1u, callbacks
.size());
837 std::vector
<DownloadItem
*> items
;
838 download_manager
->GetAllDownloads(&items
);
839 ASSERT_EQ(1u, items
.size());
840 items
[0]->Cancel(true);
841 RunAllPendingInMessageLoop();
844 EXPECT_EQ(DownloadItem::CANCELLED
, items
[0]->GetState());
846 // Run final rename callback.
851 EXPECT_EQ(DownloadItem::CANCELLED
, items
[0]->GetState());
854 // Try to cancel just after we release the download file, by delaying
855 // in ShouldOpenDownload.
856 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, CancelAtRelease
) {
857 DownloadManagerImpl
* download_manager(DownloadManagerForShell(shell()));
859 // Mark delegate for delayed open.
860 GetDownloadManagerDelegate()->SetDelayedOpen(true);
862 // Setup new factory.
863 DownloadFileWithDelayFactory
* file_factory
=
864 new DownloadFileWithDelayFactory();
865 download_manager
->SetDownloadFileFactoryForTesting(
866 scoped_ptr
<DownloadFileFactory
>(file_factory
).Pass());
869 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
870 NavigateToURL(shell(), URLRequestMockHTTPJob::GetMockUrl(file
));
872 // Wait until the first (intermediate file) rename and execute the callback.
873 file_factory
->WaitForSomeCallback();
874 std::vector
<base::Closure
> callbacks
;
875 file_factory
->GetAllRenameCallbacks(&callbacks
);
876 ASSERT_EQ(1u, callbacks
.size());
880 // Wait until the second (final) rename callback is posted.
881 file_factory
->WaitForSomeCallback();
882 file_factory
->GetAllRenameCallbacks(&callbacks
);
883 ASSERT_EQ(1u, callbacks
.size());
889 // Confirm download still IN_PROGRESS (internal state COMPLETING).
890 std::vector
<DownloadItem
*> items
;
891 download_manager
->GetAllDownloads(&items
);
892 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
894 // Cancel the download; confirm cancel fails.
895 ASSERT_EQ(1u, items
.size());
896 items
[0]->Cancel(true);
897 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
899 // Need to complete open test.
900 std::vector
<DownloadOpenDelayedCallback
> delayed_callbacks
;
901 GetDownloadManagerDelegate()->GetDelayedCallbacks(
903 ASSERT_EQ(1u, delayed_callbacks
.size());
904 delayed_callbacks
[0].Run(true);
906 // *Now* the download should be complete.
907 EXPECT_EQ(DownloadItem::COMPLETE
, items
[0]->GetState());
910 // Try to shutdown with a download in progress to make sure shutdown path
912 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ShutdownInProgress
) {
913 // Create a download that won't complete.
914 scoped_ptr
<DownloadCreateObserver
> observer(
915 CreateInProgressWaiter(shell(), 1));
916 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl
));
917 observer
->WaitForFinished();
920 std::vector
<DownloadItem
*> items
;
921 DownloadManagerForShell(shell())->GetAllDownloads(&items
);
922 ASSERT_EQ(1u, items
.size());
923 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
925 // Shutdown the download manager and make sure we get the right
926 // notifications in the right order.
927 StrictMock
<MockDownloadItemObserver
> item_observer
;
928 items
[0]->AddObserver(&item_observer
);
929 MockDownloadManagerObserver
manager_observer(
930 DownloadManagerForShell(shell()));
931 // Don't care about ModelChanged() events.
932 EXPECT_CALL(manager_observer
, ModelChanged(_
))
933 .WillRepeatedly(Return());
935 InSequence notifications
;
937 EXPECT_CALL(manager_observer
, MockManagerGoingDown(
938 DownloadManagerForShell(shell())))
940 EXPECT_CALL(item_observer
, OnDownloadUpdated(
942 Property(&DownloadItem::GetState
, DownloadItem::CANCELLED
))))
944 EXPECT_CALL(item_observer
, OnDownloadDestroyed(items
[0]))
948 // See http://crbug.com/324525. If we have a refcount release/post task
949 // race, the second post will stall the IO thread long enough so that we'll
950 // lose the race and crash. The first stall is just to give the UI thread
951 // a chance to get the second stall onto the IO thread queue after the cancel
952 // message created by Shutdown and before the notification callback
953 // created by the IO thread in canceling the request.
954 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
955 base::Bind(&base::PlatformThread::Sleep
,
956 base::TimeDelta::FromMilliseconds(25)));
957 DownloadManagerForShell(shell())->Shutdown();
958 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
959 base::Bind(&base::PlatformThread::Sleep
,
960 base::TimeDelta::FromMilliseconds(25)));
964 // Try to shutdown just after we release the download file, by delaying
966 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ShutdownAtRelease
) {
967 DownloadManagerImpl
* download_manager(DownloadManagerForShell(shell()));
969 // Mark delegate for delayed open.
970 GetDownloadManagerDelegate()->SetDelayedOpen(true);
972 // Setup new factory.
973 DownloadFileWithDelayFactory
* file_factory
=
974 new DownloadFileWithDelayFactory();
975 download_manager
->SetDownloadFileFactoryForTesting(
976 scoped_ptr
<DownloadFileFactory
>(file_factory
).Pass());
979 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
980 NavigateToURL(shell(), URLRequestMockHTTPJob::GetMockUrl(file
));
982 // Wait until the first (intermediate file) rename and execute the callback.
983 file_factory
->WaitForSomeCallback();
984 std::vector
<base::Closure
> callbacks
;
985 file_factory
->GetAllRenameCallbacks(&callbacks
);
986 ASSERT_EQ(1u, callbacks
.size());
990 // Wait until the second (final) rename callback is posted.
991 file_factory
->WaitForSomeCallback();
992 file_factory
->GetAllRenameCallbacks(&callbacks
);
993 ASSERT_EQ(1u, callbacks
.size());
999 // Confirm download isn't complete yet.
1000 std::vector
<DownloadItem
*> items
;
1001 DownloadManagerForShell(shell())->GetAllDownloads(&items
);
1002 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
1004 // Cancel the download; confirm cancel fails anyway.
1005 ASSERT_EQ(1u, items
.size());
1006 items
[0]->Cancel(true);
1007 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
1008 RunAllPendingInMessageLoop();
1009 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
1011 MockDownloadItemObserver observer
;
1012 items
[0]->AddObserver(&observer
);
1013 EXPECT_CALL(observer
, OnDownloadDestroyed(items
[0]));
1015 // Shutdown the download manager. Mostly this is confirming a lack of
1017 DownloadManagerForShell(shell())->Shutdown();
1020 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ResumeInterruptedDownload
) {
1021 CommandLine::ForCurrentProcess()->AppendSwitch(
1022 switches::kEnableDownloadResumption
);
1023 ASSERT_TRUE(test_server()->Start());
1025 GURL url
= test_server()->GetURL(
1026 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1027 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1029 MockDownloadManagerObserver
dm_observer(DownloadManagerForShell(shell()));
1030 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(1);
1032 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1033 WaitForData(download
, GetSafeBufferChunk());
1034 ::testing::Mock::VerifyAndClearExpectations(&dm_observer
);
1036 // Confirm resumption while in progress doesn't do anything.
1038 ASSERT_EQ(GetSafeBufferChunk(), download
->GetReceivedBytes());
1039 ASSERT_EQ(DownloadItem::IN_PROGRESS
, download
->GetState());
1041 // Tell the server to send the RST and confirm the interrupt happens.
1042 ReleaseRSTAndConfirmInterruptForResume(download
);
1043 ConfirmFileStatusForResume(
1044 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1045 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1047 // Resume, confirming received bytes on resumption is correct.
1048 // Make sure no creation calls are included.
1049 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(0);
1050 int initial_size
= 0;
1051 DownloadUpdatedObserver
initial_size_observer(
1052 download
, base::Bind(&InitialSizeFilter
, &initial_size
));
1054 initial_size_observer
.WaitForEvent();
1055 EXPECT_EQ(GetSafeBufferChunk(), initial_size
);
1056 ::testing::Mock::VerifyAndClearExpectations(&dm_observer
);
1058 // and wait for expected data.
1059 WaitForData(download
, GetSafeBufferChunk() * 2);
1061 // Tell the server to send the RST and confirm the interrupt happens.
1062 ReleaseRSTAndConfirmInterruptForResume(download
);
1063 ConfirmFileStatusForResume(
1064 download
, true, GetSafeBufferChunk() * 2, GetSafeBufferChunk() * 3,
1065 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1067 // Resume and wait for completion.
1068 DownloadUpdatedObserver
completion_observer(
1069 download
, base::Bind(DownloadCompleteFilter
));
1071 completion_observer
.WaitForEvent();
1073 ConfirmFileStatusForResume(
1074 download
, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1075 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1077 // Confirm resumption while complete doesn't do anything.
1079 ASSERT_EQ(GetSafeBufferChunk() * 3, download
->GetReceivedBytes());
1080 ASSERT_EQ(DownloadItem::COMPLETE
, download
->GetState());
1081 RunAllPendingInMessageLoop();
1082 ASSERT_EQ(GetSafeBufferChunk() * 3, download
->GetReceivedBytes());
1083 ASSERT_EQ(DownloadItem::COMPLETE
, download
->GetState());
1086 // Confirm restart fallback happens if a range request is bounced.
1087 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ResumeInterruptedDownloadNoRange
) {
1088 CommandLine::ForCurrentProcess()->AppendSwitch(
1089 switches::kEnableDownloadResumption
);
1090 ASSERT_TRUE(test_server()->Start());
1092 // Auto-restart if server doesn't handle ranges.
1093 GURL url
= test_server()->GetURL(
1095 // First download hits an RST, rest don't, no ranges.
1096 "rangereset?size=%d&rst_boundary=%d&"
1097 "token=NoRange&rst_limit=1&bounce_range",
1098 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1100 // Start the download and wait for first data chunk.
1101 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1102 WaitForData(download
, GetSafeBufferChunk());
1104 RecordingDownloadObserver
recorder(download
);
1106 ReleaseRSTAndConfirmInterruptForResume(download
);
1107 ConfirmFileStatusForResume(
1108 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1109 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1111 DownloadUpdatedObserver
completion_observer(
1112 download
, base::Bind(DownloadCompleteFilter
));
1114 completion_observer
.WaitForEvent();
1116 ConfirmFileStatusForResume(
1117 download
, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1118 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1120 static const RecordingDownloadObserver::RecordStruct expected_record
[] = {
1122 {DownloadItem::INTERRUPTED
, GetSafeBufferChunk()},
1123 // Starting continuation
1124 {DownloadItem::IN_PROGRESS
, GetSafeBufferChunk()},
1125 // Notification of receiving whole file.
1126 {DownloadItem::IN_PROGRESS
, 0},
1128 {DownloadItem::COMPLETE
, GetSafeBufferChunk() * 3},
1131 recorder
.CompareToExpectedRecord(expected_record
, arraysize(expected_record
));
1134 // Confirm restart fallback happens if a precondition is failed.
1135 IN_PROC_BROWSER_TEST_F(DownloadContentTest
,
1136 ResumeInterruptedDownloadBadPrecondition
) {
1137 CommandLine::ForCurrentProcess()->AppendSwitch(
1138 switches::kEnableDownloadResumption
);
1139 ASSERT_TRUE(test_server()->Start());
1141 GURL url
= test_server()->GetURL(base::StringPrintf(
1142 // First download hits an RST, rest don't, precondition fail.
1143 "rangereset?size=%d&rst_boundary=%d&"
1144 "token=BadPrecondition&rst_limit=1&fail_precondition=2",
1145 GetSafeBufferChunk() * 3,
1146 GetSafeBufferChunk()));
1148 // Start the download and wait for first data chunk.
1149 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1150 WaitForData(download
, GetSafeBufferChunk());
1152 RecordingDownloadObserver
recorder(download
);
1154 ReleaseRSTAndConfirmInterruptForResume(download
);
1155 ConfirmFileStatusForResume(
1156 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1157 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1158 EXPECT_EQ("BadPrecondition2", download
->GetETag());
1160 DownloadUpdatedObserver
completion_observer(
1161 download
, base::Bind(DownloadCompleteFilter
));
1163 completion_observer
.WaitForEvent();
1165 ConfirmFileStatusForResume(
1166 download
, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1167 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1168 EXPECT_EQ("BadPrecondition0", download
->GetETag());
1170 static const RecordingDownloadObserver::RecordStruct expected_record
[] = {
1172 {DownloadItem::INTERRUPTED
, GetSafeBufferChunk()},
1173 // Starting continuation
1174 {DownloadItem::IN_PROGRESS
, GetSafeBufferChunk()},
1175 // Server precondition fail.
1176 {DownloadItem::INTERRUPTED
, 0},
1177 // Notification of successful restart.
1178 {DownloadItem::IN_PROGRESS
, 0},
1180 {DownloadItem::COMPLETE
, GetSafeBufferChunk() * 3},
1183 recorder
.CompareToExpectedRecord(expected_record
, arraysize(expected_record
));
1186 // Confirm we don't try to resume if we don't have a verifier.
1187 IN_PROC_BROWSER_TEST_F(DownloadContentTest
,
1188 ResumeInterruptedDownloadNoVerifiers
) {
1189 CommandLine::ForCurrentProcess()->AppendSwitch(
1190 switches::kEnableDownloadResumption
);
1191 ASSERT_TRUE(test_server()->Start());
1193 GURL url
= test_server()->GetURL(
1195 // First download hits an RST, rest don't, no verifiers.
1196 "rangereset?size=%d&rst_boundary=%d&"
1197 "token=NoRange&rst_limit=1&no_verifiers",
1198 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1200 // Start the download and wait for first data chunk.
1201 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1202 WaitForData(download
, GetSafeBufferChunk());
1204 RecordingDownloadObserver
recorder(download
);
1206 ReleaseRSTAndConfirmInterruptForResume(download
);
1207 ConfirmFileStatusForResume(
1208 download
, false, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1211 DownloadUpdatedObserver
completion_observer(
1212 download
, base::Bind(DownloadCompleteFilter
));
1214 completion_observer
.WaitForEvent();
1216 ConfirmFileStatusForResume(
1217 download
, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1218 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1220 static const RecordingDownloadObserver::RecordStruct expected_record
[] = {
1222 {DownloadItem::INTERRUPTED
, GetSafeBufferChunk()},
1223 // Restart for lack of verifiers
1224 {DownloadItem::IN_PROGRESS
, 0},
1226 {DownloadItem::COMPLETE
, GetSafeBufferChunk() * 3},
1229 recorder
.CompareToExpectedRecord(expected_record
, arraysize(expected_record
));
1232 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ResumeWithDeletedFile
) {
1233 CommandLine::ForCurrentProcess()->AppendSwitch(
1234 switches::kEnableDownloadResumption
);
1235 ASSERT_TRUE(test_server()->Start());
1237 GURL url
= test_server()->GetURL(
1239 // First download hits an RST, rest don't
1240 "rangereset?size=%d&rst_boundary=%d&"
1241 "token=NoRange&rst_limit=1",
1242 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1244 // Start the download and wait for first data chunk.
1245 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1246 WaitForData(download
, GetSafeBufferChunk());
1248 RecordingDownloadObserver
recorder(download
);
1250 ReleaseRSTAndConfirmInterruptForResume(download
);
1251 ConfirmFileStatusForResume(
1252 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1253 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1255 // Delete the intermediate file.
1256 base::DeleteFile(download
->GetFullPath(), false);
1258 DownloadUpdatedObserver
completion_observer(
1259 download
, base::Bind(DownloadCompleteFilter
));
1261 completion_observer
.WaitForEvent();
1263 ConfirmFileStatusForResume(
1264 download
, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1265 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1267 static const RecordingDownloadObserver::RecordStruct expected_record
[] = {
1269 {DownloadItem::INTERRUPTED
, GetSafeBufferChunk()},
1270 // Starting continuation
1271 {DownloadItem::IN_PROGRESS
, GetSafeBufferChunk()},
1272 // Error because file isn't there.
1273 {DownloadItem::INTERRUPTED
, 0},
1275 {DownloadItem::IN_PROGRESS
, 0},
1277 {DownloadItem::COMPLETE
, GetSafeBufferChunk() * 3},
1280 recorder
.CompareToExpectedRecord(expected_record
, arraysize(expected_record
));
1283 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ResumeWithFileInitError
) {
1284 CommandLine::ForCurrentProcess()->AppendSwitch(
1285 switches::kEnableDownloadResumption
);
1286 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
1287 GURL
url(URLRequestMockHTTPJob::GetMockUrl(file
));
1289 // Setup the error injector.
1290 scoped_refptr
<TestFileErrorInjector
> injector(
1291 TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
1293 TestFileErrorInjector::FileErrorInfo err
= {
1295 TestFileErrorInjector::FILE_OPERATION_INITIALIZE
,
1297 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
1299 injector
->AddError(err
);
1300 injector
->InjectErrors();
1302 // Start and watch for interrupt.
1303 scoped_ptr
<DownloadTestObserver
> int_observer(
1304 CreateInterruptedWaiter(shell(), 1));
1305 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1306 int_observer
->WaitForFinished();
1307 ASSERT_EQ(DownloadItem::INTERRUPTED
, download
->GetState());
1308 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
,
1309 download
->GetLastReason());
1310 EXPECT_EQ(0, download
->GetReceivedBytes());
1311 EXPECT_TRUE(download
->GetFullPath().empty());
1312 EXPECT_TRUE(download
->GetTargetFilePath().empty());
1314 // We need to make sure that any cross-thread downloads communication has
1315 // quiesced before clearing and injecting the new errors, as the
1316 // InjectErrors() routine alters the currently in use download file
1317 // factory, which is a file thread object.
1318 RunAllPendingInMessageLoop(BrowserThread::FILE);
1319 RunAllPendingInMessageLoop();
1321 // Clear the old errors list.
1322 injector
->ClearErrors();
1323 injector
->InjectErrors();
1325 // Resume and watch completion.
1326 DownloadUpdatedObserver
completion_observer(
1327 download
, base::Bind(DownloadCompleteFilter
));
1329 completion_observer
.WaitForEvent();
1330 EXPECT_EQ(download
->GetState(), DownloadItem::COMPLETE
);
1333 IN_PROC_BROWSER_TEST_F(DownloadContentTest
,
1334 ResumeWithFileIntermediateRenameError
) {
1335 CommandLine::ForCurrentProcess()->AppendSwitch(
1336 switches::kEnableDownloadResumption
);
1337 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
1338 GURL
url(URLRequestMockHTTPJob::GetMockUrl(file
));
1340 // Setup the error injector.
1341 scoped_refptr
<TestFileErrorInjector
> injector(
1342 TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
1344 TestFileErrorInjector::FileErrorInfo err
= {
1346 TestFileErrorInjector::FILE_OPERATION_RENAME_UNIQUIFY
,
1348 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
1350 injector
->AddError(err
);
1351 injector
->InjectErrors();
1353 // Start and watch for interrupt.
1354 scoped_ptr
<DownloadTestObserver
> int_observer(
1355 CreateInterruptedWaiter(shell(), 1));
1356 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1357 int_observer
->WaitForFinished();
1358 ASSERT_EQ(DownloadItem::INTERRUPTED
, download
->GetState());
1359 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
,
1360 download
->GetLastReason());
1361 EXPECT_TRUE(download
->GetFullPath().empty());
1362 // Target path will have been set after file name determination. GetFullPath()
1363 // being empty is sufficient to signal that filename determination needs to be
1365 EXPECT_FALSE(download
->GetTargetFilePath().empty());
1367 // We need to make sure that any cross-thread downloads communication has
1368 // quiesced before clearing and injecting the new errors, as the
1369 // InjectErrors() routine alters the currently in use download file
1370 // factory, which is a file thread object.
1371 RunAllPendingInMessageLoop(BrowserThread::FILE);
1372 RunAllPendingInMessageLoop();
1374 // Clear the old errors list.
1375 injector
->ClearErrors();
1376 injector
->InjectErrors();
1378 // Resume and watch completion.
1379 DownloadUpdatedObserver
completion_observer(
1380 download
, base::Bind(DownloadCompleteFilter
));
1382 completion_observer
.WaitForEvent();
1383 EXPECT_EQ(download
->GetState(), DownloadItem::COMPLETE
);
1386 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ResumeWithFileFinalRenameError
) {
1387 CommandLine::ForCurrentProcess()->AppendSwitch(
1388 switches::kEnableDownloadResumption
);
1389 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
1390 GURL
url(URLRequestMockHTTPJob::GetMockUrl(file
));
1392 // Setup the error injector.
1393 scoped_refptr
<TestFileErrorInjector
> injector(
1394 TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
1396 DownloadManagerForShell(shell())->RemoveAllDownloads();
1397 TestFileErrorInjector::FileErrorInfo err
= {
1399 TestFileErrorInjector::FILE_OPERATION_RENAME_ANNOTATE
,
1401 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
1403 injector
->AddError(err
);
1404 injector
->InjectErrors();
1406 // Start and watch for interrupt.
1407 scoped_ptr
<DownloadTestObserver
> int_observer(
1408 CreateInterruptedWaiter(shell(), 1));
1409 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1410 int_observer
->WaitForFinished();
1411 ASSERT_EQ(DownloadItem::INTERRUPTED
, download
->GetState());
1412 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
,
1413 download
->GetLastReason());
1414 EXPECT_TRUE(download
->GetFullPath().empty());
1415 // Target path should still be intact.
1416 EXPECT_FALSE(download
->GetTargetFilePath().empty());
1418 // We need to make sure that any cross-thread downloads communication has
1419 // quiesced before clearing and injecting the new errors, as the
1420 // InjectErrors() routine alters the currently in use download file
1421 // factory, which is a file thread object.
1422 RunAllPendingInMessageLoop(BrowserThread::FILE);
1423 RunAllPendingInMessageLoop();
1425 // Clear the old errors list.
1426 injector
->ClearErrors();
1427 injector
->InjectErrors();
1429 // Resume and watch completion.
1430 DownloadUpdatedObserver
completion_observer(
1431 download
, base::Bind(DownloadCompleteFilter
));
1433 completion_observer
.WaitForEvent();
1434 EXPECT_EQ(download
->GetState(), DownloadItem::COMPLETE
);
1437 // An interrupted download should remove the intermediate file when it is
1439 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, CancelInterruptedDownload
) {
1440 CommandLine::ForCurrentProcess()->AppendSwitch(
1441 switches::kEnableDownloadResumption
);
1442 ASSERT_TRUE(test_server()->Start());
1444 GURL url1
= test_server()->GetURL(
1445 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1446 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1448 DownloadItem
* download(StartDownloadAndReturnItem(url1
));
1449 WaitForData(download
, GetSafeBufferChunk());
1451 ReleaseRSTAndConfirmInterruptForResume(download
);
1452 ConfirmFileStatusForResume(
1453 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1454 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1456 base::FilePath
intermediate_path(download
->GetFullPath());
1457 ASSERT_FALSE(intermediate_path
.empty());
1458 EXPECT_TRUE(base::PathExists(intermediate_path
));
1460 download
->Cancel(true /* user_cancel */);
1461 RunAllPendingInMessageLoop(BrowserThread::FILE);
1462 RunAllPendingInMessageLoop();
1464 // The intermediate file should now be gone.
1465 EXPECT_FALSE(base::PathExists(intermediate_path
));
1466 EXPECT_TRUE(download
->GetFullPath().empty());
1469 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, RemoveDownload
) {
1470 CommandLine::ForCurrentProcess()->AppendSwitch(
1471 switches::kEnableDownloadResumption
);
1472 ASSERT_TRUE(test_server()->Start());
1474 // An interrupted download should remove the intermediate file when it is
1477 GURL url1
= test_server()->GetURL(
1478 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1479 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1481 DownloadItem
* download(StartDownloadAndReturnItem(url1
));
1482 WaitForData(download
, GetSafeBufferChunk());
1483 ReleaseRSTAndConfirmInterruptForResume(download
);
1484 ConfirmFileStatusForResume(
1485 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1486 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1488 base::FilePath
intermediate_path(download
->GetFullPath());
1489 ASSERT_FALSE(intermediate_path
.empty());
1490 EXPECT_TRUE(base::PathExists(intermediate_path
));
1493 RunAllPendingInMessageLoop(BrowserThread::FILE);
1494 RunAllPendingInMessageLoop();
1496 // The intermediate file should now be gone.
1497 EXPECT_FALSE(base::PathExists(intermediate_path
));
1500 // A completed download shouldn't delete the downloaded file when it is
1503 // Start the second download and wait until it's done.
1504 base::FilePath
file2(FILE_PATH_LITERAL("download-test.lib"));
1505 GURL
url2(URLRequestMockHTTPJob::GetMockUrl(file2
));
1506 scoped_ptr
<DownloadTestObserver
> completion_observer(
1507 CreateWaiter(shell(), 1));
1508 DownloadItem
* download(StartDownloadAndReturnItem(url2
));
1509 completion_observer
->WaitForFinished();
1511 // The target path should exist.
1512 base::FilePath
target_path(download
->GetTargetFilePath());
1513 EXPECT_TRUE(base::PathExists(target_path
));
1515 RunAllPendingInMessageLoop(BrowserThread::FILE);
1516 RunAllPendingInMessageLoop();
1518 // The file should still exist.
1519 EXPECT_TRUE(base::PathExists(target_path
));
1523 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, RemoveResumingDownload
) {
1524 SetupEnsureNoPendingDownloads();
1525 CommandLine::ForCurrentProcess()->AppendSwitch(
1526 switches::kEnableDownloadResumption
);
1527 ASSERT_TRUE(test_server()->Start());
1529 GURL url
= test_server()->GetURL(
1530 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1531 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1533 MockDownloadManagerObserver
dm_observer(DownloadManagerForShell(shell()));
1534 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(1);
1536 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1537 WaitForData(download
, GetSafeBufferChunk());
1538 ::testing::Mock::VerifyAndClearExpectations(&dm_observer
);
1540 // Tell the server to send the RST and confirm the interrupt happens.
1541 ReleaseRSTAndConfirmInterruptForResume(download
);
1542 ConfirmFileStatusForResume(
1543 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1544 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1546 base::FilePath
intermediate_path(download
->GetFullPath());
1547 ASSERT_FALSE(intermediate_path
.empty());
1548 EXPECT_TRUE(base::PathExists(intermediate_path
));
1550 // Resume and remove download. We expect only a single OnDownloadCreated()
1551 // call, and that's for the second download created below.
1552 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(1);
1556 // The intermediate file should now be gone.
1557 RunAllPendingInMessageLoop(BrowserThread::FILE);
1558 RunAllPendingInMessageLoop();
1559 EXPECT_FALSE(base::PathExists(intermediate_path
));
1561 // Start the second download and wait until it's done. The test server is
1562 // single threaded. The response to this download request should follow the
1563 // response to the previous resumption request.
1564 GURL
url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x"));
1565 DownloadAndWait(shell(), url2
, DownloadItem::COMPLETE
);
1567 EXPECT_TRUE(EnsureNoPendingDownloads());
1570 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, CancelResumingDownload
) {
1571 SetupEnsureNoPendingDownloads();
1572 CommandLine::ForCurrentProcess()->AppendSwitch(
1573 switches::kEnableDownloadResumption
);
1574 ASSERT_TRUE(test_server()->Start());
1576 GURL url
= test_server()->GetURL(
1577 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1578 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1580 MockDownloadManagerObserver
dm_observer(DownloadManagerForShell(shell()));
1581 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(1);
1583 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1584 WaitForData(download
, GetSafeBufferChunk());
1585 ::testing::Mock::VerifyAndClearExpectations(&dm_observer
);
1587 // Tell the server to send the RST and confirm the interrupt happens.
1588 ReleaseRSTAndConfirmInterruptForResume(download
);
1589 ConfirmFileStatusForResume(
1590 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1591 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1593 base::FilePath
intermediate_path(download
->GetFullPath());
1594 ASSERT_FALSE(intermediate_path
.empty());
1595 EXPECT_TRUE(base::PathExists(intermediate_path
));
1597 // Resume and cancel download. We expect only a single OnDownloadCreated()
1598 // call, and that's for the second download created below.
1599 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(1);
1601 download
->Cancel(true);
1603 // The intermediate file should now be gone.
1604 RunAllPendingInMessageLoop(BrowserThread::FILE);
1605 RunAllPendingInMessageLoop();
1606 EXPECT_FALSE(base::PathExists(intermediate_path
));
1607 EXPECT_TRUE(download
->GetFullPath().empty());
1609 // Start the second download and wait until it's done. The test server is
1610 // single threaded. The response to this download request should follow the
1611 // response to the previous resumption request.
1612 GURL
url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x"));
1613 DownloadAndWait(shell(), url2
, DownloadItem::COMPLETE
);
1615 EXPECT_TRUE(EnsureNoPendingDownloads());
1618 // Check that the cookie policy is correctly updated when downloading a file
1619 // that redirects cross origin.
1620 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, CookiePolicy
) {
1621 ASSERT_TRUE(test_server()->Start());
1622 net::HostPortPair host_port
= test_server()->host_port_pair();
1623 DCHECK_EQ(host_port
.host(), std::string("127.0.0.1"));
1625 // Block third-party cookies.
1626 ShellNetworkDelegate::SetAcceptAllCookies(false);
1628 // |url| redirects to a different origin |download| which tries to set a
1630 std::string
download(base::StringPrintf(
1631 "http://localhost:%d/set-cookie?A=B", host_port
.port()));
1632 GURL
url(test_server()->GetURL("server-redirect?" + download
));
1634 // Download the file.
1635 SetupEnsureNoPendingDownloads();
1636 scoped_ptr
<DownloadUrlParameters
> dl_params(
1637 DownloadUrlParameters::FromWebContents(shell()->web_contents(), url
));
1638 scoped_ptr
<DownloadTestObserver
> observer(CreateWaiter(shell(), 1));
1639 DownloadManagerForShell(shell())->DownloadUrl(dl_params
.Pass());
1640 observer
->WaitForFinished();
1642 // Get the important info from other threads and check it.
1643 EXPECT_TRUE(EnsureNoPendingDownloads());
1645 std::vector
<DownloadItem
*> downloads
;
1646 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
1647 ASSERT_EQ(1u, downloads
.size());
1648 ASSERT_EQ(DownloadItem::COMPLETE
, downloads
[0]->GetState());
1650 // Check that the cookies were correctly set.
1652 content::GetCookies(shell()->web_contents()->GetBrowserContext(),
1656 } // namespace content