diff options
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/DEPS | 1 | ||||
-rw-r--r-- | chrome/browser/download/chrome_download_manager_delegate.cc | 32 | ||||
-rw-r--r-- | chrome/browser/download/chrome_download_manager_delegate.h | 4 | ||||
-rw-r--r-- | chrome/browser/download/download_item_unittest.cc | 348 | ||||
-rw-r--r-- | chrome/browser/download/download_manager_unittest.cc | 1323 |
5 files changed, 4 insertions, 1704 deletions
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index 782262b..6155ac4 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS @@ -44,7 +44,6 @@ include_rules = [ "+content/browser/download/download_create_info.h", "+content/browser/download/download_file_impl.h", "+content/browser/download/download_file_manager.h", - "+content/browser/download/download_item_impl.h", "+content/browser/download/download_persistent_store_info.h", "+content/browser/download/download_request_handle.h", "+content/browser/download/download_state_info.h", diff --git a/chrome/browser/download/chrome_download_manager_delegate.cc b/chrome/browser/download/chrome_download_manager_delegate.cc index 73856ba..b353035 100644 --- a/chrome/browser/download/chrome_download_manager_delegate.cc +++ b/chrome/browser/download/chrome_download_manager_delegate.cc @@ -144,31 +144,9 @@ void ChromeDownloadManagerDelegate::ChooseDownloadPath( download_manager_, web_contents, suggested_path, data); } -bool ChromeDownloadManagerDelegate::OverrideIntermediatePath( - DownloadItem* item, - FilePath* intermediate_path) { - if (item->GetDangerType() != content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) { - if (item->PromptUserForSaveLocation()) { - // When we prompt the user, we overwrite the FullPath with what the user - // wanted to use. Construct a file path using the previously determined - // intermediate filename and the new path. - // TODO(asanka): This can trample an in-progress download in the new - // target directory if it was using the same intermediate name. - FilePath file_name = item->GetSuggestedPath().BaseName(); - *intermediate_path = item->GetFullPath().DirName().Append(file_name); - return true; - } else { - // The download's name is already set to an intermediate name, so no need - // to override. - return false; - } - } - - // The download is a safe download. We need to rename it to its intermediate - // '.crdownload' path. The final name after user confirmation will be set - // from DownloadItem::OnDownloadCompleting. - *intermediate_path = download_util::GetCrDownloadPath(item->GetFullPath()); - return true; +FilePath ChromeDownloadManagerDelegate::GetIntermediatePath( + const FilePath& suggested_path) { + return download_util::GetCrDownloadPath(suggested_path); } WebContents* ChromeDownloadManagerDelegate:: @@ -254,10 +232,6 @@ bool ChromeDownloadManagerDelegate::GenerateFileHash() { #endif } -void ChromeDownloadManagerDelegate::OnResponseCompleted(DownloadItem* item) { - // TODO(noelutz): remove this method from the delegate API. -} - void ChromeDownloadManagerDelegate::AddItemToPersistentStore( DownloadItem* item) { download_history_->AddEntry(item, diff --git a/chrome/browser/download/chrome_download_manager_delegate.h b/chrome/browser/download/chrome_download_manager_delegate.h index d0464763..6d7c6ea 100644 --- a/chrome/browser/download/chrome_download_manager_delegate.h +++ b/chrome/browser/download/chrome_download_manager_delegate.h @@ -59,15 +59,13 @@ class ChromeDownloadManagerDelegate virtual void ChooseDownloadPath(content::WebContents* web_contents, const FilePath& suggested_path, void* data) OVERRIDE; - virtual bool OverrideIntermediatePath(content::DownloadItem* item, - FilePath* intermediate_path) OVERRIDE; + virtual FilePath GetIntermediatePath(const FilePath& suggested_path) OVERRIDE; virtual content::WebContents* GetAlternativeWebContentsToNotifyForDownload() OVERRIDE; virtual bool ShouldOpenFileBasedOnExtension(const FilePath& path) OVERRIDE; virtual bool ShouldCompleteDownload(content::DownloadItem* item) OVERRIDE; virtual bool ShouldOpenDownload(content::DownloadItem* item) OVERRIDE; virtual bool GenerateFileHash() OVERRIDE; - virtual void OnResponseCompleted(content::DownloadItem* item) OVERRIDE; virtual void AddItemToPersistentStore(content::DownloadItem* item) OVERRIDE; virtual void UpdateItemInPersistentStore( content::DownloadItem* item) OVERRIDE; diff --git a/chrome/browser/download/download_item_unittest.cc b/chrome/browser/download/download_item_unittest.cc deleted file mode 100644 index dcafc04..0000000 --- a/chrome/browser/download/download_item_unittest.cc +++ /dev/null @@ -1,348 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/message_loop.h" -#include "base/stl_util.h" -#include "base/threading/thread.h" -#include "chrome/test/base/testing_profile.h" -#include "content/browser/download/download_create_info.h" -#include "content/browser/download/download_item_impl.h" -#include "content/browser/download/download_request_handle.h" -#include "content/browser/download/download_status_updater.h" -#include "content/browser/download/interrupt_reasons.h" -#include "content/browser/download/mock_download_item.h" -#include "content/public/browser/download_id.h" -#include "content/test/test_browser_thread.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using content::BrowserThread; -using content::DownloadId; -using content::DownloadItem; -using content::DownloadManager; - -DownloadId::Domain kValidDownloadItemIdDomain = "valid DownloadId::Domain"; - -namespace { -class MockDelegate : public DownloadItemImpl::Delegate { - public: - MOCK_METHOD1(ShouldOpenFileBasedOnExtension, bool(const FilePath& path)); - MOCK_METHOD1(ShouldOpenDownload, bool(DownloadItem* download)); - MOCK_METHOD1(CheckForFileRemoval, void(DownloadItem* download)); - MOCK_METHOD1(MaybeCompleteDownload, void(DownloadItem* download)); - MOCK_CONST_METHOD0(GetBrowserContext, content::BrowserContext*()); - MOCK_METHOD1(DownloadCancelled, void(DownloadItem* download)); - MOCK_METHOD1(DownloadCompleted, void(DownloadItem* download)); - MOCK_METHOD1(DownloadOpened, void(DownloadItem* download)); - MOCK_METHOD1(DownloadRemoved, void(DownloadItem* download)); - MOCK_CONST_METHOD1(AssertStateConsistent, void(DownloadItem* download)); -}; - -class MockRequestHandle : public DownloadRequestHandleInterface { - public: - MOCK_CONST_METHOD0(GetTabContents, TabContents*()); - MOCK_CONST_METHOD0(GetDownloadManager, DownloadManager*()); - MOCK_CONST_METHOD0(PauseRequest, void()); - MOCK_CONST_METHOD0(ResumeRequest, void()); - MOCK_CONST_METHOD0(CancelRequest, void()); - MOCK_CONST_METHOD0(DebugString, std::string()); -}; - -} - -class DownloadItemTest : public testing::Test { - public: - class MockObserver : public content::DownloadItem::Observer { - public: - explicit MockObserver(DownloadItem* item) : item_(item), updated_(false) { - item_->AddObserver(this); - } - ~MockObserver() { item_->RemoveObserver(this); } - - virtual void OnDownloadUpdated(content::DownloadItem* download) { - updated_ = true; - } - - virtual void OnDownloadOpened(content::DownloadItem* download) { } - - bool CheckUpdated() { - bool was_updated = updated_; - updated_ = false; - return was_updated; - } - - private: - DownloadItem* item_; - bool updated_; - }; - - DownloadItemTest() - : ui_thread_(BrowserThread::UI, &loop_) { - } - - ~DownloadItemTest() { - } - - virtual void SetUp() { - } - - virtual void TearDown() { - ui_thread_.DeprecatedGetThreadObject()->message_loop()->RunAllPending(); - STLDeleteElements(&allocated_downloads_); - allocated_downloads_.clear(); - } - - // This class keeps ownership of the created download item; it will - // be torn down at the end of the test unless DestroyDownloadItem is - // called. - DownloadItem* CreateDownloadItem(DownloadItem::DownloadState state) { - // 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 int next_id; - info_->download_id = - content::DownloadId(kValidDownloadItemIdDomain, ++next_id); - info_->prompt_user_for_save_location = false; - info_->url_chain.push_back(GURL()); - info_->state = state; - - MockRequestHandle* request_handle = - new testing::NiceMock<MockRequestHandle>; - DownloadItem* download = - new DownloadItemImpl(&delegate_, *(info_.get()), - request_handle, false); - allocated_downloads_.insert(download); - return download; - } - - // Destroy a previously created download item. - void DestroyDownloadItem(DownloadItem* item) { - allocated_downloads_.erase(item); - delete item; - } - - protected: - DownloadStatusUpdater download_status_updater_; - - private: - MessageLoopForUI loop_; - // UI thread. - content::TestBrowserThread ui_thread_; - testing::NiceMock<MockDelegate> delegate_; - std::set<DownloadItem*> allocated_downloads_; -}; - -namespace { - -const int kDownloadChunkSize = 1000; -const int kDownloadSpeed = 1000; -const int kDummyDBHandle = 10; -const FilePath::CharType kDummyPath[] = FILE_PATH_LITERAL("/testpath"); - -} // namespace - -// Tests to ensure calls that change a DownloadItem generate an update to -// observers. -// State changing functions not tested: -// void OpenDownload(); -// void ShowDownloadInShell(); -// void CompleteDelayedDownload(); -// void OnDownloadCompleting(DownloadFileManager* file_manager); -// void OnDownloadRenamedToFinalName(const FilePath& full_path); -// set_* mutators - -TEST_F(DownloadItemTest, NotificationAfterUpdate) { - DownloadItem* item = CreateDownloadItem(DownloadItem::IN_PROGRESS); - MockObserver observer(item); - - item->UpdateProgress(kDownloadChunkSize, kDownloadSpeed, ""); - ASSERT_TRUE(observer.CheckUpdated()); - EXPECT_EQ(kDownloadSpeed, item->CurrentSpeed()); -} - -TEST_F(DownloadItemTest, NotificationAfterCancel) { - DownloadItem* user_cancel = CreateDownloadItem(DownloadItem::IN_PROGRESS); - MockObserver observer1(user_cancel); - - user_cancel->Cancel(true); - ASSERT_TRUE(observer1.CheckUpdated()); - - DownloadItem* system_cancel = CreateDownloadItem(DownloadItem::IN_PROGRESS); - MockObserver observer2(system_cancel); - - system_cancel->Cancel(false); - ASSERT_TRUE(observer2.CheckUpdated()); -} - -TEST_F(DownloadItemTest, NotificationAfterComplete) { - DownloadItem* item = CreateDownloadItem(DownloadItem::IN_PROGRESS); - MockObserver observer(item); - - // Calling OnAllDataSaved does not trigger notification - item->OnAllDataSaved(kDownloadChunkSize, DownloadItem::kEmptyFileHash); - ASSERT_FALSE(observer.CheckUpdated()); - - item->MarkAsComplete(); - ASSERT_TRUE(observer.CheckUpdated()); -} - -TEST_F(DownloadItemTest, NotificationAfterDownloadedFileRemoved) { - DownloadItem* item = CreateDownloadItem(DownloadItem::IN_PROGRESS); - MockObserver observer(item); - - item->OnDownloadedFileRemoved(); - ASSERT_TRUE(observer.CheckUpdated()); -} - -TEST_F(DownloadItemTest, NotificationAfterInterrupted) { - DownloadItem* item = CreateDownloadItem(DownloadItem::IN_PROGRESS); - MockObserver observer(item); - - item->Interrupted(kDownloadChunkSize, "", DOWNLOAD_INTERRUPT_REASON_NONE); - ASSERT_TRUE(observer.CheckUpdated()); -} - -TEST_F(DownloadItemTest, NotificationAfterDelete) { - DownloadItem* item = CreateDownloadItem(DownloadItem::IN_PROGRESS); - MockObserver observer(item); - - item->Delete(DownloadItem::DELETE_DUE_TO_BROWSER_SHUTDOWN); - ASSERT_TRUE(observer.CheckUpdated()); -} - -TEST_F(DownloadItemTest, NotificationAfterRemove) { - DownloadItem* item = CreateDownloadItem(DownloadItem::IN_PROGRESS); - MockObserver observer(item); - - item->Remove(); - ASSERT_TRUE(observer.CheckUpdated()); -} - -TEST_F(DownloadItemTest, NotificationAfterSetFileCheckResults) { - // Setting to safe should not trigger any notifications - DownloadItem* safe_item = CreateDownloadItem(DownloadItem::IN_PROGRESS); - MockObserver safe_observer(safe_item); - - DownloadStateInfo state = safe_item->GetStateInfo();; - state.danger = content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS; - safe_item->SetFileCheckResults(state); - ASSERT_FALSE(safe_observer.CheckUpdated()); - - // Setting to unsafe url or unsafe file should trigger notification - DownloadItem* unsafeurl_item = CreateDownloadItem(DownloadItem::IN_PROGRESS); - MockObserver unsafeurl_observer(unsafeurl_item); - - state = unsafeurl_item->GetStateInfo();; - state.danger = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL; - unsafeurl_item->SetFileCheckResults(state); - ASSERT_TRUE(unsafeurl_observer.CheckUpdated()); - - unsafeurl_item->DangerousDownloadValidated(); - ASSERT_TRUE(unsafeurl_observer.CheckUpdated()); - - DownloadItem* unsafefile_item = CreateDownloadItem(DownloadItem::IN_PROGRESS); - MockObserver unsafefile_observer(unsafefile_item); - - state = unsafefile_item->GetStateInfo();; - state.danger = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE; - unsafefile_item->SetFileCheckResults(state); - ASSERT_TRUE(unsafefile_observer.CheckUpdated()); - - unsafefile_item->DangerousDownloadValidated(); - ASSERT_TRUE(unsafefile_observer.CheckUpdated()); -} - -TEST_F(DownloadItemTest, NotificationAfterOnPathDetermined) { - DownloadItem* item = CreateDownloadItem(DownloadItem::IN_PROGRESS); - MockObserver observer(item); - - // Calling OnPathDetermined does not trigger notification - item->OnPathDetermined(FilePath(kDummyPath)); - ASSERT_FALSE(observer.CheckUpdated()); -} - -TEST_F(DownloadItemTest, NotificationAfterRename) { - DownloadItem* item = CreateDownloadItem(DownloadItem::IN_PROGRESS); - MockObserver observer(item); - - // Calling Rename does not trigger notification - item->Rename(FilePath(kDummyPath)); - ASSERT_FALSE(observer.CheckUpdated()); -} - -TEST_F(DownloadItemTest, NotificationAfterTogglePause) { - DownloadItem* item = CreateDownloadItem(DownloadItem::IN_PROGRESS); - MockObserver observer(item); - - item->TogglePause(); - ASSERT_TRUE(observer.CheckUpdated()); - - item->TogglePause(); - ASSERT_TRUE(observer.CheckUpdated()); -} - -static char external_data_test_string[] = "External data test"; -static int destructor_called = 0; - -class TestExternalData : public content::DownloadItem::ExternalData { - public: - int value; - virtual ~TestExternalData() { - destructor_called++; - } -}; - -TEST_F(DownloadItemTest, ExternalData) { - DownloadItem* item = CreateDownloadItem(DownloadItem::IN_PROGRESS); - - // Shouldn't be anything there before set. - EXPECT_EQ(NULL, item->GetExternalData(&external_data_test_string)); - - TestExternalData* test1(new TestExternalData()); - test1->value = 2; - - // Should be able to get back what you set. - item->SetExternalData(&external_data_test_string, test1); - TestExternalData* test_result = - static_cast<TestExternalData*>( - item->GetExternalData(&external_data_test_string)); - EXPECT_EQ(test1, test_result); - - // Destructor should be called if value overwritten. New value - // should then be retrievable. - TestExternalData* test2(new TestExternalData()); - test2->value = 3; - EXPECT_EQ(0, destructor_called); - item->SetExternalData(&external_data_test_string, test2); - EXPECT_EQ(1, destructor_called); - EXPECT_EQ(static_cast<DownloadItem::ExternalData*>(test2), - item->GetExternalData(&external_data_test_string)); - - // Overwriting with the same value shouldn't do anything. - EXPECT_EQ(1, destructor_called); - item->SetExternalData(&external_data_test_string, test2); - EXPECT_EQ(1, destructor_called); - EXPECT_EQ(static_cast<DownloadItem::ExternalData*>(test2), - item->GetExternalData(&external_data_test_string)); - - // Overwriting with NULL should result in destruction. - item->SetExternalData(&external_data_test_string, NULL); - EXPECT_EQ(2, destructor_called); - - // Destroying the download item should destroy the external data. - - TestExternalData* test3(new TestExternalData()); - item->SetExternalData(&external_data_test_string, test3); - EXPECT_EQ(static_cast<DownloadItem::ExternalData*>(test3), - item->GetExternalData(&external_data_test_string)); - DestroyDownloadItem(item); - EXPECT_EQ(3, destructor_called); -} - -TEST(MockDownloadItem, Compiles) { - MockDownloadItem mock_item; -} diff --git a/chrome/browser/download/download_manager_unittest.cc b/chrome/browser/download/download_manager_unittest.cc deleted file mode 100644 index 59723fe..0000000 --- a/chrome/browser/download/download_manager_unittest.cc +++ /dev/null @@ -1,1323 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <set> -#include <string> - -#include "base/bind.h" -#include "base/file_util.h" -#include "base/i18n/number_formatting.h" -#include "base/i18n/rtl.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop.h" -#include "base/scoped_temp_dir.h" -#include "base/stl_util.h" -#include "base/string16.h" -#include "base/string_util.h" -#include "base/utf_string_conversions.h" -#include "build/build_config.h" -#include "chrome/browser/download/chrome_download_manager_delegate.h" -#include "chrome/browser/download/download_item_model.h" -#include "chrome/browser/download/download_prefs.h" -#include "chrome/browser/download/download_util.h" -#include "chrome/browser/prefs/pref_service.h" -#include "chrome/common/pref_names.h" -#include "chrome/test/base/testing_profile.h" -#include "content/browser/download/download_buffer.h" -#include "content/browser/download/download_create_info.h" -#include "content/browser/download/download_file_impl.h" -#include "content/browser/download/download_file_manager.h" -#include "content/browser/download/download_request_handle.h" -#include "content/browser/download/download_status_updater.h" -#include "content/browser/download/interrupt_reasons.h" -#include "content/browser/download/mock_download_file.h" -#include "content/browser/download/mock_download_manager.h" -#include "content/public/browser/download_item.h" -#include "content/public/browser/download_manager.h" -#include "content/test/test_browser_thread.h" -#include "grit/generated_resources.h" -#include "net/base/io_buffer.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gmock_mutant.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/text/bytes_formatting.h" - -#if defined(USE_AURA) && defined(OS_WIN) -// http://crbug.com/105200 -#define MAYBE_StartDownload DISABLED_StartDownload -#define MAYBE_DownloadOverwriteTest DISABLED_DownloadOverwriteTest -#define MAYBE_DownloadRemoveTest DISABLED_DownloadRemoveTest -#define MAYBE_DownloadFileErrorTest DownloadFileErrorTest -#elif defined(OS_LINUX) -// http://crbug.com/110886 for Linux -#define MAYBE_StartDownload DISABLED_StartDownload -#define MAYBE_DownloadOverwriteTest DISABLED_DownloadOverwriteTest -#define MAYBE_DownloadRemoveTest DISABLED_DownloadRemoveTest -#define MAYBE_DownloadFileErrorTest DISABLED_DownloadFileErrorTest -#else -#define MAYBE_StartDownload StartDownload -#define MAYBE_DownloadOverwriteTest DownloadOverwriteTest -#define MAYBE_DownloadRemoveTest DownloadRemoveTest -#define MAYBE_DownloadFileErrorTest DownloadFileErrorTest -#endif - -using content::BrowserThread; -using content::DownloadFile; -using content::DownloadId; -using content::DownloadItem; -using content::DownloadManager; -using ::testing::ReturnRef; -using ::testing::Return; -using content::WebContents; - -namespace { - -class MockDownloadFileFactory - : public DownloadFileManager::DownloadFileFactory { - public: - MockDownloadFileFactory() {} - - virtual DownloadFile* CreateFile(DownloadCreateInfo* info, - const DownloadRequestHandle& request_handle, - DownloadManager* download_manager, - bool calculate_hash) OVERRIDE; -}; - -DownloadFile* MockDownloadFileFactory::CreateFile( - DownloadCreateInfo* info, - const DownloadRequestHandle& request_handle, - DownloadManager* download_manager, - bool calculate_hash) { - NOTREACHED(); - return NULL; -} - -DownloadId::Domain kValidIdDomain = "valid DownloadId::Domain"; - -class TestDownloadManagerDelegate : public ChromeDownloadManagerDelegate { - public: - explicit TestDownloadManagerDelegate(Profile* profile) - : ChromeDownloadManagerDelegate(profile), - mark_content_dangerous_(false) { - } - - virtual void ChooseDownloadPath(WebContents* web_contents, - const FilePath& suggested_path, - void* data) OVERRIDE { - if (!expected_suggested_path_.empty()) { - EXPECT_STREQ(expected_suggested_path_.value().c_str(), - suggested_path.value().c_str()); - } - if (file_selection_response_.empty()) { - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&DownloadManager::FileSelectionCanceled, - download_manager_.get(), - base::Unretained(data))); - } else { - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&DownloadManager::FileSelected, - download_manager_.get(), - file_selection_response_, - base::Unretained(data))); - } - expected_suggested_path_.clear(); - file_selection_response_.clear(); - } - - void SetFileSelectionExpectation(const FilePath& suggested_path, - const FilePath& response) { - expected_suggested_path_ = suggested_path; - file_selection_response_ = response; - } - - void SetMarkContentsDangerous(bool dangerous) { - mark_content_dangerous_ = dangerous; - } - - virtual bool ShouldCompleteDownload(DownloadItem* item) { - if (mark_content_dangerous_) { - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&TestDownloadManagerDelegate::MarkContentDangerous, - this, item->GetId())); - mark_content_dangerous_ = false; - return false; - } else { - return true; - } - } - - private: - void MarkContentDangerous(int32 download_id) { - DownloadItem* item = download_manager_->GetActiveDownloadItem(download_id); - if (!item) - return; - item->MarkContentDangerous(); - item->MaybeCompleteDownload(); - } - - FilePath expected_suggested_path_; - FilePath file_selection_response_; - bool mark_content_dangerous_; -}; - -} // namespace - -class DownloadManagerTest : public testing::Test { - public: - static const char* kTestData; - static const size_t kTestDataLen; - - DownloadManagerTest() - : profile_(new TestingProfile()), - download_manager_delegate_(new TestDownloadManagerDelegate( - profile_.get())), - download_manager_(DownloadManager::Create( - download_manager_delegate_, &download_status_updater_)), - ui_thread_(BrowserThread::UI, &message_loop_), - file_thread_(BrowserThread::FILE, &message_loop_), - download_buffer_(new content::DownloadBuffer) { - download_manager_->Init(profile_.get()); - download_manager_delegate_->SetDownloadManager(download_manager_); - } - - ~DownloadManagerTest() { - download_manager_->Shutdown(); - // profile_ must outlive download_manager_, so we explicitly delete - // download_manager_ first. - download_manager_ = NULL; - download_manager_delegate_ = NULL; - profile_.reset(NULL); - message_loop_.RunAllPending(); - } - - void AddDownloadToFileManager(int id, DownloadFile* download_file) { - file_manager()->downloads_[DownloadId(kValidIdDomain, id)] = - download_file; - } - - void AddMockDownloadToFileManager(int id, MockDownloadFile* download_file) { - AddDownloadToFileManager(id, download_file); - ON_CALL(*download_file, GetDownloadManager()) - .WillByDefault(Return(download_manager_)); - } - - void OnResponseCompleted(int32 download_id, int64 size, - const std::string& hash) { - download_manager_->OnResponseCompleted(download_id, size, hash); - } - - void FileSelected(const FilePath& path, void* params) { - download_manager_->FileSelected(path, params); - } - - void ContinueDownloadWithPath(DownloadItem* download, const FilePath& path) { - download_manager_->ContinueDownloadWithPath(download, path); - } - - void UpdateData(int32 id, const char* data, size_t length) { - // We are passing ownership of this buffer to the download file manager. - net::IOBuffer* io_buffer = new net::IOBuffer(length); - // We need |AddRef()| because we do a |Release()| in |UpdateDownload()|. - io_buffer->AddRef(); - memcpy(io_buffer->data(), data, length); - - download_buffer_->AddData(io_buffer, length); - - BrowserThread::PostTask( - BrowserThread::FILE, FROM_HERE, - base::Bind(&DownloadFileManager::UpdateDownload, file_manager_.get(), - DownloadId(kValidIdDomain, id), download_buffer_)); - - message_loop_.RunAllPending(); - } - - void OnDownloadInterrupted(int32 download_id, int64 size, - const std::string& hash_state, - InterruptReason reason) { - download_manager_->OnDownloadInterrupted(download_id, size, - hash_state, reason); - } - - // Get the download item with ID |id|. - DownloadItem* GetActiveDownloadItem(int32 id) { - return download_manager_->GetActiveDownload(id); - } - - protected: - DownloadStatusUpdater download_status_updater_; - scoped_ptr<TestingProfile> profile_; - scoped_refptr<TestDownloadManagerDelegate> download_manager_delegate_; - scoped_refptr<DownloadManager> download_manager_; - scoped_refptr<DownloadFileManager> file_manager_; - MessageLoopForUI message_loop_; - content::TestBrowserThread ui_thread_; - content::TestBrowserThread file_thread_; - scoped_refptr<content::DownloadBuffer> download_buffer_; - - DownloadFileManager* file_manager() { - if (!file_manager_) { - file_manager_ = new DownloadFileManager(NULL, - new MockDownloadFileFactory); - download_manager_->SetFileManager(file_manager_); - } - return file_manager_; - } - - DISALLOW_COPY_AND_ASSIGN(DownloadManagerTest); -}; - -const char* DownloadManagerTest::kTestData = "a;sdlfalsdfjalsdkfjad"; -const size_t DownloadManagerTest::kTestDataLen = - strlen(DownloadManagerTest::kTestData); - -// A DownloadFile that we can inject errors into. -class DownloadFileWithErrors : public DownloadFileImpl { - public: - DownloadFileWithErrors(DownloadCreateInfo* info, - DownloadManager* manager, - bool calculate_hash); - virtual ~DownloadFileWithErrors() {} - - // BaseFile delegated functions. - virtual net::Error Initialize(); - virtual net::Error AppendDataToFile(const char* data, size_t data_len); - virtual net::Error Rename(const FilePath& full_path); - - void set_forced_error(net::Error error) { forced_error_ = error; } - void clear_forced_error() { forced_error_ = net::OK; } - net::Error forced_error() const { return forced_error_; } - - private: - net::Error ReturnError(net::Error function_error) { - if (forced_error_ != net::OK) { - net::Error ret = forced_error_; - clear_forced_error(); - return ret; - } - - return function_error; - } - - net::Error forced_error_; -}; - -DownloadFileWithErrors::DownloadFileWithErrors(DownloadCreateInfo* info, - DownloadManager* manager, - bool calculate_hash) - : DownloadFileImpl(info, - new DownloadRequestHandle(), - manager, - calculate_hash), - forced_error_(net::OK) { -} - -net::Error DownloadFileWithErrors::Initialize() { - return ReturnError(DownloadFileImpl::Initialize()); -} - -net::Error DownloadFileWithErrors::AppendDataToFile(const char* data, - size_t data_len) { - return ReturnError(DownloadFileImpl::AppendDataToFile(data, data_len)); -} - -net::Error DownloadFileWithErrors::Rename(const FilePath& full_path) { - return ReturnError(DownloadFileImpl::Rename(full_path)); -} - -namespace { - -const struct { - const char* url; - const char* mime_type; - bool save_as; - bool prompt_for_download; - bool expected_save_as; -} kStartDownloadCases[] = { - { "http://www.foo.com/dont-open.html", - "text/html", - false, - false, - false, }, - { "http://www.foo.com/save-as.html", - "text/html", - true, - false, - true, }, - { "http://www.foo.com/always-prompt.html", - "text/html", - false, - true, - true, }, - { "http://www.foo.com/user-script-text-html-mimetype.user.js", - "text/html", - false, - false, - false, }, - { "http://www.foo.com/extensionless-extension", - "application/x-chrome-extension", - true, - false, - true, }, - { "http://www.foo.com/save-as.pdf", - "application/pdf", - true, - false, - true, }, - { "http://www.foo.com/sometimes_prompt.pdf", - "application/pdf", - false, - true, - false, }, - { "http://www.foo.com/always_prompt.jar", - "application/jar", - false, - true, - true, }, -}; - -const struct { - FilePath::StringType suggested_path; - content::DownloadDangerType danger; - bool finish_before_rename; - int expected_rename_count; -} kDownloadRenameCases[] = { - // Safe download, download finishes BEFORE file name determined. - // Renamed twice (linear path through UI). Crdownload file does not need - // to be deleted. - { FILE_PATH_LITERAL("foo.zip"), content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, - true, 2, }, - // Potentially dangerous download (e.g., file is dangerous), download finishes - // BEFORE file name determined. Needs to be renamed only once. - { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"), - content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, true, 1, }, - { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"), - content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE, true, 1, }, - // Safe download, download finishes AFTER file name determined. - // Needs to be renamed twice. - { FILE_PATH_LITERAL("foo.zip"), content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, - false, 2, }, - // Potentially dangerous download, download finishes AFTER file name - // determined. Needs to be renamed only once. - { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"), - content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, false, 1, }, - { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"), - content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE, false, 1, }, -}; - -// This is an observer that records what download IDs have opened a select -// file dialog. -class SelectFileObserver : public content::DownloadManager::Observer { - public: - explicit SelectFileObserver(DownloadManager* download_manager) - : download_manager_(download_manager) { - DCHECK(download_manager_.get()); - download_manager_->AddObserver(this); - } - - ~SelectFileObserver() { - download_manager_->RemoveObserver(this); - } - - // Downloadmanager::Observer functions. - virtual void ModelChanged() {} - virtual void ManagerGoingDown() {} - virtual void SelectFileDialogDisplayed(int32 id) { - file_dialog_ids_.insert(id); - } - - bool ShowedFileDialogForId(int32 id) { - return file_dialog_ids_.find(id) != file_dialog_ids_.end(); - } - - private: - std::set<int32> file_dialog_ids_; - scoped_refptr<DownloadManager> download_manager_; -}; - -// This observer tracks the progress of |DownloadItem|s. -class ItemObserver : public DownloadItem::Observer { - public: - explicit ItemObserver(DownloadItem* tracked) - : tracked_(tracked), states_hit_(0), - was_updated_(false), was_opened_(false) { - DCHECK(tracked_); - tracked_->AddObserver(this); - // Record the initial state. - OnDownloadUpdated(tracked_); - } - ~ItemObserver() { - tracked_->RemoveObserver(this); - } - - bool hit_state(int state) const { - return (1 << state) & states_hit_; - } - bool was_updated() const { return was_updated_; } - bool was_opened() const { return was_opened_; } - - private: - // DownloadItem::Observer methods - virtual void OnDownloadUpdated(DownloadItem* download) { - DCHECK_EQ(tracked_, download); - states_hit_ |= (1 << download->GetState()); - was_updated_ = true; - } - virtual void OnDownloadOpened(DownloadItem* download) { - DCHECK_EQ(tracked_, download); - states_hit_ |= (1 << download->GetState()); - was_opened_ = true; - } - - DownloadItem* tracked_; - int states_hit_; - bool was_updated_; - bool was_opened_; -}; - -} // namespace - -TEST_F(DownloadManagerTest, MAYBE_StartDownload) { - content::TestBrowserThread io_thread(BrowserThread::IO, &message_loop_); - PrefService* prefs = profile_->GetPrefs(); - prefs->SetFilePath(prefs::kDownloadDefaultDirectory, FilePath()); - DownloadPrefs* download_prefs = - DownloadPrefs::FromDownloadManager(download_manager_); - download_prefs->EnableAutoOpenBasedOnExtension( - FilePath(FILE_PATH_LITERAL("example.pdf"))); - - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kStartDownloadCases); ++i) { - prefs->SetBoolean(prefs::kPromptForDownload, - kStartDownloadCases[i].prompt_for_download); - - SelectFileObserver observer(download_manager_); - // 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(new DownloadCreateInfo); - const DownloadId id = DownloadId(kValidIdDomain, static_cast<int>(i)); - info->download_id = id; - info->prompt_user_for_save_location = kStartDownloadCases[i].save_as; - info->url_chain.push_back(GURL(kStartDownloadCases[i].url)); - info->mime_type = kStartDownloadCases[i].mime_type; - download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle()); - - DownloadFile* download_file( - new DownloadFileImpl(info.get(), new DownloadRequestHandle(), - download_manager_, false)); - AddDownloadToFileManager(info->download_id.local(), download_file); - download_file->Initialize(); - download_manager_->StartDownload(info->download_id.local()); - message_loop_.RunAllPending(); - - // SelectFileObserver will have recorded any attempt to open the - // select file dialog. - // Note that DownloadManager::FileSelectionCanceled() is never called. - EXPECT_EQ(kStartDownloadCases[i].expected_save_as, - observer.ShowedFileDialogForId(i)); - - file_manager()->CancelDownload(id); - } -} - -namespace { - -enum PromptForSaveLocation { - DONT_PROMPT, - PROMPT -}; - -enum ValidateDangerousDownload { - DONT_VALIDATE, - VALIDATE -}; - -// Test cases to be used with DownloadFilenameTest. The paths that are used in -// test cases can contain "$dl" and "$alt" tokens which are replaced by a -// default download path, and an alternate download path in -// ExpandFilenameTestPath() below. -const struct DownloadFilenameTestCase { - - // Fields to be set in DownloadStateInfo when calling SetFileCheckResults(). - const FilePath::CharType* suggested_path; - const FilePath::CharType* target_name; - PromptForSaveLocation prompt_user_for_save_location; - content::DownloadDangerType danger_type; - - // If we receive a ChooseDownloadPath() call to prompt the user for a download - // location, |prompt_path| is the expected prompt path. The - // TestDownloadManagerDelegate will respond with |final_path|. If |final_path| - // is empty, then the file choose dialog be cancelled. - const FilePath::CharType* prompt_path; - - // The expected intermediate path for the download. - const FilePath::CharType* intermediate_path; - - // The expected final path for the download. - const FilePath::CharType* final_path; - - // If this is a dangerous download, then we will either validate the download - // or delete it depending on the value of |validate_dangerous_download|. - ValidateDangerousDownload validate_dangerous_download; -} kDownloadFilenameTestCases[] = { - { - // 0: A safe file is downloaded with no prompting. - FILE_PATH_LITERAL("$dl/foo.txt"), - FILE_PATH_LITERAL(""), - DONT_PROMPT, - content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, - FILE_PATH_LITERAL(""), - FILE_PATH_LITERAL("$dl/foo.txt.crdownload"), - FILE_PATH_LITERAL("$dl/foo.txt"), - DONT_VALIDATE - }, - { - // 1: A safe file is downloaded with prompting. - FILE_PATH_LITERAL("$dl/foo.txt"), - FILE_PATH_LITERAL(""), - PROMPT, - content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, - FILE_PATH_LITERAL("$dl/foo.txt"), - FILE_PATH_LITERAL("$dl/foo.txt.crdownload"), - FILE_PATH_LITERAL("$dl/foo.txt"), - DONT_VALIDATE - }, - { - // 2: A safe file is downloaded. The filename is changed before the dialog - // completes. - FILE_PATH_LITERAL("$dl/foo.txt"), - FILE_PATH_LITERAL(""), - PROMPT, - content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, - FILE_PATH_LITERAL("$dl/foo.txt"), - FILE_PATH_LITERAL("$dl/bar.txt.crdownload"), - FILE_PATH_LITERAL("$dl/bar.txt"), - DONT_VALIDATE - }, - { - // 3: A safe file is downloaded. The download path is changed before the - // dialog completes. - FILE_PATH_LITERAL("$dl/foo.txt"), - FILE_PATH_LITERAL(""), - PROMPT, - content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, - FILE_PATH_LITERAL("$dl/foo.txt"), - FILE_PATH_LITERAL("$alt/bar.txt.crdownload"), - FILE_PATH_LITERAL("$alt/bar.txt"), - DONT_VALIDATE - }, - { - // 4: Potentially dangerous content. - FILE_PATH_LITERAL("$dl/Unconfirmed xxx.download"), - FILE_PATH_LITERAL("foo.exe"), - DONT_PROMPT, - content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, - FILE_PATH_LITERAL(""), - FILE_PATH_LITERAL("$dl/Unconfirmed xxx.download"), - FILE_PATH_LITERAL("$dl/foo.exe"), - DONT_VALIDATE - }, - { - // 5: Potentially dangerous content. Uses "Save as." - FILE_PATH_LITERAL("$dl/Unconfirmed xxx.download"), - FILE_PATH_LITERAL("foo.exe"), - PROMPT, - content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, - FILE_PATH_LITERAL("$dl/foo.exe"), - FILE_PATH_LITERAL("$dl/Unconfirmed xxx.download"), - FILE_PATH_LITERAL("$dl/foo.exe"), - DONT_VALIDATE - }, - { - // 6: Potentially dangerous content. Uses "Save as." The download filename - // is changed before the dialog completes. - FILE_PATH_LITERAL("$dl/Unconfirmed xxx.download"), - FILE_PATH_LITERAL("foo.exe"), - PROMPT, - content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, - FILE_PATH_LITERAL("$dl/foo.exe"), - FILE_PATH_LITERAL("$dl/Unconfirmed xxx.download"), - FILE_PATH_LITERAL("$dl/bar.exe"), - DONT_VALIDATE - }, - { - // 7: Potentially dangerous content. Uses "Save as." The download directory - // is changed before the dialog completes. - FILE_PATH_LITERAL("$dl/Unconfirmed xxx.download"), - FILE_PATH_LITERAL("foo.exe"), - PROMPT, - content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, - FILE_PATH_LITERAL("$dl/foo.exe"), - FILE_PATH_LITERAL("$alt/Unconfirmed xxx.download"), - FILE_PATH_LITERAL("$alt/bar.exe"), - DONT_VALIDATE - }, - { - // 8: Dangerous content. Saved directly. - FILE_PATH_LITERAL("$dl/Unconfirmed xxx.download"), - FILE_PATH_LITERAL("foo.exe"), - PROMPT, - content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL, - FILE_PATH_LITERAL(""), - FILE_PATH_LITERAL("$dl/Unconfirmed xxx.download"), - FILE_PATH_LITERAL("$dl/foo.exe"), - VALIDATE - }, - { - // 9: Dangerous content. Saved directly. Not validated. - FILE_PATH_LITERAL("$dl/Unconfirmed xxx.download"), - FILE_PATH_LITERAL("foo.exe"), - DONT_PROMPT, - content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL, - FILE_PATH_LITERAL(""), - FILE_PATH_LITERAL("$dl/Unconfirmed xxx.download"), - FILE_PATH_LITERAL(""), - DONT_VALIDATE - }, - { - // 10: Dangerous content. Uses "Save as." The download directory is changed - // before the dialog completes. - FILE_PATH_LITERAL("$dl/Unconfirmed xxx.download"), - FILE_PATH_LITERAL("foo.exe"), - PROMPT, - content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL, - FILE_PATH_LITERAL("$dl/foo.exe"), - FILE_PATH_LITERAL("$alt/Unconfirmed xxx.download"), - FILE_PATH_LITERAL("$alt/bar.exe"), - VALIDATE - }, - { - // 11: A safe file is download. The target file exists, but we don't - // uniquify. Safe downloads are uniquified in ChromeDownloadManagerDelegate - // instead of DownloadManagerImpl. - FILE_PATH_LITERAL("$dl/exists.txt"), - FILE_PATH_LITERAL(""), - DONT_PROMPT, - content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, - FILE_PATH_LITERAL(""), - FILE_PATH_LITERAL("$dl/exists.txt.crdownload"), - FILE_PATH_LITERAL("$dl/exists.txt"), - DONT_VALIDATE - }, - { - // 12: A potentially dangerous file is download. The target file exists. The - // target path is uniquified. - FILE_PATH_LITERAL("$dl/Unconfirmed xxx.download"), - FILE_PATH_LITERAL("exists.exe"), - DONT_PROMPT, - content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, - FILE_PATH_LITERAL(""), - FILE_PATH_LITERAL("$dl/Unconfirmed xxx.download"), - FILE_PATH_LITERAL("$dl/exists (1).exe"), - DONT_VALIDATE - }, - { - // 13: A dangerous file is download. The target file exists. The target path - // is uniquified. - FILE_PATH_LITERAL("$dl/Unconfirmed xxx.download"), - FILE_PATH_LITERAL("exists.exe"), - DONT_PROMPT, - content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT, - FILE_PATH_LITERAL(""), - FILE_PATH_LITERAL("$dl/Unconfirmed xxx.download"), - FILE_PATH_LITERAL("$dl/exists (1).exe"), - VALIDATE - }, - { - // 14: A potentially dangerous file is download with prompting. The target - // file exists. The target path is not uniquified because the filename was - // given to us by the user. - FILE_PATH_LITERAL("$dl/Unconfirmed xxx.download"), - FILE_PATH_LITERAL("exists.exe"), - PROMPT, - content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, - FILE_PATH_LITERAL("$dl/exists.exe"), - FILE_PATH_LITERAL("$dl/Unconfirmed xxx.download"), - FILE_PATH_LITERAL("$dl/exists.exe"), - DONT_VALIDATE - }, -}; - -FilePath ExpandFilenameTestPath(const FilePath::CharType* template_path, - const FilePath& downloads_dir, - const FilePath& alternate_dir) { - FilePath::StringType path(template_path); - ReplaceSubstringsAfterOffset(&path, 0, FILE_PATH_LITERAL("$dl"), - downloads_dir.value()); - ReplaceSubstringsAfterOffset(&path, 0, FILE_PATH_LITERAL("$alt"), - alternate_dir.value()); - FilePath file_path(path); -#if defined(FILE_PATH_USES_WIN_SEPARATORS) - file_path = file_path.NormalizeWindowsPathSeparators(); -#endif - return file_path; -} - -} // namespace - -TEST_F(DownloadManagerTest, DownloadFilenameTest) { - ScopedTempDir scoped_dl_dir; - ASSERT_TRUE(scoped_dl_dir.CreateUniqueTempDir()); - - FilePath downloads_dir(scoped_dl_dir.path()); - FilePath alternate_dir(downloads_dir.Append(FILE_PATH_LITERAL("Foo"))); - - // We create a known file to test file uniquification. - file_util::WriteFile(downloads_dir.Append(FILE_PATH_LITERAL("exists.txt")), - "", 0); - file_util::WriteFile(downloads_dir.Append(FILE_PATH_LITERAL("exists.exe")), - "", 0); - - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDownloadFilenameTestCases); ++i) { - scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo); - info->download_id = DownloadId(kValidIdDomain, i); - info->url_chain.push_back(GURL()); - - MockDownloadFile* download_file(new MockDownloadFile()); - FilePath suggested_path(ExpandFilenameTestPath( - kDownloadFilenameTestCases[i].suggested_path, - downloads_dir, alternate_dir)); - FilePath prompt_path(ExpandFilenameTestPath( - kDownloadFilenameTestCases[i].prompt_path, - downloads_dir, alternate_dir)); - FilePath intermediate_path(ExpandFilenameTestPath( - kDownloadFilenameTestCases[i].intermediate_path, - downloads_dir, alternate_dir)); - FilePath final_path(ExpandFilenameTestPath( - kDownloadFilenameTestCases[i].final_path, - downloads_dir, alternate_dir)); - - AddMockDownloadToFileManager(info->download_id.local(), download_file); - - EXPECT_CALL(*download_file, Rename(intermediate_path)) - .WillOnce(Return(net::OK)); - - if (!final_path.empty()) { - // If |final_path| is empty, its a signal that the download doesn't - // complete. Therefore it will only go through a single rename. - EXPECT_CALL(*download_file, Rename(final_path)) - .WillOnce(Return(net::OK)); - } - - download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle()); - DownloadItem* download = GetActiveDownloadItem(i); - ASSERT_TRUE(download != NULL); - - DownloadStateInfo state = download->GetStateInfo(); - state.suggested_path = suggested_path; - state.danger = kDownloadFilenameTestCases[i].danger_type; - state.prompt_user_for_save_location = - (kDownloadFilenameTestCases[i].prompt_user_for_save_location == PROMPT); - state.target_name = FilePath(kDownloadFilenameTestCases[i].target_name); - if (state.danger == content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT) { - // DANGEROUS_CONTENT will only be known once we have all the data. We let - // our TestDownloadManagerDelegate handle it. - state.danger = content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT; - download_manager_delegate_->SetMarkContentsDangerous(true); - } - download->SetFileCheckResults(state); - download_manager_delegate_->SetFileSelectionExpectation( - prompt_path, final_path); - download_manager_->RestartDownload(i); - message_loop_.RunAllPending(); - - OnResponseCompleted(i, 1024, std::string("fake_hash")); - message_loop_.RunAllPending(); - - if (download->GetSafetyState() == DownloadItem::DANGEROUS) { - if (kDownloadFilenameTestCases[i].validate_dangerous_download == VALIDATE) - download->DangerousDownloadValidated(); - else - download->Delete(DownloadItem::DELETE_DUE_TO_USER_DISCARD); - message_loop_.RunAllPending(); - // |download| might be deleted when we get here. - } - } -} - -TEST_F(DownloadManagerTest, DownloadRenameTest) { - using ::testing::_; - using ::testing::CreateFunctor; - using ::testing::Invoke; - using ::testing::Return; - - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDownloadRenameCases); ++i) { - // 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(new DownloadCreateInfo); - info->download_id = DownloadId(kValidIdDomain, static_cast<int>(i)); - info->prompt_user_for_save_location = false; - info->url_chain.push_back(GURL()); - const FilePath new_path(kDownloadRenameCases[i].suggested_path); - - MockDownloadFile* download_file(new MockDownloadFile()); - const DownloadId id = info->download_id; - ON_CALL(*download_file, GlobalId()) - .WillByDefault(ReturnRef(id)); - - AddMockDownloadToFileManager(info->download_id.local(), download_file); - - // |download_file| is owned by DownloadFileManager. - if (kDownloadRenameCases[i].expected_rename_count == 1) { - EXPECT_CALL(*download_file, Rename(new_path)) - .Times(1) - .WillOnce(Return(net::OK)); - } else { - ASSERT_EQ(2, kDownloadRenameCases[i].expected_rename_count); - FilePath crdownload(download_util::GetCrDownloadPath(new_path)); - EXPECT_CALL(*download_file, Rename(crdownload)) - .Times(1) - .WillOnce(Return(net::OK)); - EXPECT_CALL(*download_file, Rename(new_path)) - .Times(1) - .WillOnce(Return(net::OK)); - } - download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle()); - DownloadItem* download = GetActiveDownloadItem(i); - ASSERT_TRUE(download != NULL); - DownloadStateInfo state = download->GetStateInfo(); - state.danger = kDownloadRenameCases[i].danger; - download->SetFileCheckResults(state); - - int32* id_ptr = new int32; - *id_ptr = i; // Deleted in FileSelected(). - if (kDownloadRenameCases[i].finish_before_rename) { - OnResponseCompleted(i, 1024, std::string("fake_hash")); - message_loop_.RunAllPending(); - FileSelected(new_path, id_ptr); - } else { - FileSelected(new_path, id_ptr); - message_loop_.RunAllPending(); - OnResponseCompleted(i, 1024, std::string("fake_hash")); - } - // Validating the download item, so it will complete. - if (state.danger == content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE) - download->DangerousDownloadValidated(); - message_loop_.RunAllPending(); - } -} - -TEST_F(DownloadManagerTest, DownloadInterruptTest) { - using ::testing::_; - using ::testing::CreateFunctor; - using ::testing::Invoke; - using ::testing::Return; - - // 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(new DownloadCreateInfo); - info->download_id = DownloadId(kValidIdDomain, 0); - info->prompt_user_for_save_location = false; - info->url_chain.push_back(GURL()); - info->total_bytes = static_cast<int64>(kTestDataLen); - const FilePath new_path(FILE_PATH_LITERAL("foo.zip")); - const FilePath cr_path(download_util::GetCrDownloadPath(new_path)); - - MockDownloadFile* download_file(new MockDownloadFile()); - ON_CALL(*download_file, AppendDataToFile(_, _)) - .WillByDefault(Return(net::OK)); - - // |download_file| is owned by DownloadFileManager. - AddMockDownloadToFileManager(info->download_id.local(), download_file); - - EXPECT_CALL(*download_file, Rename(cr_path)) - .Times(1) - .WillOnce(Return(net::OK)); - - download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle()); - - DownloadItem* download = GetActiveDownloadItem(0); - ASSERT_TRUE(download != NULL); - scoped_ptr<DownloadItemModel> download_item_model( - new DownloadItemModel(download)); - - EXPECT_EQ(DownloadItem::IN_PROGRESS, download->GetState()); - scoped_ptr<ItemObserver> observer(new ItemObserver(download)); - - download_file->AppendDataToFile(kTestData, kTestDataLen); - - ContinueDownloadWithPath(download, new_path); - message_loop_.RunAllPending(); - EXPECT_TRUE(GetActiveDownloadItem(0) != NULL); - - int64 error_size = 3; - OnDownloadInterrupted(0, error_size, "", - DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED); - message_loop_.RunAllPending(); - - EXPECT_TRUE(GetActiveDownloadItem(0) == NULL); - EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS)); - EXPECT_TRUE(observer->hit_state(DownloadItem::INTERRUPTED)); - EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE)); - EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED)); - EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING)); - EXPECT_TRUE(observer->was_updated()); - EXPECT_FALSE(observer->was_opened()); - EXPECT_FALSE(download->GetFileExternallyRemoved()); - EXPECT_EQ(DownloadItem::INTERRUPTED, download->GetState()); - ui::DataUnits amount_units = ui::GetByteDisplayUnits(kTestDataLen); - string16 simple_size = - ui::FormatBytesWithUnits(error_size, amount_units, false); - string16 simple_total = base::i18n::GetDisplayStringInLTRDirectionality( - ui::FormatBytesWithUnits(kTestDataLen, amount_units, true)); - EXPECT_EQ(download_item_model->GetStatusText(), - l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_INTERRUPTED, - simple_size, - simple_total)); - - download->Cancel(true); - - EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS)); - EXPECT_TRUE(observer->hit_state(DownloadItem::INTERRUPTED)); - EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE)); - EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED)); - EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING)); - EXPECT_TRUE(observer->was_updated()); - EXPECT_FALSE(observer->was_opened()); - EXPECT_FALSE(download->GetFileExternallyRemoved()); - EXPECT_EQ(DownloadItem::INTERRUPTED, download->GetState()); - EXPECT_EQ(download->GetReceivedBytes(), error_size); - EXPECT_EQ(download->GetTotalBytes(), static_cast<int64>(kTestDataLen)); -} - -// Test the behavior of DownloadFileManager and DownloadManager in the event -// of a file error while writing the download to disk. -TEST_F(DownloadManagerTest, MAYBE_DownloadFileErrorTest) { - // Create a temporary file and a mock stream. - FilePath path; - ASSERT_TRUE(file_util::CreateTemporaryFile(&path)); - - // This file stream will be used, until the first rename occurs. - net::FileStream* stream = new net::FileStream; - ASSERT_EQ(0, stream->Open( - path, - base::PLATFORM_FILE_OPEN_ALWAYS | base::PLATFORM_FILE_WRITE)); - - // 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(new DownloadCreateInfo); - static const int32 local_id = 0; - info->download_id = DownloadId(kValidIdDomain, local_id); - info->prompt_user_for_save_location = false; - info->url_chain.push_back(GURL()); - info->total_bytes = static_cast<int64>(kTestDataLen * 3); - info->save_info.file_path = path; - info->save_info.file_stream.reset(stream); - - // Create a download file that we can insert errors into. - DownloadFileWithErrors* download_file(new DownloadFileWithErrors( - info.get(), download_manager_, false)); - download_file->Initialize(); - AddDownloadToFileManager(local_id, download_file); - - // |download_file| is owned by DownloadFileManager. - download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle()); - - DownloadItem* download = GetActiveDownloadItem(0); - ASSERT_TRUE(download != NULL); - // This will keep track of what should be displayed on the shelf. - scoped_ptr<DownloadItemModel> download_item_model( - new DownloadItemModel(download)); - - EXPECT_EQ(DownloadItem::IN_PROGRESS, download->GetState()); - scoped_ptr<ItemObserver> observer(new ItemObserver(download)); - - // Add some data before finalizing the file name. - UpdateData(local_id, kTestData, kTestDataLen); - - // Finalize the file name. - ContinueDownloadWithPath(download, path); - message_loop_.RunAllPending(); - EXPECT_TRUE(GetActiveDownloadItem(0) != NULL); - - // Add more data. - UpdateData(local_id, kTestData, kTestDataLen); - - // Add more data, but an error occurs. - download_file->set_forced_error(net::ERR_FAILED); - UpdateData(local_id, kTestData, kTestDataLen); - - // Check the state. The download should have been interrupted. - EXPECT_TRUE(GetActiveDownloadItem(0) == NULL); - EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS)); - EXPECT_TRUE(observer->hit_state(DownloadItem::INTERRUPTED)); - EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE)); - EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED)); - EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING)); - EXPECT_TRUE(observer->was_updated()); - EXPECT_FALSE(observer->was_opened()); - EXPECT_FALSE(download->GetFileExternallyRemoved()); - EXPECT_EQ(DownloadItem::INTERRUPTED, download->GetState()); - - // Check the download shelf's information. - size_t error_size = kTestDataLen * 3; - size_t total_size = kTestDataLen * 3; - ui::DataUnits amount_units = ui::GetByteDisplayUnits(kTestDataLen); - string16 simple_size = - ui::FormatBytesWithUnits(error_size, amount_units, false); - string16 simple_total = base::i18n::GetDisplayStringInLTRDirectionality( - ui::FormatBytesWithUnits(total_size, amount_units, true)); - EXPECT_EQ(l10n_util::GetStringFUTF16(IDS_DOWNLOAD_STATUS_INTERRUPTED, - simple_size, - simple_total), - download_item_model->GetStatusText()); - - // Clean up. - download->Cancel(true); - message_loop_.RunAllPending(); -} - -TEST_F(DownloadManagerTest, DownloadCancelTest) { - using ::testing::_; - using ::testing::CreateFunctor; - using ::testing::Invoke; - using ::testing::Return; - - // 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(new DownloadCreateInfo); - DownloadId id = DownloadId(kValidIdDomain, 0); - info->download_id = id; - info->prompt_user_for_save_location = false; - info->url_chain.push_back(GURL()); - const FilePath new_path(FILE_PATH_LITERAL("foo.zip")); - const FilePath cr_path(download_util::GetCrDownloadPath(new_path)); - - MockDownloadFile* download_file(new MockDownloadFile()); - ON_CALL(*download_file, AppendDataToFile(_, _)) - .WillByDefault(Return(net::OK)); - AddMockDownloadToFileManager(info->download_id.local(), download_file); - - // |download_file| is owned by DownloadFileManager. - EXPECT_CALL(*download_file, Rename(cr_path)) - .Times(1) - .WillOnce(Return(net::OK)); - - download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle()); - - DownloadItem* download = GetActiveDownloadItem(0); - ASSERT_TRUE(download != NULL); - scoped_ptr<DownloadItemModel> download_item_model( - new DownloadItemModel(download)); - - EXPECT_EQ(DownloadItem::IN_PROGRESS, download->GetState()); - scoped_ptr<ItemObserver> observer(new ItemObserver(download)); - - ContinueDownloadWithPath(download, new_path); - message_loop_.RunAllPending(); - EXPECT_TRUE(GetActiveDownloadItem(0) != NULL); - - download_file->AppendDataToFile(kTestData, kTestDataLen); - - download->Cancel(false); - message_loop_.RunAllPending(); - - EXPECT_TRUE(GetActiveDownloadItem(0) != NULL); - EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS)); - EXPECT_TRUE(observer->hit_state(DownloadItem::CANCELLED)); - EXPECT_FALSE(observer->hit_state(DownloadItem::INTERRUPTED)); - EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE)); - EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING)); - EXPECT_TRUE(observer->was_updated()); - EXPECT_FALSE(observer->was_opened()); - EXPECT_FALSE(download->GetFileExternallyRemoved()); - EXPECT_EQ(DownloadItem::CANCELLED, download->GetState()); - EXPECT_EQ(download_item_model->GetStatusText(), - l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_CANCELED)); - - file_manager()->CancelDownload(id); - - EXPECT_FALSE(file_util::PathExists(new_path)); - EXPECT_FALSE(file_util::PathExists(cr_path)); -} - -TEST_F(DownloadManagerTest, MAYBE_DownloadOverwriteTest) { - using ::testing::_; - using ::testing::CreateFunctor; - using ::testing::Invoke; - using ::testing::Return; - - // Create a temporary directory. - ScopedTempDir temp_dir_; - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - - // File names we're using. - const FilePath new_path(temp_dir_.path().AppendASCII("foo.txt")); - const FilePath cr_path(download_util::GetCrDownloadPath(new_path)); - EXPECT_FALSE(file_util::PathExists(new_path)); - - // Create the file that we will overwrite. Will be automatically cleaned - // up when temp_dir_ is destroyed. - FILE* fp = file_util::OpenFile(new_path, "w"); - file_util::CloseFile(fp); - EXPECT_TRUE(file_util::PathExists(new_path)); - - // Construct the unique file name that normally would be created, but - // which we will override. - int uniquifier = DownloadFile::GetUniquePathNumber(new_path); - FilePath unique_new_path = new_path; - EXPECT_NE(0, uniquifier); - DownloadFile::AppendNumberToPath(&unique_new_path, uniquifier); - - // 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(new DownloadCreateInfo); - info->download_id = DownloadId(kValidIdDomain, 0); - info->prompt_user_for_save_location = true; - info->url_chain.push_back(GURL()); - - download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle()); - - DownloadItem* download = GetActiveDownloadItem(0); - ASSERT_TRUE(download != NULL); - scoped_ptr<DownloadItemModel> download_item_model( - new DownloadItemModel(download)); - - EXPECT_EQ(DownloadItem::IN_PROGRESS, download->GetState()); - scoped_ptr<ItemObserver> observer(new ItemObserver(download)); - - // Create and initialize the download file. We're bypassing the first part - // of the download process and skipping to the part after the final file - // name has been chosen, so we need to initialize the download file - // properly. - DownloadFile* download_file( - new DownloadFileImpl(info.get(), new DownloadRequestHandle(), - download_manager_, false)); - download_file->Rename(cr_path); - // This creates the .crdownload version of the file. - download_file->Initialize(); - // |download_file| is owned by DownloadFileManager. - AddDownloadToFileManager(info->download_id.local(), download_file); - - ContinueDownloadWithPath(download, new_path); - message_loop_.RunAllPending(); - EXPECT_TRUE(GetActiveDownloadItem(0) != NULL); - - download_file->AppendDataToFile(kTestData, kTestDataLen); - - // Finish the download. - OnResponseCompleted(0, kTestDataLen, ""); - message_loop_.RunAllPending(); - - // Download is complete. - EXPECT_TRUE(GetActiveDownloadItem(0) == NULL); - EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS)); - EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED)); - EXPECT_FALSE(observer->hit_state(DownloadItem::INTERRUPTED)); - EXPECT_TRUE(observer->hit_state(DownloadItem::COMPLETE)); - EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING)); - EXPECT_TRUE(observer->was_updated()); - EXPECT_FALSE(observer->was_opened()); - EXPECT_FALSE(download->GetFileExternallyRemoved()); - EXPECT_EQ(DownloadItem::COMPLETE, download->GetState()); - EXPECT_EQ(download_item_model->GetStatusText(), string16()); - - EXPECT_TRUE(file_util::PathExists(new_path)); - EXPECT_FALSE(file_util::PathExists(cr_path)); - EXPECT_FALSE(file_util::PathExists(unique_new_path)); - std::string file_contents; - EXPECT_TRUE(file_util::ReadFileToString(new_path, &file_contents)); - EXPECT_EQ(std::string(kTestData), file_contents); -} - -TEST_F(DownloadManagerTest, MAYBE_DownloadRemoveTest) { - using ::testing::_; - using ::testing::CreateFunctor; - using ::testing::Invoke; - using ::testing::Return; - - // Create a temporary directory. - ScopedTempDir temp_dir_; - ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); - - // File names we're using. - const FilePath new_path(temp_dir_.path().AppendASCII("foo.txt")); - const FilePath cr_path(download_util::GetCrDownloadPath(new_path)); - EXPECT_FALSE(file_util::PathExists(new_path)); - - // 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(new DownloadCreateInfo); - info->download_id = DownloadId(kValidIdDomain, 0); - info->prompt_user_for_save_location = true; - info->url_chain.push_back(GURL()); - - download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle()); - - DownloadItem* download = GetActiveDownloadItem(0); - ASSERT_TRUE(download != NULL); - scoped_ptr<DownloadItemModel> download_item_model( - new DownloadItemModel(download)); - - EXPECT_EQ(DownloadItem::IN_PROGRESS, download->GetState()); - scoped_ptr<ItemObserver> observer(new ItemObserver(download)); - - // Create and initialize the download file. We're bypassing the first part - // of the download process and skipping to the part after the final file - // name has been chosen, so we need to initialize the download file - // properly. - DownloadFile* download_file( - new DownloadFileImpl(info.get(), new DownloadRequestHandle(), - download_manager_, false)); - download_file->Rename(cr_path); - // This creates the .crdownload version of the file. - download_file->Initialize(); - // |download_file| is owned by DownloadFileManager. - AddDownloadToFileManager(info->download_id.local(), download_file); - - ContinueDownloadWithPath(download, new_path); - message_loop_.RunAllPending(); - EXPECT_TRUE(GetActiveDownloadItem(0) != NULL); - - download_file->AppendDataToFile(kTestData, kTestDataLen); - - // Finish the download. - OnResponseCompleted(0, kTestDataLen, ""); - message_loop_.RunAllPending(); - - // Download is complete. - EXPECT_TRUE(GetActiveDownloadItem(0) == NULL); - EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS)); - EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED)); - EXPECT_FALSE(observer->hit_state(DownloadItem::INTERRUPTED)); - EXPECT_TRUE(observer->hit_state(DownloadItem::COMPLETE)); - EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING)); - EXPECT_TRUE(observer->was_updated()); - EXPECT_FALSE(observer->was_opened()); - EXPECT_FALSE(download->GetFileExternallyRemoved()); - EXPECT_EQ(DownloadItem::COMPLETE, download->GetState()); - EXPECT_EQ(download_item_model->GetStatusText(), string16()); - - EXPECT_TRUE(file_util::PathExists(new_path)); - EXPECT_FALSE(file_util::PathExists(cr_path)); - - // Remove the downloaded file. - ASSERT_TRUE(file_util::Delete(new_path, false)); - download->OnDownloadedFileRemoved(); - message_loop_.RunAllPending(); - - EXPECT_TRUE(GetActiveDownloadItem(0) == NULL); - EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS)); - EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED)); - EXPECT_FALSE(observer->hit_state(DownloadItem::INTERRUPTED)); - EXPECT_TRUE(observer->hit_state(DownloadItem::COMPLETE)); - EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING)); - EXPECT_TRUE(observer->was_updated()); - EXPECT_FALSE(observer->was_opened()); - EXPECT_TRUE(download->GetFileExternallyRemoved()); - EXPECT_EQ(DownloadItem::COMPLETE, download->GetState()); - EXPECT_EQ(download_item_model->GetStatusText(), - l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_REMOVED)); - - EXPECT_FALSE(file_util::PathExists(new_path)); -} |