// Copyright 2014 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. // Make sure stdint.h includes SIZE_MAX. (See C89, p259, footnote 221.) #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include "components/domain_reliability/config.h" #include <stdint.h> #include "base/json/json_reader.h" #include "base/json/json_value_converter.h" #include "base/rand_util.h" #include "base/strings/string_util.h" namespace { bool ConvertURL(const base::StringPiece& string_piece, GURL* url) { *url = GURL(string_piece.as_string()); return url->is_valid(); } bool IsValidSampleRate(double p) { return p >= 0.0 && p <= 1.0; } } // namespace namespace domain_reliability { // static const size_t DomainReliabilityConfig::kInvalidResourceIndex = SIZE_MAX; DomainReliabilityConfig::Resource::Resource() { } DomainReliabilityConfig::Resource::~Resource() {} bool DomainReliabilityConfig::Resource::MatchesUrl(const GURL& url) const { const std::string& spec = url.spec(); ScopedVector<std::string>::const_iterator it; for (it = url_patterns.begin(); it != url_patterns.end(); it++) { if (MatchPattern(spec, **it)) return true; } return false; } bool DomainReliabilityConfig::Resource::DecideIfShouldReportRequest( bool success) const { double sample_rate = success ? success_sample_rate : failure_sample_rate; DCHECK(IsValidSampleRate(sample_rate)); return base::RandDouble() < sample_rate; } // static void DomainReliabilityConfig::Resource::RegisterJSONConverter( base::JSONValueConverter<DomainReliabilityConfig::Resource>* converter) { converter->RegisterStringField("resource_name", &Resource::name); converter->RegisterRepeatedString("url_patterns", &Resource::url_patterns); converter->RegisterDoubleField("success_sample_rate", &Resource::success_sample_rate); converter->RegisterDoubleField("failure_sample_rate", &Resource::failure_sample_rate); } bool DomainReliabilityConfig::Resource::IsValid() const { return !name.empty() && !url_patterns.empty() && IsValidSampleRate(success_sample_rate) && IsValidSampleRate(failure_sample_rate); } DomainReliabilityConfig::Collector::Collector() {} DomainReliabilityConfig::Collector::~Collector() {} // static void DomainReliabilityConfig::Collector::RegisterJSONConverter( base::JSONValueConverter<DomainReliabilityConfig::Collector>* converter) { converter->RegisterCustomField<GURL>("upload_url", &Collector::upload_url, &ConvertURL); } bool DomainReliabilityConfig::Collector::IsValid() const { return upload_url.is_valid(); } DomainReliabilityConfig::DomainReliabilityConfig() : valid_until(0.0) {} DomainReliabilityConfig::~DomainReliabilityConfig() {} // static scoped_ptr<const DomainReliabilityConfig> DomainReliabilityConfig::FromJSON( const base::StringPiece& json) { scoped_ptr<base::Value> value(base::JSONReader::Read(json)); base::JSONValueConverter<DomainReliabilityConfig> converter; DomainReliabilityConfig* config = new DomainReliabilityConfig(); // If we can parse and convert the JSON into a valid config, return that. if (value && converter.Convert(*value, config) && config->IsValid()) return scoped_ptr<const DomainReliabilityConfig>(config); else return scoped_ptr<const DomainReliabilityConfig>(); } bool DomainReliabilityConfig::IsValid() const { if (valid_until == 0.0 || domain.empty() || resources.empty() || collectors.empty()) { return false; } for (size_t i = 0; i < resources.size(); ++i) { if (!resources[i]->IsValid()) return false; } for (size_t i = 0; i < collectors.size(); ++i) { if (!collectors[i]->IsValid()) return false; } return true; } bool DomainReliabilityConfig::IsExpired(base::Time now) const { DCHECK_NE(0.0, valid_until); base::Time valid_until_time = base::Time::FromDoubleT(valid_until); return now > valid_until_time; } size_t DomainReliabilityConfig::GetResourceIndexForUrl(const GURL& url) const { // Removes username, password, and fragment. GURL sanitized_url = url.GetAsReferrer(); for (size_t i = 0; i < resources.size(); ++i) { if (resources[i]->MatchesUrl(sanitized_url)) return i; } return kInvalidResourceIndex; } // static void DomainReliabilityConfig::RegisterJSONConverter( base::JSONValueConverter<DomainReliabilityConfig>* converter) { converter->RegisterStringField("config_version", &DomainReliabilityConfig::version); converter->RegisterDoubleField("config_valid_until", &DomainReliabilityConfig::valid_until); converter->RegisterStringField("monitored_domain", &DomainReliabilityConfig::domain); converter->RegisterRepeatedMessage("monitored_resources", &DomainReliabilityConfig::resources); converter->RegisterRepeatedMessage("collectors", &DomainReliabilityConfig::collectors); } } // namespace domain_reliability