Skip to content

Commit

Permalink
read homepage and title metadata from list subscriptions
Browse files Browse the repository at this point in the history
  • Loading branch information
antonok-edm committed May 20, 2022
1 parent 5623622 commit 1a9b680
Show file tree
Hide file tree
Showing 11 changed files with 336 additions and 24 deletions.
11 changes: 8 additions & 3 deletions browser/brave_shields/ad_block_service_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -210,15 +210,16 @@ bool AdBlockServiceTest::InstallDefaultAdBlockExtension(

// A test observer that allows blocking waits for an AdBlockEngine to be
// updated with new rules.
class EngineTestObserver : public brave_shields::AdBlockEngine::TestObserver {
class EngineTestObserver
: public brave_shields::AdBlockEngine::EngineUpdateObserver {
public:
// Constructs an EngineTestObserver which will observe the given adblock
// engine for filter data updates.
explicit EngineTestObserver(brave_shields::AdBlockEngine* engine)
: engine_(engine) {
engine_->AddObserverForTest(this);
engine_->AddUpdateObserver(this);
}
~EngineTestObserver() override { engine_->RemoveObserverForTest(); }
~EngineTestObserver() override { engine_->RemoveUpdateObserver(this); }

EngineTestObserver(const EngineTestObserver& other) = delete;
EngineTestObserver& operator=(const EngineTestObserver& other) = delete;
Expand Down Expand Up @@ -795,6 +796,8 @@ IN_PROC_BROWSER_TEST_F(AdBlockServiceTest,
ASSERT_EQ(subscriptions[0].last_update_attempt, base::Time());
ASSERT_EQ(subscriptions[0].last_successful_update_attempt, base::Time());
ASSERT_EQ(subscriptions[0].enabled, true);
ASSERT_EQ(subscriptions[0].homepage, absl::nullopt);
ASSERT_EQ(subscriptions[0].title, absl::nullopt);
}

// Ensure that the subscription gets update attempts, and ultimately is
Expand Down Expand Up @@ -841,6 +844,8 @@ IN_PROC_BROWSER_TEST_F(AdBlockServiceTest,
ASSERT_EQ(subscriptions[0].last_successful_update_attempt,
subscriptions[0].last_update_attempt);
ASSERT_EQ(subscriptions[0].enabled, false);
ASSERT_EQ(subscriptions[0].homepage, "https://example.com/list.txt");
ASSERT_EQ(subscriptions[0].title, "Test list");
}

EXPECT_EQ(true,
Expand Down
5 changes: 4 additions & 1 deletion components/adblock_rust_ffi/cbindgen.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# The language to output bindings in
language = "C"
include_guard = "ADBLOCK_RUST_FFI_H"
include_guard = "BRAVE_COMPONENTS_ADBLOCK_RUST_FFI_SRC_LIB_H_"

header = "/* Copyright (c) 2019 The Brave Authors. All rights reserved.\n * This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this file,\n * You can obtain one at http://mozilla.org/MPL/2.0/. */"
line_length = 80

[parse]
# Whether to parse dependent crates and include their types in the generated
Expand Down
40 changes: 39 additions & 1 deletion components/adblock_rust_ffi/src/lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@
*/
typedef struct C_Engine C_Engine;

/**
* Includes information about any "special comments" as described by
* https://help.eyeo.com/adblockplus/how-to-write-filters#special-comments
*/
typedef struct C_FilterListMetadata C_FilterListMetadata;

/**
* An external callback that receives a hostname and two out-parameters for
* start and end position. The callback should fill the start and end positions
Expand All @@ -36,9 +42,22 @@ bool set_domain_resolver(C_DomainResolverCallback resolver);
/**
* Create a new `Engine`.
*/
struct C_Engine* engine_create(const char* rules);
struct C_Engine* engine_create_from_buffer(const char* data, size_t data_size);

/**
* Create a new `Engine`.
*/
struct C_Engine* engine_create_from_buffer_with_metadata(
const char* data,
size_t data_size,
struct C_FilterListMetadata** metadata);

struct C_Engine* engine_create(const char* rules);

struct C_Engine* engine_create_with_metadata(
const char* rules,
struct C_FilterListMetadata** metadata);

/**
* Checks if a `url` matches for the specified `Engine` within the context.
*
Expand Down Expand Up @@ -109,6 +128,25 @@ bool engine_deserialize(struct C_Engine* engine,
*/
void engine_destroy(struct C_Engine* engine);

/**
* Puts a pointer to the homepage of the `FilterListMetadata` into `homepage`.
* Returns `true` if a homepage was returned.
*/
bool filter_list_metadata_homepage(const struct C_FilterListMetadata* metadata,
char** homepage);

/**
* Puts a pointer to the title of the `FilterListMetadata` into `title`. Returns
* `true` if a title was returned.
*/
bool filter_list_metadata_title(const struct C_FilterListMetadata* metadata,
char** title);

/**
* Destroy a `FilterListMetadata` once you are done with it.
*/
void filter_list_metadata_destroy(struct C_FilterListMetadata* metadata);

/**
* Destroy a `*c_char` once you are done with it.
*/
Expand Down
69 changes: 64 additions & 5 deletions components/adblock_rust_ffi/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use adblock::blocker::Redirection;
use adblock::engine::Engine;
use adblock::lists::FilterListMetadata;
use adblock::resources::{MimeType, Resource, ResourceType};
use core::ptr;
use libc::size_t;
Expand Down Expand Up @@ -56,20 +57,48 @@ pub unsafe extern "C" fn engine_create_from_buffer(
eprintln!("Failed to parse filter list with invalid UTF-8 content");
""
});
engine_create_from_str(rules)
engine_create_from_str(rules).1
}

/// Create a new `Engine`.
#[no_mangle]
pub unsafe extern "C" fn engine_create_from_buffer_with_metadata(
data: *const c_char,
data_size: size_t,
metadata: *mut *mut FilterListMetadata,
) -> *mut Engine {
let data: &[u8] = std::slice::from_raw_parts(data as *const u8, data_size);
let rules = std::str::from_utf8(data).unwrap_or_else(|_| {
eprintln!("Failed to parse filter list with invalid UTF-8 content");
""
});
let (metadata_ptr, engine_ptr) = engine_create_from_str(rules);
*metadata = metadata_ptr;
engine_ptr
}

#[no_mangle]
pub unsafe extern "C" fn engine_create(rules: *const c_char) -> *mut Engine {
let rules = CStr::from_ptr(rules).to_str().unwrap_or("");
engine_create_from_str(rules)
engine_create_from_str(rules).1
}

#[no_mangle]
pub unsafe extern "C" fn engine_create_with_metadata(rules: *const c_char, metadata: *mut *mut FilterListMetadata) -> *mut Engine {
let rules = CStr::from_ptr(rules).to_str().unwrap_or("");
let (metadata_ptr, engine_ptr) = engine_create_from_str(rules);
*metadata = metadata_ptr;
engine_ptr
}

fn engine_create_from_str(rules: &str) -> *mut Engine {
fn engine_create_from_str(rules: &str) -> (*mut FilterListMetadata, *mut Engine) {
let mut filter_set = adblock::lists::FilterSet::new(false);
filter_set.add_filter_list(&rules, Default::default());
let metadata = filter_set.add_filter_list(&rules, Default::default());
let engine = Engine::from_filter_set(filter_set, true);
Box::into_raw(Box::new(engine))
(
Box::into_raw(Box::new(metadata)),
Box::into_raw(Box::new(engine)),
)
}

/// Checks if a `url` matches for the specified `Engine` within the context.
Expand Down Expand Up @@ -234,6 +263,36 @@ pub unsafe extern "C" fn engine_destroy(engine: *mut Engine) {
}
}

/// Puts a pointer to the homepage of the `FilterListMetadata` into `homepage`. Returns `true` if a homepage was returned.
#[no_mangle]
pub unsafe extern "C" fn filter_list_metadata_homepage(metadata: *const FilterListMetadata, homepage: *mut *mut c_char) -> bool {
if let Some(this_homepage) = (*metadata).homepage.as_ref() {
*homepage = CString::new(this_homepage.as_str()).expect("Error: CString::new()").into_raw();
return true;
} else {
return false;
}
}

/// Puts a pointer to the title of the `FilterListMetadata` into `title`. Returns `true` if a title was returned.
#[no_mangle]
pub unsafe extern "C" fn filter_list_metadata_title(metadata: *const FilterListMetadata, title: *mut *mut c_char) -> bool {
if let Some(this_title) = (*metadata).title.as_ref() {
*title = CString::new(this_title.as_str()).expect("Error: CString::new()").into_raw();
return true;
} else {
return false;
}
}

/// Destroy a `FilterListMetadata` once you are done with it.
#[no_mangle]
pub unsafe extern "C" fn filter_list_metadata_destroy(metadata: *mut FilterListMetadata) {
if !metadata.is_null() {
drop(Box::from_raw(metadata));
}
}

/// Destroy a `*c_char` once you are done with it.
#[no_mangle]
pub unsafe extern "C" fn c_char_buffer_destroy(s: *mut c_char) {
Expand Down
46 changes: 46 additions & 0 deletions components/adblock_rust_ffi/src/wrapper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,52 @@ FilterList::FilterList(const FilterList& other) = default;

FilterList::~FilterList() {}

FilterListMetadata::FilterListMetadata() {}

FilterListMetadata::FilterListMetadata(C_FilterListMetadata* metadata) {
char* str_buffer;

if (filter_list_metadata_homepage(metadata, &str_buffer)) {
homepage = std::make_optional(std::string(str_buffer));
c_char_buffer_destroy(str_buffer);
}

if (filter_list_metadata_title(metadata, &str_buffer)) {
title = std::make_optional(std::string(str_buffer));
c_char_buffer_destroy(str_buffer);
}
}

FilterListMetadata::~FilterListMetadata() {}

MetadataAndEngine engineWithMetadata(const std::string& rules) {
C_FilterListMetadata* c_metadata;
std::unique_ptr<Engine> engine = std::make_unique<Engine>(
engine_create_with_metadata(rules.c_str(), &c_metadata));
FilterListMetadata metadata = FilterListMetadata(c_metadata);
filter_list_metadata_destroy(c_metadata);

return MetadataAndEngine(metadata, std::move(engine));
}

MetadataAndEngine engineFromBufferWithMetadata(const char* data,
size_t data_size) {
C_FilterListMetadata* c_metadata;
std::unique_ptr<Engine> engine = std::make_unique<Engine>(
engine_create_from_buffer_with_metadata(data, data_size, &c_metadata));
FilterListMetadata metadata = FilterListMetadata(c_metadata);
filter_list_metadata_destroy(c_metadata);

return MetadataAndEngine(metadata, std::move(engine));
}

MetadataAndEngine::MetadataAndEngine(FilterListMetadata metadata,
std::unique_ptr<Engine> engine)
: metadata_(metadata), engine_(std::move(engine)) {}
MetadataAndEngine::~MetadataAndEngine() {}

Engine::Engine(C_Engine* c_engine) : raw(c_engine) {}

Engine::Engine() : raw(engine_create("")) {}

Engine::Engine(const std::string& rules) : raw(engine_create(rules.c_str())) {}
Expand Down
29 changes: 29 additions & 0 deletions components/adblock_rust_ffi/src/wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@

#ifndef BRAVE_COMPONENTS_ADBLOCK_RUST_FFI_SRC_WRAPPER_H_
#define BRAVE_COMPONENTS_ADBLOCK_RUST_FFI_SRC_WRAPPER_H_

#include <optional>

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/memory/raw_ptr.h"
Expand Down Expand Up @@ -66,9 +70,19 @@ class ADBLOCK_EXPORT FilterList {
static std::vector<FilterList> regional_list;
};

typedef ADBLOCK_EXPORT struct FilterListMetadata {
FilterListMetadata();
explicit FilterListMetadata(C_FilterListMetadata* metadata);
~FilterListMetadata();

std::optional<std::string> homepage;
std::optional<std::string> title;
} FilterListMetadata;

class ADBLOCK_EXPORT Engine {
public:
Engine();
explicit Engine(C_Engine* c_engine);
explicit Engine(const std::string& rules);
Engine(const char* data, size_t data_size);
void matches(const std::string& url,
Expand Down Expand Up @@ -100,12 +114,27 @@ class ADBLOCK_EXPORT Engine {
const std::vector<std::string>& exceptions);
~Engine();

Engine(Engine&&) = default;

private:
Engine(const Engine&) = delete;
void operator=(const Engine&) = delete;
raw_ptr<C_Engine> raw = nullptr;
};

// Return value from engineWithMetadata
typedef struct MetadataAndEngine {
MetadataAndEngine(FilterListMetadata metadata,
std::unique_ptr<Engine> engine);
~MetadataAndEngine();
FilterListMetadata metadata_;
std::unique_ptr<Engine> engine_;
} MetadataAndEngine;

MetadataAndEngine engineWithMetadata(const std::string& rules);
MetadataAndEngine engineFromBufferWithMetadata(const char* data,
size_t data_size);

} // namespace adblock

#endif // BRAVE_COMPONENTS_ADBLOCK_RUST_FFI_SRC_WRAPPER_H_
27 changes: 17 additions & 10 deletions components/brave_shields/browser/ad_block_engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,8 @@ void AdBlockEngine::UpdateAdBlockClient(
ad_block_client_ = std::move(ad_block_client);
AddResources(resources_json);
AddKnownTagsToAdBlockInstance();
if (test_observer_) {
test_observer_->OnEngineUpdated();
for (AdBlockEngine::EngineUpdateObserver& observer : observers_) {
observer.OnEngineUpdated();
}
}

Expand All @@ -220,10 +220,15 @@ void AdBlockEngine::AddKnownTagsToAdBlockInstance() {

void AdBlockEngine::OnListSourceLoaded(const DATFileDataBuffer& filters,
const std::string& resources_json) {
UpdateAdBlockClient(
std::make_unique<adblock::Engine>(
reinterpret_cast<const char*>(filters.data()), filters.size()),
resources_json);
adblock::MetadataAndEngine metadata_and_engine =
adblock::engineFromBufferWithMetadata(
reinterpret_cast<const char*>(filters.data()), filters.size());
metadata_ = metadata_and_engine.metadata_;
UpdateAdBlockClient(std::move(metadata_and_engine.engine_), resources_json);
}

const adblock::FilterListMetadata& AdBlockEngine::GetLastListMetadata() const {
return metadata_;
}

void AdBlockEngine::OnDATLoaded(const DATFileDataBuffer& dat_buf,
Expand All @@ -240,12 +245,14 @@ void AdBlockEngine::OnDATLoaded(const DATFileDataBuffer& dat_buf,
UpdateAdBlockClient(std::move(client), resources_json);
}

void AdBlockEngine::AddObserverForTest(AdBlockEngine::TestObserver* observer) {
test_observer_ = observer;
void AdBlockEngine::AddUpdateObserver(
AdBlockEngine::EngineUpdateObserver* observer) {
observers_.AddObserver(observer);
}

void AdBlockEngine::RemoveObserverForTest() {
test_observer_ = nullptr;
void AdBlockEngine::RemoveUpdateObserver(
AdBlockEngine::EngineUpdateObserver* observer) {
observers_.RemoveObserver(observer);
}

} // namespace brave_shields
Loading

0 comments on commit 1a9b680

Please sign in to comment.