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

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

Issue 2695153002: Refactor BaseFile class to support sparse files (Closed)
Patch Set: remove the while loop around write 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
« no previous file with comments | « no previous file | content/browser/download/base_file.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 // location as determined by ContentBrowserClient. 54 // location as determined by ContentBrowserClient.
55 // 55 //
56 // |file|: The base::File handle to use. If specified, BaseFile will not open 56 // |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 57 // 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 58 // 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 59 // 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 60 // perfect way to come up with a canonical path for a file. So BaseFile
61 // will not attempt to determine the |full_path|. 61 // will not attempt to determine the |full_path|.
62 // 62 //
63 // |bytes_so_far|: If a file is provided (via |full_path| or |file|), then 63 // |bytes_so_far|: If a file is provided (via |full_path| or |file|), then
64 // this argument specifies the size of the file to expect. It is legal for 64 // this argument specifies the amount of data that has been written to
65 // the file to be larger, in which case the file will be truncated down to 65 // the file. If |is_sparse_file| is false, this value should be the size
66 // this size. However, if the file is shorter, then the operation will 66 // of the file to expect. It is legal for the file to be larger, in which
67 // case the file will be truncated down to this size if |is_sparse_file|
68 // is false. However, if the file is shorter, then the operation will
67 // fail with DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT. 69 // fail with DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT.
70
68 // 71 //
69 // |hash_so_far|: If |bytes_so_far| is non-zero, this specifies the SHA-256 72 // |hash_so_far|: If |bytes_so_far| is non-zero and |is_sparse_file| is
70 // hash of the first |bytes_so_far| bytes of the target file. If 73 // false, this specifies the SHA-256 hash of the first |bytes_so_far|
71 // specified, BaseFile will read the first |bytes_so_far| of the target 74 // bytes of the target file. If specified, BaseFile will read the first
72 // file in order to calculate the hash and verify that the file matches. 75 // |bytes_so_far| of the target file in order to calculate the hash and
73 // If there's a mismatch, then the operation fails with 76 // verify that the file matches. If there's a mismatch, then the operation
74 // DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH. Not used if |hash_state| 77 // fails with DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH. Not used if
75 // is also specified. 78 // |hash_state| is also specified.
76 // 79 //
77 // |hash_state|: The partial hash object to use. Only meaningful if there's a 80 // |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 81 // preexisting target file and it is non-empty (i.e. bytes_so_far is
79 // non-zero). If specified, BaseFile will assume that the bytes up to 82 // 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 83 // |bytes_so_far| has been accurately hashed into |hash_state| and will
81 // ignore |hash_so_far|. 84 // ignore |hash_so_far|. Not used if |is_sparse_file| is true.
85 //
86 // |is_sparse_file|: Specifies whether the file is a sparse file. If so, it is
87 // possible that a write can happen at an offset that is larger than the
88 // file size, thus creating holes in it.
82 DownloadInterruptReason Initialize( 89 DownloadInterruptReason Initialize(
83 const base::FilePath& full_path, 90 const base::FilePath& full_path,
84 const base::FilePath& default_directory, 91 const base::FilePath& default_directory,
85 base::File file, 92 base::File file,
86 int64_t bytes_so_far, 93 int64_t bytes_so_far,
87 const std::string& hash_so_far, 94 const std::string& hash_so_far,
88 std::unique_ptr<crypto::SecureHash> hash_state); 95 std::unique_ptr<crypto::SecureHash> hash_state,
96 bool is_sparse_file);
97
98 // Write a new chunk of data to the file. Returns a DownloadInterruptReason
99 // indicating the result of the operation. Works only if |is_sparse_file| is
100 // false.
101 DownloadInterruptReason AppendDataToFile(const char* data, size_t data_len);
89 102
90 // Write a new chunk of data to the file. Returns a DownloadInterruptReason 103 // Write a new chunk of data to the file. Returns a DownloadInterruptReason
91 // indicating the result of the operation. 104 // indicating the result of the operation.
92 DownloadInterruptReason AppendDataToFile(const char* data, size_t data_len); 105 DownloadInterruptReason WriteDataToFile(
106 int64_t offset,
107 const char* data,
108 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
103 // ownership of the file and hence will delete the file if the BaseFile object 119 // ownership of the file and hence will delete the file if the BaseFile object
104 // is destroyed. Calling Detach() causes BaseFile to assume that it no longer 120 // is destroyed. Calling Detach() causes BaseFile to assume that it no longer
105 // owns the file. Detach() can be called at any time. Close() must still be 121 // owns the file. Detach() can be called at any time. Close() must still be
106 // called to close the file if it is open. 122 // called to close the file if it is open.
107 void Detach(); 123 void Detach();
108 124
109 // Abort the download and automatically close and delete the file. 125 // Abort the download and automatically close and delete the file.
110 void Cancel(); 126 void Cancel();
111 127
112 // Indicate that the download has finished. No new data will be received. 128 // Indicate that the download has finished. No new data will be received.
113 // Returns the SecureHash object representing the state of the hash function 129 // Returns the SecureHash object representing the state of the hash function
114 // at the end of the operation. 130 // at the end of the operation. If |is_sparse_file_| is true, calling this
131 // will cause |secure_hash_| to get calculated.
115 std::unique_ptr<crypto::SecureHash> Finish(); 132 std::unique_ptr<crypto::SecureHash> Finish();
116 133
117 // Informs the OS that this file came from the internet. Returns a 134 // Informs the OS that this file came from the internet. Returns a
118 // DownloadInterruptReason indicating the result of the operation. 135 // DownloadInterruptReason indicating the result of the operation.
119 // 136 //
120 // |client_guid|: The client GUID which will be used to identify the caller to 137 // |client_guid|: The client GUID which will be used to identify the caller to
121 // the system AV scanning function. 138 // the system AV scanning function.
122 // 139 //
123 // |source_url| / |referrer_url|: Source and referrer for the network request 140 // |source_url| / |referrer_url|: Source and referrer for the network request
124 // that originated this download. Will be used to annotate source 141 // that originated this download. Will be used to annotate source
125 // information and also to determine the relative danger level of the 142 // information and also to determine the relative danger level of the
126 // file. 143 // file.
127 DownloadInterruptReason AnnotateWithSourceInformation( 144 DownloadInterruptReason AnnotateWithSourceInformation(
128 const std::string& client_guid, 145 const std::string& client_guid,
129 const GURL& source_url, 146 const GURL& source_url,
130 const GURL& referrer_url); 147 const GURL& referrer_url);
131 148
132 // Returns the last known path to the download file. Can be empty if there's 149 // Returns the last known path to the download file. Can be empty if there's
133 // no file. 150 // no file.
134 const base::FilePath& full_path() const { return full_path_; } 151 const base::FilePath& full_path() const { return full_path_; }
135 152
136 // Returns true if the file is open. If true, the file can be written to or 153 // Returns true if the file is open. If true, the file can be written to or
137 // renamed. 154 // renamed.
138 bool in_progress() const { return file_.IsValid(); } 155 bool in_progress() const { return file_.IsValid(); }
139 156
140 // Returns the number of bytes in the file pointed to by full_path(). 157 // Returns the number of bytes that has been written so far. If
158 // |is_sparse_file_| is false, this should always be equal to the file size.
159 // If |is_sparse_file_| is true, this should not be larger than the file size
160 // as the file may contain holes in it.
141 int64_t bytes_so_far() const { return bytes_so_far_; } 161 int64_t bytes_so_far() const { return bytes_so_far_; }
142 162
143 std::string DebugString() const; 163 std::string DebugString() const;
144 164
145 private: 165 private:
146 friend class BaseFileTest; 166 friend class BaseFileTest;
147 FRIEND_TEST_ALL_PREFIXES(BaseFileTest, IsEmptyHash); 167 FRIEND_TEST_ALL_PREFIXES(BaseFileTest, IsEmptyHash);
148 168
149 // Creates and opens the file_ if it is invalid. 169 // Creates and opens the file_ if it is invalid.
150 // 170 //
151 // If |hash_so_far| is not empty, then it must match the SHA-256 hash of the 171 // If |is_sparse_file_| is false 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() 172 // match the SHA-256 hash of the first |bytes_so_far_| bytes of |file_|. If
153 // fails with DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH. 173 // there's a hash mismatch, Open() fails with
174 // DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH.
154 // 175 //
155 // If the opened file is shorter than |bytes_so_far_| bytes, then Open() fails 176 // If the opened file is shorter than |bytes_so_far_| bytes, then Open() fails
156 // with DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT. If the opened file is 177 // with DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT. If the opened file is longer
157 // longer, then the file is truncated to |bytes_so_far_|. 178 // and |is_sparse_file_| is false, then the file is truncated to
179 // |bytes_so_far_|.
158 // 180 //
159 // Open() can fail for other reasons as well. In that case, it returns a 181 // Open() can fail for other reasons as well. In that case, it returns a
160 // relevant interrupt reason. Unless Open() return 182 // relevant interrupt reason. Unless Open() return
161 // DOWNLOAD_INTERRUPT_REASON_NONE, it should be assumed that |file_| is not 183 // DOWNLOAD_INTERRUPT_REASON_NONE, it should be assumed that |file_| is not
162 // valid. 184 // valid.
163 DownloadInterruptReason Open(const std::string& hash_so_far); 185 DownloadInterruptReason Open(const std::string& hash_so_far);
164 186
165 // Closes and resets file_. 187 // Closes and resets file_.
166 void Close(); 188 void Close();
167 189
(...skipping 10 matching lines...) Expand all
178 int64_t CurrentSpeedAtTime(base::TimeTicks current_time) const; 200 int64_t CurrentSpeedAtTime(base::TimeTicks current_time) const;
179 201
180 // Verifies that: 202 // Verifies that:
181 // * Size of the file represented by |file_| is at least |bytes_so_far_|. 203 // * Size of the file represented by |file_| is at least |bytes_so_far_|.
182 // 204 //
183 // * If |hash_to_expect| is not empty, then the result of hashing the first 205 // * 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|. 206 // |bytes_so_far_| bytes of |file_| matches |hash_to_expect|.
185 // 207 //
186 // If the result is REASON_NONE, then on return |secure_hash_| is valid and 208 // 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. 209 // is ready to hash bytes from offset |bytes_so_far_| + 1.
210 // If |is_sparse_file_| is true, this function is only called when Finish()
211 // is called.
188 DownloadInterruptReason CalculatePartialHash( 212 DownloadInterruptReason CalculatePartialHash(
189 const std::string& hash_to_expect); 213 const std::string& hash_to_expect);
190 214
191 // Log a TYPE_DOWNLOAD_FILE_ERROR NetLog event with |error| and passes error 215 // Log a TYPE_DOWNLOAD_FILE_ERROR NetLog event with |error| and passes error
192 // on through, converting to a |DownloadInterruptReason|. 216 // on through, converting to a |DownloadInterruptReason|.
193 DownloadInterruptReason LogNetError(const char* operation, net::Error error); 217 DownloadInterruptReason LogNetError(const char* operation, net::Error error);
194 218
195 // Log the system error in |os_error| and converts it into a 219 // Log the system error in |os_error| and converts it into a
196 // |DownloadInterruptReason|. 220 // |DownloadInterruptReason|.
197 DownloadInterruptReason LogSystemError(const char* operation, 221 DownloadInterruptReason LogSystemError(const char* operation,
(...skipping 17 matching lines...) Expand all
215 // Used to calculate hash for the file when calculate_hash_ is set. 239 // Used to calculate hash for the file when calculate_hash_ is set.
216 std::unique_ptr<crypto::SecureHash> secure_hash_; 240 std::unique_ptr<crypto::SecureHash> secure_hash_;
217 241
218 // Start time for calculating speed. 242 // Start time for calculating speed.
219 base::TimeTicks start_tick_; 243 base::TimeTicks start_tick_;
220 244
221 // Indicates that this class no longer owns the associated file, and so 245 // Indicates that this class no longer owns the associated file, and so
222 // won't delete it on destruction. 246 // won't delete it on destruction.
223 bool detached_ = false; 247 bool detached_ = false;
224 248
249 // Whether the file is sparse.
250 // TODO(qinmin): pass the slice information to this class so that we can
251 // verify that writes are not overlapping.
252 bool is_sparse_file_ = false;
253
225 net::NetLogWithSource net_log_; 254 net::NetLogWithSource net_log_;
226 255
227 DISALLOW_COPY_AND_ASSIGN(BaseFile); 256 DISALLOW_COPY_AND_ASSIGN(BaseFile);
228 }; 257 };
229 258
230 } // namespace content 259 } // namespace content
231 260
232 #endif // CONTENT_BROWSER_DOWNLOAD_BASE_FILE_H_ 261 #endif // CONTENT_BROWSER_DOWNLOAD_BASE_FILE_H_
OLDNEW
« no previous file with comments | « no previous file | content/browser/download/base_file.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698