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