Chromium Code Reviews| 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 |