OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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/filter/sdch_filter.h" | 5 #include "net/filter/sdch_filter.h" |
6 | 6 |
7 #include <ctype.h> | 7 #include <ctype.h> |
8 #include <limits.h> | 8 #include <limits.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
11 | 11 |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
14 #include "net/base/sdch_manager.h" | 14 #include "net/base/sdch_manager.h" |
| 15 #include "net/url_request/url_request_context.h" |
15 | 16 |
16 #include "sdch/open-vcdiff/src/google/vcdecoder.h" | 17 #include "sdch/open-vcdiff/src/google/vcdecoder.h" |
17 | 18 |
18 namespace net { | 19 namespace net { |
19 | 20 |
20 SdchFilter::SdchFilter(const FilterContext& filter_context) | 21 SdchFilter::SdchFilter(const FilterContext& filter_context) |
21 : filter_context_(filter_context), | 22 : filter_context_(filter_context), |
22 decoding_status_(DECODING_UNINITIALIZED), | 23 decoding_status_(DECODING_UNINITIALIZED), |
23 dictionary_hash_(), | 24 dictionary_hash_(), |
24 dictionary_hash_is_plausible_(false), | 25 dictionary_hash_is_plausible_(false), |
25 dictionary_(NULL), | 26 dictionary_(NULL), |
| 27 url_request_context_(filter_context.GetURLRequestContext()), |
26 dest_buffer_excess_(), | 28 dest_buffer_excess_(), |
27 dest_buffer_excess_index_(0), | 29 dest_buffer_excess_index_(0), |
28 source_bytes_(0), | 30 source_bytes_(0), |
29 output_bytes_(0), | 31 output_bytes_(0), |
30 possible_pass_through_(false) { | 32 possible_pass_through_(false) { |
31 bool success = filter_context.GetMimeType(&mime_type_); | 33 bool success = filter_context.GetMimeType(&mime_type_); |
32 DCHECK(success); | 34 DCHECK(success); |
33 success = filter_context.GetURL(&url_); | 35 success = filter_context.GetURL(&url_); |
34 DCHECK(success); | 36 DCHECK(success); |
| 37 DCHECK(url_request_context_->sdch_manager()); |
35 } | 38 } |
36 | 39 |
37 SdchFilter::~SdchFilter() { | 40 SdchFilter::~SdchFilter() { |
38 // All code here is for gathering stats, and can be removed when SDCH is | 41 // All code here is for gathering stats, and can be removed when SDCH is |
39 // considered stable. | 42 // considered stable. |
40 | 43 |
41 static int filter_use_count = 0; | 44 static int filter_use_count = 0; |
42 ++filter_use_count; | 45 ++filter_use_count; |
43 if (META_REFRESH_RECOVERY == decoding_status_) { | 46 if (META_REFRESH_RECOVERY == decoding_status_) { |
44 UMA_HISTOGRAM_COUNTS("Sdch3.FilterUseBeforeDisabling", filter_use_count); | 47 UMA_HISTOGRAM_COUNTS("Sdch3.FilterUseBeforeDisabling", filter_use_count); |
45 } | 48 } |
46 | 49 |
47 if (vcdiff_streaming_decoder_.get()) { | 50 if (vcdiff_streaming_decoder_.get()) { |
48 if (!vcdiff_streaming_decoder_->FinishDecoding()) { | 51 if (!vcdiff_streaming_decoder_->FinishDecoding()) { |
49 decoding_status_ = DECODING_ERROR; | 52 decoding_status_ = DECODING_ERROR; |
50 SdchManager::SdchErrorRecovery(SdchManager::INCOMPLETE_SDCH_CONTENT); | 53 SdchManager::SdchErrorRecovery(SdchManager::INCOMPLETE_SDCH_CONTENT); |
51 // Make it possible for the user to hit reload, and get non-sdch content. | 54 // Make it possible for the user to hit reload, and get non-sdch content. |
52 // Note this will "wear off" quickly enough, and is just meant to assure | 55 // Note this will "wear off" quickly enough, and is just meant to assure |
53 // in some rare case that the user is not stuck. | 56 // in some rare case that the user is not stuck. |
54 SdchManager::BlacklistDomain(url_); | 57 url_request_context_->sdch_manager()->BlacklistDomain( |
| 58 url_); |
55 UMA_HISTOGRAM_COUNTS("Sdch3.PartialBytesIn", | 59 UMA_HISTOGRAM_COUNTS("Sdch3.PartialBytesIn", |
56 static_cast<int>(filter_context_.GetByteReadCount())); | 60 static_cast<int>(filter_context_.GetByteReadCount())); |
57 UMA_HISTOGRAM_COUNTS("Sdch3.PartialVcdiffIn", source_bytes_); | 61 UMA_HISTOGRAM_COUNTS("Sdch3.PartialVcdiffIn", source_bytes_); |
58 UMA_HISTOGRAM_COUNTS("Sdch3.PartialVcdiffOut", output_bytes_); | 62 UMA_HISTOGRAM_COUNTS("Sdch3.PartialVcdiffOut", output_bytes_); |
59 } | 63 } |
60 } | 64 } |
61 | 65 |
62 if (!dest_buffer_excess_.empty()) { | 66 if (!dest_buffer_excess_.empty()) { |
63 // Filter chaining error, or premature teardown. | 67 // Filter chaining error, or premature teardown. |
64 SdchManager::SdchErrorRecovery(SdchManager::UNFLUSHED_CONTENT); | 68 SdchManager::SdchErrorRecovery(SdchManager::UNFLUSHED_CONTENT); |
(...skipping 16 matching lines...) Expand all Loading... |
81 case DECODING_IN_PROGRESS: { | 85 case DECODING_IN_PROGRESS: { |
82 if (output_bytes_) | 86 if (output_bytes_) |
83 UMA_HISTOGRAM_PERCENTAGE("Sdch3.Network_Decode_Ratio_a", | 87 UMA_HISTOGRAM_PERCENTAGE("Sdch3.Network_Decode_Ratio_a", |
84 static_cast<int>( | 88 static_cast<int>( |
85 (filter_context_.GetByteReadCount() * 100) / output_bytes_)); | 89 (filter_context_.GetByteReadCount() * 100) / output_bytes_)); |
86 UMA_HISTOGRAM_COUNTS("Sdch3.Network_Decode_Bytes_VcdiffOut_a", | 90 UMA_HISTOGRAM_COUNTS("Sdch3.Network_Decode_Bytes_VcdiffOut_a", |
87 output_bytes_); | 91 output_bytes_); |
88 filter_context_.RecordPacketStats(FilterContext::SDCH_DECODE); | 92 filter_context_.RecordPacketStats(FilterContext::SDCH_DECODE); |
89 | 93 |
90 // Allow latency experiments to proceed. | 94 // Allow latency experiments to proceed. |
91 SdchManager::Global()->SetAllowLatencyExperiment(url_, true); | 95 url_request_context_->sdch_manager()->SetAllowLatencyExperiment( |
| 96 url_, true); |
92 return; | 97 return; |
93 } | 98 } |
94 case PASS_THROUGH: { | 99 case PASS_THROUGH: { |
95 filter_context_.RecordPacketStats(FilterContext::SDCH_PASSTHROUGH); | 100 filter_context_.RecordPacketStats(FilterContext::SDCH_PASSTHROUGH); |
96 return; | 101 return; |
97 } | 102 } |
98 case DECODING_UNINITIALIZED: { | 103 case DECODING_UNINITIALIZED: { |
99 SdchManager::SdchErrorRecovery(SdchManager::UNINITIALIZED); | 104 SdchManager::SdchErrorRecovery(SdchManager::UNINITIALIZED); |
100 return; | 105 return; |
101 } | 106 } |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 } else { | 211 } else { |
207 // One of the first 9 bytes precluded consideration as a hash. | 212 // One of the first 9 bytes precluded consideration as a hash. |
208 // This can't be an SDCH payload, even though the server said it was. | 213 // This can't be an SDCH payload, even though the server said it was. |
209 // This is a major error, as the server or proxy tagged this SDCH even | 214 // This is a major error, as the server or proxy tagged this SDCH even |
210 // though it is not! | 215 // though it is not! |
211 // Meta-refresh won't help, as we didn't advertise an SDCH dictionary!! | 216 // Meta-refresh won't help, as we didn't advertise an SDCH dictionary!! |
212 // Worse yet, meta-refresh could lead to an infinite refresh loop. | 217 // Worse yet, meta-refresh could lead to an infinite refresh loop. |
213 SdchManager::SdchErrorRecovery(SdchManager::PASSING_THROUGH_NON_SDCH); | 218 SdchManager::SdchErrorRecovery(SdchManager::PASSING_THROUGH_NON_SDCH); |
214 decoding_status_ = PASS_THROUGH; | 219 decoding_status_ = PASS_THROUGH; |
215 // ... but further back-off on advertising SDCH support. | 220 // ... but further back-off on advertising SDCH support. |
216 SdchManager::BlacklistDomain(url_); | 221 url_request_context_->sdch_manager()->BlacklistDomain(url_); |
217 } | 222 } |
218 | 223 |
219 if (decoding_status_ == PASS_THROUGH) { | 224 if (decoding_status_ == PASS_THROUGH) { |
220 dest_buffer_excess_ = dictionary_hash_; // Send what we scanned. | 225 dest_buffer_excess_ = dictionary_hash_; // Send what we scanned. |
221 } else { | 226 } else { |
222 // This is where we try to do the expensive meta-refresh. | 227 // This is where we try to do the expensive meta-refresh. |
223 if (std::string::npos == mime_type_.find("text/html")) { | 228 if (std::string::npos == mime_type_.find("text/html")) { |
224 // Since we can't do a meta-refresh (along with an exponential | 229 // Since we can't do a meta-refresh (along with an exponential |
225 // backoff), we'll just make sure this NEVER happens again. | 230 // backoff), we'll just make sure this NEVER happens again. |
226 SdchManager::BlacklistDomainForever(url_); | 231 url_request_context_->sdch_manager()->BlacklistDomainForever(url_); |
227 if (filter_context_.IsCachedContent()) | 232 if (filter_context_.IsCachedContent()) |
228 SdchManager::SdchErrorRecovery( | 233 SdchManager::SdchErrorRecovery( |
229 SdchManager::CACHED_META_REFRESH_UNSUPPORTED); | 234 SdchManager::CACHED_META_REFRESH_UNSUPPORTED); |
230 else | 235 else |
231 SdchManager::SdchErrorRecovery( | 236 SdchManager::SdchErrorRecovery( |
232 SdchManager::META_REFRESH_UNSUPPORTED); | 237 SdchManager::META_REFRESH_UNSUPPORTED); |
233 return FILTER_ERROR; | 238 return FILTER_ERROR; |
234 } | 239 } |
235 // HTML content means we can issue a meta-refresh, and get the content | 240 // HTML content means we can issue a meta-refresh, and get the content |
236 // again, perhaps without SDCH (to be safe). | 241 // again, perhaps without SDCH (to be safe). |
237 if (filter_context_.IsCachedContent()) { | 242 if (filter_context_.IsCachedContent()) { |
238 // Cached content is probably a startup tab, so we'll just get fresh | 243 // Cached content is probably a startup tab, so we'll just get fresh |
239 // content and try again, without disabling sdch. | 244 // content and try again, without disabling sdch. |
240 SdchManager::SdchErrorRecovery( | 245 SdchManager::SdchErrorRecovery( |
241 SdchManager::META_REFRESH_CACHED_RECOVERY); | 246 SdchManager::META_REFRESH_CACHED_RECOVERY); |
242 } else { | 247 } else { |
243 // Since it wasn't in the cache, we definately need at least some | 248 // Since it wasn't in the cache, we definately need at least some |
244 // period of blacklisting to get the correct content. | 249 // period of blacklisting to get the correct content. |
245 SdchManager::BlacklistDomain(url_); | 250 url_request_context_->sdch_manager()->BlacklistDomain(url_); |
246 SdchManager::SdchErrorRecovery(SdchManager::META_REFRESH_RECOVERY); | 251 SdchManager::SdchErrorRecovery(SdchManager::META_REFRESH_RECOVERY); |
247 } | 252 } |
248 decoding_status_ = META_REFRESH_RECOVERY; | 253 decoding_status_ = META_REFRESH_RECOVERY; |
249 // Issue a meta redirect with SDCH disabled. | 254 // Issue a meta redirect with SDCH disabled. |
250 dest_buffer_excess_ = kDecompressionErrorHtml; | 255 dest_buffer_excess_ = kDecompressionErrorHtml; |
251 } | 256 } |
252 } else { | 257 } else { |
253 DCHECK_EQ(DECODING_IN_PROGRESS, decoding_status_); | 258 DCHECK_EQ(DECODING_IN_PROGRESS, decoding_status_); |
254 } | 259 } |
255 } | 260 } |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 DCHECK_LE(0, stream_data_len_); | 333 DCHECK_LE(0, stream_data_len_); |
329 if (stream_data_len_ > 0) | 334 if (stream_data_len_ > 0) |
330 next_stream_data_ += bytes_needed; | 335 next_stream_data_ += bytes_needed; |
331 else | 336 else |
332 next_stream_data_ = NULL; | 337 next_stream_data_ = NULL; |
333 | 338 |
334 DCHECK(!dictionary_.get()); | 339 DCHECK(!dictionary_.get()); |
335 dictionary_hash_is_plausible_ = true; // Assume plausible, but check. | 340 dictionary_hash_is_plausible_ = true; // Assume plausible, but check. |
336 | 341 |
337 SdchManager::Dictionary* dictionary = NULL; | 342 SdchManager::Dictionary* dictionary = NULL; |
338 if ('\0' == dictionary_hash_[kServerIdLength - 1]) | 343 if ('\0' == dictionary_hash_[kServerIdLength - 1]) { |
339 SdchManager::Global()->GetVcdiffDictionary(std::string(dictionary_hash_, 0, | 344 SdchManager* manager(url_request_context_->sdch_manager()); |
340 kServerIdLength - 1), | 345 manager->GetVcdiffDictionary( |
341 url_, &dictionary); | 346 std::string(dictionary_hash_, 0, kServerIdLength - 1), |
342 else | 347 url_, &dictionary); |
| 348 } else { |
343 dictionary_hash_is_plausible_ = false; | 349 dictionary_hash_is_plausible_ = false; |
| 350 } |
344 | 351 |
345 if (!dictionary) { | 352 if (!dictionary) { |
346 DCHECK(dictionary_hash_.size() == kServerIdLength); | 353 DCHECK(dictionary_hash_.size() == kServerIdLength); |
347 // Since dictionary was not found, check to see if hash was even plausible. | 354 // Since dictionary was not found, check to see if hash was even plausible. |
348 for (size_t i = 0; i < kServerIdLength - 1; ++i) { | 355 for (size_t i = 0; i < kServerIdLength - 1; ++i) { |
349 char base64_char = dictionary_hash_[i]; | 356 char base64_char = dictionary_hash_[i]; |
350 if (!isalnum(base64_char) && '-' != base64_char && '_' != base64_char) { | 357 if (!isalnum(base64_char) && '-' != base64_char && '_' != base64_char) { |
351 dictionary_hash_is_plausible_ = false; | 358 dictionary_hash_is_plausible_ = false; |
352 break; | 359 break; |
353 } | 360 } |
(...skipping 26 matching lines...) Expand all Loading... |
380 dest_buffer_excess_index_ += amount; | 387 dest_buffer_excess_index_ += amount; |
381 if (dest_buffer_excess_.size() <= dest_buffer_excess_index_) { | 388 if (dest_buffer_excess_.size() <= dest_buffer_excess_index_) { |
382 DCHECK(dest_buffer_excess_.size() == dest_buffer_excess_index_); | 389 DCHECK(dest_buffer_excess_.size() == dest_buffer_excess_index_); |
383 dest_buffer_excess_.clear(); | 390 dest_buffer_excess_.clear(); |
384 dest_buffer_excess_index_ = 0; | 391 dest_buffer_excess_index_ = 0; |
385 } | 392 } |
386 return amount; | 393 return amount; |
387 } | 394 } |
388 | 395 |
389 } // namespace net | 396 } // namespace net |
OLD | NEW |