diff --git a/lib/intercept.js b/lib/intercept.js index 85677df..2eb3446 100644 --- a/lib/intercept.js +++ b/lib/intercept.js @@ -81,7 +81,7 @@ case "fake": setRandomSupplyByType(prefs("rng")); var fake = changedFunction.fakeGenerator(prefs, function(messageId){ - notify({url, errorStack: error.stack, messageId, timestamp: new Date()}); + notify({url, errorStack: error.stack, messageId, timestamp: new Date(), functionName: name}); }, window, original); switch (fake){ case true: diff --git a/lib/main.js b/lib/main.js index 0b8551b..39a0fba 100644 --- a/lib/main.js +++ b/lib/main.js @@ -13,10 +13,33 @@ console.log("got port", port); port.postMessage({tabId: port.sender.tab.id}); port.onMessage.addListener(function(data){ - browser.pageAction.show(port.sender.tab.id); + browser.storage.local.get("showNotifications").then(function(data){ + // TODO: handle ignore list + if (!data.hasOwnProperty("showNotifications") || data.showNotifications){ + browser.pageAction.show(port.sender.tab.id); + } + }) console.log("got data", data, "from port", port); }); }); + + // hide all page actions when showNotifications is set to false + browser.storage.onChanged.addListener(function(change, area){ + if (area === "local" && change.hasOwnProperty("showNotifications") && !change.showNotifications.newValue){ + browser.tabs.query({}).then(function(tabs){ + tabs.forEach(function(tab){ + browser.pageAction.hide(tab.id); + }); + }); + } + }); + + // hide page action when a tab is refreshed + browser.tabs.onUpdated.addListener(function(tabId, data){ + if (data.status === "loading"){ + browser.pageAction.hide(tabId); + } + }); console.log("end main script"); return null; diff --git a/lib/require.js b/lib/require.js index 642832a..cf33e87 100644 --- a/lib/require.js +++ b/lib/require.js @@ -15,7 +15,7 @@ function require(module){ on: function(key, callback){ browser.storage.onChanged.addListener(function(changes, area){ if (area === "local"){ - if (changes[key]){ + if (changes.hasOwnProperty(key)){ callback(); } } diff --git a/pageAction/pageAction.css b/pageAction/pageAction.css index eb9bcb4..cf62b45 100644 --- a/pageAction/pageAction.css +++ b/pageAction/pageAction.css @@ -1,10 +1,13 @@ -.template { - display: none; +.actions { + display: block; +} + +body { + margin: 5px; } #prints { - min-width: 400px; -} -.print { - white-space: pre; + list-style: none; + padding: 0; + margin: 0; } \ No newline at end of file diff --git a/pageAction/pageAction.html b/pageAction/pageAction.html index 0dc3c84..af79f81 100644 --- a/pageAction/pageAction.html +++ b/pageAction/pageAction.html @@ -3,10 +3,16 @@ CanvasBlocker page action + + + + + diff --git a/pageAction/pageAction.js b/pageAction/pageAction.js index 9bfa3ba..90d465b 100644 --- a/pageAction/pageAction.js +++ b/pageAction/pageAction.js @@ -1,16 +1,128 @@ // console.log(window, browser, browser.runtime); -browser.tabs.query({active: true, currentWindow: true}).then(function(tabs){ +function modalPrompt(message, defaultValue){ + return new Promise(function(resolve, reject){ + document.body.innerHTML = ""; + document.body.appendChild(document.createTextNode(message)); + var input = document.createElement("input"); + input.value = defaultValue; + document.body.appendChild(input); + var button = document.createElement("button"); + button.textContent = "OK"; + button.addEventListener("click", function(){ + resolve(input.value); + }); + document.body.appendChild(button); + }); +} + +Promise.all([ + browser.tabs.query({active: true, currentWindow: true}), + browser.storage.local.get().then(function(data){ + Object.keys(data).forEach(function(key){ + settings[key] = data[key]; + }); + return settings; + }) +]).then(function([tabs, settings]){ if (!tabs.length){ throw new Error("noTabsFound"); } + else if (tabs.length > 1){ + console.error(tabs); + throw new Error("tooManyTabsFound"); + } + + const lists = require("./lists"); + const {parseErrorStack} = require("./callingStack"); + var actionsCallbacks = { + displayFullURL: function({url}){ + alert(url.href); + }, + displayCallingStack: function({errorStack}){ + alert(parseErrorStack(errorStack)); + }, + ignorelistDomain: function({url}){ + var domain = url.host; + modalPrompt( + browser.i18n.getMessage("inputIgnoreDomain"), + url.host + ).then(function(domain){ + if (domain){ + lists.appendTo("ignore", domain); + } + window.close(); + }); + }, + whitelistURL: function({url}){ + modalPrompt( + browser.i18n.getMessage("inputWhitelistDomain"), + "^" + url.href.replace(/([\\\+\*\?\[\^\]\$\(\)\{\}\=\!\|\.])/g, "\\$1") + "$" + ).then(function(url){ + if (url){ + lists.appendTo("white", url); + } + window.close(); + }); + }, + whitelistDomain: function({url}){ + modalPrompt( + browser.i18n.getMessage("inputWhitelistURL"), + url.host + ).then(function(domain){ + if (domain){ + lists.appendTo("white", domain); + } + window.close(); + }); + }, + disableNotifications: function(notification){ + browser.storage.local.set({showNotifications: false}); + window.close(); + }, + + }; + var tab = tabs[0]; browser.runtime.onMessage.addListener(function(data){ if (Array.isArray(data["canvasBlocker-notifications"])){ var ul = document.getElementById("prints"); + ul.innerHTML = ""; data["canvasBlocker-notifications"].forEach(function(notification){ + console.log(notification); + + var url = new URL(notification.url); var li = document.createElement("li"); li.className = "print"; - li.textContent = notification.url + ": " + notification.messageId + " (" + notification.timestamp + ")" + "\n" + notification.errorStack; + + + li.appendChild(document.createTextNode(" ")); + + var messageSpan = document.createElement("span"); + var messageParts = browser.i18n.getMessage(notification.messageId).split(/\{url\}/g); + messageSpan.appendChild(document.createTextNode(messageParts.shift())); + while (messageParts.length){ + var urlSpan = document.createElement("span"); + urlSpan.textContent = url.hostname; + urlSpan.title = url.href; + messageSpan.appendChild(urlSpan); + messageSpan.appendChild(document.createTextNode(messageParts.shift())); + } + messageSpan.title = notification.timestamp + ": " + notification.functionName; + li.appendChild(messageSpan); + + li.appendChild(document.createTextNode(" ")); + + var actions = document.createElement("span"); + actions.className = "actions"; + var data = {url, errorStack: notification.errorStack, notification}; + Object.keys(actionsCallbacks).forEach(function(key){ + var button = document.createElement("button"); + button.textContent = browser.i18n.getMessage(key); + button.addEventListener("click", function(){actionsCallbacks[key](data);}); + actions.appendChild(button); + }); + li.appendChild(actions); + ul.appendChild(li); }); } diff --git a/releaseNotes.txt b/releaseNotes.txt index a901dcc..2ea1a76 100644 --- a/releaseNotes.txt +++ b/releaseNotes.txt @@ -1,13 +1,12 @@ Version 0.4.0: todos: - import settings in content script (have to wait for the new API to register content scripts) - - add notification actions to page action popup changes: - switched to webExtension - notifications are now done via page action new features: - - + - information of all fake events in one tab are visible fixes: - ask mode did not work for input types