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 |