diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 453b7be..8ffc1e7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,14 +1,22 @@ image: debian:latest -before_script: +before_script: - export DEBIAN_FRONTEND= noninteractive - apt-get update -y - apt-get install -y zip unzip -stages: +stages: - build -build firefox: +hash rules: + stage: build + script: + - sha256sum data/data.min.json | awk '{print $1}' > rules.min.hash + artifacts: + paths: + - rules.min.hash + +build firefox: stage: build script: - zip ClearUrls_firefox -r -FS clearurls.js browser-polyfill.js manifest.json img/* external_js/* html/* core_js/* css/* fonts/* _locales/* @@ -20,7 +28,7 @@ build firefox: paths: - ClearUrls_firefox.zip -build chrome: +build chrome: stage: build script: - zip ClearUrls_chrome -r -FS ChromeVersion/clearurls.js browser-polyfill.js ChromeVersion/manifest.json img/* external_js/* html/* core_js/* css/* fonts/* _locales/* ChromeVersion/css/core.css @@ -30,4 +38,4 @@ build chrome: artifacts: paths: - - ClearUrls_chrome.zip \ No newline at end of file + - ClearUrls_chrome.zip diff --git a/ChromeVersion/clearurls.js b/ChromeVersion/clearurls.js index 9b3855e..96f42d9 100644 --- a/ChromeVersion/clearurls.js +++ b/ChromeVersion/clearurls.js @@ -782,7 +782,7 @@ function setData(key, value) break; case "hashURL": case "ruleURL": - storage[key] = replaceOldGithubURLs(value); + storage[key] = replaceOldURLs(value); break; case "types": storage[key] = value.split(','); @@ -860,7 +860,7 @@ function reload() * Replace the old GitHub URLs with the * new GitLab URLs. */ -function replaceOldGithubURLs(url) +function replaceOldURLs(url) { switch (url) { case "https://raw.githubusercontent.com/KevinRoebert/ClearUrls/master/data/rules.hash?flush_cache=true": diff --git a/clearurls.js b/clearurls.js index cbb9150..623df8a 100644 --- a/clearurls.js +++ b/clearurls.js @@ -1,7 +1,6 @@ +/*jshint esversion: 6 */ /* -* ################################################################## -* # Fetch Rules & Exception from URL # -* ################################################################## +* This script is responsible for the core functionalities. */ var providers = []; var prvKeys = []; @@ -13,13 +12,8 @@ var localDataHash; var os; var currentURL; -var storage = []; - -getDataFromDisk(); - -function start(items) +function start() { - initStorage(items); changeIcon(); /** @@ -88,39 +82,6 @@ function start(items) createProviders(); } - /** - * Load local saved data, if the browser is offline or - * some other network trouble. - */ - function loadOldDataFromStore() - { - localDataHash = storage.dataHash; - } - - /** - * Save the hash status to the local storage. - * The status can have the following values: - * 1 "up to date" - * 2 "updated" - * 3 "update available" - * @param status_code the number for the status - */ - function storeHashStatus(status_code) - { - switch(status_code) - { - case 1: status_code = "hash_status_code_1"; - break; - case 2: status_code = "hash_status_code_2"; - break; - case 3: status_code = "hash_status_code_3"; - break; - default: status_code = "hash_status_code_4"; - } - - storage.hashStatus = status_code; - } - /** * Get the hash for the rule file on github. * Check the hash with the hash form the local file. @@ -133,7 +94,7 @@ function start(items) fetch(storage.hashURL) .then(function(response){ var responseTextHash = response.clone().text().then(function(responseTextHash){ - if(response.ok) + if(response.ok && $.trim(responseTextHash)) { dataHash = responseTextHash; @@ -153,8 +114,10 @@ function start(items) }); } - /** - * Fetch the Rules & Exception from github. + /* + * ################################################################## + * # Fetch Rules & Exception from URL # + * ################################################################## */ function fetchFromURL() { @@ -164,7 +127,7 @@ function start(items) function checkResponse(response) { var responseText = response.clone().text().then(function(responseText){ - if(response.ok) + if(response.ok && $.trim(responseText)) { var downloadedFileHash = $.sha256(responseText); @@ -195,18 +158,23 @@ function start(items) * Declare constructor * * @param {String} _name Provider name - * @param {boolean} completeProvider Set URL Pattern as rule + * @param {boolean} _completeProvider Set URL Pattern as rule + * @param {boolean} _isActive Is the provider active? */ - function Provider(_name,_completeProvider = false){ + function Provider(_name, _completeProvider = false, _isActive = true){ var name = _name; var urlPattern; - var rules = []; - var exceptions = []; + var enabled_rules = {}; + var disabled_rules = {}; + var enabled_exceptions = {}; + var disabled_exceptions = {}; var canceling = _completeProvider; - var redirections = []; + var enabled_redirections = {}; + var disabled_redirections = {}; + var active = _isActive; if(_completeProvider){ - rules.push(".*"); + enabled_rules[".*"] = true; } /** @@ -240,34 +208,73 @@ function start(items) * @return {boolean} ProviderURL as RegExp */ this.matchURL = function(url) { - return !(this.matchException(url)) && urlPattern.test(url); + return urlPattern.test(url) && !(this.matchException(url)); }; /** - * Add a rule to the rule array. + * Add a rule to the rule array + * and replace old rule with new rule. * - * @param String rule RegExp as string + * @param {String} rule RegExp as string + * @param {boolean} isActive Is this rule active? */ - this.addRule = function(rule) { - rules.push(rule); + this.addRule = function(rule, isActive = true) { + // Add start and end delimiters to rule + rule = "^"+rule+"=[^\\/|\\?|&]*(\\/|&(amp;)?)?$"; + + if(isActive) + { + enabled_rules[rule] = true; + + if(disabled_rules[rule] !== undefined) + { + delete disabled_rules[rule]; + } + } + else { + disabled_rules[rule] = true; + + if(enabled_rules[rule] !== undefined) + { + delete enabled_rules[rule]; + } + } }; /** - * Return all rules as an array. + * Return all active rules as an array. * * @return Array RegExp strings */ this.getRules = function() { - return rules; + return Object.keys(enabled_rules); }; /** - * Add a exception to the exceptions array. + * Add a exception to the exceptions array + * and replace old with new exception. * - * @param String exception RegExp as string + * @param {String} exception RegExp as string + * @param {Boolean} isActive Is this exception acitve? */ - this.addException = function(exception) { - exceptions.push(exception); + this.addException = function(exception, isActive = true) { + if(isActive) + { + enabled_exceptions[exception] = true; + + if(disabled_exceptions[exception] !== undefined) + { + delete disabled_exceptions[exception]; + } + } + else { + disabled_exceptions[exception] = true; + + if(enabled_exceptions[exception] !== undefined) + { + delete enabled_exceptions[exception]; + } + } }; /** @@ -283,10 +290,10 @@ function start(items) //Add the site blocked alert to every exception if(url == siteBlockedAlert) return true; - for (var i = 0; i < exceptions.length; i++) { - if(result) { break; } + for(var exception in enabled_exceptions) { + if(result) break; - exception_regex = new RegExp(exceptions[i], "i"); + exception_regex = new RegExp(exception, "i"); result = exception_regex.test(url); } @@ -294,12 +301,30 @@ function start(items) }; /** - * Add a redirection to the redirections array. + * Add a redirection to the redirections array + * and replace old with new redirection. * - * @param String redirection RegExp as string + * @param {String} redirection RegExp as string + * @param {Boolean} isActive Is this redirection active? */ - this.addRedirection = function(redirection) { - redirections.push(redirection); + this.addRedirection = function(redirection, isActive = true) { + if(isActive) + { + enabled_redirections[redirection] = true; + + if(disabled_redirections[redirection] !== undefined) + { + delete disabled_redirections[redirection]; + } + } + else { + disabled_redirections[redirection] = true; + + if(enabled_redirections[redirection] !== undefined) + { + delete enabled_redirections[redirection]; + } + } }; /** @@ -310,13 +335,12 @@ function start(items) this.getRedirection = function(url) { var re = null; - for(var i = 0; i < redirections.length; i++) - { - result = (url.match(new RegExp(redirections[i], "i"))); + for(var redirection in enabled_redirections) { + result = (url.match(new RegExp(redirection, "i"))); - if (result && result.length > 0) + if (result && result.length > 0 && redirection) { - re = (new RegExp(redirections[i], "i")).exec(url)[1]; + re = (new RegExp(redirection, "i")).exec(url)[1]; break; } @@ -353,7 +377,7 @@ function start(items) { url = decodeURIComponent(re); //Log the action - pushToLog(request.url, re, translate('log_redirect')); + pushToLog(request.url, url, translate('log_redirect')); return { "redirect": true, @@ -362,50 +386,55 @@ function start(items) } /** - * Only test for matches, if there are fields that can be cleaned. - */ + * Only test for matches, if there are fields that can be cleaned. + */ if(existsFields(url)) { /** - * It must be non-greedy, because by default .* will match - * all ? chars. So the replace function delete everything - * before the last ?. With adding a ? on the quantifier *, - * we fixed this problem. - */ - fields = url.replace(new RegExp(".*?\\?", "i"), ""); + * It must be non-greedy, because by default .* will match + * all ? chars. So the replace function delete everything + * before the last ?. With adding a ? on the quantifier *, + * we fixed this problem. + */ + fields = extractFileds(url.replace(new RegExp(".*?\\?", "i"), "")); - for (var i = 0; i < rules.length; i++) { - var beforReplace = fields; + fields.forEach(function(field, index) { + rules.forEach(function(rule) { + var beforReplace = fields.flat().join("&"); + var match = new RegExp(rule, "i").test(field); - fields = fields.replace(new RegExp(rules[i], "i"), ""); + if(match) { + delete fields[index]; - if(beforReplace != fields) - { - //Log the action - pushToLog(domain+"?"+beforReplace, domain+"?"+fields, rules[i]); + //Log the action + pushToLog(domain+"?"+beforReplace, domain+"?"+fields.flat().join("&"), rule); - if(badges[tabid] == null) - { - badges[tabid] = 0; - } + if(badges[tabid] == null) badges[tabid] = 0; - increaseURLCounter(); + increaseURLCounter(); - if(!checkOSAndroid()) - { - if(storage.badgedStatus) { - browser.browserAction.setBadgeText({text: (++badges[tabid]).toString(), tabId: tabid}); - } - else + if(!checkOSAndroid()) { - browser.browserAction.setBadgeText({text: "", tabId: tabid}); + if(storage.badgedStatus) { + browser.browserAction.setBadgeText({text: (++badges[tabid]).toString(), tabId: tabid}); + } + else + { + browser.browserAction.setBadgeText({text: "", tabId: tabid}); + } } + changes = true; } + }); + }); - changes = true; - } + if(fields.flat().length > 0) + { + url = domain+"?"+fields.flat().join("&"); + } + else{ + url = domain; } - url = domain+"?"+fields; } else { if(domain != url) @@ -445,32 +474,6 @@ function start(items) }; } - /** - * Return the number of parameters query strings. - * @param {String} url URL as String - * @return {int} Number of Parameters - */ - function countFields(url) - { - var matches = (url.match(/[^\/|\?|&]+=[^\/|\?|&]+/gi) || []); - var count = matches.length; - - return count; - } - - /** - * Returns true if fields exists. - * @param {String} url URL as String - * @return {boolean} - */ - function existsFields(url) - { - var matches = (url.match(/\?.+/i) || []); - var count = matches.length; - - return (count > 0); - } - /** * Function which called from the webRequest to * remove the tracking fields from the url. @@ -618,7 +621,6 @@ function start(items) var ret = clearUrl(requestDetails); return ret; } - } /** @@ -646,248 +648,3 @@ function start(items) ); }); } - -/** -* Save every minute the temporary data to the disk. -*/ -setInterval(saveOnExit, 60000); - -/** -* Get the badged status from the browser storage and put the value -* into a local variable. -* -*/ -function setBadgedStatus() -{ - if(!checkOSAndroid() && storage.badgedStatus){ - browser.browserAction.setBadgeBackgroundColor({ - 'color': '#'+storage.badged_color - }); - } -} - -/** -* Change the icon. -*/ -function changeIcon() -{ - if(storage.globalStatus){ - browser.browserAction.setIcon({path: "img/clearurls.svg"}); - } else{ - browser.browserAction.setIcon({path: "img/clearurls_gray.svg"}); - } -} - -/** -* Check if it is an android device. -* @return bool -*/ -function checkOSAndroid() -{ - if(os == "android") - { - return true; - } - else{ - return false; - } -} - -/** -* Increase by {number} the GlobalURLCounter -* @param {int} number -*/ -function increaseGlobalURLCounter(number) -{ - if(storage.statisticsStatus) - { - storage.globalurlcounter += number; - } -} - -/** -* Increase by one the URLCounter -*/ -function increaseURLCounter() -{ - if(storage.statisticsStatus) - { - storage.globalCounter++; - } -} - - -/** -* Writes the storage variable to the disk. -*/ -function saveOnExit() -{ - var json = {}; - - Object.entries(storage).forEach(([key, value]) => { - switch (key) { - case "ClearURLsData": - case "log": - json[key] = JSON.stringify(value); - break; - case "types": - json[key] = value.toString(); - break; - default: - json[key] = value; - } - }); - console.log(translate('core_save_on_disk')); - browser.storage.local.set(json); -} - -/** -* Save the value under the key on the disk. -* @param {String} key -* @param {Object} value -*/ -function saveOnDisk(key, value) -{ - browser.storage.local.set({key: value}); -} - -/** -* Retrieve everything and save on the RAM. -*/ -function getDataFromDisk() -{ - browser.storage.local.get().then(start, error); -} - -/** -* Get the value under the key. -* @param {String} key -* @return {Object} -*/ -function getData(key) -{ - return storage[key]; -} - -/** -* Save the value under the key on the RAM. -* @param {String} key -* @param {Object} value -*/ -function setData(key, value) -{ - switch (key) { - case "ClearURLsData": - case "log": - storage[key] = JSON.parse(value); - break; - case "hashURL": - case "ruleURL": - storage[key] = replaceOldGithubURLs(value); - break; - case "types": - storage[key] = value.split(','); - break; - default: - storage[key] = value; - } -} - -/** -* Translate a string with the i18n API. -* -* @param {string} string Name of the attribute used for localization -*/ -function translate(string) -{ - return browser.i18n.getMessage(string); -} - - -/** -* Write error on console. -*/ -function error() -{ - console.log(translate('core_error')); -} - -/** -* Set default values, if the storage is empty. -* @param {Object} items -*/ -function initStorage(items) -{ - initSettings(); - - if(!isEmpty(items)) { - Object.entries(items).forEach(([key, value]) => { - setData(key, value); - }); - } -} - -/** -* Set default values for the settings. -*/ -function initSettings() -{ - storage.ClearURLsData = []; - storage.dataHash = ""; - storage.badgedStatus = true; - storage.globalStatus = true; - storage.globalurlcounter = 0; - storage.globalCounter = 0; - storage.hashStatus = "error"; - storage.loggingStatus = false; - storage.log = {"log": []}; - storage.statisticsStatus = true; - storage.badged_color = "ffa500"; - storage.hashURL = "https://gitlab.com/KevinRoebert/ClearUrls/raw/master/data/rules.hash"; - storage.ruleURL = "https://gitlab.com/KevinRoebert/ClearUrls/raw/master/data/data.json"; - storage.types = ["font", "image", "imageset", "main_frame", "media", "object", "object_subrequest", "other", "script", "stylesheet", "sub_frame", "websocket", "xbl", "xml_dtd", "xmlhttprequest", "xslt"]; - storage.reportServer = "https://clearurls.xn--rb-fka.it"; -} - -/** -* Reloads the extension. -*/ -function reload() -{ - browser.runtime.reload(); -} - -/** -* Replace the old GitHub URLs with the -* new GitLab URLs. -*/ -function replaceOldGithubURLs(url) -{ - switch (url) { - case "https://raw.githubusercontent.com/KevinRoebert/ClearUrls/master/data/rules.hash?flush_cache=true": - return "https://gitlab.com/KevinRoebert/ClearUrls/raw/master/data/rules.hash"; - case "https://raw.githubusercontent.com/KevinRoebert/ClearUrls/master/data/data.json?flush_cache=true": - return "https://gitlab.com/KevinRoebert/ClearUrls/raw/master/data/data.json"; - default: - return url; - } -} - -/** -* Check if an object is empty. -* @param {Object} obj -* @return {Boolean} -*/ -function isEmpty(obj) -{ - return (Object.getOwnPropertyNames(obj).length === 0); -} - -/** - * Returns the current URL. - * @return {String} [description] - */ -function getCurrentURL() -{ - return currentURL; -} diff --git a/core_js/log.js b/core_js/log.js index 46b214e..fc90b10 100644 --- a/core_js/log.js +++ b/core_js/log.js @@ -1,20 +1,20 @@ +/*jshint esversion: 6 */ /** * Get the log and display the data as table. */ var log = {}; -var core = function (func) { - return browser.runtime.getBackgroundPage().then(func); -}; - /** * Reset the global log */ function resetGlobalLog(){ - core(function (ref){ - obj = {"log": []}; - ref.setData('log', JSON.stringify(obj)); + obj = {"log": []}; + + browser.runtime.sendMessage({ + function: "setData", + params: ['log', JSON.stringify(obj)] }); + getLog(); location.reload(); } @@ -24,8 +24,11 @@ function resetGlobalLog(){ */ function getLog() { - core(function (ref){ - log = ref.getData('log'); + browser.runtime.sendMessage({ + function: "getData", + params: ['log'] + }).then((data) => { + log = data.response; // Sort the log | issue #70 log.log.sort(function(a,b) { @@ -108,3 +111,7 @@ function setText() $('#head_3').text(translate('log_html_table_head_3')); $('#head_4').text(translate('log_html_table_head_4')); } + +function handleError(error) { + console.log(`Error: ${error}`); +} diff --git a/core_js/message_handler.js b/core_js/message_handler.js new file mode 100644 index 0000000..032a8d1 --- /dev/null +++ b/core_js/message_handler.js @@ -0,0 +1,24 @@ +/*jshint esversion: 6 */ +/* + * This script is responsible for the communication between background and content_scripts. + */ + +/** + * [handleMessage description] + * @param request The message itself. This is a JSON-ifiable object. + * @param sender A runtime.MessageSender object representing the sender of the message. + * @param sendResponse A function to call, at most once, to send a response to the message. The function takes a single argument, which may be any JSON-ifiable object. This argument is passed back to the message sender. + */ +function handleMessage(request, sender, sendResponse) +{ + var fn = window[request.function]; + + if(typeof fn === "function") + { + var response = fn.apply(null, request.params); + + sendResponse({response}); + } +} + +browser.runtime.onMessage.addListener(handleMessage); diff --git a/core_js/popup_new.js b/core_js/popup.js similarity index 62% rename from core_js/popup_new.js rename to core_js/popup.js index 22a80c7..badcc81 100644 --- a/core_js/popup_new.js +++ b/core_js/popup.js @@ -1,3 +1,4 @@ +/*jshint esversion: 6 */ var element = $("#statistics_value"); var elGlobalPercentage = $("#statistics_value_global_percentage"); var elProgressbar_blocked = $('#progress_blocked'); @@ -12,25 +13,31 @@ var hashStatus; var loggingStatus; var statisticsStatus; var currentURL; -var reportServer; -var core = function (func) { - return browser.runtime.getBackgroundPage().then(func); -}; - -function getData() +async function getData() { - core(function (ref){ - globalCounter = ref.getData('globalCounter'); - globalurlcounter = ref.getData('globalurlcounter'); - globalStatus = ref.getData('globalStatus'); - badgedStatus = ref.getData('badgedStatus'); - hashStatus = ref.getData('hashStatus'); - loggingStatus = ref.getData('loggingStatus'); - statisticsStatus = ref.getData('statisticsStatus'); - currentURL = ref.getCurrentURL(); - reportServer = ref.getData('reportServer'); - }); + await browser.runtime.sendMessage({ + function: "getEntireData", + params: [] + }).then((data) => { + data = data.response; + globalCounter = data.globalCounter; + globalurlcounter = data.globalurlcounter; + globalStatus = data.globalStatus; + badgedStatus = data.badgedStatus; + hashStatus = data.hashStatus; + loggingStatus = data.loggingStatus; + statisticsStatus = data.statisticsStatus; + + browser.runtime.sendMessage({ + function: "getCurrentURL", + params: [] + }).then((data) => { + currentURL = data.response; + + return null; + }, handleError); + }, handleError); } /** @@ -48,8 +55,8 @@ function init() } /** -* Get the globalCounter value from the browser storage -* @param {(data){} Return value form browser.storage.local.get +* Get the globalCounter and globalurlcounter value from the storage +* @param {(data){} Return value form storage */ function changeStatistics() { @@ -93,19 +100,29 @@ function changeSwitchButton(id, storageID) changeVisibility(id, storageID); element.on('change', function(){ - core(function (ref){ - ref.setData(storageID, element.is(':checked')); - if(storageID == "globalStatus") ref.changeIcon(); + browser.runtime.sendMessage({ + function: "setData", + params: [storageID, element.is(':checked')] + }).then((data) => { + if(storageID == "globalStatus"){ + browser.runtime.sendMessage({ + function: "changeIcon", + params: [] + }); + } changeVisibility(id, storageID); - ref.saveOnExit(); + browser.runtime.sendMessage({ + function: "saveOnExit", + params: [] + }); }); }); } /** - * Change the visibility of sections. - */ +* Change the visibility of sections. +*/ function changeVisibility(id, storageID) { var element; @@ -113,13 +130,13 @@ function changeVisibility(id, storageID) switch(storageID) { case "loggingStatus": - element = $('#log_section'); - break; + element = $('#log_section'); + break; case "statisticsStatus": - element = $('#statistic_section'); - break; + element = $('#statistic_section'); + break; default: - element = "undefine"; + element = "undefine"; } if(element != "undefine") @@ -137,10 +154,10 @@ function changeVisibility(id, storageID) } /** - * Set the value of a switch button. - * @param {string} id HTML id - * @param {string} varname js internal variable name - */ +* Set the value of a switch button. +* @param {string} id HTML id +* @param {string} varname js internal variable name +*/ function setSwitchButton(id, varname) { var element = $('#'+id); @@ -151,25 +168,29 @@ function setSwitchButton(id, varname) * Reset the global statistic */ function resetGlobalCounter(){ - core(function (ref){ - globalurlcounter = 0; - globalCounter = 0; - ref.setData('globalCounter', 0); - ref.setData('globalurlcounter', 0); - ref.saveOnExit(); - - changeStatistics(); + browser.runtime.sendMessage({ + function: "setData", + params: ['globalCounter', 0] }); -} -if(!browser.extension.inIncognitoContext) -{ - getData(); + browser.runtime.sendMessage({ + function: "setData", + params: ['globalurlcounter', 0] + }); + + browser.runtime.sendMessage({ + function: "saveOnExit", + params: [] + }); + + globalCounter = 0; + globalurlcounter = 0; + + changeStatistics(); } $(document).ready(function(){ - if(!browser.extension.inIncognitoContext) - { + getData().then(() => { init(); $('#reset_counter_btn').on("click", resetGlobalCounter); changeSwitchButton("globalStatus", "globalStatus"); @@ -178,15 +199,8 @@ $(document).ready(function(){ changeSwitchButton("statistics", "statisticsStatus"); $('#loggingPage').attr('href', browser.extension.getURL('./html/log.html')); $('#settings').attr('href', browser.extension.getURL('./html/settings.html')); - $('#reportButton').on("click", reportURL); setText(); - } else { - $('#config_section').remove(); - $('#statistic_section').remove(); - $('#status_section').remove(); - $('#log_section').remove(); - $('#incognito').css('display', ''); - } + }); }); @@ -212,21 +226,21 @@ function setText() } /** - * Helper function to inject the translated text and tooltip. - * - * @param {string} id ID of the HTML element - * @param {string} attribute Name of the attribute used for localization - * @param {boolean} tooltip - */ +* Helper function to inject the translated text and tooltip. +* +* @param {string} id ID of the HTML element +* @param {string} attribute Name of the attribute used for localization +* @param {boolean} tooltip +*/ function injectText(id, attribute, tooltip) { object = $('#'+id); object.text(translate(attribute)); /* - This function will throw an error if no translation - is found for the tooltip. This is a planned error. - */ + This function will throw an error if no translation + is found for the tooltip. This is a planned error. + */ tooltip = translate(attribute+"_title"); if(tooltip != "") @@ -245,22 +259,6 @@ function translate(string) return browser.i18n.getMessage(string); } -/** - * Send the url to the DB on clearurls.röb.it to checked for tracking fields. - */ -function reportURL() -{ - $.ajax({ - url: reportServer+'/report_url.php?url='+encodeURI(currentURL), - success: function(result) { - BootstrapDialog.show({ - message: translate('success_report_url') - }); - }, - error: function(result) { - BootstrapDialog.show({ - message: translate('error_report_url') - }); - } - }); +function handleError(error) { + console.log(`Error: ${error}`); } diff --git a/core_js/settings.js b/core_js/settings.js index a88e5a9..a3414af 100644 --- a/core_js/settings.js +++ b/core_js/settings.js @@ -1,9 +1,5 @@ var settings = []; -var core = function (func) { - return browser.runtime.getBackgroundPage().then(func); -}; - getData(); /** @@ -17,11 +13,21 @@ $(document).ready(function(){ $("#badged_color input").on("change", function () { settings.badged_color = $(this).val(); - core(function (ref){ - ref.setData('badged_color', settings.badged_color); - ref.setBadgedStatus(); - ref.saveOnExit(); - }); + + browser.runtime.sendMessage({ + function: "setData", + params: ["badged_color", settings.badged_color] + }).then(handleResponse, handleError); + + browser.runtime.sendMessage({ + function: "setBadgedStatus", + params: [] + }).then(handleResponse, handleError); + + browser.runtime.sendMessage({ + function: "saveOnExit", + params: [] + }).then(handleResponse, handleError); }); }); @@ -31,11 +37,20 @@ $(document).ready(function(){ */ function reset() { - core(function (ref){ - ref.initSettings(); - ref.saveOnExit(); - ref.reload(); - }); + browser.runtime.sendMessage({ + function: "initSettings", + params: [] + }).then(handleResponse, handleError); + + browser.runtime.sendMessage({ + function: "saveOnExit", + params: [] + }).then(handleResponse, handleError); + + browser.runtime.sendMessage({ + function: "reload", + params: [] + }).then(handleResponse, handleError); } /** @@ -43,18 +58,42 @@ function reset() */ function save() { - core(function (ref){ - ref.setData('badged_color', $('input[name=badged_color]').val()); - ref.setBadgedStatus(); - ref.setData('ruleURL', $('input[name=rule_url]').val()); - ref.setData('hashURL', $('input[name=hash_url]').val()); - ref.setData('types', $('input[name=types]').val()); - ref.setData('reportServer', $('input[name=report_server]').val()); - ref.saveOnExit(); - ref.reload(); - }); + browser.runtime.sendMessage({ + function: "setData", + params: ["badged_color", $('input[name=badged_color]').val()] + }).then(handleResponse, handleError); - location.reload(); + browser.runtime.sendMessage({ + function: "setBadgedStatus", + params: [] + }).then(handleResponse, handleError); + + browser.runtime.sendMessage({ + function: "setData", + params: ["ruleURL", $('input[name=rule_url]').val()] + }).then(handleResponse, handleError); + + browser.runtime.sendMessage({ + function: "setData", + params: ["hashURL", $('input[name=hash_url]').val()] + }).then(handleResponse, handleError); + + browser.runtime.sendMessage({ + function: "setData", + params: ["types", $('input[name=types]').val()] + }).then(handleResponse, handleError); + + browser.runtime.sendMessage({ + function: "saveOnExit", + params: [] + }).then(handleResponse, handleError); + + browser.runtime.sendMessage({ + function: "reload", + params: [] + }).then(handleResponse, handleError); + + //location.reload(); } /** @@ -72,13 +111,25 @@ function translate(string) */ function getData() { - core(function (ref){ - settings.badged_color = ref.getData('badged_color'); - settings.rule_url = ref.getData('ruleURL'); - settings.hash_url = ref.getData('hashURL'); - settings.types = ref.getData('types'); - settings.reportServer = ref.getData('reportServer'); - }); + browser.runtime.sendMessage({ + function: "getData", + params: ["badged_color"] + }).then((data) => handleResponseData(data, "badged_color", "badged_color"), handleError); + + browser.runtime.sendMessage({ + function: "getData", + params: ["ruleURL"] + }).then((data) => handleResponseData(data, "rule_url", "rule_url"), handleError); + + browser.runtime.sendMessage({ + function: "getData", + params: ["hashURL"] + }).then((data) => handleResponseData(data, "hash_url", "hash_url"), handleError); + + browser.runtime.sendMessage({ + function: "getData", + params: ["types"] + }).then((data) => handleResponseData(data, "types", "types"), handleError); } /** @@ -89,17 +140,29 @@ function setText() document.title = translate('settings_html_page_title'); $('#page_title').text(translate('settings_html_page_title')); $('#badged_color_label').text(translate('badged_color_label')); - $('input[name=badged_color]').val(settings.badged_color); $('#reset_settings_btn').text(translate('setting_html_reset_button')); $('#reset_settings_btn').prop('title', translate('setting_html_reset_button_title')); $('#rule_url_label').text(translate('setting_rule_url_label')); - $('input[name=rule_url]').val(settings.rule_url); $('#hash_url_label').text(translate('setting_hash_url_label')); - $('input[name=hash_url]').val(settings.hash_url); $('#types_label').html(translate('setting_types_label')); - $('input[name=types]').val(settings.types); $('#save_settings_btn').text(translate('settings_html_save_button')); $('#save_settings_btn').prop('title', translate('settings_html_save_button_title')); - $('#report_server_label').html(translate('setting_report_server_label')); - $('input[name=report_server]').val(settings.reportServer); +} + +/** + * Handle the response from the storage and saves the data. + * @param {JSON-Object} data Data JSON-Object + */ +function handleResponseData(data, varName, inputID) +{ + settings[varName] = data.response; + $('input[name='+inputID+']').val(data.response); +} + +function handleResponse(message) { + console.log(`Message from the background script: ${message.response}`); +} + +function handleError(error) { + console.log(`Error: ${error}`); } diff --git a/core_js/storage.js b/core_js/storage.js new file mode 100644 index 0000000..ca103cc --- /dev/null +++ b/core_js/storage.js @@ -0,0 +1,200 @@ +/*jshint esversion: 6 */ +/* + * This script is responsible for the storage. +*/ +var storage = []; + +/** +* Writes the storage variable to the disk. +*/ +function saveOnExit() +{ + var json = {}; + + Object.entries(storage).forEach(([key, value]) => { + switch (key) { + case "ClearURLsData": + case "log": + json[key] = JSON.stringify(value); + break; + case "types": + json[key] = value.toString(); + break; + default: + json[key] = value; + } + }); + console.log(translate('core_save_on_disk')); + browser.storage.local.set(json); +} + +/** +* Save the value under the key on the disk. +* @param {String} key +* @param {Object} value +*/ +function saveOnDisk(key, value) +{ + browser.storage.local.set({key: value}); +} + +/** +* Retrieve everything and save on the RAM. +*/ +function getDataFromDisk() +{ + browser.storage.local.get().then(initStorage, error); +} + +/** +* Return the value under the key. +* @param {String} key +* @return {Object} +*/ +function getData(key) +{ + return storage[key]; +} + +/** + * Return the entire storage object. + * @return {Object} + */ +function getEntireData() +{ + return storage; +} + +/** +* Save the value under the key on the RAM. +* @param {String} key +* @param {Object} value +*/ +function setData(key, value) +{ + switch (key) { + case "ClearURLsData": + case "log": + storage[key] = JSON.parse(value); + break; + case "hashURL": + case "ruleURL": + storage[key] = replaceOldURLs(value); + break; + case "types": + storage[key] = value.split(','); + break; + default: + storage[key] = value; + } +} + +/** +* Write error on console. +*/ +function error(e) +{ + console.log(translate('core_error')); + console.error(e); +} + +/** +* Set default values, if the storage is empty. +* @param {Object} items +*/ +function initStorage(items) +{ + initSettings(); + + if(!isEmpty(items)) { + Object.entries(items).forEach(([key, value]) => { + setData(key, value); + }); + } + + // Start the clearurls.js + start(); +} + +/** +* Set default values for the settings. +*/ +function initSettings() +{ + storage.ClearURLsData = []; + storage.dataHash = ""; + storage.badgedStatus = true; + storage.globalStatus = true; + storage.globalurlcounter = 0; + storage.globalCounter = 0; + storage.hashStatus = "error"; + storage.loggingStatus = false; + storage.log = {"log": []}; + storage.statisticsStatus = true; + storage.badged_color = "ffa500"; + storage.hashURL = "https://gitlab.com/KevinRoebert/ClearUrls/-/jobs/artifacts/master/raw/rules.min.hash?job=hash%20rules"; + storage.ruleURL = "https://gitlab.com/KevinRoebert/ClearUrls/raw/master/data/data.min.json"; + storage.types = ["font", "image", "imageset", "main_frame", "media", "object", "object_subrequest", "other", "script", "stylesheet", "sub_frame", "websocket", "xbl", "xml_dtd", "xmlhttprequest", "xslt"]; + storage.reportServer = "https://clearurls.xn--rb-fka.it"; +} + +/** +* Replace the old URLs with the +* new GitLab URLs. +*/ +function replaceOldURLs(url) +{ + switch (url) { + case "https://raw.githubusercontent.com/KevinRoebert/ClearUrls/master/data/rules.hash?flush_cache=true": + return "https://gitlab.com/KevinRoebert/ClearUrls/raw/master/data/rules.hash"; + case "https://raw.githubusercontent.com/KevinRoebert/ClearUrls/master/data/data.json?flush_cache=true": + return "https://gitlab.com/KevinRoebert/ClearUrls/raw/master/data/data.json"; + case "https://gitlab.com/KevinRoebert/ClearUrls/raw/master/data/rules.hash": + return "https://gitlab.com/KevinRoebert/ClearUrls/-/jobs/artifacts/master/raw/rules.min.hash?job=hash%20rules"; + case "https://gitlab.com/KevinRoebert/ClearUrls/raw/master/data/data.json": + return "https://gitlab.com/KevinRoebert/ClearUrls/raw/master/data/data.min.json"; + default: + return url; + } +} + +/** +* Load local saved data, if the browser is offline or +* some other network trouble. +*/ +function loadOldDataFromStore() +{ + localDataHash = storage.dataHash; +} + +/** +* Save the hash status to the local storage. +* The status can have the following values: +* 1 "up to date" +* 2 "updated" +* 3 "update available" +* @param status_code the number for the status +*/ +function storeHashStatus(status_code) +{ + switch(status_code) + { + case 1: status_code = "hash_status_code_1"; + break; + case 2: status_code = "hash_status_code_2"; + break; + case 3: status_code = "hash_status_code_3"; + break; + default: status_code = "hash_status_code_4"; + } + + storage.hashStatus = status_code; +} + +/** +* Save every minute the temporary data to the disk. +*/ +setInterval(saveOnExit, 60000); + +// Start storage +getDataFromDisk(); diff --git a/core_js/tools.js b/core_js/tools.js new file mode 100644 index 0000000..1375231 --- /dev/null +++ b/core_js/tools.js @@ -0,0 +1,171 @@ +/*jshint esversion: 6 */ +/* + * This script is responsible for some tools. +*/ + +/** +* Check if an object is empty. +* @param {Object} obj +* @return {Boolean} +*/ +function isEmpty(obj) +{ + return (Object.getOwnPropertyNames(obj).length === 0); +} + +/** +* Translate a string with the i18n API. +* +* @param {string} string Name of the attribute used for localization +*/ +function translate(string) +{ + return browser.i18n.getMessage(string); +} + +/** +* Reloads the extension. +*/ +function reload() +{ + browser.runtime.reload(); +} + +/** +* Check if it is an android device. +* @return bool +*/ +function checkOSAndroid() +{ + if(os == "android") + { + return true; + } + else{ + return false; + } +} + +/** +* Return the number of parameters query strings. +* @param {String} url URL as String +* @return {int} Number of Parameters +*/ +function countFields(url) +{ + return extractFileds(url).length; +} + +/** + * Extract the fields from an url. + * @param {String} url URL as String + * @return {Array} Fields as array + */ +function extractFileds(url) +{ + return (url.match(/[^\/|\?|&]+=[^\/|\?|&]+/gi) || []); +} + +/** +* Returns true if fields exists. +* @param {String} url URL as String +* @return {boolean} +*/ +function existsFields(url) +{ + var matches = (url.match(/\?.+/i) || []); + var count = matches.length; + + return (count > 0); +} + +/** +* Load local saved data, if the browser is offline or +* some other network trouble. +*/ +function loadOldDataFromStore() +{ + localDataHash = storage.dataHash; +} + +/** +* Save the hash status to the local storage. +* The status can have the following values: +* 1 "up to date" +* 2 "updated" +* 3 "update available" +* @param status_code the number for the status +*/ +function storeHashStatus(status_code) +{ + switch(status_code) + { + case 1: status_code = "hash_status_code_1"; + break; + case 2: status_code = "hash_status_code_2"; + break; + case 3: status_code = "hash_status_code_3"; + break; + default: status_code = "hash_status_code_4"; + } + + storage.hashStatus = status_code; +} + +/** +* Increase by {number} the GlobalURLCounter +* @param {int} number +*/ +function increaseGlobalURLCounter(number) +{ + if(storage.statisticsStatus) + { + storage.globalurlcounter += number; + } +} + +/** +* Increase by one the URLCounter +*/ +function increaseURLCounter() +{ + if(storage.statisticsStatus) + { + storage.globalCounter++; + } +} + +/** +* Change the icon. +*/ +function changeIcon() +{ + if(storage.globalStatus){ + browser.browserAction.setIcon({path: "img/clearurls.svg"}); + } else{ + browser.browserAction.setIcon({path: "img/clearurls_gray.svg"}); + } +} + +/** +* Get the badged status from the browser storage and put the value +* into a local variable. +* +*/ +function setBadgedStatus() +{ + if(!checkOSAndroid() && storage.badgedStatus){ + browser.browserAction.setBadgeBackgroundColor({ + 'color': '#'+storage.badged_color + }); + } +} + +/** +* Returns the current URL. +* @return {String} [description] +*/ +function getCurrentURL() +{ + return currentURL; +} diff --git a/data/data.min.json b/data/data.min.json new file mode 100644 index 0000000..db9c62e --- /dev/null +++ b/data/data.min.json @@ -0,0 +1,412 @@ +{ + "providers": { + "amazon": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(amazon)(\\.[a-zA-Z]{2,})(.*\\?.*)", + "completeProvider": false, + "rules": [ + "pf_rd_[a-zA-Z]", + "qid", + "sr", + "srs", + "pd_rd_[a-zA-Z]*", + "__mk_[a-zA-Z]{1,3}_[a-zA-Z]{1,3}", + "spIA", + "ms3_c", + "[a-zA-Z%0-9]*ie", + "refRID", + "colid", + "coliid", + "[^a-zA-Z%0-9]adId", + "qualifier", + "_encoding", + "smid", + "field-lbr_brands_browse-bin" + ], + "exceptions": [ + ".*(amazon\\.).*(\\/gp).*\\/redirector.html\\/.*" + ], + "redirections": [] + }, + "fls-na.amazon": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(fls-na\\.amazon)(\\.[a-zA-Z]{2,}).*", + "completeProvider": true, + "rules": [], + "exceptions": [], + "redirections": [] + }, + "google": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(google)(\\.[a-zA-Z]{2,})(.*\\?.*)", + "completeProvider": false, + "rules": [ + "ved", + "bi[a-zA-Z]*", + "gfe_[a-zA-Z]*", + "ei", + "source", + "gs_[a-zA-Z]*", + "site", + "oq", + "esrc", + "uact", + "cd", + "cad", + "gws_[a-zA-Z]*", + "atyp", + "vet", + "zx", + "_u", + "je", + "dcr", + "ie", + "sei", + "sa", + "dpr", + "hl", + "btn[a-zA-Z]*", + "sa", + "usg", + "cd", + "cad", + "uact" + ], + "exceptions": [ + ".*(mail\\.google\\.).*(\\/mail\\/u\\/0).*", + ".*(google\\.).*(\\/upload)?(\\/drive)\\/.*", + ".*(docs\\.google\\.).*\\/.*", + ".*(accounts\\.google\\.).*", + ".*(google\\.).*\\/searchbyimage\\?image_url=[^\\/|\\?|&]*(\\/|&(amp;)?)?", + ".*(hangouts\\.google\\.).*\\/webchat.*zx=[^\\/|\\?|&]*(\\/|&(amp;)?)?", + ".*(client-channel\\.google\\.).*\\/client-channel.*zx=[^\\/|\\?|&]*(\\/|&(amp;)?)?", + ".*(google\\.).*\\/complete\\/search\\?.*gs_[a-zA-Z]*=[^\\/|\\?|&]*(\\/|&(amp;)?)?", + ".*(google\\.).*\\/s\\?tbm=map.*gs_[a-zA-Z]*=[^\\/|\\?|&]*(\\/|&(amp;)?)?", + ".*(news\\.google\\.).*\\?hl=.*", + ".*(google\\.).*\\/setprefs\\?.*hl=[^\\/|\\?|&]*(\\/|&(amp;)?)?", + ".*(google\\.).*\\/appsactivity\\/.*" + ], + "redirections": [ + ".*google\\..*\\/.*url\\?.*url=((https%3A%2F%2F|http%3A%2F%2F)[^&]*)" + ] + }, + "googlesyndication": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(googlesyndication)(\\.[a-zA-Z]{2,}).*", + "completeProvider": true, + "rules": [], + "exceptions": [], + "redirections": [] + }, + "doubleclick": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(doubleclick)(\\.[a-zA-Z]{2,}).*", + "completeProvider": true, + "rules": [], + "exceptions": [], + "redirections": [ + ".*doubleclick\\..*\\/.*tag_for_child_directed_treatment=;%3F(.*)" + ] + }, + "globalRules": { + "urlPattern": ".*", + "completeProvider": false, + "rules": [ + "utm_[a-zA-Z]*", + "ga_source", + "ga_medium", + "ga_term", + "ga_content", + "ga_campaign", + "ga_place", + "yclid", + "_openstat", + "fb_action_ids", + "fb_action_types", + "fb_source", + "fb_ref", + "fbclid", + "action_object_map", + "action_type_map", + "action_ref_map", + "gs_l", + "mkt_tok", + "hmb_campaign", + "hmb_medium", + "hmb_source", + "[\\?|&]ref[\\_]?" + ], + "exceptions": [ + ".*([\\.]?matrix\\.org)(\\/_matrix)\\/.*", + ".*([\\.]?prismic\\.io).*", + ".*([\\.]?gitlab\\.com).*", + ".*([\\.]?gcsip\\.com).*[\\?|&]ref[\\_]?=[^\\/|\\?|&]*.*", + ".*([\\.]?cloudflare\\.com).*" + ], + "redirections": [] + }, + "adtech": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(adtech)(\\.[a-zA-Z]{2,}).*", + "completeProvider": true, + "rules": [], + "exceptions": [], + "redirections": [] + }, + "contentpass.net": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(contentpass\\.net).*", + "completeProvider": true, + "rules": [], + "exceptions": [], + "redirections": [] + }, + "bf-ad": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(bf-ad)(\\.[a-zA-Z]{2,}).*", + "completeProvider": true, + "rules": [], + "exceptions": [], + "redirections": [] + }, + "amazon-adsystem": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(amazon-adsystem)(\\.[a-zA-Z]{2,}).*", + "completeProvider": true, + "rules": [], + "exceptions": [], + "redirections": [] + }, + "adsensecustomsearchads": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(adsensecustomsearchads)(\\.[a-zA-Z]{2,}).*", + "completeProvider": true, + "rules": [], + "exceptions": [], + "redirections": [] + }, + "youtube": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(youtube)(\\.[a-zA-Z]{2,})(.*\\?.*)", + "completeProvider": false, + "rules": [ + "feature", + "gclid", + "kw" + ], + "exceptions": [], + "redirections": [] + }, + "facebook": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(facebook)(\\.[a-zA-Z]{2,})(.*\\?.*)", + "completeProvider": false, + "rules": [ + "hc_[a-zA-Z_\\[\\]0-9]*", + "[a-zA-Z]*ref[a-zA-Z]*", + "__tn__" + ], + "exceptions": [ + ".*(facebook\\.)\\w{2,}.*(\\/plugins\\/).*" + ], + "redirections": [] + }, + "twitter": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(twitter)(\\.[a-zA-Z]{2,})(.*\\?.*)", + "completeProvider": false, + "rules": [ + "(ref_)?src" + ], + "exceptions": [], + "redirections": [] + }, + "reddit": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(reddit)(\\.[a-zA-Z]{2,})(.*\\?.*)", + "completeProvider": false, + "rules": [], + "exceptions": [], + "redirections": [ + "out\\.reddit\\.\\w{2,}\\/.*url=([^&]*)" + ] + } + , + "netflix": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(netflix)(\\.[a-zA-Z]{2,})(.*\\?.*)", + "completeProvider": false, + "rules": [ + "trackId", + "tctx", + "jb[a-zA-Z]*" + ], + "exceptions": [], + "redirections": [] + }, + "techcrunch": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?([\\.]?techcrunch\\.com)(.*\\?.*)", + "completeProvider": false, + "rules": [ + "ncid", + "sr", + "sr_share" + ], + "exceptions": [], + "redirections": [] + }, + "bing": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(bing)(\\.[a-zA-Z]{2,})(.*\\?.*)", + "completeProvider": false, + "rules": [ + "cvid", + "form", + "sk", + "sp", + "sc", + "qs", + "qp" + ], + "exceptions": [], + "redirections": [] + }, + "tweakers": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(tweakers\\.net)(.*\\?.*)", + "completeProvider": false, + "rules": [ + "nb", + "u" + ], + "exceptions": [], + "redirections": [] + }, + "twitch": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(twitch)(\\.[a-zA-Z]{2,})(.*\\?.*)", + "completeProvider": false, + "rules": [ + "tt_medium", + "tt_content" + ], + "exceptions": [], + "redirections": [] + }, + "vivaldi": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(vivaldi\\.com)(.*\\?.*)", + "completeProvider": false, + "rules": [ + "pk_campaign", + "pk_kwd" + ], + "exceptions": [], + "redirections": [] + }, + "indeed": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(indeed\\.com)(.*\\?.*)", + "completeProvider": false, + "rules": [ + "from", + "alid", + "[a-zA-Z]*tk" + ], + "exceptions": [], + "redirections": [] + }, + "hhdotru": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(hh\\.ru)(.*\\?.*)", + "completeProvider": false, + "rules": [ + "vss", + "t", + "swnt", + "grpos", + "ptl", + "stl", + "exp", + "plim" + ], + "exceptions": [], + "redirections": [] + }, + "ebay": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(ebay)(\\.[a-zA-Z]{2,})(.*\\?.*)", + "completeProvider": false, + "rules": [ + "_trkparms", + "_trksid", + "_from" + ], + "exceptions": [], + "redirections": [] + }, + "cnet": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(cnet\\.com)(.*\\?.*)", + "completeProvider": false, + "rules": [ + "ftag" + ], + "exceptions": [], + "redirections": [] + }, + "imdb.com": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(imdb\\.com)(.*\\?.*)", + "completeProvider": false, + "rules": [ + "ref_", + "pf_rd_[a-zA-Z]*" + ], + "exceptions": [], + "redirections": [] + }, + "govdelivery.com": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(govdelivery\\.com)(.*\\?.*)", + "completeProvider": false, + "rules": [], + "exceptions": [], + "redirections": [ + ".*links\\.govdelivery\\.com.*\\/track\\?.*(http:\\/\\/.*)", + ".*links\\.govdelivery\\.com.*\\/track\\?.*(https:\\/\\/.*)" + ] + }, + "walmart.com": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(walmart\\.com)(.*\\?.*)", + "completeProvider": false, + "rules": [ + "u1", + "ath[a-zA-Z]*" + ], + "exceptions": [], + "redirections": [] + }, + "net-parade.it": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(net\\-parade\\.it)(.*\\?.*)", + "completeProvider": false, + "rules": [ + "pl" + ], + "exceptions": [], + "redirections": [] + }, + "prvnizpravy.cz": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(prvnizpravy\\.cz)(.*\\?.*)", + "completeProvider": false, + "rules": [ + "xid" + ], + "exceptions": [], + "redirections": [] + }, + "youku.com": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(youku\\.com)(.*\\?.*)", + "completeProvider": false, + "rules": [ + "spm", + "tpa" + ], + "exceptions": [], + "redirections": [] + }, + "nytimes.com": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(nytimes\\.com)(.*\\?.*)", + "completeProvider": false, + "rules": [ + "smid" + ], + "exceptions": [], + "redirections": [] + }, + "tchibo.de": { + "urlPattern": "(https:\\/\\/|http:\\/\\/)([a-zA-Z0-9-]*\\.)?(tchibo\\.de)(.*\\?.*)", + "completeProvider": false, + "rules": [ + "wbdcd" + ], + "exceptions": [], + "redirections": [] + } + } +} diff --git a/html/popup.html b/html/popup.html index 377e42b..661f88d 100644 --- a/html/popup.html +++ b/html/popup.html @@ -36,16 +36,6 @@ -