| Index: net/base/sdch_manager.cc
|
| diff --git a/net/base/sdch_manager.cc b/net/base/sdch_manager.cc
|
| deleted file mode 100644
|
| index 27d86ee858f61e581c2197dca5edfe62eb2e2ea5..0000000000000000000000000000000000000000
|
| --- a/net/base/sdch_manager.cc
|
| +++ /dev/null
|
| @@ -1,675 +0,0 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "net/base/sdch_manager.h"
|
| -
|
| -#include "base/base64.h"
|
| -#include "base/logging.h"
|
| -#include "base/metrics/histogram.h"
|
| -#include "base/strings/string_number_conversions.h"
|
| -#include "base/strings/string_util.h"
|
| -#include "base/time/default_clock.h"
|
| -#include "base/values.h"
|
| -#include "crypto/sha2.h"
|
| -#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
|
| -#include "net/base/sdch_observer.h"
|
| -#include "net/url_request/url_request_http_job.h"
|
| -
|
| -namespace {
|
| -
|
| -void StripTrailingDot(GURL* gurl) {
|
| - std::string host(gurl->host());
|
| -
|
| - if (host.empty())
|
| - return;
|
| -
|
| - if (*host.rbegin() != '.')
|
| - return;
|
| -
|
| - host.resize(host.size() - 1);
|
| -
|
| - GURL::Replacements replacements;
|
| - replacements.SetHostStr(host);
|
| - *gurl = gurl->ReplaceComponents(replacements);
|
| - return;
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -namespace net {
|
| -
|
| -// Workaround for http://crbug.com/437794; remove when fixed.
|
| -#if defined(OS_IOS)
|
| -// static
|
| -bool SdchManager::g_sdch_enabled_ = false;
|
| -#else
|
| -// static
|
| -bool SdchManager::g_sdch_enabled_ = true;
|
| -#endif
|
| -
|
| -// static
|
| -bool SdchManager::g_secure_scheme_supported_ = true;
|
| -
|
| -SdchManager::Dictionary::Dictionary(const std::string& dictionary_text,
|
| - size_t offset,
|
| - const std::string& client_hash,
|
| - const std::string& server_hash,
|
| - const GURL& gurl,
|
| - const std::string& domain,
|
| - const std::string& path,
|
| - const base::Time& expiration,
|
| - const std::set<int>& ports)
|
| - : text_(dictionary_text, offset),
|
| - client_hash_(client_hash),
|
| - server_hash_(server_hash),
|
| - url_(gurl),
|
| - domain_(domain),
|
| - path_(path),
|
| - expiration_(expiration),
|
| - ports_(ports),
|
| - clock_(new base::DefaultClock) {
|
| -}
|
| -
|
| -SdchManager::Dictionary::Dictionary(const SdchManager::Dictionary& rhs)
|
| - : text_(rhs.text_),
|
| - client_hash_(rhs.client_hash_),
|
| - server_hash_(rhs.server_hash_),
|
| - url_(rhs.url_),
|
| - domain_(rhs.domain_),
|
| - path_(rhs.path_),
|
| - expiration_(rhs.expiration_),
|
| - ports_(rhs.ports_),
|
| - clock_(new base::DefaultClock) {
|
| -}
|
| -
|
| -SdchManager::Dictionary::~Dictionary() {}
|
| -
|
| -// Security functions restricting loads and use of dictionaries.
|
| -
|
| -// static
|
| -SdchProblemCode SdchManager::Dictionary::CanSet(const std::string& domain,
|
| - const std::string& path,
|
| - const std::set<int>& ports,
|
| - const GURL& dictionary_url) {
|
| - /*
|
| - A dictionary is invalid and must not be stored if any of the following are
|
| - true:
|
| - 1. The dictionary has no Domain attribute.
|
| - 2. The effective host name that derives from the referer URL host name does
|
| - not domain-match the Domain attribute.
|
| - 3. The Domain attribute is a top level domain.
|
| - 4. The referer URL host is a host domain name (not IP address) and has the
|
| - form HD, where D is the value of the Domain attribute, and H is a string
|
| - that contains one or more dots.
|
| - 5. If the dictionary has a Port attribute and the referer URL's port was not
|
| - in the list.
|
| - */
|
| -
|
| - // TODO(jar): Redirects in dictionary fetches might plausibly be problematic,
|
| - // and hence the conservative approach is to not allow any redirects (if there
|
| - // were any... then don't allow the dictionary to be set).
|
| -
|
| - if (domain.empty())
|
| - return SDCH_DICTIONARY_MISSING_DOMAIN_SPECIFIER; // Domain is required.
|
| -
|
| - if (registry_controlled_domains::GetDomainAndRegistry(
|
| - domain, registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)
|
| - .empty()) {
|
| - return SDCH_DICTIONARY_SPECIFIES_TOP_LEVEL_DOMAIN; // domain was a TLD.
|
| - }
|
| -
|
| - if (!Dictionary::DomainMatch(dictionary_url, domain))
|
| - return SDCH_DICTIONARY_DOMAIN_NOT_MATCHING_SOURCE_URL;
|
| -
|
| - std::string referrer_url_host = dictionary_url.host();
|
| - size_t postfix_domain_index = referrer_url_host.rfind(domain);
|
| - // See if it is indeed a postfix, or just an internal string.
|
| - if (referrer_url_host.size() == postfix_domain_index + domain.size()) {
|
| - // It is a postfix... so check to see if there's a dot in the prefix.
|
| - size_t end_of_host_index = referrer_url_host.find_first_of('.');
|
| - if (referrer_url_host.npos != end_of_host_index &&
|
| - end_of_host_index < postfix_domain_index) {
|
| - return SDCH_DICTIONARY_REFERER_URL_HAS_DOT_IN_PREFIX;
|
| - }
|
| - }
|
| -
|
| - if (!ports.empty() && 0 == ports.count(dictionary_url.EffectiveIntPort()))
|
| - return SDCH_DICTIONARY_PORT_NOT_MATCHING_SOURCE_URL;
|
| -
|
| - return SDCH_OK;
|
| -}
|
| -
|
| -SdchProblemCode SdchManager::Dictionary::CanUse(
|
| - const GURL& target_url) const {
|
| - /*
|
| - 1. The request URL's host name domain-matches the Domain attribute of the
|
| - dictionary.
|
| - 2. If the dictionary has a Port attribute, the request port is one of the
|
| - ports listed in the Port attribute.
|
| - 3. The request URL path-matches the path attribute of the dictionary.
|
| - 4. The request is not an HTTPS request.
|
| - We can override (ignore) item (4) only when we have explicitly enabled
|
| - HTTPS support AND the dictionary acquisition scheme matches the target
|
| - url scheme.
|
| - */
|
| - if (!DomainMatch(target_url, domain_))
|
| - return SDCH_DICTIONARY_FOUND_HAS_WRONG_DOMAIN;
|
| -
|
| - if (!ports_.empty() && 0 == ports_.count(target_url.EffectiveIntPort()))
|
| - return SDCH_DICTIONARY_FOUND_HAS_WRONG_PORT_LIST;
|
| -
|
| - if (path_.size() && !PathMatch(target_url.path(), path_))
|
| - return SDCH_DICTIONARY_FOUND_HAS_WRONG_PATH;
|
| -
|
| - if (!SdchManager::secure_scheme_supported() && target_url.SchemeIsSecure())
|
| - return SDCH_DICTIONARY_FOUND_HAS_WRONG_SCHEME;
|
| -
|
| - if (target_url.SchemeIsSecure() != url_.SchemeIsSecure())
|
| - return SDCH_DICTIONARY_FOUND_HAS_WRONG_SCHEME;
|
| -
|
| - // TODO(jar): Remove overly restrictive failsafe test (added per security
|
| - // review) when we have a need to be more general.
|
| - if (!target_url.SchemeIsHTTPOrHTTPS())
|
| - return SDCH_ATTEMPT_TO_DECODE_NON_HTTP_DATA;
|
| -
|
| - return SDCH_OK;
|
| -}
|
| -
|
| -// static
|
| -bool SdchManager::Dictionary::PathMatch(const std::string& path,
|
| - const std::string& restriction) {
|
| - /* Must be either:
|
| - 1. P2 is equal to P1
|
| - 2. P2 is a prefix of P1 and either the final character in P2 is "/" or the
|
| - character following P2 in P1 is "/".
|
| - */
|
| - if (path == restriction)
|
| - return true;
|
| - size_t prefix_length = restriction.size();
|
| - if (prefix_length > path.size())
|
| - return false; // Can't be a prefix.
|
| - if (0 != path.compare(0, prefix_length, restriction))
|
| - return false;
|
| - return restriction[prefix_length - 1] == '/' || path[prefix_length] == '/';
|
| -}
|
| -
|
| -// static
|
| -bool SdchManager::Dictionary::DomainMatch(const GURL& gurl,
|
| - const std::string& restriction) {
|
| - // TODO(jar): This is not precisely a domain match definition.
|
| - return gurl.DomainIs(restriction.data(), restriction.size());
|
| -}
|
| -
|
| -bool SdchManager::Dictionary::Expired() const {
|
| - return clock_->Now() > expiration_;
|
| -}
|
| -
|
| -void SdchManager::Dictionary::SetClockForTesting(
|
| - scoped_ptr<base::Clock> clock) {
|
| - clock_ = clock.Pass();
|
| -}
|
| -
|
| -SdchManager::DictionarySet::DictionarySet() {}
|
| -
|
| -SdchManager::DictionarySet::~DictionarySet() {}
|
| -
|
| -std::string SdchManager::DictionarySet::GetDictionaryClientHashList() const {
|
| - std::string result;
|
| - bool first = true;
|
| - for (const auto& entry: dictionaries_) {
|
| - if (!first)
|
| - result.append(",");
|
| -
|
| - result.append(entry.second->data.client_hash());
|
| - first = false;
|
| - }
|
| - return result;
|
| -}
|
| -
|
| -const SdchManager::Dictionary* SdchManager::DictionarySet::GetDictionary(
|
| - const std::string& hash) const {
|
| - auto it = dictionaries_.find(hash);
|
| - if (it == dictionaries_.end())
|
| - return NULL;
|
| -
|
| - return &it->second->data;
|
| -}
|
| -
|
| -bool SdchManager::DictionarySet::Empty() const {
|
| - return dictionaries_.empty();
|
| -}
|
| -
|
| -void SdchManager::DictionarySet::AddDictionary(
|
| - const std::string& server_hash,
|
| - const scoped_refptr<base::RefCountedData<SdchManager::Dictionary>>&
|
| - dictionary) {
|
| - DCHECK(dictionaries_.end() == dictionaries_.find(server_hash));
|
| -
|
| - dictionaries_[server_hash] = dictionary;
|
| -}
|
| -
|
| -SdchManager::SdchManager() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| -}
|
| -
|
| -SdchManager::~SdchManager() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - while (!dictionaries_.empty()) {
|
| - auto it = dictionaries_.begin();
|
| - dictionaries_.erase(it->first);
|
| - }
|
| -}
|
| -
|
| -void SdchManager::ClearData() {
|
| - blacklisted_domains_.clear();
|
| - allow_latency_experiment_.clear();
|
| - dictionaries_.clear();
|
| - FOR_EACH_OBSERVER(SdchObserver, observers_, OnClearDictionaries(this));
|
| -}
|
| -
|
| -// static
|
| -void SdchManager::SdchErrorRecovery(SdchProblemCode problem) {
|
| - UMA_HISTOGRAM_ENUMERATION("Sdch3.ProblemCodes_5", problem,
|
| - SDCH_MAX_PROBLEM_CODE);
|
| -}
|
| -
|
| -// static
|
| -void SdchManager::EnableSdchSupport(bool enabled) {
|
| - g_sdch_enabled_ = enabled;
|
| -}
|
| -
|
| -// static
|
| -void SdchManager::EnableSecureSchemeSupport(bool enabled) {
|
| - g_secure_scheme_supported_ = enabled;
|
| -}
|
| -
|
| -void SdchManager::BlacklistDomain(const GURL& url,
|
| - SdchProblemCode blacklist_reason) {
|
| - SetAllowLatencyExperiment(url, false);
|
| -
|
| - BlacklistInfo* blacklist_info =
|
| - &blacklisted_domains_[base::StringToLowerASCII(url.host())];
|
| -
|
| - if (blacklist_info->count > 0)
|
| - return; // Domain is already blacklisted.
|
| -
|
| - if (blacklist_info->exponential_count > (INT_MAX - 1) / 2) {
|
| - blacklist_info->exponential_count = INT_MAX;
|
| - } else {
|
| - blacklist_info->exponential_count =
|
| - blacklist_info->exponential_count * 2 + 1;
|
| - }
|
| -
|
| - blacklist_info->count = blacklist_info->exponential_count;
|
| - blacklist_info->reason = blacklist_reason;
|
| -}
|
| -
|
| -void SdchManager::BlacklistDomainForever(const GURL& url,
|
| - SdchProblemCode blacklist_reason) {
|
| - SetAllowLatencyExperiment(url, false);
|
| -
|
| - BlacklistInfo* blacklist_info =
|
| - &blacklisted_domains_[base::StringToLowerASCII(url.host())];
|
| - blacklist_info->count = INT_MAX;
|
| - blacklist_info->exponential_count = INT_MAX;
|
| - blacklist_info->reason = blacklist_reason;
|
| -}
|
| -
|
| -void SdchManager::ClearBlacklistings() {
|
| - blacklisted_domains_.clear();
|
| -}
|
| -
|
| -void SdchManager::ClearDomainBlacklisting(const std::string& domain) {
|
| - BlacklistInfo* blacklist_info = &blacklisted_domains_[
|
| - base::StringToLowerASCII(domain)];
|
| - blacklist_info->count = 0;
|
| - blacklist_info->reason = SDCH_OK;
|
| -}
|
| -
|
| -int SdchManager::BlackListDomainCount(const std::string& domain) {
|
| - std::string domain_lower(base::StringToLowerASCII(domain));
|
| -
|
| - if (blacklisted_domains_.end() == blacklisted_domains_.find(domain_lower))
|
| - return 0;
|
| - return blacklisted_domains_[domain_lower].count;
|
| -}
|
| -
|
| -int SdchManager::BlacklistDomainExponential(const std::string& domain) {
|
| - std::string domain_lower(base::StringToLowerASCII(domain));
|
| -
|
| - if (blacklisted_domains_.end() == blacklisted_domains_.find(domain_lower))
|
| - return 0;
|
| - return blacklisted_domains_[domain_lower].exponential_count;
|
| -}
|
| -
|
| -SdchProblemCode SdchManager::IsInSupportedDomain(const GURL& url) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - if (!g_sdch_enabled_ )
|
| - return SDCH_DISABLED;
|
| -
|
| - if (!secure_scheme_supported() && url.SchemeIsSecure())
|
| - return SDCH_SECURE_SCHEME_NOT_SUPPORTED;
|
| -
|
| - if (blacklisted_domains_.empty())
|
| - return SDCH_OK;
|
| -
|
| - DomainBlacklistInfo::iterator it =
|
| - blacklisted_domains_.find(base::StringToLowerASCII(url.host()));
|
| - if (blacklisted_domains_.end() == it || it->second.count == 0)
|
| - return SDCH_OK;
|
| -
|
| - UMA_HISTOGRAM_ENUMERATION("Sdch3.BlacklistReason", it->second.reason,
|
| - SDCH_MAX_PROBLEM_CODE);
|
| -
|
| - int count = it->second.count - 1;
|
| - if (count > 0) {
|
| - it->second.count = count;
|
| - } else {
|
| - it->second.count = 0;
|
| - it->second.reason = SDCH_OK;
|
| - }
|
| -
|
| - return SDCH_DOMAIN_BLACKLIST_INCLUDES_TARGET;
|
| -}
|
| -
|
| -SdchProblemCode SdchManager::OnGetDictionary(const GURL& request_url,
|
| - const GURL& dictionary_url) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - SdchProblemCode rv = CanFetchDictionary(request_url, dictionary_url);
|
| - if (rv != SDCH_OK)
|
| - return rv;
|
| -
|
| - FOR_EACH_OBSERVER(SdchObserver,
|
| - observers_,
|
| - OnGetDictionary(this, request_url, dictionary_url));
|
| -
|
| - return SDCH_OK;
|
| -}
|
| -
|
| -void SdchManager::OnDictionaryUsed(const std::string& server_hash) {
|
| - FOR_EACH_OBSERVER(SdchObserver, observers_,
|
| - OnDictionaryUsed(this, server_hash));
|
| -}
|
| -
|
| -SdchProblemCode SdchManager::CanFetchDictionary(
|
| - const GURL& referring_url,
|
| - const GURL& dictionary_url) const {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - /* The user agent may retrieve a dictionary from the dictionary URL if all of
|
| - the following are true:
|
| - 1 The dictionary URL host name matches the referrer URL host name and
|
| - scheme.
|
| - 2 The dictionary URL host name domain matches the parent domain of the
|
| - referrer URL host name
|
| - 3 The parent domain of the referrer URL host name is not a top level
|
| - domain
|
| - */
|
| - // Item (1) above implies item (2). Spec should be updated.
|
| - // I take "host name match" to be "is identical to"
|
| - if (referring_url.host() != dictionary_url.host() ||
|
| - referring_url.scheme() != dictionary_url.scheme())
|
| - return SDCH_DICTIONARY_LOAD_ATTEMPT_FROM_DIFFERENT_HOST;
|
| -
|
| - if (!secure_scheme_supported() && referring_url.SchemeIsSecure())
|
| - return SDCH_DICTIONARY_SELECTED_FOR_SSL;
|
| -
|
| - // TODO(jar): Remove this failsafe conservative hack which is more restrictive
|
| - // than current SDCH spec when needed, and justified by security audit.
|
| - if (!referring_url.SchemeIsHTTPOrHTTPS())
|
| - return SDCH_DICTIONARY_SELECTED_FROM_NON_HTTP;
|
| -
|
| - return SDCH_OK;
|
| -}
|
| -
|
| -scoped_ptr<SdchManager::DictionarySet>
|
| -SdchManager::GetDictionarySet(const GURL& target_url) {
|
| - if (IsInSupportedDomain(target_url) != SDCH_OK)
|
| - return NULL;
|
| -
|
| - int count = 0;
|
| - scoped_ptr<SdchManager::DictionarySet> result(new DictionarySet);
|
| - for (const auto& entry: dictionaries_) {
|
| - if (entry.second->data.CanUse(target_url) != SDCH_OK)
|
| - continue;
|
| - if (entry.second->data.Expired())
|
| - continue;
|
| - ++count;
|
| - result->AddDictionary(entry.first, entry.second);
|
| - }
|
| -
|
| - if (count == 0)
|
| - return NULL;
|
| -
|
| - UMA_HISTOGRAM_COUNTS("Sdch3.Advertisement_Count", count);
|
| -
|
| - return result.Pass();
|
| -}
|
| -
|
| -scoped_ptr<SdchManager::DictionarySet>
|
| -SdchManager::GetDictionarySetByHash(
|
| - const GURL& target_url,
|
| - const std::string& server_hash,
|
| - SdchProblemCode* problem_code) {
|
| - scoped_ptr<SdchManager::DictionarySet> result;
|
| -
|
| - *problem_code = SDCH_DICTIONARY_HASH_NOT_FOUND;
|
| - const auto& it = dictionaries_.find(server_hash);
|
| - if (it == dictionaries_.end())
|
| - return result.Pass();
|
| -
|
| - *problem_code = it->second->data.CanUse(target_url);
|
| - if (*problem_code != SDCH_OK)
|
| - return result.Pass();
|
| -
|
| - result.reset(new DictionarySet);
|
| - result->AddDictionary(it->first, it->second);
|
| - return result.Pass();
|
| -}
|
| -
|
| -// static
|
| -void SdchManager::GenerateHash(const std::string& dictionary_text,
|
| - std::string* client_hash, std::string* server_hash) {
|
| - char binary_hash[32];
|
| - crypto::SHA256HashString(dictionary_text, binary_hash, sizeof(binary_hash));
|
| -
|
| - std::string first_48_bits(&binary_hash[0], 6);
|
| - std::string second_48_bits(&binary_hash[6], 6);
|
| - UrlSafeBase64Encode(first_48_bits, client_hash);
|
| - UrlSafeBase64Encode(second_48_bits, server_hash);
|
| -
|
| - DCHECK_EQ(server_hash->length(), 8u);
|
| - DCHECK_EQ(client_hash->length(), 8u);
|
| -}
|
| -
|
| -// Methods for supporting latency experiments.
|
| -
|
| -bool SdchManager::AllowLatencyExperiment(const GURL& url) const {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - return allow_latency_experiment_.end() !=
|
| - allow_latency_experiment_.find(url.host());
|
| -}
|
| -
|
| -void SdchManager::SetAllowLatencyExperiment(const GURL& url, bool enable) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - if (enable) {
|
| - allow_latency_experiment_.insert(url.host());
|
| - return;
|
| - }
|
| - ExperimentSet::iterator it = allow_latency_experiment_.find(url.host());
|
| - if (allow_latency_experiment_.end() == it)
|
| - return; // It was already erased, or never allowed.
|
| - SdchErrorRecovery(SDCH_LATENCY_TEST_DISALLOWED);
|
| - allow_latency_experiment_.erase(it);
|
| -}
|
| -
|
| -void SdchManager::AddObserver(SdchObserver* observer) {
|
| - observers_.AddObserver(observer);
|
| -}
|
| -
|
| -void SdchManager::RemoveObserver(SdchObserver* observer) {
|
| - observers_.RemoveObserver(observer);
|
| -}
|
| -
|
| -SdchProblemCode SdchManager::AddSdchDictionary(
|
| - const std::string& dictionary_text,
|
| - const GURL& dictionary_url,
|
| - std::string* server_hash_p) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - std::string client_hash;
|
| - std::string server_hash;
|
| - GenerateHash(dictionary_text, &client_hash, &server_hash);
|
| - if (dictionaries_.find(server_hash) != dictionaries_.end())
|
| - return SDCH_DICTIONARY_ALREADY_LOADED; // Already loaded.
|
| -
|
| - std::string domain, path;
|
| - std::set<int> ports;
|
| - base::Time expiration(base::Time::Now() + base::TimeDelta::FromDays(30));
|
| -
|
| - if (dictionary_text.empty())
|
| - return SDCH_DICTIONARY_HAS_NO_TEXT; // Missing header.
|
| -
|
| - size_t header_end = dictionary_text.find("\n\n");
|
| - if (std::string::npos == header_end)
|
| - return SDCH_DICTIONARY_HAS_NO_HEADER; // Missing header.
|
| -
|
| - size_t line_start = 0; // Start of line being parsed.
|
| - while (1) {
|
| - size_t line_end = dictionary_text.find('\n', line_start);
|
| - DCHECK(std::string::npos != line_end);
|
| - DCHECK_LE(line_end, header_end);
|
| -
|
| - size_t colon_index = dictionary_text.find(':', line_start);
|
| - if (std::string::npos == colon_index)
|
| - return SDCH_DICTIONARY_HEADER_LINE_MISSING_COLON; // Illegal line missing
|
| - // a colon.
|
| -
|
| - if (colon_index > line_end)
|
| - break;
|
| -
|
| - size_t value_start = dictionary_text.find_first_not_of(" \t",
|
| - colon_index + 1);
|
| - if (std::string::npos != value_start) {
|
| - if (value_start >= line_end)
|
| - break;
|
| - std::string name(dictionary_text, line_start, colon_index - line_start);
|
| - std::string value(dictionary_text, value_start, line_end - value_start);
|
| - name = base::StringToLowerASCII(name);
|
| - if (name == "domain") {
|
| - domain = value;
|
| - } else if (name == "path") {
|
| - path = value;
|
| - } else if (name == "format-version") {
|
| - if (value != "1.0")
|
| - return SDCH_DICTIONARY_UNSUPPORTED_VERSION;
|
| - } else if (name == "max-age") {
|
| - int64 seconds;
|
| - base::StringToInt64(value, &seconds);
|
| - expiration = base::Time::Now() + base::TimeDelta::FromSeconds(seconds);
|
| - } else if (name == "port") {
|
| - int port;
|
| - base::StringToInt(value, &port);
|
| - if (port >= 0)
|
| - ports.insert(port);
|
| - }
|
| - }
|
| -
|
| - if (line_end >= header_end)
|
| - break;
|
| - line_start = line_end + 1;
|
| - }
|
| -
|
| - // Narrow fix for http://crbug.com/389451.
|
| - GURL dictionary_url_normalized(dictionary_url);
|
| - StripTrailingDot(&dictionary_url_normalized);
|
| -
|
| - SdchProblemCode rv = IsInSupportedDomain(dictionary_url_normalized);
|
| - if (rv != SDCH_OK)
|
| - return rv;
|
| -
|
| - rv = Dictionary::CanSet(domain, path, ports, dictionary_url_normalized);
|
| - if (rv != SDCH_OK)
|
| - return rv;
|
| -
|
| - UMA_HISTOGRAM_COUNTS("Sdch3.Dictionary size loaded", dictionary_text.size());
|
| - DVLOG(1) << "Loaded dictionary with client hash " << client_hash
|
| - << " and server hash " << server_hash;
|
| - Dictionary dictionary(dictionary_text, header_end + 2, client_hash,
|
| - server_hash, dictionary_url_normalized, domain, path,
|
| - expiration, ports);
|
| - dictionaries_[server_hash] =
|
| - new base::RefCountedData<Dictionary>(dictionary);
|
| - if (server_hash_p)
|
| - *server_hash_p = server_hash;
|
| -
|
| - return SDCH_OK;
|
| -}
|
| -
|
| -SdchProblemCode SdchManager::RemoveSdchDictionary(
|
| - const std::string& server_hash) {
|
| - if (dictionaries_.find(server_hash) == dictionaries_.end())
|
| - return SDCH_DICTIONARY_HASH_NOT_FOUND;
|
| -
|
| - dictionaries_.erase(server_hash);
|
| - return SDCH_OK;
|
| -}
|
| -
|
| -// static
|
| -scoped_ptr<SdchManager::DictionarySet>
|
| -SdchManager::CreateEmptyDictionarySetForTesting() {
|
| - return scoped_ptr<DictionarySet>(new DictionarySet).Pass();
|
| -}
|
| -
|
| -// static
|
| -void SdchManager::UrlSafeBase64Encode(const std::string& input,
|
| - std::string* output) {
|
| - // Since this is only done during a dictionary load, and hashes are only 8
|
| - // characters, we just do the simple fixup, rather than rewriting the encoder.
|
| - base::Base64Encode(input, output);
|
| - std::replace(output->begin(), output->end(), '+', '-');
|
| - std::replace(output->begin(), output->end(), '/', '_');
|
| -}
|
| -
|
| -base::Value* SdchManager::SdchInfoToValue() const {
|
| - base::DictionaryValue* value = new base::DictionaryValue();
|
| -
|
| - value->SetBoolean("sdch_enabled", sdch_enabled());
|
| - value->SetBoolean("secure_scheme_support", secure_scheme_supported());
|
| -
|
| - base::ListValue* entry_list = new base::ListValue();
|
| - for (const auto& entry: dictionaries_) {
|
| - base::DictionaryValue* entry_dict = new base::DictionaryValue();
|
| - entry_dict->SetString("url", entry.second->data.url().spec());
|
| - entry_dict->SetString("client_hash", entry.second->data.client_hash());
|
| - entry_dict->SetString("domain", entry.second->data.domain());
|
| - entry_dict->SetString("path", entry.second->data.path());
|
| - base::ListValue* port_list = new base::ListValue();
|
| - for (std::set<int>::const_iterator port_it =
|
| - entry.second->data.ports().begin();
|
| - port_it != entry.second->data.ports().end(); ++port_it) {
|
| - port_list->AppendInteger(*port_it);
|
| - }
|
| - entry_dict->Set("ports", port_list);
|
| - entry_dict->SetString("server_hash", entry.first);
|
| - entry_list->Append(entry_dict);
|
| - }
|
| - value->Set("dictionaries", entry_list);
|
| -
|
| - entry_list = new base::ListValue();
|
| - for (DomainBlacklistInfo::const_iterator it = blacklisted_domains_.begin();
|
| - it != blacklisted_domains_.end(); ++it) {
|
| - if (it->second.count == 0)
|
| - continue;
|
| - base::DictionaryValue* entry_dict = new base::DictionaryValue();
|
| - entry_dict->SetString("domain", it->first);
|
| - if (it->second.count != INT_MAX)
|
| - entry_dict->SetInteger("tries", it->second.count);
|
| - entry_dict->SetInteger("reason", it->second.reason);
|
| - entry_list->Append(entry_dict);
|
| - }
|
| - value->Set("blacklisted", entry_list);
|
| -
|
| - return value;
|
| -}
|
| -
|
| -} // namespace net
|
|
|