blob: d8e7bbc73f7bdf49ac6b2e902df041542f362b14 [file] [log] [blame]
// 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_matcher.h"
#include <utility>
#include "base/check.h"
#include "base/containers/span.h"
#include "base/files/file_util.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/timer/elapsed_timer.h"
#include "extensions/browser/api/declarative_net_request/constants.h"
#include "extensions/browser/api/declarative_net_request/request_action.h"
#include "extensions/browser/api/declarative_net_request/ruleset_source.h"
#include "extensions/browser/api/declarative_net_request/utils.h"
#include "extensions/common/api/declarative_net_request/utils.h"
namespace extensions {
namespace declarative_net_request {
// static
RulesetMatcher::LoadRulesetResult RulesetMatcher::CreateVerifiedMatcher(
const RulesetSource& source,
int expected_ruleset_checksum,
std::unique_ptr<RulesetMatcher>* matcher) {
DCHECK(matcher);
DCHECK(IsAPIAvailable());
base::ElapsedTimer timer;
if (!base::PathExists(source.indexed_path()))
return kLoadErrorInvalidPath;
std::string ruleset_data;
if (!base::ReadFileToString(source.indexed_path(), &ruleset_data))
return kLoadErrorFileRead;
if (!StripVersionHeaderAndParseVersion(&ruleset_data))
return kLoadErrorVersionMismatch;
// This guarantees that no memory access will end up outside the buffer.
if (!IsValidRulesetData(
base::make_span(reinterpret_cast<const uint8_t*>(ruleset_data.data()),
ruleset_data.size()),
expected_ruleset_checksum)) {
return kLoadErrorChecksumMismatch;
}
UMA_HISTOGRAM_TIMES(
"Extensions.DeclarativeNetRequest.CreateVerifiedMatcherTime",
timer.Elapsed());
// Using WrapUnique instead of make_unique since this class has a private
// constructor.
*matcher = base::WrapUnique(new RulesetMatcher(std::move(ruleset_data),
source.id(), source.type(),
source.extension_id()));
return kLoadSuccess;
}
RulesetMatcher::~RulesetMatcher() = default;
base::Optional<RequestAction> RulesetMatcher::GetBeforeRequestAction(
const RequestParams& params) const {
return GetMaxPriorityAction(
url_pattern_index_matcher_.GetBeforeRequestAction(params),
regex_matcher_.GetBeforeRequestAction(params));
}
uint8_t RulesetMatcher::GetRemoveHeadersMask(
const RequestParams& params,
uint8_t excluded_remove_headers_mask,
std::vector<RequestAction>* remove_headers_actions) const {
DCHECK(remove_headers_actions);
static_assert(
flat::RemoveHeaderType_ANY <= std::numeric_limits<uint8_t>::max(),
"flat::RemoveHeaderType can't fit in a uint8_t");
uint8_t mask = url_pattern_index_matcher_.GetRemoveHeadersMask(
params, excluded_remove_headers_mask, remove_headers_actions);
return mask | regex_matcher_.GetRemoveHeadersMask(
params, excluded_remove_headers_mask | mask,
remove_headers_actions);
}
bool RulesetMatcher::IsExtraHeadersMatcher() const {
return url_pattern_index_matcher_.IsExtraHeadersMatcher() ||
regex_matcher_.IsExtraHeadersMatcher();
}
size_t RulesetMatcher::GetRulesCount() const {
return url_pattern_index_matcher_.GetRulesCount() +
regex_matcher_.GetRulesCount();
}
size_t RulesetMatcher::GetRegexRulesCount() const {
return regex_matcher_.GetRulesCount();
}
void RulesetMatcher::OnRenderFrameCreated(content::RenderFrameHost* host) {
url_pattern_index_matcher_.OnRenderFrameCreated(host);
regex_matcher_.OnRenderFrameCreated(host);
}
void RulesetMatcher::OnRenderFrameDeleted(content::RenderFrameHost* host) {
url_pattern_index_matcher_.OnRenderFrameDeleted(host);
regex_matcher_.OnRenderFrameDeleted(host);
}
void RulesetMatcher::OnDidFinishNavigation(content::RenderFrameHost* host) {
url_pattern_index_matcher_.OnDidFinishNavigation(host);
regex_matcher_.OnDidFinishNavigation(host);
}
base::Optional<RequestAction>
RulesetMatcher::GetAllowlistedFrameActionForTesting(
content::RenderFrameHost* host) const {
return GetMaxPriorityAction(
url_pattern_index_matcher_.GetAllowlistedFrameActionForTesting(host),
regex_matcher_.GetAllowlistedFrameActionForTesting(host));
}
RulesetMatcher::RulesetMatcher(
std::string ruleset_data,
int id,
api::declarative_net_request::SourceType source_type,
const ExtensionId& extension_id)
: ruleset_data_(std::move(ruleset_data)),
root_(flat::GetExtensionIndexedRuleset(ruleset_data_.data())),
id_(id),
url_pattern_index_matcher_(extension_id,
source_type,
root_->index_list(),
root_->extension_metadata()),
regex_matcher_(extension_id,
source_type,
root_->regex_rules(),
root_->extension_metadata()) {}
} // namespace declarative_net_request
} // namespace extensions