Download code cleanup: share most of the code between DownloadFile and SaveFile.
I'm not really happy about BaseFile, but removing the remaining differences
will require changes to DownloadFileManager and SaveFileManager.
I prefer to do that in small steps.
TEST=unit_tests, browser_tests, ui_tests
BUG=48913
Review URL: http://codereview.chromium.org/3164039
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@57688 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/download/download_file.cc b/chrome/browser/download/download_file.cc
index 3c3b6d9..c877a6e 100644
--- a/chrome/browser/download/download_file.cc
+++ b/chrome/browser/download/download_file.cc
@@ -5,192 +5,32 @@
#include "chrome/browser/download/download_file.h"
#include "base/file_util.h"
-#include "build/build_config.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/download/download_manager.h"
#include "chrome/browser/download/download_util.h"
#include "chrome/browser/history/download_types.h"
-#include "net/base/net_errors.h"
-
-#if defined(OS_WIN)
-#include "chrome/common/win_safe_util.h"
-#elif defined(OS_MACOSX)
-#include "chrome/browser/cocoa/file_metadata.h"
-#endif
DownloadFile::DownloadFile(const DownloadCreateInfo* info)
- : file_stream_(info->save_info.file_stream),
- source_url_(info->url),
- referrer_url_(info->referrer_url),
+ : BaseFile(info->save_info.file_path,
+ info->url,
+ info->referrer_url,
+ info->save_info.file_stream),
id_(info->download_id),
child_id_(info->child_id),
- request_id_(info->request_id),
- full_path_(info->save_info.file_path),
- path_renamed_(false),
- dont_sleep_(true) {
+ request_id_(info->request_id) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
}
DownloadFile::~DownloadFile() {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
- if (in_progress())
- Cancel();
- Close();
-}
-
-bool DownloadFile::Initialize() {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
- if (!full_path_.empty() ||
- download_util::CreateTemporaryFileForDownload(&full_path_))
- return Open();
- return false;
-}
-
-bool DownloadFile::AppendDataToFile(const char* data, size_t data_len) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
-
- if (!file_stream_.get())
- return false;
-
- // FIXME bug 595247: handle errors on file writes.
- size_t written = file_stream_->Write(data, data_len, NULL);
- return (written == data_len);
-}
-
-void DownloadFile::Cancel() {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
- Close();
- if (!full_path_.empty())
- file_util::Delete(full_path_, false);
-}
-
-// The UI has provided us with our finalized name.
-bool DownloadFile::Rename(const FilePath& new_path, bool is_final_rename) {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
-
- // Save the information whether the download is in progress because
- // it will be overwritten by closing the file.
- bool saved_in_progress = in_progress();
-
- // 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();
-
- return true;
- }
-
- Close();
-
- file_util::CreateDirectory(new_path.DirName());
-
-#if defined(OS_WIN)
- // We cannot rename because rename will keep the same security descriptor
- // on the destination file. We want to recreate the security descriptor
- // with the security that makes sense in the new path.
- if (!file_util::RenameFileAndResetSecurityDescriptor(full_path_, new_path))
- return false;
-#elif defined(OS_POSIX)
- {
- // Similarly, on Unix, we're moving a temp file created with permissions
- // 600 to |new_path|. Here, we try to fix up the destination file with
- // appropriate permissions.
- struct stat st;
- // First check the file existence and create an empty file if it doesn't
- // exist.
- if (!file_util::PathExists(new_path))
- file_util::WriteFile(new_path, "", 0);
- bool stat_succeeded = (stat(new_path.value().c_str(), &st) == 0);
-
- // TODO(estade): Move() falls back to copying and deleting when a simple
- // rename fails. Copying sucks for large downloads. crbug.com/8737
- if (!file_util::Move(full_path_, new_path))
- return false;
-
- if (stat_succeeded)
- chmod(new_path.value().c_str(), st.st_mode);
- }
-#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)
- return true;
-
- if (!Open())
- return false;
-
- // Move to the end of the new file.
- if (file_stream_->Seek(net::FROM_END, 0) < 0)
- return false;
-
- return true;
}
void DownloadFile::DeleteCrDownload() {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
FilePath crdownload = download_util::GetCrDownloadPath(full_path_);
file_util::Delete(crdownload, false);
}
-void DownloadFile::Finish() {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
- Close();
-}
-
-void DownloadFile::Close() {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
- if (file_stream_.get()) {
-#if defined(OS_CHROMEOS)
- // Currently we don't really care about the return value, since if it fails
- // theres not much we can do. But we might in the future.
- file_stream_->Flush();
-#endif
- file_stream_->Close();
- file_stream_.reset();
- }
-}
-
-bool DownloadFile::Open() {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
- DCHECK(!full_path_.empty());
-
- // Create a new file steram if it is not provided.
- if (!file_stream_.get()) {
- file_stream_.reset(new net::FileStream);
- if (file_stream_->Open(full_path_,
- base::PLATFORM_FILE_OPEN_ALWAYS |
- base::PLATFORM_FILE_WRITE) != net::OK) {
- file_stream_.reset();
- return false;
- }
- }
-
-#if defined(OS_WIN)
- AnnotateWithSourceInformation();
-#endif
- return true;
-}
-
-void DownloadFile::AnnotateWithSourceInformation() {
- DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
-#if defined(OS_WIN)
- // Sets the Zone to tell Windows that this file comes from the internet.
- // We ignore the return value because a failure is not fatal.
- win_util::SetInternetZoneIdentifier(full_path_);
-#elif defined(OS_MACOSX)
- file_metadata::AddQuarantineMetadataToFile(full_path_, source_url_,
- referrer_url_);
- file_metadata::AddOriginMetadataToFile(full_path_, source_url_,
- referrer_url_);
-#endif
-}
-
void DownloadFile::CancelDownloadRequest(ResourceDispatcherHost* rdh) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
ChromeThread::PostTask(