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.
5 #ifndef NET_BASE_UPLOAD_DATA_STREAM_H_
6 #define NET_BASE_UPLOAD_DATA_STREAM_H_
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"
17 class DrainableIOBuffer
;
19 class UploadElementReader
;
21 // A class to read all elements from an UploadData object.
22 class NET_EXPORT UploadDataStream
{
24 // An enum used to construct chunked data stream.
25 enum Chunked
{ CHUNKED
};
27 // Constructs a non-chunked data stream.
28 UploadDataStream(ScopedVector
<UploadElementReader
> element_readers
,
31 // Constructs a chunked data stream.
32 UploadDataStream(Chunked chunked
, int64 identifier
);
36 // Creates UploadDataStream with a reader.
37 static UploadDataStream
* CreateWithReader(
38 scoped_ptr
<UploadElementReader
> reader
,
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
47 // Does the initialization synchronously and returns the result if possible,
48 // otherwise returns ERR_IO_PENDING and runs the callback with the result.
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
);
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
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
);
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_
; }
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_
; }
80 bool is_chunked() const { return is_chunked_
; }
81 bool last_chunk_appended() const { return last_chunk_appended_
; }
83 const ScopedVector
<UploadElementReader
>& element_readers() const {
84 return element_readers_
;
87 // Returns true if all data has been consumed from this upload data
91 // Returns true if the upload data in the stream is entirely in memory.
92 bool IsInMemory() const;
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
);
97 // Resets this instance to the uninitialized state.
101 // Runs Init() for all element readers.
102 // This method is used to implement Init().
103 int InitInternal(int start_index
, const CompletionCallback
& callback
);
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
);
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
);
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
);
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
,
125 ScopedVector
<UploadElementReader
> element_readers_
;
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
130 size_t element_index_
;
132 // Size and current read position within the upload data stream.
133 // |total_size_| is set to zero when the data is chunked.
135 uint64 current_position_
;
137 const int64 identifier_
;
139 const bool is_chunked_
;
140 bool last_chunk_appended_
;
142 // True if an error occcured during read operation.
145 // True if the initialization was successful.
146 bool initialized_successfully_
;
148 // Callback to resume reading chunked data.
149 base::Closure pending_chunked_read_callback_
;
151 base::WeakPtrFactory
<UploadDataStream
> weak_ptr_factory_
;
153 DISALLOW_COPY_AND_ASSIGN(UploadDataStream
);
158 #endif // NET_BASE_UPLOAD_DATA_STREAM_H_