Introduce brave://adblock-internals (#16797)

This commit is contained in:
Mikhail
2023-01-25 17:30:49 +07:00
committed by GitHub
parent 75e7486566
commit 2271a334ce
29 changed files with 775 additions and 10 deletions
+4
View File
@@ -43,6 +43,8 @@ source_set("ui") {
check_includes = false
public_deps = []
sources = [
"webui/brave_adblock_internals_ui.cc",
"webui/brave_adblock_internals_ui.h",
"webui/brave_adblock_ui.cc",
"webui/brave_adblock_ui.h",
"webui/brave_federated/federated_internals_page_handler.cc",
@@ -391,6 +393,7 @@ source_set("ui") {
"//brave/chromium_src/chrome/browser/ui",
"//brave/common",
"//brave/components/brave_adblock_ui:generated_resources",
"//brave/components/brave_adblock_ui/adblock_internals:generated_resources",
"//brave/components/brave_ads/browser",
"//brave/components/brave_ads/browser",
"//brave/components/brave_federated",
@@ -436,6 +439,7 @@ source_set("ui") {
"//content/public/common",
"//mojo/public/cpp/bindings",
"//services/network/public/cpp",
"//services/resource_coordinator/public/cpp/memory_instrumentation:browser",
"//skia",
"//third_party/abseil-cpp:absl",
"//ui/accessibility",
@@ -0,0 +1,143 @@
// Copyright (c) 2023 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
#include "brave/browser/ui/webui/brave_adblock_internals_ui.h"
#include <memory>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/process/process.h"
#include "base/strings/string_number_conversions.h"
#include "base/values.h"
#include "brave/browser/brave_browser_process.h"
#include "brave/browser/ui/webui/brave_webui_source.h"
#include "brave/components/brave_adblock/adblock_internals/resources/grit/brave_adblock_internals_generated_map.h"
#include "brave/components/brave_shields/browser/ad_block_service.h"
#include "components/grit/brave_components_resources.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/browser/web_ui_data_source.h"
#include "content/public/browser/web_ui_message_handler.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
namespace {
// See chrome/browser/metrics/process_memory_metrics_emitter.cc.
struct MemoryMetric {
// The root dump name that represents the required metric.
const char* const dump_name;
// The type of metric that is measured, usually size in bytes or object count.
const char* const metric;
} const kCollectedMemoryMetrics[] = {
{"malloc", "size"},
};
// Class acting as a controller of the brave://adblock-internals WebUI.
class BraveAdblockInternalsMessageHandler
: public content::WebUIMessageHandler {
public:
BraveAdblockInternalsMessageHandler() = default;
~BraveAdblockInternalsMessageHandler() override = default;
private:
// WebUIMessageHandler implementation.
void RegisterMessages() override {
web_ui()->RegisterMessageCallback(
"brave_adblock_internals.getDebugInfo",
base::BindRepeating(&BraveAdblockInternalsMessageHandler::GetDebugInfo,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"brave_adblock_internals.discardRegex",
base::BindRepeating(&BraveAdblockInternalsMessageHandler::DiscardRegex,
base::Unretained(this)));
}
void GetDebugInfo(const base::Value::List& args) {
CHECK_EQ(1U, args.size());
const auto& callback_id = args[0].GetString();
AllowJavascript();
auto* instrumentation =
memory_instrumentation::MemoryInstrumentation::GetInstance();
std::vector<std::string> mad_list;
for (const auto& metric : kCollectedMemoryMetrics)
mad_list.push_back(metric.dump_name);
instrumentation->RequestGlobalDumpForPid(
base::Process::Current().Pid(), mad_list,
base::BindOnce(&BraveAdblockInternalsMessageHandler::OnGetMemoryDump,
weak_ptr_factory_.GetWeakPtr(), callback_id));
}
void OnGetMemoryDump(
const std::string& callback_id,
bool success,
std::unique_ptr<memory_instrumentation::GlobalMemoryDump> dump) {
if (!success) {
RejectJavascriptCallback(base::Value(callback_id),
base::Value("failed to get dump"));
}
base::Value::Dict mem_info;
CHECK(!dump->process_dumps().empty());
const auto& pmd = dump->process_dumps().front();
for (const auto& metric : kCollectedMemoryMetrics) {
absl::optional<uint64_t> value =
pmd.GetMetric(metric.dump_name, metric.metric);
if (value) {
mem_info.Set(
std::string(metric.dump_name) + "/" + metric.metric + "_kb",
base::NumberToString(*value / 1024));
}
}
mem_info.Set("private_footprint_kb",
static_cast<int>(pmd.os_dump().private_footprint_kb));
g_brave_browser_process->ad_block_service()->GetDebugInfoAsync(
base::BindOnce(&BraveAdblockInternalsMessageHandler::OnGetDebugInfo,
weak_ptr_factory_.GetWeakPtr(), callback_id,
std::move(mem_info)));
}
void DiscardRegex(const base::Value::List& args) {
CHECK_EQ(1U, args.size());
uint64_t regex_id = 0U;
if (!base::StringToUint64(args[0].GetString(), &regex_id))
return;
g_brave_browser_process->ad_block_service()->DiscardRegex(regex_id);
}
void OnGetDebugInfo(const std::string& callback_id,
base::Value::Dict mem_info,
base::Value::Dict default_engine_info,
base::Value::Dict additional_engine_info) {
base::Value::Dict result;
result.Set("default_engine", std::move(default_engine_info));
result.Set("additional_engine", std::move(additional_engine_info));
result.Set("memory", std::move(mem_info));
ResolveJavascriptCallback(base::Value(callback_id), std::move(result));
}
base::WeakPtrFactory<BraveAdblockInternalsMessageHandler> weak_ptr_factory_{
this};
};
} // namespace
BraveAdblockInternalsUI::BraveAdblockInternalsUI(content::WebUI* web_ui,
const std::string& name)
: content::WebUIController(web_ui) {
CreateAndAddWebUIDataSource(web_ui, name, kBraveAdblockInternalsGenerated,
kBraveAdblockInternalsGeneratedSize,
IDR_BRAVE_ADBLOCK_INTERNALS_HTML);
web_ui->AddMessageHandler(
std::make_unique<BraveAdblockInternalsMessageHandler>());
}
BraveAdblockInternalsUI::~BraveAdblockInternalsUI() = default;
@@ -0,0 +1,24 @@
// Copyright (c) 2023 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.
#ifndef BRAVE_BROWSER_UI_WEBUI_BRAVE_ADBLOCK_INTERNALS_UI_H_
#define BRAVE_BROWSER_UI_WEBUI_BRAVE_ADBLOCK_INTERNALS_UI_H_
#include <string>
#include "content/public/browser/web_ui_controller.h"
// The WebUI for brave://adblock-internals
class BraveAdblockInternalsUI : public content::WebUIController {
public:
BraveAdblockInternalsUI(content::WebUI* web_ui, const std::string& name);
BraveAdblockInternalsUI(const BraveAdblockInternalsUI&) = delete;
BraveAdblockInternalsUI& operator=(const BraveAdblockInternalsUI&) = delete;
~BraveAdblockInternalsUI() override;
};
#endif // BRAVE_BROWSER_UI_WEBUI_BRAVE_ADBLOCK_INTERNALS_UI_H_
@@ -11,6 +11,7 @@
#include "base/memory/ptr_util.h"
#include "brave/browser/brave_rewards/rewards_util.h"
#include "brave/browser/ethereum_remote_client/buildflags/buildflags.h"
#include "brave/browser/ui/webui/brave_adblock_internals_ui.h"
#include "brave/browser/ui/webui/brave_adblock_ui.h"
#include "brave/browser/ui/webui/brave_federated/federated_internals_ui.h"
#include "brave/browser/ui/webui/brave_rewards_internals_ui.h"
@@ -85,6 +86,8 @@ WebUIController* NewWebUI(WebUI* web_ui, const GURL& url) {
web_ui->GetWebContents()->GetBrowserContext());
if (host == kAdblockHost) {
return new BraveAdblockUI(web_ui, url.host());
} else if (host == kAdblockInternalsHost) {
return new BraveAdblockInternalsUI(web_ui, url.host());
} else if (host == kWebcompatReporterHost) {
return new WebcompatReporterUI(web_ui, url.host());
#if BUILDFLAG(ENABLE_IPFS)
@@ -173,6 +176,7 @@ WebUIController* NewWebUI(WebUI* web_ui, const GURL& url) {
// with it.
WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, const GURL& url) {
if (url.host_piece() == kAdblockHost ||
url.host_piece() == kAdblockInternalsHost ||
url.host_piece() == kWebcompatReporterHost ||
#if BUILDFLAG(ENABLE_IPFS)
(url.host_piece() == kIPFSWebUIHost &&
+2 -2
View File
@@ -4,9 +4,9 @@ version = 3
[[package]]
name = "adblock"
version = "0.6.3"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74c2a8bca136c13544c752e911da72ff64cca1dd955f701d0202b4a9d348d39f"
checksum = "413a31d3d06e4e645113f43fbfd33f12c7ebe27cf2568e1e97f33b9f7107fcde"
dependencies = [
"base64 0.13.0",
"bitflags",
@@ -6,9 +6,9 @@
#include "brave/components/constants/webui_url_constants.h"
#include "chrome/common/webui_url_constants.h"
#define kChromeUIAttributionInternalsHost \
kChromeUIAttributionInternalsHost, kAdblockHost, kIPFSWebUIHost, \
kRewardsPageHost, kRewardsInternalsHost, kWelcomeHost, kWalletPageHost, \
kTorInternalsHost
#define kChromeUIAttributionInternalsHost \
kChromeUIAttributionInternalsHost, kAdblockHost, kAdblockInternalsHost, \
kIPFSWebUIHost, kRewardsPageHost, kRewardsInternalsHost, kWelcomeHost, \
kWalletPageHost, kTorInternalsHost
#include "src/chrome/common/webui_url_constants.cc"
#undef kChromeUIAttributionInternalsHost
+1 -1
View File
@@ -5,7 +5,7 @@ authors = ["Brian R. Bondy <netzen@gmail.com>"]
edition = "2018"
[dependencies]
adblock = { version = "0.6.3", default-features = false, features = ["full-regex-handling", "object-pooling", "unsync-regex-caching"] }
adblock = { version = "0.7.0", default-features = false, features = ["full-regex-handling", "object-pooling", "unsync-regex-caching", "debug-info"] }
serde_json = "1.0"
libc = "0.2"
+45 -1
View File
@@ -172,6 +172,50 @@ void filter_list_metadata_destroy(struct C_FilterListMetadata* metadata);
*/
void c_char_buffer_destroy(char* s);
/**
* A structure to hold debug information of engine. Matches to rust
* EngineDebugInfo.
*/
typedef struct C_Engine_Debug_Info C_Engine_Debug_Info;
/**
* Get EngineDebugInfo from the engine. Should be destoyed later by calling
* engine_debug_info_destroy(..).
*/
C_Engine_Debug_Info* get_engine_debug_info(struct C_Engine* engine);
// Returns the field of EngineDebugInfo structure.
void engine_debug_info_get_attr(struct C_Engine_Debug_Info* debug_info,
size_t* compiled_regex_count,
size_t* regex_data_size);
// Returns the fields of EngineDebugInfo->regex_data[index].
// |regex| stay untouched if it ==None in the original structure.
// |index| must be in range [0, regex_data.len() - 1].
void engine_debug_info_get_regex_entry(struct C_Engine_Debug_Info* debug_info,
size_t index,
uint64_t* id,
char** regex,
uint64_t* unused_sec,
size_t* usage_count);
/**
* Destroy a `EngineDebugInfo` once you are done with it.
*/
void engine_debug_info_destroy(struct C_Engine_Debug_Info* debug_info);
void discard_regex(struct C_Engine* engine, uint64_t regex_id);
/**
* Setup discard policy for adblock regexps.
* |cleanup_interval_sec| how ofter the engine should check the policy.
* |discard_unused_sec| time in sec after unused regex will be discarded. Zero
* means disable discarding completely.
*/
void setup_discard_policy(struct C_Engine* engine,
uint64_t cleanup_interval_sec,
uint64_t discard_unused_sec);
/**
* Returns a set of cosmetic filtering resources specific to the given url, in
* JSON format
@@ -196,4 +240,4 @@ char* engine_hidden_class_id_selectors(struct C_Engine* engine,
char* convert_rules_to_content_blocking(const char* rules);
#endif
#endif /* BRAVE_COMPONENTS_ADBLOCK_RUST_FFI_SRC_LIB_H_ */
#endif // BRAVE_COMPONENTS_ADBLOCK_RUST_FFI_SRC_LIB_H_
+78 -1
View File
@@ -3,9 +3,10 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
use adblock::engine::Engine;
use adblock::engine::{Engine, EngineDebugInfo};
use adblock::lists::FilterListMetadata;
use adblock::resources::{MimeType, Resource, ResourceType};
use adblock::regex_manager::RegexManagerDiscardPolicy;
use core::ptr;
use libc::size_t;
use std::ffi::CStr;
@@ -343,6 +344,82 @@ pub unsafe extern "C" fn filter_list_metadata_destroy(metadata: *mut FilterListM
}
}
#[no_mangle]
pub unsafe extern "C" fn get_engine_debug_info(
engine: *mut Engine,
) -> *mut EngineDebugInfo{
assert!(!engine.is_null());
let engine = Box::leak(Box::from_raw(engine));
Box::into_raw(Box::new(engine.get_debug_info()))
}
#[no_mangle]
pub unsafe extern "C" fn engine_debug_info_get_attr(
debug_info: *mut EngineDebugInfo,
compiled_regex_count: *mut size_t,
regex_data_size: *mut size_t
) {
assert!(!debug_info.is_null());
let info = Box::leak(Box::from_raw(debug_info));
*compiled_regex_count = info.blocker_debug_info.compiled_regex_count;
*regex_data_size = info.blocker_debug_info.regex_data.len();
}
#[no_mangle]
pub unsafe extern "C" fn engine_debug_info_get_regex_entry(
debug_info: *mut EngineDebugInfo,
index: size_t,
id: *mut u64,
regex: *mut *mut c_char,
unused_sec: *mut u64,
usage_count: *mut usize
) {
assert!(!debug_info.is_null());
let info = Box::leak(Box::from_raw(debug_info));
let regex_data = &info.blocker_debug_info.regex_data;
assert!(index < regex_data.len());
let entry = &regex_data[index];
*id = entry.id;
*regex = CString::new(entry.regex.as_deref().unwrap_or(""))
.expect("Error: CString::new()")
.into_raw();
*unused_sec = entry.last_used.elapsed().as_secs();
*usage_count = entry.usage_count;
}
#[no_mangle]
pub unsafe extern "C" fn engine_debug_info_destroy(
debug_info: *mut EngineDebugInfo,
) {
if !debug_info.is_null() {
drop(Box::from_raw(debug_info));
}
}
#[no_mangle]
pub unsafe extern "C" fn discard_regex(engine: *mut Engine, regex_id: u64) {
assert!(!engine.is_null());
let engine = Box::leak(Box::from_raw(engine));
engine.discard_regex(regex_id);
}
#[no_mangle]
pub unsafe extern "C" fn setup_discard_policy(
engine: *mut Engine,
cleanup_interval_sec: u64,
discard_unused_sec: u64
) {
assert!(!engine.is_null());
let engine = Box::leak(Box::from_raw(engine));
engine.set_regex_discard_policy(RegexManagerDiscardPolicy{
cleanup_interval: std::time::Duration::from_secs(cleanup_interval_sec),
discard_unused_time: std::time::Duration::from_secs(discard_unused_sec),
});
}
/// 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) {
@@ -74,6 +74,10 @@ engineFromBufferWithMetadata(const char* data, size_t data_size) {
return std::make_pair(std::move(metadata), std::move(engine));
}
AdblockDebugInfo::AdblockDebugInfo() = default;
AdblockDebugInfo::AdblockDebugInfo(const AdblockDebugInfo&) = default;
AdblockDebugInfo::~AdblockDebugInfo() = default;
Engine::Engine(C_Engine* c_engine) : raw(c_engine) {}
Engine::Engine() : raw(engine_create("")) {}
@@ -191,6 +195,38 @@ const std::string Engine::hiddenClassIdSelectors(
return stylesheet;
}
AdblockDebugInfo Engine::getAdblockDebugInfo() {
AdblockDebugInfo info;
auto* debug_info_raw = get_engine_debug_info(raw);
size_t filters_size = 0U;
engine_debug_info_get_attr(debug_info_raw, &info.compiled_regex_count,
&filters_size);
info.regex_data.reserve(filters_size);
for (size_t i = 0; i < filters_size; ++i) {
RegexDebugEntry entry;
char* regex_raw = nullptr;
engine_debug_info_get_regex_entry(debug_info_raw, i, &entry.id, &regex_raw,
&entry.unused_sec, &entry.usage_count);
if (regex_raw) {
entry.regex = std::string(regex_raw);
c_char_buffer_destroy(regex_raw);
}
info.regex_data.push_back(std::move(entry));
}
engine_debug_info_destroy(debug_info_raw);
return info;
}
void Engine::discardRegex(uint64_t regex_id) {
discard_regex(raw, regex_id);
}
void Engine::setupDiscardPolicy(const RegexManagerDiscardPolicy& policy) {
setup_discard_policy(raw, policy.cleanup_interval_sec,
policy.discard_unused_sec);
}
Engine::~Engine() {
engine_destroy(raw);
}
+28
View File
@@ -62,6 +62,30 @@ typedef ADBLOCK_EXPORT struct FilterListMetadata {
FilterListMetadata(const FilterListMetadata&) = delete;
} FilterListMetadata;
// C++ version of adblock-rust:RegexDebugEntry struct.
struct ADBLOCK_EXPORT RegexDebugEntry {
uint64_t id;
std::string regex;
uint64_t unused_sec;
size_t usage_count;
};
// C++ version of adblock-rust:RegexManagerDiscardPolicy struct.
struct ADBLOCK_EXPORT RegexManagerDiscardPolicy {
uint64_t cleanup_interval_sec;
uint64_t discard_unused_sec;
};
// C++ version of adblock-rust:EngineDebugInfo struct.
struct ADBLOCK_EXPORT AdblockDebugInfo {
std::vector<RegexDebugEntry> regex_data;
size_t compiled_regex_count;
AdblockDebugInfo();
AdblockDebugInfo(const AdblockDebugInfo&);
~AdblockDebugInfo();
};
class ADBLOCK_EXPORT Engine {
public:
Engine();
@@ -96,6 +120,10 @@ class ADBLOCK_EXPORT Engine {
const std::vector<std::string>& classes,
const std::vector<std::string>& ids,
const std::vector<std::string>& exceptions);
AdblockDebugInfo getAdblockDebugInfo();
void discardRegex(uint64_t regex_id);
void setupDiscardPolicy(const RegexManagerDiscardPolicy& policy);
~Engine();
Engine(Engine&&) = default;
@@ -0,0 +1,21 @@
# Copyright (c) 2023 The Brave Authors. All rights reserved.
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at https://mozilla.org/MPL/2.0/.
import("//brave/components/common/typescript.gni")
transpile_web_ui("brave_adblock_internals_ui") {
entry_points = [ [
"brave_adblock_internals",
rebase_path("brave_adblock_internals.tsx"),
] ]
resource_name = "brave_adblock_internals"
}
pack_web_resources("generated_resources") {
resource_name = "brave_adblock_internals"
output_dir =
"$root_gen_dir/brave/components/brave_adblock/adblock_internals/resources"
deps = [ ":brave_adblock_internals_ui" ]
}
@@ -0,0 +1,39 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Ad Block Internals</title>
<link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
<script src="chrome://resources/js/load_time_data_deprecated.js"></script>
<script src="/strings.js"></script>
<script src="/brave_adblock_internals.bundle.js"></script>
<style>
#root {
height: 100%;
}
table,
th,
td {
border: 1px solid black;
border-collapse: collapse;
}
.active-entry {
color: black;
}
.inactive-entry {
color: darkgray;
}
</style>
</head>
<body>
<div id="root"></div>
</body>
</html>
@@ -0,0 +1,18 @@
// Copyright (c) 2023 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at https://mozilla.org/MPL/2.0/.
import * as React from 'react'
import { render } from 'react-dom'
// Components
import { App } from './components/app'
function initialize () {
render(
<App />,
document.getElementById('root'))
}
document.addEventListener('DOMContentLoaded', initialize)
@@ -0,0 +1,52 @@
// Copyright (c) 2023 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at https://mozilla.org/MPL/2.0/.
import * as React from 'react'
import { sendWithPromise } from 'chrome://resources/js/cr.js'
import { MemoryInfo } from './memory_info'
import { Engine, EngineDebugInfo } from './engine'
import { discardRegexs, saveRegexTexts } from './regex'
class AppState {
default_engine = new EngineDebugInfo()
additional_engine = new EngineDebugInfo()
memory: { [key: string]: string } = {}
}
export class App extends React.Component<{}, AppState> {
constructor (props: {}) {
super(props)
this.state = new AppState()
this.getDebugInfo()
setInterval(() => { this.getDebugInfo() }, 2000)
}
getDebugInfo () {
return sendWithPromise('brave_adblock_internals.getDebugInfo').then(
this.onGetDebugInfo.bind(this))
}
onGetDebugInfo (state: AppState) {
saveRegexTexts(state.default_engine.regex_data)
saveRegexTexts(state.additional_engine.regex_data)
this.setState(state)
}
discardAll () {
discardRegexs(this.state.default_engine.regex_data)
discardRegexs(this.state.additional_engine.regex_data)
}
render () {
return (
<div>
<MemoryInfo key="memory" caption="Browser process memory" memory={this.state.memory} />
<input type="button" value="Discard All Regex" onClick={() => { this.discardAll() }} />
<Engine key="default_engine" caption="Default engine" info={this.state.default_engine} />
<Engine key="additional_engine" caption="Additional engine" info={this.state.additional_engine} />
</div>
)
}
}
@@ -0,0 +1,40 @@
// Copyright (c) 2023 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at https://mozilla.org/MPL/2.0/.
import * as React from 'react'
import { RegexDebugEntry, Regex } from './regex'
export class EngineDebugInfo {
compiled_regex_count: number = 0
regex_data: RegexDebugEntry[] = []
}
interface Props {
caption: string
info: EngineDebugInfo
}
export class Engine extends React.Component<Props, {}> {
render () {
const items = this.props.info.regex_data.map(
(d, index) => <Regex key={index} regex={d} />)
return (
<table>
<caption><h2>{this.props.caption}</h2></caption>
<tbody>
<tr>
<th>ID</th>
<th>Usage count</th>
<th>Unused (sec)</th>
<th>Regex</th>
<th>Actions</th>
</tr>
{items}
</tbody>
</table>
)
}
}
@@ -0,0 +1,25 @@
// Copyright (c) 2023 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at https://mozilla.org/MPL/2.0/.
import * as React from 'react'
interface Props {
caption: string
memory: { [key: string]: string }
}
export class MemoryInfo extends React.Component<Props, {}> {
render () {
const items = Object.keys(this.props.memory).map(key => {
const v = this.props.memory[key]
return (<div key={key}>{key} : {v}</div>)
})
return (<div>
<h2>{this.props.caption}</h2>
{items}
</div>)
}
}
@@ -0,0 +1,67 @@
// Copyright (c) 2023 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at https://mozilla.org/MPL/2.0/.
import * as React from 'react'
let gIdToRegexMap = new Map<string, string>()
export function discardRegex (id: string) {
chrome.send('brave_adblock_internals.discardRegex', [id])
}
export function saveRegexTexts (list: RegexDebugEntry[]) {
for (const entry of list) {
if (entry.regex !== '') {
gIdToRegexMap.set(entry.id, entry.regex)
}
}
}
export function discardRegexs (list: RegexDebugEntry[]) {
for (const entry of list) {
if (entry.regex !== '') {
discardRegex(entry.id)
}
}
}
export class RegexDebugEntry {
id: string = ''
regex: string = ''
unused_sec: number = 0
usage_count: number = 0
}
interface Props {
regex: RegexDebugEntry
}
export class Regex extends React.Component<Props, {}> {
render () {
const regex = this.props.regex
let regexText = regex.regex
const discarded = regexText === ''
if (discarded) {
regexText = '[UNKNOWN]'
const savedText = gIdToRegexMap.get(regex.id)
if (savedText) {
regexText = savedText
}
}
const className = discarded ? 'inactive-entry' : 'active-entry'
let unused = discarded ? '[DISCARDED]' : regex.unused_sec.toString()
return (
<tr>
<td>{regex.id}</td>
<td>{regex.usage_count}</td>
<td>{unused} </td>
<td><div className={className}>{regexText}</div></td>
<td><input type="button" value="Discard"
onClick={() => { discardRegex(regex.id) }} /></td>
</tr>)
}
}
@@ -16,7 +16,7 @@
#include "base/json/json_reader.h"
#include "base/memory/ptr_util.h"
#include "base/ranges/algorithm.h"
#include "base/strings/utf_string_conversions.h"
#include "base/strings/string_number_conversions.h"
#include "brave/components/adblock_rust_ffi/src/wrapper.h"
#include "brave/components/brave_component_updater/browser/dat_file_util.h"
#include "brave/components/brave_shields/common/brave_shield_constants.h"
@@ -178,6 +178,38 @@ bool AdBlockEngine::TagExists(const std::string& tag) {
return base::Contains(tags_, tag);
}
base::Value::Dict AdBlockEngine::GetDebugInfo() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
const auto debug_info_struct = ad_block_client_->getAdblockDebugInfo();
base::Value::List regex_list;
for (const auto& regex_entry : debug_info_struct.regex_data) {
base::Value::Dict regex_info;
regex_info.Set("id", base::NumberToString(regex_entry.id));
regex_info.Set("regex", regex_entry.regex);
regex_info.Set("unused_sec", static_cast<int>(regex_entry.unused_sec));
regex_info.Set("usage_count", static_cast<int>(regex_entry.usage_count));
regex_list.Append(std::move(regex_info));
}
base::Value::Dict result;
result.Set("compiled_regex_count",
static_cast<int>(debug_info_struct.compiled_regex_count));
result.Set("regex_data", std::move(regex_list));
return result;
}
void AdBlockEngine::DiscardRegex(uint64_t regex_id) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
ad_block_client_->discardRegex(regex_id);
}
void AdBlockEngine::SetupDiscardPolicy(
const adblock::RegexManagerDiscardPolicy& policy) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
regex_discard_policy_ = policy;
ad_block_client_->setupDiscardPolicy(policy);
}
base::Value::Dict AdBlockEngine::UrlCosmeticResources(const std::string& url) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
absl::optional<base::Value> result =
@@ -222,6 +254,7 @@ void AdBlockEngine::UpdateAdBlockClient(
const std::string& resources_json) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
ad_block_client_ = std::move(ad_block_client);
ad_block_client_->setupDiscardPolicy(regex_discard_policy_);
UseResources(resources_json);
AddKnownTagsToAdBlockInstance();
if (test_observer_) {
@@ -64,6 +64,10 @@ class AdBlockEngine : public base::SupportsWeakPtr<AdBlockEngine> {
void EnableTag(const std::string& tag, bool enabled);
bool TagExists(const std::string& tag);
base::Value::Dict GetDebugInfo();
void DiscardRegex(uint64_t regex_id);
void SetupDiscardPolicy(const adblock::RegexManagerDiscardPolicy& policy);
base::Value::Dict UrlCosmeticResources(const std::string& url);
base::Value::List HiddenClassIdSelectors(
const std::vector<std::string>& classes,
@@ -102,6 +106,8 @@ class AdBlockEngine : public base::SupportsWeakPtr<AdBlockEngine> {
friend class ::PerfPredictorTabHelperTest;
std::set<std::string> tags_ GUARDED_BY_CONTEXT(sequence_checker_);
adblock::RegexManagerDiscardPolicy regex_discard_policy_
GUARDED_BY_CONTEXT(sequence_checker_);
raw_ptr<TestObserver> test_observer_ = nullptr;
@@ -273,6 +273,16 @@ AdBlockService::AdBlockService(
// Initializes adblock-rust's domain resolution implementation
adblock::SetDomainResolver(AdBlockServiceDomainResolver);
if (base::FeatureList::IsEnabled(
features::kAdblockOverrideRegexDiscardPolicy)) {
adblock::RegexManagerDiscardPolicy policy;
policy.cleanup_interval_sec =
features::kAdblockOverrideRegexDiscardPolicyCleanupIntervalSec.Get();
policy.discard_unused_sec =
features::kAdblockOverrideRegexDiscardPolicyDiscardUnusedSec.Get();
SetupDiscardPolicy(policy);
}
resource_provider_ = std::make_unique<AdBlockDefaultResourceProvider>(
component_update_service_);
filter_list_catalog_provider_ =
@@ -313,6 +323,42 @@ void AdBlockService::EnableTag(const std::string& tag, bool enabled) {
base::Unretained(default_engine_.get()), tag, enabled));
}
void AdBlockService::GetDebugInfoAsync(GetDebugInfoCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// base::Unretained() is safe because |default_engine_| is deleted
// on the same sequence. See docs/threading_and_tasks_testing.md for
// explanations.
GetTaskRunner()->PostTaskAndReplyWithResult(
FROM_HERE,
base::BindOnce(&AdBlockEngine::GetDebugInfo,
base::Unretained(default_engine_.get())),
base::BindOnce(&AdBlockService::OnGetDebugInfoFromDefaultEngine,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
void AdBlockService::DiscardRegex(uint64_t regex_id) {
// Dispatch to both default & additional engines, ids are unique.
GetTaskRunner()->PostTask(
FROM_HERE, base::BindOnce(&AdBlockEngine::DiscardRegex,
default_engine_->AsWeakPtr(), regex_id));
GetTaskRunner()->PostTask(
FROM_HERE,
base::BindOnce(&AdBlockEngine::DiscardRegex,
additional_filters_engine_->AsWeakPtr(), regex_id));
}
void AdBlockService::SetupDiscardPolicy(
const adblock::RegexManagerDiscardPolicy& policy) {
GetTaskRunner()->PostTask(
FROM_HERE, base::BindOnce(&AdBlockEngine::SetupDiscardPolicy,
default_engine_->AsWeakPtr(), policy));
GetTaskRunner()->PostTask(
FROM_HERE,
base::BindOnce(&AdBlockEngine::SetupDiscardPolicy,
additional_filters_engine_->AsWeakPtr(), policy));
}
base::SequencedTaskRunner* AdBlockService::GetTaskRunner() {
return task_runner_.get();
}
@@ -352,6 +398,22 @@ void AdBlockService::UseCustomSourceProvidersForTest(
GetTaskRunner());
}
void AdBlockService::OnGetDebugInfoFromDefaultEngine(
GetDebugInfoCallback callback,
base::Value::Dict default_engine_debug_info) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// base::Unretained() is safe because |additional_filters_engine_| is deleted
// on the same sequence. See docs/threading_and_tasks_testing.md for
// explanations.
GetTaskRunner()->PostTaskAndReplyWithResult(
FROM_HERE,
base::BindOnce(&AdBlockEngine::GetDebugInfo,
base::Unretained(additional_filters_engine_.get())),
base::BindOnce(std::move(callback),
std::move(default_engine_debug_info)));
}
void AdBlockService::TagExistsForTest(const std::string& tag,
base::OnceCallback<void(bool)> cb) {
GetTaskRunner()->PostTaskAndReplyWithResult(
@@ -36,6 +36,9 @@ namespace component_updater {
class ComponentUpdateService;
} // namespace component_updater
namespace adblock {
struct RegexManagerDiscardPolicy;
}
namespace brave_shields {
class AdBlockEngine;
@@ -117,6 +120,14 @@ class AdBlockService {
void EnableTag(const std::string& tag, bool enabled);
// Methods for brave://adblock-internals.
using GetDebugInfoCallback =
base::OnceCallback<void(base::Value::Dict, base::Value::Dict)>;
void GetDebugInfoAsync(GetDebugInfoCallback callback);
void DiscardRegex(uint64_t regex_id);
void SetupDiscardPolicy(const adblock::RegexManagerDiscardPolicy& policy);
base::SequencedTaskRunner* GetTaskRunner();
void UseSourceProvidersForTest(AdBlockFiltersProvider* source_provider,
@@ -136,6 +147,10 @@ class AdBlockService {
return default_filters_provider_.get();
}
void OnGetDebugInfoFromDefaultEngine(
GetDebugInfoCallback callback,
base::Value::Dict default_engine_debug_info);
void TagExistsForTest(const std::string& tag,
base::OnceCallback<void(bool)> cb);
@@ -106,5 +106,17 @@ constexpr base::FeatureParam<std::string>
kCosmeticFilteringFetchNewClassIdRulesThrottlingMs{
&kCosmeticFilteringJsPerformance, "fetch_throttling_ms", "100"};
BASE_FEATURE(kAdblockOverrideRegexDiscardPolicy,
"AdblockOverrideRegexDiscardPolicy",
base::FEATURE_DISABLED_BY_DEFAULT);
constexpr base::FeatureParam<int>
kAdblockOverrideRegexDiscardPolicyCleanupIntervalSec{
&kAdblockOverrideRegexDiscardPolicy, "cleanup_interval_sec", 0};
constexpr base::FeatureParam<int>
kAdblockOverrideRegexDiscardPolicyDiscardUnusedSec{
&kAdblockOverrideRegexDiscardPolicy, "discard_unused_sec", 180};
} // namespace features
} // namespace brave_shields
@@ -35,6 +35,12 @@ extern const base::FeatureParam<std::string>
kCosmeticFilteringswitchToSelectorsPollingThreshold;
extern const base::FeatureParam<std::string>
kCosmeticFilteringFetchNewClassIdRulesThrottlingMs;
BASE_DECLARE_FEATURE(kAdblockOverrideRegexDiscardPolicy);
extern const base::FeatureParam<int>
kAdblockOverrideRegexDiscardPolicyCleanupIntervalSec;
extern const base::FeatureParam<int>
kAdblockOverrideRegexDiscardPolicyDiscardUnusedSec;
} // namespace features
} // namespace brave_shields
@@ -6,6 +6,7 @@
#include "brave/components/constants/webui_url_constants.h"
const char kAdblockHost[] = "adblock";
const char kAdblockInternalsHost[] = "adblock-internals";
const char kAdblockJS[] = "brave_adblock.js";
const char kIPFSWebUIHost[] = "ipfs-internals";
const char kIPFSWebUIURL[] = "chrome://ipfs-internals/";
@@ -7,6 +7,7 @@
#define BRAVE_COMPONENTS_CONSTANTS_WEBUI_URL_CONSTANTS_H_
extern const char kAdblockHost[];
extern const char kAdblockInternalsHost[];
extern const char kAdblockJS[];
extern const char kIPFSWebUIHost[];
extern const char kIPFSWebUIURL[];
+2
View File
@@ -54,10 +54,12 @@ repack("resources") {
if (!is_ios) {
deps += [
"//brave/components/brave_adblock_ui:generated_resources",
"//brave/components/brave_adblock_ui/adblock_internals:generated_resources",
"//brave/components/cosmetic_filters/resources/data:generated_resources",
]
sources += [
"$root_gen_dir/brave/components/brave_adblock/adblock_internals/resources/brave_adblock_internals_generated.pak",
"$root_gen_dir/brave/components/brave_adblock/resources/brave_adblock_generated.pak",
"$root_gen_dir/brave/components/cosmetic_filters/resources/cosmetic_filters_generated.pak",
]
@@ -17,6 +17,7 @@
<!-- WebUI adblock resources -->
<!-- TODO: move to brave_adblock_ui component -->
<include name="IDR_BRAVE_ADBLOCK_HTML" file="../brave_adblock_ui/brave_adblock.html" type="BINDATA" />
<include name="IDR_BRAVE_ADBLOCK_INTERNALS_HTML" file="../brave_adblock_ui/adblock_internals/brave_adblock_internals.html" type="BINDATA" />
<!-- WebUI webcompat reporter resources -->
<!-- TODO: move to webcompat_reporter_ui component -->
+4
View File
@@ -198,5 +198,9 @@
"<(SHARED_INTERMEDIATE_DIR)/brave/web-ui-brave_speedreader_panel/brave_speedreader_panel.grd": {
"META": {"sizes": {"includes": [20]}},
"includes": [59820]
},
"<(SHARED_INTERMEDIATE_DIR)/brave/web-ui-brave_adblock_internals/brave_adblock_internals.grd": {
"META": {"sizes": {"includes": [50]}},
"includes": [59840],
}
}