diff --git a/src/background/cookiesIAB.js b/src/background/cookiesIAB.js index 3446618..43b893b 100644 --- a/src/background/cookiesIAB.js +++ b/src/background/cookiesIAB.js @@ -24,7 +24,7 @@ let defaultValue = "1NYN"; * via a `us_privacy` first-party cookie * Pulls data about the current tab and intializes the cookie-set process */ -export function initIAB() { +export function initIAB(optStatus) { chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) { if (tabs[0] != undefined && tabs[0].url != undefined) { var tab = tabs[0]; @@ -33,7 +33,7 @@ export function initIAB() { // Filter out chrome://* links as they are local if (url.substr(0, 9).toLowerCase() !== "chrome://") { - checkExistsAndHandleIAB(url); + checkExistsAndHandleIAB(url,optStatus); } } }); @@ -44,7 +44,7 @@ export function initIAB() { * cookie, and handles them according to how many exist * @param {string} url - url of the current tab */ -function checkExistsAndHandleIAB(url) { +function checkExistsAndHandleIAB(url, optStatus) { let cookieMatches = []; chrome.cookies.getAll({ url: url }, function (cookieArr) { @@ -56,11 +56,15 @@ function checkExistsAndHandleIAB(url) { // Now we have an array of all the cookie matches if (cookieMatches.length === 1) { - let value = parseIAB(cookieMatches[0]["value"]); + let value = parseIAB(cookieMatches[0]["value"], optStatus); updateIAB(cookieMatches[0], value, url); } if (cookieMatches.length === 0) { - updateIAB(null, "1NYN", url); + if (optStatus){ + updateIAB(null, "1NYN", url); + } else { + updateIAB(null, "1NNN", url); + } } // If there are multiple cookies, handle here. // Currently deletes default cookie @@ -102,15 +106,27 @@ function updateIAB(cookie, value, url) { * @param {string} signal - the value of an IAB cookie. Example: `1YNN`. * @return {string} - Updated IAB value to be set */ -export function parseIAB(signal) { - if (!isValidSignalIAB(signal)) { - return "1NYN"; - } - if (signal === "1---") { - return "1YYY"; +export function parseIAB(signal, optStatus) { + if (optStatus){ + if (!isValidSignalIAB(signal)) { + return "1NYN"; + } + if (signal === "1---") { + return "1YYY"; + } else { + signal = signal.substr(0, 2) + "Y" + signal.substr(3, 1); + return signal; + } } else { - signal = signal.substr(0, 2) + "Y" + signal.substr(3, 1); - return signal; + if (!isValidSignalIAB(signal)) { + return "1NNN"; + } + if (signal === "1---") { + return "1YNY"; + } else { + signal = signal.substr(0, 2) + "N" + signal.substr(3, 1); + return signal; + } } } diff --git a/src/background/protection/cookiesOnInstall.js b/src/background/protection/cookiesOnInstall.js index ce70b90..04dcf4e 100644 --- a/src/background/protection/cookiesOnInstall.js +++ b/src/background/protection/cookiesOnInstall.js @@ -20,6 +20,11 @@ function initCookiesPerDomain(domainFilter) { setFilteredCookies(cookie_list, domainFilter); } +function deleteCookiesPerDomain(domainFilter) { + deleteFilteredCookies(cookie_list, domainFilter); + console.log("Deletecookiesperdomain called. DF: ", domainFilter); +} + /** * Sets a cookie at the given domain for each cookie in the passed in * cookies object. Currently updates cookie url info based on domain. @@ -126,9 +131,44 @@ function setFilteredCookies(cookies, domainFilter) { } } +/** + * Sets a cookie at the given domain for each item in the passed in + * cookies object. Currently updates cookie url info based on domain. + * @param {Object} cookies - Collection of info regarding each 3rd + * party cookie to be set + * Each item in `cookies` must contain a 'name', 'value', and 'domain' + */ + function deleteFilteredCookies(cookies, domainFilter) { + + for (let item in cookies) { + for (let domain in domainFilter) { + // Notice that this `if` will trigger only for sites mentioned in our + // cookies, i.e. primarily only adtech websites since all our cookies + // are adtech opt outs + if (domainFilter[domain] == cookies[item].domain) { + // Deletes cookie url based on domain, checks for domain/subdomain spec + let cookieUrl = cookies[item].domain; + let name = cookies[item].name; + + if (cookieUrl.substr(0, 1) === ".") { + cookieUrl = cookieUrl.substr(1); + } + + cookieUrl = `https://${cookieUrl}/`; + + chrome.cookies.remove({ + url: cookieUrl, + name: name, + }); + } + } + } +} + export { initCookiesOnInstall, initCookiesPerDomain, + deleteCookiesPerDomain, setAllCookies, setFilteredCookies, }; diff --git a/src/background/protection/protection-ff.js b/src/background/protection/protection-ff.js index c8bb79b..84e5a82 100644 --- a/src/background/protection/protection-ff.js +++ b/src/background/protection/protection-ff.js @@ -15,7 +15,7 @@ import { defaultSettings } from "../../data/defaultSettings.js"; import { headers } from "../../data/headers.js"; import { enableListeners, disableListeners } from "./listeners-$BROWSER.js"; import { initIAB } from "../cookiesIAB.js"; -import { initCookiesPerDomain } from "./cookiesOnInstall.js"; +import { initCookiesPerDomain, deleteCookiesPerDomain } from "./cookiesOnInstall.js"; import { initCookiesOnInstall } from "./cookiesOnInstall.js"; import psl from "psl"; @@ -99,8 +99,8 @@ const listenerCallbacks = { * @param {object} details - retrieved info passed into callback */ onCommitted: async (details) => { + initIAB(sendSignal); if (sendSignal) { - initIAB(); addDomSignal(details); updatePopupIcon(details); } @@ -463,11 +463,14 @@ async function onMessageHandlerAsync(message, sender, sendResponse) { tabs[tabID]["TIMESTAMP"] = message.data; } } - if (message.msg === "SET_OPTOUT_COOKEIS") { + if (message.msg === "SET_OPTOUT_COOKIES") { // This is specifically for when cookies are removed when a user turns off // do not sell for a particular site, and chooses to re-enable it initCookiesPerDomain(message.data); } + if (message.msg === "DELETE_OPTOUT_COOKIES") { + deleteCookiesPerDomain(message.data); + } if (message.msg === "FORCE_RELOAD") { pullToDomainlistCache(); } diff --git a/src/background/protection/protection.js b/src/background/protection/protection.js index 957de5d..c7117bc 100644 --- a/src/background/protection/protection.js +++ b/src/background/protection/protection.js @@ -14,7 +14,7 @@ import { stores, storage } from "./../storage.js"; import { defaultSettings } from "../../data/defaultSettings.js"; import { enableListeners, disableListeners } from "./listeners-$BROWSER.js"; import { initIAB } from "../cookiesIAB.js"; -import { initCookiesPerDomain } from "./cookiesOnInstall.js"; +import { initCookiesPerDomain, deleteCookiesPerDomain } from "./cookiesOnInstall.js"; import { initCookiesOnInstall } from "./cookiesOnInstall.js"; import psl, { parse } from "psl"; @@ -405,11 +405,10 @@ async function onMessageHandlerAsync(message, sender, sendResponse) { wellknown[tabID] = message.data; let wellknownData = message.data; + initIAB(!sendSignal); if (wellknown[tabID] === null && sendSignal == null) { - initIAB(); updatePopupIcon(tabID); } else if (wellknown[tabID]["gpc"] === true && sendSignal == null) { - initIAB(); chrome.action.setIcon({ tabId: tabID, path: "assets/face-icons/optmeow-face-circle-green-128.png", @@ -446,7 +445,7 @@ async function onMessageHandlerAsync(message, sender, sendResponse) { tabs[tabID]["TIMESTAMP"] = message.data; } } - if (message.msg === "SET_OPTOUT_COOKEIS") { + if (message.msg === "SET_OPTOUT_COOKIES") { // This is initialized when cookies are to be reset to a page after // do not sell is turned back on (e.g., when its turned on from the popup). @@ -454,6 +453,11 @@ async function onMessageHandlerAsync(message, sender, sendResponse) { // do not sell for a particular site, and chooses to re-enable it initCookiesPerDomain(message.data); } + if (message.msg === "DELETE_OPTOUT_COOKIES") { + console.log("Msg received. Info; ", message.data); + deleteCookiesPerDomain(message.data); + } + return true; // Async callbacks require this } diff --git a/src/background/storageCookies.js b/src/background/storageCookies.js index ee0859f..9f23c3a 100644 --- a/src/background/storageCookies.js +++ b/src/background/storageCookies.js @@ -27,26 +27,31 @@ export const storageCookies = { // Since this can run anywhere (popup, settings, background), // we must tell the background to set our correct optout cookies chrome.runtime.sendMessage({ - msg: "SET_OPTOUT_COOKEIS", + msg: "SET_OPTOUT_COOKIES", data: domainFilter, }); }, async deleteCookiesForGivenDomain(domainKey) { - let cookieArr = []; - chrome.cookies.getAll({ domain: `${domainKey}` }, function (cookies) { - cookieArr = cookies; + let domainFilter; + if (domainKey.substr(0, 1) === ".") { + domainFilter = [ + domainKey.substr(1), + domainKey, + `www${domainKey.substr(1)}`, + ]; + } else if (domainKey.substr(0, 1) === "w") { + domainFilter = [domainKey.substr(3), domainKey.substr(4), domainKey]; + } else { + domainFilter = [domainKey, `.${domainKey}`, `www.${domainKey}`]; + } - for (let i in cookieArr) { - chrome.cookies.remove({ - url: `https://${domainKey}/`, - name: cookieArr[i].name, - }); - chrome.cookies.remove({ - url: `https://www.${domainKey}/`, - name: cookieArr[i].name, - }); - } + // Since this can run anywhere (popup, settings, background), + // we must tell the background to set our correct optout cookies + chrome.runtime.sendMessage({ + msg: "DELETE_OPTOUT_COOKIES", + data: domainFilter, }); - }, + console.log("Delete message sent"); + } }; diff --git a/test/background/parseIAB.test.js b/test/background/parseIAB.test.js index ba39e7c..f2a9b77 100644 --- a/test/background/parseIAB.test.js +++ b/test/background/parseIAB.test.js @@ -15,17 +15,23 @@ import { parseIAB } from "../../src/background/cookiesIAB.js"; describe("Check parsing of IAB signal", () => { it('Should parse invalid signal to 1NYN', () => { - assert.equal(parseIAB("1WYY"), '1NYN'); + assert.equal(parseIAB("1WYY", true), '1NYN'); }); it('Should parse valid signal 1--- to 1YYY', () => { - assert.equal(parseIAB("1---"), '1YYY'); + assert.equal(parseIAB("1---",true ), '1YYY'); }); it('Should change third char in valid signal to Y', () => { - assert.equal(parseIAB("1NNN"), '1NYN'); - assert.equal(parseIAB("1YNY"), '1YYY'); - assert.equal(parseIAB("1NNY"), '1NYY'); + assert.equal(parseIAB("1NNN", true), '1NYN'); + assert.equal(parseIAB("1YNY", true), '1YYY'); + assert.equal(parseIAB("1NNY", true), '1NYY'); + }); + + it('Should change third char in valid signal to N', () => { + assert.equal(parseIAB("1NYN", false), '1NNN'); + assert.equal(parseIAB("1YYN", false), '1YNN'); + assert.equal(parseIAB("1YYY", false), '1YNY'); }); })