172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Use of this source code is governed by a BSD-style license that can be
3bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// found in the LICENSE file.
4bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
5bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/download/base_file.h"
6bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
7bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/file_util.h"
8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/format_macros.h"
9bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/logging.h"
10201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "base/stringprintf.h"
11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "crypto/secure_hash.h"
12bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "net/base/file_stream.h"
13bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "net/base/net_errors.h"
14bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/download/download_util.h"
15dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h"
16bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
17bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#if defined(OS_WIN)
18bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/common/win_safe_util.h"
19bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#elif defined(OS_MACOSX)
20dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/cocoa/file_metadata.h"
21bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#endif
22bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
23bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenBaseFile::BaseFile(const FilePath& full_path,
24bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                   const GURL& source_url,
25bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                   const GURL& referrer_url,
26bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                   int64 received_bytes,
27bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                   const linked_ptr<net::FileStream>& file_stream)
28bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    : full_path_(full_path),
29bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      source_url_(source_url),
30bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      referrer_url_(referrer_url),
31bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      file_stream_(file_stream),
32bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      bytes_so_far_(received_bytes),
3372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      power_save_blocker_(true),
34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      calculate_hash_(false),
35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      detached_(false) {
36731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  memset(sha256_hash_, 0, sizeof(sha256_hash_));
38bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
39bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
40bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian MonsenBaseFile::~BaseFile() {
41731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (detached_)
43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    Close();
44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  else
45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    Cancel();  // Will delete the file.
46bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
47bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
4872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool BaseFile::Initialize(bool calculate_hash) {
49731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(!detached_);
5172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
5272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  calculate_hash_ = calculate_hash;
5372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
5472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (calculate_hash_)
55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    secure_hash_.reset(crypto::SecureHash::Create(crypto::SecureHash::SHA256));
5672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
57bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!full_path_.empty() ||
58bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      download_util::CreateTemporaryFileForDownload(&full_path_))
59bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return Open();
60bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return false;
61bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
62bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
63bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool BaseFile::AppendDataToFile(const char* data, size_t data_len) {
64731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(!detached_);
66bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
67bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!file_stream_.get())
68bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return false;
69bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
70bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // TODO(phajdan.jr): get rid of this check.
71bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (data_len == 0)
72bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return true;
73bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
74bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  bytes_so_far_ += data_len;
75bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
76731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  // TODO(phajdan.jr): handle errors on file writes. http://crbug.com/58355
77bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  size_t written = file_stream_->Write(data, data_len, NULL);
7872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (written != data_len)
7972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
8072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
8172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (calculate_hash_)
8272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    secure_hash_->Update(data, data_len);
8372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
8472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return true;
85bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
86bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
87dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool BaseFile::Rename(const FilePath& new_path) {
88731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
89bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
90bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Save the information whether the download is in progress because
91bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // it will be overwritten by closing the file.
92bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  bool saved_in_progress = in_progress();
93bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
94bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // If the new path is same as the old one, there is no need to perform the
95bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // following renaming logic.
96bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (new_path == full_path_) {
97bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    // Don't close the file if we're not done (finished or canceled).
98bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (!saved_in_progress)
99bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      Close();
100bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
101bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return true;
102bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
103bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
104bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  Close();
105bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
106bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  file_util::CreateDirectory(new_path.DirName());
107bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
108bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#if defined(OS_WIN)
109bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // We cannot rename because rename will keep the same security descriptor
110bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // on the destination file. We want to recreate the security descriptor
111bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // with the security that makes sense in the new path.
112bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!file_util::RenameFileAndResetSecurityDescriptor(full_path_, new_path))
113bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return false;
114bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#elif defined(OS_POSIX)
115bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  {
116bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    // Similarly, on Unix, we're moving a temp file created with permissions
117bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    // 600 to |new_path|. Here, we try to fix up the destination file with
118bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    // appropriate permissions.
119bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    struct stat st;
120bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    // First check the file existence and create an empty file if it doesn't
121bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    // exist.
122bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (!file_util::PathExists(new_path))
123bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      file_util::WriteFile(new_path, "", 0);
124bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    bool stat_succeeded = (stat(new_path.value().c_str(), &st) == 0);
125bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
126bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    // TODO(estade): Move() falls back to copying and deleting when a simple
127bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    // rename fails. Copying sucks for large downloads. crbug.com/8737
128bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (!file_util::Move(full_path_, new_path))
129bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      return false;
130bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
131bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (stat_succeeded)
132bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      chmod(new_path.value().c_str(), st.st_mode);
133bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
134bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#endif
135bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
136bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  full_path_ = new_path;
137bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
138bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // We don't need to re-open the file if we're done (finished or canceled).
139bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!saved_in_progress)
140bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return true;
141bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
142bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!Open())
143bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    return false;
144bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
145bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return true;
146bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
147bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid BaseFile::Detach() {
149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  detached_ = true;
150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
152bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BaseFile::Cancel() {
153731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(!detached_);
155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
156bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  Close();
157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
158bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!full_path_.empty())
159bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    file_util::Delete(full_path_, false);
160bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
161bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
162bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BaseFile::Finish() {
163731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
16472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
16572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (calculate_hash_)
16672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    secure_hash_->Finish(sha256_hash_, kSha256HashLen);
16772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
168bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  Close();
169bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
170bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
17172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool BaseFile::GetSha256Hash(std::string* hash) {
172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(!detached_);
17372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!calculate_hash_ || in_progress())
17472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
17572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  hash->assign(reinterpret_cast<const char*>(sha256_hash_),
17672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen               sizeof(sha256_hash_));
17772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return true;
17872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
17972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
180bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BaseFile::AnnotateWithSourceInformation() {
181731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(!detached_);
183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
184bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#if defined(OS_WIN)
185bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // Sets the Zone to tell Windows that this file comes from the internet.
186bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  // We ignore the return value because a failure is not fatal.
187bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  win_util::SetInternetZoneIdentifier(full_path_);
188bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#elif defined(OS_MACOSX)
189bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  file_metadata::AddQuarantineMetadataToFile(full_path_, source_url_,
190bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                                             referrer_url_);
191bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  file_metadata::AddOriginMetadataToFile(full_path_, source_url_,
192bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                                         referrer_url_);
193bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#endif
194bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
195bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
196bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool BaseFile::Open() {
197731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(!detached_);
199bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  DCHECK(!full_path_.empty());
200bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Create a new file stream if it is not provided.
202bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (!file_stream_.get()) {
203bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    file_stream_.reset(new net::FileStream);
204bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (file_stream_->Open(full_path_,
205bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                           base::PLATFORM_FILE_OPEN_ALWAYS |
206bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen                               base::PLATFORM_FILE_WRITE) != net::OK) {
207bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      file_stream_.reset();
208bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      return false;
209bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
210bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
211bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    // We may be re-opening the file after rename. Always make sure we're
212bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    // writing at the end of the file.
213bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    if (file_stream_->Seek(net::FROM_END, 0) < 0) {
214bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      file_stream_.reset();
215bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen      return false;
216bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    }
217bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
218bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
219bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#if defined(OS_WIN)
220bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  AnnotateWithSourceInformation();
221bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#endif
222bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  return true;
223bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
224bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen
225bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid BaseFile::Close() {
226731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
227bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  if (file_stream_.get()) {
228bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#if defined(OS_CHROMEOS)
229bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    // Currently we don't really care about the return value, since if it fails
230bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    // theres not much we can do.  But we might in the future.
231bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    file_stream_->Flush();
232bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#endif
233bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    file_stream_->Close();
234bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen    file_stream_.reset();
235bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen  }
236bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}
237201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
238201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochstd::string BaseFile::DebugString() const {
239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return base::StringPrintf("{ source_url_ = \"%s\""
240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                            " full_path_ = \"%" PRFilePath "\""
241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                            " bytes_so_far_ = %" PRId64 " detached_ = %c }",
242201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                            source_url_.spec().c_str(),
243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                            full_path_.value().c_str(),
244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                            bytes_so_far_,
245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                            detached_ ? 'T' : 'F');
246201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
247