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 3 // found in the LICENSE file. 4 5 #ifndef NET_BASE_UPLOAD_DATA_STREAM_H_ 6 #define NET_BASE_UPLOAD_DATA_STREAM_H_ 7 8 #include "base/gtest_prod_util.h" 9 #include "base/memory/ref_counted.h" 10 #include "base/memory/scoped_vector.h" 11 #include "base/memory/weak_ptr.h" 12 #include "net/base/completion_callback.h" 13 #include "net/base/net_export.h" 14 15 namespace net { 16 17 class DrainableIOBuffer; 18 class IOBuffer; 19 class UploadElementReader; 20 21 // A class to read all elements from an UploadData object. 22 class NET_EXPORT UploadDataStream { 23 public: 24 // An enum used to construct chunked data stream. 25 enum Chunked { CHUNKED }; 26 27 // Constructs a non-chunked data stream. 28 UploadDataStream(ScopedVector<UploadElementReader> element_readers, 29 int64 identifier); 30 31 // Constructs a chunked data stream. 32 UploadDataStream(Chunked chunked, int64 identifier); 33 34 ~UploadDataStream(); 35 36 // Creates UploadDataStream with a reader. 37 static UploadDataStream* CreateWithReader( 38 scoped_ptr<UploadElementReader> reader, 39 int64 identifier); 40 41 // Initializes the stream. This function must be called before calling any 42 // other method. It is not valid to call any method (other than the 43 // destructor) if Init() returns a failure. This method can be called multiple 44 // times. Calling this method after a Init() success results in resetting the 45 // state. 46 // 47 // Does the initialization synchronously and returns the result if possible, 48 // otherwise returns ERR_IO_PENDING and runs the callback with the result. 49 // 50 // Returns OK on success. Returns ERR_UPLOAD_FILE_CHANGED if the expected 51 // file modification time is set (usually not set, but set for sliced 52 // files) and the target file is changed. 53 int Init(const CompletionCallback& callback); 54 55 // When possible, reads up to |buf_len| bytes synchronously from the upload 56 // data stream to |buf| and returns the number of bytes read; otherwise, 57 // returns ERR_IO_PENDING and calls |callback| with the number of bytes read. 58 // Partial reads are allowed. Zero is returned on a call to Read when there 59 // are no remaining bytes in the stream, and IsEof() will return true 60 // hereafter. 61 // 62 // If there's less data to read than we initially observed (i.e. the actual 63 // upload data is smaller than size()), zeros are padded to ensure that 64 // size() bytes can be read, which can happen for TYPE_FILE payloads. 65 int Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback); 66 67 // Identifies a particular upload instance, which is used by the cache to 68 // formulate a cache key. This value should be unique across browser 69 // sessions. A value of 0 is used to indicate an unspecified identifier. 70 int64 identifier() const { return identifier_; } 71 72 // Returns the total size of the data stream and the current position. 73 // size() is not to be used to determine whether the stream has ended 74 // because it is possible for the stream to end before its size is reached, 75 // for example, if the file is truncated. When the data is chunked, size() 76 // always returns zero. 77 uint64 size() const { return total_size_; } 78 uint64 position() const { return current_position_; } 79 80 bool is_chunked() const { return is_chunked_; } 81 bool last_chunk_appended() const { return last_chunk_appended_; } 82 83 const ScopedVector<UploadElementReader>& element_readers() const { 84 return element_readers_; 85 } 86 87 // Returns true if all data has been consumed from this upload data 88 // stream. 89 bool IsEOF() const; 90 91 // Returns true if the upload data in the stream is entirely in memory. 92 bool IsInMemory() const; 93 94 // Adds the given chunk of bytes to be sent with chunked transfer encoding. 95 void AppendChunk(const char* bytes, int bytes_len, bool is_last_chunk); 96 97 // Resets this instance to the uninitialized state. 98 void Reset(); 99 100 private: 101 // Runs Init() for all element readers. 102 // This method is used to implement Init(). 103 int InitInternal(int start_index, const CompletionCallback& callback); 104 105 // Resumes initialization and runs callback with the result when necessary. 106 void ResumePendingInit(int start_index, 107 const CompletionCallback& callback, 108 int previous_result); 109 110 // Reads data from the element readers. 111 // This method is used to implement Read(). 112 int ReadInternal(scoped_refptr<DrainableIOBuffer> buf, 113 const CompletionCallback& callback); 114 115 // Resumes pending read and calls callback with the result when necessary. 116 void ResumePendingRead(scoped_refptr<DrainableIOBuffer> buf, 117 const CompletionCallback& callback, 118 int previous_result); 119 120 // Processes result of UploadElementReader::Read(). If |result| indicates 121 // success, updates |buf|'s offset. Otherwise, sets |read_failed_| to true. 122 void ProcessReadResult(scoped_refptr<DrainableIOBuffer> buf, 123 int result); 124 125 ScopedVector<UploadElementReader> element_readers_; 126 127 // Index of the current upload element (i.e. the element currently being 128 // read). The index is used as a cursor to iterate over elements in 129 // |upload_data_|. 130 size_t element_index_; 131 132 // Size and current read position within the upload data stream. 133 // |total_size_| is set to zero when the data is chunked. 134 uint64 total_size_; 135 uint64 current_position_; 136 137 const int64 identifier_; 138 139 const bool is_chunked_; 140 bool last_chunk_appended_; 141 142 // True if an error occcured during read operation. 143 bool read_failed_; 144 145 // True if the initialization was successful. 146 bool initialized_successfully_; 147 148 // Callback to resume reading chunked data. 149 base::Closure pending_chunked_read_callback_; 150 151 base::WeakPtrFactory<UploadDataStream> weak_ptr_factory_; 152 153 DISALLOW_COPY_AND_ASSIGN(UploadDataStream); 154 }; 155 156 } // namespace net 157 158 #endif // NET_BASE_UPLOAD_DATA_STREAM_H_ 159