Skip to content

Commit

Permalink
Visual indicator as extension badge while searching/handling a CMP.
Browse files Browse the repository at this point in the history
Added option "noTimeout" to ClickAction, that if used, prevents COM from using even a setTimeout(0) after the click, this is sometimes needed for performance reasons.

Added OnOffMatcher that has a css selector for both on and off state of a consent. This enables us to only click if the state is wrong, saving clicks, and potential performance improvement.

Removed some left over logging, that was not behind the debugLog flag.

Fixed a bug realted to multiple CMP searches running on top of each other.

Added negateChildFilter option, that enables a childfilter to filter out possible targets, based on not having a specific child. (:has, is not supported in all browsers yet)
  • Loading branch information
Rolf Bagge committed Feb 23, 2023
1 parent 2b91c6e commit 84db748
Show file tree
Hide file tree
Showing 11 changed files with 733 additions and 191 deletions.
14 changes: 6 additions & 8 deletions Extension/Action.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ class Action {
if (ConsentEngine.debugValues.clickDelay) {
return 150;
} else if(ConsentEngine.singleton.pipEnabled) {
// Reduce click wait based on number of clicks
if (ConsentEngine.singleton.getClicksSoFar()>100) return 0;
if (ConsentEngine.singleton.getClicksSoFar()>20) return 1;
if (ConsentEngine.singleton.getClicksSoFar()>5) return 10;
// Reduce click wait based on number of clicks
if (ConsentEngine.singleton.getClicksSoFar()>100) return 0;
if (ConsentEngine.singleton.getClicksSoFar()>20) return 1;
if (ConsentEngine.singleton.getClicksSoFar()>5) return 10;
return 100;
} else {
return 0;
Expand Down Expand Up @@ -178,7 +178,7 @@ class ClickAction extends Action {
});
}

if(isShowing) {
if(isShowing && this.config.noTimeout !== true) {
await this.waitTimeout(this.timeout);
}

Expand All @@ -199,7 +199,7 @@ class ClickAction extends Action {

ConsentEngine.singleton.registerClick();

if(isShowing) {
if(isShowing && this.config.noTimeout !== true) {
await this.waitTimeout(this.timeout);
}
}
Expand Down Expand Up @@ -495,8 +495,6 @@ class HideAction extends Action {
let widthScale = width / targetWidth;
let heightScale = height / targetHeight;

console.log(width, height, targetWidth, targetHeight, widthScale, heightScale);

scale = Math.min(widthScale, heightScale);
}

Expand Down
47 changes: 37 additions & 10 deletions Extension/Consent.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,46 @@ class Consent {
}

async setEnabled(enabled) {
if(this.enabledMatcher != null && this.toggleAction != null) {
if(this.isEnabled() && !enabled) {
await this.toggle();
} else if(!this.isEnabled() && enabled) {
await this.toggle();
if(this.toggleAction != null) {
if(this.enabledMatcher == null) {
//Toggle is only supported with a matcher
if (ConsentEngine.debugValues.debugLog) {
throw new Error("Toggle consent action, without a matcher: "+JSON.stringify(this.config));
}
return;
}
try {
if(this.isEnabled() !== enabled) {
await this.toggle();
}
} catch(e) {
if (ConsentEngine.debugValues.debugLog) {
console.error("Error toggling:", e, this.config);
}
}
} else {
if(enabled) {
if(this.trueAction != null) {
await this.trueAction.execute();
let handled = false;

//If we have OnOffMatcher, we can reduce clicks to only happen when state is wrong
if(this.enabledMatcher != null && this.enabledMatcher instanceof OnOffMatcher) {
try {
if(this.isEnabled() && !enabled) {
await this.falseAction.execute();
} else if(!this.isEnabled() && enabled) {
await this.trueAction.execute();
}
handled = true;
} catch(e) {
if (ConsentEngine.debugValues.debugLog) {
console.error("Error pushing on/off:", e, this.config);
}
}
} else {
if(this.falseAction != null) {
}

if(!handled) {
if(enabled) {
await this.trueAction.execute();
} else {
await this.falseAction.execute();
}
}
Expand Down
95 changes: 90 additions & 5 deletions Extension/Matcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ class Matcher {
case "css": return new CssMatcher(config);
case "checkbox": return new CheckboxMatcher(config);
case "url": return new URLMatcher(config);
default: throw "Unknown matcher type: "+config.type;
case "onoff": return new OnOffMatcher(config);
default: {
throw new Error("Unknown matcher type: "+config.type);
}
}
}

Expand Down Expand Up @@ -58,6 +61,85 @@ class Matcher {
}
}

class OnOffMatcher extends Matcher {
constructor(config) {
super(config);
}

matches() {
if(this.config.onMatcher == null || this.config.offMatcher == null) {
throw new Error("Missing onMatcher/offMatcher on OnOffMatcher: "+JSON.stringify(this.config));
}

let onResult = Tools.find(this.config.onMatcher);
let offResult = Tools.find(this.config.offMatcher);

if(onResult.target == null && offResult.target == null) {
throw new Error("Did not find neither on or off targets: "+JSON.stringify(this.config));
}

if(onResult.target != null && offResult.target != null) {
throw new Error("Found both on and off targets: "+JSON.stringify(this.config));
}

return onResult.target != null;
}

async debug(shouldMatch) {
let onResult = Tools.find(this.config.onMatcher);
let offResult = Tools.find(this.config.offMatcher);

let blinker = [];

if(onResult.target == null && offResult.target == null) {
//Neither On nor Off was found, this is wrong, but we have nothing to highlight.
return;
}

if(onResult.target != null && offResult.target != null) {
//Both On and Off was found, this is wrong!
blinker.push({target: onResult.target, currect: false});
blinker.push({target: offResult.target, currect: false});
} else {
//Since not both was null, and not both was not null, excactly 1 is not null

if(shouldMatch) {
if(onResult.target != null) {
blinker.push({target: onResult.target, correct: true});
} else {
blinker.push({target: offResult.target, correct: false});
}
} else {
if(onResult.target != null) {
blinker.push({target: onResult.target, correct: false});
} else {
blinker.push({target: offResult.target, correct: true});
}
}
}

for(let result of blinker) {
if(result.correct) {
result.target.style.setProperty("border", "2px solid lime", "important");
result.target.style.setProperty("background-color", "lime", "important");
} else {
result.target.style.setProperty("border", "2px solid pink", "important");
result.target.style.setProperty("background-color", "pink", "important");
}

await new Promise((resolve, reject)=>{
if (ConsentEngine.debugValues.clickDelay) {
setTimeout(()=>{
resolve();
}, 10);
} else {
resolve();
}
});
}
}
}

class CssMatcher extends Matcher {
constructor(config) {
super(config);
Expand All @@ -78,13 +160,16 @@ class CheckboxMatcher extends Matcher {
matches() {
let result = Tools.find(this.config);

if(this.config.negated) {
console.log("Negated checkbox");
if(result.target == null) {
//No checkbox found, error
throw new Error("No checkbox found, cannot check state");
}

return result.target != null && !result.target.checked;
if(this.config.negated) {
return !result.target.checked;
}

return result.target != null && result.target.checked;
return result.target.checked;
}
}

Expand Down
6 changes: 5 additions & 1 deletion Extension/Tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,11 @@ class Tools {
Tools.setBase(possibleTarget);
let childResults = Tools.find(options.childFilter);
Tools.setBase(oldBase);
return childResults.target != null;
if(options.childFilterNegated) {
return childResults.target == null;
} else {
return childResults.target != null;
}
});
}

Expand Down
28 changes: 22 additions & 6 deletions Extension/background.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
/**
*
*/
const STATUS = {
"INIT": 0,
"NOTHING": 1,
"SEARCHING": 2,
"ERROR": 3,
"HANDLED": 4
}

chrome.runtime.onMessage.addListener(function (message, sender, reply) {
switch (message.split("|")[0]) {
case "GetTabUrl": {
Expand Down Expand Up @@ -50,24 +61,27 @@ chrome.runtime.onMessage.addListener(function (message, sender, reply) {
}

case "CMPError": {
if(!tabHandledMap.get(sender.tab.id)) {
if(tabStatusMap.get(sender.tab.id) !== STATUS.HANDLED) {
setBadgeCheckmark("\u2717", sender.tab.id);
tabStatusMap.set(sender.tab.id, STATUS.ERROR);
}

return false;
}

case "NothingFound": {
if(!tabHandledMap.get(sender.tab.id)) {
if(tabStatusMap.get(sender.tab.id) !== STATUS.HANDLED) {
setBadgeCheckmark("", sender.tab.id);
tabStatusMap.set(sender.tab.id, STATUS.NOTHING);
}

return false;
}

case "Searching": {
if(!tabHandledMap.get(sender.tab.id)) {
setBadgeCheckmark("\u2026", sender.tab.id);
if(tabStatusMap.get(sender.tab.id) !== STATUS.HANDLED) {
setBadgeCheckmark("\uD83D\uDD0E", sender.tab.id);
tabStatusMap.set(sender.tab.id, STATUS.SEARCHING);
}

return false;
Expand All @@ -78,6 +92,8 @@ chrome.runtime.onMessage.addListener(function (message, sender, reply) {

setBadgeCheckmark("\u2714", sender.tab.id);

tabStatusMap.set(sender.tab.id, STATUS.HANDLED);

GDPRConfig.getStatistics().then((entries)=>{
entries.clicks += json.clicks;

Expand Down Expand Up @@ -168,12 +184,12 @@ function fetchRules(forceUpdate) {

}

let tabHandledMap = new Map();
let tabStatusMap = new Map();

chrome.tabs.onUpdated.addListener((tabId, info, tab)=>{
if(info.status != null && info.status === "Loading") {
setBadgeCheckmark("", tabId);
tabHandledMap.set(tabId, false);
tabStatusMap.set(tabId, STATUS.INIT);
}
});

Expand Down
1 change: 1 addition & 0 deletions Extension/editor/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
<div data-type="matcher" data-variant="css">[[CSS_MATCHER]]<div class="help">[[CSS_MATCHER_DESCRIPTION]]</div></div>
<div data-type="matcher" data-variant="checkbox">[[CHECKBOX_MATCHER]]<div class="help">[[CHECKBOX_MATCHER_DESCRIPTION]]</div></div>
<div data-type="matcher" data-variant="url">[[URL_MATCHER]]<div class="help">[[URL_MATCHER_DESCRIPTION]]</div></div>
<div data-type="matcher" data-variant="onoff">[[ONOFF_MATCHER]]<div class="help">[[ONOFF_MATCHER_DESCRIPTION]]</div></div>
</div>
<div class="actions">
<div data-type="action" data-variant="click">[[CLICK_ACTION]]<div class="help">[[CLICK_ACTION_DESCRIPTION]]</div></div>
Expand Down
13 changes: 13 additions & 0 deletions Extension/editor/templates.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@
</div>
</template>

<template id="matcher_onoff">
<div data-type="matcher" data-variant="onoff" data-fold-name="[[ONOFF_MATCHER]]">
<div class="label">[[ONOFF_MATCHER_TRUE]]<div class="help">[[ONOFF_MATCHER_TRUE_HELP]]</div></div>
<div data-bind="onMatcher" data-plug="domSelector"></div>
<div class="label">[[ONOFF_MATCHER_FALSE]]<div class="help">[[ONOFF_MATCHER_FALSE_HELP]]</div></div>
<div data-bind="offMatcher" data-plug="domSelector"></div>
</div>
</template>

<template id="matcher_url">
<div data-type="matcher" data-variant="url" data-fold-name="[[URL_MATCHER]]">
<div class="label">[[URL_LABEL]]<div class="help">[[URL_LABEL_HELP]]</div></div>
Expand Down Expand Up @@ -63,6 +72,8 @@
<div data-bind="displayFilter"><input type="checkbox" /></div>
<div class="label">[[CHILD_FILTER]]<div class="help">[[CHILD_FILTER_HELP]]</div></div>
<div data-bind="childFilter" data-plug="domSelector"></div>
<div class="label">[[CHILD_FILTER_NEAGTE]]<div class="help">[[CHILD_FILTER_NEGATE_HELP]]</div></div>
<div data-bind="childFilterNegate"><input type="checkbox" /></div>
</div>
</template>

Expand Down Expand Up @@ -149,6 +160,8 @@
<div data-plug="domSelector"></div>
<div class="label">[[OPEN_IN_TAB]]<div class="help">[[OPEN_IN_TAB_HELP]]</div></div>
<div data-bind="openInTab"><input type="checkbox" /></div>
<div class="label">Disable click timeout<div class="help">If enabled, dont do any timeout for this click, warning, this means no UI is updated!</div></div>
<div data-bind="noTimeout"><input type="checkbox" /></div>
</div>
</template>

Expand Down
Loading

0 comments on commit 84db748

Please sign in to comment.