diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 453b7be..33918c7 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 > 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 aec5fd6..623df8a 100644
--- a/clearurls.js
+++ b/clearurls.js
@@ -164,14 +164,17 @@ function start()
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;
}
/**
@@ -205,7 +208,7 @@ function start()
* @return {boolean} ProviderURL as RegExp
*/
this.matchURL = function(url) {
- return !(this.matchException(url)) && urlPattern.test(url);
+ return urlPattern.test(url) && !(this.matchException(url));
};
/**
@@ -216,17 +219,26 @@ function start()
* @param {boolean} isActive Is this rule active?
*/
this.addRule = function(rule, isActive = true) {
- for(var i=0; i < rules.length; i++)
- {
- if(rules[i][0] === rule)
- {
- rules[i] = [rule, isActive];
+ // Add start and end delimiters to rule
+ rule = "^"+rule+"=[^\\/|\\?|&]*(\\/|&(amp;)?)?$";
- return;
+ if(isActive)
+ {
+ enabled_rules[rule] = true;
+
+ if(disabled_rules[rule] !== undefined)
+ {
+ delete disabled_rules[rule];
}
}
+ else {
+ disabled_rules[rule] = true;
- rules.push([rule, isActive]);
+ if(enabled_rules[rule] !== undefined)
+ {
+ delete enabled_rules[rule];
+ }
+ }
};
/**
@@ -235,16 +247,7 @@ function start()
* @return Array RegExp strings
*/
this.getRules = function() {
- var rawRules = [];
-
- rules.forEach(rule => {
- if(rule[1] === true)
- {
- rawRules.push(rule[0]);
- }
- });
-
- return rawRules;
+ return Object.keys(enabled_rules);
};
/**
@@ -255,16 +258,23 @@ function start()
* @param {Boolean} isActive Is this exception acitve?
*/
this.addException = function(exception, isActive = true) {
- for(var i=0; i < exceptions.length; i++)
+ if(isActive)
{
- if(exceptions[i][0] === exception)
+ enabled_exceptions[exception] = true;
+
+ if(disabled_exceptions[exception] !== undefined)
{
- exceptions[i] = [exception, isActive];
- return;
+ delete disabled_exceptions[exception];
}
}
+ else {
+ disabled_exceptions[exception] = true;
- exceptions.push([exception, isActive]);
+ if(enabled_exceptions[exception] !== undefined)
+ {
+ delete enabled_exceptions[exception];
+ }
+ }
};
/**
@@ -280,14 +290,11 @@ function start()
//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;
- if(exceptions[i][1])
- {
- exception_regex = new RegExp(exceptions[i][0], "i");
- result = exception_regex.test(url);
- }
+ exception_regex = new RegExp(exception, "i");
+ result = exception_regex.test(url);
}
return result;
@@ -301,15 +308,23 @@ function start()
* @param {Boolean} isActive Is this redirection active?
*/
this.addRedirection = function(redirection, isActive = true) {
- for(var i=0; i < redirections.length; i++)
+ if(isActive)
{
- if(redirections[i][0] === redirection) {
- redirections[i] = [redirection, isActive];
- return;
+ enabled_redirections[redirection] = true;
+
+ if(disabled_redirections[redirection] !== undefined)
+ {
+ delete disabled_redirections[redirection];
}
}
+ else {
+ disabled_redirections[redirection] = true;
- redirections.push([redirection, isActive]);
+ if(enabled_redirections[redirection] !== undefined)
+ {
+ delete enabled_redirections[redirection];
+ }
+ }
};
/**
@@ -320,13 +335,12 @@ function start()
this.getRedirection = function(url) {
var re = null;
- for(var i = 0; i < redirections.length; i++)
- {
- result = (url.match(new RegExp(redirections[i][0], "i")));
+ for(var redirection in enabled_redirections) {
+ result = (url.match(new RegExp(redirection, "i")));
- if (result && result.length > 0 && redirections[i][1])
+ if (result && result.length > 0 && redirection)
{
- re = (new RegExp(redirections[i][0], "i")).exec(url)[1];
+ re = (new RegExp(redirection, "i")).exec(url)[1];
break;
}
@@ -363,7 +377,7 @@ function start()
{
url = decodeURIComponent(re);
//Log the action
- pushToLog(request.url, re, translate('log_redirect'));
+ pushToLog(request.url, url, translate('log_redirect'));
return {
"redirect": true,
@@ -382,40 +396,45 @@ function start()
* before the last ?. With adding a ? on the quantifier *,
* we fixed this problem.
*/
- fields = url.replace(new RegExp(".*?\\?", "i"), "");
+ 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)
@@ -602,7 +621,6 @@ function start()
var ret = clearUrl(requestDetails);
return ret;
}
-
}
/**
diff --git a/core_js/popup.js b/core_js/popup.js
index 510dc0f..badcc81 100644
--- a/core_js/popup.js
+++ b/core_js/popup.js
@@ -13,7 +13,6 @@ var hashStatus;
var loggingStatus;
var statisticsStatus;
var currentURL;
-var reportServer;
async function getData()
{
@@ -29,7 +28,6 @@ async function getData()
hashStatus = data.hashStatus;
loggingStatus = data.loggingStatus;
statisticsStatus = data.statisticsStatus;
- reportServer = data.reportServer;
browser.runtime.sendMessage({
function: "getCurrentURL",
@@ -201,7 +199,6 @@ $(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();
});
@@ -262,26 +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 5db3284..a3414af 100644
--- a/core_js/settings.js
+++ b/core_js/settings.js
@@ -83,11 +83,6 @@ function save()
params: ["types", $('input[name=types]').val()]
}).then(handleResponse, handleError);
- browser.runtime.sendMessage({
- function: "setData",
- params: ["reportServer", $('input[name=report_server]').val()]
- }).then(handleResponse, handleError);
-
browser.runtime.sendMessage({
function: "saveOnExit",
params: []
@@ -135,11 +130,6 @@ function getData()
function: "getData",
params: ["types"]
}).then((data) => handleResponseData(data, "types", "types"), handleError);
-
- browser.runtime.sendMessage({
- function: "getData",
- params: ["reportServer"]
- }).then((data) => handleResponseData(data, "reportServer", "report_server"), handleError);
}
/**
@@ -157,7 +147,6 @@ function setText()
$('#types_label').html(translate('setting_types_label'));
$('#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'));
}
/**
diff --git a/core_js/storage.js b/core_js/storage.js
index 3565ee6..ca103cc 100644
--- a/core_js/storage.js
+++ b/core_js/storage.js
@@ -79,7 +79,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(',');
@@ -132,23 +132,27 @@ function initSettings()
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.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 GitHub URLs with the
+* Replace the old 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":
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;
}
diff --git a/core_js/tools.js b/core_js/tools.js
index 9008745..1375231 100644
--- a/core_js/tools.js
+++ b/core_js/tools.js
@@ -53,10 +53,17 @@ function checkOSAndroid()
*/
function countFields(url)
{
- var matches = (url.match(/[^\/|\?|&]+=[^\/|\?|&]+/gi) || []);
- var count = matches.length;
+ return extractFileds(url).length;
+}
- return count;
+/**
+ * Extract the fields from an url.
+ * @param {String} url URL as String
+ * @return {Array} Fields as array
+ */
+function extractFileds(url)
+{
+ return (url.match(/[^\/|\?|&]+=[^\/|\?|&]+/gi) || []);
}
/**
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 f72db69..661f88d 100644
--- a/html/popup.html
+++ b/html/popup.html
@@ -132,24 +132,15 @@
-