| Index: extensions/browser/api/declarative_net_request/ruleset_manager.cc
|
| diff --git a/extensions/browser/api/declarative_net_request/ruleset_manager.cc b/extensions/browser/api/declarative_net_request/ruleset_manager.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..391a8c9c1747a0b4355f71b63c6461000f7c7044
|
| --- /dev/null
|
| +++ b/extensions/browser/api/declarative_net_request/ruleset_manager.cc
|
| @@ -0,0 +1,251 @@
|
| +// Copyright 2017 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 "extensions/browser/api/declarative_net_request/ruleset_manager.h"
|
| +#include "base/threading/thread_restrictions.h"
|
| +#include "components/subresource_filter/core/common/flat/extension_metadata_generated.h"
|
| +#include "components/subresource_filter/core/common/flat/url_pattern_index_generated.h"
|
| +#include "content/public/browser/browser_thread.h"
|
| +#include "extensions/browser/info_map.h"
|
| +#include "extensions/common/api/declarative_net_request/indexed_rule.h"
|
| +#include "extensions/common/api/declarative_net_request/ruleset_indexer.h"
|
| +
|
| +namespace extensions {
|
| +namespace declarative_net_request {
|
| +
|
| +namespace {
|
| +
|
| +using UrlPatternIndex = subresource_filter::flat::UrlPatternIndex;
|
| +using UrlRule = subresource_filter::flat::UrlRule;
|
| +using FlatUrlRuleList = flatbuffers::Vector<flatbuffers::Offset<UrlRule>>;
|
| +using DomainList =
|
| + flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>;
|
| +using ExtensionRuleMetadata = flat::ExtensionRuleMetadata;
|
| +using ExtensionMetadataList =
|
| + flatbuffers::Vector<flatbuffers::Offset<ExtensionRuleMetadata>>;
|
| +
|
| +// const std::pair<OptionFlag, std::string> kOptionsPairs[] = {
|
| +// {OptionFlag::OptionFlag_IS_WHITELIST, "IS_WHITELIST"},
|
| +// {OptionFlag::OptionFlag_APPLIES_TO_FIRST_PARTY, "APPLIES_TO_FIRST_PARTY"},
|
| +// {OptionFlag::OptionFlag_APPLIES_TO_THIRD_PARTY, "APPLIES_TO_THIRD_PARTY"},
|
| +// {OptionFlag::OptionFlag_IS_MATCH_CASE, "IS_MATCH_CASE"},
|
| +// };
|
| +
|
| +// const std::pair<AnchorType, std::string> kAnchorPairs[] = {
|
| +// {AnchorType::AnchorType_NONE, "NONE"},
|
| +// {AnchorType::AnchorType_BOUNDARY, "BOUNDARY"},
|
| +// {AnchorType::AnchorType_SUBDOMAIN, "SUBDOMAIN"},
|
| +// };
|
| +
|
| +// const std::pair<UrlPatternType, std::string> kUrlPatternPairs[] = {
|
| +// {UrlPatternType::UrlPatternType_SUBSTRING, "SUBSTRING"},
|
| +// {UrlPatternType::UrlPatternType_WILDCARDED, "WILDCARDED"},
|
| +// {UrlPatternType::UrlPatternType_REGEXP, "REGEXP"},
|
| +// };
|
| +
|
| +// const std::pair<ActivationType, std::string> kActivationPairs[] = {
|
| +// {ActivationType::ActivationType_DOCUMENT, "DOCUMENT"},
|
| +// {ActivationType::ActivationType_ELEM_HIDE, "ELEM_HIDE"},
|
| +// {ActivationType::ActivationType_GENERIC_HIDE, "GENERIC_HIDE"},
|
| +// {ActivationType::ActivationType_GENERIC_BLOCK, "GENERIC_BLOCK"},
|
| +// };
|
| +
|
| +// const std::pair<ElementType, std::string> kElementTypePairs[] = {
|
| +// {ElementType::ElementType_OTHER, "OTHER"},
|
| +// {ElementType::ElementType_SCRIPT, "SCRIPT"},
|
| +// {ElementType::ElementType_IMAGE, "IMAGE"},
|
| +// {ElementType::ElementType_STYLESHEET, "STYLESHEET"},
|
| +// {ElementType::ElementType_OBJECT, "OBJECT"},
|
| +// {ElementType::ElementType_XMLHTTPREQUEST, "XMLHTTPREQUEST"},
|
| +// {ElementType::ElementType_OBJECT_SUBREQUEST, "OBJECT_SUBREQUEST"},
|
| +// {ElementType::ElementType_SUBDOCUMENT, "SUBDOCUMENT"},
|
| +// {ElementType::ElementType_PING, "PING"},
|
| +// {ElementType::ElementType_MEDIA, "MEDIA"},
|
| +// {ElementType::ElementType_FONT, "FONT"},
|
| +// {ElementType::ElementType_POPUP, "POPUP"},
|
| +// {ElementType::ElementType_WEBSOCKET, "WEBSOCKET"},
|
| +// };
|
| +
|
| +// void PrintDomainList(const std::string& msg, const DomainList* domain_list) {
|
| +// LOG(ERROR) << "--------msg " << msg << "\n";
|
| +// for(const auto* domain : *domain_list) {
|
| +// LOG(ERROR) << "--------*domain " << domain->c_str() << "\n";
|
| +// }
|
| +// }
|
| +
|
| +// template <typename A, typename B,typename C>
|
| +// std::string PrintMask(const std::pair<A, B> pairs[], size_t len, C elem) {
|
| +// std::string s;
|
| +// for(size_t i = 0; i < len; i++) {
|
| +// if(elem & pairs[i].first)
|
| +// s += pairs[i].second + " ";
|
| +// }
|
| +// return s;
|
| +// }
|
| +
|
| +// template <typename A, typename B,typename C>
|
| +// std::string PrintEqual(const std::pair<A, B> pairs[], size_t len, C elem) {
|
| +// for(size_t i = 0; i < len; i++) {
|
| +// if(elem == pairs[i].first)
|
| +// return pairs[i].second;
|
| +// }
|
| +// return "";
|
| +// }
|
| +
|
| +// std::string PrintOptions(uint8_t options_mask) {
|
| +// return PrintMask(kOptionsPairs, arraysize(kOptionsPairs), options_mask);
|
| +// }
|
| +
|
| +// std::string PrintAnchor(uint8_t anchor) {
|
| +// return PrintEqual(kAnchorPairs, arraysize(kAnchorPairs), anchor);
|
| +// }
|
| +
|
| +// std::string PrintUrlPatternType(uint8_t url_pattern_type) {
|
| +// return PrintEqual(kUrlPatternPairs, arraysize(kUrlPatternPairs),
|
| +// url_pattern_type);
|
| +// }
|
| +
|
| +// std::string PrintActivation(uint8_t activation_mask) {
|
| +// return PrintMask(kActivationPairs, arraysize(kActivationPairs),
|
| +// activation_mask);
|
| +// }
|
| +
|
| +// std::string PrintElements(uint16_t element_mask) {
|
| +// return PrintMask(kElementTypePairs, arraysize(kElementTypePairs),
|
| +// element_mask);
|
| +// }
|
| +
|
| +// void PrintRuleList(const std::string& msg, const FlatUrlRuleList* rule_list)
|
| +// {
|
| +// LOG(ERROR) << "--------msg " << msg << "\n";
|
| +// for(const auto* rule : *rule_list) {
|
| +// LOG(ERROR) << "--------rule->id() " << rule->id() << "\n";
|
| +// LOG(ERROR) << "--------rule->priority() " << rule->priority() << "\n";
|
| +// LOG(ERROR) << "--------rule->options() " << PrintOptions(rule->options())
|
| +// << "\n"; LOG(ERROR) << "--------rule->element_types() " <<
|
| +// PrintElements(rule->element_types()) << "\n"; LOG(ERROR) <<
|
| +// "--------rule->activation_types() " <<
|
| +// PrintActivation(rule->activation_types()) << "\n"; LOG(ERROR) <<
|
| +// "--------rule->url_pattern_type() " <<
|
| +// PrintUrlPatternType(rule->url_pattern_type()) << "\n"; LOG(ERROR) <<
|
| +// "--------rule->anchor_left() " << PrintAnchor(rule->anchor_left()) <<
|
| +// "\n"; LOG(ERROR) << "--------rule->anchor_right() " <<
|
| +// PrintAnchor(rule->anchor_right()) << "\n"; LOG(ERROR) <<
|
| +// "--------rule->url_pattern() " << rule->url_pattern()->c_str() << "\n";
|
| +// PrintDomainList("included_domains", rule->domains_included());
|
| +// PrintDomainList("excluded_domains", rule->domains_excluded());
|
| +// }
|
| +// }
|
| +
|
| +// std::string string_to_hex(const std::string& input)
|
| +// {
|
| +// static const char* const lut = "0123456789ABCDEF";
|
| +// size_t len = input.length();
|
| +
|
| +// std::string output;
|
| +// output.reserve(2 * len);
|
| +// for (size_t i = 0; i < len; ++i)
|
| +// {
|
| +// const unsigned char c = input[i];
|
| +// output.push_back(lut[c >> 4]);
|
| +// output.push_back(lut[c & 15]);
|
| +// }
|
| +// return output;
|
| +// }
|
| +
|
| +// void PrintIndex(const std::string& str, const UrlPatternIndex* index) {
|
| +// LOG(ERROR) << "--------str " << str << "\n";
|
| +// LOG(ERROR) << "--------index->n() " << index->n() << "\n";
|
| +// const ::subresource_filter::flat::NGramToRules* empty_slot =
|
| +// index->ngram_index_empty_slot(); PrintRuleList("fallback_rules",
|
| +// index->fallback_rules()); for(const auto* n_gram_rules:
|
| +// *index->ngram_index()) {
|
| +// if (n_gram_rules == empty_slot)
|
| +// continue;
|
| +// PrintRuleList("rule_list" + std::to_string(n_gram_rules->ngram()),
|
| +// n_gram_rules->rule_list());
|
| +// }
|
| +// }
|
| +
|
| +// void PrintExtensionMetadata(const std::string& msg, const
|
| +// ExtensionMetadataList* metadata_list) {
|
| +// LOG(ERROR) << "--------msg " << msg << "\n";
|
| +// for (const auto* metadata : *metadata_list) {
|
| +// LOG(ERROR) << "--------metadata->id() " << metadata->id() << "\n";
|
| +// LOG(ERROR) << "--------metadata->redirect_url()->c_str() " <<
|
| +// metadata->redirect_url()->c_str() << "\n";
|
| +// }
|
| +// }
|
| +
|
| +// void PrintIndexedRuleset(base::MemoryMappedFile* file) {
|
| +// RulesetIndexer::SerializedData data(file->data(), file->length());
|
| +// std::string file_data(reinterpret_cast<const char*>(data.first),
|
| +// data.second); LOG(ERROR) << "--------file_data " <<
|
| +// string_to_hex(file_data) << "\n"; flatbuffers::Verifier
|
| +// verifier(data.first, data.second); bool verify =
|
| +// flat::VerifyExtensionIndexedRulesetBuffer(verifier); LOG(ERROR) <<
|
| +// "--------verify " << verify << "\n"; CHECK(verify);
|
| +
|
| +// const flat::ExtensionIndexedRuleset* ruleset =
|
| +// flat::GetExtensionIndexedRuleset(data.first); PrintIndex("blacklist_index",
|
| +// ruleset->blacklist_index()); PrintIndex("whitelist_index",
|
| +// ruleset->whitelist_index()); PrintIndex("redirect_index",
|
| +// ruleset->redirect_index()); PrintExtensionMetadata("extension_metdata",
|
| +// ruleset->extension_metdata());
|
| +// }
|
| +}
|
| +
|
| +RulesetManager::ExtensionKey::ExtensionKey(ExtensionId extension_id,
|
| + base::Time extension_install_time)
|
| + : id(std::move(extension_id)),
|
| + install_time(std::move(extension_install_time)) {}
|
| +RulesetManager::ExtensionKey::~ExtensionKey() = default;
|
| +
|
| +// Comparator to ensure that ExtensionKey are sorted in order of decreasing
|
| +// extension install time i.e. most recently installed extension first. For
|
| +// equal install times, sort by id. This is also necessary since a set uses the
|
| +// this to prevent duplicates. Hence only sorting on a single parameter would
|
| +// be incorrect.
|
| +bool RulesetManager::ExtensionKeyComparator::operator()(
|
| + const ExtensionKey& lhs,
|
| + const ExtensionKey& rhs) const {
|
| + return lhs.install_time > rhs.install_time || lhs.id < rhs.id;
|
| +}
|
| +
|
| +RulesetManager::RulesetManager(InfoMap* info_map) : info_map_(info_map) {
|
| + DCHECK(info_map_);
|
| +}
|
| +RulesetManager::~RulesetManager() = default;
|
| +
|
| +void RulesetManager::AddRuleset(
|
| + ExtensionId extension_id,
|
| + std::unique_ptr<ExtensionIndexedRulesetMatcher> ruleset_matcher) {
|
| + DCHECK(info_map_);
|
| + base::Time install_time = info_map_->GetInstallTime(extension_id);
|
| + ExtensionKey key(std::move(extension_id), std::move(install_time));
|
| + // PrintIndexedRuleset(ruleset.get());
|
| + auto it = rules_.insert(std::make_pair(key, std::move(ruleset_matcher)));
|
| + // Verify insertion actually occured.
|
| + DCHECK(it.second);
|
| +}
|
| +
|
| +// Todo actually this should take a const std::string&, since it won't be moved.
|
| +// But then the API would become inconsistent.
|
| +void RulesetManager::RemoveRuleset(ExtensionId extension_id) {
|
| + DCHECK(info_map_);
|
| + base::Time install_time = info_map_->GetInstallTime(extension_id);
|
| + LOG(ERROR) << "--------Removing ruleset for " << extension_id;
|
| + // This is a bit problematic. We are depending on info map to provide the
|
| + // extension install time. If the provided time changes, the key won't be
|
| + // removed. And we won't be able to ensure that single key for single id.
|
| + // TODO Add DCHECK to ensure keys for ids are unique.
|
| + // TODO yeah this is probematic as Info::RemoveExtension may be called first.
|
| + // Check.
|
| + ExtensionKey key(std::move(extension_id), std::move(install_time));
|
| + size_t erase_count = rules_.erase(key);
|
| + DCHECK_EQ(1u, erase_count);
|
| +}
|
| +
|
| +} // namespace declarative_net_request
|
| +} // namespace extensions
|
|
|