Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-add the ability to allow individual scripts in Shields (Native part) #17152

Merged
merged 3 commits into from
Feb 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 33 additions & 4 deletions browser/brave_shields/brave_shields_web_contents_observer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -172,15 +172,44 @@ void BraveShieldsWebContentsObserver::DispatchBlockedEventForWebContents(
return;
shields_data_ctrlr->HandleItemBlocked(block_type, subresource);
}
// static
void BraveShieldsWebContentsObserver::DispatchAllowedOnceEventForWebContents(
const std::string& block_type,
const std::string& subresource,
WebContents* web_contents) {
if (!web_contents) {
return;
}
auto* shields_data_ctrlr =
brave_shields::BraveShieldsDataController::FromWebContents(web_contents);
// |shields_data_ctrlr| can be null if the |web_contents| is generated in
// component layer - We don't attach any tab helpers in this case.
if (!shields_data_ctrlr) {
return;
}
shields_data_ctrlr->HandleItemAllowedOnce(block_type, subresource);
}
#endif

void BraveShieldsWebContentsObserver::OnJavaScriptBlocked(
void BraveShieldsWebContentsObserver::OnJavaScriptAllowedOnce(
const std::u16string& details) {
#if !BUILDFLAG(IS_ANDROID)
WebContents* web_contents =
WebContents::FromRenderFrameHost(receivers_.GetCurrentTargetFrame());
if (!web_contents)
return;
DispatchAllowedOnceEventForWebContents(
brave_shields::kJavaScript, base::UTF16ToUTF8(details), web_contents);
#endif
}

void BraveShieldsWebContentsObserver::OnJavaScriptBlocked(
const std::u16string& details) {
WebContents* web_contents =
WebContents::FromRenderFrameHost(receivers_.GetCurrentTargetFrame());
if (!web_contents) {
return;
}
DispatchBlockedEventForWebContents(brave_shields::kJavaScript,
base::UTF16ToUTF8(details), web_contents);
}
Expand Down Expand Up @@ -227,9 +256,9 @@ void BraveShieldsWebContentsObserver::ReadyToCommitNavigation(
}

void BraveShieldsWebContentsObserver::AllowScriptsOnce(
const std::vector<std::string>& origins,
WebContents* contents) {
allowed_script_origins_ = std::move(origins);
const std::vector<std::string>& origins) {
allowed_script_origins_.insert(std::end(allowed_script_origins_),
std::begin(origins), std::end(origins));
}

// static
Expand Down
8 changes: 6 additions & 2 deletions browser/brave_shields/brave_shields_web_contents_observer.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,15 @@ class BraveShieldsWebContentsObserver
const std::string& block_type,
const std::string& subresource,
content::WebContents* web_contents);
static void DispatchAllowedOnceEventForWebContents(
const std::string& block_type,
const std::string& subresource,
content::WebContents* web_contents);
static void DispatchBlockedEvent(const GURL& request_url,
int frame_tree_node_id,
const std::string& block_type);
static GURL GetTabURLFromRenderFrameInfo(int render_frame_tree_node_id);
void AllowScriptsOnce(const std::vector<std::string>& origins,
content::WebContents* web_contents);
void AllowScriptsOnce(const std::vector<std::string>& origins);
bool IsBlockedSubresource(const std::string& subresource);
void AddBlockedSubresource(const std::string& subresource);

Expand All @@ -68,6 +71,7 @@ class BraveShieldsWebContentsObserver

// brave_shields::mojom::BraveShieldsHost.
void OnJavaScriptBlocked(const std::u16string& details) override;
void OnJavaScriptAllowedOnce(const std::u16string& details) override;

private:
friend class content::WebContentsUserData<BraveShieldsWebContentsObserver>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "base/memory/raw_ptr.h"
#include "base/path_service.h"
#include "brave/browser/brave_shields/brave_shields_web_contents_observer.h"
#include "brave/browser/ui/brave_shields_data_controller.h"
#include "brave/components/constants/brave_paths.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/profiles/profile.h"
Expand Down Expand Up @@ -79,6 +80,24 @@ class BraveShieldsWebContentsObserverBrowserTest : public InProcessBrowserTest {
brave_shields_web_contents_observer_);
}

std::vector<GURL> GetBlockedJsList() {
return brave_shields::BraveShieldsDataController::FromWebContents(
GetWebContents())
->GetBlockedJsList();
}

std::vector<GURL> GetAllowedJsList() {
return brave_shields::BraveShieldsDataController::FromWebContents(
GetWebContents())
->GetAllowedJsList();
}

void ClearAllResourcesList() {
return brave_shields::BraveShieldsDataController::FromWebContents(
GetWebContents())
->ClearAllResourcesList();
}

void TearDownOnMainThread() override {
BraveShieldsWebContentsObserver::SetReceiverImplForTesting(nullptr);
}
Expand Down Expand Up @@ -114,7 +133,7 @@ IN_PROC_BROWSER_TEST_F(BraveShieldsWebContentsObserverBrowserTest,
browser(), embedded_test_server()->GetURL("a.com", "/load_js.html")));
EXPECT_TRUE(WaitForLoadStop(GetWebContents()));
EXPECT_EQ(brave_shields_web_contents_observer()->block_javascript_count(), 0);

EXPECT_EQ(GetBlockedJsList().size(), 0u);
// Enable JavaScript blocking globally now.
content_settings()->SetContentSettingCustomScope(
ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
Expand All @@ -128,6 +147,7 @@ IN_PROC_BROWSER_TEST_F(BraveShieldsWebContentsObserverBrowserTest,
GetWebContents()->GetController().Reload(content::ReloadType::NORMAL, true);
EXPECT_TRUE(WaitForLoadStop(GetWebContents()));
EXPECT_GT(brave_shields_web_contents_observer()->block_javascript_count(), 0);
EXPECT_EQ(GetBlockedJsList().size(), 3u);

// Disable JavaScript blocking again now.
content_settings()->SetContentSettingCustomScope(
Expand All @@ -148,6 +168,7 @@ IN_PROC_BROWSER_TEST_F(BraveShieldsWebContentsObserverBrowserTest,
GetWebContents()->GetController().Reload(content::ReloadType::NORMAL, true);
EXPECT_TRUE(WaitForLoadStop(GetWebContents()));
EXPECT_EQ(brave_shields_web_contents_observer()->block_javascript_count(), 0);
EXPECT_EQ(GetBlockedJsList().size(), 0u);
}

IN_PROC_BROWSER_TEST_F(BraveShieldsWebContentsObserverBrowserTest,
Expand All @@ -162,6 +183,81 @@ IN_PROC_BROWSER_TEST_F(BraveShieldsWebContentsObserverBrowserTest,
browser(), embedded_test_server()->GetURL("a.com", "/embedded_js.html")));
EXPECT_TRUE(WaitForLoadStop(GetWebContents()));
EXPECT_GT(brave_shields_web_contents_observer()->block_javascript_count(), 0);
EXPECT_EQ(GetBlockedJsList().size(), 1u);
}

IN_PROC_BROWSER_TEST_F(BraveShieldsWebContentsObserverBrowserTest,
JavaScriptAllowedEvents) {
const GURL& url = GURL("a.com");

// Start with JavaScript blocking initially disabled.
ContentSetting block_javascript_setting =
content_settings()->GetContentSetting(url, url,
ContentSettingsType::JAVASCRIPT);
EXPECT_EQ(CONTENT_SETTING_ALLOW, block_javascript_setting);

// Load a simple HTML that attempts to load some JavaScript without blocking.
EXPECT_TRUE(ui_test_utils::NavigateToURL(
browser(), embedded_test_server()->GetURL("a.com", "/load_js.html")));
EXPECT_TRUE(WaitForLoadStop(GetWebContents()));
EXPECT_EQ(brave_shields_web_contents_observer()->block_javascript_count(), 0);

// Enable JavaScript blocking globally now.
content_settings()->SetContentSettingCustomScope(
ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
ContentSettingsType::JAVASCRIPT, CONTENT_SETTING_BLOCK);
block_javascript_setting = content_settings()->GetContentSetting(
url, url, ContentSettingsType::JAVASCRIPT);
EXPECT_EQ(CONTENT_SETTING_BLOCK, block_javascript_setting);

// Reload the test page now that JavaScript has been blocked.
brave_shields_web_contents_observer()->Reset();
GetWebContents()->GetController().Reload(content::ReloadType::NORMAL, true);
EXPECT_TRUE(WaitForLoadStop(GetWebContents()));
EXPECT_GT(brave_shields_web_contents_observer()->block_javascript_count(), 0);
auto blocked_list = GetBlockedJsList();
EXPECT_EQ(blocked_list.size(), 3u);

// Allow One Script
brave_shields_web_contents_observer()->AllowScriptsOnce(
std::vector<std::string>({blocked_list.back().spec()}));
ClearAllResourcesList();
GetWebContents()->GetController().Reload(content::ReloadType::NORMAL, true);
EXPECT_TRUE(WaitForLoadStop(GetWebContents()));
EXPECT_EQ(GetBlockedJsList().size(), 2u);
EXPECT_EQ(GetAllowedJsList().size(), 1u);

blocked_list.pop_back();
EXPECT_EQ(blocked_list.size(), 2u);

// Allow Second Script
brave_shields_web_contents_observer()->AllowScriptsOnce(
std::vector<std::string>({blocked_list.back().spec()}));
ClearAllResourcesList();
GetWebContents()->GetController().Reload(content::ReloadType::NORMAL, true);
EXPECT_TRUE(WaitForLoadStop(GetWebContents()));
EXPECT_EQ(GetBlockedJsList().size(), 1u);
EXPECT_EQ(GetAllowedJsList().size(), 2u);

// Disable JavaScript blocking again now.
content_settings()->SetContentSettingCustomScope(
ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(),
ContentSettingsType::JAVASCRIPT, CONTENT_SETTING_ALLOW);
block_javascript_setting = content_settings()->GetContentSetting(
url, url, ContentSettingsType::JAVASCRIPT);
EXPECT_EQ(CONTENT_SETTING_ALLOW, block_javascript_setting);

// Reload the test page now that JavaScript has been allowed again.
// Do it twice, because first reload will still trigger blocked events as
// renderer caches AllowScript results in
// ContentSettingsAgentImpl::cached_script_permissions_.
GetWebContents()->GetController().Reload(content::ReloadType::NORMAL, true);
EXPECT_TRUE(WaitForLoadStop(GetWebContents()));

brave_shields_web_contents_observer()->Reset();
GetWebContents()->GetController().Reload(content::ReloadType::NORMAL, true);
EXPECT_TRUE(WaitForLoadStop(GetWebContents()));
EXPECT_EQ(brave_shields_web_contents_observer()->block_javascript_count(), 0);
}

} // namespace brave_shields
38 changes: 37 additions & 1 deletion browser/ui/brave_shields_data_controller.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
#include "brave/browser/ui/brave_shields_data_controller.h"

#include <string>
#include <utility>

#include "brave/browser/brave_shields/brave_shields_web_contents_observer.h"
#include "brave/components/brave_shields/browser/brave_shields_util.h"
#include "brave/components/brave_shields/common/brave_shield_constants.h"
#include "chrome/browser/browser_process.h"
Expand Down Expand Up @@ -91,6 +93,7 @@ void BraveShieldsDataController::ClearAllResourcesList() {
resource_list_http_redirects_.clear();
resource_list_blocked_js_.clear();
resource_list_blocked_fingerprints_.clear();
resource_list_allowed_once_js_.clear();

for (Observer& obs : observer_list_)
obs.OnResourcesChanged();
Expand Down Expand Up @@ -129,10 +132,15 @@ std::vector<GURL> BraveShieldsDataController::GetHttpRedirectsList() {
return http_redirects;
}

std::vector<GURL> BraveShieldsDataController::GetJsList() {
std::vector<GURL> BraveShieldsDataController::GetBlockedJsList() {
std::vector<GURL> js_list(resource_list_blocked_js_.begin(),
resource_list_blocked_js_.end());
return js_list;
}

std::vector<GURL> BraveShieldsDataController::GetAllowedJsList() {
std::vector<GURL> js_list(resource_list_allowed_once_js_.begin(),
resource_list_allowed_once_js_.end());
return js_list;
}

Expand Down Expand Up @@ -376,6 +384,17 @@ void BraveShieldsDataController::SetIsHTTPSEverywhereEnabled(bool is_enabled) {
ReloadWebContents();
}

void BraveShieldsDataController::AllowScriptsOnce(
const std::vector<std::string>& origins) {
BraveShieldsWebContentsObserver* observer =
BraveShieldsWebContentsObserver::FromWebContents(web_contents());
if (!observer) {
return;
}
observer->AllowScriptsOnce(origins);
ReloadWebContents();
goodov marked this conversation as resolved.
Show resolved Hide resolved
}

bool BraveShieldsDataController::IsBraveShieldsManaged() {
PrefService* profile_prefs =
Profile::FromBrowserContext(web_contents()->GetBrowserContext())
Expand Down Expand Up @@ -405,6 +424,23 @@ void BraveShieldsDataController::HandleItemBlocked(
obs.OnResourcesChanged();
}

void BraveShieldsDataController::HandleItemAllowedOnce(
const std::string& allowed_once_type,
const std::string& subresource) {
GURL subres(subresource);
if (allowed_once_type != kJavaScript) {
return;
}
if (resource_list_allowed_once_js_.contains(subres)) {
return;
}
resource_list_allowed_once_js_.insert(std::move(subres));

for (Observer& obs : observer_list_) {
obs.OnResourcesChanged();
}
simonhong marked this conversation as resolved.
Show resolved Hide resolved
}

WEB_CONTENTS_USER_DATA_KEY_IMPL(BraveShieldsDataController);

} // namespace brave_shields
7 changes: 6 additions & 1 deletion browser/ui/brave_shields_data_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,14 @@ class BraveShieldsDataController

void HandleItemBlocked(const std::string& block_type,
const std::string& subresource);
void HandleItemAllowedOnce(const std::string& allowed_once_type,
const std::string& subresource);
void ClearAllResourcesList();
int GetTotalBlockedCount();
std::vector<GURL> GetBlockedAdsList();
std::vector<GURL> GetHttpRedirectsList();
std::vector<GURL> GetJsList();
std::vector<GURL> GetBlockedJsList();
std::vector<GURL> GetAllowedJsList();
std::vector<GURL> GetFingerprintsList();
bool GetBraveShieldsEnabled();
void SetBraveShieldsEnabled(bool is_enabled);
Expand All @@ -74,6 +77,7 @@ class BraveShieldsDataController
void SetHttpsUpgradeMode(HttpsUpgradeMode mode);
void SetIsNoScriptEnabled(bool is_enabled);
void SetIsHTTPSEverywhereEnabled(bool is_enabled);
void AllowScriptsOnce(const std::vector<std::string>& origins);

void AddObserver(Observer* obs);
void RemoveObserver(Observer* obs);
Expand Down Expand Up @@ -108,6 +112,7 @@ class BraveShieldsDataController
std::set<GURL> resource_list_blocked_ads_;
std::set<GURL> resource_list_http_redirects_;
std::set<GURL> resource_list_blocked_js_;
std::set<GURL> resource_list_allowed_once_js_;
std::set<GURL> resource_list_blocked_fingerprints_;
base::ScopedObservation<HostContentSettingsMap, content_settings::Observer>
observation_{this};
Expand Down
23 changes: 23 additions & 0 deletions browser/ui/brave_shields_data_controller_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -401,3 +401,26 @@ TEST_F(BraveShieldsDataControllerTest, SetBraveShieldsEnabledAsDefaultValue) {
->GetDict("profile.content_settings.exceptions.braveShields")
.empty());
}

TEST_F(BraveShieldsDataControllerTest, AllowedOnceScripts) {
EXPECT_EQ(GetShieldsDataController()->GetAllowedJsList().size(), 0u);
GetShieldsDataController()->HandleItemAllowedOnce(
brave_shields::kJavaScript, "https://url1.com/script.js");
EXPECT_EQ(GetShieldsDataController()->GetAllowedJsList().size(), 1u);
GetShieldsDataController()->HandleItemAllowedOnce(
brave_shields::kJavaScript, "https://url2.com/script.js");
EXPECT_EQ(GetShieldsDataController()->GetAllowedJsList().size(), 2u);
GetShieldsDataController()->HandleItemAllowedOnce(
brave_shields::kJavaScript, "https://url3.com/script.js");
EXPECT_EQ(GetShieldsDataController()->GetAllowedJsList().size(), 3u);

// Making sure we exclude duplicates
GetShieldsDataController()->HandleItemAllowedOnce(
brave_shields::kJavaScript, "https://url2.com/script.js");
GetShieldsDataController()->HandleItemAllowedOnce(
brave_shields::kJavaScript, "https://url3.com/script.js");
EXPECT_EQ(GetShieldsDataController()->GetAllowedJsList().size(), 3u);

GetShieldsDataController()->ClearAllResourcesList();
EXPECT_EQ(GetShieldsDataController()->GetAllowedJsList().size(), 0u);
}
12 changes: 11 additions & 1 deletion browser/ui/webui/brave_shields/shields_panel_data_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,15 @@ void ShieldsPanelDataHandler::SetIsNoScriptsEnabled(bool is_enabled) {
active_shields_data_controller_->SetIsNoScriptEnabled(is_enabled);
}

void ShieldsPanelDataHandler::AllowScriptsOnce(
const std::vector<std::string>& origins) {
if (!active_shields_data_controller_) {
return;
}

active_shields_data_controller_->AllowScriptsOnce(origins);
}

void ShieldsPanelDataHandler::SetHTTPSEverywhereEnabled(bool is_enabled) {
if (!active_shields_data_controller_)
return;
Expand Down Expand Up @@ -160,7 +169,8 @@ void ShieldsPanelDataHandler::UpdateSiteBlockInfo() {
active_shields_data_controller_->GetTotalBlockedCount();
site_block_info_.ads_list =
active_shields_data_controller_->GetBlockedAdsList();
site_block_info_.js_list = active_shields_data_controller_->GetJsList();
site_block_info_.js_list =
active_shields_data_controller_->GetBlockedJsList();
site_block_info_.fingerprints_list =
active_shields_data_controller_->GetFingerprintsList();
site_block_info_.http_redirects_list =
Expand Down
Loading