1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/base/scheme_host_port_matcher.h"
6 
7 #include "base/strings/string_tokenizer.h"
8 #include "base/strings/string_util.h"
9 
10 namespace net {
11 
12 // Declares SchemeHostPortMatcher::kParseRuleListDelimiterList[], not a
13 // redefinition. This is needed for link.
14 // static
15 constexpr char SchemeHostPortMatcher::kParseRuleListDelimiterList[];
16 
17 // Declares SchemeHostPortMatcher::kPrintRuleListDelimiter, not a
18 // redefinition. This is needed for link.
19 // static
20 constexpr char SchemeHostPortMatcher::kPrintRuleListDelimiter;
21 
22 // static
FromRawString(const std::string & raw)23 SchemeHostPortMatcher SchemeHostPortMatcher::FromRawString(
24     const std::string& raw) {
25   SchemeHostPortMatcher result;
26 
27   base::StringTokenizer entries(raw, kParseRuleListDelimiterList);
28   while (entries.GetNext()) {
29     auto rule =
30         SchemeHostPortMatcherRule::FromUntrimmedRawString(entries.token());
31     if (rule) {
32       result.AddAsLastRule(std::move(rule));
33     }
34   }
35 
36   return result;
37 }
38 
AddAsFirstRule(std::unique_ptr<SchemeHostPortMatcherRule> rule)39 void SchemeHostPortMatcher::AddAsFirstRule(
40     std::unique_ptr<SchemeHostPortMatcherRule> rule) {
41   DCHECK(rule);
42   rules_.insert(rules_.begin(), std::move(rule));
43 }
44 
AddAsLastRule(std::unique_ptr<SchemeHostPortMatcherRule> rule)45 void SchemeHostPortMatcher::AddAsLastRule(
46     std::unique_ptr<SchemeHostPortMatcherRule> rule) {
47   DCHECK(rule);
48   rules_.push_back(std::move(rule));
49 }
50 
ReplaceRule(size_t index,std::unique_ptr<SchemeHostPortMatcherRule> rule)51 void SchemeHostPortMatcher::ReplaceRule(
52     size_t index,
53     std::unique_ptr<SchemeHostPortMatcherRule> rule) {
54   DCHECK_LT(index, rules_.size());
55   rules_[index] = std::move(rule);
56 }
57 
Includes(const GURL & url) const58 bool SchemeHostPortMatcher::Includes(const GURL& url) const {
59   return Evaluate(url) == SchemeHostPortMatcherResult::kInclude;
60 }
61 
Evaluate(const GURL & url) const62 SchemeHostPortMatcherResult SchemeHostPortMatcher::Evaluate(
63     const GURL& url) const {
64   // Later rules override earlier rules, so evaluating the rule list can be
65   // done by iterating over it in reverse and short-circuiting when a match is
66   // found.
67   //
68   // The order of evaluation generally doesn't matter if all the rules are
69   // positive rules, so matches are just additive.
70   //
71   // However when mixing positive and negative rules, evaluation order makes a
72   // difference.
73   for (auto it = rules_.rbegin(); it != rules_.rend(); ++it) {
74     SchemeHostPortMatcherResult result = (*it)->Evaluate(url);
75     if (result != SchemeHostPortMatcherResult::kNoMatch)
76       return result;
77   }
78 
79   return SchemeHostPortMatcherResult::kNoMatch;
80 }
81 
ToString() const82 std::string SchemeHostPortMatcher::ToString() const {
83   std::string result;
84   for (const auto& rule : rules_) {
85     DCHECK(!base::Contains(rule->ToString(), kParseRuleListDelimiterList));
86     result += rule->ToString();
87     result.push_back(kPrintRuleListDelimiter);
88   }
89   return result;
90 }
91 
Clear()92 void SchemeHostPortMatcher::Clear() {
93   rules_.clear();
94 }
95 
96 }  // namespace net
97