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/embedded_test_server/embedded_test_server.h"
40 #include "net/test/embedded_test_server/http_request.h"
41 #include "net/test/embedded_test_server/http_response.h"
42 #include "net/test/spawned_test_server/spawned_test_server.h"
43 #include "testing/gmock/include/gmock/gmock.h"
44 #include "testing/gtest/include/gtest/gtest.h"
47 using ::net::test_server::EmbeddedTestServer
;
48 using ::testing::AllOf
;
49 using ::testing::Field
;
50 using ::testing::InSequence
;
51 using ::testing::Property
;
52 using ::testing::Return
;
53 using ::testing::StrictMock
;
60 class MockDownloadItemObserver
: public DownloadItem::Observer
{
62 MockDownloadItemObserver() {}
63 virtual ~MockDownloadItemObserver() {}
65 MOCK_METHOD1(OnDownloadUpdated
, void(DownloadItem
*));
66 MOCK_METHOD1(OnDownloadOpened
, void(DownloadItem
*));
67 MOCK_METHOD1(OnDownloadRemoved
, void(DownloadItem
*));
68 MOCK_METHOD1(OnDownloadDestroyed
, void(DownloadItem
*));
71 class MockDownloadManagerObserver
: public DownloadManager::Observer
{
73 MockDownloadManagerObserver(DownloadManager
* manager
) {
75 manager
->AddObserver(this);
77 virtual ~MockDownloadManagerObserver() {
79 manager_
->RemoveObserver(this);
82 MOCK_METHOD2(OnDownloadCreated
, void(DownloadManager
*, DownloadItem
*));
83 MOCK_METHOD1(ModelChanged
, void(DownloadManager
*));
84 void ManagerGoingDown(DownloadManager
* manager
) {
85 DCHECK_EQ(manager_
, manager
);
86 MockManagerGoingDown(manager
);
88 manager_
->RemoveObserver(this);
92 MOCK_METHOD1(MockManagerGoingDown
, void(DownloadManager
*));
94 DownloadManager
* manager_
;
97 class DownloadFileWithDelayFactory
;
99 static DownloadManagerImpl
* DownloadManagerForShell(Shell
* shell
) {
100 // We're in a content_browsertest; we know that the DownloadManager
101 // is a DownloadManagerImpl.
102 return static_cast<DownloadManagerImpl
*>(
103 BrowserContext::GetDownloadManager(
104 shell
->web_contents()->GetBrowserContext()));
107 class DownloadFileWithDelay
: public DownloadFileImpl
{
109 DownloadFileWithDelay(
110 scoped_ptr
<DownloadSaveInfo
> save_info
,
111 const base::FilePath
& default_download_directory
,
113 const GURL
& referrer_url
,
115 scoped_ptr
<ByteStreamReader
> stream
,
116 const net::BoundNetLog
& bound_net_log
,
117 scoped_ptr
<PowerSaveBlocker
> power_save_blocker
,
118 base::WeakPtr
<DownloadDestinationObserver
> observer
,
119 base::WeakPtr
<DownloadFileWithDelayFactory
> owner
);
121 virtual ~DownloadFileWithDelay();
123 // Wraps DownloadFileImpl::Rename* and intercepts the return callback,
124 // storing it in the factory that produced this object for later
126 virtual void RenameAndUniquify(
127 const base::FilePath
& full_path
,
128 const RenameCompletionCallback
& callback
) OVERRIDE
;
129 virtual void RenameAndAnnotate(
130 const base::FilePath
& full_path
,
131 const RenameCompletionCallback
& callback
) OVERRIDE
;
134 static void RenameCallbackWrapper(
135 const base::WeakPtr
<DownloadFileWithDelayFactory
>& factory
,
136 const RenameCompletionCallback
& original_callback
,
137 DownloadInterruptReason reason
,
138 const base::FilePath
& path
);
140 // This variable may only be read on the FILE thread, and may only be
141 // indirected through (e.g. methods on DownloadFileWithDelayFactory called)
142 // on the UI thread. This is because after construction,
143 // DownloadFileWithDelay lives on the file thread, but
144 // DownloadFileWithDelayFactory is purely a UI thread object.
145 base::WeakPtr
<DownloadFileWithDelayFactory
> owner_
;
147 DISALLOW_COPY_AND_ASSIGN(DownloadFileWithDelay
);
150 // All routines on this class must be called on the UI thread.
151 class DownloadFileWithDelayFactory
: public DownloadFileFactory
{
153 DownloadFileWithDelayFactory();
154 virtual ~DownloadFileWithDelayFactory();
156 // DownloadFileFactory interface.
157 virtual DownloadFile
* CreateFile(
158 scoped_ptr
<DownloadSaveInfo
> save_info
,
159 const base::FilePath
& default_download_directory
,
161 const GURL
& referrer_url
,
163 scoped_ptr
<ByteStreamReader
> stream
,
164 const net::BoundNetLog
& bound_net_log
,
165 base::WeakPtr
<DownloadDestinationObserver
> observer
) OVERRIDE
;
167 void AddRenameCallback(base::Closure callback
);
168 void GetAllRenameCallbacks(std::vector
<base::Closure
>* results
);
170 // Do not return until GetAllRenameCallbacks() will return a non-empty list.
171 void WaitForSomeCallback();
174 base::WeakPtrFactory
<DownloadFileWithDelayFactory
> weak_ptr_factory_
;
175 std::vector
<base::Closure
> rename_callbacks_
;
178 DISALLOW_COPY_AND_ASSIGN(DownloadFileWithDelayFactory
);
181 DownloadFileWithDelay::DownloadFileWithDelay(
182 scoped_ptr
<DownloadSaveInfo
> save_info
,
183 const base::FilePath
& default_download_directory
,
185 const GURL
& referrer_url
,
187 scoped_ptr
<ByteStreamReader
> stream
,
188 const net::BoundNetLog
& bound_net_log
,
189 scoped_ptr
<PowerSaveBlocker
> power_save_blocker
,
190 base::WeakPtr
<DownloadDestinationObserver
> observer
,
191 base::WeakPtr
<DownloadFileWithDelayFactory
> owner
)
193 save_info
.Pass(), default_download_directory
, url
, referrer_url
,
194 calculate_hash
, stream
.Pass(), bound_net_log
, observer
),
197 DownloadFileWithDelay::~DownloadFileWithDelay() {}
199 void DownloadFileWithDelay::RenameAndUniquify(
200 const base::FilePath
& full_path
,
201 const RenameCompletionCallback
& callback
) {
202 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
203 DownloadFileImpl::RenameAndUniquify(
204 full_path
, base::Bind(DownloadFileWithDelay::RenameCallbackWrapper
,
208 void DownloadFileWithDelay::RenameAndAnnotate(
209 const base::FilePath
& full_path
, const RenameCompletionCallback
& callback
) {
210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
211 DownloadFileImpl::RenameAndAnnotate(
212 full_path
, base::Bind(DownloadFileWithDelay::RenameCallbackWrapper
,
217 void DownloadFileWithDelay::RenameCallbackWrapper(
218 const base::WeakPtr
<DownloadFileWithDelayFactory
>& factory
,
219 const RenameCompletionCallback
& original_callback
,
220 DownloadInterruptReason reason
,
221 const base::FilePath
& path
) {
222 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
225 factory
->AddRenameCallback(base::Bind(original_callback
, reason
, path
));
228 DownloadFileWithDelayFactory::DownloadFileWithDelayFactory()
229 : weak_ptr_factory_(this),
231 DownloadFileWithDelayFactory::~DownloadFileWithDelayFactory() {}
233 DownloadFile
* DownloadFileWithDelayFactory::CreateFile(
234 scoped_ptr
<DownloadSaveInfo
> save_info
,
235 const base::FilePath
& default_download_directory
,
237 const GURL
& referrer_url
,
239 scoped_ptr
<ByteStreamReader
> stream
,
240 const net::BoundNetLog
& bound_net_log
,
241 base::WeakPtr
<DownloadDestinationObserver
> observer
) {
242 scoped_ptr
<PowerSaveBlocker
> psb(
243 PowerSaveBlocker::Create(
244 PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension
,
245 "Download in progress"));
246 return new DownloadFileWithDelay(
247 save_info
.Pass(), default_download_directory
, url
, referrer_url
,
248 calculate_hash
, stream
.Pass(), bound_net_log
,
249 psb
.Pass(), observer
, weak_ptr_factory_
.GetWeakPtr());
252 void DownloadFileWithDelayFactory::AddRenameCallback(base::Closure callback
) {
253 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
254 rename_callbacks_
.push_back(callback
);
256 base::MessageLoopForUI::current()->Quit();
259 void DownloadFileWithDelayFactory::GetAllRenameCallbacks(
260 std::vector
<base::Closure
>* results
) {
261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
262 results
->swap(rename_callbacks_
);
265 void DownloadFileWithDelayFactory::WaitForSomeCallback() {
266 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
268 if (rename_callbacks_
.empty()) {
275 class CountingDownloadFile
: public DownloadFileImpl
{
277 CountingDownloadFile(
278 scoped_ptr
<DownloadSaveInfo
> save_info
,
279 const base::FilePath
& default_downloads_directory
,
281 const GURL
& referrer_url
,
283 scoped_ptr
<ByteStreamReader
> stream
,
284 const net::BoundNetLog
& bound_net_log
,
285 scoped_ptr
<PowerSaveBlocker
> power_save_blocker
,
286 base::WeakPtr
<DownloadDestinationObserver
> observer
)
287 : DownloadFileImpl(save_info
.Pass(), default_downloads_directory
,
288 url
, referrer_url
, calculate_hash
,
289 stream
.Pass(), bound_net_log
, observer
) {}
291 virtual ~CountingDownloadFile() {
292 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
296 virtual void Initialize(const InitializeCallback
& callback
) OVERRIDE
{
297 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
299 return DownloadFileImpl::Initialize(callback
);
302 static void GetNumberActiveFiles(int* result
) {
303 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
304 *result
= active_files_
;
307 // Can be called on any thread, and will block (running message loop)
308 // until data is returned.
309 static int GetNumberActiveFilesFromFileThread() {
311 BrowserThread::PostTaskAndReply(
314 base::Bind(&CountingDownloadFile::GetNumberActiveFiles
, &result
),
315 base::MessageLoop::current()->QuitClosure());
316 base::MessageLoop::current()->Run();
317 DCHECK_NE(-1, result
);
322 static int active_files_
;
325 int CountingDownloadFile::active_files_
= 0;
327 class CountingDownloadFileFactory
: public DownloadFileFactory
{
329 CountingDownloadFileFactory() {}
330 virtual ~CountingDownloadFileFactory() {}
332 // DownloadFileFactory interface.
333 virtual DownloadFile
* CreateFile(
334 scoped_ptr
<DownloadSaveInfo
> save_info
,
335 const base::FilePath
& default_downloads_directory
,
337 const GURL
& referrer_url
,
339 scoped_ptr
<ByteStreamReader
> stream
,
340 const net::BoundNetLog
& bound_net_log
,
341 base::WeakPtr
<DownloadDestinationObserver
> observer
) OVERRIDE
{
342 scoped_ptr
<PowerSaveBlocker
> psb(
343 PowerSaveBlocker::Create(
344 PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension
,
345 "Download in progress"));
346 return new CountingDownloadFile(
347 save_info
.Pass(), default_downloads_directory
, url
, referrer_url
,
348 calculate_hash
, stream
.Pass(), bound_net_log
,
349 psb
.Pass(), observer
);
353 class TestShellDownloadManagerDelegate
: public ShellDownloadManagerDelegate
{
355 TestShellDownloadManagerDelegate()
356 : delay_download_open_(false) {}
357 virtual ~TestShellDownloadManagerDelegate() {}
359 virtual bool ShouldOpenDownload(
361 const DownloadOpenDelayedCallback
& callback
) OVERRIDE
{
362 if (delay_download_open_
) {
363 delayed_callbacks_
.push_back(callback
);
369 void SetDelayedOpen(bool delay
) {
370 delay_download_open_
= delay
;
373 void GetDelayedCallbacks(
374 std::vector
<DownloadOpenDelayedCallback
>* callbacks
) {
375 callbacks
->swap(delayed_callbacks_
);
378 bool delay_download_open_
;
379 std::vector
<DownloadOpenDelayedCallback
> delayed_callbacks_
;
382 // Record all state transitions and byte counts on the observed download.
383 class RecordingDownloadObserver
: DownloadItem::Observer
{
385 struct RecordStruct
{
386 DownloadItem::DownloadState state
;
390 typedef std::vector
<RecordStruct
> RecordVector
;
392 RecordingDownloadObserver(DownloadItem
* download
)
393 : download_(download
) {
394 last_state_
.state
= download
->GetState();
395 last_state_
.bytes_received
= download
->GetReceivedBytes();
396 download_
->AddObserver(this);
399 virtual ~RecordingDownloadObserver() {
403 void CompareToExpectedRecord(const RecordStruct expected
[], size_t size
) {
404 EXPECT_EQ(size
, record_
.size());
405 int min
= size
> record_
.size() ? record_
.size() : size
;
406 for (int i
= 0; i
< min
; ++i
) {
407 EXPECT_EQ(expected
[i
].state
, record_
[i
].state
) << "Iteration " << i
;
408 EXPECT_EQ(expected
[i
].bytes_received
, record_
[i
].bytes_received
)
409 << "Iteration " << i
;
414 virtual void OnDownloadUpdated(DownloadItem
* download
) OVERRIDE
{
415 DCHECK_EQ(download_
, download
);
416 DownloadItem::DownloadState state
= download
->GetState();
417 int bytes
= download
->GetReceivedBytes();
418 if (last_state_
.state
!= state
|| last_state_
.bytes_received
> bytes
) {
419 last_state_
.state
= state
;
420 last_state_
.bytes_received
= bytes
;
421 record_
.push_back(last_state_
);
425 virtual void OnDownloadDestroyed(DownloadItem
* download
) OVERRIDE
{
426 DCHECK_EQ(download_
, download
);
430 void RemoveObserver() {
432 download_
->RemoveObserver(this);
437 DownloadItem
* download_
;
438 RecordStruct last_state_
;
439 RecordVector record_
;
442 // Get the next created download.
443 class DownloadCreateObserver
: DownloadManager::Observer
{
445 DownloadCreateObserver(DownloadManager
* manager
)
449 manager_
->AddObserver(this);
452 virtual ~DownloadCreateObserver() {
454 manager_
->RemoveObserver(this);
458 virtual void ManagerGoingDown(DownloadManager
* manager
) OVERRIDE
{
459 DCHECK_EQ(manager_
, manager
);
460 manager_
->RemoveObserver(this);
464 virtual void OnDownloadCreated(DownloadManager
* manager
,
465 DownloadItem
* download
) OVERRIDE
{
470 base::MessageLoopForUI::current()->Quit();
473 DownloadItem
* WaitForFinished() {
474 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
484 DownloadManager
* manager_
;
490 // Filter for waiting for a certain number of bytes.
491 bool DataReceivedFilter(int number_of_bytes
, DownloadItem
* download
) {
492 return download
->GetReceivedBytes() >= number_of_bytes
;
495 // Filter for download completion.
496 bool DownloadCompleteFilter(DownloadItem
* download
) {
497 return download
->GetState() == DownloadItem::COMPLETE
;
500 // Filter for saving the size of the download when the first IN_PROGRESS
502 bool InitialSizeFilter(int* download_size
, DownloadItem
* download
) {
503 if (download
->GetState() != DownloadItem::IN_PROGRESS
)
506 *download_size
= download
->GetReceivedBytes();
510 // Request handler to be used with CreateRedirectHandler().
511 scoped_ptr
<net::test_server::HttpResponse
> HandleRequestAndSendRedirectResponse(
512 const std::string
& relative_url
,
513 const GURL
& target_url
,
514 const net::test_server::HttpRequest
& request
) {
515 scoped_ptr
<net::test_server::BasicHttpResponse
> response
;
516 if (request
.relative_url
== relative_url
) {
517 response
.reset(new net::test_server::BasicHttpResponse
);
518 response
->set_code(net::HTTP_FOUND
);
519 response
->AddCustomHeader("Location", target_url
.spec());
521 return response
.PassAs
<net::test_server::HttpResponse
>();
524 // Creates a request handler for EmbeddedTestServer that responds with a HTTP
525 // 302 redirect if the request URL matches |relative_url|.
526 EmbeddedTestServer::HandleRequestCallback
CreateRedirectHandler(
527 const std::string
& relative_url
,
528 const GURL
& target_url
) {
530 &HandleRequestAndSendRedirectResponse
, relative_url
, target_url
);
533 // Request handler to be used with CreateBasicResponseHandler().
534 scoped_ptr
<net::test_server::HttpResponse
> HandleRequestAndSendBasicResponse(
535 const std::string
& relative_url
,
536 const std::string
& content_type
,
537 const std::string
& body
,
538 const net::test_server::HttpRequest
& request
) {
539 scoped_ptr
<net::test_server::BasicHttpResponse
> response
;
540 if (request
.relative_url
== relative_url
) {
541 response
.reset(new net::test_server::BasicHttpResponse
);
542 response
->set_content_type(content_type
);
543 response
->set_content(body
);
545 return response
.PassAs
<net::test_server::HttpResponse
>();
548 // Creates a request handler for an EmbeddedTestServer that response with an
549 // HTTP 200 status code, a Content-Type header and a body.
550 EmbeddedTestServer::HandleRequestCallback
CreateBasicResponseHandler(
551 const std::string
& relative_url
,
552 const std::string
& content_type
,
553 const std::string
& body
) {
555 &HandleRequestAndSendBasicResponse
, relative_url
, content_type
, body
);
560 class DownloadContentTest
: public ContentBrowserTest
{
562 // An initial send from a website of at least this size will not be
563 // help up by buffering in the underlying downloads ByteStream data
564 // transfer. This is important because on resumption tests we wait
565 // until we've gotten the data we expect before allowing the test server
566 // to send its reset, to get around hard close semantics on the Windows
567 // socket layer implementation.
568 int GetSafeBufferChunk() const {
569 return (DownloadResourceHandler::kDownloadByteStreamSize
/
570 ByteStreamWriter::kFractionBufferBeforeSending
) + 1;
573 virtual void SetUpOnMainThread() OVERRIDE
{
574 ASSERT_TRUE(downloads_directory_
.CreateUniqueTempDir());
576 test_delegate_
.reset(new TestShellDownloadManagerDelegate());
577 test_delegate_
->SetDownloadBehaviorForTesting(downloads_directory_
.path());
578 DownloadManager
* manager
= DownloadManagerForShell(shell());
579 manager
->GetDelegate()->Shutdown();
580 manager
->SetDelegate(test_delegate_
.get());
581 test_delegate_
->SetDownloadManager(manager
);
583 BrowserThread::PostTask(
584 BrowserThread::IO
, FROM_HERE
,
585 base::Bind(&URLRequestSlowDownloadJob::AddUrlHandler
));
586 base::FilePath
mock_base(GetTestFilePath("download", ""));
587 BrowserThread::PostTask(
588 BrowserThread::IO
, FROM_HERE
,
589 base::Bind(&URLRequestMockHTTPJob::AddUrlHandler
, mock_base
));
592 TestShellDownloadManagerDelegate
* GetDownloadManagerDelegate() {
593 return test_delegate_
.get();
596 // Create a DownloadTestObserverTerminal that will wait for the
597 // specified number of downloads to finish.
598 DownloadTestObserver
* CreateWaiter(
599 Shell
* shell
, int num_downloads
) {
600 DownloadManager
* download_manager
= DownloadManagerForShell(shell
);
601 return new DownloadTestObserverTerminal(download_manager
, num_downloads
,
602 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL
);
605 // Create a DownloadTestObserverInProgress that will wait for the
606 // specified number of downloads to start.
607 DownloadCreateObserver
* CreateInProgressWaiter(
608 Shell
* shell
, int num_downloads
) {
609 DownloadManager
* download_manager
= DownloadManagerForShell(shell
);
610 return new DownloadCreateObserver(download_manager
);
613 DownloadTestObserver
* CreateInterruptedWaiter(
614 Shell
* shell
, int num_downloads
) {
615 DownloadManager
* download_manager
= DownloadManagerForShell(shell
);
616 return new DownloadTestObserverInterrupted(download_manager
, num_downloads
,
617 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL
);
620 // Note: Cannot be used with other alternative DownloadFileFactorys
621 void SetupEnsureNoPendingDownloads() {
622 DownloadManagerForShell(shell())->SetDownloadFileFactoryForTesting(
623 scoped_ptr
<DownloadFileFactory
>(
624 new CountingDownloadFileFactory()).Pass());
627 bool EnsureNoPendingDownloads() {
629 BrowserThread::PostTask(
630 BrowserThread::IO
, FROM_HERE
,
631 base::Bind(&EnsureNoPendingDownloadJobsOnIO
, &result
));
632 base::MessageLoop::current()->Run();
634 (CountingDownloadFile::GetNumberActiveFilesFromFileThread() == 0);
637 void NavigateToURLAndWaitForDownload(
640 DownloadItem::DownloadState expected_terminal_state
) {
641 scoped_ptr
<DownloadTestObserver
> observer(CreateWaiter(shell
, 1));
642 NavigateToURL(shell
, url
);
643 observer
->WaitForFinished();
644 EXPECT_EQ(1u, observer
->NumDownloadsSeenInState(expected_terminal_state
));
647 // Checks that |path| is has |file_size| bytes, and matches the |value|
649 bool VerifyFile(const base::FilePath
& path
,
650 const std::string
& value
,
651 const int64 file_size
) {
652 std::string file_contents
;
654 bool read
= base::ReadFileToString(path
, &file_contents
);
655 EXPECT_TRUE(read
) << "Failed reading file: " << path
.value() << std::endl
;
657 return false; // Couldn't read the file.
659 // Note: we don't handle really large files (more than size_t can hold)
660 // so we will fail in that case.
661 size_t expected_size
= static_cast<size_t>(file_size
);
664 EXPECT_EQ(expected_size
, file_contents
.size());
665 if (expected_size
!= file_contents
.size())
668 // Check the contents.
669 EXPECT_EQ(value
, file_contents
);
670 if (memcmp(file_contents
.c_str(), value
.c_str(), expected_size
) != 0)
676 // Start a download and return the item.
677 DownloadItem
* StartDownloadAndReturnItem(GURL url
) {
678 scoped_ptr
<DownloadCreateObserver
> observer(
679 CreateInProgressWaiter(shell(), 1));
680 NavigateToURL(shell(), url
);
681 observer
->WaitForFinished();
682 std::vector
<DownloadItem
*> downloads
;
683 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
684 EXPECT_EQ(1u, downloads
.size());
685 if (1u != downloads
.size())
691 void WaitForData(DownloadItem
* download
, int size
) {
692 DownloadUpdatedObserver
data_observer(
693 download
, base::Bind(&DataReceivedFilter
, size
));
694 data_observer
.WaitForEvent();
695 ASSERT_EQ(size
, download
->GetReceivedBytes());
696 ASSERT_EQ(DownloadItem::IN_PROGRESS
, download
->GetState());
699 // Tell the test server to release a pending RST and confirm
700 // that the interrupt is received properly (for download resumption
702 void ReleaseRSTAndConfirmInterruptForResume(DownloadItem
* download
) {
703 scoped_ptr
<DownloadTestObserver
> rst_observer(
704 CreateInterruptedWaiter(shell(), 1));
705 NavigateToURL(shell(), test_server()->GetURL("download-finish"));
706 rst_observer
->WaitForFinished();
707 EXPECT_EQ(DownloadItem::INTERRUPTED
, download
->GetState());
710 // Confirm file status expected for the given location in a stream
711 // provided by the resume test server.
712 void ConfirmFileStatusForResume(
713 DownloadItem
* download
, bool file_exists
,
714 int received_bytes
, int total_bytes
,
715 const base::FilePath
& expected_filename
) {
716 // expected_filename is only known if the file exists.
717 ASSERT_EQ(file_exists
, !expected_filename
.empty());
718 EXPECT_EQ(received_bytes
, download
->GetReceivedBytes());
719 EXPECT_EQ(total_bytes
, download
->GetTotalBytes());
720 EXPECT_EQ(expected_filename
.value(),
721 download
->GetFullPath().BaseName().value());
722 EXPECT_EQ(file_exists
,
723 (!download
->GetFullPath().empty() &&
724 base::PathExists(download
->GetFullPath())));
727 std::string file_contents
;
728 EXPECT_TRUE(base::ReadFileToString(
729 download
->GetFullPath(), &file_contents
));
731 ASSERT_EQ(static_cast<size_t>(received_bytes
), file_contents
.size());
732 for (int i
= 0; i
< received_bytes
; ++i
) {
733 EXPECT_EQ(static_cast<char>((i
* 2 + 15) % 256), file_contents
[i
])
734 << "File contents diverged at position " << i
735 << " for " << expected_filename
.value();
737 if (static_cast<char>((i
* 2 + 15) % 256) != file_contents
[i
])
744 static void EnsureNoPendingDownloadJobsOnIO(bool* result
) {
745 if (URLRequestSlowDownloadJob::NumberOutstandingRequests())
747 BrowserThread::PostTask(
748 BrowserThread::UI
, FROM_HERE
, base::MessageLoop::QuitClosure());
751 // Location of the downloads directory for these tests
752 base::ScopedTempDir downloads_directory_
;
753 scoped_ptr
<TestShellDownloadManagerDelegate
> test_delegate_
;
756 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, DownloadCancelled
) {
757 SetupEnsureNoPendingDownloads();
759 // Create a download, wait until it's started, and confirm
760 // we're in the expected state.
761 scoped_ptr
<DownloadCreateObserver
> observer(
762 CreateInProgressWaiter(shell(), 1));
763 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl
));
764 observer
->WaitForFinished();
766 std::vector
<DownloadItem
*> downloads
;
767 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
768 ASSERT_EQ(1u, downloads
.size());
769 ASSERT_EQ(DownloadItem::IN_PROGRESS
, downloads
[0]->GetState());
771 // Cancel the download and wait for download system quiesce.
772 downloads
[0]->Cancel(true);
773 scoped_refptr
<DownloadTestFlushObserver
> flush_observer(
774 new DownloadTestFlushObserver(DownloadManagerForShell(shell())));
775 flush_observer
->WaitForFlush();
777 // Get the important info from other threads and check it.
778 EXPECT_TRUE(EnsureNoPendingDownloads());
781 // Check that downloading multiple (in this case, 2) files does not result in
783 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, MultiDownload
) {
784 SetupEnsureNoPendingDownloads();
786 // Create a download, wait until it's started, and confirm
787 // we're in the expected state.
788 scoped_ptr
<DownloadCreateObserver
> observer1(
789 CreateInProgressWaiter(shell(), 1));
790 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl
));
791 observer1
->WaitForFinished();
793 std::vector
<DownloadItem
*> downloads
;
794 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
795 ASSERT_EQ(1u, downloads
.size());
796 ASSERT_EQ(DownloadItem::IN_PROGRESS
, downloads
[0]->GetState());
797 DownloadItem
* download1
= downloads
[0]; // The only download.
799 // Start the second download and wait until it's done.
800 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
801 GURL
url(URLRequestMockHTTPJob::GetMockUrl(file
));
802 // Download the file and wait.
803 NavigateToURLAndWaitForDownload(shell(), url
, DownloadItem::COMPLETE
);
805 // Should now have 2 items on the manager.
807 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
808 ASSERT_EQ(2u, downloads
.size());
809 // We don't know the order of the downloads.
810 DownloadItem
* download2
= downloads
[(download1
== downloads
[0]) ? 1 : 0];
812 ASSERT_EQ(DownloadItem::IN_PROGRESS
, download1
->GetState());
813 ASSERT_EQ(DownloadItem::COMPLETE
, download2
->GetState());
815 // Allow the first request to finish.
816 scoped_ptr
<DownloadTestObserver
> observer2(CreateWaiter(shell(), 1));
817 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kFinishDownloadUrl
));
818 observer2
->WaitForFinished(); // Wait for the third request.
819 EXPECT_EQ(1u, observer2
->NumDownloadsSeenInState(DownloadItem::COMPLETE
));
821 // Get the important info from other threads and check it.
822 EXPECT_TRUE(EnsureNoPendingDownloads());
824 // The |DownloadItem|s should now be done and have the final file names.
825 // Verify that the files have the expected data and size.
826 // |file1| should be full of '*'s, and |file2| should be the same as the
828 base::FilePath
file1(download1
->GetTargetFilePath());
829 size_t file_size1
= URLRequestSlowDownloadJob::kFirstDownloadSize
+
830 URLRequestSlowDownloadJob::kSecondDownloadSize
;
831 std::string
expected_contents(file_size1
, '*');
832 ASSERT_TRUE(VerifyFile(file1
, expected_contents
, file_size1
));
834 base::FilePath
file2(download2
->GetTargetFilePath());
835 ASSERT_TRUE(base::ContentsEqual(
836 file2
, GetTestFilePath("download", "download-test.lib")));
839 #if defined(ENABLE_PLUGINS)
840 // Content served with a MIME type of application/octet-stream should be
841 // downloaded even when a plugin can be found that handles the file type.
842 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, DownloadOctetStream
) {
843 const base::FilePath::CharType kTestFilePath
[] =
844 FILE_PATH_LITERAL("octet-stream.abc");
845 const char kTestPluginName
[] = "TestPlugin";
846 const char kTestMimeType
[] = "application/x-test-mime-type";
847 const char kTestFileType
[] = "abc";
849 WebPluginInfo plugin_info
;
850 plugin_info
.name
= base::ASCIIToUTF16(kTestPluginName
);
851 plugin_info
.mime_types
.push_back(
852 WebPluginMimeType(kTestMimeType
, kTestFileType
, ""));
853 PluginServiceImpl::GetInstance()->RegisterInternalPlugin(plugin_info
, false);
855 // The following is served with a Content-Type of application/octet-stream.
856 GURL
url(URLRequestMockHTTPJob::GetMockUrl(base::FilePath(kTestFilePath
)));
857 NavigateToURLAndWaitForDownload(shell(), url
, DownloadItem::COMPLETE
);
861 // Try to cancel just before we release the download file, by delaying final
863 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, CancelAtFinalRename
) {
864 // Setup new factory.
865 DownloadFileWithDelayFactory
* file_factory
=
866 new DownloadFileWithDelayFactory();
867 DownloadManagerImpl
* download_manager(DownloadManagerForShell(shell()));
868 download_manager
->SetDownloadFileFactoryForTesting(
869 scoped_ptr
<DownloadFileFactory
>(file_factory
).Pass());
872 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
873 NavigateToURL(shell(), URLRequestMockHTTPJob::GetMockUrl(file
));
875 // Wait until the first (intermediate file) rename and execute the callback.
876 file_factory
->WaitForSomeCallback();
877 std::vector
<base::Closure
> callbacks
;
878 file_factory
->GetAllRenameCallbacks(&callbacks
);
879 ASSERT_EQ(1u, callbacks
.size());
883 // Wait until the second (final) rename callback is posted.
884 file_factory
->WaitForSomeCallback();
885 file_factory
->GetAllRenameCallbacks(&callbacks
);
886 ASSERT_EQ(1u, callbacks
.size());
889 std::vector
<DownloadItem
*> items
;
890 download_manager
->GetAllDownloads(&items
);
891 ASSERT_EQ(1u, items
.size());
892 items
[0]->Cancel(true);
893 RunAllPendingInMessageLoop();
896 EXPECT_EQ(DownloadItem::CANCELLED
, items
[0]->GetState());
898 // Run final rename callback.
903 EXPECT_EQ(DownloadItem::CANCELLED
, items
[0]->GetState());
906 // Try to cancel just after we release the download file, by delaying
907 // in ShouldOpenDownload.
908 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, CancelAtRelease
) {
909 DownloadManagerImpl
* download_manager(DownloadManagerForShell(shell()));
911 // Mark delegate for delayed open.
912 GetDownloadManagerDelegate()->SetDelayedOpen(true);
914 // Setup new factory.
915 DownloadFileWithDelayFactory
* file_factory
=
916 new DownloadFileWithDelayFactory();
917 download_manager
->SetDownloadFileFactoryForTesting(
918 scoped_ptr
<DownloadFileFactory
>(file_factory
).Pass());
921 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
922 NavigateToURL(shell(), URLRequestMockHTTPJob::GetMockUrl(file
));
924 // Wait until the first (intermediate file) rename and execute the callback.
925 file_factory
->WaitForSomeCallback();
926 std::vector
<base::Closure
> callbacks
;
927 file_factory
->GetAllRenameCallbacks(&callbacks
);
928 ASSERT_EQ(1u, callbacks
.size());
932 // Wait until the second (final) rename callback is posted.
933 file_factory
->WaitForSomeCallback();
934 file_factory
->GetAllRenameCallbacks(&callbacks
);
935 ASSERT_EQ(1u, callbacks
.size());
941 // Confirm download still IN_PROGRESS (internal state COMPLETING).
942 std::vector
<DownloadItem
*> items
;
943 download_manager
->GetAllDownloads(&items
);
944 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
946 // Cancel the download; confirm cancel fails.
947 ASSERT_EQ(1u, items
.size());
948 items
[0]->Cancel(true);
949 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
951 // Need to complete open test.
952 std::vector
<DownloadOpenDelayedCallback
> delayed_callbacks
;
953 GetDownloadManagerDelegate()->GetDelayedCallbacks(
955 ASSERT_EQ(1u, delayed_callbacks
.size());
956 delayed_callbacks
[0].Run(true);
958 // *Now* the download should be complete.
959 EXPECT_EQ(DownloadItem::COMPLETE
, items
[0]->GetState());
962 // Try to shutdown with a download in progress to make sure shutdown path
964 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ShutdownInProgress
) {
965 // Create a download that won't complete.
966 scoped_ptr
<DownloadCreateObserver
> observer(
967 CreateInProgressWaiter(shell(), 1));
968 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl
));
969 observer
->WaitForFinished();
972 std::vector
<DownloadItem
*> items
;
973 DownloadManagerForShell(shell())->GetAllDownloads(&items
);
974 ASSERT_EQ(1u, items
.size());
975 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
977 // Shutdown the download manager and make sure we get the right
978 // notifications in the right order.
979 StrictMock
<MockDownloadItemObserver
> item_observer
;
980 items
[0]->AddObserver(&item_observer
);
981 MockDownloadManagerObserver
manager_observer(
982 DownloadManagerForShell(shell()));
983 // Don't care about ModelChanged() events.
984 EXPECT_CALL(manager_observer
, ModelChanged(_
))
985 .WillRepeatedly(Return());
987 InSequence notifications
;
989 EXPECT_CALL(manager_observer
, MockManagerGoingDown(
990 DownloadManagerForShell(shell())))
992 EXPECT_CALL(item_observer
, OnDownloadUpdated(
994 Property(&DownloadItem::GetState
, DownloadItem::CANCELLED
))))
996 EXPECT_CALL(item_observer
, OnDownloadDestroyed(items
[0]))
1000 // See http://crbug.com/324525. If we have a refcount release/post task
1001 // race, the second post will stall the IO thread long enough so that we'll
1002 // lose the race and crash. The first stall is just to give the UI thread
1003 // a chance to get the second stall onto the IO thread queue after the cancel
1004 // message created by Shutdown and before the notification callback
1005 // created by the IO thread in canceling the request.
1006 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
1007 base::Bind(&base::PlatformThread::Sleep
,
1008 base::TimeDelta::FromMilliseconds(25)));
1009 DownloadManagerForShell(shell())->Shutdown();
1010 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
1011 base::Bind(&base::PlatformThread::Sleep
,
1012 base::TimeDelta::FromMilliseconds(25)));
1016 // Try to shutdown just after we release the download file, by delaying
1018 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ShutdownAtRelease
) {
1019 DownloadManagerImpl
* download_manager(DownloadManagerForShell(shell()));
1021 // Mark delegate for delayed open.
1022 GetDownloadManagerDelegate()->SetDelayedOpen(true);
1024 // Setup new factory.
1025 DownloadFileWithDelayFactory
* file_factory
=
1026 new DownloadFileWithDelayFactory();
1027 download_manager
->SetDownloadFileFactoryForTesting(
1028 scoped_ptr
<DownloadFileFactory
>(file_factory
).Pass());
1030 // Create a download
1031 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
1032 NavigateToURL(shell(), URLRequestMockHTTPJob::GetMockUrl(file
));
1034 // Wait until the first (intermediate file) rename and execute the callback.
1035 file_factory
->WaitForSomeCallback();
1036 std::vector
<base::Closure
> callbacks
;
1037 file_factory
->GetAllRenameCallbacks(&callbacks
);
1038 ASSERT_EQ(1u, callbacks
.size());
1042 // Wait until the second (final) rename callback is posted.
1043 file_factory
->WaitForSomeCallback();
1044 file_factory
->GetAllRenameCallbacks(&callbacks
);
1045 ASSERT_EQ(1u, callbacks
.size());
1051 // Confirm download isn't complete yet.
1052 std::vector
<DownloadItem
*> items
;
1053 DownloadManagerForShell(shell())->GetAllDownloads(&items
);
1054 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
1056 // Cancel the download; confirm cancel fails anyway.
1057 ASSERT_EQ(1u, items
.size());
1058 items
[0]->Cancel(true);
1059 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
1060 RunAllPendingInMessageLoop();
1061 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
1063 MockDownloadItemObserver observer
;
1064 items
[0]->AddObserver(&observer
);
1065 EXPECT_CALL(observer
, OnDownloadDestroyed(items
[0]));
1067 // Shutdown the download manager. Mostly this is confirming a lack of
1069 DownloadManagerForShell(shell())->Shutdown();
1072 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ResumeInterruptedDownload
) {
1073 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1074 switches::kEnableDownloadResumption
);
1075 ASSERT_TRUE(test_server()->Start());
1077 GURL url
= test_server()->GetURL(
1078 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1079 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1081 MockDownloadManagerObserver
dm_observer(DownloadManagerForShell(shell()));
1082 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(1);
1084 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1085 WaitForData(download
, GetSafeBufferChunk());
1086 ::testing::Mock::VerifyAndClearExpectations(&dm_observer
);
1088 // Confirm resumption while in progress doesn't do anything.
1090 ASSERT_EQ(GetSafeBufferChunk(), download
->GetReceivedBytes());
1091 ASSERT_EQ(DownloadItem::IN_PROGRESS
, download
->GetState());
1093 // Tell the server to send the RST and confirm the interrupt happens.
1094 ReleaseRSTAndConfirmInterruptForResume(download
);
1095 ConfirmFileStatusForResume(
1096 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1097 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1099 // Resume, confirming received bytes on resumption is correct.
1100 // Make sure no creation calls are included.
1101 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(0);
1102 int initial_size
= 0;
1103 DownloadUpdatedObserver
initial_size_observer(
1104 download
, base::Bind(&InitialSizeFilter
, &initial_size
));
1106 initial_size_observer
.WaitForEvent();
1107 EXPECT_EQ(GetSafeBufferChunk(), initial_size
);
1108 ::testing::Mock::VerifyAndClearExpectations(&dm_observer
);
1110 // and wait for expected data.
1111 WaitForData(download
, GetSafeBufferChunk() * 2);
1113 // Tell the server to send the RST and confirm the interrupt happens.
1114 ReleaseRSTAndConfirmInterruptForResume(download
);
1115 ConfirmFileStatusForResume(
1116 download
, true, GetSafeBufferChunk() * 2, GetSafeBufferChunk() * 3,
1117 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1119 // Resume and wait for completion.
1120 DownloadUpdatedObserver
completion_observer(
1121 download
, base::Bind(DownloadCompleteFilter
));
1123 completion_observer
.WaitForEvent();
1125 ConfirmFileStatusForResume(
1126 download
, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1127 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1129 // Confirm resumption while complete doesn't do anything.
1131 ASSERT_EQ(GetSafeBufferChunk() * 3, download
->GetReceivedBytes());
1132 ASSERT_EQ(DownloadItem::COMPLETE
, download
->GetState());
1133 RunAllPendingInMessageLoop();
1134 ASSERT_EQ(GetSafeBufferChunk() * 3, download
->GetReceivedBytes());
1135 ASSERT_EQ(DownloadItem::COMPLETE
, download
->GetState());
1138 // Confirm restart fallback happens if a range request is bounced.
1139 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ResumeInterruptedDownloadNoRange
) {
1140 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1141 switches::kEnableDownloadResumption
);
1142 ASSERT_TRUE(test_server()->Start());
1144 // Auto-restart if server doesn't handle ranges.
1145 GURL url
= test_server()->GetURL(
1147 // First download hits an RST, rest don't, no ranges.
1148 "rangereset?size=%d&rst_boundary=%d&"
1149 "token=NoRange&rst_limit=1&bounce_range",
1150 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1152 // Start the download and wait for first data chunk.
1153 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1154 WaitForData(download
, GetSafeBufferChunk());
1156 RecordingDownloadObserver
recorder(download
);
1158 ReleaseRSTAndConfirmInterruptForResume(download
);
1159 ConfirmFileStatusForResume(
1160 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1161 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1163 DownloadUpdatedObserver
completion_observer(
1164 download
, base::Bind(DownloadCompleteFilter
));
1166 completion_observer
.WaitForEvent();
1168 ConfirmFileStatusForResume(
1169 download
, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1170 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1172 static const RecordingDownloadObserver::RecordStruct expected_record
[] = {
1174 {DownloadItem::INTERRUPTED
, GetSafeBufferChunk()},
1175 // Starting continuation
1176 {DownloadItem::IN_PROGRESS
, GetSafeBufferChunk()},
1177 // Notification of receiving whole file.
1178 {DownloadItem::IN_PROGRESS
, 0},
1180 {DownloadItem::COMPLETE
, GetSafeBufferChunk() * 3},
1183 recorder
.CompareToExpectedRecord(expected_record
, arraysize(expected_record
));
1186 // Confirm restart fallback happens if a precondition is failed.
1187 IN_PROC_BROWSER_TEST_F(DownloadContentTest
,
1188 ResumeInterruptedDownloadBadPrecondition
) {
1189 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1190 switches::kEnableDownloadResumption
);
1191 ASSERT_TRUE(test_server()->Start());
1193 GURL url
= test_server()->GetURL(base::StringPrintf(
1194 // First download hits an RST, rest don't, precondition fail.
1195 "rangereset?size=%d&rst_boundary=%d&"
1196 "token=BadPrecondition&rst_limit=1&fail_precondition=2",
1197 GetSafeBufferChunk() * 3,
1198 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
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1209 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1210 EXPECT_EQ("BadPrecondition2", download
->GetETag());
1212 DownloadUpdatedObserver
completion_observer(
1213 download
, base::Bind(DownloadCompleteFilter
));
1215 completion_observer
.WaitForEvent();
1217 ConfirmFileStatusForResume(
1218 download
, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1219 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1220 EXPECT_EQ("BadPrecondition0", download
->GetETag());
1222 static const RecordingDownloadObserver::RecordStruct expected_record
[] = {
1224 {DownloadItem::INTERRUPTED
, GetSafeBufferChunk()},
1225 // Starting continuation
1226 {DownloadItem::IN_PROGRESS
, GetSafeBufferChunk()},
1227 // Server precondition fail.
1228 {DownloadItem::INTERRUPTED
, 0},
1229 // Notification of successful restart.
1230 {DownloadItem::IN_PROGRESS
, 0},
1232 {DownloadItem::COMPLETE
, GetSafeBufferChunk() * 3},
1235 recorder
.CompareToExpectedRecord(expected_record
, arraysize(expected_record
));
1238 // Confirm we don't try to resume if we don't have a verifier.
1239 IN_PROC_BROWSER_TEST_F(DownloadContentTest
,
1240 ResumeInterruptedDownloadNoVerifiers
) {
1241 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1242 switches::kEnableDownloadResumption
);
1243 ASSERT_TRUE(test_server()->Start());
1245 GURL url
= test_server()->GetURL(
1247 // First download hits an RST, rest don't, no verifiers.
1248 "rangereset?size=%d&rst_boundary=%d&"
1249 "token=NoRange&rst_limit=1&no_verifiers",
1250 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1252 // Start the download and wait for first data chunk.
1253 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1254 WaitForData(download
, GetSafeBufferChunk());
1256 RecordingDownloadObserver
recorder(download
);
1258 ReleaseRSTAndConfirmInterruptForResume(download
);
1259 ConfirmFileStatusForResume(
1260 download
, false, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1263 DownloadUpdatedObserver
completion_observer(
1264 download
, base::Bind(DownloadCompleteFilter
));
1266 completion_observer
.WaitForEvent();
1268 ConfirmFileStatusForResume(
1269 download
, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1270 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1272 static const RecordingDownloadObserver::RecordStruct expected_record
[] = {
1274 {DownloadItem::INTERRUPTED
, GetSafeBufferChunk()},
1275 // Restart for lack of verifiers
1276 {DownloadItem::IN_PROGRESS
, 0},
1278 {DownloadItem::COMPLETE
, GetSafeBufferChunk() * 3},
1281 recorder
.CompareToExpectedRecord(expected_record
, arraysize(expected_record
));
1284 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ResumeWithDeletedFile
) {
1285 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1286 switches::kEnableDownloadResumption
);
1287 ASSERT_TRUE(test_server()->Start());
1289 GURL url
= test_server()->GetURL(
1291 // First download hits an RST, rest don't
1292 "rangereset?size=%d&rst_boundary=%d&"
1293 "token=NoRange&rst_limit=1",
1294 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1296 // Start the download and wait for first data chunk.
1297 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1298 WaitForData(download
, GetSafeBufferChunk());
1300 RecordingDownloadObserver
recorder(download
);
1302 ReleaseRSTAndConfirmInterruptForResume(download
);
1303 ConfirmFileStatusForResume(
1304 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1305 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1307 // Delete the intermediate file.
1308 base::DeleteFile(download
->GetFullPath(), false);
1310 DownloadUpdatedObserver
completion_observer(
1311 download
, base::Bind(DownloadCompleteFilter
));
1313 completion_observer
.WaitForEvent();
1315 ConfirmFileStatusForResume(
1316 download
, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1317 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1319 static const RecordingDownloadObserver::RecordStruct expected_record
[] = {
1321 {DownloadItem::INTERRUPTED
, GetSafeBufferChunk()},
1322 // Starting continuation
1323 {DownloadItem::IN_PROGRESS
, GetSafeBufferChunk()},
1324 // Error because file isn't there.
1325 {DownloadItem::INTERRUPTED
, 0},
1327 {DownloadItem::IN_PROGRESS
, 0},
1329 {DownloadItem::COMPLETE
, GetSafeBufferChunk() * 3},
1332 recorder
.CompareToExpectedRecord(expected_record
, arraysize(expected_record
));
1335 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ResumeWithFileInitError
) {
1336 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1337 switches::kEnableDownloadResumption
);
1338 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
1339 GURL
url(URLRequestMockHTTPJob::GetMockUrl(file
));
1341 // Setup the error injector.
1342 scoped_refptr
<TestFileErrorInjector
> injector(
1343 TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
1345 TestFileErrorInjector::FileErrorInfo err
= {
1347 TestFileErrorInjector::FILE_OPERATION_INITIALIZE
,
1349 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
1351 injector
->AddError(err
);
1352 injector
->InjectErrors();
1354 // Start and watch for interrupt.
1355 scoped_ptr
<DownloadTestObserver
> int_observer(
1356 CreateInterruptedWaiter(shell(), 1));
1357 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1358 int_observer
->WaitForFinished();
1359 ASSERT_EQ(DownloadItem::INTERRUPTED
, download
->GetState());
1360 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
,
1361 download
->GetLastReason());
1362 EXPECT_EQ(0, download
->GetReceivedBytes());
1363 EXPECT_TRUE(download
->GetFullPath().empty());
1364 EXPECT_TRUE(download
->GetTargetFilePath().empty());
1366 // We need to make sure that any cross-thread downloads communication has
1367 // quiesced before clearing and injecting the new errors, as the
1368 // InjectErrors() routine alters the currently in use download file
1369 // factory, which is a file thread object.
1370 RunAllPendingInMessageLoop(BrowserThread::FILE);
1371 RunAllPendingInMessageLoop();
1373 // Clear the old errors list.
1374 injector
->ClearErrors();
1375 injector
->InjectErrors();
1377 // Resume and watch completion.
1378 DownloadUpdatedObserver
completion_observer(
1379 download
, base::Bind(DownloadCompleteFilter
));
1381 completion_observer
.WaitForEvent();
1382 EXPECT_EQ(download
->GetState(), DownloadItem::COMPLETE
);
1385 IN_PROC_BROWSER_TEST_F(DownloadContentTest
,
1386 ResumeWithFileIntermediateRenameError
) {
1387 base::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 TestFileErrorInjector::FileErrorInfo err
= {
1398 TestFileErrorInjector::FILE_OPERATION_RENAME_UNIQUIFY
,
1400 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
1402 injector
->AddError(err
);
1403 injector
->InjectErrors();
1405 // Start and watch for interrupt.
1406 scoped_ptr
<DownloadTestObserver
> int_observer(
1407 CreateInterruptedWaiter(shell(), 1));
1408 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1409 int_observer
->WaitForFinished();
1410 ASSERT_EQ(DownloadItem::INTERRUPTED
, download
->GetState());
1411 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
,
1412 download
->GetLastReason());
1413 EXPECT_TRUE(download
->GetFullPath().empty());
1414 // Target path will have been set after file name determination. GetFullPath()
1415 // being empty is sufficient to signal that filename determination needs to be
1417 EXPECT_FALSE(download
->GetTargetFilePath().empty());
1419 // We need to make sure that any cross-thread downloads communication has
1420 // quiesced before clearing and injecting the new errors, as the
1421 // InjectErrors() routine alters the currently in use download file
1422 // factory, which is a file thread object.
1423 RunAllPendingInMessageLoop(BrowserThread::FILE);
1424 RunAllPendingInMessageLoop();
1426 // Clear the old errors list.
1427 injector
->ClearErrors();
1428 injector
->InjectErrors();
1430 // Resume and watch completion.
1431 DownloadUpdatedObserver
completion_observer(
1432 download
, base::Bind(DownloadCompleteFilter
));
1434 completion_observer
.WaitForEvent();
1435 EXPECT_EQ(download
->GetState(), DownloadItem::COMPLETE
);
1438 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ResumeWithFileFinalRenameError
) {
1439 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1440 switches::kEnableDownloadResumption
);
1441 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
1442 GURL
url(URLRequestMockHTTPJob::GetMockUrl(file
));
1444 // Setup the error injector.
1445 scoped_refptr
<TestFileErrorInjector
> injector(
1446 TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
1448 DownloadManagerForShell(shell())->RemoveAllDownloads();
1449 TestFileErrorInjector::FileErrorInfo err
= {
1451 TestFileErrorInjector::FILE_OPERATION_RENAME_ANNOTATE
,
1453 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
1455 injector
->AddError(err
);
1456 injector
->InjectErrors();
1458 // Start and watch for interrupt.
1459 scoped_ptr
<DownloadTestObserver
> int_observer(
1460 CreateInterruptedWaiter(shell(), 1));
1461 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1462 int_observer
->WaitForFinished();
1463 ASSERT_EQ(DownloadItem::INTERRUPTED
, download
->GetState());
1464 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
,
1465 download
->GetLastReason());
1466 EXPECT_TRUE(download
->GetFullPath().empty());
1467 // Target path should still be intact.
1468 EXPECT_FALSE(download
->GetTargetFilePath().empty());
1470 // We need to make sure that any cross-thread downloads communication has
1471 // quiesced before clearing and injecting the new errors, as the
1472 // InjectErrors() routine alters the currently in use download file
1473 // factory, which is a file thread object.
1474 RunAllPendingInMessageLoop(BrowserThread::FILE);
1475 RunAllPendingInMessageLoop();
1477 // Clear the old errors list.
1478 injector
->ClearErrors();
1479 injector
->InjectErrors();
1481 // Resume and watch completion.
1482 DownloadUpdatedObserver
completion_observer(
1483 download
, base::Bind(DownloadCompleteFilter
));
1485 completion_observer
.WaitForEvent();
1486 EXPECT_EQ(download
->GetState(), DownloadItem::COMPLETE
);
1489 // An interrupted download should remove the intermediate file when it is
1491 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, CancelInterruptedDownload
) {
1492 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1493 switches::kEnableDownloadResumption
);
1494 ASSERT_TRUE(test_server()->Start());
1496 GURL url1
= test_server()->GetURL(
1497 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1498 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1500 DownloadItem
* download(StartDownloadAndReturnItem(url1
));
1501 WaitForData(download
, GetSafeBufferChunk());
1503 ReleaseRSTAndConfirmInterruptForResume(download
);
1504 ConfirmFileStatusForResume(
1505 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1506 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1508 base::FilePath
intermediate_path(download
->GetFullPath());
1509 ASSERT_FALSE(intermediate_path
.empty());
1510 EXPECT_TRUE(base::PathExists(intermediate_path
));
1512 download
->Cancel(true /* user_cancel */);
1513 RunAllPendingInMessageLoop(BrowserThread::FILE);
1514 RunAllPendingInMessageLoop();
1516 // The intermediate file should now be gone.
1517 EXPECT_FALSE(base::PathExists(intermediate_path
));
1518 EXPECT_TRUE(download
->GetFullPath().empty());
1521 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, RemoveDownload
) {
1522 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1523 switches::kEnableDownloadResumption
);
1524 ASSERT_TRUE(test_server()->Start());
1526 // An interrupted download should remove the intermediate file when it is
1529 GURL url1
= test_server()->GetURL(
1530 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1531 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1533 DownloadItem
* download(StartDownloadAndReturnItem(url1
));
1534 WaitForData(download
, GetSafeBufferChunk());
1535 ReleaseRSTAndConfirmInterruptForResume(download
);
1536 ConfirmFileStatusForResume(
1537 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1538 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1540 base::FilePath
intermediate_path(download
->GetFullPath());
1541 ASSERT_FALSE(intermediate_path
.empty());
1542 EXPECT_TRUE(base::PathExists(intermediate_path
));
1545 RunAllPendingInMessageLoop(BrowserThread::FILE);
1546 RunAllPendingInMessageLoop();
1548 // The intermediate file should now be gone.
1549 EXPECT_FALSE(base::PathExists(intermediate_path
));
1552 // A completed download shouldn't delete the downloaded file when it is
1555 // Start the second download and wait until it's done.
1556 base::FilePath
file2(FILE_PATH_LITERAL("download-test.lib"));
1557 GURL
url2(URLRequestMockHTTPJob::GetMockUrl(file2
));
1558 scoped_ptr
<DownloadTestObserver
> completion_observer(
1559 CreateWaiter(shell(), 1));
1560 DownloadItem
* download(StartDownloadAndReturnItem(url2
));
1561 completion_observer
->WaitForFinished();
1563 // The target path should exist.
1564 base::FilePath
target_path(download
->GetTargetFilePath());
1565 EXPECT_TRUE(base::PathExists(target_path
));
1567 RunAllPendingInMessageLoop(BrowserThread::FILE);
1568 RunAllPendingInMessageLoop();
1570 // The file should still exist.
1571 EXPECT_TRUE(base::PathExists(target_path
));
1575 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, RemoveResumingDownload
) {
1576 SetupEnsureNoPendingDownloads();
1577 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1578 switches::kEnableDownloadResumption
);
1579 ASSERT_TRUE(test_server()->Start());
1581 GURL url
= test_server()->GetURL(
1582 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1583 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1585 MockDownloadManagerObserver
dm_observer(DownloadManagerForShell(shell()));
1586 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(1);
1588 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1589 WaitForData(download
, GetSafeBufferChunk());
1590 ::testing::Mock::VerifyAndClearExpectations(&dm_observer
);
1592 // Tell the server to send the RST and confirm the interrupt happens.
1593 ReleaseRSTAndConfirmInterruptForResume(download
);
1594 ConfirmFileStatusForResume(
1595 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1596 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1598 base::FilePath
intermediate_path(download
->GetFullPath());
1599 ASSERT_FALSE(intermediate_path
.empty());
1600 EXPECT_TRUE(base::PathExists(intermediate_path
));
1602 // Resume and remove download. We expect only a single OnDownloadCreated()
1603 // call, and that's for the second download created below.
1604 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(1);
1608 // The intermediate file should now be gone.
1609 RunAllPendingInMessageLoop(BrowserThread::FILE);
1610 RunAllPendingInMessageLoop();
1611 EXPECT_FALSE(base::PathExists(intermediate_path
));
1613 // Start the second download and wait until it's done. The test server is
1614 // single threaded. The response to this download request should follow the
1615 // response to the previous resumption request.
1616 GURL
url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x"));
1617 NavigateToURLAndWaitForDownload(shell(), url2
, DownloadItem::COMPLETE
);
1619 EXPECT_TRUE(EnsureNoPendingDownloads());
1622 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, CancelResumingDownload
) {
1623 SetupEnsureNoPendingDownloads();
1624 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1625 switches::kEnableDownloadResumption
);
1626 ASSERT_TRUE(test_server()->Start());
1628 GURL url
= test_server()->GetURL(
1629 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1630 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1632 MockDownloadManagerObserver
dm_observer(DownloadManagerForShell(shell()));
1633 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(1);
1635 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1636 WaitForData(download
, GetSafeBufferChunk());
1637 ::testing::Mock::VerifyAndClearExpectations(&dm_observer
);
1639 // Tell the server to send the RST and confirm the interrupt happens.
1640 ReleaseRSTAndConfirmInterruptForResume(download
);
1641 ConfirmFileStatusForResume(
1642 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1643 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1645 base::FilePath
intermediate_path(download
->GetFullPath());
1646 ASSERT_FALSE(intermediate_path
.empty());
1647 EXPECT_TRUE(base::PathExists(intermediate_path
));
1649 // Resume and cancel download. We expect only a single OnDownloadCreated()
1650 // call, and that's for the second download created below.
1651 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(1);
1653 download
->Cancel(true);
1655 // The intermediate file should now be gone.
1656 RunAllPendingInMessageLoop(BrowserThread::FILE);
1657 RunAllPendingInMessageLoop();
1658 EXPECT_FALSE(base::PathExists(intermediate_path
));
1659 EXPECT_TRUE(download
->GetFullPath().empty());
1661 // Start the second download and wait until it's done. The test server is
1662 // single threaded. The response to this download request should follow the
1663 // response to the previous resumption request.
1664 GURL
url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x"));
1665 NavigateToURLAndWaitForDownload(shell(), url2
, DownloadItem::COMPLETE
);
1667 EXPECT_TRUE(EnsureNoPendingDownloads());
1670 // Check that the cookie policy is correctly updated when downloading a file
1671 // that redirects cross origin.
1672 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, CookiePolicy
) {
1673 ASSERT_TRUE(test_server()->Start());
1674 net::HostPortPair host_port
= test_server()->host_port_pair();
1675 DCHECK_EQ(host_port
.host(), std::string("127.0.0.1"));
1677 // Block third-party cookies.
1678 ShellNetworkDelegate::SetAcceptAllCookies(false);
1680 // |url| redirects to a different origin |download| which tries to set a
1682 std::string
download(base::StringPrintf(
1683 "http://localhost:%d/set-cookie?A=B", host_port
.port()));
1684 GURL
url(test_server()->GetURL("server-redirect?" + download
));
1686 // Download the file.
1687 SetupEnsureNoPendingDownloads();
1688 scoped_ptr
<DownloadUrlParameters
> dl_params(
1689 DownloadUrlParameters::FromWebContents(shell()->web_contents(), url
));
1690 scoped_ptr
<DownloadTestObserver
> observer(CreateWaiter(shell(), 1));
1691 DownloadManagerForShell(shell())->DownloadUrl(dl_params
.Pass());
1692 observer
->WaitForFinished();
1694 // Get the important info from other threads and check it.
1695 EXPECT_TRUE(EnsureNoPendingDownloads());
1697 std::vector
<DownloadItem
*> downloads
;
1698 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
1699 ASSERT_EQ(1u, downloads
.size());
1700 ASSERT_EQ(DownloadItem::COMPLETE
, downloads
[0]->GetState());
1702 // Check that the cookies were correctly set.
1704 content::GetCookies(shell()->web_contents()->GetBrowserContext(),
1708 // A filename suggestion specified via a @download attribute should not be
1709 // effective if the final download URL is in another origin from the original
1711 IN_PROC_BROWSER_TEST_F(DownloadContentTest
,
1712 DownloadAttributeCrossOriginRedirect
) {
1713 EmbeddedTestServer origin_one
;
1714 EmbeddedTestServer origin_two
;
1715 ASSERT_TRUE(origin_one
.InitializeAndWaitUntilReady());
1716 ASSERT_TRUE(origin_two
.InitializeAndWaitUntilReady());
1718 // The download-attribute.html page contains an anchor element whose href is
1719 // set to the value of the query parameter (specified as |target| in the URL
1720 // below). The suggested filename for the anchor is 'suggested-filename'. When
1721 // the page is loaded, a script simulates a click on the anchor, triggering a
1722 // download of the target URL.
1724 // We construct two test servers; origin_one and origin_two. Once started, the
1725 // server URLs will differ by the port number. Therefore they will be in
1726 // different origins.
1727 GURL download_url
= origin_one
.GetURL("/ping");
1728 GURL referrer_url
= origin_one
.GetURL(
1729 std::string("/download-attribute.html?target=") + download_url
.spec());
1731 // <origin_one>/download-attribute.html initiates a download of
1732 // <origin_one>/ping, which redirects to <origin_two>/download.
1733 origin_one
.ServeFilesFromDirectory(GetTestFilePath("download", ""));
1734 origin_one
.RegisterRequestHandler(
1735 CreateRedirectHandler("/ping", origin_two
.GetURL("/download")));
1736 origin_two
.RegisterRequestHandler(CreateBasicResponseHandler(
1737 "/download", "application/octet-stream", "Hello"));
1739 NavigateToURLAndWaitForDownload(
1740 shell(), referrer_url
, DownloadItem::COMPLETE
);
1742 std::vector
<DownloadItem
*> downloads
;
1743 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
1744 ASSERT_EQ(1u, downloads
.size());
1746 EXPECT_EQ(FILE_PATH_LITERAL("download"),
1747 downloads
[0]->GetTargetFilePath().BaseName().value());
1748 ASSERT_TRUE(origin_one
.ShutdownAndWaitUntilComplete());
1749 ASSERT_TRUE(origin_two
.ShutdownAndWaitUntilComplete());
1752 // A filename suggestion specified via a @download attribute should be effective
1753 // if the final download URL is in the same origin as the initial download URL.
1754 // Test that this holds even if there are cross origin redirects in the middle
1755 // of the redirect chain.
1756 IN_PROC_BROWSER_TEST_F(DownloadContentTest
,
1757 DownloadAttributeSameOriginRedirect
) {
1758 EmbeddedTestServer origin_one
;
1759 EmbeddedTestServer origin_two
;
1760 ASSERT_TRUE(origin_one
.InitializeAndWaitUntilReady());
1761 ASSERT_TRUE(origin_two
.InitializeAndWaitUntilReady());
1763 // The download-attribute.html page contains an anchor element whose href is
1764 // set to the value of the query parameter (specified as |target| in the URL
1765 // below). The suggested filename for the anchor is 'suggested-filename'. When
1766 // the page is loaded, a script simulates a click on the anchor, triggering a
1767 // download of the target URL.
1769 // We construct two test servers; origin_one and origin_two. Once started, the
1770 // server URLs will differ by the port number. Therefore they will be in
1771 // different origins.
1772 GURL download_url
= origin_one
.GetURL("/ping");
1773 GURL referrer_url
= origin_one
.GetURL(
1774 std::string("/download-attribute.html?target=") + download_url
.spec());
1775 origin_one
.ServeFilesFromDirectory(GetTestFilePath("download", ""));
1777 // <origin_one>/download-attribute.html initiates a download of
1778 // <origin_one>/ping, which redirects to <origin_two>/pong, and then finally
1779 // to <origin_one>/download.
1780 origin_one
.RegisterRequestHandler(
1781 CreateRedirectHandler("/ping", origin_two
.GetURL("/pong")));
1782 origin_two
.RegisterRequestHandler(
1783 CreateRedirectHandler("/pong", origin_one
.GetURL("/download")));
1784 origin_one
.RegisterRequestHandler(CreateBasicResponseHandler(
1785 "/download", "application/octet-stream", "Hello"));
1787 NavigateToURLAndWaitForDownload(
1788 shell(), referrer_url
, DownloadItem::COMPLETE
);
1790 std::vector
<DownloadItem
*> downloads
;
1791 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
1792 ASSERT_EQ(1u, downloads
.size());
1794 EXPECT_EQ(FILE_PATH_LITERAL("suggested-filename"),
1795 downloads
[0]->GetTargetFilePath().BaseName().value());
1796 ASSERT_TRUE(origin_one
.ShutdownAndWaitUntilComplete());
1797 ASSERT_TRUE(origin_two
.ShutdownAndWaitUntilComplete());
1800 // The file empty.bin is served with a MIME type of application/octet-stream.
1801 // The content body is empty. Make sure this case is handled properly and we
1802 // don't regress on http://crbug.com/320394.
1803 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, DownloadGZipWithNoContent
) {
1804 EmbeddedTestServer test_server
;
1805 ASSERT_TRUE(test_server
.InitializeAndWaitUntilReady());
1807 GURL url
= test_server
.GetURL("/empty.bin");
1808 test_server
.ServeFilesFromDirectory(GetTestFilePath("download", ""));
1810 NavigateToURLAndWaitForDownload(shell(), url
, DownloadItem::COMPLETE
);
1811 // That's it. This should work without crashing.
1814 } // namespace content