Index: content/browser/download/download_item_impl_unittest.cc |
diff --git a/content/browser/download/download_item_impl_unittest.cc b/content/browser/download/download_item_impl_unittest.cc |
index 1291ce11350ca19f80de32eacc34b4a6c0c27790..7891b94b3cfd19eaad4fa25359cf53fd75d82f6a 100644 |
--- a/content/browser/download/download_item_impl_unittest.cc |
+++ b/content/browser/download/download_item_impl_unittest.cc |
@@ -5,6 +5,7 @@ |
#include "base/callback.h" |
#include "base/command_line.h" |
#include "base/message_loop/message_loop.h" |
+#include "base/run_loop.h" |
#include "base/stl_util.h" |
#include "base/threading/thread.h" |
#include "content/browser/byte_stream.h" |
@@ -14,12 +15,17 @@ |
#include "content/browser/download/download_item_impl_delegate.h" |
#include "content/browser/download/download_request_handle.h" |
#include "content/browser/download/mock_download_file.h" |
+#include "content/public/browser/browser_thread.h" |
#include "content/public/browser/download_destination_observer.h" |
#include "content/public/browser/download_interrupt_reasons.h" |
#include "content/public/browser/download_url_parameters.h" |
+#include "content/public/browser/site_instance.h" |
+#include "content/public/browser/web_contents.h" |
#include "content/public/common/content_switches.h" |
#include "content/public/test/mock_download_item.h" |
-#include "content/public/test/test_browser_thread.h" |
+#include "content/public/test/test_browser_context.h" |
+#include "content/public/test/test_browser_thread_bundle.h" |
+#include "content/public/test/web_contents_tester.h" |
#include "testing/gmock/include/gmock/gmock.h" |
#include "testing/gtest/include/gtest/gtest.h" |
@@ -92,9 +98,10 @@ class MockRequestHandle : public DownloadRequestHandleInterface { |
MOCK_CONST_METHOD0(DebugString, std::string()); |
}; |
-// Schedules a task to invoke the RenameCompletionCallback with |new_path| on |
-// the UI thread. Should only be used as the action for |
+// Schedules a task to invoke the DownloadFile::RenameCompletionCallback with |
+// |new_path| on the UI thread. Should only be used as the action for |
// MockDownloadFile::Rename as follows: |
+// |
// EXPECT_CALL(download_file, Rename*(_,_)) |
// .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE, |
// new_path)); |
@@ -104,6 +111,16 @@ ACTION_P2(ScheduleRenameCallback, interrupt_reason, new_path) { |
base::Bind(arg1, interrupt_reason, new_path)); |
} |
+// Schedules a task to invoke DownloadFile::InitializedCallback with |
+// |interrupt_reason| on the UI thread. Should be used as the action for |
+// MockDownloadFile::Initialize as follows: |
+// EXPECT_CALL(download_file, Initialize(_)) |
+// .WillOnce(ScheduleInitializeCallback(DOWNLOAD_INTERRUPT_REASON_NONE)); |
+ACTION_P(ScheduleInitializeCallback, interrupt_reason) { |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, base::Bind(arg0, interrupt_reason)); |
+} |
+ |
} // namespace |
class DownloadItemTest : public testing::Test { |
@@ -193,9 +210,14 @@ class DownloadItemTest : public testing::Test { |
}; |
DownloadItemTest() |
- : ui_thread_(BrowserThread::UI, &loop_), |
- file_thread_(BrowserThread::FILE, &loop_), |
- delegate_() { |
+ : delegate_(), |
+ next_download_id_(DownloadItem::kInvalidId + 1) { |
+ create_info_.reset(new DownloadCreateInfo()); |
+ create_info_->save_info = |
+ scoped_ptr<DownloadSaveInfo>(new DownloadSaveInfo()); |
+ create_info_->save_info->prompt_for_save_location = false; |
+ create_info_->url_chain.push_back(GURL()); |
+ create_info_->etag = "SomethingToSatisfyResumption"; |
} |
~DownloadItemTest() { |
@@ -205,7 +227,8 @@ class DownloadItemTest : public testing::Test { |
} |
virtual void TearDown() { |
- ui_thread_.DeprecatedGetThreadObject()->message_loop()->RunUntilIdle(); |
+ base::RunLoop run_loop; |
+ run_loop.RunUntilIdle(); |
STLDeleteElements(&allocated_downloads_); |
allocated_downloads_.clear(); |
} |
@@ -214,21 +237,11 @@ class DownloadItemTest : public testing::Test { |
// be torn down at the end of the test unless DestroyDownloadItem is |
// called. |
DownloadItemImpl* CreateDownloadItem() { |
- // Normally, the download system takes ownership of info, and is |
- // responsible for deleting it. In these unit tests, however, we |
- // don't call the function that deletes it, so we do so ourselves. |
- scoped_ptr<DownloadCreateInfo> info_; |
- |
- info_.reset(new DownloadCreateInfo()); |
- static uint32 next_id = DownloadItem::kInvalidId + 1; |
- info_->save_info = scoped_ptr<DownloadSaveInfo>(new DownloadSaveInfo()); |
- info_->save_info->prompt_for_save_location = false; |
- info_->url_chain.push_back(GURL()); |
- info_->etag = "SomethingToSatisfyResumption"; |
- |
- DownloadItemImpl* download = |
- new DownloadItemImpl( |
- &delegate_, next_id++, *(info_.get()), net::BoundNetLog()); |
+ create_info_->download_id = ++next_download_id_; |
+ DownloadItemImpl* download = new DownloadItemImpl(&delegate_, |
+ create_info_->download_id, |
+ *create_info_, |
+ net::BoundNetLog()); |
allocated_downloads_.insert(download); |
return download; |
} |
@@ -237,9 +250,8 @@ class DownloadItemTest : public testing::Test { |
MockDownloadFile* AddDownloadFileToDownloadItem( |
DownloadItemImpl* item, |
DownloadItemImplDelegate::DownloadTargetCallback *callback) { |
- MockDownloadFile* mock_download_file(new StrictMock<MockDownloadFile>); |
- scoped_ptr<DownloadFile> download_file(mock_download_file); |
- EXPECT_CALL(*mock_download_file, Initialize(_)); |
+ MockDownloadFile* mock_download_file = NULL; |
+ scoped_ptr<DownloadFile> download_file; |
if (callback) { |
// Save the callback. |
EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _)) |
@@ -249,10 +261,24 @@ class DownloadItemTest : public testing::Test { |
EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _)); |
} |
- scoped_ptr<DownloadRequestHandleInterface> request_handle( |
+ // Only create a DownloadFile if the request was successful. |
+ if (create_info_->interrupt_reason == DOWNLOAD_INTERRUPT_REASON_NONE) { |
+ mock_download_file = new StrictMock<MockDownloadFile>; |
+ download_file.reset(mock_download_file); |
+ EXPECT_CALL(*mock_download_file, Initialize(_)) |
+ .WillOnce(ScheduleInitializeCallback(DOWNLOAD_INTERRUPT_REASON_NONE)); |
+ EXPECT_CALL(*mock_download_file, FullPath()) |
+ .WillRepeatedly(Return(base::FilePath())); |
+ } |
+ |
+ scoped_ptr<MockRequestHandle> request_handle( |
new NiceMock<MockRequestHandle>); |
- item->Start(download_file.Pass(), request_handle.Pass()); |
- loop_.RunUntilIdle(); |
+ EXPECT_CALL(*request_handle, GetWebContents()) |
+ .WillRepeatedly(Return(GetWebContents())); |
+ item->Start(download_file.Pass(), |
+ request_handle.PassAs<DownloadRequestHandleInterface>(), |
+ *create_info_); |
+ base::RunLoop().RunUntilIdle(); |
// So that we don't have a function writing to a stack variable |
// lying around if the above failed. |
@@ -299,7 +325,7 @@ class DownloadItemTest : public testing::Test { |
if (expected_state == DownloadItem::IN_PROGRESS) { |
EXPECT_CALL(*download_file, Cancel()); |
item->Cancel(true); |
- loop_.RunUntilIdle(); |
+ base::RunLoop().RunUntilIdle(); |
} |
} |
@@ -310,7 +336,7 @@ class DownloadItemTest : public testing::Test { |
} |
void RunAllPendingInMessageLoops() { |
- loop_.RunUntilIdle(); |
+ base::RunLoop().RunUntilIdle(); |
} |
MockDelegate* mock_delegate() { |
@@ -322,12 +348,51 @@ class DownloadItemTest : public testing::Test { |
*return_path = path; |
} |
+ DownloadCreateInfo* create_info() { |
+ return create_info_.get(); |
+ } |
+ |
+ virtual WebContents* GetWebContents() { |
+ return NULL; |
+ } |
+ |
private: |
- base::MessageLoopForUI loop_; |
- TestBrowserThread ui_thread_; // UI thread |
- TestBrowserThread file_thread_; // FILE thread |
StrictMock<MockDelegate> delegate_; |
std::set<DownloadItem*> allocated_downloads_; |
+ scoped_ptr<DownloadCreateInfo> create_info_; |
+ uint32 next_download_id_; |
+ TestBrowserThreadBundle thread_bundle_; |
+}; |
+ |
+// Test fixture for resumption tests. These currently require a WebContents(). |
+// Therefore a TestBrowserContext() and a test WebContents() need to be created |
+// for these tests. |
+class DownloadItemTestWithResumption : public DownloadItemTest { |
+ public: |
+ virtual void SetUp() OVERRIDE { |
+ CommandLine::ForCurrentProcess()->AppendSwitch( |
+ switches::kEnableDownloadResumption); |
+ browser_context_.reset(new TestBrowserContext); |
+ scoped_refptr<SiteInstance> site_instance( |
+ SiteInstance::Create(browser_context_.get())); |
+ web_contents_.reset(WebContentsTester::CreateTestWebContents( |
+ browser_context_.get(), site_instance.get())); |
+ DownloadItemTest::SetUp(); |
+ } |
+ |
+ virtual void TearDown() OVERRIDE { |
+ web_contents_.reset(); |
+ browser_context_.reset(); |
+ DownloadItemTest::TearDown(); |
+ } |
+ |
+ virtual WebContents* GetWebContents() OVERRIDE { |
+ return web_contents_.get(); |
+ } |
+ |
+ private: |
+ scoped_ptr<TestBrowserContext> browser_context_; |
+ scoped_ptr<WebContents> web_contents_; |
}; |
// Tests to ensure calls that change a DownloadItem generate an update to |
@@ -408,10 +473,8 @@ TEST_F(DownloadItemTest, NotificationAfterDestroyed) { |
ASSERT_TRUE(observer.CheckDestroyed()); |
} |
-TEST_F(DownloadItemTest, ContinueAfterInterrupted) { |
- CommandLine::ForCurrentProcess()->AppendSwitch( |
- switches::kEnableDownloadResumption); |
- |
+// Test that a download is resumed automatcially after a continuable interrupt. |
+TEST_F(DownloadItemTestWithResumption, ContinueAfterInterrupted) { |
DownloadItemImpl* item = CreateDownloadItem(); |
MockObserver observer(item); |
DownloadItemImplDelegate::DownloadTargetCallback callback; |
@@ -422,12 +485,12 @@ TEST_F(DownloadItemTest, ContinueAfterInterrupted) { |
EXPECT_CALL(*download_file, FullPath()) |
.WillOnce(Return(base::FilePath())); |
EXPECT_CALL(*download_file, Detach()); |
+ EXPECT_CALL(*mock_delegate(), MockResumeInterruptedDownload(_, _)); |
item->DestinationObserverAsWeakPtr()->DestinationError( |
DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR); |
ASSERT_TRUE(observer.CheckUpdated()); |
- // Should attempt to auto-resume. Because we don't have a mock WebContents, |
- // ResumeInterruptedDownload() will abort early, with another interrupt, |
- // which will be ignored. |
+ // Should attempt to auto-resume. This is verified by the |
+ // MockResumeInterruptedDownload() test expectation above. |
ASSERT_EQ(1, observer.GetInterruptCount()); |
ASSERT_EQ(0, observer.GetResumeCount()); |
RunAllPendingInMessageLoops(); |
@@ -435,11 +498,9 @@ TEST_F(DownloadItemTest, ContinueAfterInterrupted) { |
CleanupItem(item, download_file, DownloadItem::INTERRUPTED); |
} |
-// Same as above, but with a non-continuable interrupt. |
-TEST_F(DownloadItemTest, RestartAfterInterrupted) { |
- CommandLine::ForCurrentProcess()->AppendSwitch( |
- switches::kEnableDownloadResumption); |
- |
+// Test that automatic resumption doesn't happen after a non-continuable |
+// interrupt. |
+TEST_F(DownloadItemTestWithResumption, RestartAfterInterrupted) { |
DownloadItemImpl* item = CreateDownloadItem(); |
MockObserver observer(item); |
DownloadItemImplDelegate::DownloadTargetCallback callback; |
@@ -490,68 +551,101 @@ TEST_F(DownloadItemTest, UnresumableInterrupt) { |
CleanupItem(item, download_file, DownloadItem::INTERRUPTED); |
} |
-TEST_F(DownloadItemTest, LimitRestartsAfterInterrupted) { |
- CommandLine::ForCurrentProcess()->AppendSwitch( |
- switches::kEnableDownloadResumption); |
- |
+// Test that automatic resumption only happens a limited number of times. The |
+// limit is currently hardcoded as DownloadItemImpl::kMaxAutoResumeAttempts. |
+TEST_F(DownloadItemTestWithResumption, LimitRestartsAfterInterrupted) { |
DownloadItemImpl* item = CreateDownloadItem(); |
- base::WeakPtr<DownloadDestinationObserver> as_observer( |
- item->DestinationObserverAsWeakPtr()); |
MockObserver observer(item); |
- MockDownloadFile* mock_download_file(NULL); |
- scoped_ptr<DownloadFile> download_file; |
- MockRequestHandle* mock_request_handle(NULL); |
- scoped_ptr<DownloadRequestHandleInterface> request_handle; |
- DownloadItemImplDelegate::DownloadTargetCallback callback; |
+ base::FilePath target_path(kDummyPath); |
+ base::FilePath intermediate_path(target_path.InsertBeforeExtensionASCII("x")); |
- EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _)) |
- .WillRepeatedly(SaveArg<1>(&callback)); |
for (int i = 0; i < (DownloadItemImpl::kMaxAutoResumeAttempts + 1); ++i) { |
DVLOG(20) << "Loop iteration " << i; |
- |
- mock_download_file = new NiceMock<MockDownloadFile>; |
- download_file.reset(mock_download_file); |
- mock_request_handle = new NiceMock<MockRequestHandle>; |
- request_handle.reset(mock_request_handle); |
- |
- ON_CALL(*mock_download_file, FullPath()) |
- .WillByDefault(Return(base::FilePath())); |
- |
- // It's too complicated to set up a WebContents instance that would cause |
- // the MockDownloadItemDelegate's ResumeInterruptedDownload() function |
- // to be callled, so we simply verify that GetWebContents() is called. |
- if (i < (DownloadItemImpl::kMaxAutoResumeAttempts - 1)) { |
- EXPECT_CALL(*mock_request_handle, GetWebContents()) |
- .WillRepeatedly(Return(static_cast<WebContents*>(NULL))); |
- } |
- |
- // Copied key parts of DoIntermediateRename & AddDownloadFileToDownloadItem |
- // to allow for holding onto the request handle. |
- item->Start(download_file.Pass(), request_handle.Pass()); |
- RunAllPendingInMessageLoops(); |
- if (i == 0) { |
- // Target determination is only done the first time through. |
- base::FilePath target_path(kDummyPath); |
- base::FilePath intermediate_path( |
- target_path.InsertBeforeExtensionASCII("x")); |
- EXPECT_CALL(*mock_download_file, RenameAndUniquify(intermediate_path, _)) |
+ DownloadItemImplDelegate::DownloadTargetCallback callback; |
+ MockDownloadFile* download_file = |
+ AddDownloadFileToDownloadItem(item, &callback); |
+ EXPECT_FALSE(callback.is_null()); |
+ if (i == 0) |
+ EXPECT_CALL(*download_file, RenameAndUniquify(intermediate_path, _)) |
.WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE, |
intermediate_path)); |
- callback.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE, |
- DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path); |
- RunAllPendingInMessageLoops(); |
- } |
- ASSERT_EQ(i, observer.GetResumeCount()); |
+ else |
+ EXPECT_EQ(intermediate_path, item->GetFullPath()); |
- // Use a continuable interrupt. |
+ callback.Run(target_path, |
+ DownloadItem::TARGET_DISPOSITION_OVERWRITE, |
+ DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, |
+ intermediate_path); |
+ RunAllPendingInMessageLoops(); |
+ ASSERT_EQ(i, observer.GetResumeCount()); |
+ EXPECT_CALL(*download_file, Detach()); |
+ // FILE_TRANSIENT_ERROR is a continuable interrupt that causes the download |
+ // to be resumed automatically. However, it should only attempt to resume if |
+ // the number of conesecutive automatic resumptions is less than |
+ // kMaxAutoResumeAttempts. |
+ EXPECT_CALL(*mock_delegate(), MockResumeInterruptedDownload(_, _)) |
+ .Times(i < DownloadItemImpl::kMaxAutoResumeAttempts ? 1 : 0); |
item->DestinationObserverAsWeakPtr()->DestinationError( |
DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR); |
- |
ASSERT_EQ(i + 1, observer.GetInterruptCount()); |
- ::testing::Mock::VerifyAndClearExpectations(mock_download_file); |
} |
+ EXPECT_EQ(DownloadItemImpl::kMaxAutoResumeAttempts, |
+ observer.GetResumeCount()); |
+} |
+ |
+// If the download attempts to resume and the resumption request fails, the |
+// subsequent Start() call shouldn't update the origin state (URL redirect |
+// chains, Content-Disposition, download URL, etc..) |
+TEST_F(DownloadItemTestWithResumption, |
+ FailedResumptionDoesntUpdateOriginState) { |
+ const char* kContentDisposition = "attachment; filename=foo"; |
+ const char* kFirstETag = "ABC"; |
+ const char* kFirstLastModified = "Yesterday"; |
+ const char* kFirstURL = "http://www.example.com/download"; |
+ create_info()->content_disposition = kContentDisposition; |
+ create_info()->etag = kFirstETag; |
+ create_info()->last_modified = kFirstLastModified; |
+ create_info()->url_chain.push_back(GURL(kFirstURL)); |
- CleanupItem(item, mock_download_file, DownloadItem::INTERRUPTED); |
+ DownloadItemImpl* item = CreateDownloadItem(); |
+ MockDownloadFile* download_file = |
+ DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS); |
+ EXPECT_EQ(kContentDisposition, item->GetContentDisposition()); |
+ EXPECT_EQ(kFirstETag, item->GetETag()); |
+ EXPECT_EQ(kFirstLastModified, item->GetLastModifiedTime()); |
+ EXPECT_EQ(kFirstURL, item->GetURL().spec()); |
+ |
+ EXPECT_CALL(*mock_delegate(), MockResumeInterruptedDownload(_, _)); |
+ EXPECT_CALL(*download_file, Detach()); |
+ item->DestinationObserverAsWeakPtr()->DestinationError( |
+ DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR); |
+ EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState()); |
+ |
+ // Now change the create info. The changes should not cause the DownloadItem |
+ // to be updated. |
+ const char* kSecondContentDisposition = "attachment; filename=bar"; |
+ const char* kSecondETag = "123"; |
+ const char* kSecondLastModified = "Today"; |
+ const char* kSecondURL = "http://example.com/another-download"; |
+ create_info()->content_disposition = kSecondContentDisposition; |
+ create_info()->etag = kSecondETag; |
+ create_info()->last_modified = kSecondLastModified; |
+ create_info()->url_chain.clear(); |
+ create_info()->url_chain.push_back(GURL(kSecondURL)); |
+ create_info()->interrupt_reason = DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED; |
+ |
+ // The following ends up calling DownloadItem::Start(), but shouldn't result |
+ // in an origin update. |
+ DownloadItemImplDelegate::DownloadTargetCallback download_target_callback; |
+ download_file = |
+ AddDownloadFileToDownloadItem(item, &download_target_callback); |
+ |
+ EXPECT_EQ(kContentDisposition, item->GetContentDisposition()); |
+ EXPECT_EQ(kFirstETag, item->GetETag()); |
+ EXPECT_EQ(kFirstLastModified, item->GetLastModifiedTime()); |
+ EXPECT_EQ(kFirstURL, item->GetURL().spec()); |
+ EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState()); |
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED, item->GetLastReason()); |
} |
TEST_F(DownloadItemTest, NotificationAfterRemove) { |
@@ -577,8 +671,7 @@ TEST_F(DownloadItemTest, NotificationAfterOnContentCheckCompleted) { |
EXPECT_TRUE(safe_observer.CheckUpdated()); |
// Setting to unsafe url or unsafe file should trigger a notification. |
- DownloadItemImpl* unsafeurl_item = |
- CreateDownloadItem(); |
+ DownloadItemImpl* unsafeurl_item = CreateDownloadItem(); |
MockObserver unsafeurl_observer(unsafeurl_item); |
unsafeurl_item->OnAllDataSaved(std::string()); |
@@ -589,8 +682,7 @@ TEST_F(DownloadItemTest, NotificationAfterOnContentCheckCompleted) { |
unsafeurl_item->ValidateDangerousDownload(); |
EXPECT_TRUE(unsafeurl_observer.CheckUpdated()); |
- DownloadItemImpl* unsafefile_item = |
- CreateDownloadItem(); |
+ DownloadItemImpl* unsafefile_item = CreateDownloadItem(); |
MockObserver unsafefile_observer(unsafefile_item); |
unsafefile_item->OnAllDataSaved(std::string()); |
@@ -643,7 +735,7 @@ TEST_F(DownloadItemTest, NotificationAfterTogglePause) { |
EXPECT_CALL(*mock_download_file, Initialize(_)); |
EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(_, _)); |
- item->Start(download_file.Pass(), request_handle.Pass()); |
+ item->Start(download_file.Pass(), request_handle.Pass(), *create_info()); |
item->Pause(); |
ASSERT_TRUE(observer.CheckUpdated()); |
@@ -690,12 +782,47 @@ TEST_F(DownloadItemTest, Start) { |
scoped_ptr<DownloadRequestHandleInterface> request_handle( |
new NiceMock<MockRequestHandle>); |
EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _)); |
- item->Start(download_file.Pass(), request_handle.Pass()); |
+ item->Start(download_file.Pass(), request_handle.Pass(), *create_info()); |
RunAllPendingInMessageLoops(); |
CleanupItem(item, mock_download_file, DownloadItem::IN_PROGRESS); |
} |
+// Handling of downloads initiated via a failed request. In this case, Start() |
+// will get called with a DownloadCreateInfo with a non-zero interrupt_reason. |
+TEST_F(DownloadItemTest, StartFailedDownload) { |
+ create_info()->interrupt_reason = DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED; |
+ DownloadItemImpl* item = CreateDownloadItem(); |
+ // The download is considered to be IN_PROGRESS even though there's an |
+ // interrupt reason. It will transition to INTERRUPTED once Start() is called. |
+ EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState()); |
+ |
+ // DownloadFile and DownloadRequestHandleInterface objects aren't created for |
+ // failed downloads. |
+ scoped_ptr<DownloadFile> null_download_file; |
+ scoped_ptr<DownloadRequestHandleInterface> null_request_handle; |
+ DownloadItemImplDelegate::DownloadTargetCallback download_target_callback; |
+ EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _)) |
+ .WillOnce(SaveArg<1>(&download_target_callback)); |
+ item->Start( |
+ null_download_file.Pass(), null_request_handle.Pass(), *create_info()); |
+ RunAllPendingInMessageLoops(); |
+ |
+ // The DownloadItemImpl should attempt to determine a target path even if the |
+ // download was interrupted. |
+ ASSERT_FALSE(download_target_callback.is_null()); |
+ ASSERT_EQ(DownloadItem::INTERRUPTED, item->GetState()); |
+ base::FilePath target_path(FILE_PATH_LITERAL("foo")); |
+ download_target_callback.Run(target_path, |
+ DownloadItem::TARGET_DISPOSITION_OVERWRITE, |
+ DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, |
+ target_path); |
+ RunAllPendingInMessageLoops(); |
+ |
+ EXPECT_EQ(target_path, item->GetTargetFilePath()); |
+ CleanupItem(item, NULL, DownloadItem::INTERRUPTED); |
+} |
+ |
// Test that the delegate is invoked after the download file is renamed. |
TEST_F(DownloadItemTest, CallbackAfterRename) { |
DownloadItemImpl* item = CreateDownloadItem(); |
@@ -812,9 +939,8 @@ TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Restart) { |
// As above. But if the download can be resumed by continuing, then the |
// intermediate path should be retained when the download is interrupted after |
// the intermediate rename succeeds. |
-TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Continue) { |
- CommandLine::ForCurrentProcess()->AppendSwitch( |
- switches::kEnableDownloadResumption); |
+TEST_F(DownloadItemTestWithResumption, |
+ InterruptedBeforeIntermediateRename_Continue) { |
DownloadItemImpl* item = CreateDownloadItem(); |
DownloadItemImplDelegate::DownloadTargetCallback callback; |
MockDownloadFile* download_file = |
@@ -847,9 +973,8 @@ TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Continue) { |
// As above. If the intermediate rename fails, then the interrupt reason should |
// be set to the destination error and the intermediate path should be empty. |
-TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Failed) { |
- CommandLine::ForCurrentProcess()->AppendSwitch( |
- switches::kEnableDownloadResumption); |
+TEST_F(DownloadItemTestWithResumption, |
+ InterruptedBeforeIntermediateRename_Failed) { |
DownloadItemImpl* item = CreateDownloadItem(); |
DownloadItemImplDelegate::DownloadTargetCallback callback; |
MockDownloadFile* download_file = |
@@ -1247,9 +1372,7 @@ TEST_F(DownloadItemTest, StealDangerousDownload) { |
EXPECT_EQ(full_path, returned_path); |
} |
-TEST_F(DownloadItemTest, StealInterruptedDangerousDownload) { |
- CommandLine::ForCurrentProcess()->AppendSwitch( |
- switches::kEnableDownloadResumption); |
+TEST_F(DownloadItemTestWithResumption, StealInterruptedDangerousDownload) { |
base::FilePath returned_path; |
DownloadItemImpl* item = CreateDownloadItem(); |
MockDownloadFile* download_file = |
@@ -1273,9 +1396,8 @@ TEST_F(DownloadItemTest, StealInterruptedDangerousDownload) { |
EXPECT_EQ(full_path, returned_path); |
} |
-TEST_F(DownloadItemTest, StealInterruptedNonResumableDangerousDownload) { |
- CommandLine::ForCurrentProcess()->AppendSwitch( |
- switches::kEnableDownloadResumption); |
+TEST_F(DownloadItemTestWithResumption, |
+ StealInterruptedNonResumableDangerousDownload) { |
base::FilePath returned_path; |
DownloadItemImpl* item = CreateDownloadItem(); |
MockDownloadFile* download_file = |