blob: f42e63e4d8efa029f46120a9de45bc2ffa2291bd [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/flat_ruleset_indexer.h"
#include <string>
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "extensions/browser/api/declarative_net_request/indexed_rule.h"
namespace extensions {
namespace declarative_net_request {
namespace {
namespace dnr_api = extensions::api::declarative_net_request;
namespace flat_rule = url_pattern_index::flat;
template <typename T>
using FlatOffset = flatbuffers::Offset<T>;
using FlatStringOffset = FlatOffset<flatbuffers::String>;
using FlatStringListOffset = FlatOffset<flatbuffers::Vector<FlatStringOffset>>;
// Writes to |builder| a flatbuffer vector of shared strings corresponding to
// |vec| and returns the offset to it. If |vec| is empty, returns an empty
// offset.
FlatStringListOffset BuildVectorOfSharedStrings(
flatbuffers::FlatBufferBuilder* builder,
const std::vector<std::string>& vec) {
if (vec.empty())
return FlatStringListOffset();
std::vector<FlatStringOffset> offsets;
offsets.reserve(vec.size());
for (const auto& str : vec)
offsets.push_back(builder->CreateSharedString(str));
return builder->CreateVector(offsets);
}
// Returns the RuleActionType corresponding to |indexed_rule|.
dnr_api::RuleActionType GetRuleActionType(const IndexedRule& indexed_rule) {
if (indexed_rule.options & flat_rule::OptionFlag_IS_WHITELIST) {
DCHECK(indexed_rule.redirect_url.empty());
return dnr_api::RULE_ACTION_TYPE_WHITELIST;
}
if (!indexed_rule.redirect_url.empty())
return dnr_api::RULE_ACTION_TYPE_REDIRECT;
return dnr_api::RULE_ACTION_TYPE_BLACKLIST;
}
} // namespace
FlatRulesetIndexer::FlatRulesetIndexer()
: blacklist_index_builder_(&builder_),
whitelist_index_builder_(&builder_),
redirect_index_builder_(&builder_) {}
FlatRulesetIndexer::~FlatRulesetIndexer() = default;
void FlatRulesetIndexer::AddUrlRule(const IndexedRule& indexed_rule) {
DCHECK(!finished_);
++indexed_rules_count_;
auto domains_included_offset =
BuildVectorOfSharedStrings(&builder_, indexed_rule.domains);
auto domains_excluded_offset =
BuildVectorOfSharedStrings(&builder_, indexed_rule.excluded_domains);
auto url_pattern_offset =
builder_.CreateSharedString(indexed_rule.url_pattern);
FlatOffset<flat_rule::UrlRule> offset = flat_rule::CreateUrlRule(
builder_, indexed_rule.options, indexed_rule.element_types,
indexed_rule.activation_types, indexed_rule.url_pattern_type,
indexed_rule.anchor_left, indexed_rule.anchor_right,
domains_included_offset, domains_excluded_offset, url_pattern_offset,
indexed_rule.id, indexed_rule.priority);
const dnr_api::RuleActionType type = GetRuleActionType(indexed_rule);
GetBuilder(type)->IndexUrlRule(offset);
// Store additional metadata required for a redirect rule.
if (type == dnr_api::RULE_ACTION_TYPE_REDIRECT) {
DCHECK(!indexed_rule.redirect_url.empty());
auto redirect_url_offset =
builder_.CreateSharedString(indexed_rule.redirect_url);
metadata_.push_back(flat::CreateUrlRuleMetadata(builder_, indexed_rule.id,
redirect_url_offset));
}
}
void FlatRulesetIndexer::Finish() {
DCHECK(!finished_);
finished_ = true;
auto blacklist_index_offset = blacklist_index_builder_.Finish();
auto whitelist_index_offset = whitelist_index_builder_.Finish();
auto redirect_index_offset = redirect_index_builder_.Finish();
// Store the extension metadata sorted by ID to support fast lookup through
// binary search.
auto extension_metadata_offset =
builder_.CreateVectorOfSortedTables(&metadata_);
auto root_offset = flat::CreateExtensionIndexedRuleset(
builder_, blacklist_index_offset, whitelist_index_offset,
redirect_index_offset, extension_metadata_offset);
flat::FinishExtensionIndexedRulesetBuffer(builder_, root_offset);
}
FlatRulesetIndexer::SerializedData FlatRulesetIndexer::GetData() {
DCHECK(finished_);
return SerializedData(builder_.GetBufferPointer(),
base::strict_cast<size_t>(builder_.GetSize()));
}
FlatRulesetIndexer::UrlPatternIndexBuilder* FlatRulesetIndexer::GetBuilder(
dnr_api::RuleActionType type) {
switch (type) {
case dnr_api::RULE_ACTION_TYPE_BLACKLIST:
return &blacklist_index_builder_;
case dnr_api::RULE_ACTION_TYPE_WHITELIST:
return &whitelist_index_builder_;
case dnr_api::RULE_ACTION_TYPE_REDIRECT:
return &redirect_index_builder_;
case dnr_api::RULE_ACTION_TYPE_NONE:
NOTREACHED();
}
return nullptr;
}
} // namespace declarative_net_request
} // namespace extensions