• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
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.
size()77   uint64 size() const { return total_size_; }
position()78   uint64 position() const { return current_position_; }
79 
is_chunked()80   bool is_chunked() const { return is_chunked_; }
last_chunk_appended()81   bool last_chunk_appended() const { return last_chunk_appended_; }
82 
element_readers()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