| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/download/download_file.h" | 5 #include "chrome/browser/download/download_file.h" |
| 6 | 6 |
| 7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
| 8 #include "build/build_config.h" | 8 #include "build/build_config.h" |
| 9 #include "chrome/browser/chrome_thread.h" |
| 9 #include "chrome/browser/download/download_manager.h" | 10 #include "chrome/browser/download/download_manager.h" |
| 10 #include "chrome/browser/download/download_util.h" | 11 #include "chrome/browser/download/download_util.h" |
| 11 #include "chrome/browser/history/download_types.h" | 12 #include "chrome/browser/history/download_types.h" |
| 12 #include "net/base/net_errors.h" | 13 #include "net/base/net_errors.h" |
| 13 | 14 |
| 14 #if defined(OS_WIN) | 15 #if defined(OS_WIN) |
| 15 #include "app/win_util.h" | 16 #include "app/win_util.h" |
| 16 #include "chrome/common/win_safe_util.h" | 17 #include "chrome/common/win_safe_util.h" |
| 17 #elif defined(OS_MACOSX) | 18 #elif defined(OS_MACOSX) |
| 18 #include "chrome/browser/cocoa/file_metadata.h" | 19 #include "chrome/browser/cocoa/file_metadata.h" |
| 19 #endif | 20 #endif |
| 20 | 21 |
| 21 DownloadFile::DownloadFile(const DownloadCreateInfo* info) | 22 DownloadFile::DownloadFile(const DownloadCreateInfo* info) |
| 22 : file_stream_(info->save_info.file_stream), | 23 : file_stream_(info->save_info.file_stream), |
| 23 source_url_(info->url), | 24 source_url_(info->url), |
| 24 referrer_url_(info->referrer_url), | 25 referrer_url_(info->referrer_url), |
| 25 id_(info->download_id), | 26 id_(info->download_id), |
| 26 child_id_(info->child_id), | 27 child_id_(info->child_id), |
| 27 render_view_id_(info->render_view_id), | |
| 28 request_id_(info->request_id), | 28 request_id_(info->request_id), |
| 29 bytes_so_far_(0), | |
| 30 full_path_(info->save_info.file_path), | 29 full_path_(info->save_info.file_path), |
| 31 path_renamed_(false), | 30 path_renamed_(false), |
| 32 in_progress_(true), | 31 dont_sleep_(true) { |
| 33 dont_sleep_(true), | 32 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 34 save_info_(info->save_info) { | |
| 35 } | 33 } |
| 36 | 34 |
| 37 DownloadFile::~DownloadFile() { | 35 DownloadFile::~DownloadFile() { |
| 36 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 38 Close(); | 37 Close(); |
| 39 } | 38 } |
| 40 | 39 |
| 41 bool DownloadFile::Initialize() { | 40 bool DownloadFile::Initialize() { |
| 41 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 42 if (!full_path_.empty() || | 42 if (!full_path_.empty() || |
| 43 download_util::CreateTemporaryFileForDownload(&full_path_)) | 43 download_util::CreateTemporaryFileForDownload(&full_path_)) |
| 44 return Open(); | 44 return Open(); |
| 45 return false; | 45 return false; |
| 46 } | 46 } |
| 47 | 47 |
| 48 bool DownloadFile::AppendDataToFile(const char* data, int data_len) { | 48 bool DownloadFile::AppendDataToFile(const char* data, size_t data_len) { |
| 49 if (file_stream_.get()) { | 49 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 50 // FIXME bug 595247: handle errors on file writes. | 50 |
| 51 size_t written = file_stream_->Write(data, data_len, NULL); | 51 if (!file_stream_.get()) |
| 52 bytes_so_far_ += written; | 52 return false; |
| 53 return true; | 53 |
| 54 } | 54 // FIXME bug 595247: handle errors on file writes. |
| 55 return false; | 55 size_t written = file_stream_->Write(data, data_len, NULL); |
| 56 return (written == data_len); |
| 56 } | 57 } |
| 57 | 58 |
| 58 void DownloadFile::Cancel() { | 59 void DownloadFile::Cancel() { |
| 60 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 59 Close(); | 61 Close(); |
| 60 if (!full_path_.empty()) | 62 if (!full_path_.empty()) |
| 61 file_util::Delete(full_path_, false); | 63 file_util::Delete(full_path_, false); |
| 62 } | 64 } |
| 63 | 65 |
| 64 // The UI has provided us with our finalized name. | 66 // The UI has provided us with our finalized name. |
| 65 bool DownloadFile::Rename(const FilePath& new_path) { | 67 bool DownloadFile::Rename(const FilePath& new_path) { |
| 68 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 69 |
| 70 // Save the information whether the download is in progress because |
| 71 // it will be overwritten by closing the file. |
| 72 bool saved_in_progress = in_progress(); |
| 73 |
| 66 // If the new path is same as the old one, there is no need to perform the | 74 // If the new path is same as the old one, there is no need to perform the |
| 67 // following renaming logic. | 75 // following renaming logic. |
| 68 if (new_path == full_path_) { | 76 if (new_path == full_path_) { |
| 69 path_renamed_ = true; | 77 path_renamed_ = true; |
| 70 | 78 |
| 71 // Don't close the file if we're not done (finished or canceled). | 79 // Don't close the file if we're not done (finished or canceled). |
| 72 if (!in_progress_) | 80 if (!saved_in_progress) |
| 73 Close(); | 81 Close(); |
| 74 | 82 |
| 75 return true; | 83 return true; |
| 76 } | 84 } |
| 77 | 85 |
| 78 Close(); | 86 Close(); |
| 79 | 87 |
| 80 #if defined(OS_WIN) | 88 #if defined(OS_WIN) |
| 81 // We cannot rename because rename will keep the same security descriptor | 89 // We cannot rename because rename will keep the same security descriptor |
| 82 // on the destination file. We want to recreate the security descriptor | 90 // on the destination file. We want to recreate the security descriptor |
| (...skipping 19 matching lines...) Expand all Loading... |
| 102 | 110 |
| 103 if (stat_succeeded) | 111 if (stat_succeeded) |
| 104 chmod(new_path.value().c_str(), st.st_mode); | 112 chmod(new_path.value().c_str(), st.st_mode); |
| 105 } | 113 } |
| 106 #endif | 114 #endif |
| 107 | 115 |
| 108 full_path_ = new_path; | 116 full_path_ = new_path; |
| 109 path_renamed_ = true; | 117 path_renamed_ = true; |
| 110 | 118 |
| 111 // We don't need to re-open the file if we're done (finished or canceled). | 119 // We don't need to re-open the file if we're done (finished or canceled). |
| 112 if (!in_progress_) | 120 if (!saved_in_progress) |
| 113 return true; | 121 return true; |
| 114 | 122 |
| 115 if (!Open()) | 123 if (!Open()) |
| 116 return false; | 124 return false; |
| 117 | 125 |
| 118 // Move to the end of the new file. | 126 // Move to the end of the new file. |
| 119 if (file_stream_->Seek(net::FROM_END, 0) < 0) | 127 if (file_stream_->Seek(net::FROM_END, 0) < 0) |
| 120 return false; | 128 return false; |
| 121 | 129 |
| 122 return true; | 130 return true; |
| 123 } | 131 } |
| 124 | 132 |
| 133 void DownloadFile::Finish() { |
| 134 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 135 Close(); |
| 136 } |
| 137 |
| 125 void DownloadFile::Close() { | 138 void DownloadFile::Close() { |
| 139 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 126 if (file_stream_.get()) { | 140 if (file_stream_.get()) { |
| 127 #if defined(OS_CHROMEOS) | 141 #if defined(OS_CHROMEOS) |
| 128 // Currently we don't really care about the return value, since if it fails | 142 // 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. | 143 // theres not much we can do. But we might in the future. |
| 130 file_stream_->Flush(); | 144 file_stream_->Flush(); |
| 131 #endif | 145 #endif |
| 132 file_stream_->Close(); | 146 file_stream_->Close(); |
| 133 file_stream_.reset(); | 147 file_stream_.reset(); |
| 134 } | 148 } |
| 135 } | 149 } |
| 136 | 150 |
| 137 bool DownloadFile::Open() { | 151 bool DownloadFile::Open() { |
| 152 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 138 DCHECK(!full_path_.empty()); | 153 DCHECK(!full_path_.empty()); |
| 139 | 154 |
| 140 // Create a new file steram if it is not provided. | 155 // Create a new file steram if it is not provided. |
| 141 if (!file_stream_.get()) { | 156 if (!file_stream_.get()) { |
| 142 file_stream_.reset(new net::FileStream); | 157 file_stream_.reset(new net::FileStream); |
| 143 if (file_stream_->Open(full_path_, | 158 if (file_stream_->Open(full_path_, |
| 144 base::PLATFORM_FILE_OPEN_ALWAYS | | 159 base::PLATFORM_FILE_OPEN_ALWAYS | |
| 145 base::PLATFORM_FILE_WRITE) != net::OK) { | 160 base::PLATFORM_FILE_WRITE) != net::OK) { |
| 146 file_stream_.reset(); | 161 file_stream_.reset(); |
| 147 return false; | 162 return false; |
| 148 } | 163 } |
| 149 } | 164 } |
| 150 | 165 |
| 151 #if defined(OS_WIN) | 166 #if defined(OS_WIN) |
| 152 AnnotateWithSourceInformation(); | 167 AnnotateWithSourceInformation(); |
| 153 #endif | 168 #endif |
| 154 return true; | 169 return true; |
| 155 } | 170 } |
| 156 | 171 |
| 157 void DownloadFile::AnnotateWithSourceInformation() { | 172 void DownloadFile::AnnotateWithSourceInformation() { |
| 173 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 158 #if defined(OS_WIN) | 174 #if defined(OS_WIN) |
| 159 // Sets the Zone to tell Windows that this file comes from the internet. | 175 // 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. | 176 // We ignore the return value because a failure is not fatal. |
| 161 win_util::SetInternetZoneIdentifier(full_path_); | 177 win_util::SetInternetZoneIdentifier(full_path_); |
| 162 #elif defined(OS_MACOSX) | 178 #elif defined(OS_MACOSX) |
| 163 file_metadata::AddQuarantineMetadataToFile(full_path_, source_url_, | 179 file_metadata::AddQuarantineMetadataToFile(full_path_, source_url_, |
| 164 referrer_url_); | 180 referrer_url_); |
| 165 file_metadata::AddOriginMetadataToFile(full_path_, source_url_, | 181 file_metadata::AddOriginMetadataToFile(full_path_, source_url_, |
| 166 referrer_url_); | 182 referrer_url_); |
| 167 #endif | 183 #endif |
| 168 } | 184 } |
| 185 |
| 186 void DownloadFile::CancelDownloadRequest(ResourceDispatcherHost* rdh) { |
| 187 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE)); |
| 188 ChromeThread::PostTask( |
| 189 ChromeThread::IO, FROM_HERE, |
| 190 NewRunnableFunction(&download_util::CancelDownloadRequest, |
| 191 rdh, |
| 192 child_id_, |
| 193 request_id_)); |
| 194 } |
| OLD | NEW |