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