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(BrowserThread::CurrentlyOn(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(BrowserThread::CurrentlyOn(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(BrowserThread::CurrentlyOn(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(
246 PowerSaveBlocker::Create(
247 PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension
,
248 "Download in progress"));
249 return new DownloadFileWithDelay(
250 save_info
.Pass(), default_download_directory
, url
, referrer_url
,
251 calculate_hash
, stream
.Pass(), bound_net_log
,
252 psb
.Pass(), observer
, weak_ptr_factory_
.GetWeakPtr());
255 void DownloadFileWithDelayFactory::AddRenameCallback(base::Closure callback
) {
256 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
257 rename_callbacks_
.push_back(callback
);
259 base::MessageLoopForUI::current()->Quit();
262 void DownloadFileWithDelayFactory::GetAllRenameCallbacks(
263 std::vector
<base::Closure
>* results
) {
264 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
265 results
->swap(rename_callbacks_
);
268 void DownloadFileWithDelayFactory::WaitForSomeCallback() {
269 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
271 if (rename_callbacks_
.empty()) {
278 class CountingDownloadFile
: public DownloadFileImpl
{
280 CountingDownloadFile(
281 scoped_ptr
<DownloadSaveInfo
> save_info
,
282 const base::FilePath
& default_downloads_directory
,
284 const GURL
& referrer_url
,
286 scoped_ptr
<ByteStreamReader
> stream
,
287 const net::BoundNetLog
& bound_net_log
,
288 scoped_ptr
<PowerSaveBlocker
> power_save_blocker
,
289 base::WeakPtr
<DownloadDestinationObserver
> observer
)
290 : DownloadFileImpl(save_info
.Pass(), default_downloads_directory
,
291 url
, referrer_url
, calculate_hash
,
292 stream
.Pass(), bound_net_log
, observer
) {}
294 ~CountingDownloadFile() override
{
295 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
299 void Initialize(const InitializeCallback
& callback
) override
{
300 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
302 return DownloadFileImpl::Initialize(callback
);
305 static void GetNumberActiveFiles(int* result
) {
306 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
307 *result
= active_files_
;
310 // Can be called on any thread, and will block (running message loop)
311 // until data is returned.
312 static int GetNumberActiveFilesFromFileThread() {
314 BrowserThread::PostTaskAndReply(
317 base::Bind(&CountingDownloadFile::GetNumberActiveFiles
, &result
),
318 base::MessageLoop::current()->QuitClosure());
319 base::MessageLoop::current()->Run();
320 DCHECK_NE(-1, result
);
325 static int active_files_
;
328 int CountingDownloadFile::active_files_
= 0;
330 class CountingDownloadFileFactory
: public DownloadFileFactory
{
332 CountingDownloadFileFactory() {}
333 ~CountingDownloadFileFactory() override
{}
335 // DownloadFileFactory interface.
336 DownloadFile
* CreateFile(
337 scoped_ptr
<DownloadSaveInfo
> save_info
,
338 const base::FilePath
& default_downloads_directory
,
340 const GURL
& referrer_url
,
342 scoped_ptr
<ByteStreamReader
> stream
,
343 const net::BoundNetLog
& bound_net_log
,
344 base::WeakPtr
<DownloadDestinationObserver
> observer
) override
{
345 scoped_ptr
<PowerSaveBlocker
> psb(
346 PowerSaveBlocker::Create(
347 PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension
,
348 "Download in progress"));
349 return new CountingDownloadFile(
350 save_info
.Pass(), default_downloads_directory
, url
, referrer_url
,
351 calculate_hash
, stream
.Pass(), bound_net_log
,
352 psb
.Pass(), observer
);
356 class TestShellDownloadManagerDelegate
: public ShellDownloadManagerDelegate
{
358 TestShellDownloadManagerDelegate()
359 : delay_download_open_(false) {}
360 ~TestShellDownloadManagerDelegate() override
{}
362 bool ShouldOpenDownload(
364 const DownloadOpenDelayedCallback
& callback
) override
{
365 if (delay_download_open_
) {
366 delayed_callbacks_
.push_back(callback
);
372 void SetDelayedOpen(bool delay
) {
373 delay_download_open_
= delay
;
376 void GetDelayedCallbacks(
377 std::vector
<DownloadOpenDelayedCallback
>* callbacks
) {
378 callbacks
->swap(delayed_callbacks_
);
381 bool delay_download_open_
;
382 std::vector
<DownloadOpenDelayedCallback
> delayed_callbacks_
;
385 // Record all state transitions and byte counts on the observed download.
386 class RecordingDownloadObserver
: DownloadItem::Observer
{
388 struct RecordStruct
{
389 DownloadItem::DownloadState state
;
393 typedef std::vector
<RecordStruct
> RecordVector
;
395 RecordingDownloadObserver(DownloadItem
* download
)
396 : download_(download
) {
397 last_state_
.state
= download
->GetState();
398 last_state_
.bytes_received
= download
->GetReceivedBytes();
399 download_
->AddObserver(this);
402 ~RecordingDownloadObserver() override
{ RemoveObserver(); }
404 void CompareToExpectedRecord(const RecordStruct expected
[], size_t size
) {
405 EXPECT_EQ(size
, record_
.size());
406 int min
= size
> record_
.size() ? record_
.size() : size
;
407 for (int i
= 0; i
< min
; ++i
) {
408 EXPECT_EQ(expected
[i
].state
, record_
[i
].state
) << "Iteration " << i
;
409 EXPECT_EQ(expected
[i
].bytes_received
, record_
[i
].bytes_received
)
410 << "Iteration " << i
;
415 void OnDownloadUpdated(DownloadItem
* download
) override
{
416 DCHECK_EQ(download_
, download
);
417 DownloadItem::DownloadState state
= download
->GetState();
418 int bytes
= download
->GetReceivedBytes();
419 if (last_state_
.state
!= state
|| last_state_
.bytes_received
> bytes
) {
420 last_state_
.state
= state
;
421 last_state_
.bytes_received
= bytes
;
422 record_
.push_back(last_state_
);
426 void OnDownloadDestroyed(DownloadItem
* download
) override
{
427 DCHECK_EQ(download_
, download
);
431 void RemoveObserver() {
433 download_
->RemoveObserver(this);
438 DownloadItem
* download_
;
439 RecordStruct last_state_
;
440 RecordVector record_
;
443 // Get the next created download.
444 class DownloadCreateObserver
: DownloadManager::Observer
{
446 DownloadCreateObserver(DownloadManager
* manager
)
450 manager_
->AddObserver(this);
453 ~DownloadCreateObserver() override
{
455 manager_
->RemoveObserver(this);
459 void ManagerGoingDown(DownloadManager
* manager
) override
{
460 DCHECK_EQ(manager_
, manager
);
461 manager_
->RemoveObserver(this);
465 void OnDownloadCreated(DownloadManager
* manager
,
466 DownloadItem
* download
) override
{
471 base::MessageLoopForUI::current()->Quit();
474 DownloadItem
* WaitForFinished() {
475 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
485 DownloadManager
* manager_
;
491 // Filter for waiting for a certain number of bytes.
492 bool DataReceivedFilter(int number_of_bytes
, DownloadItem
* download
) {
493 return download
->GetReceivedBytes() >= number_of_bytes
;
496 // Filter for download completion.
497 bool DownloadCompleteFilter(DownloadItem
* download
) {
498 return download
->GetState() == DownloadItem::COMPLETE
;
501 // Filter for saving the size of the download when the first IN_PROGRESS
503 bool InitialSizeFilter(int* download_size
, DownloadItem
* download
) {
504 if (download
->GetState() != DownloadItem::IN_PROGRESS
)
507 *download_size
= download
->GetReceivedBytes();
511 // Request handler to be used with CreateRedirectHandler().
512 scoped_ptr
<net::test_server::HttpResponse
> HandleRequestAndSendRedirectResponse(
513 const std::string
& relative_url
,
514 const GURL
& target_url
,
515 const net::test_server::HttpRequest
& request
) {
516 scoped_ptr
<net::test_server::BasicHttpResponse
> response
;
517 if (request
.relative_url
== relative_url
) {
518 response
.reset(new net::test_server::BasicHttpResponse
);
519 response
->set_code(net::HTTP_FOUND
);
520 response
->AddCustomHeader("Location", target_url
.spec());
522 return response
.Pass();
525 // Creates a request handler for EmbeddedTestServer that responds with a HTTP
526 // 302 redirect if the request URL matches |relative_url|.
527 EmbeddedTestServer::HandleRequestCallback
CreateRedirectHandler(
528 const std::string
& relative_url
,
529 const GURL
& target_url
) {
531 &HandleRequestAndSendRedirectResponse
, relative_url
, target_url
);
534 // Request handler to be used with CreateBasicResponseHandler().
535 scoped_ptr
<net::test_server::HttpResponse
> HandleRequestAndSendBasicResponse(
536 const std::string
& relative_url
,
537 const std::string
& content_type
,
538 const std::string
& body
,
539 const net::test_server::HttpRequest
& request
) {
540 scoped_ptr
<net::test_server::BasicHttpResponse
> response
;
541 if (request
.relative_url
== relative_url
) {
542 response
.reset(new net::test_server::BasicHttpResponse
);
543 response
->set_content_type(content_type
);
544 response
->set_content(body
);
546 return response
.Pass();
549 // Creates a request handler for an EmbeddedTestServer that response with an
550 // HTTP 200 status code, a Content-Type header and a body.
551 EmbeddedTestServer::HandleRequestCallback
CreateBasicResponseHandler(
552 const std::string
& relative_url
,
553 const std::string
& content_type
,
554 const std::string
& body
) {
556 &HandleRequestAndSendBasicResponse
, relative_url
, content_type
, body
);
561 class DownloadContentTest
: public ContentBrowserTest
{
563 // An initial send from a website of at least this size will not be
564 // help up by buffering in the underlying downloads ByteStream data
565 // transfer. This is important because on resumption tests we wait
566 // until we've gotten the data we expect before allowing the test server
567 // to send its reset, to get around hard close semantics on the Windows
568 // socket layer implementation.
569 int GetSafeBufferChunk() const {
570 return (DownloadResourceHandler::kDownloadByteStreamSize
/
571 ByteStreamWriter::kFractionBufferBeforeSending
) + 1;
574 void SetUpOnMainThread() override
{
575 ASSERT_TRUE(downloads_directory_
.CreateUniqueTempDir());
577 test_delegate_
.reset(new TestShellDownloadManagerDelegate());
578 test_delegate_
->SetDownloadBehaviorForTesting(downloads_directory_
.path());
579 DownloadManager
* manager
= DownloadManagerForShell(shell());
580 manager
->GetDelegate()->Shutdown();
581 manager
->SetDelegate(test_delegate_
.get());
582 test_delegate_
->SetDownloadManager(manager
);
584 BrowserThread::PostTask(
585 BrowserThread::IO
, FROM_HERE
,
586 base::Bind(&net::URLRequestSlowDownloadJob::AddUrlHandler
));
587 base::FilePath
mock_base(GetTestFilePath("download", ""));
588 BrowserThread::PostTask(
592 &net::URLRequestMockHTTPJob::AddUrlHandler
,
594 make_scoped_refptr(content::BrowserThread::GetBlockingPool())));
597 TestShellDownloadManagerDelegate
* GetDownloadManagerDelegate() {
598 return test_delegate_
.get();
601 // Create a DownloadTestObserverTerminal that will wait for the
602 // specified number of downloads to finish.
603 DownloadTestObserver
* CreateWaiter(
604 Shell
* shell
, int num_downloads
) {
605 DownloadManager
* download_manager
= DownloadManagerForShell(shell
);
606 return new DownloadTestObserverTerminal(download_manager
, num_downloads
,
607 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL
);
610 // Create a DownloadTestObserverInProgress that will wait for the
611 // specified number of downloads to start.
612 DownloadCreateObserver
* CreateInProgressWaiter(
613 Shell
* shell
, int num_downloads
) {
614 DownloadManager
* download_manager
= DownloadManagerForShell(shell
);
615 return new DownloadCreateObserver(download_manager
);
618 DownloadTestObserver
* CreateInterruptedWaiter(
619 Shell
* shell
, int num_downloads
) {
620 DownloadManager
* download_manager
= DownloadManagerForShell(shell
);
621 return new DownloadTestObserverInterrupted(download_manager
, num_downloads
,
622 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL
);
625 // Note: Cannot be used with other alternative DownloadFileFactorys
626 void SetupEnsureNoPendingDownloads() {
627 DownloadManagerForShell(shell())->SetDownloadFileFactoryForTesting(
628 scoped_ptr
<DownloadFileFactory
>(
629 new CountingDownloadFileFactory()).Pass());
632 bool EnsureNoPendingDownloads() {
634 BrowserThread::PostTask(
635 BrowserThread::IO
, FROM_HERE
,
636 base::Bind(&EnsureNoPendingDownloadJobsOnIO
, &result
));
637 base::MessageLoop::current()->Run();
639 (CountingDownloadFile::GetNumberActiveFilesFromFileThread() == 0);
642 void NavigateToURLAndWaitForDownload(
645 DownloadItem::DownloadState expected_terminal_state
) {
646 scoped_ptr
<DownloadTestObserver
> observer(CreateWaiter(shell
, 1));
647 NavigateToURL(shell
, url
);
648 observer
->WaitForFinished();
649 EXPECT_EQ(1u, observer
->NumDownloadsSeenInState(expected_terminal_state
));
652 // Checks that |path| is has |file_size| bytes, and matches the |value|
654 bool VerifyFile(const base::FilePath
& path
,
655 const std::string
& value
,
656 const int64 file_size
) {
657 std::string file_contents
;
659 bool read
= base::ReadFileToString(path
, &file_contents
);
660 EXPECT_TRUE(read
) << "Failed reading file: " << path
.value() << std::endl
;
662 return false; // Couldn't read the file.
664 // Note: we don't handle really large files (more than size_t can hold)
665 // so we will fail in that case.
666 size_t expected_size
= static_cast<size_t>(file_size
);
669 EXPECT_EQ(expected_size
, file_contents
.size());
670 if (expected_size
!= file_contents
.size())
673 // Check the contents.
674 EXPECT_EQ(value
, file_contents
);
675 if (memcmp(file_contents
.c_str(), value
.c_str(), expected_size
) != 0)
681 // Start a download and return the item.
682 DownloadItem
* StartDownloadAndReturnItem(GURL url
) {
683 scoped_ptr
<DownloadCreateObserver
> observer(
684 CreateInProgressWaiter(shell(), 1));
685 NavigateToURL(shell(), url
);
686 observer
->WaitForFinished();
687 std::vector
<DownloadItem
*> downloads
;
688 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
689 EXPECT_EQ(1u, downloads
.size());
690 if (1u != downloads
.size())
696 void WaitForData(DownloadItem
* download
, int size
) {
697 DownloadUpdatedObserver
data_observer(
698 download
, base::Bind(&DataReceivedFilter
, size
));
699 data_observer
.WaitForEvent();
700 ASSERT_EQ(size
, download
->GetReceivedBytes());
701 ASSERT_EQ(DownloadItem::IN_PROGRESS
, download
->GetState());
704 // Tell the test server to release a pending RST and confirm
705 // that the interrupt is received properly (for download resumption
707 void ReleaseRSTAndConfirmInterruptForResume(DownloadItem
* download
) {
708 scoped_ptr
<DownloadTestObserver
> rst_observer(
709 CreateInterruptedWaiter(shell(), 1));
710 NavigateToURL(shell(), test_server()->GetURL("download-finish"));
711 rst_observer
->WaitForFinished();
712 EXPECT_EQ(DownloadItem::INTERRUPTED
, download
->GetState());
715 // Confirm file status expected for the given location in a stream
716 // provided by the resume test server.
717 void ConfirmFileStatusForResume(
718 DownloadItem
* download
, bool file_exists
,
719 int received_bytes
, int total_bytes
,
720 const base::FilePath
& expected_filename
) {
721 // expected_filename is only known if the file exists.
722 ASSERT_EQ(file_exists
, !expected_filename
.empty());
723 EXPECT_EQ(received_bytes
, download
->GetReceivedBytes());
724 EXPECT_EQ(total_bytes
, download
->GetTotalBytes());
725 EXPECT_EQ(expected_filename
.value(),
726 download
->GetFullPath().BaseName().value());
727 EXPECT_EQ(file_exists
,
728 (!download
->GetFullPath().empty() &&
729 base::PathExists(download
->GetFullPath())));
732 std::string file_contents
;
733 EXPECT_TRUE(base::ReadFileToString(
734 download
->GetFullPath(), &file_contents
));
736 ASSERT_EQ(static_cast<size_t>(received_bytes
), file_contents
.size());
737 for (int i
= 0; i
< received_bytes
; ++i
) {
738 EXPECT_EQ(static_cast<char>((i
* 2 + 15) % 256), file_contents
[i
])
739 << "File contents diverged at position " << i
740 << " for " << expected_filename
.value();
742 if (static_cast<char>((i
* 2 + 15) % 256) != file_contents
[i
])
749 static void EnsureNoPendingDownloadJobsOnIO(bool* result
) {
750 if (net::URLRequestSlowDownloadJob::NumberOutstandingRequests())
752 BrowserThread::PostTask(
753 BrowserThread::UI
, FROM_HERE
, base::MessageLoop::QuitClosure());
756 // Location of the downloads directory for these tests
757 base::ScopedTempDir downloads_directory_
;
758 scoped_ptr
<TestShellDownloadManagerDelegate
> test_delegate_
;
761 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, DownloadCancelled
) {
762 SetupEnsureNoPendingDownloads();
764 // Create a download, wait until it's started, and confirm
765 // we're in the expected state.
766 scoped_ptr
<DownloadCreateObserver
> observer(
767 CreateInProgressWaiter(shell(), 1));
768 NavigateToURL(shell(), GURL(net::URLRequestSlowDownloadJob::kUnknownSizeUrl
));
769 observer
->WaitForFinished();
771 std::vector
<DownloadItem
*> downloads
;
772 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
773 ASSERT_EQ(1u, downloads
.size());
774 ASSERT_EQ(DownloadItem::IN_PROGRESS
, downloads
[0]->GetState());
776 // Cancel the download and wait for download system quiesce.
777 downloads
[0]->Cancel(true);
778 scoped_refptr
<DownloadTestFlushObserver
> flush_observer(
779 new DownloadTestFlushObserver(DownloadManagerForShell(shell())));
780 flush_observer
->WaitForFlush();
782 // Get the important info from other threads and check it.
783 EXPECT_TRUE(EnsureNoPendingDownloads());
786 // Check that downloading multiple (in this case, 2) files does not result in
788 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, MultiDownload
) {
789 SetupEnsureNoPendingDownloads();
791 // Create a download, wait until it's started, and confirm
792 // we're in the expected state.
793 scoped_ptr
<DownloadCreateObserver
> observer1(
794 CreateInProgressWaiter(shell(), 1));
795 NavigateToURL(shell(), GURL(net::URLRequestSlowDownloadJob::kUnknownSizeUrl
));
796 observer1
->WaitForFinished();
798 std::vector
<DownloadItem
*> downloads
;
799 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
800 ASSERT_EQ(1u, downloads
.size());
801 ASSERT_EQ(DownloadItem::IN_PROGRESS
, downloads
[0]->GetState());
802 DownloadItem
* download1
= downloads
[0]; // The only download.
804 // Start the second download and wait until it's done.
805 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
806 GURL
url(net::URLRequestMockHTTPJob::GetMockUrl(file
));
807 // Download the file and wait.
808 NavigateToURLAndWaitForDownload(shell(), url
, DownloadItem::COMPLETE
);
810 // Should now have 2 items on the manager.
812 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
813 ASSERT_EQ(2u, downloads
.size());
814 // We don't know the order of the downloads.
815 DownloadItem
* download2
= downloads
[(download1
== downloads
[0]) ? 1 : 0];
817 ASSERT_EQ(DownloadItem::IN_PROGRESS
, download1
->GetState());
818 ASSERT_EQ(DownloadItem::COMPLETE
, download2
->GetState());
820 // Allow the first request to finish.
821 scoped_ptr
<DownloadTestObserver
> observer2(CreateWaiter(shell(), 1));
822 NavigateToURL(shell(),
823 GURL(net::URLRequestSlowDownloadJob::kFinishDownloadUrl
));
824 observer2
->WaitForFinished(); // Wait for the third request.
825 EXPECT_EQ(1u, observer2
->NumDownloadsSeenInState(DownloadItem::COMPLETE
));
827 // Get the important info from other threads and check it.
828 EXPECT_TRUE(EnsureNoPendingDownloads());
830 // The |DownloadItem|s should now be done and have the final file names.
831 // Verify that the files have the expected data and size.
832 // |file1| should be full of '*'s, and |file2| should be the same as the
834 base::FilePath
file1(download1
->GetTargetFilePath());
835 size_t file_size1
= net::URLRequestSlowDownloadJob::kFirstDownloadSize
+
836 net::URLRequestSlowDownloadJob::kSecondDownloadSize
;
837 std::string
expected_contents(file_size1
, '*');
838 ASSERT_TRUE(VerifyFile(file1
, expected_contents
, file_size1
));
840 base::FilePath
file2(download2
->GetTargetFilePath());
841 ASSERT_TRUE(base::ContentsEqual(
842 file2
, GetTestFilePath("download", "download-test.lib")));
845 #if defined(ENABLE_PLUGINS)
846 // Content served with a MIME type of application/octet-stream should be
847 // downloaded even when a plugin can be found that handles the file type.
848 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, DownloadOctetStream
) {
849 const base::FilePath::CharType kTestFilePath
[] =
850 FILE_PATH_LITERAL("octet-stream.abc");
851 const char kTestPluginName
[] = "TestPlugin";
852 const char kTestMimeType
[] = "application/x-test-mime-type";
853 const char kTestFileType
[] = "abc";
855 WebPluginInfo plugin_info
;
856 plugin_info
.name
= base::ASCIIToUTF16(kTestPluginName
);
857 plugin_info
.mime_types
.push_back(
858 WebPluginMimeType(kTestMimeType
, kTestFileType
, ""));
859 PluginServiceImpl::GetInstance()->RegisterInternalPlugin(plugin_info
, false);
861 // The following is served with a Content-Type of application/octet-stream.
863 net::URLRequestMockHTTPJob::GetMockUrl(base::FilePath(kTestFilePath
)));
864 NavigateToURLAndWaitForDownload(shell(), url
, DownloadItem::COMPLETE
);
868 // Try to cancel just before we release the download file, by delaying final
870 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, CancelAtFinalRename
) {
871 // Setup new factory.
872 DownloadFileWithDelayFactory
* file_factory
=
873 new DownloadFileWithDelayFactory();
874 DownloadManagerImpl
* download_manager(DownloadManagerForShell(shell()));
875 download_manager
->SetDownloadFileFactoryForTesting(
876 scoped_ptr
<DownloadFileFactory
>(file_factory
).Pass());
879 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
880 NavigateToURL(shell(), net::URLRequestMockHTTPJob::GetMockUrl(file
));
882 // Wait until the first (intermediate file) rename and execute the callback.
883 file_factory
->WaitForSomeCallback();
884 std::vector
<base::Closure
> callbacks
;
885 file_factory
->GetAllRenameCallbacks(&callbacks
);
886 ASSERT_EQ(1u, callbacks
.size());
890 // Wait until the second (final) rename callback is posted.
891 file_factory
->WaitForSomeCallback();
892 file_factory
->GetAllRenameCallbacks(&callbacks
);
893 ASSERT_EQ(1u, callbacks
.size());
896 std::vector
<DownloadItem
*> items
;
897 download_manager
->GetAllDownloads(&items
);
898 ASSERT_EQ(1u, items
.size());
899 items
[0]->Cancel(true);
900 RunAllPendingInMessageLoop();
903 EXPECT_EQ(DownloadItem::CANCELLED
, items
[0]->GetState());
905 // Run final rename callback.
910 EXPECT_EQ(DownloadItem::CANCELLED
, items
[0]->GetState());
913 // Try to cancel just after we release the download file, by delaying
914 // in ShouldOpenDownload.
915 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, CancelAtRelease
) {
916 DownloadManagerImpl
* download_manager(DownloadManagerForShell(shell()));
918 // Mark delegate for delayed open.
919 GetDownloadManagerDelegate()->SetDelayedOpen(true);
921 // Setup new factory.
922 DownloadFileWithDelayFactory
* file_factory
=
923 new DownloadFileWithDelayFactory();
924 download_manager
->SetDownloadFileFactoryForTesting(
925 scoped_ptr
<DownloadFileFactory
>(file_factory
).Pass());
928 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
929 NavigateToURL(shell(), net::URLRequestMockHTTPJob::GetMockUrl(file
));
931 // Wait until the first (intermediate file) rename and execute the callback.
932 file_factory
->WaitForSomeCallback();
933 std::vector
<base::Closure
> callbacks
;
934 file_factory
->GetAllRenameCallbacks(&callbacks
);
935 ASSERT_EQ(1u, callbacks
.size());
939 // Wait until the second (final) rename callback is posted.
940 file_factory
->WaitForSomeCallback();
941 file_factory
->GetAllRenameCallbacks(&callbacks
);
942 ASSERT_EQ(1u, callbacks
.size());
948 // Confirm download still IN_PROGRESS (internal state COMPLETING).
949 std::vector
<DownloadItem
*> items
;
950 download_manager
->GetAllDownloads(&items
);
951 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
953 // Cancel the download; confirm cancel fails.
954 ASSERT_EQ(1u, items
.size());
955 items
[0]->Cancel(true);
956 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
958 // Need to complete open test.
959 std::vector
<DownloadOpenDelayedCallback
> delayed_callbacks
;
960 GetDownloadManagerDelegate()->GetDelayedCallbacks(
962 ASSERT_EQ(1u, delayed_callbacks
.size());
963 delayed_callbacks
[0].Run(true);
965 // *Now* the download should be complete.
966 EXPECT_EQ(DownloadItem::COMPLETE
, items
[0]->GetState());
969 // Try to shutdown with a download in progress to make sure shutdown path
971 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ShutdownInProgress
) {
972 // Create a download that won't complete.
973 scoped_ptr
<DownloadCreateObserver
> observer(
974 CreateInProgressWaiter(shell(), 1));
975 NavigateToURL(shell(), GURL(net::URLRequestSlowDownloadJob::kUnknownSizeUrl
));
976 observer
->WaitForFinished();
979 std::vector
<DownloadItem
*> items
;
980 DownloadManagerForShell(shell())->GetAllDownloads(&items
);
981 ASSERT_EQ(1u, items
.size());
982 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
984 // Shutdown the download manager and make sure we get the right
985 // notifications in the right order.
986 StrictMock
<MockDownloadItemObserver
> item_observer
;
987 items
[0]->AddObserver(&item_observer
);
988 MockDownloadManagerObserver
manager_observer(
989 DownloadManagerForShell(shell()));
990 // Don't care about ModelChanged() events.
991 EXPECT_CALL(manager_observer
, ModelChanged(_
))
992 .WillRepeatedly(Return());
994 InSequence notifications
;
996 EXPECT_CALL(manager_observer
, MockManagerGoingDown(
997 DownloadManagerForShell(shell())))
999 EXPECT_CALL(item_observer
, OnDownloadUpdated(
1001 Property(&DownloadItem::GetState
, DownloadItem::CANCELLED
))))
1002 .WillOnce(Return());
1003 EXPECT_CALL(item_observer
, OnDownloadDestroyed(items
[0]))
1004 .WillOnce(Return());
1007 // See http://crbug.com/324525. If we have a refcount release/post task
1008 // race, the second post will stall the IO thread long enough so that we'll
1009 // lose the race and crash. The first stall is just to give the UI thread
1010 // a chance to get the second stall onto the IO thread queue after the cancel
1011 // message created by Shutdown and before the notification callback
1012 // created by the IO thread in canceling the request.
1013 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
1014 base::Bind(&base::PlatformThread::Sleep
,
1015 base::TimeDelta::FromMilliseconds(25)));
1016 DownloadManagerForShell(shell())->Shutdown();
1017 BrowserThread::PostTask(BrowserThread::IO
, FROM_HERE
,
1018 base::Bind(&base::PlatformThread::Sleep
,
1019 base::TimeDelta::FromMilliseconds(25)));
1023 // Try to shutdown just after we release the download file, by delaying
1025 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ShutdownAtRelease
) {
1026 DownloadManagerImpl
* download_manager(DownloadManagerForShell(shell()));
1028 // Mark delegate for delayed open.
1029 GetDownloadManagerDelegate()->SetDelayedOpen(true);
1031 // Setup new factory.
1032 DownloadFileWithDelayFactory
* file_factory
=
1033 new DownloadFileWithDelayFactory();
1034 download_manager
->SetDownloadFileFactoryForTesting(
1035 scoped_ptr
<DownloadFileFactory
>(file_factory
).Pass());
1037 // Create a download
1038 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
1039 NavigateToURL(shell(), net::URLRequestMockHTTPJob::GetMockUrl(file
));
1041 // Wait until the first (intermediate file) rename and execute the callback.
1042 file_factory
->WaitForSomeCallback();
1043 std::vector
<base::Closure
> callbacks
;
1044 file_factory
->GetAllRenameCallbacks(&callbacks
);
1045 ASSERT_EQ(1u, callbacks
.size());
1049 // Wait until the second (final) rename callback is posted.
1050 file_factory
->WaitForSomeCallback();
1051 file_factory
->GetAllRenameCallbacks(&callbacks
);
1052 ASSERT_EQ(1u, callbacks
.size());
1058 // Confirm download isn't complete yet.
1059 std::vector
<DownloadItem
*> items
;
1060 DownloadManagerForShell(shell())->GetAllDownloads(&items
);
1061 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
1063 // Cancel the download; confirm cancel fails anyway.
1064 ASSERT_EQ(1u, items
.size());
1065 items
[0]->Cancel(true);
1066 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
1067 RunAllPendingInMessageLoop();
1068 EXPECT_EQ(DownloadItem::IN_PROGRESS
, items
[0]->GetState());
1070 MockDownloadItemObserver observer
;
1071 items
[0]->AddObserver(&observer
);
1072 EXPECT_CALL(observer
, OnDownloadDestroyed(items
[0]));
1074 // Shutdown the download manager. Mostly this is confirming a lack of
1076 DownloadManagerForShell(shell())->Shutdown();
1079 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ResumeInterruptedDownload
) {
1080 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1081 switches::kEnableDownloadResumption
);
1082 ASSERT_TRUE(test_server()->Start());
1084 GURL url
= test_server()->GetURL(
1085 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1086 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1088 MockDownloadManagerObserver
dm_observer(DownloadManagerForShell(shell()));
1089 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(1);
1091 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1092 WaitForData(download
, GetSafeBufferChunk());
1093 ::testing::Mock::VerifyAndClearExpectations(&dm_observer
);
1095 // Confirm resumption while in progress doesn't do anything.
1097 ASSERT_EQ(GetSafeBufferChunk(), download
->GetReceivedBytes());
1098 ASSERT_EQ(DownloadItem::IN_PROGRESS
, download
->GetState());
1100 // Tell the server to send the RST and confirm the interrupt happens.
1101 ReleaseRSTAndConfirmInterruptForResume(download
);
1102 ConfirmFileStatusForResume(
1103 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1104 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1106 // Resume, confirming received bytes on resumption is correct.
1107 // Make sure no creation calls are included.
1108 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(0);
1109 int initial_size
= 0;
1110 DownloadUpdatedObserver
initial_size_observer(
1111 download
, base::Bind(&InitialSizeFilter
, &initial_size
));
1113 initial_size_observer
.WaitForEvent();
1114 EXPECT_EQ(GetSafeBufferChunk(), initial_size
);
1115 ::testing::Mock::VerifyAndClearExpectations(&dm_observer
);
1117 // and wait for expected data.
1118 WaitForData(download
, GetSafeBufferChunk() * 2);
1120 // Tell the server to send the RST and confirm the interrupt happens.
1121 ReleaseRSTAndConfirmInterruptForResume(download
);
1122 ConfirmFileStatusForResume(
1123 download
, true, GetSafeBufferChunk() * 2, GetSafeBufferChunk() * 3,
1124 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1126 // Resume and wait for completion.
1127 DownloadUpdatedObserver
completion_observer(
1128 download
, base::Bind(DownloadCompleteFilter
));
1130 completion_observer
.WaitForEvent();
1132 ConfirmFileStatusForResume(
1133 download
, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1134 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1136 // Confirm resumption while complete doesn't do anything.
1138 ASSERT_EQ(GetSafeBufferChunk() * 3, download
->GetReceivedBytes());
1139 ASSERT_EQ(DownloadItem::COMPLETE
, download
->GetState());
1140 RunAllPendingInMessageLoop();
1141 ASSERT_EQ(GetSafeBufferChunk() * 3, download
->GetReceivedBytes());
1142 ASSERT_EQ(DownloadItem::COMPLETE
, download
->GetState());
1145 // Confirm restart fallback happens if a range request is bounced.
1146 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ResumeInterruptedDownloadNoRange
) {
1147 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1148 switches::kEnableDownloadResumption
);
1149 ASSERT_TRUE(test_server()->Start());
1151 // Auto-restart if server doesn't handle ranges.
1152 GURL url
= test_server()->GetURL(
1154 // First download hits an RST, rest don't, no ranges.
1155 "rangereset?size=%d&rst_boundary=%d&"
1156 "token=NoRange&rst_limit=1&bounce_range",
1157 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1159 // Start the download and wait for first data chunk.
1160 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1161 WaitForData(download
, GetSafeBufferChunk());
1163 RecordingDownloadObserver
recorder(download
);
1165 ReleaseRSTAndConfirmInterruptForResume(download
);
1166 ConfirmFileStatusForResume(
1167 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1168 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1170 DownloadUpdatedObserver
completion_observer(
1171 download
, base::Bind(DownloadCompleteFilter
));
1173 completion_observer
.WaitForEvent();
1175 ConfirmFileStatusForResume(
1176 download
, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1177 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1179 static const RecordingDownloadObserver::RecordStruct expected_record
[] = {
1181 {DownloadItem::INTERRUPTED
, GetSafeBufferChunk()},
1182 // Starting continuation
1183 {DownloadItem::IN_PROGRESS
, GetSafeBufferChunk()},
1184 // Notification of receiving whole file.
1185 {DownloadItem::IN_PROGRESS
, 0},
1187 {DownloadItem::COMPLETE
, GetSafeBufferChunk() * 3},
1190 recorder
.CompareToExpectedRecord(expected_record
, arraysize(expected_record
));
1193 // Confirm restart fallback happens if a precondition is failed.
1194 IN_PROC_BROWSER_TEST_F(DownloadContentTest
,
1195 ResumeInterruptedDownloadBadPrecondition
) {
1196 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1197 switches::kEnableDownloadResumption
);
1198 ASSERT_TRUE(test_server()->Start());
1200 GURL url
= test_server()->GetURL(base::StringPrintf(
1201 // First download hits an RST, rest don't, precondition fail.
1202 "rangereset?size=%d&rst_boundary=%d&"
1203 "token=BadPrecondition&rst_limit=1&fail_precondition=2",
1204 GetSafeBufferChunk() * 3,
1205 GetSafeBufferChunk()));
1207 // Start the download and wait for first data chunk.
1208 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1209 WaitForData(download
, GetSafeBufferChunk());
1211 RecordingDownloadObserver
recorder(download
);
1213 ReleaseRSTAndConfirmInterruptForResume(download
);
1214 ConfirmFileStatusForResume(
1215 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1216 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1217 EXPECT_EQ("BadPrecondition2", download
->GetETag());
1219 DownloadUpdatedObserver
completion_observer(
1220 download
, base::Bind(DownloadCompleteFilter
));
1222 completion_observer
.WaitForEvent();
1224 ConfirmFileStatusForResume(
1225 download
, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1226 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1227 EXPECT_EQ("BadPrecondition0", download
->GetETag());
1229 static const RecordingDownloadObserver::RecordStruct expected_record
[] = {
1231 {DownloadItem::INTERRUPTED
, GetSafeBufferChunk()},
1232 // Starting continuation
1233 {DownloadItem::IN_PROGRESS
, GetSafeBufferChunk()},
1234 // Server precondition fail.
1235 {DownloadItem::INTERRUPTED
, 0},
1236 // Notification of successful restart.
1237 {DownloadItem::IN_PROGRESS
, 0},
1239 {DownloadItem::COMPLETE
, GetSafeBufferChunk() * 3},
1242 recorder
.CompareToExpectedRecord(expected_record
, arraysize(expected_record
));
1245 // Confirm we don't try to resume if we don't have a verifier.
1246 IN_PROC_BROWSER_TEST_F(DownloadContentTest
,
1247 ResumeInterruptedDownloadNoVerifiers
) {
1248 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1249 switches::kEnableDownloadResumption
);
1250 ASSERT_TRUE(test_server()->Start());
1252 GURL url
= test_server()->GetURL(
1254 // First download hits an RST, rest don't, no verifiers.
1255 "rangereset?size=%d&rst_boundary=%d&"
1256 "token=NoRange&rst_limit=1&no_verifiers",
1257 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1259 // Start the download and wait for first data chunk.
1260 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1261 WaitForData(download
, GetSafeBufferChunk());
1263 RecordingDownloadObserver
recorder(download
);
1265 ReleaseRSTAndConfirmInterruptForResume(download
);
1266 ConfirmFileStatusForResume(
1267 download
, false, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1270 DownloadUpdatedObserver
completion_observer(
1271 download
, base::Bind(DownloadCompleteFilter
));
1273 completion_observer
.WaitForEvent();
1275 ConfirmFileStatusForResume(
1276 download
, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1277 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1279 static const RecordingDownloadObserver::RecordStruct expected_record
[] = {
1281 {DownloadItem::INTERRUPTED
, GetSafeBufferChunk()},
1282 // Restart for lack of verifiers
1283 {DownloadItem::IN_PROGRESS
, 0},
1285 {DownloadItem::COMPLETE
, GetSafeBufferChunk() * 3},
1288 recorder
.CompareToExpectedRecord(expected_record
, arraysize(expected_record
));
1291 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ResumeWithDeletedFile
) {
1292 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1293 switches::kEnableDownloadResumption
);
1294 ASSERT_TRUE(test_server()->Start());
1296 GURL url
= test_server()->GetURL(
1298 // First download hits an RST, rest don't
1299 "rangereset?size=%d&rst_boundary=%d&"
1300 "token=NoRange&rst_limit=1",
1301 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1303 // Start the download and wait for first data chunk.
1304 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1305 WaitForData(download
, GetSafeBufferChunk());
1307 RecordingDownloadObserver
recorder(download
);
1309 ReleaseRSTAndConfirmInterruptForResume(download
);
1310 ConfirmFileStatusForResume(
1311 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1312 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1314 // Delete the intermediate file.
1315 base::DeleteFile(download
->GetFullPath(), false);
1317 DownloadUpdatedObserver
completion_observer(
1318 download
, base::Bind(DownloadCompleteFilter
));
1320 completion_observer
.WaitForEvent();
1322 ConfirmFileStatusForResume(
1323 download
, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1324 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1326 static const RecordingDownloadObserver::RecordStruct expected_record
[] = {
1328 {DownloadItem::INTERRUPTED
, GetSafeBufferChunk()},
1329 // Starting continuation
1330 {DownloadItem::IN_PROGRESS
, GetSafeBufferChunk()},
1331 // Error because file isn't there.
1332 {DownloadItem::INTERRUPTED
, 0},
1334 {DownloadItem::IN_PROGRESS
, 0},
1336 {DownloadItem::COMPLETE
, GetSafeBufferChunk() * 3},
1339 recorder
.CompareToExpectedRecord(expected_record
, arraysize(expected_record
));
1342 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ResumeWithFileInitError
) {
1343 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1344 switches::kEnableDownloadResumption
);
1345 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
1346 GURL
url(net::URLRequestMockHTTPJob::GetMockUrl(file
));
1348 // Setup the error injector.
1349 scoped_refptr
<TestFileErrorInjector
> injector(
1350 TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
1352 TestFileErrorInjector::FileErrorInfo err
= {
1354 TestFileErrorInjector::FILE_OPERATION_INITIALIZE
,
1356 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
1358 injector
->AddError(err
);
1359 injector
->InjectErrors();
1361 // Start and watch for interrupt.
1362 scoped_ptr
<DownloadTestObserver
> int_observer(
1363 CreateInterruptedWaiter(shell(), 1));
1364 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1365 int_observer
->WaitForFinished();
1366 ASSERT_EQ(DownloadItem::INTERRUPTED
, download
->GetState());
1367 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
,
1368 download
->GetLastReason());
1369 EXPECT_EQ(0, download
->GetReceivedBytes());
1370 EXPECT_TRUE(download
->GetFullPath().empty());
1371 EXPECT_TRUE(download
->GetTargetFilePath().empty());
1373 // We need to make sure that any cross-thread downloads communication has
1374 // quiesced before clearing and injecting the new errors, as the
1375 // InjectErrors() routine alters the currently in use download file
1376 // factory, which is a file thread object.
1377 RunAllPendingInMessageLoop(BrowserThread::FILE);
1378 RunAllPendingInMessageLoop();
1380 // Clear the old errors list.
1381 injector
->ClearErrors();
1382 injector
->InjectErrors();
1384 // Resume and watch completion.
1385 DownloadUpdatedObserver
completion_observer(
1386 download
, base::Bind(DownloadCompleteFilter
));
1388 completion_observer
.WaitForEvent();
1389 EXPECT_EQ(download
->GetState(), DownloadItem::COMPLETE
);
1392 IN_PROC_BROWSER_TEST_F(DownloadContentTest
,
1393 ResumeWithFileIntermediateRenameError
) {
1394 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1395 switches::kEnableDownloadResumption
);
1396 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
1397 GURL
url(net::URLRequestMockHTTPJob::GetMockUrl(file
));
1399 // Setup the error injector.
1400 scoped_refptr
<TestFileErrorInjector
> injector(
1401 TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
1403 TestFileErrorInjector::FileErrorInfo err
= {
1405 TestFileErrorInjector::FILE_OPERATION_RENAME_UNIQUIFY
,
1407 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
1409 injector
->AddError(err
);
1410 injector
->InjectErrors();
1412 // Start and watch for interrupt.
1413 scoped_ptr
<DownloadTestObserver
> int_observer(
1414 CreateInterruptedWaiter(shell(), 1));
1415 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1416 int_observer
->WaitForFinished();
1417 ASSERT_EQ(DownloadItem::INTERRUPTED
, download
->GetState());
1418 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
,
1419 download
->GetLastReason());
1420 EXPECT_TRUE(download
->GetFullPath().empty());
1421 // Target path will have been set after file name determination. GetFullPath()
1422 // being empty is sufficient to signal that filename determination needs to be
1424 EXPECT_FALSE(download
->GetTargetFilePath().empty());
1426 // We need to make sure that any cross-thread downloads communication has
1427 // quiesced before clearing and injecting the new errors, as the
1428 // InjectErrors() routine alters the currently in use download file
1429 // factory, which is a file thread object.
1430 RunAllPendingInMessageLoop(BrowserThread::FILE);
1431 RunAllPendingInMessageLoop();
1433 // Clear the old errors list.
1434 injector
->ClearErrors();
1435 injector
->InjectErrors();
1437 // Resume and watch completion.
1438 DownloadUpdatedObserver
completion_observer(
1439 download
, base::Bind(DownloadCompleteFilter
));
1441 completion_observer
.WaitForEvent();
1442 EXPECT_EQ(download
->GetState(), DownloadItem::COMPLETE
);
1445 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, ResumeWithFileFinalRenameError
) {
1446 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1447 switches::kEnableDownloadResumption
);
1448 base::FilePath
file(FILE_PATH_LITERAL("download-test.lib"));
1449 GURL
url(net::URLRequestMockHTTPJob::GetMockUrl(file
));
1451 // Setup the error injector.
1452 scoped_refptr
<TestFileErrorInjector
> injector(
1453 TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
1455 DownloadManagerForShell(shell())->RemoveAllDownloads();
1456 TestFileErrorInjector::FileErrorInfo err
= {
1458 TestFileErrorInjector::FILE_OPERATION_RENAME_ANNOTATE
,
1460 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
1462 injector
->AddError(err
);
1463 injector
->InjectErrors();
1465 // Start and watch for interrupt.
1466 scoped_ptr
<DownloadTestObserver
> int_observer(
1467 CreateInterruptedWaiter(shell(), 1));
1468 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1469 int_observer
->WaitForFinished();
1470 ASSERT_EQ(DownloadItem::INTERRUPTED
, download
->GetState());
1471 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
,
1472 download
->GetLastReason());
1473 EXPECT_TRUE(download
->GetFullPath().empty());
1474 // Target path should still be intact.
1475 EXPECT_FALSE(download
->GetTargetFilePath().empty());
1477 // We need to make sure that any cross-thread downloads communication has
1478 // quiesced before clearing and injecting the new errors, as the
1479 // InjectErrors() routine alters the currently in use download file
1480 // factory, which is a file thread object.
1481 RunAllPendingInMessageLoop(BrowserThread::FILE);
1482 RunAllPendingInMessageLoop();
1484 // Clear the old errors list.
1485 injector
->ClearErrors();
1486 injector
->InjectErrors();
1488 // Resume and watch completion.
1489 DownloadUpdatedObserver
completion_observer(
1490 download
, base::Bind(DownloadCompleteFilter
));
1492 completion_observer
.WaitForEvent();
1493 EXPECT_EQ(download
->GetState(), DownloadItem::COMPLETE
);
1496 // An interrupted download should remove the intermediate file when it is
1498 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, CancelInterruptedDownload
) {
1499 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1500 switches::kEnableDownloadResumption
);
1501 ASSERT_TRUE(test_server()->Start());
1503 GURL url1
= test_server()->GetURL(
1504 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1505 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1507 DownloadItem
* download(StartDownloadAndReturnItem(url1
));
1508 WaitForData(download
, GetSafeBufferChunk());
1510 ReleaseRSTAndConfirmInterruptForResume(download
);
1511 ConfirmFileStatusForResume(
1512 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1513 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1515 base::FilePath
intermediate_path(download
->GetFullPath());
1516 ASSERT_FALSE(intermediate_path
.empty());
1517 EXPECT_TRUE(base::PathExists(intermediate_path
));
1519 download
->Cancel(true /* user_cancel */);
1520 RunAllPendingInMessageLoop(BrowserThread::FILE);
1521 RunAllPendingInMessageLoop();
1523 // The intermediate file should now be gone.
1524 EXPECT_FALSE(base::PathExists(intermediate_path
));
1525 EXPECT_TRUE(download
->GetFullPath().empty());
1528 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, RemoveDownload
) {
1529 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1530 switches::kEnableDownloadResumption
);
1531 ASSERT_TRUE(test_server()->Start());
1533 // An interrupted download should remove the intermediate file when it is
1536 GURL url1
= test_server()->GetURL(
1537 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1538 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1540 DownloadItem
* download(StartDownloadAndReturnItem(url1
));
1541 WaitForData(download
, GetSafeBufferChunk());
1542 ReleaseRSTAndConfirmInterruptForResume(download
);
1543 ConfirmFileStatusForResume(
1544 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1545 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1547 base::FilePath
intermediate_path(download
->GetFullPath());
1548 ASSERT_FALSE(intermediate_path
.empty());
1549 EXPECT_TRUE(base::PathExists(intermediate_path
));
1552 RunAllPendingInMessageLoop(BrowserThread::FILE);
1553 RunAllPendingInMessageLoop();
1555 // The intermediate file should now be gone.
1556 EXPECT_FALSE(base::PathExists(intermediate_path
));
1559 // A completed download shouldn't delete the downloaded file when it is
1562 // Start the second download and wait until it's done.
1563 base::FilePath
file2(FILE_PATH_LITERAL("download-test.lib"));
1564 GURL
url2(net::URLRequestMockHTTPJob::GetMockUrl(file2
));
1565 scoped_ptr
<DownloadTestObserver
> completion_observer(
1566 CreateWaiter(shell(), 1));
1567 DownloadItem
* download(StartDownloadAndReturnItem(url2
));
1568 completion_observer
->WaitForFinished();
1570 // The target path should exist.
1571 base::FilePath
target_path(download
->GetTargetFilePath());
1572 EXPECT_TRUE(base::PathExists(target_path
));
1574 RunAllPendingInMessageLoop(BrowserThread::FILE);
1575 RunAllPendingInMessageLoop();
1577 // The file should still exist.
1578 EXPECT_TRUE(base::PathExists(target_path
));
1582 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, RemoveResumingDownload
) {
1583 SetupEnsureNoPendingDownloads();
1584 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1585 switches::kEnableDownloadResumption
);
1586 ASSERT_TRUE(test_server()->Start());
1588 GURL url
= test_server()->GetURL(
1589 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1590 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1592 MockDownloadManagerObserver
dm_observer(DownloadManagerForShell(shell()));
1593 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(1);
1595 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1596 WaitForData(download
, GetSafeBufferChunk());
1597 ::testing::Mock::VerifyAndClearExpectations(&dm_observer
);
1599 // Tell the server to send the RST and confirm the interrupt happens.
1600 ReleaseRSTAndConfirmInterruptForResume(download
);
1601 ConfirmFileStatusForResume(
1602 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1603 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1605 base::FilePath
intermediate_path(download
->GetFullPath());
1606 ASSERT_FALSE(intermediate_path
.empty());
1607 EXPECT_TRUE(base::PathExists(intermediate_path
));
1609 // Resume and remove download. We expect only a single OnDownloadCreated()
1610 // call, and that's for the second download created below.
1611 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(1);
1615 // The intermediate file should now be gone.
1616 RunAllPendingInMessageLoop(BrowserThread::FILE);
1617 RunAllPendingInMessageLoop();
1618 EXPECT_FALSE(base::PathExists(intermediate_path
));
1620 // Start the second download and wait until it's done. The test server is
1621 // single threaded. The response to this download request should follow the
1622 // response to the previous resumption request.
1623 GURL
url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x"));
1624 NavigateToURLAndWaitForDownload(shell(), url2
, DownloadItem::COMPLETE
);
1626 EXPECT_TRUE(EnsureNoPendingDownloads());
1629 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, CancelResumingDownload
) {
1630 SetupEnsureNoPendingDownloads();
1631 base::CommandLine::ForCurrentProcess()->AppendSwitch(
1632 switches::kEnableDownloadResumption
);
1633 ASSERT_TRUE(test_server()->Start());
1635 GURL url
= test_server()->GetURL(
1636 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1637 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1639 MockDownloadManagerObserver
dm_observer(DownloadManagerForShell(shell()));
1640 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(1);
1642 DownloadItem
* download(StartDownloadAndReturnItem(url
));
1643 WaitForData(download
, GetSafeBufferChunk());
1644 ::testing::Mock::VerifyAndClearExpectations(&dm_observer
);
1646 // Tell the server to send the RST and confirm the interrupt happens.
1647 ReleaseRSTAndConfirmInterruptForResume(download
);
1648 ConfirmFileStatusForResume(
1649 download
, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1650 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1652 base::FilePath
intermediate_path(download
->GetFullPath());
1653 ASSERT_FALSE(intermediate_path
.empty());
1654 EXPECT_TRUE(base::PathExists(intermediate_path
));
1656 // Resume and cancel download. We expect only a single OnDownloadCreated()
1657 // call, and that's for the second download created below.
1658 EXPECT_CALL(dm_observer
, OnDownloadCreated(_
,_
)).Times(1);
1660 download
->Cancel(true);
1662 // The intermediate file should now be gone.
1663 RunAllPendingInMessageLoop(BrowserThread::FILE);
1664 RunAllPendingInMessageLoop();
1665 EXPECT_FALSE(base::PathExists(intermediate_path
));
1666 EXPECT_TRUE(download
->GetFullPath().empty());
1668 // Start the second download and wait until it's done. The test server is
1669 // single threaded. The response to this download request should follow the
1670 // response to the previous resumption request.
1671 GURL
url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x"));
1672 NavigateToURLAndWaitForDownload(shell(), url2
, DownloadItem::COMPLETE
);
1674 EXPECT_TRUE(EnsureNoPendingDownloads());
1677 // Check that the cookie policy is correctly updated when downloading a file
1678 // that redirects cross origin.
1679 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, CookiePolicy
) {
1680 ASSERT_TRUE(test_server()->Start());
1681 net::HostPortPair host_port
= test_server()->host_port_pair();
1682 DCHECK_EQ(host_port
.host(), std::string("127.0.0.1"));
1684 // Block third-party cookies.
1685 ShellNetworkDelegate::SetAcceptAllCookies(false);
1687 // |url| redirects to a different origin |download| which tries to set a
1689 std::string
download(base::StringPrintf(
1690 "http://localhost:%d/set-cookie?A=B", host_port
.port()));
1691 GURL
url(test_server()->GetURL("server-redirect?" + download
));
1693 // Download the file.
1694 SetupEnsureNoPendingDownloads();
1695 scoped_ptr
<DownloadUrlParameters
> dl_params(
1696 DownloadUrlParameters::FromWebContents(shell()->web_contents(), url
));
1697 scoped_ptr
<DownloadTestObserver
> observer(CreateWaiter(shell(), 1));
1698 DownloadManagerForShell(shell())->DownloadUrl(dl_params
.Pass());
1699 observer
->WaitForFinished();
1701 // Get the important info from other threads and check it.
1702 EXPECT_TRUE(EnsureNoPendingDownloads());
1704 std::vector
<DownloadItem
*> downloads
;
1705 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
1706 ASSERT_EQ(1u, downloads
.size());
1707 ASSERT_EQ(DownloadItem::COMPLETE
, downloads
[0]->GetState());
1709 // Check that the cookies were correctly set.
1711 content::GetCookies(shell()->web_contents()->GetBrowserContext(),
1715 // A filename suggestion specified via a @download attribute should not be
1716 // effective if the final download URL is in another origin from the original
1718 IN_PROC_BROWSER_TEST_F(DownloadContentTest
,
1719 DownloadAttributeCrossOriginRedirect
) {
1720 EmbeddedTestServer origin_one
;
1721 EmbeddedTestServer origin_two
;
1722 ASSERT_TRUE(origin_one
.InitializeAndWaitUntilReady());
1723 ASSERT_TRUE(origin_two
.InitializeAndWaitUntilReady());
1725 // The download-attribute.html page contains an anchor element whose href is
1726 // set to the value of the query parameter (specified as |target| in the URL
1727 // below). The suggested filename for the anchor is 'suggested-filename'. When
1728 // the page is loaded, a script simulates a click on the anchor, triggering a
1729 // download of the target URL.
1731 // We construct two test servers; origin_one and origin_two. Once started, the
1732 // server URLs will differ by the port number. Therefore they will be in
1733 // different origins.
1734 GURL download_url
= origin_one
.GetURL("/ping");
1735 GURL referrer_url
= origin_one
.GetURL(
1736 std::string("/download-attribute.html?target=") + download_url
.spec());
1738 // <origin_one>/download-attribute.html initiates a download of
1739 // <origin_one>/ping, which redirects to <origin_two>/download.
1740 origin_one
.ServeFilesFromDirectory(GetTestFilePath("download", ""));
1741 origin_one
.RegisterRequestHandler(
1742 CreateRedirectHandler("/ping", origin_two
.GetURL("/download")));
1743 origin_two
.RegisterRequestHandler(CreateBasicResponseHandler(
1744 "/download", "application/octet-stream", "Hello"));
1746 NavigateToURLAndWaitForDownload(
1747 shell(), referrer_url
, DownloadItem::COMPLETE
);
1749 std::vector
<DownloadItem
*> downloads
;
1750 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
1751 ASSERT_EQ(1u, downloads
.size());
1753 EXPECT_EQ(FILE_PATH_LITERAL("download"),
1754 downloads
[0]->GetTargetFilePath().BaseName().value());
1755 ASSERT_TRUE(origin_one
.ShutdownAndWaitUntilComplete());
1756 ASSERT_TRUE(origin_two
.ShutdownAndWaitUntilComplete());
1759 // A filename suggestion specified via a @download attribute should be effective
1760 // if the final download URL is in the same origin as the initial download URL.
1761 // Test that this holds even if there are cross origin redirects in the middle
1762 // of the redirect chain.
1763 IN_PROC_BROWSER_TEST_F(DownloadContentTest
,
1764 DownloadAttributeSameOriginRedirect
) {
1765 EmbeddedTestServer origin_one
;
1766 EmbeddedTestServer origin_two
;
1767 ASSERT_TRUE(origin_one
.InitializeAndWaitUntilReady());
1768 ASSERT_TRUE(origin_two
.InitializeAndWaitUntilReady());
1770 // The download-attribute.html page contains an anchor element whose href is
1771 // set to the value of the query parameter (specified as |target| in the URL
1772 // below). The suggested filename for the anchor is 'suggested-filename'. When
1773 // the page is loaded, a script simulates a click on the anchor, triggering a
1774 // download of the target URL.
1776 // We construct two test servers; origin_one and origin_two. Once started, the
1777 // server URLs will differ by the port number. Therefore they will be in
1778 // different origins.
1779 GURL download_url
= origin_one
.GetURL("/ping");
1780 GURL referrer_url
= origin_one
.GetURL(
1781 std::string("/download-attribute.html?target=") + download_url
.spec());
1782 origin_one
.ServeFilesFromDirectory(GetTestFilePath("download", ""));
1784 // <origin_one>/download-attribute.html initiates a download of
1785 // <origin_one>/ping, which redirects to <origin_two>/pong, and then finally
1786 // to <origin_one>/download.
1787 origin_one
.RegisterRequestHandler(
1788 CreateRedirectHandler("/ping", origin_two
.GetURL("/pong")));
1789 origin_two
.RegisterRequestHandler(
1790 CreateRedirectHandler("/pong", origin_one
.GetURL("/download")));
1791 origin_one
.RegisterRequestHandler(CreateBasicResponseHandler(
1792 "/download", "application/octet-stream", "Hello"));
1794 NavigateToURLAndWaitForDownload(
1795 shell(), referrer_url
, DownloadItem::COMPLETE
);
1797 std::vector
<DownloadItem
*> downloads
;
1798 DownloadManagerForShell(shell())->GetAllDownloads(&downloads
);
1799 ASSERT_EQ(1u, downloads
.size());
1801 EXPECT_EQ(FILE_PATH_LITERAL("suggested-filename"),
1802 downloads
[0]->GetTargetFilePath().BaseName().value());
1803 ASSERT_TRUE(origin_one
.ShutdownAndWaitUntilComplete());
1804 ASSERT_TRUE(origin_two
.ShutdownAndWaitUntilComplete());
1807 // The file empty.bin is served with a MIME type of application/octet-stream.
1808 // The content body is empty. Make sure this case is handled properly and we
1809 // don't regress on http://crbug.com/320394.
1810 IN_PROC_BROWSER_TEST_F(DownloadContentTest
, DownloadGZipWithNoContent
) {
1811 EmbeddedTestServer test_server
;
1812 ASSERT_TRUE(test_server
.InitializeAndWaitUntilReady());
1814 GURL url
= test_server
.GetURL("/empty.bin");
1815 test_server
.ServeFilesFromDirectory(GetTestFilePath("download", ""));
1817 NavigateToURLAndWaitForDownload(shell(), url
, DownloadItem::COMPLETE
);
1818 // That's it. This should work without crashing.
1821 } // namespace content