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

Update widget exceptions to be an "always activate" list #3047

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
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