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

Side by Side Diff: lib/elemHide.js

Issue 6266581101314048: WIP: Have one global element hide stylesheet and inject the other ones per site (Closed)
Patch Set: Created July 27, 2014, 11:45 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | lib/elemHideHitRegistration.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * This file is part of Adblock Plus <http://adblockplus.org/>, 2 * This file is part of Adblock Plus <http://adblockplus.org/>,
3 * Copyright (C) 2006-2014 Eyeo GmbH 3 * Copyright (C) 2006-2014 Eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 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 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 * @type nsIURI 59 * @type nsIURI
60 */ 60 */
61 let styleURL = null; 61 let styleURL = null;
62 62
63 /** 63 /**
64 * Global stylesheet that should be loaded into content windows. 64 * Global stylesheet that should be loaded into content windows.
65 * @type nsIStyleSheet 65 * @type nsIStyleSheet
66 */ 66 */
67 let styleSheet = null; 67 let styleSheet = null;
68 68
69 // fixme
70 let filterByDomain = Object.create(null);
71
69 /** 72 /**
70 * Use new way of injecting styles per Window that exists since Firefox 33. 73 * Use new way of injecting styles per Window that exists since Firefox 33.
71 * @type boolean 74 * @type boolean
72 */ 75 */
73 let useNew = ('preloadSheet' in Utils.styleService); 76 let useNew = ('preloadSheet' in Utils.styleService);
74 77
75 /** 78 /**
76 * Element hiding component 79 * Element hiding component
77 * @class 80 * @class
78 */ 81 */
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 { 137 {
135 if (topic != "content-document-global-created") 138 if (topic != "content-document-global-created")
136 return; 139 return;
137 140
138 if (!Prefs.enabled) 141 if (!Prefs.enabled)
139 return; 142 return;
140 143
141 if (Policy.shouldNeverBlockWindow(subject)) 144 if (Policy.shouldNeverBlockWindow(subject))
142 return; 145 return;
143 146
147 dump(subject.document.documentURIObject.spec + "\n");
148 let domain = subject.document.documentURIObject.host;
149 if (domain.startsWith("www."))
150 domain = domain.substring(4);
151
152 dump("domain: " + domain + "\n"); // xxx is elemhide port or subdomain inses itive?
153
154 let list = Object.create(null);
155 for (let filter of filterByDomain[domain])
156 {
157 dump("filter: " + filter.text + "\n")
158 dump("key: " + keyByFilter[filter.text] + "\n")
159 list[keyByFilter[filter.text]] = filter;
160 }
161
162 if (filterByDomain[domain]) {
163 // XXX seems to stupid to use a file for this.
164 // Somehow get this to use a data url or similar
165 let styleFile = IO.resolveFilePath(Prefs.data_directory);
166 styleFile.append(domain + ".css");
167 styleURL = Services.io.newFileURI(styleFile).QueryInterface(Ci.nsIFileURL) ;
168
169 IO.writeToFile(styleURL.file, this._generateCSSContent(list, false), funct ion(e)
170 {
171 try
172 {
173 let utils = subject.QueryInterface(Ci.nsIInterfaceRequestor)
174 .getInterface(Ci.nsIDOMWindowUtils);
175 utils.loadSheet(styleURL, Ci.nsIStyleSheetService.USER_SHEET);
176 }
177 catch (e)
178 {
179 Cu.reportError(e);
180 }
181 });
182 }
183
144 try 184 try
145 { 185 {
146 let utils = subject.QueryInterface(Ci.nsIInterfaceRequestor) 186 let utils = subject.QueryInterface(Ci.nsIInterfaceRequestor)
147 .getInterface(Ci.nsIDOMWindowUtils); 187 .getInterface(Ci.nsIDOMWindowUtils);
148 utils.addSheet(styleSheet, Ci.nsIStyleSheetService.USER_SHEET); 188 utils.addSheet(styleSheet, Ci.nsIStyleSheetService.USER_SHEET);
149 } 189 }
150 catch (e) 190 catch (e)
151 { 191 {
152 Cu.reportError(e); 192 Cu.reportError(e);
153 } 193 }
154 }, 194 },
155 195
156 /** 196 /**
157 * Removes all known filters 197 * Removes all known filters
158 */ 198 */
159 clear: function() 199 clear: function()
160 { 200 {
161 filterByKey = Object.create(null); 201 filterByKey = Object.create(null);
162 keyByFilter = Object.create(null); 202 keyByFilter = Object.create(null);
163 knownExceptions = Object.create(null); 203 knownExceptions = Object.create(null);
164 exceptions = Object.create(null); 204 exceptions = Object.create(null);
205 filterByDomain = Object.create(null);
165 ElemHide.isDirty = false; 206 ElemHide.isDirty = false;
166 ElemHide.unapply(); 207 ElemHide.unapply();
167 }, 208 },
168 209
169 /** 210 /**
170 * Add a new element hiding filter 211 * Add a new element hiding filter
171 * @param {ElemHideFilter} filter 212 * @param {ElemHideFilter} filter
172 */ 213 */
173 add: function(filter) 214 add: function(filter)
174 { 215 {
175 if (filter instanceof ElemHideException) 216 if (filter instanceof ElemHideException)
176 { 217 {
177 if (filter.text in knownExceptions) 218 if (filter.text in knownExceptions)
178 return; 219 return;
179 220
180 let selector = filter.selector; 221 let selector = filter.selector;
181 if (!(selector in exceptions)) 222 if (!(selector in exceptions))
182 exceptions[selector] = []; 223 exceptions[selector] = [];
183 exceptions[selector].push(filter); 224 exceptions[selector].push(filter);
184 knownExceptions[filter.text] = true; 225 knownExceptions[filter.text] = true;
185 } 226 }
186 else 227 else
187 { 228 {
188 if (filter.text in keyByFilter) 229 if (filter.text in keyByFilter)
189 return; 230 return;
190 231
232 if (filter.selectorDomain && useNew)
233 {
234 let domains = filter.selectorDomain.split(",");
235
236 for (let domain of domains)
237 {
238 dump(domain + "\n");
239 if (filterByDomain[domain])
240 filterByDomain[domain].push(filter);
241 else
242 filterByDomain[domain] = [filter];
243 }
244 }
245
191 let key; 246 let key;
192 do { 247 do {
193 key = Math.random().toFixed(15).substr(5); 248 key = Math.random().toFixed(15).substr(5);
194 } while (key in filterByKey); 249 } while (key in filterByKey);
195 250
196 filterByKey[key] = filter; 251 filterByKey[key] = filter;
197 keyByFilter[filter.text] = key; 252 keyByFilter[filter.text] = key;
198 ElemHide.isDirty = true; 253 ElemHide.isDirty = true;
199 } 254 }
200 }, 255 },
(...skipping 13 matching lines...) Expand all
214 let index = list.indexOf(filter); 269 let index = list.indexOf(filter);
215 if (index >= 0) 270 if (index >= 0)
216 list.splice(index, 1); 271 list.splice(index, 1);
217 delete knownExceptions[filter.text]; 272 delete knownExceptions[filter.text];
218 } 273 }
219 else 274 else
220 { 275 {
221 if (!(filter.text in keyByFilter)) 276 if (!(filter.text in keyByFilter))
222 return; 277 return;
223 278
279 // if (filter.selectorDomain && useNew)
280 // {
281 // let filters = filterByDomain[filter.selectorDomain];
282 // if (Array.isArray(filters))
283 // filters.splice(filters.indexOf(filter), 1);
284 // else
285 // delete filterByDomain[filter.selectorDomain];
286 // }
287
224 let key = keyByFilter[filter.text]; 288 let key = keyByFilter[filter.text];
225 delete filterByKey[key]; 289 delete filterByKey[key];
226 delete keyByFilter[filter.text]; 290 delete keyByFilter[filter.text];
227 ElemHide.isDirty = true; 291 ElemHide.isDirty = true;
228 } 292 }
229 }, 293 },
230 294
231 /** 295 /**
232 * Checks whether an exception rule is registered for a filter on a particular 296 * Checks whether an exception rule is registered for a filter on a particular
233 * domain. 297 * domain.
234 */ 298 */
235 getException: function(/**Filter*/ filter, /**String*/ docDomain) /**ElemHideE xception*/ 299 getException: function(/**Filter*/ filter, /**String*/ docDomain) /**ElemHideE xception*/
236 { 300 {
237 let selector = filter.selector; 301 let selector = filter.selector;
238 if (!(filter.selector in exceptions)) 302 if (!(filter.selector in exceptions))
239 return null; 303 return null;
240 304
241 let list = exceptions[filter.selector]; 305 let list = exceptions[filter.selector];
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 else if (!Prefs.enabled && ElemHide.applied) 356 else if (!Prefs.enabled && ElemHide.applied)
293 { 357 {
294 ElemHide.unapply(); 358 ElemHide.unapply();
295 TimeLine.log("ElemHide.unapply() finished"); 359 TimeLine.log("ElemHide.unapply() finished");
296 } 360 }
297 361
298 TimeLine.leave("ElemHide.apply() done (no file changes)"); 362 TimeLine.leave("ElemHide.apply() done (no file changes)");
299 return; 363 return;
300 } 364 }
301 365
302 IO.writeToFile(styleURL.file, this._generateCSSContent(), function(e) 366 IO.writeToFile(styleURL.file, this._generateCSSContent(filterByKey, useNew), function(e)
303 { 367 {
304 TimeLine.enter("ElemHide.apply() write callback"); 368 TimeLine.enter("ElemHide.apply() write callback");
305 this._applying = false; 369 this._applying = false;
306 370
307 // _generateCSSContent is throwing NS_ERROR_NOT_AVAILABLE to indicate that 371 // _generateCSSContent is throwing NS_ERROR_NOT_AVAILABLE to indicate that
308 // there are no filters. If that exception is passed through XPCOM we will 372 // there are no filters. If that exception is passed through XPCOM we will
309 // see a proper exception here, otherwise a number. 373 // see a proper exception here, otherwise a number.
310 let noFilters = (e == Cr.NS_ERROR_NOT_AVAILABLE || (e && e.result == Cr.NS _ERROR_NOT_AVAILABLE)); 374 let noFilters = (e == Cr.NS_ERROR_NOT_AVAILABLE || (e && e.result == Cr.NS _ERROR_NOT_AVAILABLE));
311 if (noFilters) 375 if (noFilters)
312 { 376 {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 FilterNotifier.triggerListeners("elemhideupdate"); 413 FilterNotifier.triggerListeners("elemhideupdate");
350 } 414 }
351 TimeLine.leave("ElemHide.apply() write callback done"); 415 TimeLine.leave("ElemHide.apply() write callback done");
352 }.bind(this), "ElemHideWrite"); 416 }.bind(this), "ElemHideWrite");
353 417
354 this._applying = true; 418 this._applying = true;
355 419
356 TimeLine.leave("ElemHide.apply() done", "ElemHideWrite"); 420 TimeLine.leave("ElemHide.apply() done", "ElemHideWrite");
357 }, 421 },
358 422
359 _generateCSSContent: function() 423 _generateCSSContent: function(filters, onlyGlobal)
360 { 424 {
361 // Grouping selectors by domains 425 // Grouping selectors by domains
362 TimeLine.log("start grouping selectors"); 426 TimeLine.log("start grouping selectors");
363 let domains = Object.create(null); 427 let domains = Object.create(null);
364 let hasFilters = false; 428 let hasFilters = false;
365 for (let key in filterByKey) 429 for (let key in filters)
366 { 430 {
367 let filter = filterByKey[key]; 431 let filter = filters[key];
368 let domain = filter.selectorDomain || ""; 432 let domain = filter.selectorDomain || "";
369 433
434 if (onlyGlobal && domain)
435 continue;
436
370 let list; 437 let list;
371 if (domain in domains) 438 if (domain in domains)
372 list = domains[domain]; 439 list = domains[domain];
373 else 440 else
374 { 441 {
375 list = Object.create(null); 442 list = Object.create(null);
376 domains[domain] = list; 443 domains[domain] = list;
377 } 444 }
378 list[filter.selector] = key; 445 list[filter.selector] = key;
379 hasFilters = true; 446 hasFilters = true;
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
457 524
458 if (specificOnly && (!domains || domains[""])) 525 if (specificOnly && (!domains || domains[""]))
459 continue; 526 continue;
460 527
461 if (filter.isActiveOnDomain(domain) && !this.getException(filter, domain)) 528 if (filter.isActiveOnDomain(domain) && !this.getException(filter, domain))
462 result.push(filter.selector); 529 result.push(filter.selector);
463 } 530 }
464 return result; 531 return result;
465 } 532 }
466 }; 533 };
OLDNEW
« no previous file with comments | « no previous file | lib/elemHideHitRegistration.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld