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