// 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 namespace domain_reliability { DomainReliabilityContextManager::DomainReliabilityContextManager( DomainReliabilityContext::Factory* context_factory) : context_factory_(context_factory) { } DomainReliabilityContextManager::~DomainReliabilityContextManager() { RemoveAllContexts(); } void DomainReliabilityContextManager::RouteBeacon( scoped_ptr beacon) { DomainReliabilityContext* context = GetContextForHost(beacon->url.host()); if (!context) return; context->OnBeacon(std::move(beacon)); } void DomainReliabilityContextManager::SetConfig( const GURL& origin, scoped_ptr 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(ttuttle): 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( scoped_ptr config) { std::string key = config->origin.host(); // TODO(ttuttle): Convert this to actual origin. scoped_ptr 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(); } scoped_ptr DomainReliabilityContextManager::GetWebUIData() const { scoped_ptr contexts_value(new base::ListValue()); for (const auto& context_entry : contexts_) contexts_value->Append(context_entry.second->GetWebUIData().release()); 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(ttuttle): 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