1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
// Copyright 2015 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 "components/domain_reliability/context_manager.h"
#include <utility>
#include "base/metrics/histogram_macros.h"
namespace domain_reliability {
DomainReliabilityContextManager::DomainReliabilityContextManager(
DomainReliabilityContext::Factory* context_factory)
: context_factory_(context_factory) {
}
DomainReliabilityContextManager::~DomainReliabilityContextManager() {
RemoveContexts(
base::Callback<bool(const GURL&)>() /* no filter - delete everything */);
}
void DomainReliabilityContextManager::RouteBeacon(
std::unique_ptr<DomainReliabilityBeacon> beacon) {
DomainReliabilityContext* context = GetContextForHost(beacon->url.host());
if (!context)
return;
bool queued = context->OnBeacon(std::move(beacon));
if (!queued)
return;
base::TimeTicks now = base::TimeTicks::Now();
if (!last_routed_beacon_time_.is_null()) {
UMA_HISTOGRAM_LONG_TIMES("DomainReliability.BeaconIntervalGlobal",
now - last_routed_beacon_time_);
}
last_routed_beacon_time_ = now;
}
void DomainReliabilityContextManager::SetConfig(
const GURL& origin,
std::unique_ptr<DomainReliabilityConfig> config,
base::TimeDelta max_age) {
std::string key = origin.host();
if (!contexts_.count(key) && !removed_contexts_.count(key)) {
LOG(WARNING) << "Ignoring NEL header for unknown origin " << origin.spec()
<< ".";
return;
}
if (contexts_.count(key)) {
// Currently, there is no easy way to change the config of a context, so
// updating the config requires recreating the context, which loses
// pending beacons and collector backoff state. Therefore, don't do so
// needlessly; make sure the config has actually changed before recreating
// the context.
bool config_same = contexts_[key]->config().Equals(*config);
UMA_HISTOGRAM_BOOLEAN("DomainReliability.SetConfigRecreatedContext",
!config_same);
if (!config_same) {
DVLOG(1) << "Ignoring unchanged NEL header for existing origin "
<< origin.spec() << ".";
return;
}
// TODO(juliatuttle): Make Context accept Config changes.
}
DVLOG(1) << "Adding/replacing context for existing origin " << origin.spec()
<< ".";
removed_contexts_.erase(key);
config->origin = origin;
AddContextForConfig(std::move(config));
}
void DomainReliabilityContextManager::ClearConfig(const GURL& origin) {
std::string key = origin.host();
if (contexts_.count(key)) {
DVLOG(1) << "Removing context for existing origin " << origin.spec() << ".";
contexts_.erase(key);
removed_contexts_.insert(key);
}
}
void DomainReliabilityContextManager::ClearBeacons(
const base::Callback<bool(const GURL&)>& origin_filter) {
for (auto& context_entry : contexts_) {
if (origin_filter.is_null() ||
origin_filter.Run(context_entry.second->config().origin)) {
context_entry.second->ClearBeacons();
}
}
}
DomainReliabilityContext* DomainReliabilityContextManager::AddContextForConfig(
std::unique_ptr<const DomainReliabilityConfig> config) {
std::string key = config->origin.host();
// TODO(juliatuttle): Convert this to actual origin.
std::unique_ptr<DomainReliabilityContext> context =
context_factory_->CreateContextForConfig(std::move(config));
DomainReliabilityContext** entry = &contexts_[key];
if (*entry)
delete *entry;
*entry = context.release();
return *entry;
}
void DomainReliabilityContextManager::RemoveContexts(
const base::Callback<bool(const GURL&)>& origin_filter) {
for (ContextMap::iterator it = contexts_.begin(); it != contexts_.end(); ) {
if (!origin_filter.is_null() &&
!origin_filter.Run(it->second->config().origin)) {
++it;
continue;
}
delete it->second;
it = contexts_.erase(it);
}
}
std::unique_ptr<base::Value> DomainReliabilityContextManager::GetWebUIData()
const {
std::unique_ptr<base::ListValue> contexts_value(new base::ListValue());
for (const auto& context_entry : contexts_)
contexts_value->Append(context_entry.second->GetWebUIData());
return std::move(contexts_value);
}
DomainReliabilityContext* DomainReliabilityContextManager::GetContextForHost(
const std::string& host) {
ContextMap::const_iterator context_it;
context_it = contexts_.find(host);
if (context_it != contexts_.end())
return context_it->second;
size_t dot_pos = host.find('.');
if (dot_pos == std::string::npos)
return nullptr;
// TODO(juliatuttle): Make sure parent is not in PSL before using.
std::string parent_host = host.substr(dot_pos + 1);
context_it = contexts_.find(parent_host);
if (context_it != contexts_.end()
&& context_it->second->config().include_subdomains) {
return context_it->second;
}
return nullptr;
}
} // namespace domain_reliability
|