Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: lib/elemHide.js

Issue 29893618: Issue 6957 - Return common style sheet for unknown domains (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore/
Patch Set: Created Sept. 27, 2018, 9:18 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | lib/elemHideExceptions.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/elemHide.js
===================================================================
--- a/lib/elemHide.js
+++ b/lib/elemHide.js
@@ -58,40 +58,93 @@
/**
* The default style sheet that applies on all domains. This is based on the
* value of <code>{@link unconditionalSelectors}</code>.
* @type {?string}
*/
let defaultStyleSheet = null;
/**
+ * The common style sheet that applies on all unknown domains. This is a
+ * concatenation of the default style sheet and an additional style sheet based
+ * on selectors from all generic filters that are not in the
+ * <code>{@link unconditionalSelectors}</code> list.
+ * @type {?string}
+ */
+let commonStyleSheet = null;
+
+/**
* Map to be used instead when a filter has a blank domains property.
* @type {Map.<string,boolean>}
* @const
*/
let defaultDomains = new Map([["", true]]);
/**
+ * Set containing all known domains
+ * @type {Set.<string>}
+ */
+let knownDomains = new Set();
+
+/**
* Set containing known element hiding filters
* @type {Set.<ElemHideFilter>}
*/
let knownFilters = new Set();
/**
+ * Returns the suffix of the given domain that is known. If no suffix is known,
+ * an empty string is returned.
+ * @param {?string} domain
+ * @returns {string}
+ */
+function getKnownSuffix(domain)
+{
+ if (!domain)
+ return "";
+
+ if (domain[domain.length - 1] == ".")
+ domain = domain.replace(/\.+$/, "");
+
+ domain = domain.toLowerCase();
+
+ while (domain)
+ {
+ if (knownDomains.has(domain) || ElemHideExceptions.isKnownDomain(domain))
+ break;
+
+ let index = domain.indexOf(".");
+ domain = index == -1 ? "" : domain.substring(index + 1);
+ }
+
+ return domain;
+}
+
+/**
* Adds a filter to the lookup table of filters by domain.
* @param {Filter} filter
*/
function addToFiltersByDomain(filter)
{
let domains = filter.domains || defaultDomains;
for (let [domain, isIncluded] of domains)
{
// There's no need to note that a filter is generically disabled.
- if (!isIncluded && domain == "")
- continue;
+ if (domain == "")
+ {
+ if (!isIncluded)
+ continue;
+ }
+ else
+ {
+ // Note: Once a domain is known it never becomes unknown, even when all
+ // the filters containing that domain are removed. This is a best-case
+ // optimization.
+ knownDomains.add(domain);
+ }
let filters = filtersByDomain.get(domain);
if (!filters)
filtersByDomain.set(domain, filters = new Map());
filters.set(filter, isIncluded);
}
}
@@ -117,17 +170,17 @@
*
* @returns {Array.<string>} The list of selectors.
*/
function getConditionalSelectorsForDomain(domain, specificOnly = false)
{
let selectors = [];
let excluded = new Set();
- let currentDomain = domain ? domain.replace(/\.+$/, "").toLowerCase() : "";
+ let currentDomain = domain;
// This code is a performance hot-spot, which is why we've made certain
// micro-optimisations. Please be careful before making changes.
while (true)
{
if (specificOnly && currentDomain == "")
break;
@@ -169,18 +222,33 @@
function getDefaultStyleSheet()
{
if (!defaultStyleSheet)
defaultStyleSheet = createStyleSheet(getUnconditionalSelectors());
return defaultStyleSheet;
}
+/**
+ * Returns the default style sheet that applies on all unknown domains.
+ * @returns {string}
+ */
+function getCommonStyleSheet()
+{
+ if (!commonStyleSheet)
+ commonStyleSheet = getDefaultStyleSheet() +
+ createStyleSheet(getConditionalSelectorsForDomain(""));
+
+ return commonStyleSheet;
+}
+
ElemHideExceptions.on("added", ({selector}) =>
{
+ commonStyleSheet = null;
+
// If this is the first exception for a previously unconditionally applied
// element hiding selector we need to take care to update the lookups.
let unconditionalFilterForSelector = filterBySelector.get(selector);
if (unconditionalFilterForSelector)
{
addToFiltersByDomain(unconditionalFilterForSelector);
filterBySelector.delete(selector);
unconditionalSelectors = null;
@@ -193,17 +261,20 @@
* @class
*/
exports.ElemHide = {
/**
* Removes all known filters
*/
clear()
{
- for (let collection of [filtersByDomain, filterBySelector, knownFilters])
+ commonStyleSheet = null;
+
+ for (let collection of [filtersByDomain, filterBySelector, knownDomains,
+ knownFilters])
collection.clear();
unconditionalSelectors = null;
defaultStyleSheet = null;
filterNotifier.emit("elemhideupdate");
},
@@ -211,16 +282,18 @@
* Add a new element hiding filter
* @param {ElemHideFilter} filter
*/
add(filter)
{
if (knownFilters.has(filter))
return;
+ commonStyleSheet = null;
+
let {selector} = filter;
if (!(filter.domains || ElemHideExceptions.hasExceptions(selector)))
{
// The new filter's selector is unconditionally applied to all domains
filterBySelector.set(selector, filter);
unconditionalSelectors = null;
defaultStyleSheet = null;
@@ -239,16 +312,18 @@
* Removes an element hiding filter
* @param {ElemHideFilter} filter
*/
remove(filter)
{
if (!knownFilters.has(filter))
return;
+ commonStyleSheet = null;
+
let {selector} = filter;
// Unconditially applied element hiding filters
if (filterBySelector.get(selector) == filter)
{
filterBySelector.delete(selector);
unconditionalSelectors = null;
defaultStyleSheet = null;
@@ -288,19 +363,22 @@
* @param {boolean} [specificOnly=false] Whether selectors from generic
* filters should be included.
*
* @returns {ElemHideStyleSheet} An object containing the CSS code and the
* list of selectors.
*/
generateStyleSheetForDomain(domain, specificOnly = false)
{
- let selectors = getConditionalSelectorsForDomain(domain, specificOnly);
+ let knownSuffix = getKnownSuffix(domain);
+
+ let selectors = getConditionalSelectorsForDomain(knownSuffix, specificOnly);
let code = specificOnly ? createStyleSheet(selectors) :
- (getDefaultStyleSheet() + createStyleSheet(selectors));
+ knownSuffix == "" ? getCommonStyleSheet() :
+ (getDefaultStyleSheet() + createStyleSheet(selectors));
if (!specificOnly)
selectors = getUnconditionalSelectors().concat(selectors);
return {code, selectors};
}
};
« no previous file with comments | « no previous file | lib/elemHideExceptions.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld