| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 // | 4 // |
| 5 // Filter performs filtering on data streams. Sample usage: | 5 // Filter performs filtering on data streams. Sample usage: |
| 6 // | 6 // |
| 7 // IStream* pre_filter_source; | 7 // IStream* pre_filter_source; |
| 8 // ... | 8 // ... |
| 9 // Filter* filter = Filter::Factory(filter_type, size); | 9 // Filter* filter = Filter::Factory(filter_type, size); |
| 10 // int pre_filter_data_len = filter->stream_buffer_size(); | 10 // int pre_filter_data_len = filter->stream_buffer_size(); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 | 34 |
| 35 #include "base/basictypes.h" | 35 #include "base/basictypes.h" |
| 36 #include "base/scoped_ptr.h" | 36 #include "base/scoped_ptr.h" |
| 37 #include "base/time.h" | 37 #include "base/time.h" |
| 38 #include "net/base/io_buffer.h" | 38 #include "net/base/io_buffer.h" |
| 39 #include "googleurl/src/gurl.h" | 39 #include "googleurl/src/gurl.h" |
| 40 #include "testing/gtest/include/gtest/gtest_prod.h" | 40 #include "testing/gtest/include/gtest/gtest_prod.h" |
| 41 | 41 |
| 42 //------------------------------------------------------------------------------ | 42 //------------------------------------------------------------------------------ |
| 43 // Define an interface class that allows access to contextual information | 43 // Define an interface class that allows access to contextual information |
| 44 // supplied by the owner of this filter. | 44 // supplied by the owner of this filter. In the case where there are a chain of |
| 45 // filters, there is only one owner of all the chained filters, and that context |
| 46 // is passed to the constructor of all those filters. To be clear, the context |
| 47 // does NOT reflect the position in a chain, or the fact that there are prior |
| 48 // or later filters in a chain. |
| 45 class FilterContext { | 49 class FilterContext { |
| 46 public: | 50 public: |
| 47 FilterContext() {}; | 51 virtual ~FilterContext() {} |
| 48 virtual ~FilterContext() {}; | |
| 49 | 52 |
| 50 // What mime type was specified in the header for this data? | 53 // What mime type was specified in the header for this data? |
| 54 // Only makes senses for some types of contexts, and returns false |
| 55 // when not applicable. |
| 51 virtual bool GetMimeType(std::string* mime_type) const = 0; | 56 virtual bool GetMimeType(std::string* mime_type) const = 0; |
| 52 | 57 |
| 53 // What URL was used to access this data? | 58 // What URL was used to access this data? |
| 54 // Return false if gurl is not present. | 59 // Return false if gurl is not present. |
| 55 virtual bool GetURL(GURL* gurl) const = 0; | 60 virtual bool GetURL(GURL* gurl) const = 0; |
| 56 | 61 |
| 57 // When was this data requested from a server? | 62 // When was this data requested from a server? |
| 58 virtual base::Time GetRequestTime() const = 0; | 63 virtual base::Time GetRequestTime() const = 0; |
| 59 | 64 |
| 60 // Is data supplied from cache, or fresh across the net? | 65 // Is data supplied from cache, or fresh across the net? |
| 61 virtual bool IsCachedContent() const = 0; | 66 virtual bool IsCachedContent() const = 0; |
| 62 | 67 |
| 63 // TODO(jar): We could use flags, defined by callers, rather than naming a | |
| 64 // protocol here in the base class. | |
| 65 // Was this data flagged as a response to a request with an SDCH dictionary? | 68 // Was this data flagged as a response to a request with an SDCH dictionary? |
| 66 virtual bool IsSdchResponse() const = 0; | 69 virtual bool IsSdchResponse() const = 0; |
| 67 | 70 |
| 71 // How many bytes were read from the net or cache so far (and potentially |
| 72 // pushed into a filter for processing)? |
| 73 virtual int64 GetByteReadCount() const = 0; |
| 74 |
| 68 // What is the desirable input buffer size for these filters? | 75 // What is the desirable input buffer size for these filters? |
| 69 virtual int GetInputStreambufferSize() const = 0; | 76 // This value is currently supplied by the context, and is constant for all |
| 70 | 77 // filters, even when they are part of a chain of filters. (i.e., we currently |
| 71 private: | 78 // don't change the input buffer sizes for a linked chain of filters, and the |
| 72 DISALLOW_COPY_AND_ASSIGN(FilterContext); | 79 // buffer size for input to all filters in a chain is this one constant). |
| 80 virtual int GetInputStreamBufferSize() const = 0; |
| 73 }; | 81 }; |
| 74 | 82 |
| 75 //------------------------------------------------------------------------------ | 83 //------------------------------------------------------------------------------ |
| 76 class Filter { | 84 class Filter { |
| 77 public: | 85 public: |
| 78 // Return values of function ReadFilteredData. | 86 // Return values of function ReadFilteredData. |
| 79 enum FilterStatus { | 87 enum FilterStatus { |
| 80 // Read filtered data successfully | 88 // Read filtered data successfully |
| 81 FILTER_OK, | 89 FILTER_OK, |
| 82 // Read filtered data successfully, and the data in the buffer has been | 90 // Read filtered data successfully, and the data in the buffer has been |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 // start filtering. Then after this function is called, the caller can get | 152 // start filtering. Then after this function is called, the caller can get |
| 145 // post-filtered data using ReadFilteredData. The caller must not write to | 153 // post-filtered data using ReadFilteredData. The caller must not write to |
| 146 // stream_buffer_ and call this function again before stream_buffer_ is | 154 // stream_buffer_ and call this function again before stream_buffer_ is |
| 147 // emptied out by ReadFilteredData. | 155 // emptied out by ReadFilteredData. |
| 148 // | 156 // |
| 149 // The input stream_data_len is the length (in number of chars) of valid | 157 // The input stream_data_len is the length (in number of chars) of valid |
| 150 // data in stream_buffer_. It can not be greater than stream_buffer_size_. | 158 // data in stream_buffer_. It can not be greater than stream_buffer_size_. |
| 151 // The function returns true if success, and false otherwise. | 159 // The function returns true if success, and false otherwise. |
| 152 bool FlushStreamBuffer(int stream_data_len); | 160 bool FlushStreamBuffer(int stream_data_len); |
| 153 | 161 |
| 154 void SetURL(const GURL& url); | |
| 155 const GURL& url() const { return url_; } | |
| 156 | |
| 157 void SetMimeType(const std::string& mime_type); | |
| 158 const std::string& mime_type() const { return mime_type_; } | |
| 159 | |
| 160 void SetConnectTime(const base::Time& time, bool was_cached); | |
| 161 | |
| 162 // Translate the text of a filter name (from Content-Encoding header) into a | 162 // Translate the text of a filter name (from Content-Encoding header) into a |
| 163 // FilterType. | 163 // FilterType. |
| 164 static FilterType ConvertEncodingToType(const std::string& filter_type); | 164 static FilterType ConvertEncodingToType(const std::string& filter_type); |
| 165 | 165 |
| 166 // Given a array of encoding_types, try to do some error recovery adjustment | 166 // Given a array of encoding_types, try to do some error recovery adjustment |
| 167 // to the list. This includes handling known bugs in the Apache server (where | 167 // to the list. This includes handling known bugs in the Apache server (where |
| 168 // redundant gzip encoding is specified), as well as issues regarding SDCH | 168 // redundant gzip encoding is specified), as well as issues regarding SDCH |
| 169 // encoding, where various proxies and anti-virus products modify or strip the | 169 // encoding, where various proxies and anti-virus products modify or strip the |
| 170 // encodings. These fixups require context, which includes whether this | 170 // encodings. These fixups require context, which includes whether this |
| 171 // response was made to an SDCH request (i.e., an available dictionary was | 171 // response was made to an SDCH request (i.e., an available dictionary was |
| 172 // advertised in the GET), as well as the mime type of the content. | 172 // advertised in the GET), as well as the mime type of the content. |
| 173 static void FixupEncodingTypes(bool is_sdch_response, | 173 static void FixupEncodingTypes(const FilterContext& filter_context, |
| 174 const std::string& mime_type, | |
| 175 std::vector<FilterType>* encoding_types); | 174 std::vector<FilterType>* encoding_types); |
| 176 protected: | 175 protected: |
| 177 explicit Filter(const FilterContext& filter_context); | 176 explicit Filter(const FilterContext& filter_context); |
| 178 | 177 |
| 179 FRIEND_TEST(SdchFilterTest, ContentTypeId); | 178 FRIEND_TEST(SdchFilterTest, ContentTypeId); |
| 180 // Filters the data stored in stream_buffer_ and writes the output into the | 179 // Filters the data stored in stream_buffer_ and writes the output into the |
| 181 // dest_buffer passed in. | 180 // dest_buffer passed in. |
| 182 // | 181 // |
| 183 // Upon entry, *dest_len is the total size (in number of chars) of the | 182 // Upon entry, *dest_len is the total size (in number of chars) of the |
| 184 // destination buffer. Upon exit, *dest_len is the actual number of chars | 183 // destination buffer. Upon exit, *dest_len is the actual number of chars |
| 185 // written into the destination buffer. | 184 // written into the destination buffer. |
| 186 // | 185 // |
| 187 // This function will fail if there is no pre-filter data in the | 186 // This function will fail if there is no pre-filter data in the |
| 188 // stream_buffer_. On the other hand, *dest_len can be 0 upon successful | 187 // stream_buffer_. On the other hand, *dest_len can be 0 upon successful |
| 189 // return. For example, a decoding filter may process some pre-filter data | 188 // return. For example, a decoding filter may process some pre-filter data |
| 190 // but not produce output yet. | 189 // but not produce output yet. |
| 191 virtual FilterStatus ReadFilteredData(char* dest_buffer, int* dest_len); | 190 virtual FilterStatus ReadFilteredData(char* dest_buffer, int* dest_len); |
| 192 | 191 |
| 193 // Copy pre-filter data directly to destination buffer without decoding. | 192 // Copy pre-filter data directly to destination buffer without decoding. |
| 194 FilterStatus CopyOut(char* dest_buffer, int* dest_len); | 193 FilterStatus CopyOut(char* dest_buffer, int* dest_len); |
| 195 | 194 |
| 196 // Allocates and initializes stream_buffer_ based on filter_context_. | |
| 197 // Establishes a buffer large enough to handle the amount specified in | |
| 198 // filter_context_.GetInputStreambufferSize(). | |
| 199 bool InitBuffer(); | |
| 200 | |
| 201 // A factory helper for creating filters for within a chain of potentially | |
| 202 // multiple encodings. If a chain of filters is created, then this may be | |
| 203 // called multiple times during the filter creation process. In most simple | |
| 204 // cases, this is only called once. Returns NULL and cleans up (deleting | |
| 205 // filter_list) if a new filter can't be constructed. | |
| 206 static Filter* PrependNewFilter(FilterType type_id, | |
| 207 const FilterContext& filter_context, | |
| 208 Filter* filter_list); | |
| 209 | |
| 210 FilterStatus last_status() const { return last_status_; } | 195 FilterStatus last_status() const { return last_status_; } |
| 211 | 196 |
| 212 base::Time connect_time() const { return connect_time_; } | 197 const FilterContext& filter_context() const { return filter_context_; } |
| 213 | |
| 214 bool was_cached() const { return was_cached_; } | |
| 215 | 198 |
| 216 // Buffer to hold the data to be filtered (the input queue). | 199 // Buffer to hold the data to be filtered (the input queue). |
| 217 scoped_refptr<net::IOBuffer> stream_buffer_; | 200 scoped_refptr<net::IOBuffer> stream_buffer_; |
| 218 | 201 |
| 219 // Maximum size of stream_buffer_ in number of chars. | 202 // Maximum size of stream_buffer_ in number of chars. |
| 220 int stream_buffer_size_; | 203 int stream_buffer_size_; |
| 221 | 204 |
| 222 // Pointer to the next data in stream_buffer_ to be filtered. | 205 // Pointer to the next data in stream_buffer_ to be filtered. |
| 223 char* next_stream_data_; | 206 char* next_stream_data_; |
| 224 | 207 |
| 225 // Total number of remaining chars in stream_buffer_ to be filtered. | 208 // Total number of remaining chars in stream_buffer_ to be filtered. |
| 226 int stream_data_len_; | 209 int stream_data_len_; |
| 227 | 210 |
| 228 private: // TODO(jar): Make more data private by moving this up higher. | 211 private: |
| 229 // The URL that is currently being filtered. | 212 // A factory helper for creating filters for within a chain of potentially |
| 230 // This is used by SDCH filters which need to restrict use of a dictionary to | 213 // multiple encodings. If a chain of filters is created, then this may be |
| 231 // a specific URL or path. | 214 // called multiple times during the filter creation process. In most simple |
| 232 GURL url_; | 215 // cases, this is only called once. Returns NULL and cleans up (deleting |
| 216 // filter_list) if a new filter can't be constructed. |
| 217 static Filter* PrependNewFilter(FilterType type_id, |
| 218 const FilterContext& filter_context, |
| 219 Filter* filter_list); |
| 233 | 220 |
| 234 // To facilitate histogramming by individual filters, we store the connect | 221 // Allocates and initializes stream_buffer_ based on filter_context_. |
| 235 // time for the corresponding HTTP transaction, as well as whether this time | 222 // Establishes a buffer large enough to handle the amount specified in |
| 236 // was recalled from a cached entry. | 223 // filter_context_.GetInputStreamBufferSize(). |
| 237 base::Time connect_time_; | 224 bool InitBuffer(); |
| 238 bool was_cached_; | |
| 239 | 225 |
| 240 // Helper function to empty our output into the next filter's input. | 226 // Helper function to empty our output into the next filter's input. |
| 241 void PushDataIntoNextFilter(); | 227 void PushDataIntoNextFilter(); |
| 242 | 228 |
| 243 // To facilitate error recovery in SDCH filters, allow filter to know if | |
| 244 // content is text/html by checking within this mime type (SDCH filter may | |
| 245 // do a meta-refresh via html). | |
| 246 std::string mime_type_; | |
| 247 | |
| 248 // An optional filter to process output from this filter. | 229 // An optional filter to process output from this filter. |
| 249 scoped_ptr<Filter> next_filter_; | 230 scoped_ptr<Filter> next_filter_; |
| 250 // Remember what status or local filter last returned so we can better handle | 231 // Remember what status or local filter last returned so we can better handle |
| 251 // chained filters. | 232 // chained filters. |
| 252 FilterStatus last_status_; | 233 FilterStatus last_status_; |
| 253 | 234 |
| 254 // Context data from the owner of this filter. Some filters need additional | 235 // Context data from the owner of this filter. Some filters need additional |
| 255 // context information (mime type, etc.) to properly function, and they access | 236 // context information (mime type, etc.) to properly function, and they access |
| 256 // this data via this reference member. | 237 // this data via this reference member. |
| 257 const FilterContext& filter_context_; | 238 const FilterContext& filter_context_; |
| 258 | 239 |
| 259 DISALLOW_COPY_AND_ASSIGN(Filter); | 240 DISALLOW_COPY_AND_ASSIGN(Filter); |
| 260 }; | 241 }; |
| 261 | 242 |
| 262 #endif // NET_BASE_FILTER_H__ | 243 #endif // NET_BASE_FILTER_H__ |
| OLD | NEW |