Skip to content

Commit

Permalink
Widget exceptions is now an "always activate" list
Browse files Browse the repository at this point in the history
Instead of a "keep blocking but don't replace" list.
  • Loading branch information
ghostwords committed Feb 4, 2025
1 parent 30fb890 commit 7d558e1
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 71 deletions.
4 changes: 2 additions & 2 deletions src/_locales/en_US/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -495,8 +495,8 @@
"message": "Widget Exceptions",
"description": "Header text on the Widget Replacement tab"
},
"options_hide_social_widgets": {
"message": "Don't replace the following widgets:",
"options_widget_exceptions_label": {
"message": "Always allow the following widgets:",
"description": "Label for a form on the Widget Replacement tab"
},
"options_widget_site_exceptions_header": {
Expand Down
3 changes: 2 additions & 1 deletion src/js/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,7 @@ Badger.prototype = {
showExpandedTrackingSection: false,
showIntroPage: true,
showNonTrackingDomains: false,
widgetReplacementExceptions: [],
widgetAllowlist: [],
widgetSiteAllowlist: {},
},

Expand Down Expand Up @@ -846,6 +846,7 @@ Badger.prototype = {
"showTrackingDomains",
"socialWidgetReplacementEnabled",
"webRTCIPProtection",
"widgetReplacementExceptions",
].forEach(item => {
if (settings.hasItem(item)) { settings.deleteItem(item); }
});
Expand Down
30 changes: 17 additions & 13 deletions src/js/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -259,21 +259,23 @@ function loadOptions() {
});
});

const $widgetExceptions = $("#hide-widgets-select");
const $widgetExceptions = $("#always-activate-select");

// Initialize Select2 and populate options
$widgetExceptions.select2({
width: '100%'
});
OPTIONS_DATA.widgets.forEach(function (key) {
const isSelected = OPTIONS_DATA.settings.widgetReplacementExceptions && OPTIONS_DATA.settings.widgetReplacementExceptions.includes(key);
const option = new Option(key, key, false, isSelected);
$widgetExceptions.append(option).trigger("change");
});
for (let widget_name of OPTIONS_DATA.widgets) {
let is_selected = OPTIONS_DATA.settings.widgetAllowlist &&
OPTIONS_DATA.settings.widgetAllowlist.includes(widget_name);
$widgetExceptions
.append(new Option(widget_name, widget_name, false, is_selected))
.trigger("change");
}

$widgetExceptions.on('select2:select', updateWidgetReplacementExceptions);
$widgetExceptions.on('select2:unselect', updateWidgetReplacementExceptions);
$widgetExceptions.on('select2:clear', updateWidgetReplacementExceptions);
$widgetExceptions.on('select2:select', updateWidgetExceptions);
$widgetExceptions.on('select2:unselect', updateWidgetExceptions);
$widgetExceptions.on('select2:clear', updateWidgetExceptions);

reloadDisabledSites();
reloadTrackingDomainsTab();
Expand Down Expand Up @@ -1035,13 +1037,15 @@ function removeDomain(event) {
}

/**
* Update which widgets should not get replaced
* Update which widgets should always get activated.
*/
function updateWidgetReplacementExceptions() {
const widgetReplacementExceptions = $('#hide-widgets-select').select2('data').map(({ id }) => id);
function updateWidgetExceptions() {
let $el = $('#always-activate-select'),
widgetAllowlist = $el.select2('data').map(({ id }) => id);

chrome.runtime.sendMessage({
type: "updateSettings",
data: { widgetReplacementExceptions }
data: { widgetAllowlist }
});
}

Expand Down
2 changes: 1 addition & 1 deletion src/js/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -782,7 +782,7 @@ BadgerStorage.prototype = {
if (self.name == "settings_map") {
for (let prop in mapData) {
// combine array settings via intersection/union
if (prop == "disabledSites" || prop == "widgetReplacementExceptions") {
if (prop == "disabledSites" || prop == "widgetAllowlist") {
self.setItem(prop, utils.concatUniq(self.getItem(prop), mapData[prop]));

// string/array map
Expand Down
50 changes: 20 additions & 30 deletions src/js/webrequest.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,17 +175,7 @@ function onBeforeRequest(details) {
}

if ((type == 'script' || sw_request) && from_current_tab) {
let surrogate;

if (utils.hasOwn(surrogates.WIDGET_SURROGATES, request_host)) {
let settings = badger.getSettings();
if (!settings.getItem('widgetReplacementExceptions').includes(surrogates.WIDGET_SURROGATES[request_host].widgetName)) {
surrogate = surrogates.getSurrogateUri(url, request_host);
}

} else {
surrogate = surrogates.getSurrogateUri(url, request_host);
}
let surrogate = surrogates.getSurrogateUri(url, request_host);

if (surrogate) {
let secret = getWarSecret(tab_id, frame_id, surrogate);
Expand Down Expand Up @@ -625,11 +615,7 @@ function hideBlockedFrame(tab_id, parent_frame_id, frame_url, frame_host) {
}

// don't hide widget frames
let exceptions = badger.getSettings().getItem('widgetReplacementExceptions');
for (let widget of badger.widgetList) {
if (exceptions.includes(widget.name)) {
continue;
}
for (let domain of widget.domains) {
if (domain == frame_host) {
return;
Expand Down Expand Up @@ -844,8 +830,7 @@ let getWidgetList = (function () {
let widgetsToReplace = {},
widgetList = [],
trackers = badger.tabData.getTrackers(tab_id),
trackerDomains = Object.keys(trackers),
exceptions = badger.getSettings().getItem('widgetReplacementExceptions');
trackerDomains = Object.keys(trackers);

// optimize translation lookups by doing them just once,
// the first time they are needed
Expand All @@ -862,12 +847,6 @@ let getWidgetList = (function () {
}

for (let widget of badger.widgetList) {
// replace only if the widget is not on the 'do not replace' list
// also don't send widget data used later for dynamic replacement
if (exceptions.includes(widget.name)) {
continue;
}

widgetList.push(widget);

// replace only if we haven't already allowed this widget for the tab/site
Expand Down Expand Up @@ -1004,13 +983,24 @@ function getWidgetDomains(widget_name) {
* with domains for widgets marked as always allowed on a given site.
*/
function initAllowedWidgets(tab_id, tab_host) {
let allowedWidgets = badger.getSettings().getItem('widgetSiteAllowlist');
if (utils.hasOwn(allowedWidgets, tab_host)) {
for (let widget_name of allowedWidgets[tab_host]) {
let widgetDomains = getWidgetDomains(widget_name);
if (widgetDomains) {
badger.tabData.allowOnTab(tab_id, widgetDomains, widget_name);
}
let allowedWidgets = {},
conf = badger.getSettings();

for (let widget_name of conf.getItem('widgetAllowlist')) {
allowedWidgets[widget_name] = true;
}

let siteExceptions = conf.getItem('widgetSiteAllowlist');
if (utils.hasOwn(siteExceptions, tab_host)) {
for (let widget_name of siteExceptions[tab_host]) {
allowedWidgets[widget_name] = true;
}
}

for (let name of Object.keys(allowedWidgets)) {
let widgetDomains = getWidgetDomains(name);
if (widgetDomains) {
badger.tabData.allowOnTab(tab_id, widgetDomains, name);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/skin/options-layout.css
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ p, #settingsForm {
padding-inline-start: 25px;
}

label[for=hide-widgets-select] {
label[for=always-activate-select] {
display: block;
}

Expand Down
6 changes: 3 additions & 3 deletions src/skin/options.html
Original file line number Diff line number Diff line change
Expand Up @@ -258,10 +258,10 @@ <h4 class="i18n_options_advanced_settings"></h4>
<h4 class="i18n_options_widget_exceptions_header"></h4>

<div style="max-width: 420px">
<label for="hide-widgets-select">
<span class="i18n_options_hide_social_widgets"></span>
<label for="always-activate-select">
<span class="i18n_options_widget_exceptions_label"></span>
</label>
<select name="states[]" multiple="multiple" id="hide-widgets-select"></select>
<select name="states[]" multiple="multiple" id="always-activate-select"></select>
</div>

<h4 class="i18n_options_widget_site_exceptions_header"></h4>
Expand Down
38 changes: 18 additions & 20 deletions tests/selenium/widgets_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,48 +276,46 @@ def test_activation_site(self):
self.load_url(self.BASIC_FIXTURE_URL)
self.assert_replacement()

def test_disabling_site(self):
def test_activation_global(self):
self.block_domain(self.THIRD_PARTY_DOMAIN)

self.disable_badger_on_site(self.BASIC_FIXTURE_URL)
# add the widget to the list of exceptions
self.load_url(self.options_url)
self.wait_for_script("return window.OPTIONS_INITIALIZED")
self.find_el_by_css('a[href="#tab-manage-widgets"]').click()
self.find_el_by_css('input[type="search"]').send_keys(
self.TYPE3_WIDGET_NAME, Keys.ENTER)

# verify basic widget is neither replaced nor blocked
self.load_url(self.BASIC_FIXTURE_URL)
self.assert_no_replacement()
self.assert_widget()
# type 4 replacement should also be missing
self.assert_no_replacement(self.TYPE4_WIDGET_NAME)
# while the type 4 widget script should have executed
self.assert_widget("type4")

# verify dynamic widget is neither replaced nor blocked
# verify dynamic widget is no longer replaced
self.load_url(self.DYNAMIC_FIXTURE_URL)
self.find_el_by_css('#widget-trigger').click()
self.assert_no_replacement()
self.assert_widget()

def test_disabling_replacement_for_one_widget(self):
def test_disabling_site(self):
self.block_domain(self.THIRD_PARTY_DOMAIN)

# add the widget to the list of exceptions
self.load_url(self.options_url)
self.wait_for_script("return window.OPTIONS_INITIALIZED")
self.find_el_by_css('a[href="#tab-manage-widgets"]').click()
self.find_el_by_css('input[type="search"]').send_keys(
self.TYPE3_WIDGET_NAME, Keys.ENTER)
self.disable_badger_on_site(self.BASIC_FIXTURE_URL)

# verify basic widget is no longer replaced
# verify basic widget is neither replaced nor blocked
self.load_url(self.BASIC_FIXTURE_URL)
self.assert_no_replacement()
self.assert_widget_blocked()
# verify the type 4 widget is still replaced
self.assert_replacement(self.TYPE4_WIDGET_NAME)
self.assert_widget()
# type 4 replacement should also be missing
self.assert_no_replacement(self.TYPE4_WIDGET_NAME)
# while the type 4 widget script should have executed
self.assert_widget("type4")

# verify dynamic widget is no longer replaced
# verify dynamic widget is neither replaced nor blocked
self.load_url(self.DYNAMIC_FIXTURE_URL)
self.find_el_by_css('#widget-trigger').click()
self.assert_no_replacement()
self.assert_widget_blocked()
self.assert_widget()

def test_no_replacement_when_cookieblocked(self):
self.cookieblock_domain(self.THIRD_PARTY_DOMAIN)
Expand Down

0 comments on commit 7d558e1

Please sign in to comment.