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

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

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 #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,
asanka 2017/02/16 18:46:26 I'd argue that the distinction is that the file is
qinmin 2017/02/16 21:35:50 Done. Changed this to a boolean variable is_sparse
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 // |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 71 // 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 72 // the file. If |access_mode| is EXCLUSIVE, this value should be the size
66 // this size. However, if the file is shorter, then the operation will 73 // of the file to expect. It is legal for the file to be larger, in which
74 // case the file will be truncated down to this size if |access_mode| is
75 // EXCLUSIVE. However, if the file is shorter, then the operation will
67 // fail with DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT. 76 // fail with DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT.
77
68 // 78 //
69 // |hash_so_far|: If |bytes_so_far| is non-zero, this specifies the SHA-256 79 // |hash_so_far|: If |bytes_so_far| is non-zero and |access_mode| is
70 // hash of the first |bytes_so_far| bytes of the target file. If 80 // EXCLUSIVE, 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 81 // 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. 82 // |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 83 // 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| 84 // fails with DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH. Not used if
75 // is also specified. 85 // |hash_state| is also specified.
76 // 86 //
77 // |hash_state|: The partial hash object to use. Only meaningful if there's a 87 // |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 88 // 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 89 // 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 90 // |bytes_so_far| has been accurately hashed into |hash_state| and will
81 // ignore |hash_so_far|. 91 // ignore |hash_so_far|. Not used if |access_mode| is SHARED.
92 //
93 // |access_mode|: Specifies whether the file is going to be accessed by
94 // multiple writers. If so, it is possible that one writer can request
95 // writing to an offset that is larger than the file size.
82 DownloadInterruptReason Initialize( 96 DownloadInterruptReason Initialize(
83 const base::FilePath& full_path, 97 const base::FilePath& full_path,
84 const base::FilePath& default_directory, 98 const base::FilePath& default_directory,
85 base::File file, 99 base::File file,
86 int64_t bytes_so_far, 100 int64_t bytes_so_far,
87 const std::string& hash_so_far, 101 const std::string& hash_so_far,
88 std::unique_ptr<crypto::SecureHash> hash_state); 102 std::unique_ptr<crypto::SecureHash> hash_state,
103 AccessMode access_mode);
104
105 // Write a new chunk of data to the file. Returns a DownloadInterruptReason
106 // indicating the result of the operation. Works only if |access_mode| is
107 // EXCLUSIVE.
108 DownloadInterruptReason AppendDataToFile(const char* data, size_t data_len);
89 109
90 // Write a new chunk of data to the file. Returns a DownloadInterruptReason 110 // Write a new chunk of data to the file. Returns a DownloadInterruptReason
91 // indicating the result of the operation. 111 // indicating the result of the operation.
92 DownloadInterruptReason AppendDataToFile(const char* data, size_t data_len); 112 DownloadInterruptReason WriteDataToFile(
113 int64_t offset,
114 const char* data,
115 size_t data_len);
93 116
94 // Rename the download file. Returns a DownloadInterruptReason indicating the 117 // Rename the download file. Returns a DownloadInterruptReason indicating the
95 // result of the operation. A return code of NONE indicates that the rename 118 // 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 119 // 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 120 // 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 121 // for writing or retrying the rename. Call Finish() to obtain the last known
99 // hash state. 122 // hash state.
100 DownloadInterruptReason Rename(const base::FilePath& full_path); 123 DownloadInterruptReason Rename(const base::FilePath& full_path);
101 124
102 // Mark the file as detached. Up until this method is called, BaseFile assumes 125 // Mark the file as detached. Up until this method is called, BaseFile assumes
(...skipping 27 matching lines...) Expand all
130 const GURL& referrer_url); 153 const GURL& referrer_url);
131 154
132 // Returns the last known path to the download file. Can be empty if there's 155 // Returns the last known path to the download file. Can be empty if there's
133 // no file. 156 // no file.
134 const base::FilePath& full_path() const { return full_path_; } 157 const base::FilePath& full_path() const { return full_path_; }
135 158
136 // Returns true if the file is open. If true, the file can be written to or 159 // Returns true if the file is open. If true, the file can be written to or
137 // renamed. 160 // renamed.
138 bool in_progress() const { return file_.IsValid(); } 161 bool in_progress() const { return file_.IsValid(); }
139 162
140 // Returns the number of bytes in the file pointed to by full_path(). 163 // Returns the number of bytes that has been written so far. If |access_mode_|
164 // is EXCLUSIVE, this should always be equal to the file size. If
165 // |access_mode_| is SHARED, this should not be larger than the file size
166 // as the file may contain holes in it.
141 int64_t bytes_so_far() const { return bytes_so_far_; } 167 int64_t bytes_so_far() const { return bytes_so_far_; }
142 168
143 std::string DebugString() const; 169 std::string DebugString() const;
144 170
145 private: 171 private:
146 friend class BaseFileTest; 172 friend class BaseFileTest;
147 FRIEND_TEST_ALL_PREFIXES(BaseFileTest, IsEmptyHash); 173 FRIEND_TEST_ALL_PREFIXES(BaseFileTest, IsEmptyHash);
148 174
149 // Creates and opens the file_ if it is invalid. 175 // Creates and opens the file_ if it is invalid.
150 // 176 //
151 // If |hash_so_far| is not empty, then it must match the SHA-256 hash of the 177 // 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() 178 // match the SHA-256 hash of the first |bytes_so_far_| bytes of |file_|. If
153 // fails with DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH. 179 // there's a hash mismatch, Open() fails with
180 // DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH.
154 // 181 //
155 // If the opened file is shorter than |bytes_so_far_| bytes, then Open() fails 182 // 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 183 // with DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT. If the opened file is longer
157 // longer, then the file is truncated to |bytes_so_far_|. 184 // and |access_mode_| is EXCLUSIVE, then the file is truncated to
185 // |bytes_so_far_|.
158 // 186 //
159 // Open() can fail for other reasons as well. In that case, it returns a 187 // Open() can fail for other reasons as well. In that case, it returns a
160 // relevant interrupt reason. Unless Open() return 188 // relevant interrupt reason. Unless Open() return
161 // DOWNLOAD_INTERRUPT_REASON_NONE, it should be assumed that |file_| is not 189 // DOWNLOAD_INTERRUPT_REASON_NONE, it should be assumed that |file_| is not
162 // valid. 190 // valid.
163 DownloadInterruptReason Open(const std::string& hash_so_far); 191 DownloadInterruptReason Open(const std::string& hash_so_far);
164 192
165 // Closes and resets file_. 193 // Closes and resets file_.
166 void Close(); 194 void Close();
167 195
168 // Resets file_. 196 // Resets file_.
169 void ClearFile(); 197 void ClearFile();
170 198
199 // Writes data at the current position.
200 DownloadInterruptReason WriteAtCurrentPos(const char* data, size_t data_len);
201
171 // Platform specific method that moves a file to a new path and adjusts the 202 // 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 203 // security descriptor / permissions on the file to match the defaults for the
173 // new directory. 204 // new directory.
174 DownloadInterruptReason MoveFileAndAdjustPermissions( 205 DownloadInterruptReason MoveFileAndAdjustPermissions(
175 const base::FilePath& new_path); 206 const base::FilePath& new_path);
176 207
177 // Split out from CurrentSpeed to enable testing. 208 // Split out from CurrentSpeed to enable testing.
178 int64_t CurrentSpeedAtTime(base::TimeTicks current_time) const; 209 int64_t CurrentSpeedAtTime(base::TimeTicks current_time) const;
179 210
180 // Verifies that: 211 // This function is only useful when |access_mode_| is EXCLUSIVE. It verifies
asanka 2017/02/16 18:46:26 Once the download is complete, we'd still need use
qinmin 2017/02/16 21:35:50 Added the code to calculate the hash when finish()
212 // that:
181 // * Size of the file represented by |file_| is at least |bytes_so_far_|. 213 // * Size of the file represented by |file_| is at least |bytes_so_far_|.
182 // 214 //
183 // * If |hash_to_expect| is not empty, then the result of hashing the first 215 // * 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|. 216 // |bytes_so_far_| bytes of |file_| matches |hash_to_expect|.
185 // 217 //
186 // If the result is REASON_NONE, then on return |secure_hash_| is valid and 218 // 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. 219 // is ready to hash bytes from offset |bytes_so_far_| + 1.
188 DownloadInterruptReason CalculatePartialHash( 220 DownloadInterruptReason CalculatePartialHash(
189 const std::string& hash_to_expect); 221 const std::string& hash_to_expect);
190 222
(...skipping 24 matching lines...) Expand all
215 // Used to calculate hash for the file when calculate_hash_ is set. 247 // Used to calculate hash for the file when calculate_hash_ is set.
216 std::unique_ptr<crypto::SecureHash> secure_hash_; 248 std::unique_ptr<crypto::SecureHash> secure_hash_;
217 249
218 // Start time for calculating speed. 250 // Start time for calculating speed.
219 base::TimeTicks start_tick_; 251 base::TimeTicks start_tick_;
220 252
221 // Indicates that this class no longer owns the associated file, and so 253 // Indicates that this class no longer owns the associated file, and so
222 // won't delete it on destruction. 254 // won't delete it on destruction.
223 bool detached_ = false; 255 bool detached_ = false;
224 256
257 AccessMode access_mode_ = EXCLUSIVE;
258
225 net::NetLogWithSource net_log_; 259 net::NetLogWithSource net_log_;
226 260
227 DISALLOW_COPY_AND_ASSIGN(BaseFile); 261 DISALLOW_COPY_AND_ASSIGN(BaseFile);
228 }; 262 };
229 263
230 } // namespace content 264 } // namespace content
231 265
232 #endif // CONTENT_BROWSER_DOWNLOAD_BASE_FILE_H_ 266 #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