Delete chrome.mediaGalleriesPrivate because the functionality unique to it has since...
[chromium-blink-merge.git] / content / browser / download / download_browsertest.cc
blobd8354b27f6a845ece9ec2cd76ad1a1fdb5b5154e
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"
45 #include "url/gurl.h"
47 #if defined(ENABLE_PLUGINS)
48 #include "content/browser/plugin_service_impl.h"
49 #endif
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;
58 using ::testing::_;
60 namespace content {
62 namespace {
64 class MockDownloadItemObserver : public DownloadItem::Observer {
65 public:
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 {
76 public:
77 MockDownloadManagerObserver(DownloadManager* manager) {
78 manager_ = manager;
79 manager->AddObserver(this);
81 virtual ~MockDownloadManagerObserver() {
82 if (manager_)
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);
93 manager_ = NULL;
96 MOCK_METHOD1(MockManagerGoingDown, void(DownloadManager*));
97 private:
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 {
112 public:
113 DownloadFileWithDelay(
114 scoped_ptr<DownloadSaveInfo> save_info,
115 const base::FilePath& default_download_directory,
116 const GURL& url,
117 const GURL& referrer_url,
118 bool calculate_hash,
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
129 // retrieval.
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;
135 private:
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 {
154 public:
155 DownloadFileWithDelayFactory();
156 ~DownloadFileWithDelayFactory() override;
158 // DownloadFileFactory interface.
159 DownloadFile* CreateFile(
160 scoped_ptr<DownloadSaveInfo> save_info,
161 const base::FilePath& default_download_directory,
162 const GURL& url,
163 const GURL& referrer_url,
164 bool calculate_hash,
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();
175 private:
176 std::vector<base::Closure> rename_callbacks_;
177 bool waiting_;
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,
186 const GURL& url,
187 const GURL& referrer_url,
188 bool calculate_hash,
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)
194 : DownloadFileImpl(
195 save_info.Pass(), default_download_directory, url, referrer_url,
196 calculate_hash, stream.Pass(), bound_net_log, observer),
197 owner_(owner) {}
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,
207 owner_, callback));
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,
215 owner_, callback));
218 // static
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));
225 if (!factory)
226 return;
227 factory->AddRenameCallback(base::Bind(original_callback, reason, path));
230 DownloadFileWithDelayFactory::DownloadFileWithDelayFactory()
231 : waiting_(false),
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,
239 const GURL& url,
240 const GURL& referrer_url,
241 bool calculate_hash,
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);
258 if (waiting_)
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()) {
272 waiting_ = true;
273 RunMessageLoop();
274 waiting_ = false;
278 class CountingDownloadFile : public DownloadFileImpl {
279 public:
280 CountingDownloadFile(
281 scoped_ptr<DownloadSaveInfo> save_info,
282 const base::FilePath& default_downloads_directory,
283 const GURL& url,
284 const GURL& referrer_url,
285 bool calculate_hash,
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));
296 active_files_--;
299 void Initialize(const InitializeCallback& callback) override {
300 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
301 active_files_++;
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() {
313 int result = -1;
314 BrowserThread::PostTaskAndReply(
315 BrowserThread::FILE,
316 FROM_HERE,
317 base::Bind(&CountingDownloadFile::GetNumberActiveFiles, &result),
318 base::MessageLoop::current()->QuitClosure());
319 base::MessageLoop::current()->Run();
320 DCHECK_NE(-1, result);
321 return result;
324 private:
325 static int active_files_;
328 int CountingDownloadFile::active_files_ = 0;
330 class CountingDownloadFileFactory : public DownloadFileFactory {
331 public:
332 CountingDownloadFileFactory() {}
333 ~CountingDownloadFileFactory() override {}
335 // DownloadFileFactory interface.
336 DownloadFile* CreateFile(
337 scoped_ptr<DownloadSaveInfo> save_info,
338 const base::FilePath& default_downloads_directory,
339 const GURL& url,
340 const GURL& referrer_url,
341 bool calculate_hash,
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 {
357 public:
358 TestShellDownloadManagerDelegate()
359 : delay_download_open_(false) {}
360 ~TestShellDownloadManagerDelegate() override {}
362 bool ShouldOpenDownload(
363 DownloadItem* item,
364 const DownloadOpenDelayedCallback& callback) override {
365 if (delay_download_open_) {
366 delayed_callbacks_.push_back(callback);
367 return false;
369 return true;
372 void SetDelayedOpen(bool delay) {
373 delay_download_open_ = delay;
376 void GetDelayedCallbacks(
377 std::vector<DownloadOpenDelayedCallback>* callbacks) {
378 callbacks->swap(delayed_callbacks_);
380 private:
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 {
387 public:
388 struct RecordStruct {
389 DownloadItem::DownloadState state;
390 int bytes_received;
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;
414 private:
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);
428 RemoveObserver();
431 void RemoveObserver() {
432 if (download_) {
433 download_->RemoveObserver(this);
434 download_ = NULL;
438 DownloadItem* download_;
439 RecordStruct last_state_;
440 RecordVector record_;
443 // Get the next created download.
444 class DownloadCreateObserver : DownloadManager::Observer {
445 public:
446 DownloadCreateObserver(DownloadManager* manager)
447 : manager_(manager),
448 item_(NULL),
449 waiting_(false) {
450 manager_->AddObserver(this);
453 ~DownloadCreateObserver() override {
454 if (manager_)
455 manager_->RemoveObserver(this);
456 manager_ = NULL;
459 void ManagerGoingDown(DownloadManager* manager) override {
460 DCHECK_EQ(manager_, manager);
461 manager_->RemoveObserver(this);
462 manager_ = NULL;
465 void OnDownloadCreated(DownloadManager* manager,
466 DownloadItem* download) override {
467 if (!item_)
468 item_ = download;
470 if (waiting_)
471 base::MessageLoopForUI::current()->Quit();
474 DownloadItem* WaitForFinished() {
475 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
476 if (!item_) {
477 waiting_ = true;
478 RunMessageLoop();
479 waiting_ = false;
481 return item_;
484 private:
485 DownloadManager* manager_;
486 DownloadItem* item_;
487 bool waiting_;
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
502 // is hit.
503 bool InitialSizeFilter(int* download_size, DownloadItem* download) {
504 if (download->GetState() != DownloadItem::IN_PROGRESS)
505 return false;
507 *download_size = download->GetReceivedBytes();
508 return true;
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) {
530 return base::Bind(
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) {
555 return base::Bind(
556 &HandleRequestAndSendBasicResponse, relative_url, content_type, body);
559 } // namespace
561 class DownloadContentTest : public ContentBrowserTest {
562 protected:
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(
589 BrowserThread::IO,
590 FROM_HERE,
591 base::Bind(
592 &net::URLRequestMockHTTPJob::AddUrlHandler,
593 mock_base,
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() {
633 bool result = true;
634 BrowserThread::PostTask(
635 BrowserThread::IO, FROM_HERE,
636 base::Bind(&EnsureNoPendingDownloadJobsOnIO, &result));
637 base::MessageLoop::current()->Run();
638 return result &&
639 (CountingDownloadFile::GetNumberActiveFilesFromFileThread() == 0);
642 void NavigateToURLAndWaitForDownload(
643 Shell* shell,
644 const GURL& url,
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|
653 // string.
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;
661 if (!read)
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);
668 // Check the size.
669 EXPECT_EQ(expected_size, file_contents.size());
670 if (expected_size != file_contents.size())
671 return false;
673 // Check the contents.
674 EXPECT_EQ(value, file_contents);
675 if (memcmp(file_contents.c_str(), value.c_str(), expected_size) != 0)
676 return false;
678 return true;
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())
691 return NULL;
692 return downloads[0];
695 // Wait for data
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
706 // testing).
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())));
731 if (file_exists) {
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])
743 return;
748 private:
749 static void EnsureNoPendingDownloadJobsOnIO(bool* result) {
750 if (net::URLRequestSlowDownloadJob::NumberOutstandingRequests())
751 *result = false;
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
787 // corrupted files.
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.
811 downloads.clear();
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
833 // source file.
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.
862 GURL url(
863 net::URLRequestMockHTTPJob::GetMockUrl(base::FilePath(kTestFilePath)));
864 NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE);
866 #endif
868 // Try to cancel just before we release the download file, by delaying final
869 // rename callback.
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());
878 // Create a download
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());
887 callbacks[0].Run();
888 callbacks.clear();
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());
895 // Cancel it.
896 std::vector<DownloadItem*> items;
897 download_manager->GetAllDownloads(&items);
898 ASSERT_EQ(1u, items.size());
899 items[0]->Cancel(true);
900 RunAllPendingInMessageLoop();
902 // Check state.
903 EXPECT_EQ(DownloadItem::CANCELLED, items[0]->GetState());
905 // Run final rename callback.
906 callbacks[0].Run();
907 callbacks.clear();
909 // Check state.
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());
927 // Create a download
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());
936 callbacks[0].Run();
937 callbacks.clear();
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());
944 // Call it.
945 callbacks[0].Run();
946 callbacks.clear();
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(
961 &delayed_callbacks);
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
970 // works properly.
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();
978 // Get the item.
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())))
998 .WillOnce(Return());
999 EXPECT_CALL(item_observer, OnDownloadUpdated(
1000 AllOf(items[0],
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)));
1020 items.clear();
1023 // Try to shutdown just after we release the download file, by delaying
1024 // release.
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());
1046 callbacks[0].Run();
1047 callbacks.clear();
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());
1054 // Call it.
1055 callbacks[0].Run();
1056 callbacks.clear();
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
1075 // crashes.
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.
1096 download->Resume();
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));
1112 download->Resume();
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));
1129 download->Resume();
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.
1137 download->Resume();
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(
1153 base::StringPrintf(
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));
1172 download->Resume();
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[] = {
1180 // Result of RST
1181 {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
1182 // Starting continuation
1183 {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()},
1184 // Notification of receiving whole file.
1185 {DownloadItem::IN_PROGRESS, 0},
1186 // Completion.
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));
1221 download->Resume();
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[] = {
1230 // Result of RST
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},
1238 // Completion.
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(
1253 base::StringPrintf(
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,
1268 base::FilePath());
1270 DownloadUpdatedObserver completion_observer(
1271 download, base::Bind(DownloadCompleteFilter));
1272 download->Resume();
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[] = {
1280 // Result of RST
1281 {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
1282 // Restart for lack of verifiers
1283 {DownloadItem::IN_PROGRESS, 0},
1284 // Completion.
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(
1297 base::StringPrintf(
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));
1319 download->Resume();
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[] = {
1327 // Result of RST
1328 {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
1329 // Starting continuation
1330 {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()},
1331 // Error because file isn't there.
1332 {DownloadItem::INTERRUPTED, 0},
1333 // Restart.
1334 {DownloadItem::IN_PROGRESS, 0},
1335 // Completion.
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 = {
1353 url.spec(),
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));
1387 download->Resume();
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 = {
1404 url.spec(),
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
1423 // redone.
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));
1440 download->Resume();
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 = {
1457 url.spec(),
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));
1491 download->Resume();
1492 completion_observer.WaitForEvent();
1493 EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE);
1496 // An interrupted download should remove the intermediate file when it is
1497 // cancelled.
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
1534 // removed.
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));
1551 download->Remove();
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
1560 // removed.
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));
1573 download->Remove();
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);
1612 download->Resume();
1613 download->Remove();
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);
1659 download->Resume();
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
1688 // cookie.
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.
1710 EXPECT_EQ("A=B",
1711 content::GetCookies(shell()->web_contents()->GetBrowserContext(),
1712 GURL(download)));
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
1717 // download URL.
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