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

Side by Side Diff: chrome/content/watcher.js

Issue 29331940: Issue 3225 - Make Diagnostics compatible with the upcoming Adblock Plus 2.7 release (Closed)
Patch Set: Created Dec. 4, 2015, 3:28 p.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 | chrome/content/watcher.xul » ('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 Source Code is subject to the terms of the Mozilla Public License 2 * This Source Code is subject to the terms of the Mozilla Public License
3 * version 2.0 (the "License"). You can obtain a copy of the License at 3 * version 2.0 (the "License"). You can obtain a copy of the License at
4 * http://mozilla.org/MPL/2.0/. 4 * http://mozilla.org/MPL/2.0/.
5 */ 5 */
6 6
7 const Cc = Components.classes; 7 const Cc = Components.classes;
8 const Ci = Components.interfaces; 8 const Ci = Components.interfaces;
9 const Cr = Components.results; 9 const Cr = Components.results;
10 const Cu = Components.utils; 10 const Cu = Components.utils;
11 11
12 Cu.import("resource://gre/modules/Services.jsm"); 12 Cu.import("resource://gre/modules/Services.jsm");
13 13
14 function abprequire(module) 14 function abprequire(module)
15 { 15 {
16 let result = {}; 16 let result = {};
17 result.wrappedJSObject = result; 17 result.wrappedJSObject = result;
18 Services.obs.notifyObservers(result, "adblockplus-require", module); 18 Services.obs.notifyObservers(result, "adblockplus-require", module);
19 return result.exports; 19 return result.exports;
20 } 20 }
21 21
22 let {Policy} = abprequire("contentPolicy"); 22 let {Policy} = abprequire("contentPolicy");
23 let {RequestNotifier} = abprequire("requestNotifier"); 23 let {RequestNotifier} = abprequire("requestNotifier");
24 let {Filter} = abprequire("filterClasses"); 24 let {Filter} = abprequire("filterClasses");
25 25
26 let policyGlobal = Cu.getGlobalForObject(Policy); 26 let origShouldAllow = Policy.shouldAllow;
27 let PolicyPrivate = null; 27 if (!origShouldAllow)
28
29 if ("PolicyImplementation" in policyGlobal) // ABP 2.1+ with scope separation
30 PolicyPrivate = policyGlobal.PolicyImplementation;
31 else if ("require" in policyGlobal) // ABP 2.1+ without scope sepa ration
32 PolicyPrivate = policyGlobal.require.scopes.contentPolicy.PolicyImplementation ;
33 else
34 window.close(); 28 window.close();
35 29
36 let origShouldLoad = PolicyPrivate.shouldLoad;
37 let origProcessNode = Policy.processNode;
38
39 let currentData = null; 30 let currentData = null;
40 let processingQueue = []; 31 let processingQueue = [];
41 let notifier = null; 32 let notifier = null;
42 33
43 // Randomize URI to work around bug 719376 34 // Randomize URI to work around bug 719376
44 let stringBundle = Services.strings.createBundle("chrome://abpwatcher/locale/glo bal.properties?" + Math.random()); 35 let stringBundle = Services.strings.createBundle("chrome://abpwatcher/locale/glo bal.properties?" + Math.random());
45 36
46 let clipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci. nsIClipboardHelper); 37 let clipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci. nsIClipboardHelper);
47 38
48 function init() 39 function init()
49 { 40 {
50 let list = document.getElementById("list"); 41 let list = document.getElementById("list");
51 list.view = treeView; 42 list.view = treeView;
52 list.focus(); 43 list.focus();
53 44
54 treeView.addObserver(updateProcessingTime); 45 treeView.addObserver(updateProcessingTime);
55 updateProcessingTime(treeView, "refresh"); 46 updateProcessingTime(treeView, "refresh");
56 47
57 // Make sure the tree view has correct filters 48 // Make sure the tree view has correct filters
58 document.getElementById("ignore-early").doCommand();
59 document.getElementById("filterText").doCommand(); 49 document.getElementById("filterText").doCommand();
60 50
61 notifier = new RequestNotifier(null, handleFilterHit); 51 notifier = new RequestNotifier(null, handleFilterHit);
Wladimir Palant 2015/12/07 12:17:55 I realized that I didn't test the Filter column -
62 52
63 PolicyPrivate.shouldLoad = replacementShouldLoad; 53 Policy.shouldAllow = replacementShouldAllow;
64 Policy.processNode = replacementProcessNode;
65 setInterval(processQueue, 200); 54 setInterval(processQueue, 200);
66 } 55 }
67 56
68 function E(id) 57 function E(id)
69 { 58 {
70 return document.getElementById(id); 59 return document.getElementById(id);
71 } 60 }
72 61
73 function replacementShouldLoad(contentType, contentLocation, requestOrigin, node , mimeTypeGuess, extra) 62 function replacementShouldAllow({contentType, location, frames, isPrivate})
74 { 63 {
75 let startTime = null; 64 let startTime = null;
76 try 65 try
77 { 66 {
78 currentData = {internal: false, earlyReturn: true, filters: []}; 67 currentData = {
68 filters: [],
69 type: contentType,
70 location: location,
71 frames: frames,
72 isPrivate: isPrivate
73 };
79 startTime = Date.now(); 74 startTime = Date.now();
80
81 if (contentLocation)
82 currentData.location = contentLocation.spec;
83 if (requestOrigin)
84 currentData.origin = requestOrigin.spec;
85
86 currentData.type = contentType;
87 } catch(e) {}
88
89 let ret;
90 try
91 {
92 ret = origShouldLoad.apply(this, arguments);
93 return ret;
94 }
95 finally
96 {
97 if (startTime !== null)
98 currentData.processingTime = (Date.now() - startTime);
99 currentData.result = (ret == Ci.nsIContentPolicy.ACCEPT);
100
101 processingQueue.push(currentData);
102 currentData = null;
103 }
104 }
105
106 function replacementProcessNode(wnd, node, contentType, location, collapse)
107 {
108 let startTime = null;
109 try
110 {
111 if (currentData && !("context" in currentData))
112 {
113 currentData.earlyReturn = false;
114 currentData.context = node;
115 currentData.window = wnd;
116 currentData.internalType = contentType;
117 if (location)
118 currentData.internalLocation = location.spec;
119 }
120 else
121 {
122 // shouldLoad wasn't called - this isn't being called by content policy
123 let locationString = (location instanceof Filter ? location.text : locatio n.spec);
124
125 currentData = {
126 internal: true,
127 earlyReturn: false,
128 filters: [],
129 location: locationString,
130 internalLocation: locationString,
131 context: node,
132 window: wnd,
133 type: contentType,
134 internalType: contentType
135 };
136 startTime = Date.now();
137 }
138 } 75 }
139 catch(e) 76 catch(e)
140 { 77 {
141 Cu.reportError(e); 78 Cu.reportError(e);
142 } 79 }
143 80
144 let ret; 81 let ret;
145 try 82 try
146 { 83 {
147 ret = origProcessNode.apply(this, arguments); 84 ret = origShouldAllow.apply(this, arguments);
148 return ret; 85 return ret;
149 } 86 }
150 finally 87 finally
151 { 88 {
152 if (startTime !== null) 89 if (startTime !== null)
153 { 90 {
154 currentData.processingTime = (Date.now() - startTime); 91 currentData.processingTime = (Date.now() - startTime);
155 currentData.result = (ret == true); 92 currentData.result = ret;
156 93
157 processingQueue.push(currentData); 94 processingQueue.push(currentData);
158 currentData = null; 95 currentData = null;
159 } 96 }
160 } 97 }
161 } 98 }
162 99
163 function destroy() 100 function destroy()
164 { 101 {
165 if (notifier) 102 if (notifier)
166 notifier.shutdown(); 103 notifier.shutdown();
167 if (origShouldLoad) 104 if (origShouldAllow)
168 PolicyPrivate.shouldLoad = origShouldLoad; 105 Policy.shouldAllow = origShouldAllow;
169 if (origProcessNode)
170 Policy.processNode = origProcessNode;
171 } 106 }
172 107
173 function handleFilterHit(wnd, node, data) 108 function handleFilterHit(data)
174 { 109 {
175 if (data.filter && currentData) 110 if (data.filter && currentData)
176 currentData.filters.push(data.filter.text); 111 currentData.filters.push(data.filter);
177 } 112 }
178 113
179 function processQueue() 114 function processQueue()
180 { 115 {
181 if (!processingQueue.length) 116 if (!processingQueue.length)
182 return; 117 return;
183 118
119 function stringify(value)
120 {
121 if (typeof value == "undefined" || value == null)
122 return "";
123 else
124 return String(value);
125 }
126
184 for each (let entry in processingQueue) 127 for each (let entry in processingQueue)
185 { 128 {
186 entry.cols = {}; 129 entry.cols = {
187 if (typeof entry.location != "undefined") 130 address: stringify(entry.location),
188 entry.cols.address = String(entry.location); 131 type: stringify(entry.type),
189 if (typeof entry.type != "undefined") 132 result: stringBundle.GetStringFromName(entry.result && entry.result.allow ? "decision.allow" : "decision.block"),
190 { 133 origin: stringify(entry.frames && entry.frames[0] && entry.frames[0].locat ion),
191 entry.cols.type = String(entry.type); 134 filters: stringify(entry.filters && entry.filters.join(", ")),
192 try { 135 time: stringify(entry.processingTime)
193 // Nasty hack: try to get type name from ABP 136 };
194 if (entry.type in Policy.localizedDescr)
195 entry.cols.type = String(Policy.localizedDescr[entry.type]);
196 } catch(e) {}
197 }
198 entry.cols.result = stringBundle.GetStringFromName(entry.result ? "decision. allow" : "decision.block");
199 if (typeof entry.context != "undefined")
200 entry.cols.context = (entry.context ? getNodeLabel(entry.context) : String (entry.context));
201 if (typeof entry.window != "undefined")
202 entry.cols.document = (entry.window ? getNodeLabel(entry.window) : String( entry.window));
203 if (typeof entry.origin != "undefined")
204 entry.cols.origin = String(entry.origin);
205 if (entry.filters.length)
206 entry.cols.filter = entry.filters.join(", ");
207 if (typeof entry.processingTime != "undefined")
208 entry.cols.time = String(entry.processingTime);
209
210 let additional = [];
211 if (entry.internal)
212 additional.push(stringBundle.GetStringFromName("additional.internalInvocat ion"));
213 if (typeof entry.internalType != "undefined" && entry.type != entry.internal Type)
214 {
215 let internalType = String(entry.internalType);
216 try {
217 // Nasty hack: try to get type name from ABP
218 if (entry.internalType in Policy.localizedDescr)
219 internalType = String(Policy.localizedDescr[entry.internalType]);
220 } catch(e) {}
221 additional.push(stringBundle.formatStringFromName("additional.typeChanged" , [internalType], 1));
222 }
223 if (typeof entry.internalLocation != "undefined" && entry.location != entry. internalLocation)
224 additional.push(stringBundle.formatStringFromName("additional.locationChan ged", [String(entry.internalLocation)], 1));
225
226 if (additional.length > 0)
227 entry.cols.additional = additional.join(", ");
228
229 treeView.add(entry); 137 treeView.add(entry);
230 } 138 }
231 139
232 processingQueue = []; 140 processingQueue = [];
233 } 141 }
234 142
235 function getNodeLabel(node)
236 {
237 try
238 {
239 if (node instanceof Ci.nsIDOMWindow)
240 return stringBundle.formatStringFromName("NodeLabel.window", [node.locatio n.href], 1);
241 if (node instanceof Ci.nsIDOMDocument)
242 return stringBundle.formatStringFromName("NodeLabel.document", [node.URL], 1);
243 else if (node instanceof Ci.nsIDOMXULElement)
244 return stringBundle.formatStringFromName("NodeLabel.xulElement", [node.tag Name], 1);
245 else if (node instanceof Ci.nsIDOMHTMLElement)
246 return stringBundle.formatStringFromName("NodeLabel.htmlElement", [node.ta gName], 1);
247 else if (node instanceof Ci.nsIDOMSVGElement)
248 return stringBundle.formatStringFromName("NodeLabel.svgElement", [node.tag Name], 1);
249 else if (node instanceof Ci.nsIDOMElement)
250 return stringBundle.formatStringFromName("NodeLabel.element", [node.tagNam e], 1);
251 else
252 return stringBundle.formatStringFromName("NodeLabel.unknown", [String(node )], 1);
253 }
254 catch (e)
255 {
256 Cu.reportError(e);
257 return stringBundle.formatStringFromName("NodeLabel.unknown", [""], 1);
258 }
259 }
260
261 function fillInTooltip(event) 143 function fillInTooltip(event)
262 { 144 {
263 let entry = treeView.getEntryAt(event.clientX, event.clientY); 145 let entry = treeView.getEntryAt(event.clientX, event.clientY);
264 if (!entry) 146 if (!entry)
265 return false; 147 return false;
266 148
267 let rows = document.getElementById("tooltip-rows"); 149 let rows = document.getElementById("tooltip-rows");
268 while (rows.firstChild) 150 while (rows.firstChild)
269 rows.removeChild(rows.firstChild); 151 rows.removeChild(rows.firstChild);
270 152
271 let cols = document.getElementById("list").getElementsByTagName("treecol"); 153 let cols = document.getElementById("list").getElementsByTagName("treecol");
272 for (let i = 0; i < cols.length; i++) 154 for (let i = 0; i < cols.length; i++)
273 { 155 {
274 let col = cols[i].id; 156 let col = cols[i].id;
275 if (col && col in entry.cols) 157 if (col && col in entry.cols)
276 { 158 {
277 let row = document.createElement("row"); 159 let row = document.createElement("row");
278 160
279 let label = document.createElement("description"); 161 let label = document.createElement("description");
280 label.setAttribute("class", "tooltip-label"); 162 label.setAttribute("class", "tooltip-label");
281 label.setAttribute("value", cols[i].getAttribute("label")); 163 label.setAttribute("value", cols[i].getAttribute("label"));
282 row.appendChild(label); 164 row.appendChild(label);
283 165
284 let value = document.createElement("vbox"); 166 let value = document.createElement("vbox");
285 setMultilineContent(value, entry.cols[col]); 167 let data = entry.cols[col];
168 if (col == "origin")
169 data = entry.frames.map(f => f.location).join("\n");
170 setMultilineContent(value, data);
286 row.appendChild(value); 171 row.appendChild(value);
287 172
288 rows.appendChild(row); 173 rows.appendChild(row);
289 } 174 }
290 } 175 }
291 176
292 return true; 177 return true;
293 } 178 }
294 179
295 function updateContextMenu(event) 180 function updateContextMenu(event)
(...skipping 14 matching lines...) Expand all
310 clipboardHelper.copyString(String(entry.location)); 195 clipboardHelper.copyString(String(entry.location));
311 } 196 }
312 197
313 function copyFilters() 198 function copyFilters()
314 { 199 {
315 let entry = treeView.getCurrentEntry(); 200 let entry = treeView.getCurrentEntry();
316 if (entry && entry.filters.length) 201 if (entry && entry.filters.length)
317 clipboardHelper.copyString(entry.filters.join("\n")); 202 clipboardHelper.copyString(entry.filters.join("\n"));
318 } 203 }
319 204
320 function setMultilineContent(box, text) { 205 function setMultilineContent(box, text)
321 // The following is sufficient in Gecko 1.9 but Gecko 1.8 fails on multiline 206 {
322 // text fields in tooltips 207 let lines = text.split(/\n+/);
323 // box.textContent = text.replace(/\S{80}(?=\S)/g, "$& "); 208 for (let line of lines)
324 209 {
325 for (let i = 0; i < text.length; i += 80) {
326 let description = document.createElement("description"); 210 let description = document.createElement("description");
327 description.setAttribute("value", text.substr(i, 80)); 211 description.textContent = line.replace(/\S{80}(?=\S)/g, "$& ");
328 box.appendChild(description); 212 box.appendChild(description);
329 } 213 }
330 } 214 }
331 215
332 var totalProcessingTime = 0; 216 var totalProcessingTime = 0;
333 function updateProcessingTime(view, operation, entry) 217 function updateProcessingTime(view, operation, entry)
334 { 218 {
335 if (operation == "add") 219 if (operation == "add")
336 totalProcessingTime += entry.processingTime; 220 totalProcessingTime += entry.processingTime;
337 else { 221 else {
338 totalProcessingTime = 0; 222 totalProcessingTime = 0;
339 for each (let entry in view.displayedItems) 223 for each (let entry in view.displayedItems)
340 totalProcessingTime += entry.processingTime; 224 totalProcessingTime += entry.processingTime;
341 } 225 }
342 226
343 let numItems = view.displayedItems.length; 227 let numItems = view.displayedItems.length;
344 228
345 let summary = document.getElementById("summary"); 229 let summary = document.getElementById("summary");
346 let template = summary.getAttribute("_template"); 230 let template = summary.getAttribute("_template");
347 summary.textContent = template.replace(/\*NUMITEMS\*/g, numItems).replace(/\*T IME\*/, (totalProcessingTime / 1000).toFixed(3)); 231 summary.textContent = template.replace(/\*NUMITEMS\*/g, numItems).replace(/\*T IME\*/, (totalProcessingTime / 1000).toFixed(3));
348 } 232 }
349 233
350 var treeView = { 234 var treeView = {
351 currentItems: [], 235 currentItems: [],
352 displayedItems: [], 236 displayedItems: [],
353 _ignoreEarlyReturns: false,
354 _filterString: "", 237 _filterString: "",
355 _sortColumn: null, 238 _sortColumn: null,
356 _sortDirection: null, 239 _sortDirection: null,
357 boxObject: null, 240 boxObject: null,
358 atoms: {}, 241 atoms: {},
359 observers: [], 242 observers: [],
360 243
361 // 244 //
362 // nsISupports implementation 245 // nsISupports implementation
363 // 246 //
(...skipping 15 matching lines...) Expand all
379 selection: null, 262 selection: null,
380 263
381 setTree: function(boxObject) 264 setTree: function(boxObject)
382 { 265 {
383 if (!boxObject) 266 if (!boxObject)
384 return; 267 return;
385 268
386 this.boxObject = boxObject; 269 this.boxObject = boxObject;
387 270
388 let atomService = Cc["@mozilla.org/atom-service;1"].getService(Ci.nsIAtomSer vice); 271 let atomService = Cc["@mozilla.org/atom-service;1"].getService(Ci.nsIAtomSer vice);
389 for each (let col in ["address", "type", "result", "context", "document", "o rigin", "additional", "filter", "time"]) 272 for each (let col in ["address", "type", "result", "origin", "filter", "time "])
390 { 273 {
391 let atomStr = "col-" + col; 274 let atomStr = "col-" + col;
392 this.atoms[atomStr] = atomService.getAtom(atomStr); 275 this.atoms[atomStr] = atomService.getAtom(atomStr);
393 } 276 }
394 for each (let flag in ["selected", "blocked"]) 277 for each (let flag in ["selected", "blocked"])
395 { 278 {
396 let atomStr = flag + "-true"; 279 let atomStr = flag + "-true";
397 this.atoms[atomStr] = atomService.getAtom(atomStr); 280 this.atoms[atomStr] = atomService.getAtom(atomStr);
398 281
399 atomStr = flag + "-false"; 282 atomStr = flag + "-false";
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 }, 337 },
455 338
456 getRowProperties: function(row, properties) 339 getRowProperties: function(row, properties)
457 { 340 {
458 if (row < 0 || row >= this.displayedItems.length) 341 if (row < 0 || row >= this.displayedItems.length)
459 return ""; 342 return "";
460 343
461 let entry = this.displayedItems[row]; 344 let entry = this.displayedItems[row];
462 return this.generateProperties([ 345 return this.generateProperties([
463 "selected-" + this.selection.isSelected(row), 346 "selected-" + this.selection.isSelected(row),
464 "blocked-" + !entry.result 347 "blocked-" + !(entry.result && entry.result.allow)
465 ], properties); 348 ], properties);
466 }, 349 },
467 350
468 getCellProperties: function(row, col, properties) 351 getCellProperties: function(row, col, properties)
469 { 352 {
470 return this.getRowProperties(row, properties) + " " + this.getColumnProperti es(col, properties); 353 return this.getRowProperties(row, properties) + " " + this.getColumnProperti es(col, properties);
471 }, 354 },
472 355
473 cycleHeader: function(col) 356 cycleHeader: function(col)
474 { 357 {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 cycleCell: function() {}, 407 cycleCell: function() {},
525 performAction: function() {}, 408 performAction: function() {},
526 performActionOnRow: function() {}, 409 performActionOnRow: function() {},
527 performActionOnCell: function() {}, 410 performActionOnCell: function() {},
528 selectionChanged: function() {}, 411 selectionChanged: function() {},
529 412
530 // 413 //
531 // Custom methods 414 // Custom methods
532 // 415 //
533 416
534 get ignoreEarlyReturns()
535 {
536 return this._ignoreEarlyReturns;
537 },
538 set ignoreEarlyReturns(value)
539 {
540 this._ignoreEarlyReturns = value;
541 this.refilter();
542 },
543
544 get filterString() 417 get filterString()
545 { 418 {
546 return this._filterString; 419 return this._filterString;
547 }, 420 },
548 set filterString(value) 421 set filterString(value)
549 { 422 {
550 this._filterString = value.toLowerCase(); 423 this._filterString = value.toLowerCase();
551 this.refilter(); 424 this.refilter();
552 }, 425 },
553 426
554 filter: function(entry) 427 filter: function(entry)
555 { 428 {
556 if (this._ignoreEarlyReturns && entry.earlyReturn)
557 return false;
558
559 if (this._filterString) 429 if (this._filterString)
560 { 430 {
561 let foundMatch = false; 431 let foundMatch = false;
562 for each (let label in entry.cols) 432 for each (let label in entry.cols)
563 if (label.toLowerCase().indexOf(this._filterString) >= 0) 433 if (label.toLowerCase().indexOf(this._filterString) >= 0)
564 foundMatch = true; 434 foundMatch = true;
565 435
566 if (!foundMatch) 436 if (!foundMatch)
567 return false; 437 return false;
568 } 438 }
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
678 for (let i = 0; i < this.observers.length; i++) 548 for (let i = 0; i < this.observers.length; i++)
679 if (this.observers[i] == observer) 549 if (this.observers[i] == observer)
680 this.observers.splice(i--, 1); 550 this.observers.splice(i--, 1);
681 }, 551 },
682 notifyObservers: function(operation, entry) 552 notifyObservers: function(operation, entry)
683 { 553 {
684 for each (let observer in this.observers) 554 for each (let observer in this.observers)
685 observer(this, operation, entry); 555 observer(this, operation, entry);
686 } 556 }
687 }; 557 };
OLDNEW
« no previous file with comments | « no previous file | chrome/content/watcher.xul » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld