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