blob: 3bacbce54c6beee9b5e0c7c0de000bf63f5303ab [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 <cstdint>
#include <memory>
#include <string>
#include <vector>
#include "base/containers/flat_map.h"
#include "components/url_pattern_index/url_pattern_index.h"
#include "extensions/browser/api/declarative_net_request/flat/extension_ruleset_generated.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace extensions {
struct WebRequestInfo;
namespace declarative_net_request {
class RulesetSource;
namespace flat {
struct ExtensionIndexedRuleset;
struct UrlRuleMetadata;
} // namespace flat
class RulesetMatcher;
// Struct to hold parameters for a network request.
struct RequestParams {
// |info| must outlive this instance.
explicit RequestParams(const WebRequestInfo& info);
// This is a pointer to a GURL. Hence the GURL must outlive this struct.
const GURL* url = nullptr;
url::Origin first_party_origin;
url_pattern_index::flat::ElementType element_type;
bool is_third_party;
// A map of RulesetMatchers to results of |HasMatchingAllowRule| for this
// request. Used as a cache to prevent extra calls to |HasMatchingAllowRule|.
mutable base::flat_map<const RulesetMatcher*, bool> allow_rule_cache;
// RulesetMatcher encapsulates the Declarative Net Request API ruleset
// corresponding to a single RulesetSource. This uses the url_pattern_index
// component to achieve fast matching of network requests against declarative
// rules. Since this class is immutable, it is thread-safe. In practice it is
// accessed on the IO thread but created on a sequence where file IO is allowed.
class RulesetMatcher {
// Describes the result of creating a RulesetMatcher instance.
// This is logged as part of UMA. Hence existing values should not be re-
// numbered or deleted. New values should be added before kLoadRulesetMax.
enum LoadRulesetResult {
// Ruleset loading succeeded.
kLoadSuccess = 0,
// Ruleset loading failed since the provided path did not exist.
kLoadErrorInvalidPath = 1,
// Ruleset loading failed due to a file read error.
kLoadErrorFileRead = 2,
// Ruleset loading failed due to a checksum mismatch.
kLoadErrorChecksumMismatch = 3,
// Ruleset loading failed due to version header mismatch.
// TODO(karandeepb): This should be split into two cases:
// - When the indexed ruleset doesn't have the version header in the
// correct format.
// - When the indexed ruleset's version is not the same as that used by
// Chrome.
kLoadErrorVersionMismatch = 4,
// Factory function to create a verified RulesetMatcher for |source|. Must be
// called on a sequence where file IO is allowed. Returns kLoadSuccess on
// success along with the ruleset |matcher|.
static LoadRulesetResult CreateVerifiedMatcher(
const RulesetSource& source,
int expected_ruleset_checksum,
std::unique_ptr<RulesetMatcher>* matcher);
// Returns whether the ruleset has a matching blocking rule.
bool HasMatchingBlockRule(const RequestParams& params) const {
return GetMatchingRule(params, flat::ActionIndex_block);
// Returns whether the ruleset has a matching allow rule.
bool HasMatchingAllowRule(const RequestParams& params) const {
return GetMatchingRule(params, flat::ActionIndex_allow);
// Returns the bitmask of headers to remove from the request. The bitmask
// corresponds to RemoveHeadersMask type. |current_mask| denotes the current
// mask of headers to be removed and is included in the return value.
uint8_t GetRemoveHeadersMask(const RequestParams& params,
uint8_t current_mask) const;
// Returns whether the ruleset has a matching redirect rule. Populates
// |redirect_url| on returning true. |redirect_url| must not be null.
bool HasMatchingRedirectRule(const RequestParams& params,
GURL* redirect_url) const;
// Returns whether this modifies "extraHeaders".
bool IsExtraHeadersMatcher() const { return is_extra_headers_matcher_; }
// ID of the ruleset. Each extension can have multiple rulesets with
// their own unique ids.
size_t id() const { return id_; }
// Priority of the ruleset. Each extension can have multiple rulesets with
// their own different priorities.
size_t priority() const { return priority_; }
using UrlPatternIndexMatcher = url_pattern_index::UrlPatternIndexMatcher;
using ExtensionMetadataList =
explicit RulesetMatcher(std::string ruleset_data, size_t id, size_t priority);
const url_pattern_index::flat::UrlRule* GetMatchingRule(
const RequestParams& params,
flat::ActionIndex index,
UrlPatternIndexMatcher::FindRuleStrategy strategy =
UrlPatternIndexMatcher::FindRuleStrategy::kAny) const;
const std::string ruleset_data_;
const flat::ExtensionIndexedRuleset* const root_;
// UrlPatternIndexMatchers corresponding to entries in flat::ActionIndex.
const std::vector<UrlPatternIndexMatcher> matchers_;
const ExtensionMetadataList* const metadata_list_;
size_t id_;
size_t priority_;
const bool is_extra_headers_matcher_;
} // namespace declarative_net_request
} // namespace extensions