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 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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |