OLD | NEW |
1 // We are currently limited to ECMAScript 5 in this file, because it is being | 1 /* |
2 // used in the browser tests. See https://issues.adblockplus.org/ticket/4796 | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
| 3 * Copyright (C) 2006-2017 eyeo GmbH |
| 4 * |
| 5 * Adblock Plus is free software: you can redistribute it and/or modify |
| 6 * it under the terms of the GNU General Public License version 3 as |
| 7 * published by the Free Software Foundation. |
| 8 * |
| 9 * Adblock Plus is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 * GNU General Public License for more details. |
| 13 * |
| 14 * You should have received a copy of the GNU General Public License |
| 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
| 16 */ |
3 | 17 |
4 var propertySelectorRegExp = /\[\-abp\-properties=(["'])([^"']+)\1\]/; | 18 /* globals filterToRegExp */ |
| 19 |
| 20 "use strict"; |
| 21 |
| 22 let propertySelectorRegExp = /\[-abp-properties=(["'])([^"']+)\1\]/; |
5 | 23 |
6 function splitSelector(selector) | 24 function splitSelector(selector) |
7 { | 25 { |
8 if (selector.indexOf(",") == -1) | 26 if (selector.indexOf(",") == -1) |
9 return [selector]; | 27 return [selector]; |
10 | 28 |
11 var selectors = []; | 29 let selectors = []; |
12 var start = 0; | 30 let start = 0; |
13 var level = 0; | 31 let level = 0; |
14 var sep = ""; | 32 let sep = ""; |
15 | 33 |
16 for (var i = 0; i < selector.length; i++) | 34 for (let i = 0; i < selector.length; i++) |
17 { | 35 { |
18 var chr = selector[i]; | 36 let chr = selector[i]; |
19 | 37 |
20 if (chr == "\\") // ignore escaped characters | 38 if (chr == "\\") // ignore escaped characters |
21 i++; | 39 i++; |
22 else if (chr == sep) // don't split within quoted text | 40 else if (chr == sep) // don't split within quoted text |
23 sep = ""; // e.g. [attr=","] | 41 sep = ""; // e.g. [attr=","] |
24 else if (sep == "") | 42 else if (sep == "") |
25 { | 43 { |
26 if (chr == '"' || chr == "'") | 44 if (chr == '"' || chr == "'") |
27 sep = chr; | 45 sep = chr; |
28 else if (chr == "(") // don't split between parentheses | 46 else if (chr == "(") // don't split between parentheses |
(...skipping 13 matching lines...) Expand all Loading... |
42 } | 60 } |
43 | 61 |
44 function ElemHideEmulation(window, getFiltersFunc, addSelectorsFunc) | 62 function ElemHideEmulation(window, getFiltersFunc, addSelectorsFunc) |
45 { | 63 { |
46 this.window = window; | 64 this.window = window; |
47 this.getFiltersFunc = getFiltersFunc; | 65 this.getFiltersFunc = getFiltersFunc; |
48 this.addSelectorsFunc = addSelectorsFunc; | 66 this.addSelectorsFunc = addSelectorsFunc; |
49 } | 67 } |
50 | 68 |
51 ElemHideEmulation.prototype = { | 69 ElemHideEmulation.prototype = { |
52 stringifyStyle: function(style) | 70 stringifyStyle(style) |
53 { | 71 { |
54 var styles = []; | 72 let styles = []; |
55 for (var i = 0; i < style.length; i++) | 73 for (let i = 0; i < style.length; i++) |
56 { | 74 { |
57 var property = style.item(i); | 75 let property = style.item(i); |
58 var value = style.getPropertyValue(property); | 76 let value = style.getPropertyValue(property); |
59 var priority = style.getPropertyPriority(property); | 77 let priority = style.getPropertyPriority(property); |
60 styles.push(property + ": " + value + (priority ? " !" + priority : "") +
";"); | 78 styles.push(property + ": " + value + (priority ? " !" + priority : "") + |
| 79 ";"); |
61 } | 80 } |
62 styles.sort(); | 81 styles.sort(); |
63 return styles.join(" "); | 82 return styles.join(" "); |
64 }, | 83 }, |
65 | 84 |
66 isSameOrigin: function(stylesheet) | 85 isSameOrigin(stylesheet) |
67 { | 86 { |
68 try | 87 try |
69 { | 88 { |
70 return new URL(stylesheet.href).origin == this.window.location.origin; | 89 return new URL(stylesheet.href).origin == this.window.location.origin; |
71 } | 90 } |
72 catch (e) | 91 catch (e) |
73 { | 92 { |
74 // Invalid URL, assume that it is first-party. | 93 // Invalid URL, assume that it is first-party. |
75 return true; | 94 return true; |
76 } | 95 } |
77 }, | 96 }, |
78 | 97 |
79 findSelectors: function(stylesheet, selectors, filters) | 98 findSelectors(stylesheet, selectors, filters) |
80 { | 99 { |
81 // Explicitly ignore third-party stylesheets to ensure consistent behavior | 100 // Explicitly ignore third-party stylesheets to ensure consistent behavior |
82 // between Firefox and Chrome. | 101 // between Firefox and Chrome. |
83 if (!this.isSameOrigin(stylesheet)) | 102 if (!this.isSameOrigin(stylesheet)) |
84 return; | 103 return; |
85 | 104 |
86 var rules = stylesheet.cssRules; | 105 let rules = stylesheet.cssRules; |
87 if (!rules) | 106 if (!rules) |
88 return; | 107 return; |
89 | 108 |
90 for (var i = 0; i < rules.length; i++) | 109 for (let rule of rules) |
91 { | 110 { |
92 var rule = rules[i]; | |
93 if (rule.type != rule.STYLE_RULE) | 111 if (rule.type != rule.STYLE_RULE) |
94 continue; | 112 continue; |
95 | 113 |
96 var style = this.stringifyStyle(rule.style); | 114 let style = this.stringifyStyle(rule.style); |
97 for (var j = 0; j < this.patterns.length; j++) | 115 for (let pattern of this.patterns) |
98 { | 116 { |
99 var pattern = this.patterns[j]; | |
100 if (pattern.regexp.test(style)) | 117 if (pattern.regexp.test(style)) |
101 { | 118 { |
102 var subSelectors = splitSelector(rule.selectorText); | 119 let subSelectors = splitSelector(rule.selectorText); |
103 for (var k = 0; k < subSelectors.length; k++) | 120 for (let subSelector of subSelectors) |
104 { | 121 { |
105 var subSelector = subSelectors[k]; | |
106 selectors.push(pattern.prefix + subSelector + pattern.suffix); | 122 selectors.push(pattern.prefix + subSelector + pattern.suffix); |
107 filters.push(pattern.text); | 123 filters.push(pattern.text); |
108 } | 124 } |
109 } | 125 } |
110 } | 126 } |
111 } | 127 } |
112 }, | 128 }, |
113 | 129 |
114 addSelectors: function(stylesheets) | 130 addSelectors(stylesheets) |
115 { | 131 { |
116 var selectors = []; | 132 let selectors = []; |
117 var filters = []; | 133 let filters = []; |
118 for (var i = 0; i < stylesheets.length; i++) | 134 for (let stylesheet of stylesheets) |
119 this.findSelectors(stylesheets[i], selectors, filters); | 135 this.findSelectors(stylesheet, selectors, filters); |
120 this.addSelectorsFunc(selectors, filters); | 136 this.addSelectorsFunc(selectors, filters); |
121 }, | 137 }, |
122 | 138 |
123 onLoad: function(event) | 139 onLoad(event) |
124 { | 140 { |
125 var stylesheet = event.target.sheet; | 141 let stylesheet = event.target.sheet; |
126 if (stylesheet) | 142 if (stylesheet) |
127 this.addSelectors([stylesheet]); | 143 this.addSelectors([stylesheet]); |
128 }, | 144 }, |
129 | 145 |
130 apply: function() | 146 apply() |
131 { | 147 { |
132 this.getFiltersFunc(function(patterns) | 148 this.getFiltersFunc(patterns => |
133 { | 149 { |
134 this.patterns = []; | 150 this.patterns = []; |
135 for (var i = 0; i < patterns.length; i++) | 151 for (let pattern of patterns) |
136 { | 152 { |
137 var pattern = patterns[i]; | 153 let match = propertySelectorRegExp.exec(pattern.selector); |
138 var match = propertySelectorRegExp.exec(pattern.selector); | |
139 if (!match) | 154 if (!match) |
140 continue; | 155 continue; |
141 | 156 |
142 var propertyExpression = match[2]; | 157 let propertyExpression = match[2]; |
143 var regexpString; | 158 let regexpString; |
144 if (propertyExpression.length >= 2 && propertyExpression[0] == "/" && | 159 if (propertyExpression.length >= 2 && propertyExpression[0] == "/" && |
145 propertyExpression[propertyExpression.length - 1] == "/") | 160 propertyExpression[propertyExpression.length - 1] == "/") |
| 161 { |
146 regexpString = propertyExpression.slice(1, -1) | 162 regexpString = propertyExpression.slice(1, -1) |
147 .replace("\\x7B ", "{").replace("\\x7D ", "}"); | 163 .replace("\\x7B ", "{").replace("\\x7D ", "}"); |
| 164 } |
148 else | 165 else |
149 regexpString = filterToRegExp(propertyExpression); | 166 regexpString = filterToRegExp(propertyExpression); |
150 | 167 |
151 this.patterns.push({ | 168 this.patterns.push({ |
152 text: pattern.text, | 169 text: pattern.text, |
153 regexp: new RegExp(regexpString, "i"), | 170 regexp: new RegExp(regexpString, "i"), |
154 prefix: pattern.selector.substr(0, match.index), | 171 prefix: pattern.selector.substr(0, match.index), |
155 suffix: pattern.selector.substr(match.index + match[0].length) | 172 suffix: pattern.selector.substr(match.index + match[0].length) |
156 }); | 173 }); |
157 } | 174 } |
158 | 175 |
159 if (this.patterns.length > 0) | 176 if (this.patterns.length > 0) |
160 { | 177 { |
161 var document = this.window.document; | 178 let {document} = this.window; |
162 this.addSelectors(document.styleSheets); | 179 this.addSelectors(document.styleSheets); |
163 document.addEventListener("load", this.onLoad.bind(this), true); | 180 document.addEventListener("load", this.onLoad.bind(this), true); |
164 } | 181 } |
165 }.bind(this)); | 182 }); |
166 } | 183 } |
167 }; | 184 }; |
OLD | NEW |