1 // Copyright 2014 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 // Filter performs filtering on data streams. Sample usage: 6 // 7 // IStream* pre_filter_source; 8 // ... 9 // Filter* filter = Filter::Factory(filter_type, size); 10 // int pre_filter_data_len = filter->stream_buffer_size(); 11 // pre_filter_source->read(filter->stream_buffer(), pre_filter_data_len); 12 // 13 // filter->FlushStreamBuffer(pre_filter_data_len); 14 // 15 // char post_filter_buf[kBufferSize]; 16 // int post_filter_data_len = kBufferSize; 17 // filter->ReadFilteredData(post_filter_buf, &post_filter_data_len); 18 // 19 // To filter a data stream, the caller first gets filter's stream_buffer_ 20 // through its accessor and fills in stream_buffer_ with pre-filter data, next 21 // calls FlushStreamBuffer to notify Filter, then calls ReadFilteredData 22 // repeatedly to get all the filtered data. After all data have been fitlered 23 // and read out, the caller may fill in stream_buffer_ again. This 24 // WriteBuffer-Flush-Read cycle is repeated until reaching the end of data 25 // stream. 26 // 27 // The lifetime of a Filter instance is completely controlled by its caller. 28 29 #ifndef NET_FILTER_FILTER_H__ 30 #define NET_FILTER_FILTER_H__ 31 32 #include <string> 33 #include <vector> 34 35 #include "base/basictypes.h" 36 #include "base/gtest_prod_util.h" 37 #include "base/memory/ref_counted.h" 38 #include "base/memory/scoped_ptr.h" 39 #include "base/time/time.h" 40 #include "net/base/net_export.h" 41 42 class GURL; 43 44 namespace net { 45 46 class URLRequestContext; 47 class IOBuffer; 48 49 //------------------------------------------------------------------------------ 50 // Define an interface class that allows access to contextual information 51 // supplied by the owner of this filter. In the case where there are a chain of 52 // filters, there is only one owner of all the chained filters, and that context 53 // is passed to the constructor of all those filters. To be clear, the context 54 // does NOT reflect the position in a chain, or the fact that there are prior 55 // or later filters in a chain. 56 class NET_EXPORT_PRIVATE FilterContext { 57 public: 58 // Enum to control what histograms are emitted near end-of-life of this 59 // instance. 60 enum StatisticSelector { 61 SDCH_DECODE, 62 SDCH_PASSTHROUGH, 63 SDCH_EXPERIMENT_DECODE, 64 SDCH_EXPERIMENT_HOLDBACK, 65 }; 66 67 virtual ~FilterContext(); 68 69 // What mime type was specified in the header for this data? 70 // Only makes senses for some types of contexts, and returns false 71 // when not applicable. 72 virtual bool GetMimeType(std::string* mime_type) const = 0; 73 74 // What URL was used to access this data? 75 // Return false if gurl is not present. 76 virtual bool GetURL(GURL* gurl) const = 0; 77 78 // What Content-Disposition header came with this data? 79 // Return false if no header was present. 80 virtual bool GetContentDisposition(std::string* disposition) const = 0; 81 82 // When was this data requested from a server? 83 virtual base::Time GetRequestTime() const = 0; 84 85 // Is data supplied from cache, or fresh across the net? 86 virtual bool IsCachedContent() const = 0; 87 88 // Is this a download? 89 virtual bool IsDownload() const = 0; 90 91 // Was this data flagged as a response to a request with an SDCH dictionary? 92 virtual bool IsSdchResponse() const = 0; 93 94 // How many bytes were read from the net or cache so far (and potentially 95 // pushed into a filter for processing)? 96 virtual int64 GetByteReadCount() const = 0; 97 98 // What response code was received with the associated network transaction? 99 // For example: 200 is ok. 4xx are error codes. etc. 100 virtual int GetResponseCode() const = 0; 101 102 // The URLRequestContext associated with the request. 103 virtual const URLRequestContext* GetURLRequestContext() const = 0; 104 105 // The following method forces the context to emit a specific set of 106 // statistics as selected by the argument. 107 virtual void RecordPacketStats(StatisticSelector statistic) const = 0; 108 }; 109 110 //------------------------------------------------------------------------------ 111 class NET_EXPORT_PRIVATE Filter { 112 public: 113 // Return values of function ReadFilteredData. 114 enum FilterStatus { 115 // Read filtered data successfully 116 FILTER_OK, 117 // Read filtered data successfully, and the data in the buffer has been 118 // consumed by the filter, but more data is needed in order to continue 119 // filtering. At this point, the caller is free to reuse the filter 120 // buffer to provide more data. 121 FILTER_NEED_MORE_DATA, 122 // Read filtered data successfully, and filter reaches the end of the data 123 // stream. 124 FILTER_DONE, 125 // There is an error during filtering. 126 FILTER_ERROR 127 }; 128 129 // Specifies type of filters that can be created. 130 enum FilterType { 131 FILTER_TYPE_DEFLATE, 132 FILTER_TYPE_GZIP, 133 FILTER_TYPE_GZIP_HELPING_SDCH, // Gzip possible, but pass through allowed. 134 FILTER_TYPE_SDCH, 135 FILTER_TYPE_SDCH_POSSIBLE, // Sdch possible, but pass through allowed. 136 FILTER_TYPE_UNSUPPORTED, 137 }; 138 139 virtual ~Filter(); 140 141 // Creates a Filter object. 142 // Parameters: Filter_types specifies the type of filter created; 143 // filter_context allows filters to acquire additional details needed for 144 // construction and operation, such as a specification of requisite input 145 // buffer size. 146 // If success, the function returns the pointer to the Filter object created. 147 // If failed or a filter is not needed, the function returns NULL. 148 // 149 // Note: filter_types is an array of filter types (content encoding types as 150 // provided in an HTTP header), which will be chained together serially to do 151 // successive filtering of data. The types in the vector are ordered based on 152 // encoding order, and the filters are chained to operate in the reverse 153 // (decoding) order. For example, types[0] = FILTER_TYPE_SDCH, 154 // types[1] = FILTER_TYPE_GZIP will cause data to first be gunzip filtered, 155 // and the resulting output from that filter will be sdch decoded. 156 static Filter* Factory(const std::vector<FilterType>& filter_types, 157 const FilterContext& filter_context); 158 159 // A simpler version of Factory() which creates a single, unchained 160 // Filter of type FILTER_TYPE_GZIP, or NULL if the filter could not be 161 // initialized. 162 static Filter* GZipFactory(); 163 164 // External call to obtain data from this filter chain. If ther is no 165 // next_filter_, then it obtains data from this specific filter. 166 FilterStatus ReadData(char* dest_buffer, int* dest_len); 167 168 // Returns a pointer to the stream_buffer_. stream_buffer()169 IOBuffer* stream_buffer() const { return stream_buffer_.get(); } 170 171 // Returns the maximum size of stream_buffer_ in number of chars. stream_buffer_size()172 int stream_buffer_size() const { return stream_buffer_size_; } 173 174 // Returns the total number of chars remaining in stream_buffer_ to be 175 // filtered. 176 // 177 // If the function returns 0 then all data has been filtered, and the caller 178 // is safe to copy new data into stream_buffer_. stream_data_len()179 int stream_data_len() const { return stream_data_len_; } 180 181 // Flushes stream_buffer_ for next round of filtering. After copying data to 182 // stream_buffer_, the caller should call this function to notify Filter to 183 // start filtering. Then after this function is called, the caller can get 184 // post-filtered data using ReadFilteredData. The caller must not write to 185 // stream_buffer_ and call this function again before stream_buffer_ is 186 // emptied out by ReadFilteredData. 187 // 188 // The input stream_data_len is the length (in number of chars) of valid 189 // data in stream_buffer_. It can not be greater than stream_buffer_size_. 190 // The function returns true if success, and false otherwise. 191 bool FlushStreamBuffer(int stream_data_len); 192 193 // Translate the text of a filter name (from Content-Encoding header) into a 194 // FilterType. 195 static FilterType ConvertEncodingToType(const std::string& filter_type); 196 197 // Given a array of encoding_types, try to do some error recovery adjustment 198 // to the list. This includes handling known bugs in the Apache server (where 199 // redundant gzip encoding is specified), as well as issues regarding SDCH 200 // encoding, where various proxies and anti-virus products modify or strip the 201 // encodings. These fixups require context, which includes whether this 202 // response was made to an SDCH request (i.e., an available dictionary was 203 // advertised in the GET), as well as the mime type of the content. 204 static void FixupEncodingTypes(const FilterContext& filter_context, 205 std::vector<FilterType>* encoding_types); 206 207 protected: 208 friend class GZipUnitTest; 209 friend class SdchFilterChainingTest; 210 211 Filter(); 212 213 // Filters the data stored in stream_buffer_ and writes the output into the 214 // dest_buffer passed in. 215 // 216 // Upon entry, *dest_len is the total size (in number of chars) of the 217 // destination buffer. Upon exit, *dest_len is the actual number of chars 218 // written into the destination buffer. 219 // 220 // This function will fail if there is no pre-filter data in the 221 // stream_buffer_. On the other hand, *dest_len can be 0 upon successful 222 // return. For example, a decoding filter may process some pre-filter data 223 // but not produce output yet. 224 virtual FilterStatus ReadFilteredData(char* dest_buffer, int* dest_len) = 0; 225 226 // Copy pre-filter data directly to destination buffer without decoding. 227 FilterStatus CopyOut(char* dest_buffer, int* dest_len); 228 last_status()229 FilterStatus last_status() const { return last_status_; } 230 231 // Buffer to hold the data to be filtered (the input queue). 232 scoped_refptr<IOBuffer> stream_buffer_; 233 234 // Maximum size of stream_buffer_ in number of chars. 235 int stream_buffer_size_; 236 237 // Pointer to the next data in stream_buffer_ to be filtered. 238 char* next_stream_data_; 239 240 // Total number of remaining chars in stream_buffer_ to be filtered. 241 int stream_data_len_; 242 243 private: 244 // Allocates and initializes stream_buffer_ and stream_buffer_size_. 245 void InitBuffer(int size); 246 247 // A factory helper for creating filters for within a chain of potentially 248 // multiple encodings. If a chain of filters is created, then this may be 249 // called multiple times during the filter creation process. In most simple 250 // cases, this is only called once. Returns NULL and cleans up (deleting 251 // filter_list) if a new filter can't be constructed. 252 static Filter* PrependNewFilter(FilterType type_id, 253 const FilterContext& filter_context, 254 int buffer_size, 255 Filter* filter_list); 256 257 // Helper methods for PrependNewFilter. If initialization is successful, 258 // they return a fully initialized Filter. Otherwise, return NULL. 259 static Filter* InitGZipFilter(FilterType type_id, int buffer_size); 260 static Filter* InitSdchFilter(FilterType type_id, 261 const FilterContext& filter_context, 262 int buffer_size); 263 264 // Helper function to empty our output into the next filter's input. 265 void PushDataIntoNextFilter(); 266 267 // Constructs a filter with an internal buffer of the given size. 268 // Only meant to be called by unit tests that need to control the buffer size. 269 static Filter* FactoryForTests(const std::vector<FilterType>& filter_types, 270 const FilterContext& filter_context, 271 int buffer_size); 272 273 // An optional filter to process output from this filter. 274 scoped_ptr<Filter> next_filter_; 275 // Remember what status or local filter last returned so we can better handle 276 // chained filters. 277 FilterStatus last_status_; 278 279 DISALLOW_COPY_AND_ASSIGN(Filter); 280 }; 281 282 } // namespace net 283 284 #endif // NET_FILTER_FILTER_H__ 285