1 // Copyright (c) 2011 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_H_ 6 #define NET_BASE_UPLOAD_DATA_H_ 7 #pragma once 8 9 #include <vector> 10 11 #include "base/basictypes.h" 12 #include "base/file_path.h" 13 #include "base/gtest_prod_util.h" 14 #include "base/memory/ref_counted.h" 15 #include "googleurl/src/gurl.h" 16 #include "base/time.h" 17 18 namespace net { 19 20 class FileStream; 21 22 // Interface implemented by callers who require callbacks when new chunks 23 // of data are added. 24 class ChunkCallback { 25 public: 26 // Invoked when a new data chunk was given for a chunked transfer upload. 27 virtual void OnChunkAvailable() = 0; 28 29 protected: ~ChunkCallback()30 virtual ~ChunkCallback() {} 31 }; 32 33 class UploadData : public base::RefCounted<UploadData> { 34 public: 35 enum Type { 36 TYPE_BYTES, 37 TYPE_FILE, 38 TYPE_BLOB, 39 40 // A block of bytes to be sent in chunked encoding immediately, without 41 // waiting for rest of the data. 42 TYPE_CHUNK, 43 }; 44 45 class Element { 46 public: 47 Element(); 48 ~Element(); 49 type()50 Type type() const { return type_; } 51 // Explicitly sets the type of this Element. Used during IPC 52 // marshalling. set_type(Type type)53 void set_type(Type type) { 54 type_ = type; 55 } 56 bytes()57 const std::vector<char>& bytes() const { return bytes_; } file_path()58 const FilePath& file_path() const { return file_path_; } file_range_offset()59 uint64 file_range_offset() const { return file_range_offset_; } file_range_length()60 uint64 file_range_length() const { return file_range_length_; } 61 // If NULL time is returned, we do not do the check. expected_file_modification_time()62 const base::Time& expected_file_modification_time() const { 63 return expected_file_modification_time_; 64 } blob_url()65 const GURL& blob_url() const { return blob_url_; } 66 SetToBytes(const char * bytes,int bytes_len)67 void SetToBytes(const char* bytes, int bytes_len) { 68 type_ = TYPE_BYTES; 69 bytes_.assign(bytes, bytes + bytes_len); 70 } 71 SetToFilePath(const FilePath & path)72 void SetToFilePath(const FilePath& path) { 73 SetToFilePathRange(path, 0, kuint64max, base::Time()); 74 } 75 76 // If expected_modification_time is NULL, we do not check for the file 77 // change. Also note that the granularity for comparison is time_t, not 78 // the full precision. SetToFilePathRange(const FilePath & path,uint64 offset,uint64 length,const base::Time & expected_modification_time)79 void SetToFilePathRange(const FilePath& path, 80 uint64 offset, uint64 length, 81 const base::Time& expected_modification_time) { 82 type_ = TYPE_FILE; 83 file_path_ = path; 84 file_range_offset_ = offset; 85 file_range_length_ = length; 86 expected_file_modification_time_ = expected_modification_time; 87 } 88 89 // TODO(jianli): UploadData should not contain any blob reference. We need 90 // to define another structure to represent WebKit::WebHTTPBody. SetToBlobUrl(const GURL & blob_url)91 void SetToBlobUrl(const GURL& blob_url) { 92 type_ = TYPE_BLOB; 93 blob_url_ = blob_url; 94 } 95 96 // Though similar to bytes, a chunk indicates that the element is sent via 97 // chunked transfer encoding and not buffered until the full upload data 98 // is available. 99 void SetToChunk(const char* bytes, int bytes_len, bool is_last_chunk); 100 is_last_chunk()101 bool is_last_chunk() const { return is_last_chunk_; } 102 // Sets whether this is the last chunk. Used during IPC marshalling. set_is_last_chunk(bool is_last_chunk)103 void set_is_last_chunk(bool is_last_chunk) { 104 is_last_chunk_ = is_last_chunk; 105 } 106 107 // Returns the byte-length of the element. For files that do not exist, 0 108 // is returned. This is done for consistency with Mozilla. 109 // Once called, this function will always return the same value. 110 uint64 GetContentLength(); 111 112 // Returns a FileStream opened for reading for this element, positioned at 113 // |file_range_offset_|. The caller gets ownership and is responsible 114 // for cleaning up the FileStream. Returns NULL if this element is not of 115 // type TYPE_FILE or if the file is not openable. 116 FileStream* NewFileStreamForReading(); 117 118 private: 119 // Allows tests to override the result of GetContentLength. SetContentLength(uint64 content_length)120 void SetContentLength(uint64 content_length) { 121 override_content_length_ = true; 122 content_length_ = content_length; 123 } 124 125 Type type_; 126 std::vector<char> bytes_; 127 FilePath file_path_; 128 uint64 file_range_offset_; 129 uint64 file_range_length_; 130 base::Time expected_file_modification_time_; 131 GURL blob_url_; 132 bool is_last_chunk_; 133 bool override_content_length_; 134 bool content_length_computed_; 135 uint64 content_length_; 136 FileStream* file_stream_; 137 138 FRIEND_TEST_ALL_PREFIXES(UploadDataStreamTest, FileSmallerThanLength); 139 FRIEND_TEST_ALL_PREFIXES(HttpNetworkTransactionTest, 140 UploadFileSmallerThanLength); 141 }; 142 143 UploadData(); 144 145 void AppendBytes(const char* bytes, int bytes_len); 146 147 void AppendFile(const FilePath& file_path); 148 149 void AppendFileRange(const FilePath& file_path, 150 uint64 offset, uint64 length, 151 const base::Time& expected_modification_time); 152 153 void AppendBlob(const GURL& blob_url); 154 155 // Adds the given chunk of bytes to be sent immediately with chunked transfer 156 // encoding. 157 void AppendChunk(const char* bytes, int bytes_len, bool is_last_chunk); 158 159 // Sets the callback to be invoked when a new chunk is available to upload. 160 void set_chunk_callback(ChunkCallback* callback); 161 162 // Initializes the object to send chunks of upload data over time rather 163 // than all at once. set_is_chunked(bool set)164 void set_is_chunked(bool set) { is_chunked_ = set; } is_chunked()165 bool is_chunked() const { return is_chunked_; } 166 167 // Returns the total size in bytes of the data to upload. 168 uint64 GetContentLength(); 169 elements()170 std::vector<Element>* elements() { 171 return &elements_; 172 } 173 174 void SetElements(const std::vector<Element>& elements); 175 swap_elements(std::vector<Element> * elements)176 void swap_elements(std::vector<Element>* elements) { 177 elements_.swap(*elements); 178 } 179 180 // Identifies a particular upload instance, which is used by the cache to 181 // formulate a cache key. This value should be unique across browser 182 // sessions. A value of 0 is used to indicate an unspecified identifier. set_identifier(int64 id)183 void set_identifier(int64 id) { identifier_ = id; } identifier()184 int64 identifier() const { return identifier_; } 185 186 private: 187 friend class base::RefCounted<UploadData>; 188 189 ~UploadData(); 190 191 std::vector<Element> elements_; 192 int64 identifier_; 193 ChunkCallback* chunk_callback_; 194 bool is_chunked_; 195 196 DISALLOW_COPY_AND_ASSIGN(UploadData); 197 }; 198 199 #if defined(UNIT_TEST) 200 inline bool operator==(const UploadData::Element& a, 201 const UploadData::Element& b) { 202 if (a.type() != b.type()) 203 return false; 204 if (a.type() == UploadData::TYPE_BYTES) 205 return a.bytes() == b.bytes(); 206 if (a.type() == UploadData::TYPE_FILE) { 207 return a.file_path() == b.file_path() && 208 a.file_range_offset() == b.file_range_offset() && 209 a.file_range_length() == b.file_range_length() && 210 a.expected_file_modification_time() == 211 b.expected_file_modification_time(); 212 } 213 if (a.type() == UploadData::TYPE_BLOB) 214 return a.blob_url() == b.blob_url(); 215 return false; 216 } 217 218 inline bool operator!=(const UploadData::Element& a, 219 const UploadData::Element& b) { 220 return !(a == b); 221 } 222 #endif // defined(UNIT_TEST) 223 224 } // namespace net 225 226 #endif // NET_BASE_UPLOAD_DATA_H_ 227