Skip to content

Commit

Permalink
Added adblock info tab. (#25490)
Browse files Browse the repository at this point in the history
* Added adblock info tab.
  • Loading branch information
boocmp authored Sep 17, 2024
1 parent ea7af3e commit 0955815
Show file tree
Hide file tree
Showing 41 changed files with 948 additions and 22 deletions.
103 changes: 103 additions & 0 deletions browser/brave_shields/ad_block_devtools_browsertest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/* Copyright (c) 2024 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 "base/values.h"
#include "brave/browser/brave_shields/ad_block_service_browsertest.h"
#include "chrome/browser/interstitials/security_interstitial_page_test_utils.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_devtools_protocol_client.h"
#include "url/gurl.h"

#if BUILDFLAG(IS_ANDROID)
#include "chrome/test/base/android/android_browser_test.h"
#else
#include "chrome/test/base/in_process_browser_test.h"
#endif

class AdblockDevtoolsTest : public AdBlockServiceTest,
public content::TestDevToolsProtocolClient {
public:
AdblockDevtoolsTest() = default;
~AdblockDevtoolsTest() override = default;

bool IsShowingInterstitial() {
return chrome_browser_interstitials::IsShowingInterstitial(web_contents());
}

protected:
void TearDownOnMainThread() override {
DetachProtocolClient();
AdBlockServiceTest::TearDownOnMainThread();
}
};

IN_PROC_BROWSER_TEST_F(AdblockDevtoolsTest, DomainBlock) {
AttachToWebContents(web_contents());
SendCommandSync("Network.enable");

const GURL& url = embedded_test_server()->GetURL("a.com", "/simple.html");
UpdateAdBlockInstanceWithRules("||" + url.host() + "^");
NavigateToURL(url);

EXPECT_TRUE(IsShowingInterstitial());

const base::Value::Dict& notification =
WaitForNotification("Network.requestAdblockInfoReceived", true);
const auto* info = notification.FindDict("info");
ASSERT_TRUE(info);
EXPECT_EQ(url.spec(), *info->FindString("requestUrl"));
EXPECT_EQ("Document", *info->FindString("resourceType"));
EXPECT_TRUE(*info->FindBool("blocked"));
EXPECT_TRUE(*info->FindBool("didMatchRule"));
}

IN_PROC_BROWSER_TEST_F(AdblockDevtoolsTest, ResourceBlock) {
AttachToWebContents(web_contents());
SendCommandSync("Network.enable");

const GURL& url = embedded_test_server()->GetURL("/blocking.html");
UpdateCustomAdBlockInstanceWithRules("*ad_banner.png");
NavigateToURL(url);

ASSERT_EQ(true, EvalJs(web_contents(),
"setExpectations(0, 1, 0, 0);"
"addImage('ad_banner.png')"));
const base::Value::Dict& notification =
WaitForNotification("Network.requestAdblockInfoReceived", true);

const auto* info = notification.FindDict("info");
ASSERT_TRUE(info);
const GURL& image_url = embedded_test_server()->GetURL("/ad_banner.png");
EXPECT_EQ(image_url.spec(), *info->FindString("requestUrl"));
EXPECT_EQ("Image", *info->FindString("resourceType"));
EXPECT_TRUE(*info->FindBool("blocked"));
EXPECT_TRUE(*info->FindBool("didMatchRule"));
}

IN_PROC_BROWSER_TEST_F(AdblockDevtoolsTest, Exception) {
AttachToWebContents(web_contents());
SendCommandSync("Network.enable");

const GURL& url = embedded_test_server()->GetURL("/blocking.html");
UpdateAdBlockInstanceWithRules("*ad_banner.png");
UpdateCustomAdBlockInstanceWithRules("@@ad_banner.png");
NavigateToURL(url);

ASSERT_EQ(true, EvalJs(web_contents(),
"setExpectations(1, 0, 0, 0);"
"addImage('ad_banner.png')"));
const base::Value::Dict& notification =
WaitForNotification("Network.requestAdblockInfoReceived", true);

const auto* info = notification.FindDict("info");
ASSERT_TRUE(info);
const GURL& image_url = embedded_test_server()->GetURL("/ad_banner.png");
EXPECT_EQ(image_url.spec(), *info->FindString("requestUrl"));
EXPECT_EQ("Image", *info->FindString("resourceType"));
EXPECT_FALSE(*info->FindBool("blocked"));
EXPECT_TRUE(*info->FindBool("didMatchRule"));
EXPECT_TRUE(*info->FindBool("didMatchException"));
}
27 changes: 27 additions & 0 deletions browser/net/brave_ad_block_tp_network_delegate_helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "brave/components/brave_shields/core/common/brave_shield_constants.h"
#include "brave/components/brave_shields/core/common/features.h"
#include "brave/components/constants/url_constants.h"
#include "brave/content/public/browser/devtools/adblock_devtools_instumentation.h"
#include "chrome/browser/net/secure_dns_config.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "components/prefs/pref_service.h"
Expand Down Expand Up @@ -198,11 +199,13 @@ EngineFlags ShouldBlockRequestOnTaskRunner(
previous_result.did_match_rule, previous_result.did_match_exception,
previous_result.did_match_important);

bool has_valid_rewritten_url = false;
if (adblock_result.rewritten_url.has_value &&
GURL(std::string(adblock_result.rewritten_url.value)).is_valid() &&
(ctx->method == "GET" || ctx->method == "HEAD" ||
ctx->method == "OPTIONS")) {
ctx->new_url_spec = std::string(adblock_result.rewritten_url.value);
has_valid_rewritten_url = true;
}

ctx->mock_data_url = std::string(adblock_result.redirect.value);
Expand All @@ -217,6 +220,30 @@ EngineFlags ShouldBlockRequestOnTaskRunner(
ctx->blocked_by = kAdBlocked;
}

const bool should_report_to_devtools =
ctx->devtools_request_id &&
(ctx->blocked_by == kAdBlocked || previous_result.did_match_exception);

if (should_report_to_devtools) {
content::devtools_instrumentation::AdblockInfo info;
info.request_url = ctx->request_url;
info.checked_url = url_to_check;
info.source_host = source_host;
info.resource_type = ctx->resource_type;
info.aggressive = ctx->aggressive_blocking || force_aggressive;
info.blocked = ctx->blocked_by == kAdBlocked;
info.did_match_important_rule = previous_result.did_match_important;
info.did_match_rule = previous_result.did_match_rule;
info.did_match_exception = previous_result.did_match_exception;
info.has_mock_data = !ctx->mock_data_url.empty();
if (has_valid_rewritten_url) {
info.rewritten_url = ctx->new_url_spec;
}

content::devtools_instrumentation::SendAdblockInfo(
ctx->frame_tree_node_id, ctx->devtools_request_id.value(), info);
}

return previous_result;
}

Expand Down
2 changes: 2 additions & 0 deletions browser/net/url_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ std::shared_ptr<brave::BraveRequestInfo> BraveRequestInfo::MakeCTX(
ctx->redirect_source = old_ctx->redirect_source;
}

ctx->devtools_request_id = request.devtools_request_id;

return ctx;
}

Expand Down
2 changes: 2 additions & 0 deletions browser/net/url_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ struct BraveRequestInfo {

std::string upload_data;

std::optional<std::string> devtools_request_id;

static std::shared_ptr<brave::BraveRequestInfo> MakeCTX(
const network::ResourceRequest& request,
int render_process_id,
Expand Down
6 changes: 6 additions & 0 deletions build/commands/lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,12 @@ Config.prototype.buildArgs = function () {
args.enable_brave_page_graph_webapi_probes = false
}

// Devtools: Now we patch devtools frontend, so it is useful to see
// if something goes wrong on CI builds.
if (this.targetOS !== 'android' && this.targetOS !== 'ios' && this.isCI) {
args.devtools_skip_typecheck = false
}

if (this.targetOS) {
args.target_os = this.targetOS;
}
Expand Down
2 changes: 1 addition & 1 deletion build/commands/lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,7 @@ const util = {
// Return true when original file of |file| should be touched.
const applyFileFilter = (file) => {
// Only include overridable files.
const supportedExts = ['.cc', '.h', '.icon', '.json', '.mm', '.mojom', '.pdl', '.py'];
const supportedExts = ['.cc', '.h', '.icon', '.json', '.mm', '.mojom', '.pdl', '.py', '.ts'];
return supportedExts.includes(path.extname(file))
}

Expand Down
22 changes: 22 additions & 0 deletions chromium_src/content/browser/devtools/protocol/network_handler.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/* Copyright (c) 2024 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 "content/browser/devtools/protocol/network_handler.h"

#include "src/content/browser/devtools/protocol/network_handler.cc"

namespace content::protocol {

void NetworkHandler::RequestAdblockInfoReceived(
const std::string& request_id,
std::unique_ptr<protocol::Network::AdblockInfo> info) {
if (!enabled_) {
return;
}

frontend_->RequestAdblockInfoReceived(request_id, std::move(info));
}

} // namespace content::protocol
19 changes: 19 additions & 0 deletions chromium_src/content/browser/devtools/protocol/network_handler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/* Copyright (c) 2024 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_CHROMIUM_SRC_CONTENT_BROWSER_DEVTOOLS_PROTOCOL_NETWORK_HANDLER_H_
#define BRAVE_CHROMIUM_SRC_CONTENT_BROWSER_DEVTOOLS_PROTOCOL_NETWORK_HANDLER_H_

#define NavigationRequestWillBeSent(...) \
NavigationRequestWillBeSent(__VA_ARGS__); \
void RequestAdblockInfoReceived( \
const std::string& request_id, \
std::unique_ptr<protocol::Network::AdblockInfo> info)

#include "src/content/browser/devtools/protocol/network_handler.h" // IWYU pragma: export

#undef NavigationRequestWillBeSent

#endif // BRAVE_CHROMIUM_SRC_CONTENT_BROWSER_DEVTOOLS_PROTOCOL_NETWORK_HANDLER_H_
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,24 @@ domain Page
returns
# Generated report lines
array of string report


domain Network
experimental type AdblockInfo extends object
properties
string requestUrl
string checkedUrl
string sourceHost
optional ResourceType resourceType
boolean aggressive
boolean blocked
boolean didMatchImportantRule
boolean didMatchRule
boolean didMatchException
boolean hasMockData
optional string rewrittenUrl

experimental event requestAdblockInfoReceived
parameters
Network.RequestId requestId
AdblockInfo info
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* Copyright (c) 2024 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/. */

type NetworkDispatcherType = new (...args: any[]) => {
clearRequests(): void
requestForId(id: string): any
// private updateNetworkRequest: (request: NetworkRequest) => void;
}

export function PatchNetworkDispatcher(
NetworkDispatcher: NetworkDispatcherType
): any {
return class extends NetworkDispatcher {
#requestsAdblockInfo: Map<string, object> | undefined

adblockInfoForId(id: string): object | null {
return this.#requestsAdblockInfo?.get(id) || null
}

requestAdblockInfoReceived(params: any): void {
if (!this.#requestsAdblockInfo) {
this.#requestsAdblockInfo = new Map()
}
this.#requestsAdblockInfo.set(params.requestId, params.info)
const networkRequest = this.requestForId(params.requestId)
if (networkRequest) {
;(this as any).updateNetworkRequest(networkRequest)
}
}

override clearRequests(): void {
if (this.#requestsAdblockInfo) {
for (const [requestId, _] of this.#requestsAdblockInfo) {
const request = this.requestForId(requestId)
if (request?.finished) {
this.#requestsAdblockInfo.delete(requestId)
}
}
}

super.clearRequests()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* Copyright (c) 2024 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 SDK from '../../core/sdk/sdk.js'

type NetworkRequestNodeType = new (...args: any[]) => {
request(): SDK.NetworkRequest.NetworkRequest
existingElement(): Element | null
updateBackgroundColor(): void
}

export function PatchNetworkRequestNode(
NetworkRequestNode: NetworkRequestNodeType
): any {
return class extends NetworkRequestNode {
override updateBackgroundColor(): void {
const networkManager = SDK.NetworkManager.NetworkManager.forRequest(
this.request()
)
if (networkManager && networkManager.dispatcher) {
const info = (networkManager.dispatcher as any).adblockInfoForId(
this.request().requestId()
)
const element = this.existingElement() as HTMLElement
if (info && element) {
if ('blocked' in info && info.blocked) {
element.style.color = 'var(--sys-color-error)'
} else if ('didMatchException' in info && info.didMatchException) {
element.style.color = 'var(--ref-palette-green60)'
}
}
}
super.updateBackgroundColor()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/* Copyright (c) 2024 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 SDK from '../../core/sdk/sdk.js'
import * as LegacyWrapper from '../../ui/components/legacy_wrapper/legacy_wrapper.js'
import * as UI from '../../ui/legacy/legacy.js'

import { RequestAdblockView } from './RequestAdblockView.js'

type NetworkItemViewType = new (...args: any[]) => {
request(): SDK.NetworkRequest.NetworkRequest
appendTab(
id: string,
tabTitle: string,
view: any,
tabTooltip?: string,
userGesture?: boolean,
isCloseable?: boolean,
isPreviewFeature?: boolean,
index?: number,
jslogContext?: string
): void
}

export function PatchNetworkItemView(
NetworkItemView: NetworkItemViewType
): any {
return class extends NetworkItemView {
constructor(...args: any[]) {
super(...args)
this.appendTab(
'blocking',
'Adblock',
LegacyWrapper.LegacyWrapper.legacyWrapper(
UI.Widget.VBox,
new RequestAdblockView(this.request())
),
'Adblock'
)
}
}
}
Loading

0 comments on commit 0955815

Please sign in to comment.