Index: storage/browser/blob/blob_reader.h |
diff --git a/storage/browser/blob/blob_reader.h b/storage/browser/blob/blob_reader.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..54b262f3ef3e910dfcf932c37a87d8b9e85ab8b7 |
--- /dev/null |
+++ b/storage/browser/blob/blob_reader.h |
@@ -0,0 +1,190 @@ |
+// 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 <stdint.h> |
+#include <map> |
+#include <vector> |
+ |
+#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<FileStreamReader> CreateForLocalFile( |
+ base::TaskRunner* task_runner, |
+ const base::FilePath& file_path, |
+ int64_t initial_offset, |
+ const base::Time& expected_modification_time) = 0; |
+ |
+ virtual scoped_ptr<FileStreamReader> 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<FileStreamReaderProvider> 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<FileStreamReader> reader); |
+ // Creates a FileStreamReader for the item with additional_offset. |
+ scoped_ptr<FileStreamReader> CreateFileStreamReader( |
+ const BlobDataItem& item, |
+ uint64_t additional_offset); |
+ |
+ scoped_ptr<BlobDataSnapshot> blob_data_; |
+ scoped_ptr<FileStreamReaderProvider> file_stream_provider_; |
+ scoped_refptr<base::SequencedTaskRunner> file_task_runner_; |
+ |
+ int net_error_; |
+ bool item_list_populated_ = false; |
+ std::vector<uint64_t> item_length_list_; |
+ |
+ scoped_refptr<net::DrainableIOBuffer> 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<size_t, FileStreamReader*> 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<BlobReader> weak_factory_; |
+ DISALLOW_COPY_AND_ASSIGN(BlobReader); |
+}; |
+ |
+} // namespace storage |
+#endif // STORAGE_BROWSER_BLOB_BLOB_READER_H_ |