origin_matcher.cc 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  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. #include "components/js_injection/common/origin_matcher.h"
  5. #include "base/containers/adapters.h"
  6. #include "components/js_injection/common/origin_matcher_internal.h"
  7. #include "net/base/ip_address.h"
  8. #include "net/base/ip_endpoint.h"
  9. #include "net/base/parse_number.h"
  10. #include "net/base/url_util.h"
  11. #include "url/gurl.h"
  12. #include "url/origin.h"
  13. #include "url/url_constants.h"
  14. #include "url/url_util.h"
  15. namespace js_injection {
  16. namespace {
  17. inline int GetDefaultPortForSchemeIfNoPortInfo(const std::string& scheme,
  18. int port) {
  19. // The input has explicit port information, so don't modify it.
  20. if (port != -1)
  21. return port;
  22. // Hard code the port for http and https.
  23. if (scheme == url::kHttpScheme)
  24. return 80;
  25. if (scheme == url::kHttpsScheme)
  26. return 443;
  27. return port;
  28. }
  29. } // namespace
  30. OriginMatcher::OriginMatcher(const OriginMatcher& rhs) {
  31. *this = rhs;
  32. }
  33. OriginMatcher& OriginMatcher::operator=(const OriginMatcher& rhs) {
  34. rules_.clear();
  35. for (const auto& rule : rhs.Serialize())
  36. AddRuleFromString(rule);
  37. return *this;
  38. }
  39. void OriginMatcher::SetRules(RuleList rules) {
  40. rules_.swap(rules);
  41. }
  42. bool OriginMatcher::AddRuleFromString(const std::string& raw_untrimmed) {
  43. std::string raw;
  44. base::TrimWhitespaceASCII(raw_untrimmed, base::TRIM_ALL, &raw);
  45. if (raw == "*") {
  46. rules_.push_back(std::make_unique<MatchAllOriginsRule>());
  47. return true;
  48. }
  49. // Extract scheme-restriction.
  50. std::string::size_type scheme_pos = raw.find("://");
  51. if (scheme_pos == std::string::npos)
  52. return false;
  53. const std::string scheme = raw.substr(0, scheme_pos);
  54. if (!SubdomainMatchingRule::IsValidScheme(scheme))
  55. return false;
  56. std::string host_and_port = raw.substr(scheme_pos + 3);
  57. if (host_and_port.empty()) {
  58. if (!SubdomainMatchingRule::IsValidSchemeAndHost(scheme, std::string()))
  59. return false;
  60. rules_.push_back(
  61. std::make_unique<SubdomainMatchingRule>(scheme, std::string(), -1));
  62. return true;
  63. }
  64. std::string host;
  65. int port;
  66. if (!net::ParseHostAndPort(host_and_port, &host, &port) ||
  67. !SubdomainMatchingRule::IsValidSchemeAndHost(scheme, host)) {
  68. return false;
  69. }
  70. // Check if we have an <ip-address>[:port] input and try to canonicalize the
  71. // IP literal.
  72. net::IPAddress ip_address;
  73. if (ip_address.AssignFromIPLiteral(host)) {
  74. port = GetDefaultPortForSchemeIfNoPortInfo(scheme, port);
  75. host = ip_address.ToString();
  76. if (ip_address.IsIPv6())
  77. host = '[' + host + ']';
  78. rules_.push_back(
  79. std::make_unique<SubdomainMatchingRule>(scheme, host, port));
  80. return true;
  81. }
  82. port = GetDefaultPortForSchemeIfNoPortInfo(scheme, port);
  83. rules_.push_back(std::make_unique<SubdomainMatchingRule>(scheme, host, port));
  84. return true;
  85. }
  86. bool OriginMatcher::Matches(const url::Origin& origin) const {
  87. GURL origin_url = origin.GetURL();
  88. // Since we only do kInclude vs kNoMatch, the order doesn't actually matter.
  89. for (const std::unique_ptr<OriginMatcherRule>& rule :
  90. base::Reversed(rules_)) {
  91. net::SchemeHostPortMatcherResult result = rule->Evaluate(origin_url);
  92. if (result == net::SchemeHostPortMatcherResult::kInclude)
  93. return true;
  94. }
  95. return false;
  96. }
  97. std::vector<std::string> OriginMatcher::Serialize() const {
  98. std::vector<std::string> result;
  99. result.reserve(rules_.size());
  100. for (const auto& rule : rules_) {
  101. result.push_back(rule->ToString());
  102. }
  103. return result;
  104. }
  105. } // namespace js_injection