Skip to content

Commit

Permalink
DownloadFile no longer keeps track of whether or not the final rename…
Browse files Browse the repository at this point in the history
… has occurred.

Instead, DownloadFileManager puts the DownloadFile in a new map when it has the final name.

This is a step towards moving the 'final rename' determination happen in the UI thread.

BUG=None
TEST=None

Review URL: http://codereview.chromium.org/6480079

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@75400 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
ahendrickson@chromium.org committed Feb 18, 2011
1 parent 77a042c commit d231014
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 130 deletions.
6 changes: 1 addition & 5 deletions chrome/browser/download/base_file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ BaseFile::BaseFile(const FilePath& full_path,
int64 received_bytes,
const linked_ptr<net::FileStream>& file_stream)
: full_path_(full_path),
path_renamed_(false),
source_url_(source_url),
referrer_url_(referrer_url),
file_stream_(file_stream),
Expand Down Expand Up @@ -79,7 +78,7 @@ bool BaseFile::AppendDataToFile(const char* data, size_t data_len) {
return true;
}

bool BaseFile::Rename(const FilePath& new_path, bool is_final_rename) {
bool BaseFile::Rename(const FilePath& new_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

// Save the information whether the download is in progress because
Expand All @@ -89,8 +88,6 @@ bool BaseFile::Rename(const FilePath& new_path, bool is_final_rename) {
// If the new path is same as the old one, there is no need to perform the
// following renaming logic.
if (new_path == full_path_) {
path_renamed_ = is_final_rename;

// Don't close the file if we're not done (finished or canceled).
if (!saved_in_progress)
Close();
Expand Down Expand Up @@ -131,7 +128,6 @@ bool BaseFile::Rename(const FilePath& new_path, bool is_final_rename) {
#endif

full_path_ = new_path;
path_renamed_ = is_final_rename;

// We don't need to re-open the file if we're done (finished or canceled).
if (!saved_in_progress)
Expand Down
8 changes: 1 addition & 7 deletions chrome/browser/download/base_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,7 @@ class BaseFile {
bool AppendDataToFile(const char* data, size_t data_len);

// Rename the download file. Returns true on success.
// |path_renamed_| is set to true only if |is_final_rename| is true.
// Marked virtual for testing.
virtual bool Rename(const FilePath& full_path, bool is_final_rename);
virtual bool Rename(const FilePath& full_path);

// Abort the download and automatically close the file.
void Cancel();
Expand All @@ -54,7 +52,6 @@ class BaseFile {
void AnnotateWithSourceInformation();

FilePath full_path() const { return full_path_; }
bool path_renamed() const { return path_renamed_; }
bool in_progress() const { return file_stream_ != NULL; }
int64 bytes_so_far() const { return bytes_so_far_; }

Expand All @@ -71,9 +68,6 @@ class BaseFile {
// Full path to the file including the file name.
FilePath full_path_;

// Whether the download is still using its initial temporary path.
bool path_renamed_;

private:
static const size_t kSha256HashLen = 32;

Expand Down
17 changes: 2 additions & 15 deletions chrome/browser/download/base_file_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ class BaseFileTest : public testing::Test {
// in production, where we would at least Initialize it.
TEST_F(BaseFileTest, CreateDestroy) {
EXPECT_EQ(FilePath().value(), base_file_->full_path().value());
EXPECT_FALSE(base_file_->path_renamed());
}

// Cancel the download explicitly.
Expand All @@ -87,16 +86,13 @@ TEST_F(BaseFileTest, Cancel) {
base_file_->Cancel();
EXPECT_FALSE(file_util::PathExists(base_file_->full_path()));
EXPECT_NE(FilePath().value(), base_file_->full_path().value());
EXPECT_FALSE(base_file_->path_renamed());
}

// Write data to the file once.
TEST_F(BaseFileTest, SingleWrite) {
ASSERT_TRUE(base_file_->Initialize(false));
AppendDataToFile(kTestData1);
base_file_->Finish();

EXPECT_FALSE(base_file_->path_renamed());
}

// Write data to the file multiple times.
Expand All @@ -108,8 +104,6 @@ TEST_F(BaseFileTest, MultipleWrites) {
std::string hash;
EXPECT_FALSE(base_file_->GetSha256Hash(&hash));
base_file_->Finish();

EXPECT_FALSE(base_file_->path_renamed());
}

// Write data to the file once and calculate its sha256 hash.
Expand All @@ -118,8 +112,6 @@ TEST_F(BaseFileTest, SingleWriteWithHash) {
AppendDataToFile(kTestData1);
base_file_->Finish();

EXPECT_FALSE(base_file_->path_renamed());

std::string hash;
base_file_->GetSha256Hash(&hash);
EXPECT_EQ("0B2D3F3F7943AD64B860DF94D05CB56A8A97C6EC5768B5B70B930C5AA7FA9ADE",
Expand All @@ -138,7 +130,6 @@ TEST_F(BaseFileTest, MultipleWritesWithHash) {
EXPECT_FALSE(base_file_->GetSha256Hash(&hash));
base_file_->Finish();

EXPECT_FALSE(base_file_->path_renamed());
EXPECT_TRUE(base_file_->GetSha256Hash(&hash));
EXPECT_EQ("CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8",
base::HexEncode(hash.data(), hash.size()));
Expand All @@ -155,13 +146,11 @@ TEST_F(BaseFileTest, WriteThenRename) {

AppendDataToFile(kTestData1);

EXPECT_TRUE(base_file_->Rename(new_path, true));
EXPECT_TRUE(base_file_->Rename(new_path));
EXPECT_FALSE(file_util::PathExists(initial_path));
EXPECT_TRUE(file_util::PathExists(new_path));

base_file_->Finish();

EXPECT_TRUE(base_file_->path_renamed());
}

// Rename the file while the download is still in progress.
Expand All @@ -176,15 +165,13 @@ TEST_F(BaseFileTest, RenameWhileInProgress) {
AppendDataToFile(kTestData1);

EXPECT_TRUE(base_file_->in_progress());
EXPECT_TRUE(base_file_->Rename(new_path, true));
EXPECT_TRUE(base_file_->Rename(new_path));
EXPECT_FALSE(file_util::PathExists(initial_path));
EXPECT_TRUE(file_util::PathExists(new_path));

AppendDataToFile(kTestData2);

base_file_->Finish();

EXPECT_TRUE(base_file_->path_renamed());
}

} // namespace
45 changes: 30 additions & 15 deletions chrome/browser/download/download_file_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ DownloadFileManager::DownloadFileManager(ResourceDispatcherHost* rdh)

DownloadFileManager::~DownloadFileManager() {
DCHECK(downloads_.empty());
DCHECK(downloads_with_final_name_.empty());
}

void DownloadFileManager::Shutdown() {
Expand All @@ -66,6 +67,7 @@ void DownloadFileManager::Shutdown() {
void DownloadFileManager::OnShutdown() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
StopUpdateTimer();
downloads_with_final_name_.clear();
STLDeleteValues(&downloads_);
}

Expand Down Expand Up @@ -224,10 +226,8 @@ void DownloadFileManager::OnResponseCompleted(int id, DownloadBuffer* buffer) {

// We need to keep the download around until the UI thread has finalized
// the name.
if (download->path_renamed()) {
downloads_.erase(it);
delete download;
}
if (ContainsKey(downloads_with_final_name_, id))
EraseDownload(id);
}

if (downloads_.empty())
Expand All @@ -247,10 +247,8 @@ void DownloadFileManager::CancelDownload(int id) {
<< " download = " << download->DebugString();
download->Cancel();

if (download->path_renamed()) {
downloads_.erase(it);
delete download;
}
if (ContainsKey(downloads_with_final_name_, id))
EraseDownload(id);
}

if (downloads_.empty())
Expand All @@ -269,6 +267,7 @@ void DownloadFileManager::OnDownloadManagerShutdown(DownloadManager* manager) {
if (download_file->GetDownloadManager() == manager) {
download_file->CancelDownloadRequest(resource_dispatcher_host_);
to_remove.insert(download_file);
downloads_with_final_name_.erase(download_file->id());
}
}

Expand All @@ -292,10 +291,11 @@ void DownloadFileManager::OnIntermediateDownloadName(
DownloadFileMap::iterator it = downloads_.find(id);
if (it == downloads_.end())
return;
DCHECK(!ContainsKey(downloads_with_final_name_, id));

DownloadFile* download = it->second;
VLOG(20) << __FUNCTION__ << "()" << " download = " << download->DebugString();
if (!download->Rename(full_path, false /* is_final_rename */)) {
if (!download->Rename(full_path)) {
// Error. Between the time the UI thread generated 'full_path' to the time
// this code runs, something happened that prevents us from renaming.
CancelDownloadOnRename(id);
Expand All @@ -309,7 +309,8 @@ void DownloadFileManager::OnIntermediateDownloadName(
// There are 2 possible rename cases where this method can be called:
// 1. foo.crdownload -> foo
// 2. tmp-> Unconfirmed.xxx.crdownload
// We don't call this function before the download is complete.
// We don't call this function before a safe temp file has been renamed (in
// that case tmp -> foo.crdownload occurs in |OnIntermediateDownloadName|).
void DownloadFileManager::OnFinalDownloadName(
int id, const FilePath& full_path, DownloadManager* download_manager) {
VLOG(20) << __FUNCTION__ << "()" << " id = " << id
Expand All @@ -320,7 +321,9 @@ void DownloadFileManager::OnFinalDownloadName(
if (!download)
return;
VLOG(20) << __FUNCTION__ << "()" << " download = " << download->DebugString();
if (download->Rename(full_path, true /* is_final_rename */)) {
DCHECK(!ContainsKey(downloads_with_final_name_, id));
if (download->Rename(full_path)) {
downloads_with_final_name_[id] = download;
#if defined(OS_MACOSX)
// Done here because we only want to do this once; see
// http://crbug.com/13120 for details.
Expand All @@ -339,10 +342,8 @@ void DownloadFileManager::OnFinalDownloadName(

// If the download has completed before we got this final name, we remove it
// from our in progress map.
if (!download->in_progress()) {
downloads_.erase(id);
delete download;
}
if (!download->in_progress())
EraseDownload(id);

if (downloads_.empty())
StopUpdateTimer();
Expand All @@ -368,3 +369,17 @@ void DownloadFileManager::CancelDownloadOnRename(int id) {
NewRunnableMethod(download_manager,
&DownloadManager::DownloadCancelled, id));
}

void DownloadFileManager::EraseDownload(int id) {
if (!ContainsKey(downloads_, id))
return;

DownloadFile* download_file = downloads_[id];

downloads_.erase(id);

if (ContainsKey(downloads_with_final_name_, id))
downloads_with_final_name_.erase(id);

delete download_file;
}
11 changes: 10 additions & 1 deletion chrome/browser/download/download_file_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,22 @@ class DownloadFileManager
// on the FILE thread.
void CancelDownloadOnRename(int id);

// Erases the download file with the given the download |id| and removes
// it from the maps.
void EraseDownload(int id);

// Unique ID for each DownloadFile.
int next_id_;

// A map of all in progress downloads.
typedef base::hash_map<int, DownloadFile*> DownloadFileMap;

// A map of all in progress downloads. It owns the download files,
// although they may also show up in |downloads_with_final_name_|.
DownloadFileMap downloads_;

// download files are owned by |downloads_|.
DownloadFileMap downloads_with_final_name_;

// Schedule periodic updates of the download progress. This timer
// is controlled from the FILE thread, and posts updates to the UI thread.
base::RepeatingTimer<DownloadFileManager> update_timer_;
Expand Down
Loading

0 comments on commit d231014

Please sign in to comment.