diff --git a/.eslintrc.json b/.eslintrc.json index 0349490..b746700 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -7,6 +7,7 @@ "ecmaVersion": 2018 }, "globals": { + "browser": true, "it": true, "describe": true, "after": true, diff --git a/package.json b/package.json index 3e6b105..b975b93 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "puppeteer": "^1.20.0", "stylelint": "^9.9.0", "stylelint-config-recommended": "^2.1.0", - "webextension-polyfill": "^0.5.0", + "webextension-polyfill": "github:Manvel/webextension-polyfill#privacy-manager", "webpack": "^4.41.0" }, "dependencies": { diff --git a/src/js/ui/components/settingList.js b/src/js/ui/components/settingList.js index 5fc7dd1..a2cb36a 100644 --- a/src/js/ui/components/settingList.js +++ b/src/js/ui/components/settingList.js @@ -15,7 +15,7 @@ const {additionalPermission, getStorage, setStorage} = require("../../common"); * The callback parameter should be a function that looks like this: * function(state) {...}; where "state" is boolean */ -function addSettingItem(parent, dataObj, type, callback) +async function addSettingItem(parent, dataObj, type, callback) { const content = Elem("#settings-list").content; const listElem = document.importNode(content, true); @@ -34,91 +34,72 @@ function addSettingItem(parent, dataObj, type, callback) switch (type) { case "privacy": - var privacyObject = dataObj.privacyObj; - - privacyObject.get({}, function(details) - { - _updateSettingButton(pmToggle, details.value); - }); - pmToggle.addEventListener("change", function() + { + const privacyObject = dataObj.privacyObj; + _updateSettingButton(pmToggle, (await privacyObject.get({})).value); + pmToggle.addEventListener("change", async() => { - privacyObject.get({}, function(details) + const details = await privacyObject.get({}); + if (details.levelOfControl == "controllable_by_this_extension" || + details.levelOfControl == "controlled_by_this_extension") { - if (details.levelOfControl == "controllable_by_this_extension" || - details.levelOfControl == "controlled_by_this_extension") + await privacyObject.set({ value: !details.value }); + // TODO: test + if (browser.runtime.lastError != undefined) { - privacyObject.set({ value: !details.value }, function() + const message = browser.runtime.lastError.message; + if (message == + "Can't modify regular settings from an incognito context.") { - if (chrome.runtime.lastError != undefined) - { - const message = chrome.runtime.lastError.message; - if (message == - "Can't modify regular settings from an incognito context.") - { - alert(getMsg("regularSettingChangeIncognito_error")); - } - else - { - alert(message); - } - } - }); - } - else - { - //TODO: Inform user if control level is not controlable by - //extension details.levelOfControl + alert(getMsg("regularSettingChangeIncognito_error")); + } + else + { + alert(message); + } } - }); + } + else + { + //TODO: Inform user if control level is not controlable by + //extension details.levelOfControl + } }, false); - privacyObject.onChange.addListener(function(detail) + privacyObject.onChange.addListener((detail) => { _updateSettingButton(accessor, detail.value); }); break; + + } case "storage": - getStorage("settingList", function(data) + { + const state = await _getStorage(accessor); + _updateSettingButton(pmToggle, state === true); + if (callback) + callback(state); + pmToggle.addEventListener("change", async() => { - var settingList = data["settingList"]; - if (!settingList) - return; - - var state = settingList[accessor] == true; - _updateSettingButton(pmToggle, state); + const currentState = await _getStorage(accessor); + const data = await _setStorage(accessor, !currentState); if (callback) - callback(state); - }); - pmToggle.addEventListener("change", function() - { - getStorage("settingList", function(data) - { - if (data.settingList) - data.settingList[accessor] = !data.settingList[accessor]; - else - { - data.settingList = {}; - data.settingList[accessor] = true; - } - setStorage(data, function(result) - { - if (callback) - callback(data.settingList[accessor]); - }); - }); + callback(data); }, false); break; + } case "permission": - chrome.permissions.contains(additionalPermission, function(result) + { + chrome.permissions.contains(additionalPermission, (result) => { if (callback) callback(result); _updateSettingButton(accessor, result); }); - pmToggle.addEventListener("click", function() + pmToggle.addEventListener("click", () => { - chrome.permissions.contains(additionalPermission, function(result) + chrome.permissions.contains(additionalPermission, (result) => { if (result) chrome.permissions.remove(additionalPermission); @@ -127,25 +108,44 @@ function addSettingItem(parent, dataObj, type, callback) }); }, false); - chrome.permissions.onAdded.addListener(function(result) + chrome.permissions.onAdded.addListener((result) => { _updateSettingButton(accessor, true); // Currently called multiple times if (callback) callback(true); }); - chrome.permissions.onRemoved.addListener(function(result) + chrome.permissions.onRemoved.addListener((result) => { _updateSettingButton(accessor, false); if (callback) callback(false); }); break; + } } } +async function _setStorage(name, value) +{ + const data = await browser.storage.local.get("settingList"); + if (!data.settingList) + data.settingList = {}; + data.settingList[name] = value; + return (await browser.storage.local.set(data)).settingList[name]; +} + +async function _getStorage(name) +{ + const data = await browser.storage.local.get("settingList"); + const settingList = data["settingList"]; + if (!settingList) + return; + return settingList[name]; +} + function checkSettingState(accessor, callback) { - getStorage("settingList", function(data) + getStorage("settingList", (data) => { if (data.settingList) callback(data.settingList[accessor]); @@ -156,9 +156,9 @@ function checkSettingState(accessor, callback) function turnSwitchesOff(accessors, callback) { - getStorage("settingList", function(data) + getStorage("settingList", (data) => { - accessors.forEach(function(accessor) + accessors.forEach((accessor) => { if (data.settingList[accessor]) data.settingList[accessor] = false; @@ -171,7 +171,7 @@ function _updateSettingButton(setting, state) { if (typeof setting == "string") { - Elems("[data-access='" + setting + "']").forEach(function(settingItem) + Elems("[data-access='" + setting + "']").forEach((settingItem) => { _updateSettingButton(settingItem, state); }); @@ -182,7 +182,7 @@ function _updateSettingButton(setting, state) } } -chrome.storage.onChanged.addListener(function(change) +chrome.storage.onChanged.addListener((change) => { if ("settingList" in change) { diff --git a/src/js/ui/tab_main.js b/src/js/ui/tab_main.js index 829866e..bdef594 100644 --- a/src/js/ui/tab_main.js +++ b/src/js/ui/tab_main.js @@ -32,10 +32,10 @@ const {browsingData} = require("../common"); { privacyData[category].forEach(function(settingName) { - if (!chrome.privacy[category][settingName]) + if (!browser.privacy[category][settingName]) return; var settingObj = createBasicSettingObj(settingName); - settingObj.privacyObj = chrome.privacy[category][settingName]; + settingObj.privacyObj = browser.privacy[category][settingName]; addSettingItem(Elem("#privacyManagement ul"), settingObj, "privacy"); }); } diff --git a/test/index.js b/test/index.js index 2f72910..d6b1df5 100644 --- a/test/index.js +++ b/test/index.js @@ -1,11 +1,13 @@ const puppeteer = require("puppeteer"); const assert = require("assert"); -const {privacyData} = require("../src/js/ui/data"); +const additionalPermission = {"origins": [""]}; const extensionPath = "dist"; let browser; let page; let thirdPartyToggleHandle; +let clearCookiesHandle; +let additionalPermissionHandles; before(async() => { @@ -30,6 +32,8 @@ before(async() => await page.goto(`chrome-extension://${extensionID}/${extensionPopupHtml}`); thirdPartyToggleHandle = await page.$("[data-access='thirdPartyCookiesAllowed']"); + clearCookiesHandle = await page.$("[data-access='cookies']"); + additionalPermissionHandles = await page.$$("[data-access='additionalPermissions']"); }); function getLabel(pmToggleHandle) @@ -60,24 +64,49 @@ function setWebsitePrivacy(settingName, value) { return page.evaluate((settingName, value) => { - chrome.privacy.websites[settingName].set({ value }); + browser.privacy.websites[settingName].set({ value }); }, settingName, value); } function getWebsitePrivacy(settingName) { - return page.evaluate((settingName) => + return page.evaluate(async(settingName) => { - return new Promise((resolve) => - { - chrome.privacy.websites[settingName].get({}, ({value}) => - { - resolve(value); - }); - }); + return (await browser.privacy.websites[settingName].get({})).value; }, settingName); } +function getSettingListData(name) +{ + return page.evaluate(async(name) => + { + return (await browser.storage.local.get("settingList")).settingList[name]; + }, name); +} + +function setSettingListData(name, value) +{ + return page.evaluate(async(name, value) => + { + const data = await browser.storage.local.get("settingList"); + if (!data.settingList) + data.settingList = {}; + data.settingList[name] = value; + await browser.storage.local.set(data); + }, name, value); +} + +function setPermission(state) +{ + return page.evaluate(async(state, additionalPermission) => + { + if (state) + return await browser.permissions.request(additionalPermission); + else + return await browser.permissions.remove(additionalPermission); + }, state, additionalPermission); +} + describe("Testing Privacy Manager extension", () => { it("The first PM item is '3-rd party cookies' and is enabled", async() => @@ -99,6 +128,21 @@ describe("Testing Privacy Manager extension", () => await clickToggle(thirdPartyToggleHandle); assert.equal(await getWebsitePrivacy("thirdPartyCookiesAllowed"), true); }); + it("Setting settingList.cookies in local storage should switch 'Cookies' toggle", async() => + { + await setSettingListData("cookies", true); + assert.equal(await isEnabled(clearCookiesHandle), true); + await setSettingListData("cookies", false); + assert.equal(await isEnabled(clearCookiesHandle), false); + }); + it("Clicking the 'Cookies' toggle should set settingList.cookies in local storage", async() => + { + await clickToggle(clearCookiesHandle); + assert.equal(await getSettingListData("cookies"), true); + await clickToggle(clearCookiesHandle); + assert.equal(await getSettingListData("cookies"), false); + }); + it("When additional permissions are changed, 'Additional Permissions' toggle is updated accordingly"); }); after(async() =>