| // Copyright 2018 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/url_pattern_index/url_rule_util.h" |
| |
| #include "base/macros.h" |
| #include "base/strings/string_util.h" |
| #include "components/url_pattern_index/flat/url_pattern_index_generated.h" |
| |
| namespace url_pattern_index { |
| |
| namespace { |
| |
| std::string AnchorToString(url_pattern_index::flat::AnchorType anchor_type) { |
| switch (anchor_type) { |
| case url_pattern_index::flat::AnchorType_NONE: |
| return std::string(); |
| case url_pattern_index::flat::AnchorType_SUBDOMAIN: |
| return "||"; |
| case url_pattern_index::flat::AnchorType_BOUNDARY: |
| return "|"; |
| } |
| NOTREACHED(); |
| return std::string(); |
| } |
| |
| // Class that aids in appending options to a pretty-printed rule. |
| class OptionsPrinter { |
| public: |
| OptionsPrinter() = default; |
| |
| // If this is the first printed option for the rule, add a $ separator, |
| // otherwise a comma. |
| std::string PrintOption(const std::string& option) { |
| std::string out = printed_options_ ? "," : "$"; |
| printed_options_ = true; |
| return out + option; |
| } |
| |
| private: |
| bool printed_options_ = false; |
| |
| DISALLOW_COPY_AND_ASSIGN(OptionsPrinter); |
| }; |
| |
| std::string PartyOptionsToString( |
| OptionsPrinter* options_printer, |
| const url_pattern_index::flat::UrlRule* flat_rule) { |
| std::string out; |
| bool third_party = flat_rule->options() & |
| url_pattern_index::flat::OptionFlag_APPLIES_TO_THIRD_PARTY; |
| bool first_party = flat_rule->options() & |
| url_pattern_index::flat::OptionFlag_APPLIES_TO_FIRST_PARTY; |
| if (first_party ^ third_party) { |
| if (first_party) |
| out += options_printer->PrintOption("~third-party"); |
| else |
| out += options_printer->PrintOption("third-party"); |
| } |
| return out; |
| } |
| |
| std::string TypeOptionsToString( |
| OptionsPrinter* options_printer, |
| const url_pattern_index::flat::UrlRule* flat_rule) { |
| std::string out; |
| |
| if (flat_rule->activation_types() & |
| url_pattern_index::flat::ActivationType_DOCUMENT) { |
| out += options_printer->PrintOption("document"); |
| } |
| |
| if (flat_rule->activation_types() & |
| url_pattern_index::flat::ActivationType_GENERIC_BLOCK) { |
| out += options_printer->PrintOption("genericblock"); |
| } |
| |
| // Filterlists do not support the "main_frame" and "csp_report" element types. |
| // Hence we ignore them here. |
| constexpr uint16_t kSupportedElementTypes = |
| url_pattern_index::flat::ElementType_ANY & |
| ~url_pattern_index::flat::ElementType_MAIN_FRAME & |
| ~url_pattern_index::flat::ElementType_CSP_REPORT; |
| uint16_t types = flat_rule->element_types() & kSupportedElementTypes; |
| if (types == kSupportedElementTypes) |
| return out; |
| |
| if (types & url_pattern_index::flat::ElementType_OTHER) |
| out += options_printer->PrintOption("other"); |
| if (types & url_pattern_index::flat::ElementType_SCRIPT) |
| out += options_printer->PrintOption("script"); |
| if (types & url_pattern_index::flat::ElementType_IMAGE) |
| out += options_printer->PrintOption("image"); |
| if (types & url_pattern_index::flat::ElementType_STYLESHEET) |
| out += options_printer->PrintOption("stylesheet"); |
| if (types & url_pattern_index::flat::ElementType_OBJECT) |
| out += options_printer->PrintOption("object"); |
| if (types & url_pattern_index::flat::ElementType_XMLHTTPREQUEST) |
| out += options_printer->PrintOption("xmlhttprequest"); |
| if (types & url_pattern_index::flat::ElementType_OBJECT_SUBREQUEST) |
| out += options_printer->PrintOption("object-subrequest"); |
| if (types & url_pattern_index::flat::ElementType_SUBDOCUMENT) |
| out += options_printer->PrintOption("subdocument"); |
| if (types & url_pattern_index::flat::ElementType_PING) |
| out += options_printer->PrintOption("ping"); |
| if (types & url_pattern_index::flat::ElementType_MEDIA) |
| out += options_printer->PrintOption("media"); |
| if (types & url_pattern_index::flat::ElementType_FONT) |
| out += options_printer->PrintOption("font"); |
| if (types & url_pattern_index::flat::ElementType_WEBSOCKET) |
| out += options_printer->PrintOption("websocket"); |
| |
| return out; |
| } |
| |
| std::string ConvertFlatString(const flatbuffers::String* string) { |
| return string ? std::string(string->data(), string->size()) : ""; |
| } |
| |
| std::string DomainOptionsToString( |
| OptionsPrinter* options_printer, |
| const url_pattern_index::flat::UrlRule* flat_rule) { |
| std::string out; |
| if (!flat_rule->domains_included() && !flat_rule->domains_excluded()) |
| return ""; |
| |
| out += options_printer->PrintOption("domain="); |
| |
| bool first = true; |
| if (flat_rule->domains_included()) { |
| for (auto* domain : *flat_rule->domains_included()) { |
| if (!first) |
| out += "|"; |
| first = false; |
| out += ConvertFlatString(domain); |
| } |
| } |
| if (flat_rule->domains_excluded()) { |
| for (auto* domain : *flat_rule->domains_excluded()) { |
| if (!first) |
| out += "|"; |
| first = false; |
| out += "~" + ConvertFlatString(domain); |
| } |
| } |
| return out; |
| } |
| |
| } // namespace |
| |
| std::string FlatUrlRuleToFilterlistString(const flat::UrlRule* flat_rule) { |
| std::string out; |
| |
| if (flat_rule->options() & url_pattern_index::flat::OptionFlag_IS_WHITELIST) |
| out += "@@"; |
| |
| out += AnchorToString(flat_rule->anchor_left()); |
| |
| std::string pattern = ConvertFlatString(flat_rule->url_pattern()); |
| |
| // Add a wildcard to pattern if necessary to differentiate it from a regex. |
| // E.g., /foo/ should be /foo/*. |
| if (flat_rule->url_pattern_type() != |
| url_pattern_index::flat::UrlPatternType_REGEXP && |
| pattern.size() >= 2 && pattern[0] == '/' && |
| pattern[pattern.size() - 1] == '/') { |
| pattern += "*"; |
| } |
| out += pattern; |
| |
| out += AnchorToString(flat_rule->anchor_right()); |
| |
| OptionsPrinter options_printer; |
| |
| out += PartyOptionsToString(&options_printer, flat_rule); |
| |
| // TODO(csharrison): Consider printing something for case-insensitive / |
| // case-sensitive rules. |
| |
| out += TypeOptionsToString(&options_printer, flat_rule); |
| |
| out += DomainOptionsToString(&options_printer, flat_rule); |
| |
| return out; |
| } |
| |
| } // namespace url_pattern_index |