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