Chromium Code Reviews| Index: content/browser/download/base_file.h |
| diff --git a/content/browser/download/base_file.h b/content/browser/download/base_file.h |
| index 8351c49be340654f99fce3e0f41477ecb77f65a6..39470a36043c46f70d1b2bd4b6387f427c38c66f 100644 |
| --- a/content/browser/download/base_file.h |
| +++ b/content/browser/download/base_file.h |
| @@ -33,6 +33,13 @@ namespace content { |
| // Detach(). |
| class CONTENT_EXPORT BaseFile { |
| public: |
| + // Enum to indicate whether the file is exclusived owned, or shared among |
| + // multiple writers. |
| + enum AccessMode { |
| + EXCLUSIVE = 0, |
| + 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
|
| + }; |
| + |
| // May be constructed on any thread. All other routines (including |
| // destruction) must occur on the FILE thread. |
| BaseFile(const net::NetLogWithSource& net_log); |
| @@ -61,36 +68,52 @@ class CONTENT_EXPORT BaseFile { |
| // will not attempt to determine the |full_path|. |
| // |
| // |bytes_so_far|: If a file is provided (via |full_path| or |file|), then |
| - // this argument specifies the size of the file to expect. It is legal for |
| - // the file to be larger, in which case the file will be truncated down to |
| - // this size. However, if the file is shorter, then the operation will |
| + // this argument specifies the amount of data that has been written to |
| + // the file. If |access_mode| is EXCLUSIVE, this value should be the size |
| + // of the file to expect. It is legal for the file to be larger, in which |
| + // case the file will be truncated down to this size if |access_mode| is |
| + // EXCLUSIVE. However, if the file is shorter, then the operation will |
| // fail with DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT. |
| + |
| // |
| - // |hash_so_far|: If |bytes_so_far| is non-zero, this specifies the SHA-256 |
| - // hash of the first |bytes_so_far| bytes of the target file. If |
| - // specified, BaseFile will read the first |bytes_so_far| of the target |
| - // file in order to calculate the hash and verify that the file matches. |
| - // If there's a mismatch, then the operation fails with |
| - // DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH. Not used if |hash_state| |
| - // is also specified. |
| + // |hash_so_far|: If |bytes_so_far| is non-zero and |access_mode| is |
| + // EXCLUSIVE, this specifies the SHA-256 hash of the first |bytes_so_far| |
| + // bytes of the target file. If specified, BaseFile will read the first |
| + // |bytes_so_far| of the target file in order to calculate the hash and |
| + // verify that the file matches. If there's a mismatch, then the operation |
| + // fails with DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH. Not used if |
| + // |hash_state| is also specified. |
| // |
| // |hash_state|: The partial hash object to use. Only meaningful if there's a |
| // preexisting target file and it is non-empty (i.e. bytes_so_far is |
| // non-zero). If specified, BaseFile will assume that the bytes up to |
| // |bytes_so_far| has been accurately hashed into |hash_state| and will |
| - // ignore |hash_so_far|. |
| + // ignore |hash_so_far|. Not used if |access_mode| is SHARED. |
| + // |
| + // |access_mode|: Specifies whether the file is going to be accessed by |
| + // multiple writers. If so, it is possible that one writer can request |
| + // writing to an offset that is larger than the file size. |
| DownloadInterruptReason Initialize( |
| const base::FilePath& full_path, |
| const base::FilePath& default_directory, |
| base::File file, |
| int64_t bytes_so_far, |
| const std::string& hash_so_far, |
| - std::unique_ptr<crypto::SecureHash> hash_state); |
| + std::unique_ptr<crypto::SecureHash> hash_state, |
| + AccessMode access_mode); |
| // Write a new chunk of data to the file. Returns a DownloadInterruptReason |
| - // indicating the result of the operation. |
| + // indicating the result of the operation. Works only if |access_mode| is |
| + // EXCLUSIVE. |
| DownloadInterruptReason AppendDataToFile(const char* data, size_t data_len); |
| + // Write a new chunk of data to the file. Returns a DownloadInterruptReason |
| + // indicating the result of the operation. |
| + DownloadInterruptReason WriteDataToFile( |
| + int64_t offset, |
| + const char* data, |
| + size_t data_len); |
| + |
| // Rename the download file. Returns a DownloadInterruptReason indicating the |
| // result of the operation. A return code of NONE indicates that the rename |
| // was successful. After a failure, the full_path() and in_progress() can be |
| @@ -137,7 +160,10 @@ class CONTENT_EXPORT BaseFile { |
| // renamed. |
| bool in_progress() const { return file_.IsValid(); } |
| - // Returns the number of bytes in the file pointed to by full_path(). |
| + // Returns the number of bytes that has been written so far. If |access_mode_| |
| + // is EXCLUSIVE, this should always be equal to the file size. If |
| + // |access_mode_| is SHARED, this should not be larger than the file size |
| + // as the file may contain holes in it. |
| int64_t bytes_so_far() const { return bytes_so_far_; } |
| std::string DebugString() const; |
| @@ -148,13 +174,15 @@ class CONTENT_EXPORT BaseFile { |
| // Creates and opens the file_ if it is invalid. |
| // |
| - // If |hash_so_far| is not empty, then it must match the SHA-256 hash of the |
| - // first |bytes_so_far_| bytes of |file_|. If there's a hash mismatch, Open() |
| - // fails with DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH. |
| + // If |access_mode_| is EXCLUSIVE and |hash_so_far| is not empty, then it must |
| + // match the SHA-256 hash of the first |bytes_so_far_| bytes of |file_|. If |
| + // there's a hash mismatch, Open() fails with |
| + // DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH. |
| // |
| // If the opened file is shorter than |bytes_so_far_| bytes, then Open() fails |
| - // with DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT. If the opened file is |
| - // longer, then the file is truncated to |bytes_so_far_|. |
| + // with DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT. If the opened file is longer |
| + // and |access_mode_| is EXCLUSIVE, then the file is truncated to |
| + // |bytes_so_far_|. |
| // |
| // Open() can fail for other reasons as well. In that case, it returns a |
| // relevant interrupt reason. Unless Open() return |
| @@ -168,6 +196,9 @@ class CONTENT_EXPORT BaseFile { |
| // Resets file_. |
| void ClearFile(); |
| + // Writes data at the current position. |
| + DownloadInterruptReason WriteAtCurrentPos(const char* data, size_t data_len); |
| + |
| // Platform specific method that moves a file to a new path and adjusts the |
| // security descriptor / permissions on the file to match the defaults for the |
| // new directory. |
| @@ -177,7 +208,8 @@ class CONTENT_EXPORT BaseFile { |
| // Split out from CurrentSpeed to enable testing. |
| int64_t CurrentSpeedAtTime(base::TimeTicks current_time) const; |
| - // Verifies that: |
| + // 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()
|
| + // that: |
| // * Size of the file represented by |file_| is at least |bytes_so_far_|. |
| // |
| // * If |hash_to_expect| is not empty, then the result of hashing the first |
| @@ -222,6 +254,8 @@ class CONTENT_EXPORT BaseFile { |
| // won't delete it on destruction. |
| bool detached_ = false; |
| + AccessMode access_mode_ = EXCLUSIVE; |
| + |
| net::NetLogWithSource net_log_; |
| DISALLOW_COPY_AND_ASSIGN(BaseFile); |