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" |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 32 GURL::Replacements replacements; | 32 GURL::Replacements replacements; |
| 33 replacements.SetHostStr(host); | 33 replacements.SetHostStr(host); |
| 34 *gurl = gurl->ReplaceComponents(replacements); | 34 *gurl = gurl->ReplaceComponents(replacements); |
| 35 return; | 35 return; |
| 36 } | 36 } |
| 37 | 37 |
| 38 } // namespace | 38 } // namespace |
| 39 | 39 |
| 40 namespace net { | 40 namespace net { |
| 41 | 41 |
| 42 // Adjust SDCH limits downwards for mobile. | |
| 43 #if defined(OS_ANDROID) || defined(OS_IOS) | |
| 44 // static | |
| 45 const size_t SdchManager::kMaxDictionaryCount = 1; | |
| 46 const size_t SdchManager::kMaxDictionarySize = 500 * 1000; | |
| 47 #else | |
| 48 // static | |
| 49 const size_t SdchManager::kMaxDictionaryCount = 20; | |
| 50 const size_t SdchManager::kMaxDictionarySize = 1000 * 1000; | |
| 51 #endif | |
| 52 | |
| 53 // Workaround for http://crbug.com/437794; remove when fixed. | 42 // Workaround for http://crbug.com/437794; remove when fixed. |
| 54 #if defined(OS_IOS) | 43 #if defined(OS_IOS) |
| 55 // static | 44 // static |
| 56 bool SdchManager::g_sdch_enabled_ = false; | 45 bool SdchManager::g_sdch_enabled_ = false; |
| 57 #else | 46 #else |
| 58 // static | 47 // static |
| 59 bool SdchManager::g_sdch_enabled_ = true; | 48 bool SdchManager::g_sdch_enabled_ = true; |
| 60 #endif | 49 #endif |
| 61 | 50 |
| 62 // static | 51 // static |
| 63 bool SdchManager::g_secure_scheme_supported_ = true; | 52 bool SdchManager::g_secure_scheme_supported_ = true; |
| 64 | 53 |
| 65 SdchManager::Dictionary::Dictionary(const std::string& dictionary_text, | 54 SdchManager::Dictionary::Dictionary(const std::string& dictionary_text, |
| 66 size_t offset, | 55 size_t offset, |
| 67 const std::string& client_hash, | 56 const std::string& client_hash, |
| 57 const std::string& server_hash, | |
| 68 const GURL& gurl, | 58 const GURL& gurl, |
| 69 const std::string& domain, | 59 const std::string& domain, |
| 70 const std::string& path, | 60 const std::string& path, |
| 71 const base::Time& expiration, | 61 const base::Time& expiration, |
| 72 const std::set<int>& ports) | 62 const std::set<int>& ports) |
| 73 : text_(dictionary_text, offset), | 63 : text_(dictionary_text, offset), |
| 74 client_hash_(client_hash), | 64 client_hash_(client_hash), |
| 65 server_hash_(server_hash), | |
| 75 url_(gurl), | 66 url_(gurl), |
| 76 domain_(domain), | 67 domain_(domain), |
| 77 path_(path), | 68 path_(path), |
| 78 expiration_(expiration), | 69 expiration_(expiration), |
| 79 ports_(ports), | 70 ports_(ports), |
| 80 clock_(new base::DefaultClock) { | 71 clock_(new base::DefaultClock) { |
| 81 } | 72 } |
| 82 | 73 |
| 83 SdchManager::Dictionary::Dictionary(const SdchManager::Dictionary& rhs) | 74 SdchManager::Dictionary::Dictionary(const SdchManager::Dictionary& rhs) |
| 84 : text_(rhs.text_), | 75 : text_(rhs.text_), |
| 85 client_hash_(rhs.client_hash_), | 76 client_hash_(rhs.client_hash_), |
| 77 server_hash_(rhs.server_hash_), | |
| 86 url_(rhs.url_), | 78 url_(rhs.url_), |
| 87 domain_(rhs.domain_), | 79 domain_(rhs.domain_), |
| 88 path_(rhs.path_), | 80 path_(rhs.path_), |
| 89 expiration_(rhs.expiration_), | 81 expiration_(rhs.expiration_), |
| 90 ports_(rhs.ports_), | 82 ports_(rhs.ports_), |
| 91 clock_(new base::DefaultClock) {} | 83 clock_(new base::DefaultClock) { |
| 84 } | |
| 92 | 85 |
| 93 SdchManager::Dictionary::~Dictionary() {} | 86 SdchManager::Dictionary::~Dictionary() {} |
| 94 | 87 |
| 95 // Security functions restricting loads and use of dictionaries. | 88 // Security functions restricting loads and use of dictionaries. |
| 96 | 89 |
| 97 // static | 90 // static |
| 98 SdchProblemCode SdchManager::Dictionary::CanSet(const std::string& domain, | 91 SdchProblemCode SdchManager::Dictionary::CanSet(const std::string& domain, |
| 99 const std::string& path, | 92 const std::string& path, |
| 100 const std::set<int>& ports, | 93 const std::set<int>& ports, |
| 101 const GURL& dictionary_url) { | 94 const GURL& dictionary_url) { |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 265 while (!dictionaries_.empty()) { | 258 while (!dictionaries_.empty()) { |
| 266 auto it = dictionaries_.begin(); | 259 auto it = dictionaries_.begin(); |
| 267 dictionaries_.erase(it->first); | 260 dictionaries_.erase(it->first); |
| 268 } | 261 } |
| 269 } | 262 } |
| 270 | 263 |
| 271 void SdchManager::ClearData() { | 264 void SdchManager::ClearData() { |
| 272 blacklisted_domains_.clear(); | 265 blacklisted_domains_.clear(); |
| 273 allow_latency_experiment_.clear(); | 266 allow_latency_experiment_.clear(); |
| 274 | 267 |
| 275 // Note that this may result in not having dictionaries we've advertised | 268 while (!dictionaries_.empty()) { |
|
Bence
2015/01/08 14:37:17
What was wrong with dictionaries_.clear()?
Randy Smith (Not in Mondays)
2015/01/08 15:48:23
Huh. Good question. I think this is from an earl
| |
| 276 // for incoming responses. The window is relatively small (as ClearData() | 269 auto it(dictionaries_.begin()); |
| 277 // is not expected to be called frequently), so we rely on meta-refresh | 270 dictionaries_.erase(it); |
| 278 // to handle this case. | 271 } |
| 279 dictionaries_.clear(); | |
| 280 | 272 |
| 281 FOR_EACH_OBSERVER(SdchObserver, observers_, OnClearDictionaries(this)); | 273 FOR_EACH_OBSERVER(SdchObserver, observers_, OnClearDictionaries(this)); |
| 282 } | 274 } |
| 283 | 275 |
| 284 // static | 276 // static |
| 285 void SdchManager::SdchErrorRecovery(SdchProblemCode problem) { | 277 void SdchManager::SdchErrorRecovery(SdchProblemCode problem) { |
| 286 UMA_HISTOGRAM_ENUMERATION("Sdch3.ProblemCodes_5", problem, | 278 UMA_HISTOGRAM_ENUMERATION("Sdch3.ProblemCodes_5", problem, |
| 287 SDCH_MAX_PROBLEM_CODE); | 279 SDCH_MAX_PROBLEM_CODE); |
| 288 } | 280 } |
| 289 | 281 |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 393 if (rv != SDCH_OK) | 385 if (rv != SDCH_OK) |
| 394 return rv; | 386 return rv; |
| 395 | 387 |
| 396 FOR_EACH_OBSERVER(SdchObserver, | 388 FOR_EACH_OBSERVER(SdchObserver, |
| 397 observers_, | 389 observers_, |
| 398 OnGetDictionary(this, request_url, dictionary_url)); | 390 OnGetDictionary(this, request_url, dictionary_url)); |
| 399 | 391 |
| 400 return SDCH_OK; | 392 return SDCH_OK; |
| 401 } | 393 } |
| 402 | 394 |
| 395 void SdchManager::OnDictionaryUsed(const std::string& server_hash) { | |
| 396 FOR_EACH_OBSERVER(SdchObserver, observers_, | |
| 397 OnDictionaryUsed(this, server_hash)); | |
| 398 } | |
| 399 | |
| 403 SdchProblemCode SdchManager::CanFetchDictionary( | 400 SdchProblemCode SdchManager::CanFetchDictionary( |
| 404 const GURL& referring_url, | 401 const GURL& referring_url, |
| 405 const GURL& dictionary_url) const { | 402 const GURL& dictionary_url) const { |
| 406 DCHECK(thread_checker_.CalledOnValidThread()); | 403 DCHECK(thread_checker_.CalledOnValidThread()); |
| 407 /* The user agent may retrieve a dictionary from the dictionary URL if all of | 404 /* The user agent may retrieve a dictionary from the dictionary URL if all of |
| 408 the following are true: | 405 the following are true: |
| 409 1 The dictionary URL host name matches the referrer URL host name and | 406 1 The dictionary URL host name matches the referrer URL host name and |
| 410 scheme. | 407 scheme. |
| 411 2 The dictionary URL host name domain matches the parent domain of the | 408 2 The dictionary URL host name domain matches the parent domain of the |
| 412 referrer URL host name | 409 referrer URL host name |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 514 void SdchManager::AddObserver(SdchObserver* observer) { | 511 void SdchManager::AddObserver(SdchObserver* observer) { |
| 515 observers_.AddObserver(observer); | 512 observers_.AddObserver(observer); |
| 516 } | 513 } |
| 517 | 514 |
| 518 void SdchManager::RemoveObserver(SdchObserver* observer) { | 515 void SdchManager::RemoveObserver(SdchObserver* observer) { |
| 519 observers_.RemoveObserver(observer); | 516 observers_.RemoveObserver(observer); |
| 520 } | 517 } |
| 521 | 518 |
| 522 SdchProblemCode SdchManager::AddSdchDictionary( | 519 SdchProblemCode SdchManager::AddSdchDictionary( |
| 523 const std::string& dictionary_text, | 520 const std::string& dictionary_text, |
| 524 const GURL& dictionary_url) { | 521 const GURL& dictionary_url, |
| 522 std::string* server_hash_p) { | |
| 525 DCHECK(thread_checker_.CalledOnValidThread()); | 523 DCHECK(thread_checker_.CalledOnValidThread()); |
| 526 std::string client_hash; | 524 std::string client_hash; |
| 527 std::string server_hash; | 525 std::string server_hash; |
| 528 GenerateHash(dictionary_text, &client_hash, &server_hash); | 526 GenerateHash(dictionary_text, &client_hash, &server_hash); |
| 529 if (dictionaries_.find(server_hash) != dictionaries_.end()) | 527 if (dictionaries_.find(server_hash) != dictionaries_.end()) |
| 530 return SDCH_DICTIONARY_ALREADY_LOADED; // Already loaded. | 528 return SDCH_DICTIONARY_ALREADY_LOADED; // Already loaded. |
| 531 | 529 |
| 532 std::string domain, path; | 530 std::string domain, path; |
| 533 std::set<int> ports; | 531 std::set<int> ports; |
| 534 base::Time expiration(base::Time::Now() + base::TimeDelta::FromDays(30)); | 532 base::Time expiration(base::Time::Now() + base::TimeDelta::FromDays(30)); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 591 StripTrailingDot(&dictionary_url_normalized); | 589 StripTrailingDot(&dictionary_url_normalized); |
| 592 | 590 |
| 593 SdchProblemCode rv = IsInSupportedDomain(dictionary_url_normalized); | 591 SdchProblemCode rv = IsInSupportedDomain(dictionary_url_normalized); |
| 594 if (rv != SDCH_OK) | 592 if (rv != SDCH_OK) |
| 595 return rv; | 593 return rv; |
| 596 | 594 |
| 597 rv = Dictionary::CanSet(domain, path, ports, dictionary_url_normalized); | 595 rv = Dictionary::CanSet(domain, path, ports, dictionary_url_normalized); |
| 598 if (rv != SDCH_OK) | 596 if (rv != SDCH_OK) |
| 599 return rv; | 597 return rv; |
| 600 | 598 |
| 601 // TODO(jar): Remove these hacks to preclude a DOS attack involving piles of | |
| 602 // useless dictionaries. We should probably have a cache eviction plan, | |
| 603 // instead of just blocking additions. For now, with the spec in flux, it | |
| 604 // is probably not worth doing eviction handling. | |
| 605 if (kMaxDictionarySize < dictionary_text.size()) | |
| 606 return SDCH_DICTIONARY_IS_TOO_LARGE; | |
| 607 | |
| 608 if (kMaxDictionaryCount <= dictionaries_.size()) | |
| 609 return SDCH_DICTIONARY_COUNT_EXCEEDED; | |
| 610 | |
| 611 UMA_HISTOGRAM_COUNTS("Sdch3.Dictionary size loaded", dictionary_text.size()); | 599 UMA_HISTOGRAM_COUNTS("Sdch3.Dictionary size loaded", dictionary_text.size()); |
| 612 DVLOG(1) << "Loaded dictionary with client hash " << client_hash | 600 DVLOG(1) << "Loaded dictionary with client hash " << client_hash |
| 613 << " and server hash " << server_hash; | 601 << " and server hash " << server_hash; |
| 614 Dictionary dictionary(dictionary_text, header_end + 2, client_hash, | 602 Dictionary dictionary(dictionary_text, header_end + 2, client_hash, |
| 615 dictionary_url_normalized, domain, path, expiration, | 603 server_hash, dictionary_url_normalized, domain, path, |
| 616 ports); | 604 expiration, ports); |
| 617 dictionaries_[server_hash] = | 605 dictionaries_[server_hash] = |
| 618 new base::RefCountedData<Dictionary>(dictionary); | 606 new base::RefCountedData<Dictionary>(dictionary); |
| 607 if (server_hash_p) | |
| 608 *server_hash_p = server_hash; | |
| 619 | 609 |
| 620 return SDCH_OK; | 610 return SDCH_OK; |
| 621 } | 611 } |
| 622 | 612 |
| 613 SdchProblemCode SdchManager::RemoveSdchDictionary( | |
| 614 const std::string& server_hash) { | |
| 615 if (dictionaries_.find(server_hash) == dictionaries_.end()) | |
| 616 return SDCH_DICTIONARY_HASH_NOT_FOUND; | |
| 617 | |
| 618 dictionaries_.erase(server_hash); | |
| 619 return SDCH_OK; | |
| 620 } | |
| 621 | |
| 623 // static | 622 // static |
| 624 scoped_ptr<SdchManager::DictionarySet> | 623 scoped_ptr<SdchManager::DictionarySet> |
| 625 SdchManager::CreateEmptyDictionarySetForTesting() { | 624 SdchManager::CreateEmptyDictionarySetForTesting() { |
| 626 return scoped_ptr<DictionarySet>(new DictionarySet).Pass(); | 625 return scoped_ptr<DictionarySet>(new DictionarySet).Pass(); |
| 627 } | 626 } |
| 628 | 627 |
| 629 // static | 628 // static |
| 630 void SdchManager::UrlSafeBase64Encode(const std::string& input, | 629 void SdchManager::UrlSafeBase64Encode(const std::string& input, |
| 631 std::string* output) { | 630 std::string* output) { |
| 632 // 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 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 672 entry_dict->SetInteger("tries", it->second.count); | 671 entry_dict->SetInteger("tries", it->second.count); |
| 673 entry_dict->SetInteger("reason", it->second.reason); | 672 entry_dict->SetInteger("reason", it->second.reason); |
| 674 entry_list->Append(entry_dict); | 673 entry_list->Append(entry_dict); |
| 675 } | 674 } |
| 676 value->Set("blacklisted", entry_list); | 675 value->Set("blacklisted", entry_list); |
| 677 | 676 |
| 678 return value; | 677 return value; |
| 679 } | 678 } |
| 680 | 679 |
| 681 } // namespace net | 680 } // namespace net |
| OLD | NEW |