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