Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/sdch_manager.h" | 5 #include "net/base/sdch_manager.h" |
| 6 | 6 |
| 7 #include "base/base64.h" | 7 #include "base/base64.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| 11 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
| 12 #include "base/time/default_clock.h" | |
| 12 #include "base/values.h" | 13 #include "base/values.h" |
| 13 #include "crypto/sha2.h" | 14 #include "crypto/sha2.h" |
| 14 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | 15 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
| 15 #include "net/base/sdch_observer.h" | 16 #include "net/base/sdch_observer.h" |
| 16 #include "net/url_request/url_request_http_job.h" | 17 #include "net/url_request/url_request_http_job.h" |
| 17 | 18 |
| 18 namespace { | 19 namespace { |
| 19 | 20 |
| 20 void StripTrailingDot(GURL* gurl) { | 21 void StripTrailingDot(GURL* gurl) { |
| 21 std::string host(gurl->host()); | 22 std::string host(gurl->host()); |
| 22 | 23 |
| 23 if (host.empty()) | 24 if (host.empty()) |
| 24 return; | 25 return; |
| 25 | 26 |
| 26 if (*host.rbegin() != '.') | 27 if (*host.rbegin() != '.') |
| 27 return; | 28 return; |
| 28 | 29 |
| 29 host.resize(host.size() - 1); | 30 host.resize(host.size() - 1); |
| 30 | 31 |
| 31 GURL::Replacements replacements; | 32 GURL::Replacements replacements; |
| 32 replacements.SetHostStr(host); | 33 replacements.SetHostStr(host); |
| 33 *gurl = gurl->ReplaceComponents(replacements); | 34 *gurl = gurl->ReplaceComponents(replacements); |
| 34 return; | 35 return; |
| 35 } | 36 } |
| 36 | 37 |
| 37 } // namespace | 38 } // namespace |
| 38 | 39 |
| 39 namespace net { | 40 namespace net { |
| 40 | 41 |
| 41 //------------------------------------------------------------------------------ | |
| 42 // static | |
| 43 | |
| 44 // Adjust SDCH limits downwards for mobile. | 42 // Adjust SDCH limits downwards for mobile. |
| 45 #if defined(OS_ANDROID) || defined(OS_IOS) | 43 #if defined(OS_ANDROID) || defined(OS_IOS) |
| 46 // static | 44 // static |
| 47 const size_t SdchManager::kMaxDictionaryCount = 1; | 45 const size_t SdchManager::kMaxDictionaryCount = 1; |
| 48 const size_t SdchManager::kMaxDictionarySize = 500 * 1000; | 46 const size_t SdchManager::kMaxDictionarySize = 500 * 1000; |
| 49 #else | 47 #else |
| 50 // static | 48 // static |
| 51 const size_t SdchManager::kMaxDictionaryCount = 20; | 49 const size_t SdchManager::kMaxDictionaryCount = 20; |
| 52 const size_t SdchManager::kMaxDictionarySize = 1000 * 1000; | 50 const size_t SdchManager::kMaxDictionarySize = 1000 * 1000; |
| 53 #endif | 51 #endif |
| 54 | 52 |
| 55 // static | 53 // static |
| 56 bool SdchManager::g_sdch_enabled_ = true; | 54 bool SdchManager::g_sdch_enabled_ = true; |
| 57 | 55 |
| 58 // static | 56 // static |
| 59 bool SdchManager::g_secure_scheme_supported_ = true; | 57 bool SdchManager::g_secure_scheme_supported_ = true; |
| 60 | 58 |
| 61 //------------------------------------------------------------------------------ | |
| 62 SdchManager::Dictionary::Dictionary(const std::string& dictionary_text, | 59 SdchManager::Dictionary::Dictionary(const std::string& dictionary_text, |
| 63 size_t offset, | 60 size_t offset, |
| 64 const std::string& client_hash, | 61 const std::string& client_hash, |
| 65 const GURL& gurl, | 62 const GURL& gurl, |
| 66 const std::string& domain, | 63 const std::string& domain, |
| 67 const std::string& path, | 64 const std::string& path, |
| 68 const base::Time& expiration, | 65 const base::Time& expiration, |
| 69 const std::set<int>& ports) | 66 const std::set<int>& ports) |
| 70 : text_(dictionary_text, offset), | 67 : text_(dictionary_text, offset), |
| 71 client_hash_(client_hash), | 68 client_hash_(client_hash), |
| 72 url_(gurl), | 69 url_(gurl), |
| 73 domain_(domain), | 70 domain_(domain), |
| 74 path_(path), | 71 path_(path), |
| 75 expiration_(expiration), | 72 expiration_(expiration), |
| 76 ports_(ports) { | 73 ports_(ports), |
| 74 clock_(new base::DefaultClock) { | |
| 77 } | 75 } |
| 78 | 76 |
| 79 SdchManager::Dictionary::~Dictionary() { | 77 SdchManager::Dictionary::Dictionary(const SdchManager::Dictionary& rhs) |
| 80 } | 78 : text_(rhs.text_), |
| 79 client_hash_(rhs.client_hash_), | |
| 80 url_(rhs.url_), | |
| 81 domain_(rhs.domain_), | |
| 82 path_(rhs.path_), | |
| 83 expiration_(rhs.expiration_), | |
| 84 ports_(rhs.ports_), | |
| 85 clock_(new base::DefaultClock) {} | |
| 81 | 86 |
| 82 SdchProblemCode SdchManager::Dictionary::CanAdvertise( | 87 SdchManager::Dictionary::~Dictionary() {} |
| 83 const GURL& target_url) const { | |
| 84 /* The specific rules of when a dictionary should be advertised in an | |
| 85 Avail-Dictionary header are modeled after the rules for cookie scoping. The | |
| 86 terms "domain-match" and "pathmatch" are defined in RFC 2965 [6]. A | |
| 87 dictionary may be advertised in the Avail-Dictionaries header exactly when | |
| 88 all of the following are true: | |
| 89 1. The server's effective host name domain-matches the Domain attribute of | |
| 90 the dictionary. | |
| 91 2. If the dictionary has a Port attribute, the request port is one of the | |
| 92 ports listed in the Port attribute. | |
| 93 3. The request URI path-matches the path header of the dictionary. | |
| 94 4. The request is not an HTTPS request. | |
| 95 We can override (ignore) item (4) only when we have explicitly enabled | |
| 96 HTTPS support AND the dictionary acquisition scheme matches the target | |
| 97 url scheme. | |
| 98 */ | |
| 99 if (!DomainMatch(target_url, domain_)) | |
| 100 return SDCH_DICTIONARY_FOUND_HAS_WRONG_DOMAIN; | |
| 101 if (!ports_.empty() && 0 == ports_.count(target_url.EffectiveIntPort())) | |
| 102 return SDCH_DICTIONARY_FOUND_HAS_WRONG_PORT_LIST; | |
| 103 if (path_.size() && !PathMatch(target_url.path(), path_)) | |
| 104 return SDCH_DICTIONARY_FOUND_HAS_WRONG_PATH; | |
| 105 if (!SdchManager::secure_scheme_supported() && target_url.SchemeIsSecure()) | |
| 106 return SDCH_DICTIONARY_FOUND_HAS_WRONG_SCHEME; | |
| 107 if (target_url.SchemeIsSecure() != url_.SchemeIsSecure()) | |
| 108 return SDCH_DICTIONARY_FOUND_HAS_WRONG_SCHEME; | |
| 109 if (base::Time::Now() > expiration_) | |
| 110 return SDCH_DICTIONARY_FOUND_EXPIRED; | |
| 111 return SDCH_OK; | |
| 112 } | |
| 113 | 88 |
| 114 //------------------------------------------------------------------------------ | |
| 115 // Security functions restricting loads and use of dictionaries. | 89 // Security functions restricting loads and use of dictionaries. |
| 116 | 90 |
| 117 // static | 91 // static |
| 118 SdchProblemCode SdchManager::Dictionary::CanSet(const std::string& domain, | 92 SdchProblemCode SdchManager::Dictionary::CanSet(const std::string& domain, |
| 119 const std::string& path, | 93 const std::string& path, |
| 120 const std::set<int>& ports, | 94 const std::set<int>& ports, |
| 121 const GURL& dictionary_url) { | 95 const GURL& dictionary_url) { |
| 122 /* | 96 /* |
| 123 A dictionary is invalid and must not be stored if any of the following are | 97 A dictionary is invalid and must not be stored if any of the following are |
| 124 true: | 98 true: |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 161 } | 135 } |
| 162 } | 136 } |
| 163 | 137 |
| 164 if (!ports.empty() && 0 == ports.count(dictionary_url.EffectiveIntPort())) | 138 if (!ports.empty() && 0 == ports.count(dictionary_url.EffectiveIntPort())) |
| 165 return SDCH_DICTIONARY_PORT_NOT_MATCHING_SOURCE_URL; | 139 return SDCH_DICTIONARY_PORT_NOT_MATCHING_SOURCE_URL; |
| 166 | 140 |
| 167 return SDCH_OK; | 141 return SDCH_OK; |
| 168 } | 142 } |
| 169 | 143 |
| 170 SdchProblemCode SdchManager::Dictionary::CanUse( | 144 SdchProblemCode SdchManager::Dictionary::CanUse( |
| 171 const GURL& referring_url) const { | 145 const GURL& target_url) const { |
| 172 /* | 146 /* |
| 173 1. The request URL's host name domain-matches the Domain attribute of the | 147 1. The request URL's host name domain-matches the Domain attribute of the |
| 174 dictionary. | 148 dictionary. |
| 175 2. If the dictionary has a Port attribute, the request port is one of the | 149 2. If the dictionary has a Port attribute, the request port is one of the |
| 176 ports listed in the Port attribute. | 150 ports listed in the Port attribute. |
| 177 3. The request URL path-matches the path attribute of the dictionary. | 151 3. The request URL path-matches the path attribute of the dictionary. |
| 178 4. The request is not an HTTPS request. | 152 4. The request is not an HTTPS request. |
| 179 We can override (ignore) item (4) only when we have explicitly enabled | 153 We can override (ignore) item (4) only when we have explicitly enabled |
| 180 HTTPS support AND the dictionary acquisition scheme matches the target | 154 HTTPS support AND the dictionary acquisition scheme matches the target |
| 181 url scheme. | 155 url scheme. |
| 182 */ | 156 */ |
| 183 if (!DomainMatch(referring_url, domain_)) | 157 if (!DomainMatch(target_url, domain_)) |
| 184 return SDCH_DICTIONARY_FOUND_HAS_WRONG_DOMAIN; | 158 return SDCH_DICTIONARY_FOUND_HAS_WRONG_DOMAIN; |
| 185 | 159 |
| 186 if (!ports_.empty() && 0 == ports_.count(referring_url.EffectiveIntPort())) | 160 if (!ports_.empty() && 0 == ports_.count(target_url.EffectiveIntPort())) |
| 187 return SDCH_DICTIONARY_FOUND_HAS_WRONG_PORT_LIST; | 161 return SDCH_DICTIONARY_FOUND_HAS_WRONG_PORT_LIST; |
| 188 | 162 |
| 189 if (path_.size() && !PathMatch(referring_url.path(), path_)) | 163 if (path_.size() && !PathMatch(target_url.path(), path_)) |
| 190 return SDCH_DICTIONARY_FOUND_HAS_WRONG_PATH; | 164 return SDCH_DICTIONARY_FOUND_HAS_WRONG_PATH; |
| 191 | 165 |
| 192 if (!SdchManager::secure_scheme_supported() && referring_url.SchemeIsSecure()) | 166 if (!SdchManager::secure_scheme_supported() && target_url.SchemeIsSecure()) |
| 193 return SDCH_DICTIONARY_FOUND_HAS_WRONG_SCHEME; | 167 return SDCH_DICTIONARY_FOUND_HAS_WRONG_SCHEME; |
| 194 | 168 |
| 195 if (referring_url.SchemeIsSecure() != url_.SchemeIsSecure()) | 169 if (target_url.SchemeIsSecure() != url_.SchemeIsSecure()) |
| 196 return SDCH_DICTIONARY_FOUND_HAS_WRONG_SCHEME; | 170 return SDCH_DICTIONARY_FOUND_HAS_WRONG_SCHEME; |
| 197 | 171 |
| 198 // TODO(jar): Remove overly restrictive failsafe test (added per security | 172 // TODO(jar): Remove overly restrictive failsafe test (added per security |
| 199 // review) when we have a need to be more general. | 173 // review) when we have a need to be more general. |
| 200 if (!referring_url.SchemeIsHTTPOrHTTPS()) | 174 if (!target_url.SchemeIsHTTPOrHTTPS()) |
| 201 return SDCH_ATTEMPT_TO_DECODE_NON_HTTP_DATA; | 175 return SDCH_ATTEMPT_TO_DECODE_NON_HTTP_DATA; |
| 202 | 176 |
| 203 return SDCH_OK; | 177 return SDCH_OK; |
| 204 } | 178 } |
| 205 | 179 |
| 206 // static | 180 // static |
| 207 bool SdchManager::Dictionary::PathMatch(const std::string& path, | 181 bool SdchManager::Dictionary::PathMatch(const std::string& path, |
| 208 const std::string& restriction) { | 182 const std::string& restriction) { |
| 209 /* Must be either: | 183 /* Must be either: |
| 210 1. P2 is equal to P1 | 184 1. P2 is equal to P1 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 221 return restriction[prefix_length - 1] == '/' || path[prefix_length] == '/'; | 195 return restriction[prefix_length - 1] == '/' || path[prefix_length] == '/'; |
| 222 } | 196 } |
| 223 | 197 |
| 224 // static | 198 // static |
| 225 bool SdchManager::Dictionary::DomainMatch(const GURL& gurl, | 199 bool SdchManager::Dictionary::DomainMatch(const GURL& gurl, |
| 226 const std::string& restriction) { | 200 const std::string& restriction) { |
| 227 // TODO(jar): This is not precisely a domain match definition. | 201 // TODO(jar): This is not precisely a domain match definition. |
| 228 return gurl.DomainIs(restriction.data(), restriction.size()); | 202 return gurl.DomainIs(restriction.data(), restriction.size()); |
| 229 } | 203 } |
| 230 | 204 |
| 231 //------------------------------------------------------------------------------ | 205 bool SdchManager::Dictionary::Expired() const { |
| 206 return clock_->Now() > expiration_; | |
| 207 } | |
| 208 | |
| 209 void SdchManager::Dictionary::SetClockForTesting( | |
| 210 scoped_ptr<base::Clock> clock) { | |
| 211 clock_ = clock.Pass(); | |
| 212 } | |
| 213 | |
| 214 SdchManager::DictionaryWrapper::DictionaryWrapper( | |
| 215 scoped_ptr<SdchManager::Dictionary> dictionary) | |
| 216 : dictionary_(dictionary.Pass()) {} | |
| 217 | |
| 218 SdchManager::DictionaryWrapper::~DictionaryWrapper() {} | |
| 219 | |
| 220 SdchManager::DictionarySet::DictionarySet() {} | |
| 221 | |
| 222 SdchManager::DictionarySet::~DictionarySet() {} | |
| 223 | |
| 224 std::string SdchManager::DictionarySet::GetDictionaryClientHashList() const { | |
| 225 std::string result; | |
| 226 bool first = true; | |
| 227 for (const auto& entry: dictionaries_) { | |
| 228 if (!first) | |
| 229 result.append(","); | |
| 230 | |
| 231 result.append(entry.second->data.client_hash()); | |
| 232 first = false; | |
| 233 } | |
| 234 return result; | |
| 235 } | |
| 236 | |
| 237 const SdchManager::Dictionary* SdchManager::DictionarySet::Dictionary( | |
| 238 const std::string& hash) const { | |
| 239 auto it = dictionaries_.find(hash); | |
| 240 if (it == dictionaries_.end()) | |
| 241 return NULL; | |
| 242 | |
| 243 return &it->second->data; | |
| 244 } | |
| 245 | |
| 246 bool SdchManager::DictionarySet::Empty() const { | |
| 247 return dictionaries_.empty(); | |
| 248 } | |
| 249 | |
| 250 void SdchManager::DictionarySet::AddDictionary( | |
| 251 const std::string& server_hash, | |
| 252 scoped_refptr<base::RefCountedData<SdchManager::Dictionary>> dictionary) { | |
| 253 DCHECK(dictionaries_.end() == dictionaries_.find(server_hash)); | |
| 254 | |
| 255 dictionaries_[server_hash] = dictionary; | |
| 256 } | |
| 257 | |
| 232 SdchManager::SdchManager() { | 258 SdchManager::SdchManager() { |
| 233 DCHECK(thread_checker_.CalledOnValidThread()); | 259 DCHECK(thread_checker_.CalledOnValidThread()); |
| 234 } | 260 } |
| 235 | 261 |
| 236 SdchManager::~SdchManager() { | 262 SdchManager::~SdchManager() { |
| 237 DCHECK(thread_checker_.CalledOnValidThread()); | 263 DCHECK(thread_checker_.CalledOnValidThread()); |
| 238 while (!dictionaries_.empty()) { | 264 while (!dictionaries_.empty()) { |
| 239 DictionaryMap::iterator it = dictionaries_.begin(); | 265 auto it = dictionaries_.begin(); |
| 240 dictionaries_.erase(it->first); | 266 dictionaries_.erase(it->first); |
| 241 } | 267 } |
| 242 } | 268 } |
| 243 | 269 |
| 244 void SdchManager::ClearData() { | 270 void SdchManager::ClearData() { |
| 245 blacklisted_domains_.clear(); | 271 blacklisted_domains_.clear(); |
| 246 allow_latency_experiment_.clear(); | 272 allow_latency_experiment_.clear(); |
| 247 | 273 |
| 248 // Note that this may result in not having dictionaries we've advertised | 274 // Note that this may result in not having dictionaries we've advertised |
| 249 // for incoming responses. The window is relatively small (as ClearData() | 275 // for incoming responses. The window is relatively small (as ClearData() |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 396 return SDCH_DICTIONARY_SELECTED_FOR_SSL; | 422 return SDCH_DICTIONARY_SELECTED_FOR_SSL; |
| 397 | 423 |
| 398 // TODO(jar): Remove this failsafe conservative hack which is more restrictive | 424 // TODO(jar): Remove this failsafe conservative hack which is more restrictive |
| 399 // than current SDCH spec when needed, and justified by security audit. | 425 // than current SDCH spec when needed, and justified by security audit. |
| 400 if (!referring_url.SchemeIsHTTPOrHTTPS()) | 426 if (!referring_url.SchemeIsHTTPOrHTTPS()) |
| 401 return SDCH_DICTIONARY_SELECTED_FROM_NON_HTTP; | 427 return SDCH_DICTIONARY_SELECTED_FROM_NON_HTTP; |
| 402 | 428 |
| 403 return SDCH_OK; | 429 return SDCH_OK; |
| 404 } | 430 } |
| 405 | 431 |
| 406 SdchProblemCode SdchManager::GetVcdiffDictionary( | 432 scoped_ptr<SdchManager::DictionarySet> |
| 407 const std::string& server_hash, | 433 SdchManager::GetDictionarySet(const GURL& target_url) { |
| 408 const GURL& referring_url, | 434 if (IsInSupportedDomain(target_url) != SDCH_OK) |
| 409 scoped_refptr<Dictionary>* dictionary) { | 435 return NULL; |
| 410 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 411 *dictionary = NULL; | |
| 412 DictionaryMap::iterator it = dictionaries_.find(server_hash); | |
| 413 if (it == dictionaries_.end()) | |
| 414 return SDCH_DICTIONARY_HASH_NOT_FOUND; | |
| 415 | 436 |
| 416 scoped_refptr<Dictionary> matching_dictionary = it->second; | 437 int count = 0; |
| 438 scoped_ptr<SdchManager::DictionarySet> result(new DictionarySet); | |
| 439 for (const auto& entry: dictionaries_) { | |
| 440 if (entry.second->data.CanUse(target_url) != SDCH_OK) | |
| 441 continue; | |
| 442 if (entry.second->data.Expired()) | |
| 443 continue; | |
| 444 ++count; | |
| 445 result->AddDictionary(entry.first, entry.second); | |
| 446 } | |
| 417 | 447 |
| 418 SdchProblemCode rv = IsInSupportedDomain(referring_url); | 448 if (count == 0) |
| 419 if (rv != SDCH_OK) | 449 return NULL; |
| 420 return rv; | |
| 421 | 450 |
| 422 rv = matching_dictionary->CanUse(referring_url); | 451 UMA_HISTOGRAM_COUNTS("Sdch3.Advertisement_Count", count); |
| 423 if (rv == SDCH_OK) | 452 |
| 424 *dictionary = matching_dictionary; | 453 return result.Pass(); |
| 425 return rv; | |
| 426 } | 454 } |
| 427 | 455 |
| 428 // TODO(jar): If we have evictions from the dictionaries_, then we need to | 456 scoped_ptr<SdchManager::DictionarySet> |
| 429 // change this interface to return a list of reference counted Dictionary | 457 SdchManager::GetDictionarySetByHash( |
| 430 // instances that can be used if/when a server specifies one. | 458 const GURL& target_url, |
| 431 void SdchManager::GetAvailDictionaryList(const GURL& target_url, | 459 const std::string& server_hash, |
| 432 std::string* list) { | 460 SdchProblemCode* problem_code) { |
| 433 DCHECK(thread_checker_.CalledOnValidThread()); | 461 scoped_ptr<SdchManager::DictionarySet> result; |
| 434 int count = 0; | |
| 435 for (DictionaryMap::iterator it = dictionaries_.begin(); | |
| 436 it != dictionaries_.end(); ++it) { | |
| 437 SdchProblemCode rv = IsInSupportedDomain(target_url); | |
| 438 if (rv != SDCH_OK) | |
| 439 continue; | |
| 440 | 462 |
| 441 if (it->second->CanAdvertise(target_url) != SDCH_OK) | 463 *problem_code = SDCH_DICTIONARY_HASH_NOT_FOUND; |
| 442 continue; | 464 auto it = dictionaries_.find(server_hash); |
|
Ryan Sleevi
2014/11/20 22:50:29
Should this be a const auto&? Doesn't seem like yo
Randy Smith (Not in Mondays)
2014/11/20 23:44:28
Done.
| |
| 443 ++count; | 465 if (it == dictionaries_.end()) |
| 444 if (!list->empty()) | 466 return result; |
| 445 list->append(","); | 467 |
| 446 list->append(it->second->client_hash()); | 468 *problem_code = it->second->data.CanUse(target_url); |
| 447 } | 469 if (*problem_code != SDCH_OK) |
| 448 // Watch to see if we have corrupt or numerous dictionaries. | 470 return result; |
| 449 if (count > 0) | 471 |
| 450 UMA_HISTOGRAM_COUNTS("Sdch3.Advertisement_Count", count); | 472 result.reset(new DictionarySet); |
| 473 result->AddDictionary(it->first, it->second); | |
| 474 return result; | |
| 451 } | 475 } |
| 452 | 476 |
| 453 // static | 477 // static |
| 454 void SdchManager::GenerateHash(const std::string& dictionary_text, | 478 void SdchManager::GenerateHash(const std::string& dictionary_text, |
| 455 std::string* client_hash, std::string* server_hash) { | 479 std::string* client_hash, std::string* server_hash) { |
| 456 char binary_hash[32]; | 480 char binary_hash[32]; |
| 457 crypto::SHA256HashString(dictionary_text, binary_hash, sizeof(binary_hash)); | 481 crypto::SHA256HashString(dictionary_text, binary_hash, sizeof(binary_hash)); |
| 458 | 482 |
| 459 std::string first_48_bits(&binary_hash[0], 6); | 483 std::string first_48_bits(&binary_hash[0], 6); |
| 460 std::string second_48_bits(&binary_hash[6], 6); | 484 std::string second_48_bits(&binary_hash[6], 6); |
| 461 UrlSafeBase64Encode(first_48_bits, client_hash); | 485 UrlSafeBase64Encode(first_48_bits, client_hash); |
| 462 UrlSafeBase64Encode(second_48_bits, server_hash); | 486 UrlSafeBase64Encode(second_48_bits, server_hash); |
| 463 | 487 |
| 464 DCHECK_EQ(server_hash->length(), 8u); | 488 DCHECK_EQ(server_hash->length(), 8u); |
| 465 DCHECK_EQ(client_hash->length(), 8u); | 489 DCHECK_EQ(client_hash->length(), 8u); |
| 466 } | 490 } |
| 467 | 491 |
| 468 //------------------------------------------------------------------------------ | |
| 469 // Methods for supporting latency experiments. | 492 // Methods for supporting latency experiments. |
| 470 | 493 |
| 471 bool SdchManager::AllowLatencyExperiment(const GURL& url) const { | 494 bool SdchManager::AllowLatencyExperiment(const GURL& url) const { |
| 472 DCHECK(thread_checker_.CalledOnValidThread()); | 495 DCHECK(thread_checker_.CalledOnValidThread()); |
| 473 return allow_latency_experiment_.end() != | 496 return allow_latency_experiment_.end() != |
| 474 allow_latency_experiment_.find(url.host()); | 497 allow_latency_experiment_.find(url.host()); |
| 475 } | 498 } |
| 476 | 499 |
| 477 void SdchManager::SetAllowLatencyExperiment(const GURL& url, bool enable) { | 500 void SdchManager::SetAllowLatencyExperiment(const GURL& url, bool enable) { |
| 478 DCHECK(thread_checker_.CalledOnValidThread()); | 501 DCHECK(thread_checker_.CalledOnValidThread()); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 580 // is probably not worth doing eviction handling. | 603 // is probably not worth doing eviction handling. |
| 581 if (kMaxDictionarySize < dictionary_text.size()) | 604 if (kMaxDictionarySize < dictionary_text.size()) |
| 582 return SDCH_DICTIONARY_IS_TOO_LARGE; | 605 return SDCH_DICTIONARY_IS_TOO_LARGE; |
| 583 | 606 |
| 584 if (kMaxDictionaryCount <= dictionaries_.size()) | 607 if (kMaxDictionaryCount <= dictionaries_.size()) |
| 585 return SDCH_DICTIONARY_COUNT_EXCEEDED; | 608 return SDCH_DICTIONARY_COUNT_EXCEEDED; |
| 586 | 609 |
| 587 UMA_HISTOGRAM_COUNTS("Sdch3.Dictionary size loaded", dictionary_text.size()); | 610 UMA_HISTOGRAM_COUNTS("Sdch3.Dictionary size loaded", dictionary_text.size()); |
| 588 DVLOG(1) << "Loaded dictionary with client hash " << client_hash | 611 DVLOG(1) << "Loaded dictionary with client hash " << client_hash |
| 589 << " and server hash " << server_hash; | 612 << " and server hash " << server_hash; |
| 590 Dictionary* dictionary = | 613 Dictionary dictionary(dictionary_text, header_end + 2, client_hash, |
| 591 new Dictionary(dictionary_text, header_end + 2, client_hash, | 614 dictionary_url_normalized, domain, path, expiration, |
| 592 dictionary_url_normalized, domain, | 615 ports); |
| 593 path, expiration, ports); | 616 dictionaries_[server_hash] = |
| 594 dictionaries_[server_hash] = dictionary; | 617 new base::RefCountedData<Dictionary>(dictionary); |
| 618 | |
| 595 return SDCH_OK; | 619 return SDCH_OK; |
| 596 } | 620 } |
| 597 | 621 |
| 598 // static | 622 // static |
| 623 scoped_ptr<SdchManager::DictionarySet> | |
| 624 SdchManager::CreateEmptyDictionarySetForTesting() { | |
| 625 return scoped_ptr<DictionarySet>(new DictionarySet).Pass(); | |
| 626 } | |
| 627 | |
| 628 // static | |
| 599 void SdchManager::UrlSafeBase64Encode(const std::string& input, | 629 void SdchManager::UrlSafeBase64Encode(const std::string& input, |
| 600 std::string* output) { | 630 std::string* output) { |
| 601 // Since this is only done during a dictionary load, and hashes are only 8 | 631 // Since this is only done during a dictionary load, and hashes are only 8 |
| 602 // characters, we just do the simple fixup, rather than rewriting the encoder. | 632 // characters, we just do the simple fixup, rather than rewriting the encoder. |
| 603 base::Base64Encode(input, output); | 633 base::Base64Encode(input, output); |
| 604 std::replace(output->begin(), output->end(), '+', '-'); | 634 std::replace(output->begin(), output->end(), '+', '-'); |
| 605 std::replace(output->begin(), output->end(), '/', '_'); | 635 std::replace(output->begin(), output->end(), '/', '_'); |
| 606 } | 636 } |
| 607 | 637 |
| 608 base::Value* SdchManager::SdchInfoToValue() const { | 638 base::Value* SdchManager::SdchInfoToValue() const { |
| 609 base::DictionaryValue* value = new base::DictionaryValue(); | 639 base::DictionaryValue* value = new base::DictionaryValue(); |
| 610 | 640 |
| 611 value->SetBoolean("sdch_enabled", sdch_enabled()); | 641 value->SetBoolean("sdch_enabled", sdch_enabled()); |
| 612 value->SetBoolean("secure_scheme_support", secure_scheme_supported()); | 642 value->SetBoolean("secure_scheme_support", secure_scheme_supported()); |
| 613 | 643 |
| 614 base::ListValue* entry_list = new base::ListValue(); | 644 base::ListValue* entry_list = new base::ListValue(); |
| 615 for (DictionaryMap::const_iterator it = dictionaries_.begin(); | 645 for (const auto& entry: dictionaries_) { |
| 616 it != dictionaries_.end(); ++it) { | |
| 617 base::DictionaryValue* entry_dict = new base::DictionaryValue(); | 646 base::DictionaryValue* entry_dict = new base::DictionaryValue(); |
| 618 entry_dict->SetString("url", it->second->url().spec()); | 647 entry_dict->SetString("url", entry.second->data.url().spec()); |
| 619 entry_dict->SetString("client_hash", it->second->client_hash()); | 648 entry_dict->SetString("client_hash", entry.second->data.client_hash()); |
| 620 entry_dict->SetString("domain", it->second->domain()); | 649 entry_dict->SetString("domain", entry.second->data.domain()); |
| 621 entry_dict->SetString("path", it->second->path()); | 650 entry_dict->SetString("path", entry.second->data.path()); |
| 622 base::ListValue* port_list = new base::ListValue(); | 651 base::ListValue* port_list = new base::ListValue(); |
| 623 for (std::set<int>::const_iterator port_it = it->second->ports().begin(); | 652 for (std::set<int>::const_iterator port_it = |
| 624 port_it != it->second->ports().end(); ++port_it) { | 653 entry.second->data.ports().begin(); |
| 654 port_it != entry.second->data.ports().end(); ++port_it) { | |
| 625 port_list->AppendInteger(*port_it); | 655 port_list->AppendInteger(*port_it); |
| 626 } | 656 } |
| 627 entry_dict->Set("ports", port_list); | 657 entry_dict->Set("ports", port_list); |
| 628 entry_dict->SetString("server_hash", it->first); | 658 entry_dict->SetString("server_hash", entry.first); |
| 629 entry_list->Append(entry_dict); | 659 entry_list->Append(entry_dict); |
| 630 } | 660 } |
| 631 value->Set("dictionaries", entry_list); | 661 value->Set("dictionaries", entry_list); |
| 632 | 662 |
| 633 entry_list = new base::ListValue(); | 663 entry_list = new base::ListValue(); |
| 634 for (DomainBlacklistInfo::const_iterator it = blacklisted_domains_.begin(); | 664 for (DomainBlacklistInfo::const_iterator it = blacklisted_domains_.begin(); |
| 635 it != blacklisted_domains_.end(); ++it) { | 665 it != blacklisted_domains_.end(); ++it) { |
| 636 if (it->second.count == 0) | 666 if (it->second.count == 0) |
| 637 continue; | 667 continue; |
| 638 base::DictionaryValue* entry_dict = new base::DictionaryValue(); | 668 base::DictionaryValue* entry_dict = new base::DictionaryValue(); |
| 639 entry_dict->SetString("domain", it->first); | 669 entry_dict->SetString("domain", it->first); |
| 640 if (it->second.count != INT_MAX) | 670 if (it->second.count != INT_MAX) |
| 641 entry_dict->SetInteger("tries", it->second.count); | 671 entry_dict->SetInteger("tries", it->second.count); |
| 642 entry_dict->SetInteger("reason", it->second.reason); | 672 entry_dict->SetInteger("reason", it->second.reason); |
| 643 entry_list->Append(entry_dict); | 673 entry_list->Append(entry_dict); |
| 644 } | 674 } |
| 645 value->Set("blacklisted", entry_list); | 675 value->Set("blacklisted", entry_list); |
| 646 | 676 |
| 647 return value; | 677 return value; |
| 648 } | 678 } |
| 649 | 679 |
| 650 } // namespace net | 680 } // namespace net |
| OLD | NEW |