Home | History | Annotate | Download | only in base
      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