| 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 162 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 264   DCHECK(thread_checker_.CalledOnValidThread()); | 257   DCHECK(thread_checker_.CalledOnValidThread()); | 
| 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 |  | 
| 275   // Note that this may result in not having dictionaries we've advertised |  | 
| 276   // for incoming responses. The window is relatively small (as ClearData() |  | 
| 277   // is not expected to be called frequently), so we rely on meta-refresh |  | 
| 278   // to handle this case. |  | 
| 279   dictionaries_.clear(); | 267   dictionaries_.clear(); | 
| 280 |  | 
| 281   FOR_EACH_OBSERVER(SdchObserver, observers_, OnClearDictionaries(this)); | 268   FOR_EACH_OBSERVER(SdchObserver, observers_, OnClearDictionaries(this)); | 
| 282 } | 269 } | 
| 283 | 270 | 
| 284 // static | 271 // static | 
| 285 void SdchManager::SdchErrorRecovery(SdchProblemCode problem) { | 272 void SdchManager::SdchErrorRecovery(SdchProblemCode problem) { | 
| 286   UMA_HISTOGRAM_ENUMERATION("Sdch3.ProblemCodes_5", problem, | 273   UMA_HISTOGRAM_ENUMERATION("Sdch3.ProblemCodes_5", problem, | 
| 287                             SDCH_MAX_PROBLEM_CODE); | 274                             SDCH_MAX_PROBLEM_CODE); | 
| 288 } | 275 } | 
| 289 | 276 | 
| 290 // static | 277 // static | 
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 393   if (rv != SDCH_OK) | 380   if (rv != SDCH_OK) | 
| 394     return rv; | 381     return rv; | 
| 395 | 382 | 
| 396   FOR_EACH_OBSERVER(SdchObserver, | 383   FOR_EACH_OBSERVER(SdchObserver, | 
| 397                     observers_, | 384                     observers_, | 
| 398                     OnGetDictionary(this, request_url, dictionary_url)); | 385                     OnGetDictionary(this, request_url, dictionary_url)); | 
| 399 | 386 | 
| 400   return SDCH_OK; | 387   return SDCH_OK; | 
| 401 } | 388 } | 
| 402 | 389 | 
|  | 390 void SdchManager::OnDictionaryUsed(const std::string& server_hash) { | 
|  | 391   FOR_EACH_OBSERVER(SdchObserver, observers_, | 
|  | 392                     OnDictionaryUsed(this, server_hash)); | 
|  | 393 } | 
|  | 394 | 
| 403 SdchProblemCode SdchManager::CanFetchDictionary( | 395 SdchProblemCode SdchManager::CanFetchDictionary( | 
| 404     const GURL& referring_url, | 396     const GURL& referring_url, | 
| 405     const GURL& dictionary_url) const { | 397     const GURL& dictionary_url) const { | 
| 406   DCHECK(thread_checker_.CalledOnValidThread()); | 398   DCHECK(thread_checker_.CalledOnValidThread()); | 
| 407   /* The user agent may retrieve a dictionary from the dictionary URL if all of | 399   /* The user agent may retrieve a dictionary from the dictionary URL if all of | 
| 408      the following are true: | 400      the following are true: | 
| 409        1 The dictionary URL host name matches the referrer URL host name and | 401        1 The dictionary URL host name matches the referrer URL host name and | 
| 410            scheme. | 402            scheme. | 
| 411        2 The dictionary URL host name domain matches the parent domain of the | 403        2 The dictionary URL host name domain matches the parent domain of the | 
| 412            referrer URL host name | 404            referrer URL host name | 
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 514 void SdchManager::AddObserver(SdchObserver* observer) { | 506 void SdchManager::AddObserver(SdchObserver* observer) { | 
| 515   observers_.AddObserver(observer); | 507   observers_.AddObserver(observer); | 
| 516 } | 508 } | 
| 517 | 509 | 
| 518 void SdchManager::RemoveObserver(SdchObserver* observer) { | 510 void SdchManager::RemoveObserver(SdchObserver* observer) { | 
| 519   observers_.RemoveObserver(observer); | 511   observers_.RemoveObserver(observer); | 
| 520 } | 512 } | 
| 521 | 513 | 
| 522 SdchProblemCode SdchManager::AddSdchDictionary( | 514 SdchProblemCode SdchManager::AddSdchDictionary( | 
| 523     const std::string& dictionary_text, | 515     const std::string& dictionary_text, | 
| 524     const GURL& dictionary_url) { | 516     const GURL& dictionary_url, | 
|  | 517     std::string* server_hash_p) { | 
| 525   DCHECK(thread_checker_.CalledOnValidThread()); | 518   DCHECK(thread_checker_.CalledOnValidThread()); | 
| 526   std::string client_hash; | 519   std::string client_hash; | 
| 527   std::string server_hash; | 520   std::string server_hash; | 
| 528   GenerateHash(dictionary_text, &client_hash, &server_hash); | 521   GenerateHash(dictionary_text, &client_hash, &server_hash); | 
| 529   if (dictionaries_.find(server_hash) != dictionaries_.end()) | 522   if (dictionaries_.find(server_hash) != dictionaries_.end()) | 
| 530     return SDCH_DICTIONARY_ALREADY_LOADED;  // Already loaded. | 523     return SDCH_DICTIONARY_ALREADY_LOADED;  // Already loaded. | 
| 531 | 524 | 
| 532   std::string domain, path; | 525   std::string domain, path; | 
| 533   std::set<int> ports; | 526   std::set<int> ports; | 
| 534   base::Time expiration(base::Time::Now() + base::TimeDelta::FromDays(30)); | 527   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); | 584   StripTrailingDot(&dictionary_url_normalized); | 
| 592 | 585 | 
| 593   SdchProblemCode rv = IsInSupportedDomain(dictionary_url_normalized); | 586   SdchProblemCode rv = IsInSupportedDomain(dictionary_url_normalized); | 
| 594   if (rv != SDCH_OK) | 587   if (rv != SDCH_OK) | 
| 595     return rv; | 588     return rv; | 
| 596 | 589 | 
| 597   rv = Dictionary::CanSet(domain, path, ports, dictionary_url_normalized); | 590   rv = Dictionary::CanSet(domain, path, ports, dictionary_url_normalized); | 
| 598   if (rv != SDCH_OK) | 591   if (rv != SDCH_OK) | 
| 599     return rv; | 592     return rv; | 
| 600 | 593 | 
| 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()); | 594   UMA_HISTOGRAM_COUNTS("Sdch3.Dictionary size loaded", dictionary_text.size()); | 
| 612   DVLOG(1) << "Loaded dictionary with client hash " << client_hash | 595   DVLOG(1) << "Loaded dictionary with client hash " << client_hash | 
| 613            << " and server hash " << server_hash; | 596            << " and server hash " << server_hash; | 
| 614   Dictionary dictionary(dictionary_text, header_end + 2, client_hash, | 597   Dictionary dictionary(dictionary_text, header_end + 2, client_hash, | 
| 615                         dictionary_url_normalized, domain, path, expiration, | 598                         server_hash, dictionary_url_normalized, domain, path, | 
| 616                         ports); | 599                         expiration, ports); | 
| 617   dictionaries_[server_hash] = | 600   dictionaries_[server_hash] = | 
| 618       new base::RefCountedData<Dictionary>(dictionary); | 601       new base::RefCountedData<Dictionary>(dictionary); | 
|  | 602   if (server_hash_p) | 
|  | 603     *server_hash_p = server_hash; | 
| 619 | 604 | 
| 620   return SDCH_OK; | 605   return SDCH_OK; | 
| 621 } | 606 } | 
| 622 | 607 | 
|  | 608 SdchProblemCode SdchManager::RemoveSdchDictionary( | 
|  | 609     const std::string& server_hash) { | 
|  | 610   if (dictionaries_.find(server_hash) == dictionaries_.end()) | 
|  | 611     return SDCH_DICTIONARY_HASH_NOT_FOUND; | 
|  | 612 | 
|  | 613   dictionaries_.erase(server_hash); | 
|  | 614   return SDCH_OK; | 
|  | 615 } | 
|  | 616 | 
| 623 // static | 617 // static | 
| 624 scoped_ptr<SdchManager::DictionarySet> | 618 scoped_ptr<SdchManager::DictionarySet> | 
| 625 SdchManager::CreateEmptyDictionarySetForTesting() { | 619 SdchManager::CreateEmptyDictionarySetForTesting() { | 
| 626   return scoped_ptr<DictionarySet>(new DictionarySet).Pass(); | 620   return scoped_ptr<DictionarySet>(new DictionarySet).Pass(); | 
| 627 } | 621 } | 
| 628 | 622 | 
| 629 // static | 623 // static | 
| 630 void SdchManager::UrlSafeBase64Encode(const std::string& input, | 624 void SdchManager::UrlSafeBase64Encode(const std::string& input, | 
| 631                                       std::string* output) { | 625                                       std::string* output) { | 
| 632   // Since this is only done during a dictionary load, and hashes are only 8 | 626   // 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); | 666       entry_dict->SetInteger("tries", it->second.count); | 
| 673     entry_dict->SetInteger("reason", it->second.reason); | 667     entry_dict->SetInteger("reason", it->second.reason); | 
| 674     entry_list->Append(entry_dict); | 668     entry_list->Append(entry_dict); | 
| 675   } | 669   } | 
| 676   value->Set("blacklisted", entry_list); | 670   value->Set("blacklisted", entry_list); | 
| 677 | 671 | 
| 678   return value; | 672   return value; | 
| 679 } | 673 } | 
| 680 | 674 | 
| 681 }  // namespace net | 675 }  // namespace net | 
| OLD | NEW | 
|---|