blob: 54d5eaa176e7f978770bec4df59c9f2b2565d3d0 [file] [log] [blame]
// 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>
namespace domain_reliability {
DomainReliabilityContextManager::DomainReliabilityContextManager(
DomainReliabilityContext::Factory* context_factory)
: context_factory_(context_factory) {
}
DomainReliabilityContextManager::~DomainReliabilityContextManager() {
RemoveAllContexts();
}
void DomainReliabilityContextManager::RouteBeacon(
std::unique_ptr<DomainReliabilityBeacon> beacon) {
DomainReliabilityContext* context = GetContextForHost(beacon->url.host());
if (!context)
return;
context->OnBeacon(std::move(beacon));
}
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.
if (contexts_[key]->config().Equals(*config)) {
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::ClearBeaconsInAllContexts() {
for (auto& context_entry : contexts_)
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::RemoveAllContexts() {
STLDeleteContainerPairSecondPointers(
contexts_.begin(), contexts_.end());
contexts_.clear();
}
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