url_rule_util_unittest.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. // Copyright 2018 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/url_pattern_index/url_rule_util.h"
  5. #include <cmath>
  6. #include <string>
  7. #include <utility>
  8. #include <vector>
  9. #include "base/strings/string_piece.h"
  10. #include "components/url_pattern_index/flat/url_pattern_index_generated.h"
  11. #include "components/url_pattern_index/url_pattern.h"
  12. #include "components/url_pattern_index/url_pattern_index.h"
  13. #include "components/url_pattern_index/url_rule_test_support.h"
  14. #include "testing/gtest/include/gtest/gtest.h"
  15. #include "url/gurl.h"
  16. #include "url/origin.h"
  17. namespace url_pattern_index {
  18. namespace {
  19. proto::UrlRule MakeProtoRule(proto::RuleSemantics semantics,
  20. const UrlPattern& url_pattern,
  21. proto::SourceType source_type,
  22. proto::ElementType types,
  23. const std::vector<std::string>& domains) {
  24. proto::UrlRule rule;
  25. rule.set_semantics(semantics);
  26. rule.set_source_type(source_type);
  27. rule.set_element_types(types);
  28. rule.set_url_pattern_type(url_pattern.type());
  29. rule.set_anchor_left(url_pattern.anchor_left());
  30. rule.set_anchor_right(url_pattern.anchor_right());
  31. rule.set_match_case(url_pattern.match_case());
  32. rule.set_url_pattern(std::string(url_pattern.url_pattern()));
  33. testing::AddInitiatorDomains(domains, &rule);
  34. return rule;
  35. }
  36. struct RuleTest {
  37. const char* rule_string;
  38. const char* match_string;
  39. };
  40. class UrlRuleUtilTest : public ::testing::Test {
  41. public:
  42. UrlRuleUtilTest(const UrlRuleUtilTest&) = delete;
  43. UrlRuleUtilTest& operator=(const UrlRuleUtilTest&) = delete;
  44. protected:
  45. UrlRuleUtilTest() = default;
  46. const flat::UrlRule* MakeFlatRule(const proto::UrlRule& rule) {
  47. auto offset =
  48. url_pattern_index::SerializeUrlRule(rule, &flat_builder_, &domain_map_);
  49. return flatbuffers::GetTemporaryPointer(flat_builder_, offset);
  50. }
  51. const flat::UrlRule* MakeFlatRule(const std::string& pattern,
  52. uint16_t flat_element_types_mask) {
  53. auto pattern_offset = flat_builder_.CreateString(pattern);
  54. flat::UrlRuleBuilder rule_builder(flat_builder_);
  55. rule_builder.add_url_pattern(pattern_offset);
  56. rule_builder.add_element_types(flat_element_types_mask);
  57. auto offset = rule_builder.Finish();
  58. return flatbuffers::GetTemporaryPointer(flat_builder_, offset);
  59. }
  60. flatbuffers::FlatBufferBuilder flat_builder_;
  61. FlatDomainMap domain_map_;
  62. };
  63. TEST_F(UrlRuleUtilTest, Blocklist) {
  64. const flat::UrlRule* flat_rule = MakeFlatRule(
  65. MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("example.com/"),
  66. proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
  67. EXPECT_EQ("example.com/", FlatUrlRuleToFilterlistString(flat_rule));
  68. }
  69. TEST_F(UrlRuleUtilTest, Allowlist) {
  70. const flat::UrlRule* flat_rule = MakeFlatRule(
  71. MakeProtoRule(proto::RULE_SEMANTICS_ALLOWLIST, UrlPattern("example.com/"),
  72. proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
  73. EXPECT_EQ("@@example.com/", FlatUrlRuleToFilterlistString(flat_rule));
  74. }
  75. TEST_F(UrlRuleUtilTest, LeftAnchor) {
  76. const flat::UrlRule* flat_rule = MakeFlatRule(
  77. MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST,
  78. UrlPattern("example.com/", proto::ANCHOR_TYPE_NONE,
  79. proto::ANCHOR_TYPE_NONE),
  80. proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
  81. EXPECT_EQ("example.com/", FlatUrlRuleToFilterlistString(flat_rule));
  82. flat_rule = MakeFlatRule(
  83. MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST,
  84. UrlPattern("example.com/", proto::ANCHOR_TYPE_BOUNDARY,
  85. proto::ANCHOR_TYPE_NONE),
  86. proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
  87. EXPECT_EQ("|example.com/", FlatUrlRuleToFilterlistString(flat_rule));
  88. flat_rule = MakeFlatRule(
  89. MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST,
  90. UrlPattern("example.com/", proto::ANCHOR_TYPE_SUBDOMAIN,
  91. proto::ANCHOR_TYPE_NONE),
  92. proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
  93. EXPECT_EQ("||example.com/", FlatUrlRuleToFilterlistString(flat_rule));
  94. }
  95. TEST_F(UrlRuleUtilTest, RightAnchor) {
  96. const flat::UrlRule* flat_rule = MakeFlatRule(
  97. MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST,
  98. UrlPattern("example.com", proto::ANCHOR_TYPE_NONE,
  99. proto::ANCHOR_TYPE_NONE),
  100. proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
  101. EXPECT_EQ("example.com", FlatUrlRuleToFilterlistString(flat_rule));
  102. flat_rule = MakeFlatRule(
  103. MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST,
  104. UrlPattern("example.com", proto::ANCHOR_TYPE_NONE,
  105. proto::ANCHOR_TYPE_BOUNDARY),
  106. proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
  107. EXPECT_EQ("example.com|", FlatUrlRuleToFilterlistString(flat_rule));
  108. }
  109. TEST_F(UrlRuleUtilTest, BothSidesAnchored) {
  110. const flat::UrlRule* flat_rule = MakeFlatRule(
  111. MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST,
  112. UrlPattern("example.com", proto::ANCHOR_TYPE_SUBDOMAIN,
  113. proto::ANCHOR_TYPE_BOUNDARY),
  114. proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
  115. EXPECT_EQ("||example.com|", FlatUrlRuleToFilterlistString(flat_rule));
  116. }
  117. TEST_F(UrlRuleUtilTest, NonRegex) {
  118. const flat::UrlRule* flat_rule = MakeFlatRule(
  119. MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("/foo/"),
  120. proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
  121. EXPECT_EQ("/foo/*", FlatUrlRuleToFilterlistString(flat_rule));
  122. // Show that allowlist rules work too.
  123. flat_rule = MakeFlatRule(
  124. MakeProtoRule(proto::RULE_SEMANTICS_ALLOWLIST, UrlPattern("/foo/"),
  125. proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
  126. EXPECT_EQ("@@/foo/*", FlatUrlRuleToFilterlistString(flat_rule));
  127. // TODO(jkarlin): If regex support is added to UrlRule, verify that regex
  128. // rules don't get the '*' appended.
  129. }
  130. TEST_F(UrlRuleUtilTest, Party) {
  131. const flat::UrlRule* flat_rule = MakeFlatRule(MakeProtoRule(
  132. proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("example.com/"),
  133. proto::SOURCE_TYPE_THIRD_PARTY, proto::ELEMENT_TYPE_ALL, {}));
  134. EXPECT_EQ("example.com/$third-party",
  135. FlatUrlRuleToFilterlistString(flat_rule));
  136. flat_rule = MakeFlatRule(MakeProtoRule(
  137. proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("example.com/"),
  138. proto::SOURCE_TYPE_FIRST_PARTY, proto::ELEMENT_TYPE_ALL, {}));
  139. EXPECT_EQ("example.com/$~third-party",
  140. FlatUrlRuleToFilterlistString(flat_rule));
  141. }
  142. TEST_F(UrlRuleUtilTest, MultipleOptions) {
  143. const flat::UrlRule* flat_rule = MakeFlatRule(MakeProtoRule(
  144. proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("example.com/"),
  145. proto::SOURCE_TYPE_THIRD_PARTY, proto::ELEMENT_TYPE_SCRIPT, {}));
  146. EXPECT_EQ("example.com/$third-party,script",
  147. FlatUrlRuleToFilterlistString(flat_rule));
  148. }
  149. TEST_F(UrlRuleUtilTest, ElementType) {
  150. // Test a single type.
  151. const flat::UrlRule* flat_rule = MakeFlatRule(
  152. MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("example.com/"),
  153. proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_SCRIPT, {}));
  154. EXPECT_EQ("example.com/$script", FlatUrlRuleToFilterlistString(flat_rule));
  155. // Test blocking every type.
  156. flat_rule = MakeFlatRule(
  157. MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("example.com/"),
  158. proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
  159. EXPECT_EQ("example.com/", FlatUrlRuleToFilterlistString(flat_rule));
  160. // Block everything except other. This test will need to be updated as
  161. // proto::ElementType is changed.
  162. flat_rule = MakeFlatRule(MakeProtoRule(
  163. proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("example.com/"),
  164. proto::SOURCE_TYPE_ANY,
  165. static_cast<proto::ElementType>(proto::ELEMENT_TYPE_ALL - 1), {}));
  166. std::string expected =
  167. "example.com/"
  168. "$script,image,stylesheet,object,xmlhttprequest,object-subrequest,"
  169. "subdocument,ping,media,font,websocket,webtransport,webbundle";
  170. EXPECT_EQ(expected, FlatUrlRuleToFilterlistString(flat_rule));
  171. }
  172. TEST_F(UrlRuleUtilTest, ActivationType) {
  173. // Test with no activiation type.
  174. const flat::UrlRule* flat_rule = MakeFlatRule(
  175. MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("example.com/"),
  176. proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
  177. EXPECT_EQ("example.com/", FlatUrlRuleToFilterlistString(flat_rule));
  178. // Test with a document activation type.
  179. auto proto_rule =
  180. MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("example.com/"),
  181. proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {});
  182. proto_rule.set_activation_types(proto::ACTIVATION_TYPE_DOCUMENT);
  183. flat_rule = MakeFlatRule(proto_rule);
  184. EXPECT_EQ("example.com/$document", FlatUrlRuleToFilterlistString(flat_rule));
  185. // Test with Document & Generic block types.
  186. proto_rule.set_activation_types(proto::ACTIVATION_TYPE_DOCUMENT |
  187. proto::ACTIVATION_TYPE_GENERICBLOCK);
  188. flat_rule = MakeFlatRule(proto_rule);
  189. EXPECT_EQ("example.com/$document,genericblock",
  190. FlatUrlRuleToFilterlistString(flat_rule));
  191. }
  192. TEST_F(UrlRuleUtilTest, DomainList) {
  193. // Test with no domains set.
  194. const flat::UrlRule* flat_rule = MakeFlatRule(
  195. MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("example.com/"),
  196. proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
  197. EXPECT_EQ("example.com/", FlatUrlRuleToFilterlistString(flat_rule));
  198. // Test with domains set.
  199. flat_rule = MakeFlatRule(
  200. MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("example.com/"),
  201. proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL,
  202. {"foo.example.com", "~bar.example.com"}));
  203. EXPECT_EQ("example.com/$domain=foo.example.com|~bar.example.com",
  204. FlatUrlRuleToFilterlistString(flat_rule));
  205. }
  206. // Ensures that MAIN_FRAME and CSP_REPORT types are ignored since Filterlist
  207. // does not support these.
  208. TEST_F(UrlRuleUtilTest, IgnoredTypes) {
  209. const flat::UrlRule* flat_rule =
  210. MakeFlatRule("example.com/", flat::ElementType_MAIN_FRAME |
  211. flat::ElementType_CSP_REPORT |
  212. flat::ElementType_SCRIPT);
  213. EXPECT_EQ("example.com/$script", FlatUrlRuleToFilterlistString(flat_rule));
  214. }
  215. } // namespace
  216. } // namespace url_pattern_index