Index: extensions/browser/api/declarative_net_request/matcher_util.cc |
diff --git a/extensions/browser/api/declarative_net_request/matcher_util.cc b/extensions/browser/api/declarative_net_request/matcher_util.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..7236282b4ad4c31c33502d48e45029117a2021a3 |
--- /dev/null |
+++ b/extensions/browser/api/declarative_net_request/matcher_util.cc |
@@ -0,0 +1,188 @@ |
+// 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/matcher_util.h" |
+ |
+#include "base/files/file_util.h" |
+#include "base/files/memory_mapped_file.h" |
+#include "base/memory/ptr_util.h" |
+#include "base/metrics/histogram_macros.h" |
+#include "base/threading/thread_restrictions.h" |
+#include "components/subresource_filter/core/common/first_party_origin.h" |
+#include "components/subresource_filter/core/common/flat/extension_metadata_generated.h" |
+#include "content/public/browser/resource_request_info.h" |
+#include "extensions/browser/info_map.h" |
+#include "net/url_request/url_request.h" |
+ |
+namespace extensions { |
+namespace declarative_net_request { |
+ |
+namespace { |
+ |
+ElementType ToElementType(content::ResourceType type) { |
+ switch (type) { |
+ case content::RESOURCE_TYPE_LAST_TYPE: |
+ case content::RESOURCE_TYPE_PREFETCH: |
+ case content::RESOURCE_TYPE_CSP_REPORT: // TODO |
+ case content::RESOURCE_TYPE_SUB_RESOURCE: // TODO |
+ return ElementType::ElementType_OTHER; |
+ case content::RESOURCE_TYPE_SCRIPT: |
+ case content::RESOURCE_TYPE_WORKER: |
+ case content::RESOURCE_TYPE_SHARED_WORKER: |
+ case content::RESOURCE_TYPE_SERVICE_WORKER: |
+ return ElementType::ElementType_SCRIPT; |
+ case content::RESOURCE_TYPE_IMAGE: |
+ case content::RESOURCE_TYPE_FAVICON: |
+ return ElementType::ElementType_IMAGE; |
+ case content::RESOURCE_TYPE_STYLESHEET: |
+ return ElementType::ElementType_STYLESHEET; |
+ case content::RESOURCE_TYPE_OBJECT: |
+ case content::RESOURCE_TYPE_PLUGIN_RESOURCE: // TODO |
+ return ElementType::ElementType_OBJECT; |
+ case content::RESOURCE_TYPE_XHR: |
+ return ElementType::ElementType_XMLHTTPREQUEST; |
+ case content::RESOURCE_TYPE_MAIN_FRAME: // TODO |
+ case content::RESOURCE_TYPE_SUB_FRAME: |
+ return ElementType::ElementType_SUBDOCUMENT; |
+ case content::RESOURCE_TYPE_PING: |
+ return ElementType::ElementType_PING; |
+ case content::RESOURCE_TYPE_MEDIA: |
+ return ElementType::ElementType_MEDIA; |
+ case content::RESOURCE_TYPE_FONT_RESOURCE: |
+ return ElementType::ElementType_FONT; |
+ } |
+ NOTREACHED(); |
+ return ElementType::ElementType_OTHER; |
+} |
+ |
+subresource_filter::proto::ElementType ToProtoElementType(ElementType type) { |
+ switch (type) { |
+ case ElementType::ElementType_OTHER: |
+ return subresource_filter::proto::ELEMENT_TYPE_OTHER; |
+ case ElementType::ElementType_SCRIPT: |
+ return subresource_filter::proto::ELEMENT_TYPE_SCRIPT; |
+ case ElementType::ElementType_IMAGE: |
+ return subresource_filter::proto::ELEMENT_TYPE_IMAGE; |
+ case ElementType::ElementType_STYLESHEET: |
+ return subresource_filter::proto::ELEMENT_TYPE_STYLESHEET; |
+ case ElementType::ElementType_OBJECT: |
+ return subresource_filter::proto::ELEMENT_TYPE_OBJECT; |
+ case ElementType::ElementType_XMLHTTPREQUEST: |
+ return subresource_filter::proto::ELEMENT_TYPE_XMLHTTPREQUEST; |
+ case ElementType::ElementType_OBJECT_SUBREQUEST: |
+ return subresource_filter::proto::ELEMENT_TYPE_OBJECT_SUBREQUEST; |
+ case ElementType::ElementType_SUBDOCUMENT: |
+ return subresource_filter::proto::ELEMENT_TYPE_SUBDOCUMENT; |
+ case ElementType::ElementType_PING: |
+ return subresource_filter::proto::ELEMENT_TYPE_PING; |
+ case ElementType::ElementType_MEDIA: |
+ return subresource_filter::proto::ELEMENT_TYPE_MEDIA; |
+ case ElementType::ElementType_FONT: |
+ return subresource_filter::proto::ELEMENT_TYPE_FONT; |
+ case ElementType::ElementType_POPUP: |
+ return subresource_filter::proto::ELEMENT_TYPE_POPUP; |
+ case ElementType::ElementType_WEBSOCKET: |
+ return subresource_filter::proto::ELEMENT_TYPE_WEBSOCKET; |
+ default: |
+ NOTREACHED(); |
+ return subresource_filter::proto::ELEMENT_TYPE_UNSPECIFIED; |
+ } |
+} |
+ |
+ElementType GetElementType(const net::URLRequest* request) { |
+ DCHECK(request); |
+ if (request->url().SchemeIsWSOrWSS()) |
+ return ElementType::ElementType_WEBSOCKET; |
+ const auto* info = content::ResourceRequestInfo::ForRequest(request); |
+ return info ? ToElementType(info->GetResourceType()) |
+ : ElementType::ElementType_OTHER; |
+} |
+ |
+} // namespace |
+ |
+ExtensionIndexedRulesetMatcher::ExtensionIndexedRulesetMatcher( |
+ std::unique_ptr<base::MemoryMappedFile, |
+ content::BrowserThread::DeleteOnFileThread> ruleset_file) |
+ : ruleset_file_(std::move(ruleset_file)), |
+ root_(flat::GetExtensionIndexedRuleset(ruleset_file_->data())), |
+ blacklist_matcher_(root_->blacklist_index()), |
+ whitelist_matcher_(root_->whitelist_index()), |
+ redirect_matcher_(root_->redirect_index()), |
+ extension_metdata_(root_->extension_metdata()) {} |
+ |
+bool ExtensionIndexedRulesetMatcher::ShouldBlockRequest( |
+ const GURL& url, |
+ const url::Origin& first_party_origin, |
+ ElementType element_type, |
+ bool is_third_party) { |
+ return !!blacklist_matcher_.FindMatch( |
+ url, first_party_origin, ToProtoElementType(element_type), |
+ subresource_filter::proto::ACTIVATION_TYPE_UNSPECIFIED, |
+ is_third_party, false) && |
+ !whitelist_matcher_.FindMatch( |
+ url, first_party_origin, ToProtoElementType(element_type), |
+ subresource_filter::proto::ACTIVATION_TYPE_UNSPECIFIED, |
+ is_third_party, false); |
+} |
+ |
+bool ShouldBlockRequest(void* BrowserContext, |
+ const InfoMap* info_map, |
+ net::URLRequest* request) { |
+ SCOPED_UMA_HISTOGRAM_TIMER("DNR.ShouldBlockRequest"); |
+ const GURL& url = request->url(); |
+ const base::Optional<url::Origin> initiator = request->initiator(); |
+ const url::Origin first_party_origin = |
+ initiator ? initiator.value() : url::Origin(); |
+ ElementType element_type = GetElementType(request); |
+ const bool is_third_party = |
+ subresource_filter::FirstPartyOrigin::IsThirdParty(url, |
+ first_party_origin); |
+ |
+ for (const auto& pair : *info_map->ruleset_manager()->rules_map()) { |
+ // const string& extension_id = pair.first.id; |
+ |
+ if (pair.second->ShouldBlockRequest(url, first_party_origin, element_type, |
+ is_third_party)) |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+std::unique_ptr<ExtensionIndexedRulesetMatcher> |
+CreateVerifiedExtensionIndexedRulesetMatcher( |
+ const base::FilePath& indexed_ruleset_path) { |
+ SCOPED_UMA_HISTOGRAM_TIMER("DNR.LoadRulesetMatcher"); |
+ base::ThreadRestrictions::AssertIOAllowed(); |
+ |
+ // TODO log error uma. |
+ if (!base::PathExists(indexed_ruleset_path)) { |
+ NOTREACHED() << "Ruleset file does not exist"; |
+ return nullptr; |
+ } |
+ |
+ std::unique_ptr<base::MemoryMappedFile, |
+ content::BrowserThread::DeleteOnFileThread> |
+ ruleset_file(new base::MemoryMappedFile()); |
+ LOG(ERROR) << "--------indexed_ruleset_path " << indexed_ruleset_path.value() |
+ << "\n"; |
+ if (!ruleset_file->Initialize(indexed_ruleset_path, |
+ base::MemoryMappedFile::READ_ONLY)) { |
+ NOTREACHED() << "Error reading indexed ruleset"; |
+ return nullptr; |
+ } |
+ |
+ LOG(ERROR) << "--------initialized ruleset\n"; |
+ |
+ // TODO we should also verify file checksum. |
+ flatbuffers::Verifier verifier(ruleset_file->data(), ruleset_file->length()); |
+ if (!flat::VerifyExtensionIndexedRulesetBuffer(verifier)) { |
+ NOTREACHED() << "Buffer could not be verified"; |
+ } |
+ |
+ return base::MakeUnique<ExtensionIndexedRulesetMatcher>( |
+ std::move(ruleset_file)); |
+} |
+ |
+} // namespace declarative_net_request |
+} // namespace extensions |