1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // This file contains download browser tests that are known to be runnable
6 // in a pure content context. Over time tests should be migrated here.
8 #include "base/command_line.h"
9 #include "base/file_util.h"
10 #include "base/files/file_path.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/threading/platform_thread.h"
15 #include "base/time/time.h"
16 #include "content/browser/byte_stream.h"
17 #include "content/browser/download/download_file_factory.h"
18 #include "content/browser/download/download_file_impl.h"
19 #include "content/browser/download/download_item_impl.h"
20 #include "content/browser/download/download_manager_impl.h"
21 #include "content/browser/download/download_resource_handler.h"
22 #include "content/browser/plugin_service_impl.h"
23 #include "content/browser/web_contents/web_contents_impl.h"
24 #include "content/public/browser/power_save_blocker.h"
25 #include "content/public/common/content_switches.h"
26 #include "content/public/common/webplugininfo.h"
27 #include "content/public/test/browser_test_utils.h"
28 #include "content/public/test/content_browser_test.h"
29 #include "content/public/test/content_browser_test_utils.h"
30 #include "content/public/test/download_test_observer.h"
31 #include "content/public/test/test_file_error_injector.h"
32 #include "content/public/test/test_utils.h"
33 #include "content/shell/browser/shell.h"
34 #include "content/shell/browser/shell_browser_context.h"
35 #include "content/shell/browser/shell_download_manager_delegate.h"
36 #include "content/shell/browser/shell_network_delegate.h"
37 #include "content/test/net/url_request_mock_http_job.h"
38 #include "content/test/net/url_request_slow_download_job.h"
39 #include "net/test/embedded_test_server/embedded_test_server.h"
40 #include "net/test/embedded_test_server/http_request.h"
41 #include "net/test/embedded_test_server/http_response.h"
42 #include "net/test/spawned_test_server/spawned_test_server.h"
43 #include "testing/gmock/include/gmock/gmock.h"
44 #include "testing/gtest/include/gtest/gtest.h"
47 using ::net::test_server::EmbeddedTestServer;
48 using ::testing::AllOf;
49 using ::testing::Field;
50 using ::testing::InSequence;
51 using ::testing::Property;
52 using ::testing::Return;
53 using ::testing::StrictMock;
60 class MockDownloadItemObserver : public DownloadItem::Observer {
62 MockDownloadItemObserver() {}
63 virtual ~MockDownloadItemObserver() {}
65 MOCK_METHOD1(OnDownloadUpdated, void(DownloadItem*));
66 MOCK_METHOD1(OnDownloadOpened, void(DownloadItem*));
67 MOCK_METHOD1(OnDownloadRemoved, void(DownloadItem*));
68 MOCK_METHOD1(OnDownloadDestroyed, void(DownloadItem*));
71 class MockDownloadManagerObserver : public DownloadManager::Observer {
73 MockDownloadManagerObserver(DownloadManager* manager) {
75 manager->AddObserver(this);
77 virtual ~MockDownloadManagerObserver() {
79 manager_->RemoveObserver(this);
82 MOCK_METHOD2(OnDownloadCreated, void(DownloadManager*, DownloadItem*));
83 MOCK_METHOD1(ModelChanged, void(DownloadManager*));
84 void ManagerGoingDown(DownloadManager* manager) {
85 DCHECK_EQ(manager_, manager);
86 MockManagerGoingDown(manager);
88 manager_->RemoveObserver(this);
92 MOCK_METHOD1(MockManagerGoingDown, void(DownloadManager*));
94 DownloadManager* manager_;
97 class DownloadFileWithDelayFactory;
99 static DownloadManagerImpl* DownloadManagerForShell(Shell* shell) {
100 // We're in a content_browsertest; we know that the DownloadManager
101 // is a DownloadManagerImpl.
102 return static_cast<DownloadManagerImpl*>(
103 BrowserContext::GetDownloadManager(
104 shell->web_contents()->GetBrowserContext()));
107 class DownloadFileWithDelay : public DownloadFileImpl {
109 DownloadFileWithDelay(
110 scoped_ptr<DownloadSaveInfo> save_info,
111 const base::FilePath& default_download_directory,
113 const GURL& referrer_url,
115 scoped_ptr<ByteStreamReader> stream,
116 const net::BoundNetLog& bound_net_log,
117 scoped_ptr<PowerSaveBlocker> power_save_blocker,
118 base::WeakPtr<DownloadDestinationObserver> observer,
119 base::WeakPtr<DownloadFileWithDelayFactory> owner);
121 virtual ~DownloadFileWithDelay();
123 // Wraps DownloadFileImpl::Rename* and intercepts the return callback,
124 // storing it in the factory that produced this object for later
126 virtual void RenameAndUniquify(
127 const base::FilePath& full_path,
128 const RenameCompletionCallback& callback) OVERRIDE;
129 virtual void RenameAndAnnotate(
130 const base::FilePath& full_path,
131 const RenameCompletionCallback& callback) OVERRIDE;
134 static void RenameCallbackWrapper(
135 const base::WeakPtr<DownloadFileWithDelayFactory>& factory,
136 const RenameCompletionCallback& original_callback,
137 DownloadInterruptReason reason,
138 const base::FilePath& path);
140 // This variable may only be read on the FILE thread, and may only be
141 // indirected through (e.g. methods on DownloadFileWithDelayFactory called)
142 // on the UI thread. This is because after construction,
143 // DownloadFileWithDelay lives on the file thread, but
144 // DownloadFileWithDelayFactory is purely a UI thread object.
145 base::WeakPtr<DownloadFileWithDelayFactory> owner_;
147 DISALLOW_COPY_AND_ASSIGN(DownloadFileWithDelay);
150 // All routines on this class must be called on the UI thread.
151 class DownloadFileWithDelayFactory : public DownloadFileFactory {
153 DownloadFileWithDelayFactory();
154 virtual ~DownloadFileWithDelayFactory();
156 // DownloadFileFactory interface.
157 virtual DownloadFile* CreateFile(
158 scoped_ptr<DownloadSaveInfo> save_info,
159 const base::FilePath& default_download_directory,
161 const GURL& referrer_url,
163 scoped_ptr<ByteStreamReader> stream,
164 const net::BoundNetLog& bound_net_log,
165 base::WeakPtr<DownloadDestinationObserver> observer) OVERRIDE;
167 void AddRenameCallback(base::Closure callback);
168 void GetAllRenameCallbacks(std::vector<base::Closure>* results);
170 // Do not return until GetAllRenameCallbacks() will return a non-empty list.
171 void WaitForSomeCallback();
174 base::WeakPtrFactory<DownloadFileWithDelayFactory> weak_ptr_factory_;
175 std::vector<base::Closure> rename_callbacks_;
178 DISALLOW_COPY_AND_ASSIGN(DownloadFileWithDelayFactory);
181 DownloadFileWithDelay::DownloadFileWithDelay(
182 scoped_ptr<DownloadSaveInfo> save_info,
183 const base::FilePath& default_download_directory,
185 const GURL& referrer_url,
187 scoped_ptr<ByteStreamReader> stream,
188 const net::BoundNetLog& bound_net_log,
189 scoped_ptr<PowerSaveBlocker> power_save_blocker,
190 base::WeakPtr<DownloadDestinationObserver> observer,
191 base::WeakPtr<DownloadFileWithDelayFactory> owner)
193 save_info.Pass(), default_download_directory, url, referrer_url,
194 calculate_hash, stream.Pass(), bound_net_log,
195 power_save_blocker.Pass(), observer),
198 DownloadFileWithDelay::~DownloadFileWithDelay() {}
200 void DownloadFileWithDelay::RenameAndUniquify(
201 const base::FilePath& full_path,
202 const RenameCompletionCallback& callback) {
203 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
204 DownloadFileImpl::RenameAndUniquify(
205 full_path, base::Bind(DownloadFileWithDelay::RenameCallbackWrapper,
209 void DownloadFileWithDelay::RenameAndAnnotate(
210 const base::FilePath& full_path, const RenameCompletionCallback& callback) {
211 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
212 DownloadFileImpl::RenameAndAnnotate(
213 full_path, base::Bind(DownloadFileWithDelay::RenameCallbackWrapper,
218 void DownloadFileWithDelay::RenameCallbackWrapper(
219 const base::WeakPtr<DownloadFileWithDelayFactory>& factory,
220 const RenameCompletionCallback& original_callback,
221 DownloadInterruptReason reason,
222 const base::FilePath& path) {
223 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
226 factory->AddRenameCallback(base::Bind(original_callback, reason, path));
229 DownloadFileWithDelayFactory::DownloadFileWithDelayFactory()
230 : weak_ptr_factory_(this),
232 DownloadFileWithDelayFactory::~DownloadFileWithDelayFactory() {}
234 DownloadFile* DownloadFileWithDelayFactory::CreateFile(
235 scoped_ptr<DownloadSaveInfo> save_info,
236 const base::FilePath& default_download_directory,
238 const GURL& referrer_url,
240 scoped_ptr<ByteStreamReader> stream,
241 const net::BoundNetLog& bound_net_log,
242 base::WeakPtr<DownloadDestinationObserver> observer) {
243 scoped_ptr<PowerSaveBlocker> psb(
244 PowerSaveBlocker::Create(
245 PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
246 "Download in progress"));
247 return new DownloadFileWithDelay(
248 save_info.Pass(), default_download_directory, url, referrer_url,
249 calculate_hash, stream.Pass(), bound_net_log,
250 psb.Pass(), observer, weak_ptr_factory_.GetWeakPtr());
253 void DownloadFileWithDelayFactory::AddRenameCallback(base::Closure callback) {
254 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
255 rename_callbacks_.push_back(callback);
257 base::MessageLoopForUI::current()->Quit();
260 void DownloadFileWithDelayFactory::GetAllRenameCallbacks(
261 std::vector<base::Closure>* results) {
262 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
263 results->swap(rename_callbacks_);
266 void DownloadFileWithDelayFactory::WaitForSomeCallback() {
267 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
269 if (rename_callbacks_.empty()) {
276 class CountingDownloadFile : public DownloadFileImpl {
278 CountingDownloadFile(
279 scoped_ptr<DownloadSaveInfo> save_info,
280 const base::FilePath& default_downloads_directory,
282 const GURL& referrer_url,
284 scoped_ptr<ByteStreamReader> stream,
285 const net::BoundNetLog& bound_net_log,
286 scoped_ptr<PowerSaveBlocker> power_save_blocker,
287 base::WeakPtr<DownloadDestinationObserver> observer)
288 : DownloadFileImpl(save_info.Pass(), default_downloads_directory,
289 url, referrer_url, calculate_hash,
290 stream.Pass(), bound_net_log,
291 power_save_blocker.Pass(), observer) {}
293 virtual ~CountingDownloadFile() {
294 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
298 virtual void Initialize(const InitializeCallback& callback) OVERRIDE {
299 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
301 return DownloadFileImpl::Initialize(callback);
304 static void GetNumberActiveFiles(int* result) {
305 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
306 *result = active_files_;
309 // Can be called on any thread, and will block (running message loop)
310 // until data is returned.
311 static int GetNumberActiveFilesFromFileThread() {
313 BrowserThread::PostTaskAndReply(
316 base::Bind(&CountingDownloadFile::GetNumberActiveFiles, &result),
317 base::MessageLoop::current()->QuitClosure());
318 base::MessageLoop::current()->Run();
319 DCHECK_NE(-1, result);
324 static int active_files_;
327 int CountingDownloadFile::active_files_ = 0;
329 class CountingDownloadFileFactory : public DownloadFileFactory {
331 CountingDownloadFileFactory() {}
332 virtual ~CountingDownloadFileFactory() {}
334 // DownloadFileFactory interface.
335 virtual DownloadFile* CreateFile(
336 scoped_ptr<DownloadSaveInfo> save_info,
337 const base::FilePath& default_downloads_directory,
339 const GURL& referrer_url,
341 scoped_ptr<ByteStreamReader> stream,
342 const net::BoundNetLog& bound_net_log,
343 base::WeakPtr<DownloadDestinationObserver> observer) OVERRIDE {
344 scoped_ptr<PowerSaveBlocker> psb(
345 PowerSaveBlocker::Create(
346 PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
347 "Download in progress"));
348 return new CountingDownloadFile(
349 save_info.Pass(), default_downloads_directory, url, referrer_url,
350 calculate_hash, stream.Pass(), bound_net_log,
351 psb.Pass(), observer);
355 class TestShellDownloadManagerDelegate : public ShellDownloadManagerDelegate {
357 TestShellDownloadManagerDelegate()
358 : delay_download_open_(false) {}
359 virtual ~TestShellDownloadManagerDelegate() {}
361 virtual bool ShouldOpenDownload(
363 const DownloadOpenDelayedCallback& callback) OVERRIDE {
364 if (delay_download_open_) {
365 delayed_callbacks_.push_back(callback);
371 void SetDelayedOpen(bool delay) {
372 delay_download_open_ = delay;
375 void GetDelayedCallbacks(
376 std::vector<DownloadOpenDelayedCallback>* callbacks) {
377 callbacks->swap(delayed_callbacks_);
380 bool delay_download_open_;
381 std::vector<DownloadOpenDelayedCallback> delayed_callbacks_;
384 // Record all state transitions and byte counts on the observed download.
385 class RecordingDownloadObserver : DownloadItem::Observer {
387 struct RecordStruct {
388 DownloadItem::DownloadState state;
392 typedef std::vector<RecordStruct> RecordVector;
394 RecordingDownloadObserver(DownloadItem* download)
395 : download_(download) {
396 last_state_.state = download->GetState();
397 last_state_.bytes_received = download->GetReceivedBytes();
398 download_->AddObserver(this);
401 virtual ~RecordingDownloadObserver() {
405 void CompareToExpectedRecord(const RecordStruct expected[], size_t size) {
406 EXPECT_EQ(size, record_.size());
407 int min = size > record_.size() ? record_.size() : size;
408 for (int i = 0; i < min; ++i) {
409 EXPECT_EQ(expected[i].state, record_[i].state) << "Iteration " << i;
410 EXPECT_EQ(expected[i].bytes_received, record_[i].bytes_received)
411 << "Iteration " << i;
416 virtual void OnDownloadUpdated(DownloadItem* download) OVERRIDE {
417 DCHECK_EQ(download_, download);
418 DownloadItem::DownloadState state = download->GetState();
419 int bytes = download->GetReceivedBytes();
420 if (last_state_.state != state || last_state_.bytes_received > bytes) {
421 last_state_.state = state;
422 last_state_.bytes_received = bytes;
423 record_.push_back(last_state_);
427 virtual void OnDownloadDestroyed(DownloadItem* download) OVERRIDE {
428 DCHECK_EQ(download_, download);
432 void RemoveObserver() {
434 download_->RemoveObserver(this);
439 DownloadItem* download_;
440 RecordStruct last_state_;
441 RecordVector record_;
444 // Get the next created download.
445 class DownloadCreateObserver : DownloadManager::Observer {
447 DownloadCreateObserver(DownloadManager* manager)
451 manager_->AddObserver(this);
454 virtual ~DownloadCreateObserver() {
456 manager_->RemoveObserver(this);
460 virtual void ManagerGoingDown(DownloadManager* manager) OVERRIDE {
461 DCHECK_EQ(manager_, manager);
462 manager_->RemoveObserver(this);
466 virtual void OnDownloadCreated(DownloadManager* manager,
467 DownloadItem* download) OVERRIDE {
472 base::MessageLoopForUI::current()->Quit();
475 DownloadItem* WaitForFinished() {
476 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
486 DownloadManager* manager_;
492 // Filter for waiting for a certain number of bytes.
493 bool DataReceivedFilter(int number_of_bytes, DownloadItem* download) {
494 return download->GetReceivedBytes() >= number_of_bytes;
497 // Filter for download completion.
498 bool DownloadCompleteFilter(DownloadItem* download) {
499 return download->GetState() == DownloadItem::COMPLETE;
502 // Filter for saving the size of the download when the first IN_PROGRESS
504 bool InitialSizeFilter(int* download_size, DownloadItem* download) {
505 if (download->GetState() != DownloadItem::IN_PROGRESS)
508 *download_size = download->GetReceivedBytes();
512 // Request handler to be used with CreateRedirectHandler().
513 scoped_ptr<net::test_server::HttpResponse> HandleRequestAndSendRedirectResponse(
514 const std::string& relative_url,
515 const GURL& target_url,
516 const net::test_server::HttpRequest& request) {
517 scoped_ptr<net::test_server::BasicHttpResponse> response;
518 if (request.relative_url == relative_url) {
519 response.reset(new net::test_server::BasicHttpResponse);
520 response->set_code(net::HTTP_FOUND);
521 response->AddCustomHeader("Location", target_url.spec());
523 return response.PassAs<net::test_server::HttpResponse>();
526 // Creates a request handler for EmbeddedTestServer that responds with a HTTP
527 // 302 redirect if the request URL matches |relative_url|.
528 EmbeddedTestServer::HandleRequestCallback CreateRedirectHandler(
529 const std::string& relative_url,
530 const GURL& target_url) {
532 &HandleRequestAndSendRedirectResponse, relative_url, target_url);
535 // Request handler to be used with CreateBasicResponseHandler().
536 scoped_ptr<net::test_server::HttpResponse> HandleRequestAndSendBasicResponse(
537 const std::string& relative_url,
538 const std::string& content_type,
539 const std::string& body,
540 const net::test_server::HttpRequest& request) {
541 scoped_ptr<net::test_server::BasicHttpResponse> response;
542 if (request.relative_url == relative_url) {
543 response.reset(new net::test_server::BasicHttpResponse);
544 response->set_content_type(content_type);
545 response->set_content(body);
547 return response.PassAs<net::test_server::HttpResponse>();
550 // Creates a request handler for an EmbeddedTestServer that response with an
551 // HTTP 200 status code, a Content-Type header and a body.
552 EmbeddedTestServer::HandleRequestCallback CreateBasicResponseHandler(
553 const std::string& relative_url,
554 const std::string& content_type,
555 const std::string& body) {
557 &HandleRequestAndSendBasicResponse, relative_url, content_type, body);
562 class DownloadContentTest : public ContentBrowserTest {
564 // An initial send from a website of at least this size will not be
565 // help up by buffering in the underlying downloads ByteStream data
566 // transfer. This is important because on resumption tests we wait
567 // until we've gotten the data we expect before allowing the test server
568 // to send its reset, to get around hard close semantics on the Windows
569 // socket layer implementation.
570 int GetSafeBufferChunk() const {
571 return (DownloadResourceHandler::kDownloadByteStreamSize /
572 ByteStreamWriter::kFractionBufferBeforeSending) + 1;
575 virtual void SetUpOnMainThread() OVERRIDE {
576 ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir());
578 test_delegate_.reset(new TestShellDownloadManagerDelegate());
579 test_delegate_->SetDownloadBehaviorForTesting(downloads_directory_.path());
580 DownloadManager* manager = DownloadManagerForShell(shell());
581 manager->GetDelegate()->Shutdown();
582 manager->SetDelegate(test_delegate_.get());
583 test_delegate_->SetDownloadManager(manager);
585 BrowserThread::PostTask(
586 BrowserThread::IO, FROM_HERE,
587 base::Bind(&URLRequestSlowDownloadJob::AddUrlHandler));
588 base::FilePath mock_base(GetTestFilePath("download", ""));
589 BrowserThread::PostTask(
590 BrowserThread::IO, FROM_HERE,
591 base::Bind(&URLRequestMockHTTPJob::AddUrlHandler, mock_base));
594 TestShellDownloadManagerDelegate* GetDownloadManagerDelegate() {
595 return test_delegate_.get();
598 // Create a DownloadTestObserverTerminal that will wait for the
599 // specified number of downloads to finish.
600 DownloadTestObserver* CreateWaiter(
601 Shell* shell, int num_downloads) {
602 DownloadManager* download_manager = DownloadManagerForShell(shell);
603 return new DownloadTestObserverTerminal(download_manager, num_downloads,
604 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
607 // Create a DownloadTestObserverInProgress that will wait for the
608 // specified number of downloads to start.
609 DownloadCreateObserver* CreateInProgressWaiter(
610 Shell* shell, int num_downloads) {
611 DownloadManager* download_manager = DownloadManagerForShell(shell);
612 return new DownloadCreateObserver(download_manager);
615 DownloadTestObserver* CreateInterruptedWaiter(
616 Shell* shell, int num_downloads) {
617 DownloadManager* download_manager = DownloadManagerForShell(shell);
618 return new DownloadTestObserverInterrupted(download_manager, num_downloads,
619 DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
622 // Note: Cannot be used with other alternative DownloadFileFactorys
623 void SetupEnsureNoPendingDownloads() {
624 DownloadManagerForShell(shell())->SetDownloadFileFactoryForTesting(
625 scoped_ptr<DownloadFileFactory>(
626 new CountingDownloadFileFactory()).Pass());
629 bool EnsureNoPendingDownloads() {
631 BrowserThread::PostTask(
632 BrowserThread::IO, FROM_HERE,
633 base::Bind(&EnsureNoPendingDownloadJobsOnIO, &result));
634 base::MessageLoop::current()->Run();
636 (CountingDownloadFile::GetNumberActiveFilesFromFileThread() == 0);
639 void NavigateToURLAndWaitForDownload(
642 DownloadItem::DownloadState expected_terminal_state) {
643 scoped_ptr<DownloadTestObserver> observer(CreateWaiter(shell, 1));
644 NavigateToURL(shell, url);
645 observer->WaitForFinished();
646 EXPECT_EQ(1u, observer->NumDownloadsSeenInState(expected_terminal_state));
649 // Checks that |path| is has |file_size| bytes, and matches the |value|
651 bool VerifyFile(const base::FilePath& path,
652 const std::string& value,
653 const int64 file_size) {
654 std::string file_contents;
656 bool read = base::ReadFileToString(path, &file_contents);
657 EXPECT_TRUE(read) << "Failed reading file: " << path.value() << std::endl;
659 return false; // Couldn't read the file.
661 // Note: we don't handle really large files (more than size_t can hold)
662 // so we will fail in that case.
663 size_t expected_size = static_cast<size_t>(file_size);
666 EXPECT_EQ(expected_size, file_contents.size());
667 if (expected_size != file_contents.size())
670 // Check the contents.
671 EXPECT_EQ(value, file_contents);
672 if (memcmp(file_contents.c_str(), value.c_str(), expected_size) != 0)
678 // Start a download and return the item.
679 DownloadItem* StartDownloadAndReturnItem(GURL url) {
680 scoped_ptr<DownloadCreateObserver> observer(
681 CreateInProgressWaiter(shell(), 1));
682 NavigateToURL(shell(), url);
683 observer->WaitForFinished();
684 std::vector<DownloadItem*> downloads;
685 DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
686 EXPECT_EQ(1u, downloads.size());
687 if (1u != downloads.size())
693 void WaitForData(DownloadItem* download, int size) {
694 DownloadUpdatedObserver data_observer(
695 download, base::Bind(&DataReceivedFilter, size));
696 data_observer.WaitForEvent();
697 ASSERT_EQ(size, download->GetReceivedBytes());
698 ASSERT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
701 // Tell the test server to release a pending RST and confirm
702 // that the interrupt is received properly (for download resumption
704 void ReleaseRSTAndConfirmInterruptForResume(DownloadItem* download) {
705 scoped_ptr<DownloadTestObserver> rst_observer(
706 CreateInterruptedWaiter(shell(), 1));
707 NavigateToURL(shell(), test_server()->GetURL("download-finish"));
708 rst_observer->WaitForFinished();
709 EXPECT_EQ(DownloadItem::INTERRUPTED, download->GetState());
712 // Confirm file status expected for the given location in a stream
713 // provided by the resume test server.
714 void ConfirmFileStatusForResume(
715 DownloadItem* download, bool file_exists,
716 int received_bytes, int total_bytes,
717 const base::FilePath& expected_filename) {
718 // expected_filename is only known if the file exists.
719 ASSERT_EQ(file_exists, !expected_filename.empty());
720 EXPECT_EQ(received_bytes, download->GetReceivedBytes());
721 EXPECT_EQ(total_bytes, download->GetTotalBytes());
722 EXPECT_EQ(expected_filename.value(),
723 download->GetFullPath().BaseName().value());
724 EXPECT_EQ(file_exists,
725 (!download->GetFullPath().empty() &&
726 base::PathExists(download->GetFullPath())));
729 std::string file_contents;
730 EXPECT_TRUE(base::ReadFileToString(
731 download->GetFullPath(), &file_contents));
733 ASSERT_EQ(static_cast<size_t>(received_bytes), file_contents.size());
734 for (int i = 0; i < received_bytes; ++i) {
735 EXPECT_EQ(static_cast<char>((i * 2 + 15) % 256), file_contents[i])
736 << "File contents diverged at position " << i
737 << " for " << expected_filename.value();
739 if (static_cast<char>((i * 2 + 15) % 256) != file_contents[i])
746 static void EnsureNoPendingDownloadJobsOnIO(bool* result) {
747 if (URLRequestSlowDownloadJob::NumberOutstandingRequests())
749 BrowserThread::PostTask(
750 BrowserThread::UI, FROM_HERE, base::MessageLoop::QuitClosure());
753 // Location of the downloads directory for these tests
754 base::ScopedTempDir downloads_directory_;
755 scoped_ptr<TestShellDownloadManagerDelegate> test_delegate_;
758 IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadCancelled) {
759 SetupEnsureNoPendingDownloads();
761 // Create a download, wait until it's started, and confirm
762 // we're in the expected state.
763 scoped_ptr<DownloadCreateObserver> observer(
764 CreateInProgressWaiter(shell(), 1));
765 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl));
766 observer->WaitForFinished();
768 std::vector<DownloadItem*> downloads;
769 DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
770 ASSERT_EQ(1u, downloads.size());
771 ASSERT_EQ(DownloadItem::IN_PROGRESS, downloads[0]->GetState());
773 // Cancel the download and wait for download system quiesce.
774 downloads[0]->Cancel(true);
775 scoped_refptr<DownloadTestFlushObserver> flush_observer(
776 new DownloadTestFlushObserver(DownloadManagerForShell(shell())));
777 flush_observer->WaitForFlush();
779 // Get the important info from other threads and check it.
780 EXPECT_TRUE(EnsureNoPendingDownloads());
783 // Check that downloading multiple (in this case, 2) files does not result in
785 IN_PROC_BROWSER_TEST_F(DownloadContentTest, MultiDownload) {
786 SetupEnsureNoPendingDownloads();
788 // Create a download, wait until it's started, and confirm
789 // we're in the expected state.
790 scoped_ptr<DownloadCreateObserver> observer1(
791 CreateInProgressWaiter(shell(), 1));
792 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl));
793 observer1->WaitForFinished();
795 std::vector<DownloadItem*> downloads;
796 DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
797 ASSERT_EQ(1u, downloads.size());
798 ASSERT_EQ(DownloadItem::IN_PROGRESS, downloads[0]->GetState());
799 DownloadItem* download1 = downloads[0]; // The only download.
801 // Start the second download and wait until it's done.
802 base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
803 GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
804 // Download the file and wait.
805 NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE);
807 // Should now have 2 items on the manager.
809 DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
810 ASSERT_EQ(2u, downloads.size());
811 // We don't know the order of the downloads.
812 DownloadItem* download2 = downloads[(download1 == downloads[0]) ? 1 : 0];
814 ASSERT_EQ(DownloadItem::IN_PROGRESS, download1->GetState());
815 ASSERT_EQ(DownloadItem::COMPLETE, download2->GetState());
817 // Allow the first request to finish.
818 scoped_ptr<DownloadTestObserver> observer2(CreateWaiter(shell(), 1));
819 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kFinishDownloadUrl));
820 observer2->WaitForFinished(); // Wait for the third request.
821 EXPECT_EQ(1u, observer2->NumDownloadsSeenInState(DownloadItem::COMPLETE));
823 // Get the important info from other threads and check it.
824 EXPECT_TRUE(EnsureNoPendingDownloads());
826 // The |DownloadItem|s should now be done and have the final file names.
827 // Verify that the files have the expected data and size.
828 // |file1| should be full of '*'s, and |file2| should be the same as the
830 base::FilePath file1(download1->GetTargetFilePath());
831 size_t file_size1 = URLRequestSlowDownloadJob::kFirstDownloadSize +
832 URLRequestSlowDownloadJob::kSecondDownloadSize;
833 std::string expected_contents(file_size1, '*');
834 ASSERT_TRUE(VerifyFile(file1, expected_contents, file_size1));
836 base::FilePath file2(download2->GetTargetFilePath());
837 ASSERT_TRUE(base::ContentsEqual(
838 file2, GetTestFilePath("download", "download-test.lib")));
841 #if defined(ENABLE_PLUGINS)
842 // Content served with a MIME type of application/octet-stream should be
843 // downloaded even when a plugin can be found that handles the file type.
844 IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadOctetStream) {
845 const base::FilePath::CharType kTestFilePath[] =
846 FILE_PATH_LITERAL("octet-stream.abc");
847 const char kTestPluginName[] = "TestPlugin";
848 const char kTestMimeType[] = "application/x-test-mime-type";
849 const char kTestFileType[] = "abc";
851 WebPluginInfo plugin_info;
852 plugin_info.name = base::ASCIIToUTF16(kTestPluginName);
853 plugin_info.mime_types.push_back(
854 WebPluginMimeType(kTestMimeType, kTestFileType, ""));
855 PluginServiceImpl::GetInstance()->RegisterInternalPlugin(plugin_info, false);
857 // The following is served with a Content-Type of application/octet-stream.
858 GURL url(URLRequestMockHTTPJob::GetMockUrl(base::FilePath(kTestFilePath)));
859 NavigateToURLAndWaitForDownload(shell(), url, DownloadItem::COMPLETE);
863 // Try to cancel just before we release the download file, by delaying final
865 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelAtFinalRename) {
866 // Setup new factory.
867 DownloadFileWithDelayFactory* file_factory =
868 new DownloadFileWithDelayFactory();
869 DownloadManagerImpl* download_manager(DownloadManagerForShell(shell()));
870 download_manager->SetDownloadFileFactoryForTesting(
871 scoped_ptr<DownloadFileFactory>(file_factory).Pass());
874 base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
875 NavigateToURL(shell(), URLRequestMockHTTPJob::GetMockUrl(file));
877 // Wait until the first (intermediate file) rename and execute the callback.
878 file_factory->WaitForSomeCallback();
879 std::vector<base::Closure> callbacks;
880 file_factory->GetAllRenameCallbacks(&callbacks);
881 ASSERT_EQ(1u, callbacks.size());
885 // Wait until the second (final) rename callback is posted.
886 file_factory->WaitForSomeCallback();
887 file_factory->GetAllRenameCallbacks(&callbacks);
888 ASSERT_EQ(1u, callbacks.size());
891 std::vector<DownloadItem*> items;
892 download_manager->GetAllDownloads(&items);
893 ASSERT_EQ(1u, items.size());
894 items[0]->Cancel(true);
895 RunAllPendingInMessageLoop();
898 EXPECT_EQ(DownloadItem::CANCELLED, items[0]->GetState());
900 // Run final rename callback.
905 EXPECT_EQ(DownloadItem::CANCELLED, items[0]->GetState());
908 // Try to cancel just after we release the download file, by delaying
909 // in ShouldOpenDownload.
910 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelAtRelease) {
911 DownloadManagerImpl* download_manager(DownloadManagerForShell(shell()));
913 // Mark delegate for delayed open.
914 GetDownloadManagerDelegate()->SetDelayedOpen(true);
916 // Setup new factory.
917 DownloadFileWithDelayFactory* file_factory =
918 new DownloadFileWithDelayFactory();
919 download_manager->SetDownloadFileFactoryForTesting(
920 scoped_ptr<DownloadFileFactory>(file_factory).Pass());
923 base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
924 NavigateToURL(shell(), URLRequestMockHTTPJob::GetMockUrl(file));
926 // Wait until the first (intermediate file) rename and execute the callback.
927 file_factory->WaitForSomeCallback();
928 std::vector<base::Closure> callbacks;
929 file_factory->GetAllRenameCallbacks(&callbacks);
930 ASSERT_EQ(1u, callbacks.size());
934 // Wait until the second (final) rename callback is posted.
935 file_factory->WaitForSomeCallback();
936 file_factory->GetAllRenameCallbacks(&callbacks);
937 ASSERT_EQ(1u, callbacks.size());
943 // Confirm download still IN_PROGRESS (internal state COMPLETING).
944 std::vector<DownloadItem*> items;
945 download_manager->GetAllDownloads(&items);
946 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
948 // Cancel the download; confirm cancel fails.
949 ASSERT_EQ(1u, items.size());
950 items[0]->Cancel(true);
951 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
953 // Need to complete open test.
954 std::vector<DownloadOpenDelayedCallback> delayed_callbacks;
955 GetDownloadManagerDelegate()->GetDelayedCallbacks(
957 ASSERT_EQ(1u, delayed_callbacks.size());
958 delayed_callbacks[0].Run(true);
960 // *Now* the download should be complete.
961 EXPECT_EQ(DownloadItem::COMPLETE, items[0]->GetState());
964 // Try to shutdown with a download in progress to make sure shutdown path
966 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownInProgress) {
967 // Create a download that won't complete.
968 scoped_ptr<DownloadCreateObserver> observer(
969 CreateInProgressWaiter(shell(), 1));
970 NavigateToURL(shell(), GURL(URLRequestSlowDownloadJob::kUnknownSizeUrl));
971 observer->WaitForFinished();
974 std::vector<DownloadItem*> items;
975 DownloadManagerForShell(shell())->GetAllDownloads(&items);
976 ASSERT_EQ(1u, items.size());
977 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
979 // Shutdown the download manager and make sure we get the right
980 // notifications in the right order.
981 StrictMock<MockDownloadItemObserver> item_observer;
982 items[0]->AddObserver(&item_observer);
983 MockDownloadManagerObserver manager_observer(
984 DownloadManagerForShell(shell()));
985 // Don't care about ModelChanged() events.
986 EXPECT_CALL(manager_observer, ModelChanged(_))
987 .WillRepeatedly(Return());
989 InSequence notifications;
991 EXPECT_CALL(manager_observer, MockManagerGoingDown(
992 DownloadManagerForShell(shell())))
994 EXPECT_CALL(item_observer, OnDownloadUpdated(
996 Property(&DownloadItem::GetState, DownloadItem::CANCELLED))))
998 EXPECT_CALL(item_observer, OnDownloadDestroyed(items[0]))
1002 // See http://crbug.com/324525. If we have a refcount release/post task
1003 // race, the second post will stall the IO thread long enough so that we'll
1004 // lose the race and crash. The first stall is just to give the UI thread
1005 // a chance to get the second stall onto the IO thread queue after the cancel
1006 // message created by Shutdown and before the notification callback
1007 // created by the IO thread in canceling the request.
1008 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
1009 base::Bind(&base::PlatformThread::Sleep,
1010 base::TimeDelta::FromMilliseconds(25)));
1011 DownloadManagerForShell(shell())->Shutdown();
1012 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
1013 base::Bind(&base::PlatformThread::Sleep,
1014 base::TimeDelta::FromMilliseconds(25)));
1018 // Try to shutdown just after we release the download file, by delaying
1020 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownAtRelease) {
1021 DownloadManagerImpl* download_manager(DownloadManagerForShell(shell()));
1023 // Mark delegate for delayed open.
1024 GetDownloadManagerDelegate()->SetDelayedOpen(true);
1026 // Setup new factory.
1027 DownloadFileWithDelayFactory* file_factory =
1028 new DownloadFileWithDelayFactory();
1029 download_manager->SetDownloadFileFactoryForTesting(
1030 scoped_ptr<DownloadFileFactory>(file_factory).Pass());
1032 // Create a download
1033 base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
1034 NavigateToURL(shell(), URLRequestMockHTTPJob::GetMockUrl(file));
1036 // Wait until the first (intermediate file) rename and execute the callback.
1037 file_factory->WaitForSomeCallback();
1038 std::vector<base::Closure> callbacks;
1039 file_factory->GetAllRenameCallbacks(&callbacks);
1040 ASSERT_EQ(1u, callbacks.size());
1044 // Wait until the second (final) rename callback is posted.
1045 file_factory->WaitForSomeCallback();
1046 file_factory->GetAllRenameCallbacks(&callbacks);
1047 ASSERT_EQ(1u, callbacks.size());
1053 // Confirm download isn't complete yet.
1054 std::vector<DownloadItem*> items;
1055 DownloadManagerForShell(shell())->GetAllDownloads(&items);
1056 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
1058 // Cancel the download; confirm cancel fails anyway.
1059 ASSERT_EQ(1u, items.size());
1060 items[0]->Cancel(true);
1061 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
1062 RunAllPendingInMessageLoop();
1063 EXPECT_EQ(DownloadItem::IN_PROGRESS, items[0]->GetState());
1065 MockDownloadItemObserver observer;
1066 items[0]->AddObserver(&observer);
1067 EXPECT_CALL(observer, OnDownloadDestroyed(items[0]));
1069 // Shutdown the download manager. Mostly this is confirming a lack of
1071 DownloadManagerForShell(shell())->Shutdown();
1074 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeInterruptedDownload) {
1075 CommandLine::ForCurrentProcess()->AppendSwitch(
1076 switches::kEnableDownloadResumption);
1077 ASSERT_TRUE(test_server()->Start());
1079 GURL url = test_server()->GetURL(
1080 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1081 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1083 MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell()));
1084 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
1086 DownloadItem* download(StartDownloadAndReturnItem(url));
1087 WaitForData(download, GetSafeBufferChunk());
1088 ::testing::Mock::VerifyAndClearExpectations(&dm_observer);
1090 // Confirm resumption while in progress doesn't do anything.
1092 ASSERT_EQ(GetSafeBufferChunk(), download->GetReceivedBytes());
1093 ASSERT_EQ(DownloadItem::IN_PROGRESS, download->GetState());
1095 // Tell the server to send the RST and confirm the interrupt happens.
1096 ReleaseRSTAndConfirmInterruptForResume(download);
1097 ConfirmFileStatusForResume(
1098 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1099 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1101 // Resume, confirming received bytes on resumption is correct.
1102 // Make sure no creation calls are included.
1103 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(0);
1104 int initial_size = 0;
1105 DownloadUpdatedObserver initial_size_observer(
1106 download, base::Bind(&InitialSizeFilter, &initial_size));
1108 initial_size_observer.WaitForEvent();
1109 EXPECT_EQ(GetSafeBufferChunk(), initial_size);
1110 ::testing::Mock::VerifyAndClearExpectations(&dm_observer);
1112 // and wait for expected data.
1113 WaitForData(download, GetSafeBufferChunk() * 2);
1115 // Tell the server to send the RST and confirm the interrupt happens.
1116 ReleaseRSTAndConfirmInterruptForResume(download);
1117 ConfirmFileStatusForResume(
1118 download, true, GetSafeBufferChunk() * 2, GetSafeBufferChunk() * 3,
1119 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1121 // Resume and wait for completion.
1122 DownloadUpdatedObserver completion_observer(
1123 download, base::Bind(DownloadCompleteFilter));
1125 completion_observer.WaitForEvent();
1127 ConfirmFileStatusForResume(
1128 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1129 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1131 // Confirm resumption while complete doesn't do anything.
1133 ASSERT_EQ(GetSafeBufferChunk() * 3, download->GetReceivedBytes());
1134 ASSERT_EQ(DownloadItem::COMPLETE, download->GetState());
1135 RunAllPendingInMessageLoop();
1136 ASSERT_EQ(GetSafeBufferChunk() * 3, download->GetReceivedBytes());
1137 ASSERT_EQ(DownloadItem::COMPLETE, download->GetState());
1140 // Confirm restart fallback happens if a range request is bounced.
1141 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeInterruptedDownloadNoRange) {
1142 CommandLine::ForCurrentProcess()->AppendSwitch(
1143 switches::kEnableDownloadResumption);
1144 ASSERT_TRUE(test_server()->Start());
1146 // Auto-restart if server doesn't handle ranges.
1147 GURL url = test_server()->GetURL(
1149 // First download hits an RST, rest don't, no ranges.
1150 "rangereset?size=%d&rst_boundary=%d&"
1151 "token=NoRange&rst_limit=1&bounce_range",
1152 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1154 // Start the download and wait for first data chunk.
1155 DownloadItem* download(StartDownloadAndReturnItem(url));
1156 WaitForData(download, GetSafeBufferChunk());
1158 RecordingDownloadObserver recorder(download);
1160 ReleaseRSTAndConfirmInterruptForResume(download);
1161 ConfirmFileStatusForResume(
1162 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1163 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1165 DownloadUpdatedObserver completion_observer(
1166 download, base::Bind(DownloadCompleteFilter));
1168 completion_observer.WaitForEvent();
1170 ConfirmFileStatusForResume(
1171 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1172 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1174 static const RecordingDownloadObserver::RecordStruct expected_record[] = {
1176 {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
1177 // Starting continuation
1178 {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()},
1179 // Notification of receiving whole file.
1180 {DownloadItem::IN_PROGRESS, 0},
1182 {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
1185 recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
1188 // Confirm restart fallback happens if a precondition is failed.
1189 IN_PROC_BROWSER_TEST_F(DownloadContentTest,
1190 ResumeInterruptedDownloadBadPrecondition) {
1191 CommandLine::ForCurrentProcess()->AppendSwitch(
1192 switches::kEnableDownloadResumption);
1193 ASSERT_TRUE(test_server()->Start());
1195 GURL url = test_server()->GetURL(base::StringPrintf(
1196 // First download hits an RST, rest don't, precondition fail.
1197 "rangereset?size=%d&rst_boundary=%d&"
1198 "token=BadPrecondition&rst_limit=1&fail_precondition=2",
1199 GetSafeBufferChunk() * 3,
1200 GetSafeBufferChunk()));
1202 // Start the download and wait for first data chunk.
1203 DownloadItem* download(StartDownloadAndReturnItem(url));
1204 WaitForData(download, GetSafeBufferChunk());
1206 RecordingDownloadObserver recorder(download);
1208 ReleaseRSTAndConfirmInterruptForResume(download);
1209 ConfirmFileStatusForResume(
1210 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1211 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1212 EXPECT_EQ("BadPrecondition2", download->GetETag());
1214 DownloadUpdatedObserver completion_observer(
1215 download, base::Bind(DownloadCompleteFilter));
1217 completion_observer.WaitForEvent();
1219 ConfirmFileStatusForResume(
1220 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1221 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1222 EXPECT_EQ("BadPrecondition0", download->GetETag());
1224 static const RecordingDownloadObserver::RecordStruct expected_record[] = {
1226 {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
1227 // Starting continuation
1228 {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()},
1229 // Server precondition fail.
1230 {DownloadItem::INTERRUPTED, 0},
1231 // Notification of successful restart.
1232 {DownloadItem::IN_PROGRESS, 0},
1234 {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
1237 recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
1240 // Confirm we don't try to resume if we don't have a verifier.
1241 IN_PROC_BROWSER_TEST_F(DownloadContentTest,
1242 ResumeInterruptedDownloadNoVerifiers) {
1243 CommandLine::ForCurrentProcess()->AppendSwitch(
1244 switches::kEnableDownloadResumption);
1245 ASSERT_TRUE(test_server()->Start());
1247 GURL url = test_server()->GetURL(
1249 // First download hits an RST, rest don't, no verifiers.
1250 "rangereset?size=%d&rst_boundary=%d&"
1251 "token=NoRange&rst_limit=1&no_verifiers",
1252 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1254 // Start the download and wait for first data chunk.
1255 DownloadItem* download(StartDownloadAndReturnItem(url));
1256 WaitForData(download, GetSafeBufferChunk());
1258 RecordingDownloadObserver recorder(download);
1260 ReleaseRSTAndConfirmInterruptForResume(download);
1261 ConfirmFileStatusForResume(
1262 download, false, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1265 DownloadUpdatedObserver completion_observer(
1266 download, base::Bind(DownloadCompleteFilter));
1268 completion_observer.WaitForEvent();
1270 ConfirmFileStatusForResume(
1271 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1272 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1274 static const RecordingDownloadObserver::RecordStruct expected_record[] = {
1276 {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
1277 // Restart for lack of verifiers
1278 {DownloadItem::IN_PROGRESS, 0},
1280 {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
1283 recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
1286 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithDeletedFile) {
1287 CommandLine::ForCurrentProcess()->AppendSwitch(
1288 switches::kEnableDownloadResumption);
1289 ASSERT_TRUE(test_server()->Start());
1291 GURL url = test_server()->GetURL(
1293 // First download hits an RST, rest don't
1294 "rangereset?size=%d&rst_boundary=%d&"
1295 "token=NoRange&rst_limit=1",
1296 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1298 // Start the download and wait for first data chunk.
1299 DownloadItem* download(StartDownloadAndReturnItem(url));
1300 WaitForData(download, GetSafeBufferChunk());
1302 RecordingDownloadObserver recorder(download);
1304 ReleaseRSTAndConfirmInterruptForResume(download);
1305 ConfirmFileStatusForResume(
1306 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1307 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1309 // Delete the intermediate file.
1310 base::DeleteFile(download->GetFullPath(), false);
1312 DownloadUpdatedObserver completion_observer(
1313 download, base::Bind(DownloadCompleteFilter));
1315 completion_observer.WaitForEvent();
1317 ConfirmFileStatusForResume(
1318 download, true, GetSafeBufferChunk() * 3, GetSafeBufferChunk() * 3,
1319 base::FilePath(FILE_PATH_LITERAL("rangereset")));
1321 static const RecordingDownloadObserver::RecordStruct expected_record[] = {
1323 {DownloadItem::INTERRUPTED, GetSafeBufferChunk()},
1324 // Starting continuation
1325 {DownloadItem::IN_PROGRESS, GetSafeBufferChunk()},
1326 // Error because file isn't there.
1327 {DownloadItem::INTERRUPTED, 0},
1329 {DownloadItem::IN_PROGRESS, 0},
1331 {DownloadItem::COMPLETE, GetSafeBufferChunk() * 3},
1334 recorder.CompareToExpectedRecord(expected_record, arraysize(expected_record));
1337 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithFileInitError) {
1338 CommandLine::ForCurrentProcess()->AppendSwitch(
1339 switches::kEnableDownloadResumption);
1340 base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
1341 GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
1343 // Setup the error injector.
1344 scoped_refptr<TestFileErrorInjector> injector(
1345 TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
1347 TestFileErrorInjector::FileErrorInfo err = {
1349 TestFileErrorInjector::FILE_OPERATION_INITIALIZE,
1351 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
1353 injector->AddError(err);
1354 injector->InjectErrors();
1356 // Start and watch for interrupt.
1357 scoped_ptr<DownloadTestObserver> int_observer(
1358 CreateInterruptedWaiter(shell(), 1));
1359 DownloadItem* download(StartDownloadAndReturnItem(url));
1360 int_observer->WaitForFinished();
1361 ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState());
1362 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE,
1363 download->GetLastReason());
1364 EXPECT_EQ(0, download->GetReceivedBytes());
1365 EXPECT_TRUE(download->GetFullPath().empty());
1366 EXPECT_TRUE(download->GetTargetFilePath().empty());
1368 // We need to make sure that any cross-thread downloads communication has
1369 // quiesced before clearing and injecting the new errors, as the
1370 // InjectErrors() routine alters the currently in use download file
1371 // factory, which is a file thread object.
1372 RunAllPendingInMessageLoop(BrowserThread::FILE);
1373 RunAllPendingInMessageLoop();
1375 // Clear the old errors list.
1376 injector->ClearErrors();
1377 injector->InjectErrors();
1379 // Resume and watch completion.
1380 DownloadUpdatedObserver completion_observer(
1381 download, base::Bind(DownloadCompleteFilter));
1383 completion_observer.WaitForEvent();
1384 EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE);
1387 IN_PROC_BROWSER_TEST_F(DownloadContentTest,
1388 ResumeWithFileIntermediateRenameError) {
1389 CommandLine::ForCurrentProcess()->AppendSwitch(
1390 switches::kEnableDownloadResumption);
1391 base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
1392 GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
1394 // Setup the error injector.
1395 scoped_refptr<TestFileErrorInjector> injector(
1396 TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
1398 TestFileErrorInjector::FileErrorInfo err = {
1400 TestFileErrorInjector::FILE_OPERATION_RENAME_UNIQUIFY,
1402 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
1404 injector->AddError(err);
1405 injector->InjectErrors();
1407 // Start and watch for interrupt.
1408 scoped_ptr<DownloadTestObserver> int_observer(
1409 CreateInterruptedWaiter(shell(), 1));
1410 DownloadItem* download(StartDownloadAndReturnItem(url));
1411 int_observer->WaitForFinished();
1412 ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState());
1413 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE,
1414 download->GetLastReason());
1415 EXPECT_TRUE(download->GetFullPath().empty());
1416 // Target path will have been set after file name determination. GetFullPath()
1417 // being empty is sufficient to signal that filename determination needs to be
1419 EXPECT_FALSE(download->GetTargetFilePath().empty());
1421 // We need to make sure that any cross-thread downloads communication has
1422 // quiesced before clearing and injecting the new errors, as the
1423 // InjectErrors() routine alters the currently in use download file
1424 // factory, which is a file thread object.
1425 RunAllPendingInMessageLoop(BrowserThread::FILE);
1426 RunAllPendingInMessageLoop();
1428 // Clear the old errors list.
1429 injector->ClearErrors();
1430 injector->InjectErrors();
1432 // Resume and watch completion.
1433 DownloadUpdatedObserver completion_observer(
1434 download, base::Bind(DownloadCompleteFilter));
1436 completion_observer.WaitForEvent();
1437 EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE);
1440 IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeWithFileFinalRenameError) {
1441 CommandLine::ForCurrentProcess()->AppendSwitch(
1442 switches::kEnableDownloadResumption);
1443 base::FilePath file(FILE_PATH_LITERAL("download-test.lib"));
1444 GURL url(URLRequestMockHTTPJob::GetMockUrl(file));
1446 // Setup the error injector.
1447 scoped_refptr<TestFileErrorInjector> injector(
1448 TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
1450 DownloadManagerForShell(shell())->RemoveAllDownloads();
1451 TestFileErrorInjector::FileErrorInfo err = {
1453 TestFileErrorInjector::FILE_OPERATION_RENAME_ANNOTATE,
1455 DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE
1457 injector->AddError(err);
1458 injector->InjectErrors();
1460 // Start and watch for interrupt.
1461 scoped_ptr<DownloadTestObserver> int_observer(
1462 CreateInterruptedWaiter(shell(), 1));
1463 DownloadItem* download(StartDownloadAndReturnItem(url));
1464 int_observer->WaitForFinished();
1465 ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState());
1466 EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE,
1467 download->GetLastReason());
1468 EXPECT_TRUE(download->GetFullPath().empty());
1469 // Target path should still be intact.
1470 EXPECT_FALSE(download->GetTargetFilePath().empty());
1472 // We need to make sure that any cross-thread downloads communication has
1473 // quiesced before clearing and injecting the new errors, as the
1474 // InjectErrors() routine alters the currently in use download file
1475 // factory, which is a file thread object.
1476 RunAllPendingInMessageLoop(BrowserThread::FILE);
1477 RunAllPendingInMessageLoop();
1479 // Clear the old errors list.
1480 injector->ClearErrors();
1481 injector->InjectErrors();
1483 // Resume and watch completion.
1484 DownloadUpdatedObserver completion_observer(
1485 download, base::Bind(DownloadCompleteFilter));
1487 completion_observer.WaitForEvent();
1488 EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE);
1491 // An interrupted download should remove the intermediate file when it is
1493 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelInterruptedDownload) {
1494 CommandLine::ForCurrentProcess()->AppendSwitch(
1495 switches::kEnableDownloadResumption);
1496 ASSERT_TRUE(test_server()->Start());
1498 GURL url1 = test_server()->GetURL(
1499 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1500 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1502 DownloadItem* download(StartDownloadAndReturnItem(url1));
1503 WaitForData(download, GetSafeBufferChunk());
1505 ReleaseRSTAndConfirmInterruptForResume(download);
1506 ConfirmFileStatusForResume(
1507 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1508 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1510 base::FilePath intermediate_path(download->GetFullPath());
1511 ASSERT_FALSE(intermediate_path.empty());
1512 EXPECT_TRUE(base::PathExists(intermediate_path));
1514 download->Cancel(true /* user_cancel */);
1515 RunAllPendingInMessageLoop(BrowserThread::FILE);
1516 RunAllPendingInMessageLoop();
1518 // The intermediate file should now be gone.
1519 EXPECT_FALSE(base::PathExists(intermediate_path));
1520 EXPECT_TRUE(download->GetFullPath().empty());
1523 IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveDownload) {
1524 CommandLine::ForCurrentProcess()->AppendSwitch(
1525 switches::kEnableDownloadResumption);
1526 ASSERT_TRUE(test_server()->Start());
1528 // An interrupted download should remove the intermediate file when it is
1531 GURL url1 = test_server()->GetURL(
1532 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1533 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1535 DownloadItem* download(StartDownloadAndReturnItem(url1));
1536 WaitForData(download, GetSafeBufferChunk());
1537 ReleaseRSTAndConfirmInterruptForResume(download);
1538 ConfirmFileStatusForResume(
1539 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1540 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1542 base::FilePath intermediate_path(download->GetFullPath());
1543 ASSERT_FALSE(intermediate_path.empty());
1544 EXPECT_TRUE(base::PathExists(intermediate_path));
1547 RunAllPendingInMessageLoop(BrowserThread::FILE);
1548 RunAllPendingInMessageLoop();
1550 // The intermediate file should now be gone.
1551 EXPECT_FALSE(base::PathExists(intermediate_path));
1554 // A completed download shouldn't delete the downloaded file when it is
1557 // Start the second download and wait until it's done.
1558 base::FilePath file2(FILE_PATH_LITERAL("download-test.lib"));
1559 GURL url2(URLRequestMockHTTPJob::GetMockUrl(file2));
1560 scoped_ptr<DownloadTestObserver> completion_observer(
1561 CreateWaiter(shell(), 1));
1562 DownloadItem* download(StartDownloadAndReturnItem(url2));
1563 completion_observer->WaitForFinished();
1565 // The target path should exist.
1566 base::FilePath target_path(download->GetTargetFilePath());
1567 EXPECT_TRUE(base::PathExists(target_path));
1569 RunAllPendingInMessageLoop(BrowserThread::FILE);
1570 RunAllPendingInMessageLoop();
1572 // The file should still exist.
1573 EXPECT_TRUE(base::PathExists(target_path));
1577 IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveResumingDownload) {
1578 SetupEnsureNoPendingDownloads();
1579 CommandLine::ForCurrentProcess()->AppendSwitch(
1580 switches::kEnableDownloadResumption);
1581 ASSERT_TRUE(test_server()->Start());
1583 GURL url = test_server()->GetURL(
1584 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1585 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1587 MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell()));
1588 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
1590 DownloadItem* download(StartDownloadAndReturnItem(url));
1591 WaitForData(download, GetSafeBufferChunk());
1592 ::testing::Mock::VerifyAndClearExpectations(&dm_observer);
1594 // Tell the server to send the RST and confirm the interrupt happens.
1595 ReleaseRSTAndConfirmInterruptForResume(download);
1596 ConfirmFileStatusForResume(
1597 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1598 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1600 base::FilePath intermediate_path(download->GetFullPath());
1601 ASSERT_FALSE(intermediate_path.empty());
1602 EXPECT_TRUE(base::PathExists(intermediate_path));
1604 // Resume and remove download. We expect only a single OnDownloadCreated()
1605 // call, and that's for the second download created below.
1606 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
1610 // The intermediate file should now be gone.
1611 RunAllPendingInMessageLoop(BrowserThread::FILE);
1612 RunAllPendingInMessageLoop();
1613 EXPECT_FALSE(base::PathExists(intermediate_path));
1615 // Start the second download and wait until it's done. The test server is
1616 // single threaded. The response to this download request should follow the
1617 // response to the previous resumption request.
1618 GURL url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x"));
1619 NavigateToURLAndWaitForDownload(shell(), url2, DownloadItem::COMPLETE);
1621 EXPECT_TRUE(EnsureNoPendingDownloads());
1624 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelResumingDownload) {
1625 SetupEnsureNoPendingDownloads();
1626 CommandLine::ForCurrentProcess()->AppendSwitch(
1627 switches::kEnableDownloadResumption);
1628 ASSERT_TRUE(test_server()->Start());
1630 GURL url = test_server()->GetURL(
1631 base::StringPrintf("rangereset?size=%d&rst_boundary=%d",
1632 GetSafeBufferChunk() * 3, GetSafeBufferChunk()));
1634 MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell()));
1635 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
1637 DownloadItem* download(StartDownloadAndReturnItem(url));
1638 WaitForData(download, GetSafeBufferChunk());
1639 ::testing::Mock::VerifyAndClearExpectations(&dm_observer);
1641 // Tell the server to send the RST and confirm the interrupt happens.
1642 ReleaseRSTAndConfirmInterruptForResume(download);
1643 ConfirmFileStatusForResume(
1644 download, true, GetSafeBufferChunk(), GetSafeBufferChunk() * 3,
1645 base::FilePath(FILE_PATH_LITERAL("rangereset.crdownload")));
1647 base::FilePath intermediate_path(download->GetFullPath());
1648 ASSERT_FALSE(intermediate_path.empty());
1649 EXPECT_TRUE(base::PathExists(intermediate_path));
1651 // Resume and cancel download. We expect only a single OnDownloadCreated()
1652 // call, and that's for the second download created below.
1653 EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
1655 download->Cancel(true);
1657 // The intermediate file should now be gone.
1658 RunAllPendingInMessageLoop(BrowserThread::FILE);
1659 RunAllPendingInMessageLoop();
1660 EXPECT_FALSE(base::PathExists(intermediate_path));
1661 EXPECT_TRUE(download->GetFullPath().empty());
1663 // Start the second download and wait until it's done. The test server is
1664 // single threaded. The response to this download request should follow the
1665 // response to the previous resumption request.
1666 GURL url2(test_server()->GetURL("rangereset?size=100&rst_limit=0&token=x"));
1667 NavigateToURLAndWaitForDownload(shell(), url2, DownloadItem::COMPLETE);
1669 EXPECT_TRUE(EnsureNoPendingDownloads());
1672 // Check that the cookie policy is correctly updated when downloading a file
1673 // that redirects cross origin.
1674 IN_PROC_BROWSER_TEST_F(DownloadContentTest, CookiePolicy) {
1675 ASSERT_TRUE(test_server()->Start());
1676 net::HostPortPair host_port = test_server()->host_port_pair();
1677 DCHECK_EQ(host_port.host(), std::string("127.0.0.1"));
1679 // Block third-party cookies.
1680 ShellNetworkDelegate::SetAcceptAllCookies(false);
1682 // |url| redirects to a different origin |download| which tries to set a
1684 std::string download(base::StringPrintf(
1685 "http://localhost:%d/set-cookie?A=B", host_port.port()));
1686 GURL url(test_server()->GetURL("server-redirect?" + download));
1688 // Download the file.
1689 SetupEnsureNoPendingDownloads();
1690 scoped_ptr<DownloadUrlParameters> dl_params(
1691 DownloadUrlParameters::FromWebContents(shell()->web_contents(), url));
1692 scoped_ptr<DownloadTestObserver> observer(CreateWaiter(shell(), 1));
1693 DownloadManagerForShell(shell())->DownloadUrl(dl_params.Pass());
1694 observer->WaitForFinished();
1696 // Get the important info from other threads and check it.
1697 EXPECT_TRUE(EnsureNoPendingDownloads());
1699 std::vector<DownloadItem*> downloads;
1700 DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
1701 ASSERT_EQ(1u, downloads.size());
1702 ASSERT_EQ(DownloadItem::COMPLETE, downloads[0]->GetState());
1704 // Check that the cookies were correctly set.
1706 content::GetCookies(shell()->web_contents()->GetBrowserContext(),
1710 // A filename suggestion specified via a @download attribute should not be
1711 // effective if the final download URL is in another origin from the original
1713 IN_PROC_BROWSER_TEST_F(DownloadContentTest,
1714 DownloadAttributeCrossOriginRedirect) {
1715 EmbeddedTestServer origin_one;
1716 EmbeddedTestServer origin_two;
1717 ASSERT_TRUE(origin_one.InitializeAndWaitUntilReady());
1718 ASSERT_TRUE(origin_two.InitializeAndWaitUntilReady());
1720 // The download-attribute.html page contains an anchor element whose href is
1721 // set to the value of the query parameter (specified as |target| in the URL
1722 // below). The suggested filename for the anchor is 'suggested-filename'. When
1723 // the page is loaded, a script simulates a click on the anchor, triggering a
1724 // download of the target URL.
1726 // We construct two test servers; origin_one and origin_two. Once started, the
1727 // server URLs will differ by the port number. Therefore they will be in
1728 // different origins.
1729 GURL download_url = origin_one.GetURL("/ping");
1730 GURL referrer_url = origin_one.GetURL(
1731 std::string("/download-attribute.html?target=") + download_url.spec());
1733 // <origin_one>/download-attribute.html initiates a download of
1734 // <origin_one>/ping, which redirects to <origin_two>/download.
1735 origin_one.ServeFilesFromDirectory(GetTestFilePath("download", ""));
1736 origin_one.RegisterRequestHandler(
1737 CreateRedirectHandler("/ping", origin_two.GetURL("/download")));
1738 origin_two.RegisterRequestHandler(CreateBasicResponseHandler(
1739 "/download", "application/octet-stream", "Hello"));
1741 NavigateToURLAndWaitForDownload(
1742 shell(), referrer_url, DownloadItem::COMPLETE);
1744 std::vector<DownloadItem*> downloads;
1745 DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
1746 ASSERT_EQ(1u, downloads.size());
1748 EXPECT_EQ(FILE_PATH_LITERAL("download"),
1749 downloads[0]->GetTargetFilePath().BaseName().value());
1750 ASSERT_TRUE(origin_one.ShutdownAndWaitUntilComplete());
1751 ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete());
1754 // A filename suggestion specified via a @download attribute should be effective
1755 // if the final download URL is in the same origin as the initial download URL.
1756 // Test that this holds even if there are cross origin redirects in the middle
1757 // of the redirect chain.
1758 IN_PROC_BROWSER_TEST_F(DownloadContentTest,
1759 DownloadAttributeSameOriginRedirect) {
1760 EmbeddedTestServer origin_one;
1761 EmbeddedTestServer origin_two;
1762 ASSERT_TRUE(origin_one.InitializeAndWaitUntilReady());
1763 ASSERT_TRUE(origin_two.InitializeAndWaitUntilReady());
1765 // The download-attribute.html page contains an anchor element whose href is
1766 // set to the value of the query parameter (specified as |target| in the URL
1767 // below). The suggested filename for the anchor is 'suggested-filename'. When
1768 // the page is loaded, a script simulates a click on the anchor, triggering a
1769 // download of the target URL.
1771 // We construct two test servers; origin_one and origin_two. Once started, the
1772 // server URLs will differ by the port number. Therefore they will be in
1773 // different origins.
1774 GURL download_url = origin_one.GetURL("/ping");
1775 GURL referrer_url = origin_one.GetURL(
1776 std::string("/download-attribute.html?target=") + download_url.spec());
1777 origin_one.ServeFilesFromDirectory(GetTestFilePath("download", ""));
1779 // <origin_one>/download-attribute.html initiates a download of
1780 // <origin_one>/ping, which redirects to <origin_two>/pong, and then finally
1781 // to <origin_one>/download.
1782 origin_one.RegisterRequestHandler(
1783 CreateRedirectHandler("/ping", origin_two.GetURL("/pong")));
1784 origin_two.RegisterRequestHandler(
1785 CreateRedirectHandler("/pong", origin_one.GetURL("/download")));
1786 origin_one.RegisterRequestHandler(CreateBasicResponseHandler(
1787 "/download", "application/octet-stream", "Hello"));
1789 NavigateToURLAndWaitForDownload(
1790 shell(), referrer_url, DownloadItem::COMPLETE);
1792 std::vector<DownloadItem*> downloads;
1793 DownloadManagerForShell(shell())->GetAllDownloads(&downloads);
1794 ASSERT_EQ(1u, downloads.size());
1796 EXPECT_EQ(FILE_PATH_LITERAL("suggested-filename"),
1797 downloads[0]->GetTargetFilePath().BaseName().value());
1798 ASSERT_TRUE(origin_one.ShutdownAndWaitUntilComplete());
1799 ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete());
1802 } // namespace content