| OLD | NEW | 
|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "content/browser/download/base_file.h" | 5 #include "content/browser/download/base_file.h" | 
| 6 | 6 | 
| 7 #include <utility> | 7 #include <utility> | 
| 8 | 8 | 
| 9 #include "base/bind.h" | 9 #include "base/bind.h" | 
| 10 #include "base/files/file.h" | 10 #include "base/files/file.h" | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
| 37   else | 37   else | 
| 38     Cancel();  // Will delete the file. | 38     Cancel();  // Will delete the file. | 
| 39 } | 39 } | 
| 40 | 40 | 
| 41 DownloadInterruptReason BaseFile::Initialize( | 41 DownloadInterruptReason BaseFile::Initialize( | 
| 42     const base::FilePath& full_path, | 42     const base::FilePath& full_path, | 
| 43     const base::FilePath& default_directory, | 43     const base::FilePath& default_directory, | 
| 44     base::File file, | 44     base::File file, | 
| 45     int64_t bytes_so_far, | 45     int64_t bytes_so_far, | 
| 46     const std::string& hash_so_far, | 46     const std::string& hash_so_far, | 
| 47     std::unique_ptr<crypto::SecureHash> hash_state) { | 47     std::unique_ptr<crypto::SecureHash> hash_state, | 
|  | 48     bool is_sparse_file) { | 
| 48   DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 49   DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 
| 49   DCHECK(!detached_); | 50   DCHECK(!detached_); | 
| 50 | 51 | 
| 51   if (full_path.empty()) { | 52   if (full_path.empty()) { | 
| 52     base::FilePath initial_directory(default_directory); | 53     base::FilePath initial_directory(default_directory); | 
| 53     base::FilePath temp_file; | 54     base::FilePath temp_file; | 
| 54     if (initial_directory.empty()) { | 55     if (initial_directory.empty()) { | 
| 55       initial_directory = | 56       initial_directory = | 
| 56           GetContentClient()->browser()->GetDefaultDownloadDirectory(); | 57           GetContentClient()->browser()->GetDefaultDownloadDirectory(); | 
| 57     } | 58     } | 
| 58     // |initial_directory| can still be empty if ContentBrowserClient returned | 59     // |initial_directory| can still be empty if ContentBrowserClient returned | 
| 59     // an empty path for the downloads directory. | 60     // an empty path for the downloads directory. | 
| 60     if ((initial_directory.empty() || | 61     if ((initial_directory.empty() || | 
| 61          !base::CreateTemporaryFileInDir(initial_directory, &temp_file)) && | 62          !base::CreateTemporaryFileInDir(initial_directory, &temp_file)) && | 
| 62         !base::CreateTemporaryFile(&temp_file)) { | 63         !base::CreateTemporaryFile(&temp_file)) { | 
| 63       return LogInterruptReason("Unable to create", 0, | 64       return LogInterruptReason("Unable to create", 0, | 
| 64                                 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); | 65                                 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); | 
| 65     } | 66     } | 
| 66     full_path_ = temp_file; | 67     full_path_ = temp_file; | 
| 67   } else { | 68   } else { | 
| 68     full_path_ = full_path; | 69     full_path_ = full_path; | 
| 69   } | 70   } | 
| 70 | 71 | 
| 71   bytes_so_far_ = bytes_so_far; | 72   bytes_so_far_ = bytes_so_far; | 
| 72   secure_hash_ = std::move(hash_state); | 73   secure_hash_ = std::move(hash_state); | 
|  | 74   is_sparse_file_ = is_sparse_file; | 
|  | 75   DCHECK(!is_sparse_file_ || !secure_hash_); | 
| 73   file_ = std::move(file); | 76   file_ = std::move(file); | 
| 74 | 77 | 
| 75   return Open(hash_so_far); | 78   return Open(hash_so_far); | 
| 76 } | 79 } | 
| 77 | 80 | 
| 78 DownloadInterruptReason BaseFile::AppendDataToFile(const char* data, | 81 DownloadInterruptReason BaseFile::AppendDataToFile(const char* data, | 
| 79                                                    size_t data_len) { | 82                                                    size_t data_len) { | 
| 80   DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 83   DCHECK(!is_sparse_file_); | 
| 81   DCHECK(!detached_); | 84   return WriteDataToFile(bytes_so_far_, data, data_len); | 
|  | 85 } | 
| 82 | 86 | 
|  | 87 DownloadInterruptReason BaseFile::WriteDataToFile(int64_t offset, | 
|  | 88                                                   const char* data, | 
|  | 89                                                   size_t data_len) { | 
| 83   // NOTE(benwells): The above DCHECK won't be present in release builds, | 90   // NOTE(benwells): The above DCHECK won't be present in release builds, | 
| 84   // so we log any occurences to see how common this error is in the wild. | 91   // so we log any occurences to see how common this error is in the wild. | 
| 85   if (detached_) | 92   if (detached_) | 
| 86     RecordDownloadCount(APPEND_TO_DETACHED_FILE_COUNT); | 93     RecordDownloadCount(APPEND_TO_DETACHED_FILE_COUNT); | 
| 87 | 94 | 
| 88   if (!file_.IsValid()) | 95   if (!file_.IsValid()) | 
| 89     return LogInterruptReason("No file stream on append", 0, | 96     return LogInterruptReason("No file stream on append", 0, | 
| 90                               DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); | 97                               DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); | 
| 91 | 98 | 
| 92   // TODO(phajdan.jr): get rid of this check. | 99   // TODO(phajdan.jr): get rid of this check. | 
| 93   if (data_len == 0) | 100   if (data_len == 0) | 
| 94     return DOWNLOAD_INTERRUPT_REASON_NONE; | 101     return DOWNLOAD_INTERRUPT_REASON_NONE; | 
| 95 | 102 | 
| 96   // The Write call below is not guaranteed to write all the data. |  | 
| 97   size_t write_count = 0; |  | 
| 98   size_t len = data_len; |  | 
| 99   const char* current_data = data; |  | 
| 100   net_log_.BeginEvent(net::NetLogEventType::DOWNLOAD_FILE_WRITTEN); | 103   net_log_.BeginEvent(net::NetLogEventType::DOWNLOAD_FILE_WRITTEN); | 
| 101   while (len > 0) { | 104   int write_result = file_.Write(offset, data, data_len); | 
| 102     write_count++; | 105   DCHECK_NE(0, write_result); | 
| 103     int write_result = file_.WriteAtCurrentPos(current_data, len); |  | 
| 104     DCHECK_NE(0, write_result); |  | 
| 105 | 106 | 
| 106     // Report errors on file writes. | 107   // Report errors on file writes. | 
| 107     if (write_result < 0) | 108   if (write_result < 0) | 
| 108       return LogSystemError("Write", logging::GetLastSystemErrorCode()); | 109     return LogSystemError("Write", logging::GetLastSystemErrorCode()); | 
| 109 | 110 | 
| 110     // Update status. | 111   DCHECK_EQ(static_cast<size_t>(write_result), data_len); | 
| 111     size_t write_size = static_cast<size_t>(write_result); | 112   bytes_so_far_ += data_len; | 
| 112     DCHECK_LE(write_size, len); |  | 
| 113     len -= write_size; |  | 
| 114     current_data += write_size; |  | 
| 115     bytes_so_far_ += write_size; |  | 
| 116   } |  | 
| 117   net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_WRITTEN, | 113   net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_WRITTEN, | 
| 118                     net::NetLog::Int64Callback("bytes", data_len)); | 114                     net::NetLog::Int64Callback("bytes", data_len)); | 
| 119 | 115 | 
| 120   if (secure_hash_) | 116   if (secure_hash_) | 
| 121     secure_hash_->Update(data, data_len); | 117     secure_hash_->Update(data, data_len); | 
| 122 | 118 | 
| 123   return DOWNLOAD_INTERRUPT_REASON_NONE; | 119   return DOWNLOAD_INTERRUPT_REASON_NONE; | 
| 124 } | 120 } | 
| 125 | 121 | 
| 126 DownloadInterruptReason BaseFile::Rename(const base::FilePath& new_path) { | 122 DownloadInterruptReason BaseFile::Rename(const base::FilePath& new_path) { | 
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 179   if (!full_path_.empty()) { | 175   if (!full_path_.empty()) { | 
| 180     net_log_.AddEvent(net::NetLogEventType::DOWNLOAD_FILE_DELETED); | 176     net_log_.AddEvent(net::NetLogEventType::DOWNLOAD_FILE_DELETED); | 
| 181     base::DeleteFile(full_path_, false); | 177     base::DeleteFile(full_path_, false); | 
| 182   } | 178   } | 
| 183 | 179 | 
| 184   Detach(); | 180   Detach(); | 
| 185 } | 181 } | 
| 186 | 182 | 
| 187 std::unique_ptr<crypto::SecureHash> BaseFile::Finish() { | 183 std::unique_ptr<crypto::SecureHash> BaseFile::Finish() { | 
| 188   DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 184   DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 
|  | 185 | 
|  | 186   // TODO(qinmin): verify that all the holes have been filled. | 
|  | 187   if (is_sparse_file_) | 
|  | 188     CalculatePartialHash(std::string()); | 
| 189   Close(); | 189   Close(); | 
| 190   return std::move(secure_hash_); | 190   return std::move(secure_hash_); | 
| 191 } | 191 } | 
| 192 | 192 | 
| 193 std::string BaseFile::DebugString() const { | 193 std::string BaseFile::DebugString() const { | 
| 194   return base::StringPrintf( | 194   return base::StringPrintf( | 
| 195       "{ " | 195       "{ " | 
| 196       " full_path_ = \"%" PRFilePath | 196       " full_path_ = \"%" PRFilePath | 
| 197       "\"" | 197       "\"" | 
| 198       " bytes_so_far_ = %" PRId64 " detached_ = %c }", | 198       " bytes_so_far_ = %" PRId64 " detached_ = %c }", | 
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 281     if (!file_.IsValid()) { | 281     if (!file_.IsValid()) { | 
| 282       return LogNetError("Open/Initialize File", | 282       return LogNetError("Open/Initialize File", | 
| 283                          net::FileErrorToNetError(file_.error_details())); | 283                          net::FileErrorToNetError(file_.error_details())); | 
| 284     } | 284     } | 
| 285   } | 285   } | 
| 286 | 286 | 
| 287   net_log_.BeginEvent( | 287   net_log_.BeginEvent( | 
| 288       net::NetLogEventType::DOWNLOAD_FILE_OPENED, | 288       net::NetLogEventType::DOWNLOAD_FILE_OPENED, | 
| 289       base::Bind(&FileOpenedNetLogCallback, &full_path_, bytes_so_far_)); | 289       base::Bind(&FileOpenedNetLogCallback, &full_path_, bytes_so_far_)); | 
| 290 | 290 | 
|  | 291   // For sparse file, skip hash validation. | 
|  | 292   if (is_sparse_file_) { | 
|  | 293     if (file_.GetLength() < bytes_so_far_) { | 
|  | 294       ClearFile(); | 
|  | 295       return LogInterruptReason("File has fewer written bytes than expected", 0, | 
|  | 296                                 DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT); | 
|  | 297     } | 
|  | 298     return DOWNLOAD_INTERRUPT_REASON_NONE; | 
|  | 299   } | 
|  | 300 | 
| 291   if (!secure_hash_) { | 301   if (!secure_hash_) { | 
| 292     DownloadInterruptReason reason = CalculatePartialHash(hash_so_far); | 302     DownloadInterruptReason reason = CalculatePartialHash(hash_so_far); | 
| 293     if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { | 303     if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { | 
| 294       ClearFile(); | 304       ClearFile(); | 
| 295       return reason; | 305       return reason; | 
| 296     } | 306     } | 
| 297   } | 307   } | 
| 298 | 308 | 
| 299   int64_t file_size = file_.Seek(base::File::FROM_END, 0); | 309   int64_t file_size = file_.Seek(base::File::FROM_END, 0); | 
| 300   if (file_size < 0) { | 310   if (file_size < 0) { | 
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 456 #else  // !OS_WIN && !OS_MACOSX && !OS_LINUX | 466 #else  // !OS_WIN && !OS_MACOSX && !OS_LINUX | 
| 457 DownloadInterruptReason BaseFile::AnnotateWithSourceInformation( | 467 DownloadInterruptReason BaseFile::AnnotateWithSourceInformation( | 
| 458     const std::string& client_guid, | 468     const std::string& client_guid, | 
| 459     const GURL& source_url, | 469     const GURL& source_url, | 
| 460     const GURL& referrer_url) { | 470     const GURL& referrer_url) { | 
| 461   return DOWNLOAD_INTERRUPT_REASON_NONE; | 471   return DOWNLOAD_INTERRUPT_REASON_NONE; | 
| 462 } | 472 } | 
| 463 #endif | 473 #endif | 
| 464 | 474 | 
| 465 }  // namespace content | 475 }  // namespace content | 
| OLD | NEW | 
|---|