// Copyright 2020 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/scheme_host_port_matcher.h" #include "base/containers/adapters.h" #include "base/containers/contains.h" #include "base/strings/string_tokenizer.h" #include "base/strings/string_util.h" namespace net { // Declares SchemeHostPortMatcher::kParseRuleListDelimiterList[], not a // redefinition. This is needed for link. // static constexpr char SchemeHostPortMatcher::kParseRuleListDelimiterList[]; // Declares SchemeHostPortMatcher::kPrintRuleListDelimiter, not a // redefinition. This is needed for link. // static constexpr char SchemeHostPortMatcher::kPrintRuleListDelimiter; // static SchemeHostPortMatcher SchemeHostPortMatcher::FromRawString( const std::string& raw) { SchemeHostPortMatcher result; base::StringTokenizer entries(raw, kParseRuleListDelimiterList); while (entries.GetNext()) { auto rule = SchemeHostPortMatcherRule::FromUntrimmedRawString( entries.token_piece()); if (rule) { result.AddAsLastRule(std::move(rule)); } } return result; } void SchemeHostPortMatcher::AddAsFirstRule( std::unique_ptr rule) { DCHECK(rule); rules_.insert(rules_.begin(), std::move(rule)); } void SchemeHostPortMatcher::AddAsLastRule( std::unique_ptr rule) { DCHECK(rule); rules_.push_back(std::move(rule)); } void SchemeHostPortMatcher::ReplaceRule( size_t index, std::unique_ptr rule) { DCHECK_LT(index, rules_.size()); rules_[index] = std::move(rule); } bool SchemeHostPortMatcher::Includes(const GURL& url) const { return Evaluate(url) == SchemeHostPortMatcherResult::kInclude; } SchemeHostPortMatcherResult SchemeHostPortMatcher::Evaluate( const GURL& url) const { // Later rules override earlier rules, so evaluating the rule list can be // done by iterating over it in reverse and short-circuiting when a match is // found. // // The order of evaluation generally doesn't matter if all the rules are // positive rules, so matches are just additive. // // However when mixing positive and negative rules, evaluation order makes a // difference. for (const auto& rule : base::Reversed(rules_)) { SchemeHostPortMatcherResult result = rule->Evaluate(url); if (result != SchemeHostPortMatcherResult::kNoMatch) return result; } return SchemeHostPortMatcherResult::kNoMatch; } std::string SchemeHostPortMatcher::ToString() const { std::string result; for (const auto& rule : rules_) { DCHECK(!base::Contains(rule->ToString(), kParseRuleListDelimiterList)); result += rule->ToString(); result.push_back(kPrintRuleListDelimiter); } return result; } void SchemeHostPortMatcher::Clear() { rules_.clear(); } } // namespace net