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

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

Issue 2695153002: Refactor BaseFile class to support sparse files (Closed)
Patch Set: 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 #ifndef CONTENT_BROWSER_DOWNLOAD_BASE_FILE_H_ 5 #ifndef CONTENT_BROWSER_DOWNLOAD_BASE_FILE_H_
6 #define CONTENT_BROWSER_DOWNLOAD_BASE_FILE_H_ 6 #define CONTENT_BROWSER_DOWNLOAD_BASE_FILE_H_
7 7
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <stdint.h> 9 #include <stdint.h>
10 10
(...skipping 15 matching lines...) Expand all
26 26
27 namespace content { 27 namespace content {
28 28
29 // File being downloaded and saved to disk. This is a base class 29 // File being downloaded and saved to disk. This is a base class
30 // for DownloadFile and SaveFile, which keep more state information. BaseFile 30 // for DownloadFile and SaveFile, which keep more state information. BaseFile
31 // considers itself the owner of the physical file and will delete it when the 31 // considers itself the owner of the physical file and will delete it when the
32 // BaseFile object is destroyed unless the ownership is revoked via a call to 32 // BaseFile object is destroyed unless the ownership is revoked via a call to
33 // Detach(). 33 // Detach().
34 class CONTENT_EXPORT BaseFile { 34 class CONTENT_EXPORT BaseFile {
35 public: 35 public:
36 // Enum to indicate whether the file is exclusived owned, or shared among
37 // multiple writers.
38 enum AccessMode {
39 EXCLUSIVE = 0,
40 SHARED,
41 };
42
36 // May be constructed on any thread. All other routines (including 43 // May be constructed on any thread. All other routines (including
37 // destruction) must occur on the FILE thread. 44 // destruction) must occur on the FILE thread.
38 BaseFile(const net::NetLogWithSource& net_log); 45 BaseFile(const net::NetLogWithSource& net_log);
39 ~BaseFile(); 46 ~BaseFile();
40 47
41 // Returns DOWNLOAD_INTERRUPT_REASON_NONE on success, or a 48 // Returns DOWNLOAD_INTERRUPT_REASON_NONE on success, or a
42 // DownloadInterruptReason on failure. Upon success, the file at |full_path()| 49 // DownloadInterruptReason on failure. Upon success, the file at |full_path()|
43 // is assumed to be owned by the BaseFile. It will be deleted when the 50 // is assumed to be owned by the BaseFile. It will be deleted when the
44 // BaseFile object is destroyed unless Detach() is called before destroying 51 // BaseFile object is destroyed unless Detach() is called before destroying
45 // the BaseFile instance. 52 // the BaseFile instance.
46 // 53 //
47 // |full_path|: Full path to the download file. Can be empty, in which case 54 // |full_path|: Full path to the download file. Can be empty, in which case
48 // the rules described in |default_directory| will be used to generate a 55 // the rules described in |default_directory| will be used to generate a
49 // temporary filename. 56 // temporary filename.
50 // 57 //
51 // |default_directory|: specifies the directory to create the temporary file 58 // |default_directory|: specifies the directory to create the temporary file
52 // in if |full_path| is empty. If |default_directory| and |full_path| are 59 // in if |full_path| is empty. If |default_directory| and |full_path| are
53 // empty, then a temporary file will be created in the default download 60 // empty, then a temporary file will be created in the default download
54 // location as determined by ContentBrowserClient. 61 // location as determined by ContentBrowserClient.
55 // 62 //
56 // |file|: The base::File handle to use. If specified, BaseFile will not open 63 // |file|: The base::File handle to use. If specified, BaseFile will not open
57 // a file and will use this handle. The file should be opened for both 64 // a file and will use this handle. The file should be opened for both
58 // read and write. Only makes sense if |full_path| is non-empty since it 65 // read and write. Only makes sense if |full_path| is non-empty since it
59 // implies that the caller already knows the path to the file. There's no 66 // implies that the caller already knows the path to the file. There's no
60 // perfect way to come up with a canonical path for a file. So BaseFile 67 // perfect way to come up with a canonical path for a file. So BaseFile
61 // will not attempt to determine the |full_path|. 68 // will not attempt to determine the |full_path|.
62 // 69 //
63 // |bytes_so_far|: If a file is provided (via |full_path| or |file|), then 70 // |offset|: If a file is provided (via |full_path| or |file|), then this
64 // this argument specifies the size of the file to expect. It is legal for 71 // argument specifies the starting position to write the file. If
65 // the file to be larger, in which case the file will be truncated down to 72 // |access_mode| is EXCLUSIVE, this value should be the size of the file
66 // this size. However, if the file is shorter, then the operation will 73 // to expect. It is legal for the file to be larger, in which case the
67 // fail with DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT. 74 // file will be truncated down to this size. However, if the file is
75 // shorter, then the operation will fail with
76 // DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT. If |access_mode_| is SHARED,
77 // file size check is ignored as the writer is expecting other writers to
78 // fill the gaps or append more data.
68 // 79 //
69 // |hash_so_far|: If |bytes_so_far| is non-zero, this specifies the SHA-256 80 // |hash_so_far|: If |offset| is non-zero, this specifies the SHA-256
70 // hash of the first |bytes_so_far| bytes of the target file. If 81 // hash of the first |offset| bytes of the target file. If
71 // specified, BaseFile will read the first |bytes_so_far| of the target 82 // specified, BaseFile will read the first |offset| of the target
72 // file in order to calculate the hash and verify that the file matches. 83 // file in order to calculate the hash and verify that the file matches.
73 // If there's a mismatch, then the operation fails with 84 // If there's a mismatch, then the operation fails with
74 // DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH. Not used if |hash_state| 85 // DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH. Not used if |hash_state|
75 // is also specified. 86 // is also specified or |access_mode| is equal to SHARED.
76 // 87 //
77 // |hash_state|: The partial hash object to use. Only meaningful if there's a 88 // |hash_state|: The partial hash object to use. Only meaningful if there's a
78 // preexisting target file and it is non-empty (i.e. bytes_so_far is 89 // preexisting target file and it is non-empty (i.e. offset is
79 // non-zero). If specified, BaseFile will assume that the bytes up to 90 // non-zero). If specified, BaseFile will assume that the bytes up to
80 // |bytes_so_far| has been accurately hashed into |hash_state| and will 91 // |offset| has been accurately hashed into |hash_state| and will
81 // ignore |hash_so_far|. 92 // ignore |hash_so_far|. Not used if |access_mode| is equal to SHARED.
93 //
94 // |access_mode|: Specifies whether the file is going to be accessed by
95 // multiple writers. If so, it is possible that one writer can request
96 // writing to a |offset| that is larger than the file size.
82 DownloadInterruptReason Initialize( 97 DownloadInterruptReason Initialize(
83 const base::FilePath& full_path, 98 const base::FilePath& full_path,
84 const base::FilePath& default_directory, 99 const base::FilePath& default_directory,
85 base::File file, 100 base::File file,
86 int64_t bytes_so_far, 101 int64_t offset,
87 const std::string& hash_so_far, 102 const std::string& hash_so_far,
88 std::unique_ptr<crypto::SecureHash> hash_state); 103 std::unique_ptr<crypto::SecureHash> hash_state,
104 AccessMode access_mode);
89 105
90 // Write a new chunk of data to the file. Returns a DownloadInterruptReason 106 // Write a new chunk of data to the current |offset_| inside the file. Returns
91 // indicating the result of the operation. 107 // a DownloadInterruptReason indicating the result of the operation.
92 DownloadInterruptReason AppendDataToFile(const char* data, size_t data_len); 108 DownloadInterruptReason WriteDataToFile(const char* data, size_t data_len);
93 109
94 // Rename the download file. Returns a DownloadInterruptReason indicating the 110 // Rename the download file. Returns a DownloadInterruptReason indicating the
95 // result of the operation. A return code of NONE indicates that the rename 111 // result of the operation. A return code of NONE indicates that the rename
96 // was successful. After a failure, the full_path() and in_progress() can be 112 // was successful. After a failure, the full_path() and in_progress() can be
97 // used to determine the last known filename and whether the file is available 113 // used to determine the last known filename and whether the file is available
98 // for writing or retrying the rename. Call Finish() to obtain the last known 114 // for writing or retrying the rename. Call Finish() to obtain the last known
99 // hash state. 115 // hash state.
100 DownloadInterruptReason Rename(const base::FilePath& full_path); 116 DownloadInterruptReason Rename(const base::FilePath& full_path);
101 117
102 // Mark the file as detached. Up until this method is called, BaseFile assumes 118 // Mark the file as detached. Up until this method is called, BaseFile assumes
(...skipping 27 matching lines...) Expand all
130 const GURL& referrer_url); 146 const GURL& referrer_url);
131 147
132 // Returns the last known path to the download file. Can be empty if there's 148 // Returns the last known path to the download file. Can be empty if there's
133 // no file. 149 // no file.
134 const base::FilePath& full_path() const { return full_path_; } 150 const base::FilePath& full_path() const { return full_path_; }
135 151
136 // Returns true if the file is open. If true, the file can be written to or 152 // Returns true if the file is open. If true, the file can be written to or
137 // renamed. 153 // renamed.
138 bool in_progress() const { return file_.IsValid(); } 154 bool in_progress() const { return file_.IsValid(); }
139 155
140 // Returns the number of bytes in the file pointed to by full_path(). 156 // Returns the number of bytes that has been written so far. If |access_mode_|
157 // is EXCLUSIVE, this should always be equal to the file size. If
158 // |access_mode_| is SHARED, this only records the byte that is written by
159 // the current writer. So it is smaller than the file size as there are other
160 // writers around.
141 int64_t bytes_so_far() const { return bytes_so_far_; } 161 int64_t bytes_so_far() const { return bytes_so_far_; }
142 162
163 // Returns the current offset that data will be written to.
164 int64_t offset() const { return offset_; }
165
143 std::string DebugString() const; 166 std::string DebugString() const;
144 167
145 private: 168 private:
146 friend class BaseFileTest; 169 friend class BaseFileTest;
147 FRIEND_TEST_ALL_PREFIXES(BaseFileTest, IsEmptyHash); 170 FRIEND_TEST_ALL_PREFIXES(BaseFileTest, IsEmptyHash);
148 171
149 // Creates and opens the file_ if it is invalid. 172 // Creates and opens the file_ if it is invalid.
150 // 173 //
151 // If |hash_so_far| is not empty, then it must match the SHA-256 hash of the 174 // If |access_mode_| is EXCLUSIVE and |hash_so_far| is not empty, then it must
152 // first |bytes_so_far_| bytes of |file_|. If there's a hash mismatch, Open() 175 // match the SHA-256 hash of the first |offset_| bytes of |file_|. If there's
153 // fails with DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH. 176 // a hash mismatch, Open() fails with
177 // DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH.
154 // 178 //
155 // If the opened file is shorter than |bytes_so_far_| bytes, then Open() fails 179 // When |access_mode_| is EXCLUSIVE, If the opened file is shorter than
156 // with DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT. If the opened file is 180 // |offset_| bytes, then Open() fails with
157 // longer, then the file is truncated to |bytes_so_far_|. 181 // DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT. If the opened file is
182 // longer, then the file is truncated to |offset_|.
158 // 183 //
159 // Open() can fail for other reasons as well. In that case, it returns a 184 // Open() can fail for other reasons as well. In that case, it returns a
160 // relevant interrupt reason. Unless Open() return 185 // relevant interrupt reason. Unless Open() return
161 // DOWNLOAD_INTERRUPT_REASON_NONE, it should be assumed that |file_| is not 186 // DOWNLOAD_INTERRUPT_REASON_NONE, it should be assumed that |file_| is not
162 // valid. 187 // valid.
163 DownloadInterruptReason Open(const std::string& hash_so_far); 188 DownloadInterruptReason Open(const std::string& hash_so_far);
164 189
165 // Closes and resets file_. 190 // Closes and resets file_.
166 void Close(); 191 void Close();
167 192
168 // Resets file_. 193 // Resets file_.
169 void ClearFile(); 194 void ClearFile();
170 195
171 // Platform specific method that moves a file to a new path and adjusts the 196 // Platform specific method that moves a file to a new path and adjusts the
172 // security descriptor / permissions on the file to match the defaults for the 197 // security descriptor / permissions on the file to match the defaults for the
173 // new directory. 198 // new directory.
174 DownloadInterruptReason MoveFileAndAdjustPermissions( 199 DownloadInterruptReason MoveFileAndAdjustPermissions(
175 const base::FilePath& new_path); 200 const base::FilePath& new_path);
176 201
177 // Split out from CurrentSpeed to enable testing. 202 // Split out from CurrentSpeed to enable testing.
178 int64_t CurrentSpeedAtTime(base::TimeTicks current_time) const; 203 int64_t CurrentSpeedAtTime(base::TimeTicks current_time) const;
179 204
180 // Verifies that: 205 // This function is only used when |access_mode_| is EXCLUSIVE. It verifies
181 // * Size of the file represented by |file_| is at least |bytes_so_far_|. 206 // that:
207 // * Size of the file represented by |file_| is at least |offset_|.
182 // 208 //
183 // * If |hash_to_expect| is not empty, then the result of hashing the first 209 // * If |hash_to_expect| is not empty, then the result of hashing the first
184 // |bytes_so_far_| bytes of |file_| matches |hash_to_expect|. 210 // |offset_| bytes of |file_| matches |hash_to_expect|.
185 // 211 //
186 // If the result is REASON_NONE, then on return |secure_hash_| is valid and 212 // If the result is REASON_NONE, then on return |secure_hash_| is valid and
187 // is ready to hash bytes from offset |bytes_so_far_| + 1. 213 // is ready to hash bytes from offset |offset_| + 1.
188 DownloadInterruptReason CalculatePartialHash( 214 DownloadInterruptReason CalculatePartialHash(
189 const std::string& hash_to_expect); 215 const std::string& hash_to_expect);
190 216
191 // Log a TYPE_DOWNLOAD_FILE_ERROR NetLog event with |error| and passes error 217 // Log a TYPE_DOWNLOAD_FILE_ERROR NetLog event with |error| and passes error
192 // on through, converting to a |DownloadInterruptReason|. 218 // on through, converting to a |DownloadInterruptReason|.
193 DownloadInterruptReason LogNetError(const char* operation, net::Error error); 219 DownloadInterruptReason LogNetError(const char* operation, net::Error error);
194 220
195 // Log the system error in |os_error| and converts it into a 221 // Log the system error in |os_error| and converts it into a
196 // |DownloadInterruptReason|. 222 // |DownloadInterruptReason|.
197 DownloadInterruptReason LogSystemError(const char* operation, 223 DownloadInterruptReason LogSystemError(const char* operation,
198 logging::SystemErrorCode os_error); 224 logging::SystemErrorCode os_error);
199 225
200 // Log a TYPE_DOWNLOAD_FILE_ERROR NetLog event with |os_error| and |reason|. 226 // Log a TYPE_DOWNLOAD_FILE_ERROR NetLog event with |os_error| and |reason|.
201 // Returns |reason|. 227 // Returns |reason|.
202 DownloadInterruptReason LogInterruptReason( 228 DownloadInterruptReason LogInterruptReason(
203 const char* operation, int os_error, 229 const char* operation, int os_error,
204 DownloadInterruptReason reason); 230 DownloadInterruptReason reason);
205 231
206 // Full path to the file including the file name. 232 // Full path to the file including the file name.
207 base::FilePath full_path_; 233 base::FilePath full_path_;
208 234
209 // OS file for writing 235 // OS file for writing
210 base::File file_; 236 base::File file_;
211 237
212 // Amount of data received up so far, in bytes. 238 // Current byte offset to write the data.
239 int64_t offset_ = 0;
240
241 // Amount of data received up so far, in bytes. This should be equal to
242 // |offset_| when |access_mode_| is EXCLUSIVE. If |access_mode_| is SHARED,
243 // this only tracks the bytes received by the current writer.
213 int64_t bytes_so_far_ = 0; 244 int64_t bytes_so_far_ = 0;
214 245
215 // Used to calculate hash for the file when calculate_hash_ is set. 246 // Used to calculate hash for the file when calculate_hash_ is set.
216 std::unique_ptr<crypto::SecureHash> secure_hash_; 247 std::unique_ptr<crypto::SecureHash> secure_hash_;
217 248
218 // Start time for calculating speed. 249 // Start time for calculating speed.
219 base::TimeTicks start_tick_; 250 base::TimeTicks start_tick_;
220 251
221 // Indicates that this class no longer owns the associated file, and so 252 // Indicates that this class no longer owns the associated file, and so
222 // won't delete it on destruction. 253 // won't delete it on destruction.
223 bool detached_ = false; 254 bool detached_ = false;
224 255
256 AccessMode access_mode_ = EXCLUSIVE;
257
225 net::NetLogWithSource net_log_; 258 net::NetLogWithSource net_log_;
226 259
227 DISALLOW_COPY_AND_ASSIGN(BaseFile); 260 DISALLOW_COPY_AND_ASSIGN(BaseFile);
228 }; 261 };
229 262
230 } // namespace content 263 } // namespace content
231 264
232 #endif // CONTENT_BROWSER_DOWNLOAD_BASE_FILE_H_ 265 #endif // CONTENT_BROWSER_DOWNLOAD_BASE_FILE_H_
OLDNEW
« no previous file with comments | « no previous file | content/browser/download/base_file.cc » ('j') | content/browser/download/base_file.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698