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 |