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(