Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(449)

Side by Side Diff: content/browser/download/base_file.cc

Issue 2695153002: Refactor BaseFile class to support sparse files (Closed)
Patch Set: using a single fd Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 AccessMode access_mode) {
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 access_mode_ = access_mode;
75 DCHECK(access_mode_ == EXCLUSIVE || !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_EQ(access_mode_, EXCLUSIVE);
81 DCHECK(!detached_); 84 return WriteAtCurrentPos(data, data_len);
85 }
82 86
87 DownloadInterruptReason BaseFile::WriteDataToFile(int64_t offset,
88 const char* data,
89 size_t data_len) {
90 DCHECK_EQ(access_mode_, SHARED);
91
92 if (file_.Seek(base::File::FROM_BEGIN, offset) < 0) {
asanka 2017/02/16 18:11:24 base::File::Write() can be used to write to a spec
asanka 2017/02/16 18:46:25 Disregard.
qinmin 2017/02/16 21:35:50 I used this seek() to reuse some of code from Appe
asanka 2017/02/16 21:58:02 Probably because this code predates the logic in b
qinmin 2017/02/16 22:20:29 Done. Removed the while loop around the Write() ca
93 logging::SystemErrorCode error = logging::GetLastSystemErrorCode();
94 return LogSystemError("Unable to seek", error);
95 }
96 return WriteAtCurrentPos(data, data_len);
97 }
98
99 DownloadInterruptReason BaseFile::WriteAtCurrentPos(const char* data,
100 size_t data_len) {
83 // NOTE(benwells): The above DCHECK won't be present in release builds, 101 // 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. 102 // so we log any occurences to see how common this error is in the wild.
85 if (detached_) 103 if (detached_)
86 RecordDownloadCount(APPEND_TO_DETACHED_FILE_COUNT); 104 RecordDownloadCount(APPEND_TO_DETACHED_FILE_COUNT);
87 105
88 if (!file_.IsValid()) 106 if (!file_.IsValid())
89 return LogInterruptReason("No file stream on append", 0, 107 return LogInterruptReason("No file stream on append", 0,
90 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED); 108 DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
91 109
92 // TODO(phajdan.jr): get rid of this check. 110 // TODO(phajdan.jr): get rid of this check.
(...skipping 23 matching lines...) Expand all
116 } 134 }
117 net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_WRITTEN, 135 net_log_.EndEvent(net::NetLogEventType::DOWNLOAD_FILE_WRITTEN,
118 net::NetLog::Int64Callback("bytes", data_len)); 136 net::NetLog::Int64Callback("bytes", data_len));
119 137
120 if (secure_hash_) 138 if (secure_hash_)
121 secure_hash_->Update(data, data_len); 139 secure_hash_->Update(data, data_len);
122 140
123 return DOWNLOAD_INTERRUPT_REASON_NONE; 141 return DOWNLOAD_INTERRUPT_REASON_NONE;
124 } 142 }
125 143
126 DownloadInterruptReason BaseFile::Rename(const base::FilePath& new_path) { 144 DownloadInterruptReason BaseFile::Rename(const base::FilePath& new_path) {
asanka 2017/02/16 18:11:24 Methods like Rename() and Annotate...() depend on
asanka 2017/02/16 18:46:26 Disregard. I misunderstood how BaseFile is intende
qinmin 2017/02/16 21:35:50 Yes, the BaseFile will still be owned by a Downloa
127 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 145 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
128 DownloadInterruptReason rename_result = DOWNLOAD_INTERRUPT_REASON_NONE; 146 DownloadInterruptReason rename_result = DOWNLOAD_INTERRUPT_REASON_NONE;
129 147
130 // If the new path is same as the old one, there is no need to perform the 148 // If the new path is same as the old one, there is no need to perform the
131 // following renaming logic. 149 // following renaming logic.
132 if (new_path == full_path_) 150 if (new_path == full_path_)
133 return DOWNLOAD_INTERRUPT_REASON_NONE; 151 return DOWNLOAD_INTERRUPT_REASON_NONE;
134 152
135 // Save the information whether the download is in progress because 153 // Save the information whether the download is in progress because
136 // it will be overwritten by closing the file. 154 // it will be overwritten by closing the file.
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 if (!file_.IsValid()) { 299 if (!file_.IsValid()) {
282 return LogNetError("Open/Initialize File", 300 return LogNetError("Open/Initialize File",
283 net::FileErrorToNetError(file_.error_details())); 301 net::FileErrorToNetError(file_.error_details()));
284 } 302 }
285 } 303 }
286 304
287 net_log_.BeginEvent( 305 net_log_.BeginEvent(
288 net::NetLogEventType::DOWNLOAD_FILE_OPENED, 306 net::NetLogEventType::DOWNLOAD_FILE_OPENED,
289 base::Bind(&FileOpenedNetLogCallback, &full_path_, bytes_so_far_)); 307 base::Bind(&FileOpenedNetLogCallback, &full_path_, bytes_so_far_));
290 308
309 // For SHARED file, skip hash validation.
310 if (access_mode_ == SHARED) {
311 if (file_.GetLength() < bytes_so_far_) {
312 ClearFile();
313 return LogInterruptReason("File has fewer written bytes than expected", 0,
314 DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT);
315 }
316 return DOWNLOAD_INTERRUPT_REASON_NONE;
317 }
318
291 if (!secure_hash_) { 319 if (!secure_hash_) {
292 DownloadInterruptReason reason = CalculatePartialHash(hash_so_far); 320 DownloadInterruptReason reason = CalculatePartialHash(hash_so_far);
293 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) { 321 if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) {
294 ClearFile(); 322 ClearFile();
295 return reason; 323 return reason;
296 } 324 }
297 } 325 }
298 326
299 int64_t file_size = file_.Seek(base::File::FROM_END, 0); 327 int64_t file_size = file_.Seek(base::File::FROM_END, 0);
300 if (file_size < 0) { 328 if (file_size < 0) {
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
456 #else // !OS_WIN && !OS_MACOSX && !OS_LINUX 484 #else // !OS_WIN && !OS_MACOSX && !OS_LINUX
457 DownloadInterruptReason BaseFile::AnnotateWithSourceInformation( 485 DownloadInterruptReason BaseFile::AnnotateWithSourceInformation(
458 const std::string& client_guid, 486 const std::string& client_guid,
459 const GURL& source_url, 487 const GURL& source_url,
460 const GURL& referrer_url) { 488 const GURL& referrer_url) {
461 return DOWNLOAD_INTERRUPT_REASON_NONE; 489 return DOWNLOAD_INTERRUPT_REASON_NONE;
462 } 490 }
463 #endif 491 #endif
464 492
465 } // namespace content 493 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698