summaryrefslogtreecommitdiffstats
path: root/content/browser
diff options
context:
space:
mode:
authorasanka@chromium.org <asanka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-30 23:32:06 +0000
committerasanka@chromium.org <asanka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-30 23:32:06 +0000
commit3d833de2590e5bcddec48b51691d088afb3d84e3 (patch)
tree66337201944575e32a60e36334076b4bb2be7874 /content/browser
parentbb8f10a98c8f3a96025c47100c6473e2ce9645ad (diff)
downloadchromium_src-3d833de2590e5bcddec48b51691d088afb3d84e3.zip
chromium_src-3d833de2590e5bcddec48b51691d088afb3d84e3.tar.gz
chromium_src-3d833de2590e5bcddec48b51691d088afb3d84e3.tar.bz2
Download filename determination refactor (1/3)
- Removes dependency on DownloadStateInfo in chrome/. - Adds unit tests for ChromeDownloadManagerDelegate. - Cleanup methods for filename determination in DownloadItem to eliminate setters. BUG=78085 TEST=unit tests Review URL: https://chromiumcodereview.appspot.com/10083010 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@139682 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser')
-rw-r--r--content/browser/download/download_file_manager.cc66
-rw-r--r--content/browser/download/download_file_manager.h74
-rw-r--r--content/browser/download/download_file_manager_unittest.cc82
-rw-r--r--content/browser/download/download_item_impl.cc302
-rw-r--r--content/browser/download/download_item_impl.h90
-rw-r--r--content/browser/download/download_item_impl_unittest.cc251
-rw-r--r--content/browser/download/download_manager_impl.cc150
-rw-r--r--content/browser/download/download_manager_impl.h10
-rw-r--r--content/browser/download/download_manager_impl_unittest.cc677
-rw-r--r--content/browser/download/download_state_info.cc41
-rw-r--r--content/browser/download/download_state_info.h55
11 files changed, 965 insertions, 833 deletions
diff --git a/content/browser/download/download_file_manager.cc b/content/browser/download/download_file_manager.cc
index a9ab8ff..40f1acb 100644
--- a/content/browser/download/download_file_manager.cc
+++ b/content/browser/download/download_file_manager.cc
@@ -335,25 +335,43 @@ void DownloadFileManager::OnDownloadManagerShutdown(DownloadManager* manager) {
// There are 2 possible rename cases where this method can be called:
// 1. tmp -> foo.crdownload (not final, safe)
// 2. tmp-> Unconfirmed.xxx.crdownload (not final, dangerous)
+// TODO(asanka): Merge with RenameCompletingDownloadFile() and move
+// uniquification logic into DownloadFile.
void DownloadFileManager::RenameInProgressDownloadFile(
- DownloadId global_id, const FilePath& full_path) {
+ DownloadId global_id,
+ const FilePath& full_path,
+ bool overwrite_existing_file,
+ const RenameCompletionCallback& callback) {
VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id
<< " full_path = \"" << full_path.value() << "\"";
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
DownloadFile* download_file = GetDownloadFile(global_id);
- if (!download_file)
+ if (!download_file) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(callback, FilePath()));
return;
+ }
VLOG(20) << __FUNCTION__ << "()"
<< " download_file = " << download_file->DebugString();
+ FilePath new_path(full_path);
+ if (!overwrite_existing_file) {
+ int uniquifier =
+ file_util::GetUniquePathNumber(new_path, FILE_PATH_LITERAL(""));
+ if (uniquifier > 0) {
+ new_path = new_path.InsertBeforeExtensionASCII(
+ StringPrintf(" (%d)", uniquifier));
+ }
+ }
- net::Error rename_error = download_file->Rename(full_path);
+ net::Error rename_error = download_file->Rename(new_path);
if (net::OK != rename_error) {
- // Error. Between the time the UI thread generated 'full_path' to the time
- // this code runs, something happened that prevents us from renaming.
CancelDownloadOnRename(global_id, rename_error);
+ new_path.clear();
}
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(callback, new_path));
}
// The DownloadManager in the UI thread has provided a final name for the
@@ -366,23 +384,23 @@ void DownloadFileManager::RenameInProgressDownloadFile(
void DownloadFileManager::RenameCompletingDownloadFile(
DownloadId global_id,
const FilePath& full_path,
- bool overwrite_existing_file) {
+ bool overwrite_existing_file,
+ const RenameCompletionCallback& callback) {
VLOG(20) << __FUNCTION__ << "()" << " id = " << global_id
<< " overwrite_existing_file = " << overwrite_existing_file
<< " full_path = \"" << full_path.value() << "\"";
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
DownloadFile* download_file = GetDownloadFile(global_id);
- if (!download_file)
+ if (!download_file) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(callback, FilePath()));
return;
-
- DCHECK(download_file->GetDownloadManager());
- DownloadManager* download_manager = download_file->GetDownloadManager();
+ }
VLOG(20) << __FUNCTION__ << "()"
<< " download_file = " << download_file->DebugString();
- int uniquifier = 0;
FilePath new_path = full_path;
if (!overwrite_existing_file) {
// Make our name unique at this point, as if a dangerous file is
@@ -392,7 +410,7 @@ void DownloadFileManager::RenameCompletingDownloadFile(
// not exists yet, so the second file gets the same name.
// This should not happen in the SAFE case, and we check for that in the UI
// thread.
- uniquifier =
+ int uniquifier =
file_util::GetUniquePathNumber(new_path, FILE_PATH_LITERAL(""));
if (uniquifier > 0) {
new_path = new_path.InsertBeforeExtensionASCII(
@@ -406,23 +424,27 @@ void DownloadFileManager::RenameCompletingDownloadFile(
// Error. Between the time the UI thread generated 'full_path' to the time
// this code runs, something happened that prevents us from renaming.
CancelDownloadOnRename(global_id, rename_error);
- return;
- }
-
+ new_path.clear();
+ } else {
#if defined(OS_MACOSX)
- // Done here because we only want to do this once; see
- // http://crbug.com/13120 for details.
- download_file->AnnotateWithSourceInformation();
+ // Done here because we only want to do this once; see
+ // http://crbug.com/13120 for details.
+ download_file->AnnotateWithSourceInformation();
#endif
+ }
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&DownloadManager::OnDownloadRenamedToFinalName,
- download_manager, global_id.local(), new_path, uniquifier));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(callback, new_path));
+}
+
+int DownloadFileManager::NumberOfActiveDownloads() const {
+ return downloads_.size();
}
// Called only from RenameInProgressDownloadFile and
// RenameCompletingDownloadFile on the FILE thread.
+// TODO(asanka): Use the RenameCompletionCallback instead of a separate
+// OnDownloadInterrupted call.
void DownloadFileManager::CancelDownloadOnRename(
DownloadId global_id, net::Error rename_error) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
diff --git a/content/browser/download/download_file_manager.h b/content/browser/download/download_file_manager.h
index 255dc3d..965a93c 100644
--- a/content/browser/download/download_file_manager.h
+++ b/content/browser/download/download_file_manager.h
@@ -44,6 +44,7 @@
#include "base/atomic_sequence_num.h"
#include "base/basictypes.h"
+#include "base/callback_forward.h"
#include "base/gtest_prod_util.h"
#include "base/hash_tables.h"
#include "base/memory/ref_counted.h"
@@ -70,9 +71,15 @@ class BoundNetLog;
}
// Manages all in progress downloads.
+// Methods are virtual to allow mocks--this class is not intended
+// to be a base class.
class CONTENT_EXPORT DownloadFileManager
: public base::RefCountedThreadSafe<DownloadFileManager> {
public:
+ // Callback used with RenameInProgressDownloadFile() and
+ // RenameCompletingDownloadFile().
+ typedef base::Callback<void(const FilePath&)> RenameCompletionCallback;
+
class DownloadFileFactory {
public:
virtual ~DownloadFileFactory() {}
@@ -91,56 +98,66 @@ class CONTENT_EXPORT DownloadFileManager
explicit DownloadFileManager(DownloadFileFactory* factory);
// Called on shutdown on the UI thread.
- void Shutdown();
+ virtual void Shutdown();
// Called on UI thread to make DownloadFileManager start the download.
- void StartDownload(DownloadCreateInfo* info,
- const DownloadRequestHandle& request_handle);
+ virtual void StartDownload(DownloadCreateInfo* info,
+ const DownloadRequestHandle& request_handle);
// Handlers for notifications sent from the IO thread and run on the
// FILE thread.
- void UpdateDownload(content::DownloadId global_id,
- content::DownloadBuffer* buffer);
+ virtual void UpdateDownload(content::DownloadId global_id,
+ content::DownloadBuffer* buffer);
// |reason| is the reason for interruption, if one occurs.
// |security_info| contains SSL information (cert_id, cert_status,
// security_bits, ssl_connection_status), which can be used to
// fine-tune the error message. It is empty if the transaction
// was not performed securely.
- void OnResponseCompleted(content::DownloadId global_id,
- content::DownloadInterruptReason reason,
- const std::string& security_info);
+ virtual void OnResponseCompleted(content::DownloadId global_id,
+ content::DownloadInterruptReason reason,
+ const std::string& security_info);
// Handlers for notifications sent from the UI thread and run on the
// FILE thread. These are both terminal actions with respect to the
// download file, as far as the DownloadFileManager is concerned -- if
// anything happens to the download file after they are called, it will
// be ignored.
- void CancelDownload(content::DownloadId id);
- void CompleteDownload(content::DownloadId id);
+ virtual void CancelDownload(content::DownloadId id);
+ virtual void CompleteDownload(content::DownloadId id);
// Called on FILE thread by DownloadManager at the beginning of its shutdown.
- void OnDownloadManagerShutdown(content::DownloadManager* manager);
-
- // The DownloadManager in the UI thread has provided an intermediate
- // .crdownload name for the download specified by |id|.
- void RenameInProgressDownloadFile(content::DownloadId id,
- const FilePath& full_path);
+ virtual void OnDownloadManagerShutdown(content::DownloadManager* manager);
+
+ // The DownloadManager in the UI thread has provided an intermediate name for
+ // the download specified by |id|. |overwrite_existing_file| indicates whether
+ // any existing file at |full_path| should be overwritten. If false, adds a
+ // uniquifier to |full_path| and uses the resulting name as the intermediate
+ // path for the download. Invokes |callback| with the new path on success. If
+ // the rename fails, calls CancelDownloadOnRename() and invokes |callback|
+ // with an empty FilePath().
+ virtual void RenameInProgressDownloadFile(
+ content::DownloadId id,
+ const FilePath& full_path,
+ bool overwrite_existing_file,
+ const RenameCompletionCallback& callback);
// The DownloadManager in the UI thread has provided a final name for the
- // download specified by |id|.
- // |overwrite_existing_file| prevents uniquification, and is used for SAFE
- // downloads, as the user may have decided to overwrite the file.
- // Sent from the UI thread and run on the FILE thread.
- void RenameCompletingDownloadFile(content::DownloadId id,
- const FilePath& full_path,
- bool overwrite_existing_file);
+ // download specified by |id|. |overwrite_existing_file| prevents
+ // uniquification, and is used for SAFE downloads, as the user may have
+ // decided to overwrite the file. Sent from the UI thread and run on the FILE
+ // thread. Invokes |callback| with the new path on success. If the rename
+ // fails, calls CancelDownloadOnRename() and invokes |callback| with an empty
+ // FilePath().
+ virtual void RenameCompletingDownloadFile(
+ content::DownloadId id,
+ const FilePath& full_path,
+ bool overwrite_existing_file,
+ const RenameCompletionCallback& callback);
// The number of downloads currently active on the DownloadFileManager.
// Primarily for testing.
- int NumberOfActiveDownloads() const {
- return downloads_.size();
- }
+ virtual int NumberOfActiveDownloads() const;
void SetFileFactoryForTesting(scoped_ptr<DownloadFileFactory> file_factory) {
download_file_factory_.reset(file_factory.release());
@@ -150,14 +167,15 @@ class CONTENT_EXPORT DownloadFileManager
return download_file_factory_.get(); // Explicitly NOT a scoped_ptr.
}
+ protected:
+ virtual ~DownloadFileManager();
+
private:
friend class base::RefCountedThreadSafe<DownloadFileManager>;
friend class DownloadFileManagerTest;
friend class DownloadManagerTest;
FRIEND_TEST_ALL_PREFIXES(DownloadManagerTest, StartDownload);
- ~DownloadFileManager();
-
// Timer helpers for updating the UI about the current progress of a download.
void StartUpdateTimer();
void StopUpdateTimer();
diff --git a/content/browser/download/download_file_manager_unittest.cc b/content/browser/download/download_file_manager_unittest.cc
index 15eab3a..43863c4 100644
--- a/content/browser/download/download_file_manager_unittest.cc
+++ b/content/browser/download/download_file_manager_unittest.cc
@@ -35,6 +35,15 @@ using ::testing::StrEq;
namespace {
+// MockDownloadManager with the addition of a mock callback used for testing.
+class TestDownloadManager : public MockDownloadManager {
+ public:
+ MOCK_METHOD2(OnDownloadRenamed,
+ void(int download_id, const FilePath& full_path));
+ private:
+ ~TestDownloadManager() {}
+};
+
class MockDownloadFileFactory :
public DownloadFileManager::DownloadFileFactory {
@@ -136,7 +145,7 @@ class DownloadFileManagerTest : public testing::Test {
}
virtual void SetUp() {
- download_manager_ = new MockDownloadManager();
+ download_manager_ = new TestDownloadManager();
request_handle_.reset(new MockDownloadRequestHandle(download_manager_));
download_file_factory_ = new MockDownloadFileFactory;
download_file_manager_ = new DownloadFileManager(download_file_factory_);
@@ -295,33 +304,9 @@ class DownloadFileManagerTest : public testing::Test {
net::Error rename_error,
RenameFileState state,
RenameFileOverwrite should_overwrite) {
- // Expected call sequence:
- // RenameInProgressDownloadFile/RenameCompletingDownloadFile
- // GetDownloadFile
- // DownloadFile::Rename
- //
- // On Error:
- // CancelDownloadOnRename
- // GetDownloadFile
- // DownloadFile::GetDownloadManager
- // No Manager:
- // DownloadFile::CancelDownloadRequest/return
- // Has Manager:
- // DownloadFile::BytesSoFar
- // Process one message in the message loop
- // DownloadManager::OnDownloadInterrupted
- //
- // On Success, if final rename:
- // Process one message in the message loop
- // DownloadManager::OnDownloadRenamedToFinalName
MockDownloadFile* file = download_file_factory_->GetExistingFile(id);
ASSERT_TRUE(file != NULL);
- if (state == COMPLETE || rename_error != net::OK) {
- EXPECT_CALL(*file, GetDownloadManager())
- .Times(AtLeast(1));
- }
-
EXPECT_CALL(*file, Rename(unique_path))
.Times(1)
.WillOnce(Return(rename_error));
@@ -332,13 +317,24 @@ class DownloadFileManagerTest : public testing::Test {
.WillRepeatedly(Return(byte_count_[id]));
EXPECT_CALL(*file, GetHashState())
.Times(AtLeast(1));
+ EXPECT_CALL(*file, GetDownloadManager())
+ .Times(AtLeast(1));
+ } else if (state == COMPLETE) {
+#if defined(OS_MACOSX)
+ EXPECT_CALL(*file, AnnotateWithSourceInformation());
+#endif
}
if (state == IN_PROGRESS) {
- download_file_manager_->RenameInProgressDownloadFile(id, new_path);
+ download_file_manager_->RenameInProgressDownloadFile(
+ id, new_path, (should_overwrite == OVERWRITE),
+ base::Bind(&TestDownloadManager::OnDownloadRenamed,
+ download_manager_, id.local()));
} else { // state == COMPLETE
download_file_manager_->RenameCompletingDownloadFile(
- id, new_path, (should_overwrite == OVERWRITE));
+ id, new_path, (should_overwrite == OVERWRITE),
+ base::Bind(&TestDownloadManager::OnDownloadRenamed,
+ download_manager_, id.local()));
}
if (rename_error != net::OK) {
@@ -350,11 +346,13 @@ class DownloadFileManagerTest : public testing::Test {
content::ConvertNetErrorToInterruptReason(
rename_error,
content::DOWNLOAD_INTERRUPT_FROM_DISK)));
+ EXPECT_CALL(*download_manager_,
+ OnDownloadRenamed(id.local(), FilePath()));
ProcessAllPendingMessages();
++error_count_[id];
- } else if (state == COMPLETE) {
- EXPECT_CALL(*download_manager_, OnDownloadRenamedToFinalName(
- id.local(), unique_path, _));
+ } else {
+ EXPECT_CALL(*download_manager_,
+ OnDownloadRenamed(id.local(), unique_path));
ProcessAllPendingMessages();
}
}
@@ -438,7 +436,7 @@ class DownloadFileManagerTest : public testing::Test {
}
protected:
- scoped_refptr<MockDownloadManager> download_manager_;
+ scoped_refptr<TestDownloadManager> download_manager_;
scoped_ptr<MockDownloadRequestHandle> request_handle_;
MockDownloadFileFactory* download_file_factory_;
scoped_refptr<DownloadFileManager> download_file_manager_;
@@ -560,6 +558,28 @@ TEST_F(DownloadFileManagerTest, RenameInProgress) {
CleanUp(dummy_id);
}
+TEST_F(DownloadFileManagerTest, RenameInProgressWithUniquification) {
+ // Same as StartDownload, at first.
+ DownloadCreateInfo* info = new DownloadCreateInfo;
+ DownloadId dummy_id(download_manager_.get(), kDummyDownloadId);
+ ScopedTempDir download_dir;
+ ASSERT_TRUE(download_dir.CreateUniqueTempDir());
+
+ StartDownload(info, dummy_id);
+
+ UpdateDownload(dummy_id, kTestData1, strlen(kTestData1), net::OK);
+ UpdateDownload(dummy_id, kTestData2, strlen(kTestData2), net::OK);
+ FilePath foo(download_dir.path().Append(FILE_PATH_LITERAL("foo.txt")));
+ FilePath unique_foo(foo.InsertBeforeExtension(FILE_PATH_LITERAL(" (1)")));
+ ASSERT_EQ(0, file_util::WriteFile(foo, "", 0));
+ RenameFile(dummy_id, foo, unique_foo, net::OK, IN_PROGRESS, DONT_OVERWRITE);
+ UpdateDownload(dummy_id, kTestData3, strlen(kTestData3), net::OK);
+
+ OnResponseCompleted(dummy_id, content::DOWNLOAD_INTERRUPT_REASON_NONE, "");
+
+ CleanUp(dummy_id);
+}
+
TEST_F(DownloadFileManagerTest, RenameInProgressWithError) {
// Same as StartDownload, at first.
DownloadCreateInfo* info = new DownloadCreateInfo;
diff --git a/content/browser/download/download_item_impl.cc b/content/browser/download/download_item_impl.cc
index b931744..2f967a8 100644
--- a/content/browser/download/download_item_impl.cc
+++ b/content/browser/download/download_item_impl.cc
@@ -164,15 +164,20 @@ DownloadItemImpl::DownloadItemImpl(Delegate* delegate,
const DownloadPersistentStoreInfo& info,
const net::BoundNetLog& bound_net_log)
: download_id_(download_id),
- full_path_(info.path),
+ current_path_(info.path),
+ target_path_(info.path),
+ target_disposition_(TARGET_DISPOSITION_OVERWRITE),
url_chain_(1, info.url),
referrer_url_(info.referrer_url),
+ transition_type_(content::PAGE_TRANSITION_LINK),
+ has_user_gesture_(false),
total_bytes_(info.total_bytes),
received_bytes_(info.received_bytes),
bytes_per_sec_(0),
last_reason_(content::DOWNLOAD_INTERRUPT_REASON_NONE),
start_tick_(base::TimeTicks()),
state_(static_cast<DownloadState>(info.state)),
+ danger_type_(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS),
start_time_(info.start_time),
end_time_(info.end_time),
db_handle_(info.db_handle),
@@ -189,7 +194,8 @@ DownloadItemImpl::DownloadItemImpl(Delegate* delegate,
opened_(info.opened),
open_enabled_(true),
delegate_delayed_complete_(false),
- bound_net_log_(bound_net_log) {
+ bound_net_log_(bound_net_log),
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
delegate_->Attach();
if (IsInProgress())
state_ = CANCELLED;
@@ -206,14 +212,17 @@ DownloadItemImpl::DownloadItemImpl(
DownloadRequestHandleInterface* request_handle,
bool is_otr,
const net::BoundNetLog& bound_net_log)
- : state_info_(info.save_info.file_path,
- info.has_user_gesture, info.transition_type,
- info.prompt_user_for_save_location),
- request_handle_(request_handle),
+ : request_handle_(request_handle),
download_id_(info.download_id),
+ target_disposition_(
+ (info.prompt_user_for_save_location) ?
+ TARGET_DISPOSITION_PROMPT : TARGET_DISPOSITION_OVERWRITE),
url_chain_(info.url_chain),
referrer_url_(info.referrer_url),
suggested_filename_(UTF16ToUTF8(info.save_info.suggested_name)),
+ forced_file_path_(info.save_info.file_path),
+ transition_type_(info.transition_type),
+ has_user_gesture_(info.has_user_gesture),
content_disposition_(info.content_disposition),
mime_type_(info.mime_type),
original_mime_type_(info.original_mime_type),
@@ -225,6 +234,7 @@ DownloadItemImpl::DownloadItemImpl(
last_reason_(content::DOWNLOAD_INTERRUPT_REASON_NONE),
start_tick_(base::TimeTicks::Now()),
state_(IN_PROGRESS),
+ danger_type_(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS),
start_time_(info.start_time),
db_handle_(DownloadItem::kUninitializedHandle),
delegate_(delegate),
@@ -240,7 +250,8 @@ DownloadItemImpl::DownloadItemImpl(
opened_(false),
open_enabled_(true),
delegate_delayed_complete_(false),
- bound_net_log_(bound_net_log) {
+ bound_net_log_(bound_net_log),
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
delegate_->Attach();
Init(true /* actively downloading */,
download_net_logs::SRC_NEW_DOWNLOAD);
@@ -269,9 +280,13 @@ DownloadItemImpl::DownloadItemImpl(Delegate* delegate,
const net::BoundNetLog& bound_net_log)
: request_handle_(new NullDownloadRequestHandle()),
download_id_(download_id),
- full_path_(path),
+ current_path_(path),
+ target_path_(path),
+ target_disposition_(TARGET_DISPOSITION_OVERWRITE),
url_chain_(1, url),
referrer_url_(GURL()),
+ transition_type_(content::PAGE_TRANSITION_LINK),
+ has_user_gesture_(false),
mime_type_(mime_type),
original_mime_type_(mime_type),
total_bytes_(0),
@@ -280,6 +295,7 @@ DownloadItemImpl::DownloadItemImpl(Delegate* delegate,
last_reason_(content::DOWNLOAD_INTERRUPT_REASON_NONE),
start_tick_(base::TimeTicks::Now()),
state_(IN_PROGRESS),
+ danger_type_(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS),
start_time_(base::Time::Now()),
db_handle_(DownloadItem::kUninitializedHandle),
delegate_(delegate),
@@ -295,7 +311,8 @@ DownloadItemImpl::DownloadItemImpl(Delegate* delegate,
opened_(false),
open_enabled_(true),
delegate_delayed_complete_(false),
- bound_net_log_(bound_net_log) {
+ bound_net_log_(bound_net_log),
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
delegate_->Attach();
Init(true /* actively downloading */,
download_net_logs::SRC_SAVE_PAGE_AS);
@@ -576,26 +593,35 @@ void DownloadItemImpl::TransitionTo(DownloadState new_state) {
bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE, NULL);
}
-void DownloadItemImpl::UpdateSafetyState() {
- SafetyState updated_value = state_info_.IsDangerous() ?
- DownloadItem::DANGEROUS : DownloadItem::SAFE;
+void DownloadItemImpl::SetDangerType(content::DownloadDangerType danger_type) {
+ danger_type_ = danger_type;
+ // Notify observers if the safety state has changed as a result of the new
+ // danger type.
+ SafetyState updated_value = IsDangerous() ?
+ DownloadItem::DANGEROUS : DownloadItem::SAFE;
if (updated_value != safety_state_) {
safety_state_ = updated_value;
-
bound_net_log_.AddEvent(
net::NetLog::TYPE_DOWNLOAD_ITEM_SAFETY_STATE_UPDATED,
make_scoped_refptr(new download_net_logs::ItemCheckedParameters(
GetDangerType(), GetSafetyState())));
-
UpdateObservers();
}
}
-void DownloadItemImpl::UpdateTarget() {
+void DownloadItemImpl::SetFullPath(const FilePath& new_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ VLOG(20) << __FUNCTION__ << "()"
+ << " new_path = \"" << new_path.value() << "\""
+ << " " << DebugString(true);
+ DCHECK(!new_path.empty());
+ current_path_ = new_path;
- if (state_info_.target_name.value().empty())
- state_info_.target_name = full_path_.BaseName();
+ bound_net_log_.AddEvent(
+ net::NetLog::TYPE_DOWNLOAD_ITEM_RENAMED,
+ make_scoped_refptr(
+ new download_net_logs::ItemRenamedParameters(
+ current_path_.AsUTF8Unsafe(), new_path.AsUTF8Unsafe())));
}
void DownloadItemImpl::Interrupted(int64 size,
@@ -632,8 +658,10 @@ void DownloadItemImpl::Delete(DeleteReason reason) {
NOTREACHED();
}
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(&DeleteDownloadedFile, full_path_));
+ // TODO(asanka): Avoid deleting a file that is still owned by DownloadFile.
+ if (!current_path_.empty())
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(&DeleteDownloadedFile, current_path_));
Remove();
// We have now been deleted.
}
@@ -678,32 +706,6 @@ int DownloadItemImpl::PercentComplete() const {
return static_cast<int>(received_bytes_ * 100.0 / total_bytes_);
}
-void DownloadItemImpl::OnPathDetermined(const FilePath& path) {
- full_path_ = path;
- // If we prompted the user, then target_name is stale. Allow it to be
- // populated by UpdateTarget().
- if (PromptUserForSaveLocation())
- state_info_.target_name.clear();
- UpdateTarget();
-}
-
-void DownloadItemImpl::Rename(const FilePath& full_path) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- VLOG(20) << __FUNCTION__ << "()"
- << " full_path = \"" << full_path.value() << "\""
- << " " << DebugString(true);
- DCHECK(!full_path.empty());
-
- bound_net_log_.AddEvent(
- net::NetLog::TYPE_DOWNLOAD_ITEM_RENAMED,
- make_scoped_refptr(
- new download_net_logs::ItemRenamedParameters(
- full_path_.AsUTF8Unsafe(), full_path.AsUTF8Unsafe())));
-
- full_path_ = full_path;
-}
-
void DownloadItemImpl::TogglePause() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -726,29 +728,32 @@ void DownloadItemImpl::OnDownloadCompleting(DownloadFileManager* file_manager) {
DCHECK_NE(DANGEROUS, GetSafetyState());
DCHECK(file_manager);
- // If we prompted the user for save location, then we should overwrite the
- // target. Otherwise, if the danger state was NOT_DANGEROUS, we already
- // uniquified the path and should overwrite.
- bool should_overwrite =
- (PromptUserForSaveLocation() ||
- GetDangerType() == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
+ // TODO(asanka): Reduce code duplication across the NeedsRename() and
+ // !NeedsRename() completion pathways.
if (NeedsRename()) {
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ bool should_overwrite =
+ (GetTargetDisposition() != DownloadItem::TARGET_DISPOSITION_UNIQUIFY);
+ DownloadFileManager::RenameCompletionCallback callback =
+ base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::Unretained(file_manager));
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
base::Bind(&DownloadFileManager::RenameCompletingDownloadFile,
- file_manager, download_id_,
- GetTargetFilePath(), should_overwrite));
- return;
+ file_manager, GetGlobalId(), GetTargetFilePath(),
+ should_overwrite, callback));
+ } else {
+ Completed();
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&DownloadFileManager::CompleteDownload,
+ file_manager, download_id_));
}
-
- Completed();
-
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&DownloadFileManager::CompleteDownload,
- file_manager, download_id_));
}
-void DownloadItemImpl::OnDownloadRenamedToFinalName(const FilePath& full_path) {
+void DownloadItemImpl::OnDownloadRenamedToFinalName(
+ DownloadFileManager* file_manager,
+ const FilePath& full_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
VLOG(20) << __FUNCTION__ << "()"
@@ -757,13 +762,32 @@ void DownloadItemImpl::OnDownloadRenamedToFinalName(const FilePath& full_path) {
<< " " << DebugString(false);
DCHECK(NeedsRename());
- Rename(full_path);
+ if (!full_path.empty()) {
+ // full_path is now the current and target file path.
+ target_path_ = full_path;
+ SetFullPath(full_path);
+ delegate_->DownloadRenamedToFinalName(this);
+
+ if (delegate_->ShouldOpenDownload(this))
+ Completed();
+ else
+ delegate_delayed_complete_ = true;
+
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&DownloadFileManager::CompleteDownload,
+ file_manager, GetGlobalId()));
+ }
+}
- if (delegate_->ShouldOpenDownload(this)) {
- Completed();
- } else {
- delegate_delayed_complete_ = true;
+void DownloadItemImpl::OnDownloadRenamedToIntermediateName(
+ const FilePath& full_path) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (!full_path.empty()) {
+ SetFullPath(full_path);
+ UpdateObservers();
}
+ delegate_->DownloadRenamedToIntermediateName(this);
}
bool DownloadItemImpl::MatchesQuery(const string16& query) const {
@@ -788,35 +812,33 @@ bool DownloadItemImpl::MatchesQuery(const string16& query) const {
if (base::i18n::StringSearchIgnoringCaseAndAccents(query, url_formatted))
return true;
+ // TODO(asanka): Change this to GetTargetFilePath() once DownloadQuery has
+ // been modified to work with target paths.
string16 path(GetFullPath().LossyDisplayName());
return base::i18n::StringSearchIgnoringCaseAndAccents(query, path);
}
-void DownloadItemImpl::SetFileCheckResults(const DownloadStateInfo& state) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- VLOG(20) << " " << __FUNCTION__ << "()" << " this = " << DebugString(true);
- state_info_ = state;
- VLOG(20) << " " << __FUNCTION__ << "()" << " this = " << DebugString(true);
-
- UpdateSafetyState();
-}
-
content::DownloadDangerType DownloadItemImpl::GetDangerType() const {
- return state_info_.danger;
-}
-
-void DownloadItemImpl::SetDangerType(content::DownloadDangerType danger_type) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- state_info_.danger = danger_type;
- UpdateSafetyState();
+ return danger_type_;
}
+// TODO(asanka): Unify GetSafetyState() and IsDangerous().
bool DownloadItemImpl::IsDangerous() const {
- return state_info_.IsDangerous();
+ // TODO(noelutz): At this point only the windows views UI supports
+ // warnings based on dangerous content.
+#ifdef OS_WIN
+ return (danger_type_ == content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE ||
+ danger_type_ == content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL ||
+ danger_type_ == content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT ||
+ danger_type_ == content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT);
+#else
+ return (danger_type_ == content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE ||
+ danger_type_ == content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL);
+#endif
}
DownloadPersistentStoreInfo DownloadItemImpl::GetPersistentStoreInfo() const {
+ // TODO(asanka): Persist GetTargetFilePath() as well.
return DownloadPersistentStoreInfo(GetFullPath(),
GetURL(),
GetReferrerUrl(),
@@ -843,18 +865,61 @@ content::BrowserContext* DownloadItemImpl::GetBrowserContext() const {
return delegate_->GetBrowserContext();
}
-FilePath DownloadItemImpl::GetTargetFilePath() const {
- return full_path_.DirName().Append(state_info_.target_name);
+const FilePath& DownloadItemImpl::GetTargetFilePath() const {
+ return target_path_;
+}
+
+DownloadItem::TargetDisposition DownloadItemImpl::GetTargetDisposition() const {
+ return target_disposition_;
+}
+
+void DownloadItemImpl::OnTargetPathDetermined(
+ const FilePath& target_path,
+ TargetDisposition disposition,
+ content::DownloadDangerType danger_type) {
+ // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ target_path_ = target_path;
+ target_disposition_ = disposition;
+ SetDangerType(danger_type);
+}
+
+void DownloadItemImpl::OnTargetPathSelected(const FilePath& target_path) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK_EQ(TARGET_DISPOSITION_PROMPT, target_disposition_);
+ target_path_ = target_path;
+}
+
+void DownloadItemImpl::OnContentCheckCompleted(
+ content::DownloadDangerType danger_type) {
+ // TODO(rdsmith): Change to DCHECK after http://crbug.com/85408 resolved.
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(AllDataSaved());
+ SetDangerType(danger_type);
+}
+
+void DownloadItemImpl::OnIntermediatePathDetermined(
+ DownloadFileManager* file_manager,
+ const FilePath& intermediate_path,
+ bool ok_to_overwrite) {
+ DownloadFileManager::RenameCompletionCallback callback =
+ base::Bind(&DownloadItemImpl::OnDownloadRenamedToIntermediateName,
+ weak_ptr_factory_.GetWeakPtr());
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&DownloadFileManager::RenameInProgressDownloadFile,
+ file_manager, GetGlobalId(), intermediate_path,
+ ok_to_overwrite, callback));
+}
+
+const FilePath& DownloadItemImpl::GetFullPath() const {
+ return current_path_;
}
FilePath DownloadItemImpl::GetFileNameToReportUser() const {
if (!display_name_.empty())
return display_name_;
- if (state_info_.path_uniquifier > 0) {
- return state_info_.target_name.InsertBeforeExtensionASCII(
- StringPrintf(" (%d)", state_info_.path_uniquifier));
- }
- return state_info_.target_name;
+ return target_path_.BaseName();
}
void DownloadItemImpl::SetDisplayName(const FilePath& name) {
@@ -863,7 +928,7 @@ void DownloadItemImpl::SetDisplayName(const FilePath& name) {
FilePath DownloadItemImpl::GetUserVerifiedFilePath() const {
return (safety_state_ == DownloadItem::SAFE) ?
- GetTargetFilePath() : full_path_;
+ GetTargetFilePath() : GetFullPath();
}
void DownloadItemImpl::OffThreadCancel(DownloadFileManager* file_manager) {
@@ -880,17 +945,18 @@ void DownloadItemImpl::Init(bool active,
download_net_logs::DownloadType download_type) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- UpdateTarget();
if (active)
download_stats::RecordDownloadCount(download_stats::START_COUNT);
+ if (target_path_.empty())
+ target_path_ = current_path_;
std::string file_name;
if (download_type == download_net_logs::SRC_HISTORY_IMPORT) {
- // full_path_ works for History and Save As versions.
- file_name = full_path_.AsUTF8Unsafe();
+ // target_path_ works for History and Save As versions.
+ file_name = target_path_.AsUTF8Unsafe();
} else {
// See if it's set programmatically.
- file_name = state_info_.force_file_name.AsUTF8Unsafe();
+ file_name = forced_file_path_.AsUTF8Unsafe();
// Possibly has a 'download' attribute for the anchor.
if (file_name.empty())
file_name = suggested_filename_;
@@ -924,6 +990,11 @@ void DownloadItemImpl::Init(bool active,
VLOG(20) << __FUNCTION__ << "() " << DebugString(true);
}
+bool DownloadItemImpl::NeedsRename() const {
+ DCHECK(target_path_.DirName() == current_path_.DirName());
+ return target_path_ != current_path_;
+}
+
// TODO(ahendrickson) -- Move |INTERRUPTED| from |IsCancelled()| to
// |IsPartialDownload()|, when resuming interrupted downloads is implemented.
bool DownloadItemImpl::IsPartialDownload() const {
@@ -985,8 +1056,8 @@ std::string DownloadItemImpl::DebugString(bool verbose) const {
" last_modified = '%s'"
" etag = '%s'"
" url_chain = \n\t\"%s\"\n\t"
- " target = \"%" PRFilePath "\""
- " full_path = \"%" PRFilePath "\"",
+ " full_path = \"%" PRFilePath "\""
+ " target_path = \"%" PRFilePath "\"",
GetDbHandle(),
GetTotalBytes(),
GetReceivedBytes(),
@@ -997,8 +1068,8 @@ std::string DownloadItemImpl::DebugString(bool verbose) const {
GetLastModifiedTime().c_str(),
GetETag().c_str(),
url_list.c_str(),
- state_info_.target_name.value().c_str(),
- GetFullPath().value().c_str());
+ GetFullPath().value().c_str(),
+ GetTargetFilePath().value().c_str());
} else {
description += base::StringPrintf(" url = \"%s\"", url_list.c_str());
}
@@ -1012,10 +1083,6 @@ bool DownloadItemImpl::AllDataSaved() const { return all_data_saved_; }
DownloadItem::DownloadState DownloadItemImpl::GetState() const {
return state_;
}
-const FilePath& DownloadItemImpl::GetFullPath() const { return full_path_; }
-void DownloadItemImpl::SetPathUniquifier(int uniquifier) {
- state_info_.path_uniquifier = uniquifier;
-}
const std::vector<GURL>& DownloadItemImpl::GetUrlChain() const {
return url_chain_;
}
@@ -1086,15 +1153,20 @@ DownloadItem::SafetyState DownloadItemImpl::GetSafetyState() const {
}
bool DownloadItemImpl::IsOtr() const { return is_otr_; }
bool DownloadItemImpl::GetAutoOpened() { return auto_opened_; }
-const FilePath& DownloadItemImpl::GetTargetName() const {
- return state_info_.target_name;
-}
-bool DownloadItemImpl::PromptUserForSaveLocation() const {
- return state_info_.prompt_user_for_save_location;
+FilePath DownloadItemImpl::GetTargetName() const {
+ return target_path_.BaseName();
}
-const FilePath& DownloadItemImpl::GetSuggestedPath() const {
- return state_info_.suggested_path;
+const FilePath& DownloadItemImpl::GetForcedFilePath() const {
+ // TODO(asanka): Get rid of GetForcedFilePath(). We should instead just
+ // require that clients respect GetTargetFilePath() if it is already set.
+ return forced_file_path_;
}
+bool DownloadItemImpl::HasUserGesture() const {
+ return has_user_gesture_;
+};
+content::PageTransition DownloadItemImpl::GetTransitionType() const {
+ return transition_type_;
+};
bool DownloadItemImpl::IsTemporary() const { return is_temporary_; }
void DownloadItemImpl::SetIsTemporary(bool temporary) {
is_temporary_ = temporary;
@@ -1108,10 +1180,6 @@ const std::string& DownloadItemImpl::GetETag() const { return etag_; }
content::DownloadInterruptReason DownloadItemImpl::GetLastReason() const {
return last_reason_;
}
-DownloadStateInfo DownloadItemImpl::GetStateInfo() const { return state_info_; }
-bool DownloadItemImpl::NeedsRename() const {
- return state_info_.target_name != full_path_.BaseName();
-}
void DownloadItemImpl::MockDownloadOpenForTesting() { open_enabled_ = false; }
DownloadItem::ExternalData*
diff --git a/content/browser/download/download_item_impl.h b/content/browser/download/download_item_impl.h
index 1bcdcd4..2b1d7c8 100644
--- a/content/browser/download/download_item_impl.h
+++ b/content/browser/download/download_item_impl.h
@@ -11,6 +11,7 @@
#include "base/basictypes.h"
#include "base/file_path.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/time.h"
#include "base/timer.h"
@@ -69,6 +70,8 @@ class CONTENT_EXPORT DownloadItemImpl : public content::DownloadItem {
virtual void DownloadCompleted(DownloadItem* download) = 0;
virtual void DownloadOpened(DownloadItem* download) = 0;
virtual void DownloadRemoved(DownloadItem* download) = 0;
+ virtual void DownloadRenamedToIntermediateName(DownloadItem* download) = 0;
+ virtual void DownloadRenamedToFinalName(DownloadItem* download) = 0;
// Assert consistent state for delgate object at various transitions.
virtual void AssertStateConsistent(DownloadItem* download) const = 0;
@@ -137,13 +140,9 @@ class CONTENT_EXPORT DownloadItemImpl : public content::DownloadItem {
virtual bool TimeRemaining(base::TimeDelta* remaining) const OVERRIDE;
virtual int64 CurrentSpeed() const OVERRIDE;
virtual int PercentComplete() const OVERRIDE;
- virtual void OnPathDetermined(const FilePath& path) OVERRIDE;
virtual bool AllDataSaved() const OVERRIDE;
- virtual void SetFileCheckResults(const DownloadStateInfo& state) OVERRIDE;
- virtual void Rename(const FilePath& full_path) OVERRIDE;
virtual void TogglePause() OVERRIDE;
virtual void OnDownloadCompleting(DownloadFileManager* file_manager) OVERRIDE;
- virtual void OnDownloadRenamedToFinalName(const FilePath& full_path) OVERRIDE;
virtual bool MatchesQuery(const string16& query) const OVERRIDE;
virtual bool IsPartialDownload() const OVERRIDE;
virtual bool IsInProgress() const OVERRIDE;
@@ -152,7 +151,18 @@ class CONTENT_EXPORT DownloadItemImpl : public content::DownloadItem {
virtual bool IsComplete() const OVERRIDE;
virtual DownloadState GetState() const OVERRIDE;
virtual const FilePath& GetFullPath() const OVERRIDE;
- virtual void SetPathUniquifier(int uniquifier) OVERRIDE;
+ virtual const FilePath& GetTargetFilePath() const OVERRIDE;
+ virtual TargetDisposition GetTargetDisposition() const OVERRIDE;
+ virtual void OnTargetPathDetermined(
+ const FilePath& target_path,
+ TargetDisposition disposition,
+ content::DownloadDangerType danger_type) OVERRIDE;
+ virtual void OnTargetPathSelected(const FilePath& target_path) OVERRIDE;
+ virtual void OnContentCheckCompleted(
+ content::DownloadDangerType danger_type) OVERRIDE;
+ virtual void OnIntermediatePathDetermined(DownloadFileManager* file_manager,
+ const FilePath& path,
+ bool ok_to_overwrite) OVERRIDE;
virtual const GURL& GetURL() const OVERRIDE;
virtual const std::vector<GURL>& GetUrlChain() const OVERRIDE;
virtual const GURL& GetOriginalUrl() const OVERRIDE;
@@ -182,13 +192,13 @@ class CONTENT_EXPORT DownloadItemImpl : public content::DownloadItem {
virtual bool GetFileExternallyRemoved() const OVERRIDE;
virtual SafetyState GetSafetyState() const OVERRIDE;
virtual content::DownloadDangerType GetDangerType() const OVERRIDE;
- virtual void SetDangerType(content::DownloadDangerType danger_type) OVERRIDE;
virtual bool IsDangerous() const OVERRIDE;
virtual bool GetAutoOpened() OVERRIDE;
- virtual const FilePath& GetTargetName() const OVERRIDE;
- virtual bool PromptUserForSaveLocation() const OVERRIDE;
+ virtual FilePath GetTargetName() const OVERRIDE;
+ virtual const FilePath& GetForcedFilePath() const OVERRIDE;
+ virtual bool HasUserGesture() const OVERRIDE;
+ virtual content::PageTransition GetTransitionType() const OVERRIDE;
virtual bool IsOtr() const OVERRIDE;
- virtual const FilePath& GetSuggestedPath() const OVERRIDE;
virtual bool IsTemporary() const OVERRIDE;
virtual void SetIsTemporary(bool temporary) OVERRIDE;
virtual void SetOpened(bool opened) OVERRIDE;
@@ -198,14 +208,11 @@ class CONTENT_EXPORT DownloadItemImpl : public content::DownloadItem {
virtual content::DownloadInterruptReason GetLastReason() const OVERRIDE;
virtual content::DownloadPersistentStoreInfo
GetPersistentStoreInfo() const OVERRIDE;
- virtual DownloadStateInfo GetStateInfo() const OVERRIDE;
virtual content::BrowserContext* GetBrowserContext() const OVERRIDE;
virtual content::WebContents* GetWebContents() const OVERRIDE;
- virtual FilePath GetTargetFilePath() const OVERRIDE;
virtual FilePath GetFileNameToReportUser() const OVERRIDE;
virtual void SetDisplayName(const FilePath& name) OVERRIDE;
virtual FilePath GetUserVerifiedFilePath() const OVERRIDE;
- virtual bool NeedsRename() const OVERRIDE;
virtual void OffThreadCancel(DownloadFileManager* file_manager) OVERRIDE;
virtual std::string DebugString(bool verbose) const OVERRIDE;
virtual void MockDownloadOpenForTesting() OVERRIDE;
@@ -220,6 +227,10 @@ class CONTENT_EXPORT DownloadItemImpl : public content::DownloadItem {
// this is.
void Init(bool active, download_net_logs::DownloadType download_type);
+ // Returns true if the download still needs to be renamed to
+ // GetTargetFilePath().
+ bool NeedsRename() const;
+
// Internal helper for maintaining consistent received and total sizes, and
// hash state.
void UpdateProgress(int64 bytes_so_far, const std::string& hash_state);
@@ -242,20 +253,19 @@ class CONTENT_EXPORT DownloadItemImpl : public content::DownloadItem {
// Call to transition state; all state transitions should go through this.
void TransitionTo(DownloadState new_state);
- // Called when safety_state_ should be recomputed from is_dangerous_file
- // and is_dangerous_url.
- void UpdateSafetyState();
+ // Set the |danger_type_| and invoke obserers if necessary.
+ void SetDangerType(content::DownloadDangerType danger_type);
- // Helper function to recompute |state_info_.target_name| when
- // it may have changed. (If it's non-null it should be left alone,
- // otherwise updated from |full_path_|.)
- void UpdateTarget();
+ // Set the |current_path_| to |new_path|.
+ void SetFullPath(const FilePath& new_path);
- // State information used by the download manager.
- DownloadStateInfo state_info_;
+ // Callback invoked when the download has been renamed to its final name.
+ void OnDownloadRenamedToFinalName(DownloadFileManager* file_manager,
+ const FilePath& full_path);
- // Display name for the download if different from the target filename.
- FilePath display_name_;
+ // Callback invoked when the download has been renamed to its intermediate
+ // name.
+ void OnDownloadRenamedToIntermediateName(const FilePath& full_path);
// The handle to the request information. Used for operations outside the
// download system.
@@ -264,8 +274,23 @@ class CONTENT_EXPORT DownloadItemImpl : public content::DownloadItem {
// Download ID assigned by DownloadResourceHandler.
content::DownloadId download_id_;
- // Full path to the downloaded or downloading file.
- FilePath full_path_;
+ // Display name for the download. If this is empty, then the display name is
+ // considered to be |target_path_.BaseName()|.
+ FilePath display_name_;
+
+ // Full path to the downloaded or downloading file. This is the path to the
+ // physical file, if one exists. The final target path is specified by
+ // |target_path_|. |current_path_| can be empty if the in-progress path hasn't
+ // been determined.
+ FilePath current_path_;
+
+ // Target path of an in-progress download. We may be downloading to a
+ // temporary or intermediate file (specified by |current_path_|. Once the
+ // download completes, we will rename the file to |target_path_|.
+ FilePath target_path_;
+
+ // Whether the target should be overwritten, uniquified or prompted for.
+ TargetDisposition target_disposition_;
// The chain of redirects that leading up to and including the final URL.
std::vector<GURL> url_chain_;
@@ -278,6 +303,16 @@ class CONTENT_EXPORT DownloadItemImpl : public content::DownloadItem {
// http://www.whatwg.org/specs/web-apps/current-work/#downloading-hyperlinks
std::string suggested_filename_;
+ // If non-empty, contains an externally supplied path that should be used as
+ // the target path.
+ FilePath forced_file_path_;
+
+ // Page transition that triggerred the download.
+ content::PageTransition transition_type_;
+
+ // Whether the download was triggered with a user gesture.
+ bool has_user_gesture_;
+
// Information from the request.
// Content-disposition field from the header.
std::string content_disposition_;
@@ -331,6 +366,9 @@ class CONTENT_EXPORT DownloadItemImpl : public content::DownloadItem {
// The current state of this download.
DownloadState state_;
+ // Current danger type for the download.
+ content::DownloadDangerType danger_type_;
+
// The views of this item in the download shelf and download contents.
ObserverList<Observer> observers_;
@@ -394,6 +432,8 @@ class CONTENT_EXPORT DownloadItemImpl : public content::DownloadItem {
// Net log to use for this download.
const net::BoundNetLog bound_net_log_;
+ base::WeakPtrFactory<DownloadItemImpl> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(DownloadItemImpl);
};
diff --git a/content/browser/download/download_item_impl_unittest.cc b/content/browser/download/download_item_impl_unittest.cc
index d4c62a0..0700f88 100644
--- a/content/browser/download/download_item_impl_unittest.cc
+++ b/content/browser/download/download_item_impl_unittest.cc
@@ -6,6 +6,7 @@
#include "base/stl_util.h"
#include "base/threading/thread.h"
#include "content/browser/download/download_create_info.h"
+#include "content/browser/download/download_file_manager.h"
#include "content/browser/download/download_item_impl.h"
#include "content/browser/download/download_request_handle.h"
#include "content/public/browser/download_id.h"
@@ -21,6 +22,9 @@ using content::DownloadItem;
using content::DownloadManager;
using content::MockDownloadItem;
using content::WebContents;
+using ::testing::_;
+using ::testing::AllOf;
+using ::testing::Property;
DownloadId::Domain kValidDownloadItemIdDomain = "valid DownloadId::Domain";
@@ -36,6 +40,8 @@ class MockDelegate : public DownloadItemImpl::Delegate {
MOCK_METHOD1(DownloadCompleted, void(DownloadItem* download));
MOCK_METHOD1(DownloadOpened, void(DownloadItem* download));
MOCK_METHOD1(DownloadRemoved, void(DownloadItem* download));
+ MOCK_METHOD1(DownloadRenamedToIntermediateName, void(DownloadItem* download));
+ MOCK_METHOD1(DownloadRenamedToFinalName, void(DownloadItem* download));
MOCK_CONST_METHOD1(AssertStateConsistent, void(DownloadItem* download));
};
@@ -49,8 +55,58 @@ class MockRequestHandle : public DownloadRequestHandleInterface {
MOCK_CONST_METHOD0(DebugString, std::string());
};
+class MockDownloadFileFactory
+ : public DownloadFileManager::DownloadFileFactory {
+ public:
+ MOCK_METHOD5(CreateFile,
+ content::DownloadFile*(DownloadCreateInfo*,
+ const DownloadRequestHandle&,
+ DownloadManager*,
+ bool,
+ const net::BoundNetLog&));
+};
+
+class MockDownloadFileManager : public DownloadFileManager {
+ public:
+ MockDownloadFileManager();
+ MOCK_METHOD0(Shutdown, void());
+ MOCK_METHOD2(StartDownload,
+ void(DownloadCreateInfo*, const DownloadRequestHandle&));
+ MOCK_METHOD2(UpdateDownload, void(DownloadId, content::DownloadBuffer*));
+ MOCK_METHOD3(OnResponseCompleted,
+ void(DownloadId, content::DownloadInterruptReason,
+ const std::string&));
+ MOCK_METHOD1(CancelDownload, void(DownloadId));
+ MOCK_METHOD1(CompleteDownload, void(DownloadId));
+ MOCK_METHOD1(OnDownloadManagerShutdown, void(DownloadManager*));
+ MOCK_METHOD4(RenameInProgressDownloadFile,
+ void(DownloadId, const FilePath&, bool,
+ const RenameCompletionCallback&));
+ MOCK_METHOD4(RenameCompletingDownloadFile,
+ void(DownloadId, const FilePath&, bool,
+ const RenameCompletionCallback&));
+ MOCK_CONST_METHOD0(NumberOfActiveDownloads, int());
+ private:
+ ~MockDownloadFileManager() {}
+};
+
+// Schedules a task to invoke the RenameCompletionCallback with |new_path| on
+// the UI thread. Should only be used as the action for
+// MockDownloadFileManager::Rename*DownloadFile as follows:
+// EXPECT_CALL(mock_download_file_manager,
+// RenameInProgressDownloadFile(_,_,_,_))
+// .WillOnce(ScheduleRenameCallback(new_path));
+ACTION_P(ScheduleRenameCallback, new_path) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(arg3, new_path));
+}
+
+MockDownloadFileManager::MockDownloadFileManager()
+ : DownloadFileManager(new MockDownloadFileFactory) {
}
+} // namespace
+
class DownloadItemTest : public testing::Test {
public:
class MockObserver : public DownloadItem::Observer {
@@ -78,7 +134,8 @@ class DownloadItemTest : public testing::Test {
};
DownloadItemTest()
- : ui_thread_(BrowserThread::UI, &loop_) {
+ : ui_thread_(BrowserThread::UI, &loop_),
+ file_thread_(BrowserThread::FILE, &loop_) {
}
~DownloadItemTest() {
@@ -125,10 +182,18 @@ class DownloadItemTest : public testing::Test {
delete item;
}
+ void RunAllPendingInMessageLoops() {
+ loop_.RunAllPending();
+ }
+
+ MockDelegate* mock_delegate() {
+ return &delegate_;
+ }
+
private:
MessageLoopForUI loop_;
- // UI thread.
- content::TestBrowserThread ui_thread_;
+ content::TestBrowserThread ui_thread_; // UI thread
+ content::TestBrowserThread file_thread_; // FILE thread
testing::NiceMock<MockDelegate> delegate_;
std::set<DownloadItem*> allocated_downloads_;
};
@@ -149,7 +214,6 @@ const FilePath::CharType kDummyPath[] = FILE_PATH_LITERAL("/testpath");
// void ShowDownloadInShell();
// void CompleteDelayedDownload();
// void OnDownloadCompleting(DownloadFileManager* file_manager);
-// void OnDownloadRenamedToFinalName(const FilePath& full_path);
// set_* mutators
TEST_F(DownloadItemTest, NotificationAfterUpdate) {
@@ -219,56 +283,110 @@ TEST_F(DownloadItemTest, NotificationAfterRemove) {
ASSERT_TRUE(observer.CheckUpdated());
}
-TEST_F(DownloadItemTest, NotificationAfterSetFileCheckResults) {
- // Setting to safe should not trigger any notifications
+TEST_F(DownloadItemTest, NotificationAfterOnTargetPathDetermined) {
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());
+ // Calling OnTargetPathDetermined does not trigger notification if danger type
+ // is NOT_DANGEROUS.
+ safe_item->OnTargetPathDetermined(
+ FilePath(kDummyPath), DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+ content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
+ EXPECT_FALSE(safe_observer.CheckUpdated());
+
+ DownloadItem* dangerous_item = CreateDownloadItem(DownloadItem::IN_PROGRESS);
+ MockObserver dangerous_observer(dangerous_item);
+
+ // Calling OnTargetPathDetermined does trigger notification if danger type
+ // anything other than NOT_DANGEROUS.
+ dangerous_item->OnTargetPathDetermined(
+ FilePath(kDummyPath), DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+ content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE);
+ EXPECT_TRUE(dangerous_observer.CheckUpdated());
+}
- // Setting to unsafe url or unsafe file should trigger notification
+TEST_F(DownloadItemTest, NotificationAfterOnTargetPathSelected) {
+ DownloadItem* item = CreateDownloadItem(DownloadItem::IN_PROGRESS);
+ MockObserver observer(item);
+
+ item->OnTargetPathDetermined(
+ FilePath(kDummyPath), DownloadItem::TARGET_DISPOSITION_PROMPT,
+ content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
+ item->OnTargetPathSelected(FilePath(kDummyPath));
+ EXPECT_FALSE(observer.CheckUpdated());
+}
+
+TEST_F(DownloadItemTest, NotificationAfterOnContentCheckCompleted) {
+ // Setting to NOT_DANGEROUS does not trigger a notification.
+ DownloadItem* safe_item = CreateDownloadItem(DownloadItem::IN_PROGRESS);
+ MockObserver safe_observer(safe_item);
+
+ safe_item->OnTargetPathDetermined(
+ FilePath(kDummyPath), DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+ content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
+ EXPECT_FALSE(safe_observer.CheckUpdated());
+ safe_item->OnAllDataSaved(1, "");
+ EXPECT_TRUE(safe_observer.CheckUpdated());
+ safe_item->OnContentCheckCompleted(
+ content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
+ EXPECT_FALSE(safe_observer.CheckUpdated());
+
+ // Setting to unsafe url or unsafe file should trigger a 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->OnTargetPathDetermined(
+ FilePath(kDummyPath), DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+ content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
+ EXPECT_FALSE(unsafeurl_observer.CheckUpdated());
+ unsafeurl_item->OnAllDataSaved(1, "");
+ EXPECT_TRUE(unsafeurl_observer.CheckUpdated());
+ unsafeurl_item->OnContentCheckCompleted(
+ content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL);
+ EXPECT_TRUE(unsafeurl_observer.CheckUpdated());
unsafeurl_item->DangerousDownloadValidated();
- ASSERT_TRUE(unsafeurl_observer.CheckUpdated());
+ EXPECT_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->OnTargetPathDetermined(
+ FilePath(kDummyPath), DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+ content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
+ EXPECT_FALSE(unsafefile_observer.CheckUpdated());
+ unsafefile_item->OnAllDataSaved(1, "");
+ EXPECT_TRUE(unsafefile_observer.CheckUpdated());
+ unsafefile_item->OnContentCheckCompleted(
+ content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE);
+ EXPECT_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());
+ EXPECT_TRUE(unsafefile_observer.CheckUpdated());
}
-TEST_F(DownloadItemTest, NotificationAfterRename) {
+// DownloadItemImpl::OnIntermediatePathDetermined will schedule a task to run
+// DownloadFileManager::RenameInProgressDownloadFile(). Once the rename
+// completes, DownloadItemImpl receives a notification with the new file
+// name. Check that observers are updated when the new filename is available and
+// not before.
+TEST_F(DownloadItemTest, NotificationAfterOnIntermediatePathDetermined) {
DownloadItem* item = CreateDownloadItem(DownloadItem::IN_PROGRESS);
MockObserver observer(item);
-
- // Calling Rename does not trigger notification
- item->Rename(FilePath(kDummyPath));
- ASSERT_FALSE(observer.CheckUpdated());
+ FilePath intermediate_path(kDummyPath);
+ FilePath new_intermediate_path(intermediate_path.AppendASCII("foo"));
+ scoped_refptr<MockDownloadFileManager> file_manager(
+ new MockDownloadFileManager);
+ EXPECT_CALL(*file_manager.get(),
+ RenameInProgressDownloadFile(_,intermediate_path,false,_))
+ .WillOnce(ScheduleRenameCallback(new_intermediate_path));
+
+ item->OnIntermediatePathDetermined(file_manager.get(), intermediate_path,
+ false /* ok_to_overwrite */);
+ EXPECT_FALSE(observer.CheckUpdated());
+ RunAllPendingInMessageLoops();
+ EXPECT_TRUE(observer.CheckUpdated());
+ EXPECT_EQ(new_intermediate_path, item->GetFullPath());
}
TEST_F(DownloadItemTest, NotificationAfterTogglePause) {
@@ -284,14 +402,11 @@ TEST_F(DownloadItemTest, NotificationAfterTogglePause) {
TEST_F(DownloadItemTest, DisplayName) {
DownloadItem* item = CreateDownloadItem(DownloadItem::IN_PROGRESS);
- DownloadStateInfo info = item->GetStateInfo();
- info.target_name = FilePath(FILE_PATH_LITERAL("foo.bar"));
- item->SetFileCheckResults(info);
+ item->OnTargetPathDetermined(FilePath(kDummyPath).AppendASCII("foo.bar"),
+ DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+ content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
EXPECT_EQ(FILE_PATH_LITERAL("foo.bar"),
item->GetFileNameToReportUser().value());
- item->SetPathUniquifier(1);
- EXPECT_EQ(FILE_PATH_LITERAL("foo (1).bar"),
- item->GetFileNameToReportUser().value());
item->SetDisplayName(FilePath(FILE_PATH_LITERAL("new.name")));
EXPECT_EQ(FILE_PATH_LITERAL("new.name"),
item->GetFileNameToReportUser().value());
@@ -364,6 +479,60 @@ TEST_F(DownloadItemTest, ExternalData) {
EXPECT_EQ(3, destructor_called);
}
+// Test that the delegate is invoked after the download file is renamed.
+// Delegate::DownloadRenamedToIntermediateName() should be invoked when the
+// download is renamed to the intermediate name.
+// Delegate::DownloadRenamedToFinalName() should be invoked after the final
+// rename.
+TEST_F(DownloadItemTest, CallbackAfterRenameToIntermediateName) {
+ DownloadItem* item = CreateDownloadItem(DownloadItem::IN_PROGRESS);
+ FilePath intermediate_path(kDummyPath);
+ FilePath new_intermediate_path(intermediate_path.AppendASCII("foo"));
+ FilePath final_path(intermediate_path.AppendASCII("bar"));
+ scoped_refptr<MockDownloadFileManager> file_manager(
+ new MockDownloadFileManager);
+ EXPECT_CALL(*file_manager.get(),
+ RenameInProgressDownloadFile(item->GetGlobalId(),
+ intermediate_path, false, _))
+ .WillOnce(ScheduleRenameCallback(new_intermediate_path));
+ // DownloadItemImpl should invoke this callback on the delegate once the
+ // download is renamed to the intermediate name. Also check that GetFullPath()
+ // returns the intermediate path at the time of the call.
+ EXPECT_CALL(*mock_delegate(),
+ DownloadRenamedToIntermediateName(
+ AllOf(item,
+ Property(&DownloadItem::GetFullPath,
+ new_intermediate_path))));
+ item->OnTargetPathDetermined(final_path,
+ DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+ content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
+ item->OnIntermediatePathDetermined(file_manager.get(), intermediate_path,
+ false /* ok_to_overwrite */);
+ RunAllPendingInMessageLoops();
+ // All the callbacks should have happened by now.
+ ::testing::Mock::VerifyAndClearExpectations(file_manager.get());
+ ::testing::Mock::VerifyAndClearExpectations(mock_delegate());
+
+ EXPECT_CALL(*file_manager.get(),
+ RenameCompletingDownloadFile(item->GetGlobalId(),
+ final_path, true, _))
+ .WillOnce(ScheduleRenameCallback(final_path));
+ EXPECT_CALL(*file_manager.get(), CompleteDownload(item->GetGlobalId()));
+ // DownloadItemImpl should invoke this callback on the delegate after the
+ // final rename has completed. Also check that GetFullPath() and
+ // GetTargetFilePath() return the final path at the time of the call.
+ EXPECT_CALL(*mock_delegate(),
+ DownloadRenamedToFinalName(
+ AllOf(item,
+ Property(&DownloadItem::GetFullPath, final_path),
+ Property(&DownloadItem::GetTargetFilePath,
+ final_path))));
+ item->OnDownloadCompleting(file_manager.get());
+ RunAllPendingInMessageLoops();
+ ::testing::Mock::VerifyAndClearExpectations(file_manager.get());
+ ::testing::Mock::VerifyAndClearExpectations(mock_delegate());
+}
+
TEST(MockDownloadItem, Compiles) {
MockDownloadItem mock_item;
}
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc
index aae7f8a..3296daa 100644
--- a/content/browser/download/download_manager_impl.cc
+++ b/content/browser/download/download_manager_impl.cc
@@ -259,7 +259,8 @@ void DownloadManagerImpl::GetTemporaryDownloads(
for (DownloadMap::iterator it = history_downloads_.begin();
it != history_downloads_.end(); ++it) {
if (it->second->IsTemporary() &&
- (dir_path.empty() || it->second->GetFullPath().DirName() == dir_path))
+ (dir_path.empty() ||
+ it->second->GetTargetFilePath().DirName() == dir_path))
result->push_back(it->second);
}
}
@@ -271,7 +272,8 @@ void DownloadManagerImpl::GetAllDownloads(
for (DownloadMap::iterator it = history_downloads_.begin();
it != history_downloads_.end(); ++it) {
if (!it->second->IsTemporary() &&
- (dir_path.empty() || it->second->GetFullPath().DirName() == dir_path))
+ (dir_path.empty() ||
+ it->second->GetTargetFilePath().DirName() == dir_path))
result->push_back(it->second);
}
}
@@ -377,29 +379,18 @@ void DownloadManagerImpl::RestartDownload(int32 download_id) {
VLOG(20) << __FUNCTION__ << "()"
<< " download = " << download->DebugString(true);
- FilePath suggested_path = download->GetSuggestedPath();
-
- if (download->PromptUserForSaveLocation()) {
+ if (download->GetTargetDisposition() ==
+ DownloadItem::TARGET_DISPOSITION_PROMPT) {
// We must ask the user for the place to put the download.
WebContents* contents = download->GetWebContents();
- FilePath target_path;
- // If |download| is a potentially dangerous file, then |suggested_path|
- // contains the intermediate name instead of the final download
- // filename. The latter is GetTargetName().
- if (download->GetDangerType() !=
- content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)
- target_path = suggested_path.DirName().Append(download->GetTargetName());
- else
- target_path = suggested_path;
-
- delegate_->ChooseDownloadPath(contents, target_path,
+ delegate_->ChooseDownloadPath(contents, download->GetTargetFilePath(),
download_id);
FOR_EACH_OBSERVER(Observer, observers_,
SelectFileDialogDisplayed(this, download_id));
} else {
- // No prompting for download, just continue with the suggested name.
- ContinueDownloadWithPath(download, suggested_path);
+ // No prompting for download, just continue with the current target path.
+ OnTargetPathAvailable(download);
}
}
@@ -458,13 +449,9 @@ DownloadItem* DownloadManagerImpl::CreateSavePackageDownloadItem(
return download;
}
-// For non-safe downloads with no prompting, |chosen_file| is the intermediate
-// path for saving the in-progress download. The final target filename for these
-// is |download->GetTargetName()|. For all other downloads (non-safe downloads
-// for which we have prompted for a save location, and all safe downloads),
-// |chosen_file| is the final target download path.
-void DownloadManagerImpl::ContinueDownloadWithPath(
- DownloadItem* download, const FilePath& chosen_file) {
+// The target path for the download item is now valid. We proceed with the
+// determination of an intermediate path.
+void DownloadManagerImpl::OnTargetPathAvailable(DownloadItem* download) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(download);
@@ -473,46 +460,24 @@ void DownloadManagerImpl::ContinueDownloadWithPath(
DCHECK(ContainsKey(downloads_, download));
DCHECK(ContainsKey(active_downloads_, download_id));
- // Make sure the initial file name is set only once.
- DCHECK(download->GetFullPath().empty());
- download->OnPathDetermined(chosen_file);
-
VLOG(20) << __FUNCTION__ << "()"
<< " download = " << download->DebugString(true);
// Rename to intermediate name.
- FilePath download_path;
- if (download->GetDangerType() !=
- content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) {
- if (download->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 = download->GetSuggestedPath().BaseName();
- download_path = download->GetFullPath().DirName().Append(file_name);
- } else {
- // The download's name is already set to an intermediate name, so no need
- // to override.
- download_path = download->GetFullPath();
- }
- } else {
- // The download is a safe download. We need to rename it to its
- // intermediate path. The final name after user confirmation will be set
- // from DownloadItem::OnDownloadCompleting.
- download_path = delegate_->GetIntermediatePath(download->GetFullPath());
- }
-
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&DownloadFileManager::RenameInProgressDownloadFile,
- file_manager_, download->GetGlobalId(),
- download_path));
-
- download->Rename(download_path);
-
- delegate_->AddItemToPersistentStore(download);
+ // TODO(asanka): Skip this rename if download->AllDataSaved() is true. This
+ // avoids a spurious rename when we can just rename to the final
+ // filename. Unnecessary renames may cause bugs like
+ // http://crbug.com/74187.
+ bool ok_to_overwrite = true;
+ FilePath intermediate_path =
+ delegate_->GetIntermediatePath(*download, &ok_to_overwrite);
+ // We want the intermediate and target paths to refer to the same directory so
+ // that they are both on the same device and subject to same
+ // space/permission/availability constraints.
+ DCHECK(intermediate_path.DirName() ==
+ download->GetTargetFilePath().DirName());
+ download->OnIntermediatePathDetermined(file_manager_, intermediate_path,
+ ok_to_overwrite);
}
void DownloadManagerImpl::UpdateDownload(int32 download_id,
@@ -650,8 +615,6 @@ void DownloadManagerImpl::MaybeCompleteDownload(DownloadItem* download) {
<< download->DebugString(false);
delegate_->UpdateItemInPersistentStore(download);
-
- // Finish the download.
download->OnDownloadCompleting(file_manager_);
}
@@ -669,38 +632,6 @@ void DownloadManagerImpl::DownloadCompleted(DownloadItem* download) {
AssertStateConsistent(download);
}
-void DownloadManagerImpl::OnDownloadRenamedToFinalName(
- int download_id,
- const FilePath& full_path,
- int uniquifier) {
- VLOG(20) << __FUNCTION__ << "()" << " download_id = " << download_id
- << " full_path = \"" << full_path.value() << "\""
- << " uniquifier = " << uniquifier;
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- DownloadItem* item = GetDownloadItem(download_id);
- if (!item)
- return;
-
- if (item->GetDangerType() == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS ||
- item->PromptUserForSaveLocation()) {
- DCHECK_EQ(0, uniquifier)
- << "We should not uniquify user supplied filenames or safe filenames "
- "that have already been uniquified.";
- }
-
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&DownloadFileManager::CompleteDownload,
- file_manager_, item->GetGlobalId()));
-
- if (uniquifier)
- item->SetPathUniquifier(uniquifier);
-
- item->OnDownloadRenamedToFinalName(full_path);
- delegate_->UpdatePathForItemInPersistentStore(item, full_path);
-}
-
void DownloadManagerImpl::CancelDownload(int32 download_id) {
DownloadItem* download = GetActiveDownload(download_id);
// A cancel at the right time could remove the download from the
@@ -882,20 +813,22 @@ void DownloadManagerImpl::RemoveObserver(Observer* observer) {
void DownloadManagerImpl::FileSelected(const FilePath& path,
int32 download_id) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!path.empty());
DownloadItem* download = GetActiveDownloadItem(download_id);
if (!download)
return;
VLOG(20) << __FUNCTION__ << "()" << " path = \"" << path.value() << "\""
- << " download = " << download->DebugString(true);
+ << " download = " << download->DebugString(true);
- // Retain the last directory that was picked by the user. Exclude temporary
- // downloads since the path likely points at the location of a temporary file.
- if (download->PromptUserForSaveLocation() && !download->IsTemporary())
+ // Retain the last directory. Exclude temporary downloads since the path
+ // likely points at the location of a temporary file.
+ if (!download->IsTemporary())
last_download_path_ = path.DirName();
// Make sure the initial file name is set only once.
- ContinueDownloadWithPath(download, path);
+ download->OnTargetPathSelected(path);
+ OnTargetPathAvailable(download);
}
void DownloadManagerImpl::FileSelectionCanceled(int32 download_id) {
@@ -1174,6 +1107,23 @@ void DownloadManagerImpl::DownloadOpened(DownloadItem* download) {
download_stats::RecordOpensOutstanding(num_unopened);
}
+void DownloadManagerImpl::DownloadRenamedToIntermediateName(
+ DownloadItem* download) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ // If the rename failed, we receive an OnDownloadInterrupted() call before we
+ // receive the DownloadRenamedToIntermediateName() call.
+ delegate_->AddItemToPersistentStore(download);
+}
+
+void DownloadManagerImpl::DownloadRenamedToFinalName(
+ DownloadItem* download) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ // If the rename failed, we receive an OnDownloadInterrupted() call before we
+ // receive the DownloadRenamedToFinalName() call.
+ delegate_->UpdatePathForItemInPersistentStore(download,
+ download->GetFullPath());
+}
+
void DownloadManagerImpl::SetFileManagerForTesting(
DownloadFileManager* file_manager) {
file_manager_ = file_manager;
diff --git a/content/browser/download/download_manager_impl.h b/content/browser/download/download_manager_impl.h
index 7f267b2..ad1a027 100644
--- a/content/browser/download/download_manager_impl.h
+++ b/content/browser/download/download_manager_impl.h
@@ -50,9 +50,6 @@ class CONTENT_EXPORT DownloadManagerImpl
int64 size,
const std::string& hash_state,
content::DownloadInterruptReason reason) OVERRIDE;
- virtual void OnDownloadRenamedToFinalName(int download_id,
- const FilePath& full_path,
- int uniquifier) OVERRIDE;
virtual int RemoveDownloadsBetween(base::Time remove_begin,
base::Time remove_end) OVERRIDE;
virtual int RemoveDownloads(base::Time remove_begin) OVERRIDE;
@@ -107,6 +104,10 @@ class CONTENT_EXPORT DownloadManagerImpl
virtual void DownloadOpened(
content::DownloadItem* download) OVERRIDE;
virtual void DownloadRemoved(content::DownloadItem* download) OVERRIDE;
+ virtual void DownloadRenamedToIntermediateName(
+ content::DownloadItem* download) OVERRIDE;
+ virtual void DownloadRenamedToFinalName(
+ content::DownloadItem* download) OVERRIDE;
virtual void AssertStateConsistent(
content::DownloadItem* download) const OVERRIDE;
@@ -150,8 +151,7 @@ class CONTENT_EXPORT DownloadManagerImpl
// Called back after a target path for the file to be downloaded to has been
// determined, either automatically based on the suggested file name, or by
// the user in a Save As dialog box.
- void ContinueDownloadWithPath(content::DownloadItem* download,
- const FilePath& chosen_file);
+ void OnTargetPathAvailable(content::DownloadItem* download);
// Retrieves the download from the |download_id|.
// Returns NULL if the download is not active.
diff --git a/content/browser/download/download_manager_impl_unittest.cc b/content/browser/download/download_manager_impl_unittest.cc
index 2f3bbe8..5337374 100644
--- a/content/browser/download/download_manager_impl_unittest.cc
+++ b/content/browser/download/download_manager_impl_unittest.cc
@@ -102,9 +102,14 @@ class TestDownloadManagerDelegate : public content::DownloadManagerDelegate {
TestDownloadManagerDelegate()
: mark_content_dangerous_(false),
prompt_user_for_save_location_(false),
+ should_complete_download_(true),
download_manager_(NULL) {
}
+ void set_download_directory(const FilePath& path) {
+ download_directory_ = path;
+ }
+
void set_download_manager(content::DownloadManager* dm) {
download_manager_ = dm;
}
@@ -115,22 +120,30 @@ class TestDownloadManagerDelegate : public content::DownloadManagerDelegate {
virtual bool ShouldStartDownload(int32 download_id) OVERRIDE {
DownloadItem* item = download_manager_->GetActiveDownloadItem(download_id);
- DownloadStateInfo state = item->GetStateInfo();
FilePath path = net::GenerateFileName(item->GetURL(),
item->GetContentDisposition(),
item->GetReferrerCharset(),
item->GetSuggestedFilename(),
item->GetMimeType(),
std::string());
+ DownloadItem::TargetDisposition disposition = item->GetTargetDisposition();
if (!ShouldOpenFileBasedOnExtension(path) && prompt_user_for_save_location_)
- state.prompt_user_for_save_location = true;
- item->SetFileCheckResults(state);
+ disposition = DownloadItem::TARGET_DISPOSITION_PROMPT;
+ item->OnTargetPathDetermined(download_directory_.Append(path),
+ disposition,
+ content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
return true;
}
- virtual FilePath GetIntermediatePath(
- const FilePath& suggested_path) OVERRIDE {
- return GetTempDownloadPath(suggested_path);
+ virtual FilePath GetIntermediatePath(const DownloadItem& item,
+ bool* ok_to_overwrite) OVERRIDE {
+ if (intermediate_path_.empty()) {
+ *ok_to_overwrite = true;
+ return GetTempDownloadPath(item.GetTargetFilePath());
+ } else {
+ *ok_to_overwrite = overwrite_intermediate_path_;
+ return intermediate_path_;
+ }
}
virtual void ChooseDownloadPath(WebContents* web_contents,
@@ -177,38 +190,60 @@ class TestDownloadManagerDelegate : public content::DownloadManagerDelegate {
mark_content_dangerous_ = dangerous;
}
+ void SetIntermediatePath(const FilePath& intermediate_path,
+ bool overwrite_intermediate_path) {
+ intermediate_path_ = intermediate_path;
+ overwrite_intermediate_path_ = overwrite_intermediate_path;
+ }
+
+ void SetShouldCompleteDownload(bool value) {
+ should_complete_download_ = value;
+ }
+
+ void InvokeDownloadCompletionCallback() {
+ EXPECT_FALSE(download_completion_callback_.is_null());
+ download_completion_callback_.Run();
+ download_completion_callback_.Reset();
+ }
+
virtual bool ShouldCompleteDownload(
DownloadItem* item,
- const base::Closure& complete_callback) {
+ const base::Closure& complete_callback) OVERRIDE {
+ download_completion_callback_ = complete_callback;
if (mark_content_dangerous_) {
CHECK(!complete_callback.is_null());
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&TestDownloadManagerDelegate::MarkContentDangerous,
- base::Unretained(this), item->GetId(), complete_callback));
+ base::Unretained(this), item->GetId()));
mark_content_dangerous_ = false;
return false;
} else {
- return true;
+ return should_complete_download_;
}
}
private:
void MarkContentDangerous(
- int32 download_id,
- const base::Closure& complete_callback) {
+ int32 download_id) {
DownloadItem* item = download_manager_->GetActiveDownloadItem(download_id);
if (!item)
return;
- item->SetDangerType(content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT);
- complete_callback.Run();
+ item->OnContentCheckCompleted(
+ content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT);
+ InvokeDownloadCompletionCallback();
}
+ FilePath download_directory_;
FilePath expected_suggested_path_;
FilePath file_selection_response_;
+ FilePath intermediate_path_;
+ bool overwrite_intermediate_path_;
bool mark_content_dangerous_;
bool prompt_user_for_save_location_;
+ bool should_complete_download_;
DownloadManager* download_manager_;
+ base::Closure download_completion_callback_;
DISALLOW_COPY_AND_ASSIGN(TestDownloadManagerDelegate);
};
@@ -242,6 +277,15 @@ class DownloadManagerTest : public testing::Test {
message_loop_.RunAllPending();
}
+ // Create a temporary directory as the downloads directory.
+ bool CreateTempDownloadsDirectory() {
+ if (!scoped_download_dir_.CreateUniqueTempDir())
+ return false;
+ download_manager_delegate_->set_download_directory(
+ scoped_download_dir_.path());
+ return true;
+ }
+
void AddDownloadToFileManager(int id, DownloadFile* download_file) {
file_manager()->downloads_[DownloadId(kValidIdDomain, id)] =
download_file;
@@ -249,8 +293,8 @@ class DownloadManagerTest : public testing::Test {
void AddMockDownloadToFileManager(int id, MockDownloadFile* download_file) {
AddDownloadToFileManager(id, download_file);
- ON_CALL(*download_file, GetDownloadManager())
- .WillByDefault(Return(download_manager_));
+ EXPECT_CALL(*download_file, GetDownloadManager())
+ .WillRepeatedly(Return(download_manager_));
}
void OnResponseCompleted(int32 download_id, int64 size,
@@ -263,7 +307,10 @@ class DownloadManagerTest : public testing::Test {
}
void ContinueDownloadWithPath(DownloadItem* download, const FilePath& path) {
- download_manager_->ContinueDownloadWithPath(download, path);
+ download->OnTargetPathDetermined(
+ path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+ content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
+ download_manager_->OnTargetPathAvailable(download);
}
void UpdateData(int32 id, const char* data, size_t length) {
@@ -295,6 +342,12 @@ class DownloadManagerTest : public testing::Test {
return download_manager_->GetActiveDownload(id);
}
+ FilePath GetPathInDownloadsDir(const FilePath::StringType& fragment) {
+ DCHECK(scoped_download_dir_.IsValid());
+ FilePath full_path(scoped_download_dir_.path().Append(fragment));
+ return full_path.NormalizePathSeparators();
+ }
+
protected:
scoped_ptr<TestBrowserContext> browser_context;
scoped_ptr<TestDownloadManagerDelegate> download_manager_delegate_;
@@ -304,6 +357,7 @@ class DownloadManagerTest : public testing::Test {
content::TestBrowserThread ui_thread_;
content::TestBrowserThread file_thread_;
scoped_refptr<content::DownloadBuffer> download_buffer_;
+ ScopedTempDir scoped_download_dir_;
DownloadFileManager* file_manager() {
if (!file_manager_) {
@@ -329,9 +383,10 @@ class DownloadFileWithErrors : public DownloadFileImpl {
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);
+ virtual net::Error Initialize() OVERRIDE;
+ virtual net::Error AppendDataToFile(const char* data,
+ size_t data_len) OVERRIDE;
+ virtual net::Error Rename(const FilePath& full_path) OVERRIDE;
void set_forced_error(net::Error error) { forced_error_ = error; }
void clear_forced_error() { forced_error_ = net::OK; }
@@ -427,35 +482,6 @@ const struct {
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). temp 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.temp"),
- content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, true, 1, },
- { FILE_PATH_LITERAL("Unconfirmed xxx.temp"),
- 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.temp"),
- content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT, false, 1, },
- { FILE_PATH_LITERAL("Unconfirmed xxx.temp"),
- 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 DownloadManager::Observer {
@@ -510,12 +536,12 @@ class ItemObserver : public DownloadItem::Observer {
private:
// DownloadItem::Observer methods
- virtual void OnDownloadUpdated(DownloadItem* download) {
+ virtual void OnDownloadUpdated(DownloadItem* download) OVERRIDE {
DCHECK_EQ(tracked_, download);
states_hit_ |= (1 << download->GetState());
was_updated_ = true;
}
- virtual void OnDownloadOpened(DownloadItem* download) {
+ virtual void OnDownloadOpened(DownloadItem* download) OVERRIDE{
DCHECK_EQ(tracked_, download);
states_hit_ |= (1 << download->GetState());
was_opened_ = true;
@@ -531,7 +557,9 @@ class ItemObserver : public DownloadItem::Observer {
TEST_F(DownloadManagerTest, MAYBE_StartDownload) {
content::TestBrowserThread io_thread(BrowserThread::IO, &message_loop_);
+ ASSERT_TRUE(CreateTempDownloadsDirectory());
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kStartDownloadCases); ++i) {
+ DVLOG(1) << "Test case " << i;
download_manager_delegate_->set_prompt_user_for_save_location(
kStartDownloadCases[i].prompt_for_download);
@@ -569,373 +597,288 @@ TEST_F(DownloadManagerTest, MAYBE_StartDownload) {
namespace {
-enum PromptForSaveLocation {
- DONT_PROMPT,
- PROMPT
+enum OverwriteDownloadPath {
+ DONT_OVERWRITE,
+ OVERWRITE
};
-enum ValidateDangerousDownload {
- DONT_VALIDATE,
- VALIDATE
+enum ResponseCompletionTime {
+ COMPLETES_BEFORE_RENAME,
+ COMPLETES_AFTER_RENAME
};
-// 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.
+// Test cases to be used with DownloadFilenameTest. The paths are relative to
+// the temporary downloads directory used for testing.
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;
+ // DownloadItem properties prior to calling RestartDownload().
+ const FilePath::CharType* target_path;
+ DownloadItem::TargetDisposition target_disposition;
// 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;
+ // location, |expected_prompt_path| is the expected prompt path. The
+ // TestDownloadManagerDelegate will respond with |chosen_path|. If
+ // |chosen_path| is empty, then the file choose dialog be cancelled.
+ const FilePath::CharType* expected_prompt_path;
+ const FilePath::CharType* chosen_path;
+
+ // Response to GetIntermediatePath(). If |intermediate_path| is empty, then a
+ // temporary path is constructed with
+ // GetTempDownloadPath(item->GetTargetFilePath()).
+ const FilePath::CharType* intermediate_path;
+ OverwriteDownloadPath overwrite_intermediate_path;
+
+ // Determines when OnResponseCompleted() is called. If this is
+ // COMPLETES_BEFORE_RENAME, then the response completes before the filename is
+ // determines.
+ ResponseCompletionTime completion;
// The expected intermediate path for the download.
- const FilePath::CharType* intermediate_path;
+ const FilePath::CharType* expected_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;
+ const FilePath::CharType* expected_final_path;
} kDownloadFilenameTestCases[] = {
+
+#define TARGET FILE_PATH_LITERAL
+#define INTERMEDIATE FILE_PATH_LITERAL
+#define EXPECTED_PROMPT FILE_PATH_LITERAL
+#define PROMPT_RESPONSE FILE_PATH_LITERAL
+#define EXPECTED_INTERMEDIATE FILE_PATH_LITERAL
+#define EXPECTED_FINAL FILE_PATH_LITERAL
+
{
- // 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.temp"),
- 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.temp"),
- 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.temp"),
- 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.temp"),
- 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
+ // 0: No prompting.
+ TARGET("foo.txt"),
+ DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+
+ EXPECTED_PROMPT(""),
+ PROMPT_RESPONSE(""),
+
+ INTERMEDIATE("foo.txt.intermediate"),
+ OVERWRITE,
+
+ COMPLETES_AFTER_RENAME,
+ EXPECTED_INTERMEDIATE("foo.txt.intermediate"),
+ EXPECTED_FINAL("foo.txt"),
},
{
- // 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
+ // 1: With prompting. No rename.
+ TARGET("foo.txt"),
+ DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+
+ EXPECTED_PROMPT("foo.txt"),
+ PROMPT_RESPONSE("foo.txt"),
+
+ INTERMEDIATE("foo.txt.intermediate"),
+ OVERWRITE,
+
+ COMPLETES_AFTER_RENAME,
+ EXPECTED_INTERMEDIATE("foo.txt.intermediate"),
+ EXPECTED_FINAL("foo.txt"),
},
{
- // 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
+ // 2: With prompting. Download is renamed.
+ TARGET("foo.txt"),
+ DownloadItem::TARGET_DISPOSITION_PROMPT,
+
+ EXPECTED_PROMPT("foo.txt"),
+ PROMPT_RESPONSE("bar.txt"),
+
+ INTERMEDIATE("bar.txt.intermediate"),
+ OVERWRITE,
+
+ COMPLETES_AFTER_RENAME,
+ EXPECTED_INTERMEDIATE("bar.txt.intermediate"),
+ EXPECTED_FINAL("bar.txt"),
},
{
- // 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
+ // 3: With prompting. Download path is changed.
+ TARGET("foo.txt"),
+ DownloadItem::TARGET_DISPOSITION_PROMPT,
+
+ EXPECTED_PROMPT("foo.txt"),
+ PROMPT_RESPONSE("Foo/bar.txt"),
+
+ INTERMEDIATE("Foo/bar.txt.intermediate"),
+ OVERWRITE,
+
+ COMPLETES_AFTER_RENAME,
+ EXPECTED_INTERMEDIATE("Foo/bar.txt.intermediate"),
+ EXPECTED_FINAL("Foo/bar.txt"),
},
{
- // 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
+ // 4: No prompting. Intermediate path exists. Doesn't overwrite
+ // intermediate path.
+ TARGET("exists.png"),
+ DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+
+ EXPECTED_PROMPT(""),
+ PROMPT_RESPONSE(""),
+
+ INTERMEDIATE("exists.png.temp"),
+ DONT_OVERWRITE,
+
+ COMPLETES_AFTER_RENAME,
+ EXPECTED_INTERMEDIATE("exists.png (1).temp"),
+ EXPECTED_FINAL("exists.png"),
},
{
- // 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
+ // 5: No prompting. Intermediate path exists. Overwrites.
+ TARGET("exists.png"),
+ DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+
+ EXPECTED_PROMPT(""),
+ PROMPT_RESPONSE(""),
+
+ INTERMEDIATE("exists.png.temp"),
+ OVERWRITE,
+
+ COMPLETES_AFTER_RENAME,
+ EXPECTED_INTERMEDIATE("exists.png.temp"),
+ EXPECTED_FINAL("exists.png"),
},
{
- // 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.temp"),
- FILE_PATH_LITERAL("$dl/exists.txt"),
- DONT_VALIDATE
+ // 6: No prompting. Final path exists. Doesn't overwrite.
+ TARGET("exists.txt"),
+ DownloadItem::TARGET_DISPOSITION_UNIQUIFY,
+
+ EXPECTED_PROMPT(""),
+ PROMPT_RESPONSE(""),
+
+ INTERMEDIATE("exists.txt.temp"),
+ OVERWRITE,
+
+ COMPLETES_AFTER_RENAME,
+ EXPECTED_INTERMEDIATE("exists.txt.temp"),
+ EXPECTED_FINAL("exists (1).txt"),
},
{
- // 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
+ // 7: No prompting. Final path exists. Overwrites.
+ TARGET("exists.txt"),
+ DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+
+ EXPECTED_PROMPT(""),
+ PROMPT_RESPONSE(""),
+
+ INTERMEDIATE("exists.txt.temp"),
+ OVERWRITE,
+
+ COMPLETES_AFTER_RENAME,
+ EXPECTED_INTERMEDIATE("exists.txt.temp"),
+ EXPECTED_FINAL("exists.txt"),
},
{
- // 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
+ // 8: No prompting. Response completes before filename determination.
+ TARGET("foo.txt"),
+ DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+
+ EXPECTED_PROMPT(""),
+ PROMPT_RESPONSE(""),
+
+ INTERMEDIATE("foo.txt.intermediate"),
+ OVERWRITE,
+
+ COMPLETES_BEFORE_RENAME,
+ EXPECTED_INTERMEDIATE("foo.txt.intermediate"),
+ EXPECTED_FINAL("foo.txt"),
},
{
- // 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
+ // 9: With prompting. Download path is changed. Response completes before
+ // filename determination.
+ TARGET("foo.txt"),
+ DownloadItem::TARGET_DISPOSITION_PROMPT,
+
+ EXPECTED_PROMPT("foo.txt"),
+ PROMPT_RESPONSE("Foo/bar.txt"),
+
+ INTERMEDIATE("Foo/bar.txt.intermediate"),
+ OVERWRITE,
+
+ COMPLETES_BEFORE_RENAME,
+ EXPECTED_INTERMEDIATE("Foo/bar.txt.intermediate"),
+ EXPECTED_FINAL("Foo/bar.txt"),
},
-};
-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());
- return FilePath(path).NormalizePathSeparators();
-}
+#undef TARGET
+#undef INTERMEDIATE
+#undef EXPECTED_PROMPT
+#undef PROMPT_RESPONSE
+#undef EXPECTED_INTERMEDIATE
+#undef EXPECTED_FINAL
+};
} // 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")));
+ ASSERT_TRUE(CreateTempDownloadsDirectory());
// 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);
+ ASSERT_TRUE(file_util::WriteFile(
+ GetPathInDownloadsDir(FILE_PATH_LITERAL("exists.txt")), "", 0) == 0);
+ ASSERT_TRUE(file_util::WriteFile(
+ GetPathInDownloadsDir(FILE_PATH_LITERAL("exists.png.temp")), "", 0) == 0);
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDownloadFilenameTestCases); ++i) {
+ const DownloadFilenameTestCase& test_case = kDownloadFilenameTestCases[i];
scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
+
+ SCOPED_TRACE(testing::Message() << "Running test case " << i);
info->download_id = DownloadId(kValidIdDomain, i);
info->url_chain.push_back(GURL());
- MockDownloadFile* download_file(new NiceMock<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));
+ MockDownloadFile* download_file(
+ new ::testing::StrictMock<MockDownloadFile>());
+ FilePath target_path = GetPathInDownloadsDir(test_case.target_path);
+ FilePath expected_prompt_path =
+ GetPathInDownloadsDir(test_case.expected_prompt_path);
+ FilePath chosen_path = GetPathInDownloadsDir(test_case.chosen_path);
+ FilePath intermediate_path =
+ GetPathInDownloadsDir(test_case.intermediate_path);
+ FilePath expected_intermediate_path =
+ GetPathInDownloadsDir(test_case.expected_intermediate_path);
+ FilePath expected_final_path =
+ GetPathInDownloadsDir(test_case.expected_final_path);
AddMockDownloadToFileManager(info->download_id.local(), download_file);
-
- EXPECT_CALL(*download_file, Rename(intermediate_path))
+ EXPECT_CALL(*download_file, Rename(expected_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));
- }
+ EXPECT_CALL(*download_file, Rename(expected_final_path))
+ .WillOnce(Return(net::OK));
+#if defined(OS_MACOSX)
+ EXPECT_CALL(*download_file, AnnotateWithSourceInformation());
+#endif
+ EXPECT_CALL(*download_file, Detach());
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);
+ if (test_case.completion == COMPLETES_BEFORE_RENAME)
+ OnResponseCompleted(i, 1024, std::string("fake_hash"));
+
+ download->OnTargetPathDetermined(
+ target_path, test_case.target_disposition,
+ content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
download_manager_delegate_->SetFileSelectionExpectation(
- prompt_path, final_path);
+ expected_prompt_path, chosen_path);
+ download_manager_delegate_->SetIntermediatePath(
+ intermediate_path, test_case.overwrite_intermediate_path);
+ download_manager_delegate_->SetShouldCompleteDownload(false);
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 NiceMock<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 temp(GetTempDownloadPath(new_path));
- EXPECT_CALL(*download_file, Rename(temp))
- .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);
-
- if (kDownloadRenameCases[i].finish_before_rename) {
+ if (test_case.completion == COMPLETES_AFTER_RENAME) {
OnResponseCompleted(i, 1024, std::string("fake_hash"));
message_loop_.RunAllPending();
- FileSelected(new_path, i);
- } else {
- FileSelected(new_path, i);
- 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();
+
+ EXPECT_EQ(expected_intermediate_path.value(),
+ download->GetFullPath().value());
+ download_manager_delegate_->SetShouldCompleteDownload(true);
+ download_manager_delegate_->InvokeDownloadCompletionCallback();
message_loop_.RunAllPending();
+ EXPECT_EQ(expected_final_path.value(),
+ download->GetTargetFilePath().value());
}
}
@@ -964,8 +907,10 @@ TEST_F(DownloadManagerTest, DownloadInterruptTest) {
AddMockDownloadToFileManager(info->download_id.local(), download_file);
EXPECT_CALL(*download_file, Rename(cr_path))
- .Times(1)
.WillOnce(Return(net::OK));
+ EXPECT_CALL(*download_file, AppendDataToFile(kTestData, kTestDataLen))
+ .WillOnce(Return(net::OK));
+ EXPECT_CALL(*download_file, Cancel());
download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle());
@@ -975,7 +920,6 @@ TEST_F(DownloadManagerTest, DownloadInterruptTest) {
scoped_ptr<ItemObserver> observer(new ItemObserver(download));
download_file->AppendDataToFile(kTestData, kTestDataLen);
-
ContinueDownloadWithPath(download, new_path);
message_loop_.RunAllPending();
EXPECT_TRUE(GetActiveDownloadItem(0) != NULL);
@@ -1107,8 +1051,10 @@ TEST_F(DownloadManagerTest, DownloadCancelTest) {
// |download_file| is owned by DownloadFileManager.
EXPECT_CALL(*download_file, Rename(cr_path))
- .Times(1)
.WillOnce(Return(net::OK));
+ EXPECT_CALL(*download_file, AppendDataToFile(kTestData, kTestDataLen))
+ .WillOnce(Return(net::OK));
+ EXPECT_CALL(*download_file, Cancel());
download_manager_->CreateDownloadItem(info.get(), DownloadRequestHandle());
@@ -1150,12 +1096,9 @@ TEST_F(DownloadManagerTest, MAYBE_DownloadOverwriteTest) {
using ::testing::Invoke;
using ::testing::Return;
- // Create a temporary directory.
- ScopedTempDir temp_dir_;
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-
+ ASSERT_TRUE(CreateTempDownloadsDirectory());
// File names we're using.
- const FilePath new_path(temp_dir_.path().AppendASCII("foo.txt"));
+ const FilePath new_path(GetPathInDownloadsDir(FILE_PATH_LITERAL("foo.txt")));
const FilePath cr_path(GetTempDownloadPath(new_path));
EXPECT_FALSE(file_util::PathExists(new_path));
@@ -1241,12 +1184,10 @@ TEST_F(DownloadManagerTest, MAYBE_DownloadRemoveTest) {
using ::testing::Invoke;
using ::testing::Return;
- // Create a temporary directory.
- ScopedTempDir temp_dir_;
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ ASSERT_TRUE(CreateTempDownloadsDirectory());
// File names we're using.
- const FilePath new_path(temp_dir_.path().AppendASCII("foo.txt"));
+ const FilePath new_path(GetPathInDownloadsDir(FILE_PATH_LITERAL("foo.txt")));
const FilePath cr_path(GetTempDownloadPath(new_path));
EXPECT_FALSE(file_util::PathExists(new_path));
diff --git a/content/browser/download/download_state_info.cc b/content/browser/download/download_state_info.cc
deleted file mode 100644
index b927fb0..0000000
--- a/content/browser/download/download_state_info.cc
+++ /dev/null
@@ -1,41 +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 "content/browser/download/download_state_info.h"
-
-#include "content/public/browser/download_item.h"
-
-DownloadStateInfo::DownloadStateInfo()
- : path_uniquifier(0),
- has_user_gesture(false),
- transition_type(content::PAGE_TRANSITION_LINK),
- prompt_user_for_save_location(false),
- danger(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) {
-}
-
-DownloadStateInfo::DownloadStateInfo(const FilePath& forced_name,
- bool has_user_gesture,
- content::PageTransition transition_type,
- bool prompt_user_for_save_location)
- : path_uniquifier(0),
- has_user_gesture(has_user_gesture),
- transition_type(transition_type),
- prompt_user_for_save_location(prompt_user_for_save_location),
- danger(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS),
- force_file_name(forced_name) {
-}
-
-bool DownloadStateInfo::IsDangerous() const {
- // TODO(noelutz): At this point only the windows views UI supports
- // warnings based on dangerous content.
-#ifdef OS_WIN
- return (danger == content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE ||
- danger == content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL ||
- danger == content::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT ||
- danger == content::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT);
-#else
- return (danger == content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE ||
- danger == content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL);
-#endif
-}
diff --git a/content/browser/download/download_state_info.h b/content/browser/download/download_state_info.h
deleted file mode 100644
index 2768a5f..0000000
--- a/content/browser/download/download_state_info.h
+++ /dev/null
@@ -1,55 +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.
-
-#ifndef CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_STATE_INFO_H_
-#define CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_STATE_INFO_H_
-#pragma once
-
-#include "base/file_path.h"
-#include "content/common/content_export.h"
-#include "content/public/browser/download_danger_type.h"
-#include "content/public/common/page_transition_types.h"
-
-// Contains information relating to the process of determining what to do with
-// the download.
-struct DownloadStateInfo {
- DownloadStateInfo();
- DownloadStateInfo(const FilePath& forced_name,
- bool has_user_gesture,
- content::PageTransition transition_type,
- bool prompt_user_for_save_location);
-
- // Indicates if the download is dangerous.
- CONTENT_EXPORT bool IsDangerous() const;
-
- // The original name for a dangerous download, specified by the request.
- FilePath target_name;
-
- // The path where we save the download. Typically generated.
- FilePath suggested_path;
-
- // A number that should be added to the suggested path to make it unique.
- // 0 means no number should be appended. It is eventually incorporated
- // into the final file name.
- int path_uniquifier;
-
- // True if the download is the result of user action.
- bool has_user_gesture;
-
- content::PageTransition transition_type;
-
- // True if we should display the 'save as...' UI and prompt the user
- // for the download location.
- // False if the UI should be suppressed and the download performed to the
- // default location.
- bool prompt_user_for_save_location;
-
- content::DownloadDangerType danger;
-
- // If non-empty, contains an externally supplied filename that should be used
- // as the target path.
- FilePath force_file_name;
-};
-
-#endif // CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_STATE_INFO_H_