blob: 81d80b4c89cab028d419c3c9b1c48964b63f82e4 [file] [log] [blame]
[email protected]6c69796d2010-07-16 21:41:161// Copyright (c) 2010 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]cdaa8652008-09-13 02:48:595#include "chrome/browser/download/download_file.h"
initial.commit09911bf2008-07-26 23:55:296
7#include "base/file_util.h"
[email protected]e93d2822009-01-30 05:59:598#include "build/build_config.h"
[email protected]b47da722009-02-23 23:54:189#include "chrome/browser/download/download_manager.h"
[email protected]290c9702010-03-09 04:01:3610#include "chrome/browser/download/download_util.h"
[email protected]6c69796d2010-07-16 21:41:1611#include "chrome/browser/history/download_types.h"
12#include "net/base/net_errors.h"
initial.commit09911bf2008-07-26 23:55:2913
[email protected]e93d2822009-01-30 05:59:5914#if defined(OS_WIN)
[email protected]4a0765a2009-05-08 23:12:2515#include "app/win_util.h"
[email protected]e93d2822009-01-30 05:59:5916#include "chrome/common/win_safe_util.h"
[email protected]8ef06372009-04-27 21:11:3417#elif defined(OS_MACOSX)
[email protected]eae033a32009-09-29 15:47:5318#include "chrome/browser/cocoa/file_metadata.h"
[email protected]e93d2822009-01-30 05:59:5919#endif
[email protected]e1acf6f2008-10-27 20:43:3320
initial.commit09911bf2008-07-26 23:55:2921DownloadFile::DownloadFile(const DownloadCreateInfo* info)
[email protected]8af9d032010-02-10 00:00:3222 : file_stream_(info->save_info.file_stream),
[email protected]8ef06372009-04-27 21:11:3423 source_url_(info->url),
24 referrer_url_(info->referrer_url),
initial.commit09911bf2008-07-26 23:55:2925 id_(info->download_id),
[email protected]76543b92009-08-31 17:27:4526 child_id_(info->child_id),
initial.commit09911bf2008-07-26 23:55:2927 render_view_id_(info->render_view_id),
28 request_id_(info->request_id),
29 bytes_so_far_(0),
[email protected]8af9d032010-02-10 00:00:3230 full_path_(info->save_info.file_path),
initial.commit09911bf2008-07-26 23:55:2931 path_renamed_(false),
[email protected]36e93a772009-10-23 04:18:0532 in_progress_(true),
[email protected]8af9d032010-02-10 00:00:3233 dont_sleep_(true),
34 save_info_(info->save_info) {
initial.commit09911bf2008-07-26 23:55:2935}
36
37DownloadFile::~DownloadFile() {
38 Close();
39}
40
41bool DownloadFile::Initialize() {
[email protected]290c9702010-03-09 04:01:3642 if (!full_path_.empty() ||
43 download_util::CreateTemporaryFileForDownload(&full_path_))
[email protected]8af9d032010-02-10 00:00:3244 return Open();
initial.commit09911bf2008-07-26 23:55:2945 return false;
46}
47
initial.commit09911bf2008-07-26 23:55:2948bool DownloadFile::AppendDataToFile(const char* data, int data_len) {
[email protected]8af9d032010-02-10 00:00:3249 if (file_stream_.get()) {
[email protected]5415e4f2009-02-23 23:53:3150 // FIXME bug 595247: handle errors on file writes.
[email protected]8af9d032010-02-10 00:00:3251 size_t written = file_stream_->Write(data, data_len, NULL);
[email protected]5415e4f2009-02-23 23:53:3152 bytes_so_far_ += written;
initial.commit09911bf2008-07-26 23:55:2953 return true;
54 }
55 return false;
56}
57
58void DownloadFile::Cancel() {
59 Close();
[email protected]8af9d032010-02-10 00:00:3260 if (!full_path_.empty())
61 file_util::Delete(full_path_, false);
initial.commit09911bf2008-07-26 23:55:2962}
63
64// The UI has provided us with our finalized name.
[email protected]7ae7c2cb2009-01-06 23:31:4165bool DownloadFile::Rename(const FilePath& new_path) {
[email protected]2cee72c2010-02-11 22:25:1666 // If the new path is same as the old one, there is no need to perform the
67 // following renaming logic.
68 if (new_path == full_path_) {
69 path_renamed_ = true;
initial.commit09911bf2008-07-26 23:55:2970
[email protected]2cee72c2010-02-11 22:25:1671 // Don't close the file if we're not done (finished or canceled).
72 if (!in_progress_)
73 Close();
74
[email protected]8af9d032010-02-10 00:00:3275 return true;
[email protected]2cee72c2010-02-11 22:25:1676 }
77
78 Close();
[email protected]8af9d032010-02-10 00:00:3279
[email protected]cc7948a2009-03-13 20:01:4380#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:2981 // We cannot rename because rename will keep the same security descriptor
82 // on the destination file. We want to recreate the security descriptor
83 // with the security that makes sense in the new path.
[email protected]cc7948a2009-03-13 20:01:4384 if (!file_util::RenameFileAndResetSecurityDescriptor(full_path_, new_path))
initial.commit09911bf2008-07-26 23:55:2985 return false;
[email protected]cc7948a2009-03-13 20:01:4386#elif defined(OS_POSIX)
[email protected]f84233c62010-02-24 23:55:5587 {
88 // Similarly, on Unix, we're moving a temp file created with permissions
89 // 600 to |new_path|. Here, we try to fix up the destination file with
90 // appropriate permissions.
91 struct stat st;
[email protected]87391de2010-03-09 00:58:3092 // First check the file existence and create an empty file if it doesn't
93 // exist.
94 if (!file_util::PathExists(new_path))
95 file_util::WriteFile(new_path, "", 0);
[email protected]f84233c62010-02-24 23:55:5596 bool stat_succeeded = (stat(new_path.value().c_str(), &st) == 0);
97
98 // TODO(estade): Move() falls back to copying and deleting when a simple
99 // rename fails. Copying sucks for large downloads. crbug.com/8737
100 if (!file_util::Move(full_path_, new_path))
[email protected]cc7948a2009-03-13 20:01:43101 return false;
[email protected]f84233c62010-02-24 23:55:55102
103 if (stat_succeeded)
104 chmod(new_path.value().c_str(), st.st_mode);
105 }
[email protected]cc7948a2009-03-13 20:01:43106#endif
initial.commit09911bf2008-07-26 23:55:29107
108 full_path_ = new_path;
109 path_renamed_ = true;
110
111 // We don't need to re-open the file if we're done (finished or canceled).
112 if (!in_progress_)
113 return true;
114
[email protected]8af9d032010-02-10 00:00:32115 if (!Open())
initial.commit09911bf2008-07-26 23:55:29116 return false;
[email protected]4f0872b2010-02-10 17:47:39117
118 // Move to the end of the new file.
119 if (file_stream_->Seek(net::FROM_END, 0) < 0)
120 return false;
121
initial.commit09911bf2008-07-26 23:55:29122 return true;
123}
124
125void DownloadFile::Close() {
[email protected]8af9d032010-02-10 00:00:32126 if (file_stream_.get()) {
[email protected]b2a3a252010-06-10 22:36:38127#if defined(OS_CHROMEOS)
128 // Currently we don't really care about the return value, since if it fails
129 // theres not much we can do. But we might in the future.
130 file_stream_->Flush();
131#endif
[email protected]8af9d032010-02-10 00:00:32132 file_stream_->Close();
133 file_stream_.reset();
initial.commit09911bf2008-07-26 23:55:29134 }
135}
136
[email protected]8af9d032010-02-10 00:00:32137bool DownloadFile::Open() {
initial.commit09911bf2008-07-26 23:55:29138 DCHECK(!full_path_.empty());
[email protected]8af9d032010-02-10 00:00:32139
140 // Create a new file steram if it is not provided.
141 if (!file_stream_.get()) {
142 file_stream_.reset(new net::FileStream);
143 if (file_stream_->Open(full_path_,
144 base::PLATFORM_FILE_OPEN_ALWAYS |
145 base::PLATFORM_FILE_WRITE) != net::OK) {
146 file_stream_.reset();
147 return false;
148 }
initial.commit09911bf2008-07-26 23:55:29149 }
[email protected]e93d2822009-01-30 05:59:59150
151#if defined(OS_WIN)
[email protected]df72c092009-09-10 19:56:17152 AnnotateWithSourceInformation();
153#endif
154 return true;
155}
156
157void DownloadFile::AnnotateWithSourceInformation() {
158#if defined(OS_WIN)
initial.commit09911bf2008-07-26 23:55:29159 // Sets the Zone to tell Windows that this file comes from the internet.
160 // We ignore the return value because a failure is not fatal.
[email protected]345e1b82009-01-05 23:36:01161 win_util::SetInternetZoneIdentifier(full_path_);
[email protected]4edb0b92009-02-26 01:57:09162#elif defined(OS_MACOSX)
[email protected]eae033a32009-09-29 15:47:53163 file_metadata::AddQuarantineMetadataToFile(full_path_, source_url_,
164 referrer_url_);
165 file_metadata::AddOriginMetadataToFile(full_path_, source_url_,
166 referrer_url_);
[email protected]e93d2822009-01-30 05:59:59167#endif
initial.commit09911bf2008-07-26 23:55:29168}