15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NET_BASE_UPLOAD_DATA_STREAM_H_ 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NET_BASE_UPLOAD_DATA_STREAM_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/gtest_prod_util.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_vector.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/completion_callback.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_export.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DrainableIOBuffer; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IOBuffer; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class UploadElementReader; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A class to read all elements from an UploadData object. 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NET_EXPORT UploadDataStream { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // An enum used to construct chunked data stream. 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) enum Chunked { CHUNKED }; 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Constructs a non-chunked data stream. 2868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) UploadDataStream(ScopedVector<UploadElementReader> element_readers, 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64 identifier); 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Constructs a chunked data stream. 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UploadDataStream(Chunked chunked, int64 identifier); 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~UploadDataStream(); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Creates UploadDataStream with a reader. 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static UploadDataStream* CreateWithReader( 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<UploadElementReader> reader, 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64 identifier); 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initializes the stream. This function must be called before calling any 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // other method. It is not valid to call any method (other than the 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // destructor) if Init() returns a failure. This method can be called multiple 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // times. Calling this method after a Init() success results in resetting the 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // state. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Does the initialization synchronously and returns the result if possible, 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // otherwise returns ERR_IO_PENDING and runs the callback with the result. 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns OK on success. Returns ERR_UPLOAD_FILE_CHANGED if the expected 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // file modification time is set (usually not set, but set for sliced 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // files) and the target file is changed. 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int Init(const CompletionCallback& callback); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When possible, reads up to |buf_len| bytes synchronously from the upload 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // data stream to |buf| and returns the number of bytes read; otherwise, 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // returns ERR_IO_PENDING and calls |callback| with the number of bytes read. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Partial reads are allowed. Zero is returned on a call to Read when there 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // are no remaining bytes in the stream, and IsEof() will return true 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // hereafter. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there's less data to read than we initially observed (i.e. the actual 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // upload data is smaller than size()), zeros are padded to ensure that 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // size() bytes can be read, which can happen for TYPE_FILE payloads. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int Read(IOBuffer* buf, int buf_len, const CompletionCallback& callback); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Identifies a particular upload instance, which is used by the cache to 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // formulate a cache key. This value should be unique across browser 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // sessions. A value of 0 is used to indicate an unspecified identifier. 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int64 identifier() const { return identifier_; } 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns the total size of the data stream and the current position. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // size() is not to be used to determine whether the stream has ended 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // because it is possible for the stream to end before its size is reached, 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for example, if the file is truncated. When the data is chunked, size() 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // always returns zero. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 size() const { return total_size_; } 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 position() const { return current_position_; } 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_chunked() const { return is_chunked_; } 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool last_chunk_appended() const { return last_chunk_appended_; } 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ScopedVector<UploadElementReader>& element_readers() const { 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return element_readers_; 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if all data has been consumed from this upload data 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // stream. 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool IsEOF() const; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true if the upload data in the stream is entirely in memory. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool IsInMemory() const; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Adds the given chunk of bytes to be sent with chunked transfer encoding. 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void AppendChunk(const char* bytes, int bytes_len, bool is_last_chunk); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Resets this instance to the uninitialized state. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Reset(); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private: 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Runs Init() for all element readers. 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This method is used to implement Init(). 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int InitInternal(int start_index, const CompletionCallback& callback); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Resumes initialization and runs callback with the result when necessary. 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ResumePendingInit(int start_index, 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback, 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int previous_result); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reads data from the element readers. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This method is used to implement Read(). 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ReadInternal(scoped_refptr<DrainableIOBuffer> buf, 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Resumes pending read and calls callback with the result when necessary. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ResumePendingRead(scoped_refptr<DrainableIOBuffer> buf, 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback, 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int previous_result); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Processes result of UploadElementReader::Read(). If |result| indicates 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // success, updates |buf|'s offset. Otherwise, sets |read_failed_| to true. 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void ProcessReadResult(scoped_refptr<DrainableIOBuffer> buf, 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int result); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedVector<UploadElementReader> element_readers_; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Index of the current upload element (i.e. the element currently being 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // read). The index is used as a cursor to iterate over elements in 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |upload_data_|. 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t element_index_; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Size and current read position within the upload data stream. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |total_size_| is set to zero when the data is chunked. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 total_size_; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 current_position_; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int64 identifier_; 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const bool is_chunked_; 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool last_chunk_appended_; 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // True if an error occcured during read operation. 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool read_failed_; 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // True if the initialization was successful. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool initialized_successfully_; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Callback to resume reading chunked data. 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Closure pending_chunked_read_callback_; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::WeakPtrFactory<UploadDataStream> weak_ptr_factory_; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(UploadDataStream); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // NET_BASE_UPLOAD_DATA_STREAM_H_ 159