| 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..e1714c6ca397ef8513096d9ed9efe85828603fcf 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,
|
| + };
|
| +
|
| // May be constructed on any thread. All other routines (including
|
| // destruction) must occur on the FILE thread.
|
| BaseFile(const net::NetLogWithSource& net_log);
|
| @@ -60,36 +67,45 @@ class CONTENT_EXPORT BaseFile {
|
| // perfect way to come up with a canonical path for a file. So 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
|
| - // fail with DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT.
|
| + // |offset|: If a file is provided (via |full_path| or |file|), then this
|
| + // argument specifies the starting position to write 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. However, if the file is
|
| + // shorter, then the operation will fail with
|
| + // DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT. If |access_mode_| is SHARED,
|
| + // file size check is ignored as the writer is expecting other writers to
|
| + // fill the gaps or append more data.
|
| //
|
| - // |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
|
| + // |hash_so_far|: If |offset| is non-zero, this specifies the SHA-256
|
| + // hash of the first |offset| bytes of the target file. If
|
| + // specified, BaseFile will read the first |offset| 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.
|
| + // is also specified or |access_mode| is equal to SHARED.
|
| //
|
| // |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
|
| + // preexisting target file and it is non-empty (i.e. offset 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|.
|
| + // |offset| has been accurately hashed into |hash_state| and will
|
| + // ignore |hash_so_far|. Not used if |access_mode| is equal to 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 a |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,
|
| + int64_t offset,
|
| 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.
|
| - DownloadInterruptReason AppendDataToFile(const char* data, size_t data_len);
|
| + // Write a new chunk of data to the current |offset_| inside the file. Returns
|
| + // a DownloadInterruptReason indicating the result of the operation.
|
| + DownloadInterruptReason WriteDataToFile(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
|
| @@ -137,9 +153,16 @@ 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 only records the byte that is written by
|
| + // the current writer. So it is smaller than the file size as there are other
|
| + // writers around.
|
| int64_t bytes_so_far() const { return bytes_so_far_; }
|
|
|
| + // Returns the current offset that data will be written to.
|
| + int64_t offset() const { return offset_; }
|
| +
|
| std::string DebugString() const;
|
|
|
| private:
|
| @@ -148,13 +171,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 |offset_| 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_|.
|
| + // When |access_mode_| is EXCLUSIVE, If the opened file is shorter than
|
| + // |offset_| bytes, then Open() fails with
|
| + // DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT. If the opened file is
|
| + // longer, then the file is truncated to |offset_|.
|
| //
|
| // Open() can fail for other reasons as well. In that case, it returns a
|
| // relevant interrupt reason. Unless Open() return
|
| @@ -177,14 +202,15 @@ class CONTENT_EXPORT BaseFile {
|
| // Split out from CurrentSpeed to enable testing.
|
| int64_t CurrentSpeedAtTime(base::TimeTicks current_time) const;
|
|
|
| - // Verifies that:
|
| - // * Size of the file represented by |file_| is at least |bytes_so_far_|.
|
| + // This function is only used when |access_mode_| is EXCLUSIVE. It verifies
|
| + // that:
|
| + // * Size of the file represented by |file_| is at least |offset_|.
|
| //
|
| // * If |hash_to_expect| is not empty, then the result of hashing the first
|
| - // |bytes_so_far_| bytes of |file_| matches |hash_to_expect|.
|
| + // |offset_| bytes of |file_| matches |hash_to_expect|.
|
| //
|
| // If the result is REASON_NONE, then on return |secure_hash_| is valid and
|
| - // is ready to hash bytes from offset |bytes_so_far_| + 1.
|
| + // is ready to hash bytes from offset |offset_| + 1.
|
| DownloadInterruptReason CalculatePartialHash(
|
| const std::string& hash_to_expect);
|
|
|
| @@ -209,7 +235,12 @@ class CONTENT_EXPORT BaseFile {
|
| // OS file for writing
|
| base::File file_;
|
|
|
| - // Amount of data received up so far, in bytes.
|
| + // Current byte offset to write the data.
|
| + int64_t offset_ = 0;
|
| +
|
| + // Amount of data received up so far, in bytes. This should be equal to
|
| + // |offset_| when |access_mode_| is EXCLUSIVE. If |access_mode_| is SHARED,
|
| + // this only tracks the bytes received by the current writer.
|
| int64_t bytes_so_far_ = 0;
|
|
|
| // Used to calculate hash for the file when calculate_hash_ is set.
|
| @@ -222,6 +253,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);
|
|
|