Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(531)

Side by Side Diff: net/base/sdch_manager.cc

Issue 841883002: Add an eviction mechanism for SDCH dictionaries. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: git cl format Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698