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 #include "net/base/filter.h" | 5 #include "net/base/filter.h" |
6 | 6 |
7 #include "base/string_util.h" | 7 #include "base/string_util.h" |
8 #include "net/base/gzip_filter.h" | 8 #include "net/base/gzip_filter.h" |
9 #include "net/base/bzip2_filter.h" | 9 #include "net/base/bzip2_filter.h" |
10 #include "net/base/sdch_filter.h" | 10 #include "net/base/sdch_filter.h" |
(...skipping 19 matching lines...) Expand all Loading... | |
30 const char kApplicationXGzip[] = "application/x-gzip"; | 30 const char kApplicationXGzip[] = "application/x-gzip"; |
31 const char kApplicationGzip[] = "application/gzip"; | 31 const char kApplicationGzip[] = "application/gzip"; |
32 const char kApplicationXGunzip[] = "application/x-gunzip"; | 32 const char kApplicationXGunzip[] = "application/x-gunzip"; |
33 const char kApplicationXCompress[] = "application/x-compress"; | 33 const char kApplicationXCompress[] = "application/x-compress"; |
34 const char kApplicationCompress[] = "application/compress"; | 34 const char kApplicationCompress[] = "application/compress"; |
35 const char kTextHtml[] = "text/html"; | 35 const char kTextHtml[] = "text/html"; |
36 | 36 |
37 } // namespace | 37 } // namespace |
38 | 38 |
39 Filter* Filter::Factory(const std::vector<FilterType>& filter_types, | 39 Filter* Filter::Factory(const std::vector<FilterType>& filter_types, |
40 int buffer_size) { | 40 const FilterContext& filter_context) { |
41 if (filter_types.empty() || buffer_size < 0) | 41 DCHECK(filter_context.GetInputStreambufferSize() > 0); |
42 if (filter_types.empty() || filter_context.GetInputStreambufferSize() <= 0) | |
42 return NULL; | 43 return NULL; |
43 | 44 |
45 | |
44 Filter* filter_list = NULL; // Linked list of filters. | 46 Filter* filter_list = NULL; // Linked list of filters. |
45 for (size_t i = 0; i < filter_types.size(); i++) { | 47 for (size_t i = 0; i < filter_types.size(); i++) { |
46 filter_list = PrependNewFilter(filter_types[i], buffer_size, filter_list); | 48 filter_list = PrependNewFilter(filter_types[i], filter_context, |
49 filter_list); | |
47 if (!filter_list) | 50 if (!filter_list) |
48 return NULL; | 51 return NULL; |
49 } | 52 } |
50 | 53 |
54 // TODO(jar): These settings should go into the derived classes, on an as-need ed basis. | |
huanr
2009/03/09 17:50:44
Per our discussion, would be helpful to mention th
jar (doing other things)
2009/03/09 19:00:41
Done.
| |
55 std::string mime_type; | |
56 bool success = filter_context.GetMimeType(&mime_type); | |
57 DCHECK(success); | |
58 GURL gurl; | |
59 success = filter_context.GetURL(&gurl); | |
60 DCHECK(success); | |
61 base::Time request_time = filter_context.GetRequestTime(); | |
62 bool is_cached_content = filter_context.IsCachedContent(); | |
63 | |
64 filter_list->SetMimeType(mime_type); | |
65 filter_list->SetURL(gurl); | |
66 // Approximate connect time with request_time. If it is not cached, then | |
67 // this is a good approximation for when the first bytes went on the | |
68 // wire. | |
69 filter_list->SetConnectTime(request_time, is_cached_content); | |
70 | |
51 return filter_list; | 71 return filter_list; |
52 } | 72 } |
53 | 73 |
54 // static | 74 // static |
55 Filter::FilterType Filter::ConvertEncodingToType( | 75 Filter::FilterType Filter::ConvertEncodingToType( |
56 const std::string& filter_type) { | 76 const std::string& filter_type) { |
57 FilterType type_id; | 77 FilterType type_id; |
58 if (LowerCaseEqualsASCII(filter_type, kDeflate)) { | 78 if (LowerCaseEqualsASCII(filter_type, kDeflate)) { |
59 type_id = FILTER_TYPE_DEFLATE; | 79 type_id = FILTER_TYPE_DEFLATE; |
60 } else if (LowerCaseEqualsASCII(filter_type, kGZip) || | 80 } else if (LowerCaseEqualsASCII(filter_type, kGZip) || |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
167 } | 187 } |
168 } | 188 } |
169 | 189 |
170 encoding_types->clear(); | 190 encoding_types->clear(); |
171 encoding_types->push_back(FILTER_TYPE_SDCH_POSSIBLE); | 191 encoding_types->push_back(FILTER_TYPE_SDCH_POSSIBLE); |
172 encoding_types->push_back(FILTER_TYPE_GZIP_HELPING_SDCH); | 192 encoding_types->push_back(FILTER_TYPE_GZIP_HELPING_SDCH); |
173 return; | 193 return; |
174 } | 194 } |
175 | 195 |
176 // static | 196 // static |
177 Filter* Filter::PrependNewFilter(FilterType type_id, int buffer_size, | 197 Filter* Filter::PrependNewFilter(FilterType type_id, |
198 const FilterContext& filter_context, | |
178 Filter* filter_list) { | 199 Filter* filter_list) { |
179 Filter* first_filter = NULL; // Soon to be start of chain. | 200 Filter* first_filter = NULL; // Soon to be start of chain. |
180 switch (type_id) { | 201 switch (type_id) { |
181 case FILTER_TYPE_GZIP_HELPING_SDCH: | 202 case FILTER_TYPE_GZIP_HELPING_SDCH: |
182 case FILTER_TYPE_DEFLATE: | 203 case FILTER_TYPE_DEFLATE: |
183 case FILTER_TYPE_GZIP: { | 204 case FILTER_TYPE_GZIP: { |
184 scoped_ptr<GZipFilter> gz_filter(new GZipFilter()); | 205 scoped_ptr<GZipFilter> gz_filter(new GZipFilter(filter_context)); |
185 if (gz_filter->InitBuffer(buffer_size)) { | 206 if (gz_filter->InitBuffer()) { |
186 if (gz_filter->InitDecoding(type_id)) { | 207 if (gz_filter->InitDecoding(type_id)) { |
187 first_filter = gz_filter.release(); | 208 first_filter = gz_filter.release(); |
188 } | 209 } |
189 } | 210 } |
190 break; | 211 break; |
191 } | 212 } |
192 case FILTER_TYPE_BZIP2: { | 213 case FILTER_TYPE_BZIP2: { |
193 scoped_ptr<BZip2Filter> bzip2_filter(new BZip2Filter()); | 214 scoped_ptr<BZip2Filter> bzip2_filter(new BZip2Filter(filter_context)); |
194 if (bzip2_filter->InitBuffer(buffer_size)) { | 215 if (bzip2_filter->InitBuffer()) { |
195 if (bzip2_filter->InitDecoding(false)) { | 216 if (bzip2_filter->InitDecoding(false)) { |
196 first_filter = bzip2_filter.release(); | 217 first_filter = bzip2_filter.release(); |
197 } | 218 } |
198 } | 219 } |
199 break; | 220 break; |
200 } | 221 } |
201 case FILTER_TYPE_SDCH: | 222 case FILTER_TYPE_SDCH: |
202 case FILTER_TYPE_SDCH_POSSIBLE: { | 223 case FILTER_TYPE_SDCH_POSSIBLE: { |
203 scoped_ptr<SdchFilter> sdch_filter(new SdchFilter()); | 224 scoped_ptr<SdchFilter> sdch_filter(new SdchFilter(filter_context)); |
204 if (sdch_filter->InitBuffer(buffer_size)) { | 225 if (sdch_filter->InitBuffer()) { |
205 if (sdch_filter->InitDecoding(type_id)) { | 226 if (sdch_filter->InitDecoding(type_id)) { |
206 first_filter = sdch_filter.release(); | 227 first_filter = sdch_filter.release(); |
207 } | 228 } |
208 } | 229 } |
209 break; | 230 break; |
210 } | 231 } |
211 default: { | 232 default: { |
212 break; | 233 break; |
213 } | 234 } |
214 } | 235 } |
215 | 236 |
216 if (first_filter) { | 237 if (!first_filter) { |
217 first_filter->next_filter_.reset(filter_list); | |
218 } else { | |
219 // Cleanup and exit, since we can't construct this filter list. | 238 // Cleanup and exit, since we can't construct this filter list. |
220 delete filter_list; | 239 delete filter_list; |
221 filter_list = NULL; | 240 return NULL; |
222 } | 241 } |
242 | |
243 first_filter->next_filter_.reset(filter_list); | |
223 return first_filter; | 244 return first_filter; |
224 } | 245 } |
225 | 246 |
226 Filter::Filter() | 247 Filter::Filter(const FilterContext& filter_context) |
227 : stream_buffer_(NULL), | 248 : stream_buffer_(NULL), |
228 stream_buffer_size_(0), | 249 stream_buffer_size_(0), |
229 next_stream_data_(NULL), | 250 next_stream_data_(NULL), |
230 stream_data_len_(0), | 251 stream_data_len_(0), |
231 url_(), | 252 url_(), |
232 connect_time_(), | 253 connect_time_(), |
233 was_cached_(false), | 254 was_cached_(false), |
234 mime_type_(), | 255 mime_type_(), |
235 next_filter_(NULL), | 256 next_filter_(NULL), |
236 last_status_(FILTER_NEED_MORE_DATA) { | 257 last_status_(FILTER_NEED_MORE_DATA), |
258 filter_context_(filter_context) { | |
237 } | 259 } |
238 | 260 |
239 Filter::~Filter() {} | 261 Filter::~Filter() {} |
240 | 262 |
241 bool Filter::InitBuffer(int buffer_size) { | 263 bool Filter::InitBuffer() { |
242 if (buffer_size < 0 || stream_buffer()) | 264 int buffer_size = filter_context_.GetInputStreambufferSize(); |
265 DCHECK(buffer_size > 0); | |
266 if (buffer_size <= 0 || stream_buffer()) | |
243 return false; | 267 return false; |
244 | 268 |
245 stream_buffer_ = new net::IOBuffer(buffer_size); | 269 stream_buffer_ = new net::IOBuffer(buffer_size); |
246 | 270 |
247 if (stream_buffer()) { | 271 if (stream_buffer()) { |
248 stream_buffer_size_ = buffer_size; | 272 stream_buffer_size_ = buffer_size; |
249 return true; | 273 return true; |
250 } | 274 } |
251 | 275 |
252 return false; | 276 return false; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
321 void Filter::PushDataIntoNextFilter() { | 345 void Filter::PushDataIntoNextFilter() { |
322 net::IOBuffer* next_buffer = next_filter_->stream_buffer(); | 346 net::IOBuffer* next_buffer = next_filter_->stream_buffer(); |
323 int next_size = next_filter_->stream_buffer_size(); | 347 int next_size = next_filter_->stream_buffer_size(); |
324 last_status_ = ReadFilteredData(next_buffer->data(), &next_size); | 348 last_status_ = ReadFilteredData(next_buffer->data(), &next_size); |
325 if (FILTER_ERROR != last_status_) | 349 if (FILTER_ERROR != last_status_) |
326 next_filter_->FlushStreamBuffer(next_size); | 350 next_filter_->FlushStreamBuffer(next_size); |
327 } | 351 } |
328 | 352 |
329 | 353 |
330 bool Filter::FlushStreamBuffer(int stream_data_len) { | 354 bool Filter::FlushStreamBuffer(int stream_data_len) { |
355 DCHECK(stream_data_len <= stream_buffer_size_); | |
331 if (stream_data_len <= 0 || stream_data_len > stream_buffer_size_) | 356 if (stream_data_len <= 0 || stream_data_len > stream_buffer_size_) |
332 return false; | 357 return false; |
333 | 358 |
334 // bail out if there are more data in the stream buffer to be filtered. | 359 DCHECK(stream_buffer()); |
360 // Bail out if there is more data in the stream buffer to be filtered. | |
335 if (!stream_buffer() || stream_data_len_) | 361 if (!stream_buffer() || stream_data_len_) |
336 return false; | 362 return false; |
337 | 363 |
338 next_stream_data_ = stream_buffer()->data(); | 364 next_stream_data_ = stream_buffer()->data(); |
339 stream_data_len_ = stream_data_len; | 365 stream_data_len_ = stream_data_len; |
340 return true; | 366 return true; |
341 } | 367 } |
342 | 368 |
343 void Filter::SetURL(const GURL& url) { | 369 void Filter::SetURL(const GURL& url) { |
344 url_ = url; | 370 url_ = url; |
345 if (next_filter_.get()) | 371 if (next_filter_.get()) |
346 next_filter_->SetURL(url); | 372 next_filter_->SetURL(url); |
347 } | 373 } |
348 | 374 |
349 void Filter::SetMimeType(const std::string& mime_type) { | 375 void Filter::SetMimeType(const std::string& mime_type) { |
350 mime_type_ = mime_type; | 376 mime_type_ = mime_type; |
351 if (next_filter_.get()) | 377 if (next_filter_.get()) |
352 next_filter_->SetMimeType(mime_type); | 378 next_filter_->SetMimeType(mime_type); |
353 } | 379 } |
354 | 380 |
355 void Filter::SetConnectTime(const base::Time& time, bool was_cached) { | 381 void Filter::SetConnectTime(const base::Time& time, bool was_cached) { |
356 connect_time_ = time; | 382 connect_time_ = time; |
357 was_cached_ = was_cached; | 383 was_cached_ = was_cached; |
358 if (next_filter_.get()) | 384 if (next_filter_.get()) |
359 next_filter_->SetConnectTime(time, was_cached_); | 385 next_filter_->SetConnectTime(time, was_cached_); |
360 } | 386 } |
OLD | NEW |