// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef STORAGE_BROWSER_BLOB_BLOB_READER_H_ #define STORAGE_BROWSER_BLOB_BLOB_READER_H_ #include #include #include #include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "net/base/completion_callback.h" #include "storage/browser/storage_browser_export.h" class GURL; namespace base { class FilePath; class SequencedTaskRunner; class TaskRunner; class Time; } namespace net { class DrainableIOBuffer; class IOBuffer; } namespace storage { class BlobDataItem; class BlobDataHandle; class BlobDataSnapshot; class FileStreamReader; class FileSystemContext; // The blob reader is used to read a blob. This can only be used in the browser // process, and we need to be on the IO thread. // * There can only be one read happening at a time per reader. // * If a status of Status::NET_ERROR is returned, that means there was an // error and the net_error() variable contains the error code. // Use a BlobDataHandle to create an instance. class STORAGE_EXPORT BlobReader { public: class STORAGE_EXPORT FileStreamReaderProvider { public: virtual ~FileStreamReaderProvider(); virtual scoped_ptr CreateForLocalFile( base::TaskRunner* task_runner, const base::FilePath& file_path, int64_t initial_offset, const base::Time& expected_modification_time) = 0; virtual scoped_ptr CreateFileStreamReader( const GURL& filesystem_url, int64_t offset, int64_t max_bytes_to_read, const base::Time& expected_modification_time) = 0; }; enum class Status { NET_ERROR, IO_PENDING, DONE }; virtual ~BlobReader(); // This calculates the total size of the blob, and initializes the reading // cursor. // * This should only be called once per reader. // * Status::Done means that the total_size() value is populated and you can // continue to SetReadRange or Read. // * The 'done' callback is only called if Status::IO_PENDING is returned. // The callback value contains the error code or net::OK. Please use the // total_size() value to query the blob size, as it's uint64_t. Status CalculateSize(const net::CompletionCallback& done); // Used to set the read position. // * This should be called after CalculateSize and before Read. // * Range can only be set once. Status SetReadRange(uint64_t position, uint64_t length); // Reads a portion of the data. // * CalculateSize (and optionally SetReadRange) must be called beforehand. // * bytes_read is populated only if Status::DONE is returned. Otherwise the // bytes read (or error code) is populated in the 'done' callback. // * The done callback is only called if Status::IO_PENDING is returned. // * This method can be called multiple times. A bytes_read value (either from // the callback for Status::IO_PENDING or the bytes_read value for // Status::DONE) of 0 means we're finished reading. Status Read(net::IOBuffer* buffer, size_t dest_size, int* bytes_read, net::CompletionCallback done); // Kills reading and invalidates all callbacks. The reader cannot be used // after this call. void Kill(); // Returns if all of the blob's items are in memory. bool IsInMemory() const; // Returns the remaining bytes to be read in the blob. This is populated // after CalculateSize, and is modified by SetReadRange. uint64_t remaining_bytes() const { return remaining_bytes_; } // Returns the net error code if there was an error. Defaults to net::OK. int net_error() const { return net_error_; } // Returns the total size of the blob. This is populated after CalculateSize // is called. uint64_t total_size() const { return total_size_; } protected: friend class BlobDataHandle; friend class BlobReaderTest; BlobReader(const BlobDataHandle* blob_handle, scoped_ptr file_stream_provider, base::SequencedTaskRunner* file_task_runner); bool total_size_calculated() const { return total_size_calculated_; } private: Status ReportError(int net_error); void InvalidateCallbacksAndDone(int net_error, net::CompletionCallback done); bool AddItemLength(size_t index, uint64_t length); bool ResolveFileItemLength(const BlobDataItem& item, int64_t total_length, uint64_t* output_length); void DidGetFileItemLength(size_t index, int64_t result); void DidCountSize(); // For reading the blob. // Returns if we're done, PENDING_IO if we're waiting on async. Status ReadLoop(int* bytes_read); // Called from asynchronously called methods to continue the read loop. void ContinueAsyncReadLoop(); // PENDING_IO means we're waiting on async. Status ReadItem(); void AdvanceItem(); void AdvanceBytesRead(int result); void ReadBytesItem(const BlobDataItem& item, int bytes_to_read); BlobReader::Status ReadFileItem(FileStreamReader* reader, int bytes_to_read); void DidReadFile(int result); void DeleteCurrentFileReader(); Status ReadDiskCacheEntryItem(const BlobDataItem& item, int bytes_to_read); void DidReadDiskCacheEntry(int result); void DidReadItem(int result); int ComputeBytesToRead() const; int BytesReadCompleted(); // Returns a FileStreamReader for a blob item at |index|. // If the item at |index| is not of file this returns NULL. FileStreamReader* GetOrCreateFileReaderAtIndex(size_t index); // If the reader is null, then this basically performs a delete operation. void SetFileReaderAtIndex(size_t index, scoped_ptr reader); // Creates a FileStreamReader for the item with additional_offset. scoped_ptr CreateFileStreamReader( const BlobDataItem& item, uint64_t additional_offset); scoped_ptr blob_data_; scoped_ptr file_stream_provider_; scoped_refptr file_task_runner_; int net_error_; bool item_list_populated_ = false; std::vector item_length_list_; scoped_refptr read_buf_; bool total_size_calculated_ = false; uint64_t total_size_ = 0; uint64_t remaining_bytes_ = 0; size_t pending_get_file_info_count_ = 0; std::map index_to_reader_; size_t current_item_index_ = 0; uint64_t current_item_offset_ = 0; bool io_pending_ = false; net::CompletionCallback size_callback_; net::CompletionCallback read_callback_; base::WeakPtrFactory weak_factory_; DISALLOW_COPY_AND_ASSIGN(BlobReader); }; } // namespace storage #endif // STORAGE_BROWSER_BLOB_BLOB_READER_H_