Logo Search packages:      
Sourcecode: chromium-browser version File versions  Download package

download_file.cc

// Copyright (c) 2010 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 "chrome/browser/download/download_file.h"

#include "base/file_util.h"
#include "build/build_config.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 "app/win_util.h"
#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),
      id_(info->download_id),
      child_id_(info->child_id),
      render_view_id_(info->render_view_id),
      request_id_(info->request_id),
      bytes_so_far_(0),
      full_path_(info->save_info.file_path),
      path_renamed_(false),
      in_progress_(true),
      dont_sleep_(true),
      save_info_(info->save_info) {
}

DownloadFile::~DownloadFile() {
  Close();
}

bool DownloadFile::Initialize() {
  if (!full_path_.empty() ||
      download_util::CreateTemporaryFileForDownload(&full_path_))
    return Open();
  return false;
}

bool DownloadFile::AppendDataToFile(const char* data, int data_len) {
  if (file_stream_.get()) {
    // FIXME bug 595247: handle errors on file writes.
    size_t written = file_stream_->Write(data, data_len, NULL);
    bytes_so_far_ += written;
    return true;
  }
  return false;
}

void DownloadFile::Cancel() {
  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) {
  // 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_ = true;

    // Don't close the file if we're not done (finished or canceled).
    if (!in_progress_)
      Close();

    return true;
  }

  Close();

#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_ = true;

  // We don't need to re-open the file if we're done (finished or canceled).
  if (!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::Close() {
  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(!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() {
#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
}

Generated by  Doxygen 1.6.0   Back to index