| Index: chrome/content/watcher.js |
| =================================================================== |
| --- a/chrome/content/watcher.js |
| +++ b/chrome/content/watcher.js |
| @@ -18,29 +18,20 @@ function abprequire(module) |
| Services.obs.notifyObservers(result, "adblockplus-require", module); |
| return result.exports; |
| } |
| let {Policy} = abprequire("contentPolicy"); |
| let {RequestNotifier} = abprequire("requestNotifier"); |
| let {Filter} = abprequire("filterClasses"); |
| -let policyGlobal = Cu.getGlobalForObject(Policy); |
| -let PolicyPrivate = null; |
| - |
| -if ("PolicyImplementation" in policyGlobal) // ABP 2.1+ with scope separation |
| - PolicyPrivate = policyGlobal.PolicyImplementation; |
| -else if ("require" in policyGlobal) // ABP 2.1+ without scope separation |
| - PolicyPrivate = policyGlobal.require.scopes.contentPolicy.PolicyImplementation; |
| -else |
| +let origShouldAllow = Policy.shouldAllow; |
| +if (!origShouldAllow) |
| window.close(); |
| -let origShouldLoad = PolicyPrivate.shouldLoad; |
| -let origProcessNode = Policy.processNode; |
| - |
| let currentData = null; |
| let processingQueue = []; |
| let notifier = null; |
| // Randomize URI to work around bug 719376 |
| let stringBundle = Services.strings.createBundle("chrome://abpwatcher/locale/global.properties?" + Math.random()); |
| let clipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(Ci.nsIClipboardHelper); |
| @@ -50,219 +41,110 @@ function init() |
| let list = document.getElementById("list"); |
| list.view = treeView; |
| list.focus(); |
| treeView.addObserver(updateProcessingTime); |
| updateProcessingTime(treeView, "refresh"); |
| // Make sure the tree view has correct filters |
| - document.getElementById("ignore-early").doCommand(); |
| document.getElementById("filterText").doCommand(); |
| notifier = new RequestNotifier(null, handleFilterHit); |
|
Wladimir Palant
2015/12/07 12:17:55
I realized that I didn't test the Filter column -
|
| - PolicyPrivate.shouldLoad = replacementShouldLoad; |
| - Policy.processNode = replacementProcessNode; |
| + Policy.shouldAllow = replacementShouldAllow; |
| setInterval(processQueue, 200); |
| } |
| function E(id) |
| { |
| return document.getElementById(id); |
| } |
| -function replacementShouldLoad(contentType, contentLocation, requestOrigin, node, mimeTypeGuess, extra) |
| +function replacementShouldAllow({contentType, location, frames, isPrivate}) |
| { |
| let startTime = null; |
| try |
| { |
| - currentData = {internal: false, earlyReturn: true, filters: []}; |
| + currentData = { |
| + filters: [], |
| + type: contentType, |
| + location: location, |
| + frames: frames, |
| + isPrivate: isPrivate |
| + }; |
| startTime = Date.now(); |
| - |
| - if (contentLocation) |
| - currentData.location = contentLocation.spec; |
| - if (requestOrigin) |
| - currentData.origin = requestOrigin.spec; |
| - |
| - currentData.type = contentType; |
| - } catch(e) {} |
| - |
| - let ret; |
| - try |
| - { |
| - ret = origShouldLoad.apply(this, arguments); |
| - return ret; |
| - } |
| - finally |
| - { |
| - if (startTime !== null) |
| - currentData.processingTime = (Date.now() - startTime); |
| - currentData.result = (ret == Ci.nsIContentPolicy.ACCEPT); |
| - |
| - processingQueue.push(currentData); |
| - currentData = null; |
| - } |
| -} |
| - |
| -function replacementProcessNode(wnd, node, contentType, location, collapse) |
| -{ |
| - let startTime = null; |
| - try |
| - { |
| - if (currentData && !("context" in currentData)) |
| - { |
| - currentData.earlyReturn = false; |
| - currentData.context = node; |
| - currentData.window = wnd; |
| - currentData.internalType = contentType; |
| - if (location) |
| - currentData.internalLocation = location.spec; |
| - } |
| - else |
| - { |
| - // shouldLoad wasn't called - this isn't being called by content policy |
| - let locationString = (location instanceof Filter ? location.text : location.spec); |
| - |
| - currentData = { |
| - internal: true, |
| - earlyReturn: false, |
| - filters: [], |
| - location: locationString, |
| - internalLocation: locationString, |
| - context: node, |
| - window: wnd, |
| - type: contentType, |
| - internalType: contentType |
| - }; |
| - startTime = Date.now(); |
| - } |
| } |
| catch(e) |
| { |
| Cu.reportError(e); |
| } |
| let ret; |
| try |
| { |
| - ret = origProcessNode.apply(this, arguments); |
| + ret = origShouldAllow.apply(this, arguments); |
| return ret; |
| } |
| finally |
| { |
| if (startTime !== null) |
| { |
| currentData.processingTime = (Date.now() - startTime); |
| - currentData.result = (ret == true); |
| + currentData.result = ret; |
| processingQueue.push(currentData); |
| currentData = null; |
| } |
| } |
| } |
| function destroy() |
| { |
| if (notifier) |
| notifier.shutdown(); |
| - if (origShouldLoad) |
| - PolicyPrivate.shouldLoad = origShouldLoad; |
| - if (origProcessNode) |
| - Policy.processNode = origProcessNode; |
| + if (origShouldAllow) |
| + Policy.shouldAllow = origShouldAllow; |
| } |
| -function handleFilterHit(wnd, node, data) |
| +function handleFilterHit(data) |
| { |
| if (data.filter && currentData) |
| - currentData.filters.push(data.filter.text); |
| + currentData.filters.push(data.filter); |
| } |
| function processQueue() |
| { |
| if (!processingQueue.length) |
| return; |
| + function stringify(value) |
| + { |
| + if (typeof value == "undefined" || value == null) |
| + return ""; |
| + else |
| + return String(value); |
| + } |
| + |
| for each (let entry in processingQueue) |
| { |
| - entry.cols = {}; |
| - if (typeof entry.location != "undefined") |
| - entry.cols.address = String(entry.location); |
| - if (typeof entry.type != "undefined") |
| - { |
| - entry.cols.type = String(entry.type); |
| - try { |
| - // Nasty hack: try to get type name from ABP |
| - if (entry.type in Policy.localizedDescr) |
| - entry.cols.type = String(Policy.localizedDescr[entry.type]); |
| - } catch(e) {} |
| - } |
| - entry.cols.result = stringBundle.GetStringFromName(entry.result ? "decision.allow" : "decision.block"); |
| - if (typeof entry.context != "undefined") |
| - entry.cols.context = (entry.context ? getNodeLabel(entry.context) : String(entry.context)); |
| - if (typeof entry.window != "undefined") |
| - entry.cols.document = (entry.window ? getNodeLabel(entry.window) : String(entry.window)); |
| - if (typeof entry.origin != "undefined") |
| - entry.cols.origin = String(entry.origin); |
| - if (entry.filters.length) |
| - entry.cols.filter = entry.filters.join(", "); |
| - if (typeof entry.processingTime != "undefined") |
| - entry.cols.time = String(entry.processingTime); |
| - |
| - let additional = []; |
| - if (entry.internal) |
| - additional.push(stringBundle.GetStringFromName("additional.internalInvocation")); |
| - if (typeof entry.internalType != "undefined" && entry.type != entry.internalType) |
| - { |
| - let internalType = String(entry.internalType); |
| - try { |
| - // Nasty hack: try to get type name from ABP |
| - if (entry.internalType in Policy.localizedDescr) |
| - internalType = String(Policy.localizedDescr[entry.internalType]); |
| - } catch(e) {} |
| - additional.push(stringBundle.formatStringFromName("additional.typeChanged", [internalType], 1)); |
| - } |
| - if (typeof entry.internalLocation != "undefined" && entry.location != entry.internalLocation) |
| - additional.push(stringBundle.formatStringFromName("additional.locationChanged", [String(entry.internalLocation)], 1)); |
| - |
| - if (additional.length > 0) |
| - entry.cols.additional = additional.join(", "); |
| - |
| + entry.cols = { |
| + address: stringify(entry.location), |
| + type: stringify(entry.type), |
| + result: stringBundle.GetStringFromName(entry.result && entry.result.allow ? "decision.allow" : "decision.block"), |
| + origin: stringify(entry.frames && entry.frames[0] && entry.frames[0].location), |
| + filters: stringify(entry.filters && entry.filters.join(", ")), |
| + time: stringify(entry.processingTime) |
| + }; |
| treeView.add(entry); |
| } |
| processingQueue = []; |
| } |
| -function getNodeLabel(node) |
| -{ |
| - try |
| - { |
| - if (node instanceof Ci.nsIDOMWindow) |
| - return stringBundle.formatStringFromName("NodeLabel.window", [node.location.href], 1); |
| - if (node instanceof Ci.nsIDOMDocument) |
| - return stringBundle.formatStringFromName("NodeLabel.document", [node.URL], 1); |
| - else if (node instanceof Ci.nsIDOMXULElement) |
| - return stringBundle.formatStringFromName("NodeLabel.xulElement", [node.tagName], 1); |
| - else if (node instanceof Ci.nsIDOMHTMLElement) |
| - return stringBundle.formatStringFromName("NodeLabel.htmlElement", [node.tagName], 1); |
| - else if (node instanceof Ci.nsIDOMSVGElement) |
| - return stringBundle.formatStringFromName("NodeLabel.svgElement", [node.tagName], 1); |
| - else if (node instanceof Ci.nsIDOMElement) |
| - return stringBundle.formatStringFromName("NodeLabel.element", [node.tagName], 1); |
| - else |
| - return stringBundle.formatStringFromName("NodeLabel.unknown", [String(node)], 1); |
| - } |
| - catch (e) |
| - { |
| - Cu.reportError(e); |
| - return stringBundle.formatStringFromName("NodeLabel.unknown", [""], 1); |
| - } |
| -} |
| - |
| function fillInTooltip(event) |
| { |
| let entry = treeView.getEntryAt(event.clientX, event.clientY); |
| if (!entry) |
| return false; |
| let rows = document.getElementById("tooltip-rows"); |
| while (rows.firstChild) |
| @@ -277,17 +159,20 @@ function fillInTooltip(event) |
| let row = document.createElement("row"); |
| let label = document.createElement("description"); |
| label.setAttribute("class", "tooltip-label"); |
| label.setAttribute("value", cols[i].getAttribute("label")); |
| row.appendChild(label); |
| let value = document.createElement("vbox"); |
| - setMultilineContent(value, entry.cols[col]); |
| + let data = entry.cols[col]; |
| + if (col == "origin") |
| + data = entry.frames.map(f => f.location).join("\n"); |
| + setMultilineContent(value, data); |
| row.appendChild(value); |
| rows.appendChild(row); |
| } |
| } |
| return true; |
| } |
| @@ -312,24 +197,23 @@ function copyLocation() |
| function copyFilters() |
| { |
| let entry = treeView.getCurrentEntry(); |
| if (entry && entry.filters.length) |
| clipboardHelper.copyString(entry.filters.join("\n")); |
| } |
| -function setMultilineContent(box, text) { |
| - // The following is sufficient in Gecko 1.9 but Gecko 1.8 fails on multiline |
| - // text fields in tooltips |
| - // box.textContent = text.replace(/\S{80}(?=\S)/g, "$& "); |
| - |
| - for (let i = 0; i < text.length; i += 80) { |
| +function setMultilineContent(box, text) |
| +{ |
| + let lines = text.split(/\n+/); |
| + for (let line of lines) |
| + { |
| let description = document.createElement("description"); |
| - description.setAttribute("value", text.substr(i, 80)); |
| + description.textContent = line.replace(/\S{80}(?=\S)/g, "$& "); |
| box.appendChild(description); |
| } |
| } |
| var totalProcessingTime = 0; |
| function updateProcessingTime(view, operation, entry) |
| { |
| if (operation == "add") |
| @@ -345,17 +229,16 @@ function updateProcessingTime(view, oper |
| let summary = document.getElementById("summary"); |
| let template = summary.getAttribute("_template"); |
| summary.textContent = template.replace(/\*NUMITEMS\*/g, numItems).replace(/\*TIME\*/, (totalProcessingTime / 1000).toFixed(3)); |
| } |
| var treeView = { |
| currentItems: [], |
| displayedItems: [], |
| - _ignoreEarlyReturns: false, |
| _filterString: "", |
| _sortColumn: null, |
| _sortDirection: null, |
| boxObject: null, |
| atoms: {}, |
| observers: [], |
| // |
| @@ -381,17 +264,17 @@ var treeView = { |
| setTree: function(boxObject) |
| { |
| if (!boxObject) |
| return; |
| this.boxObject = boxObject; |
| let atomService = Cc["@mozilla.org/atom-service;1"].getService(Ci.nsIAtomService); |
| - for each (let col in ["address", "type", "result", "context", "document", "origin", "additional", "filter", "time"]) |
| + for each (let col in ["address", "type", "result", "origin", "filter", "time"]) |
| { |
| let atomStr = "col-" + col; |
| this.atoms[atomStr] = atomService.getAtom(atomStr); |
| } |
| for each (let flag in ["selected", "blocked"]) |
| { |
| let atomStr = flag + "-true"; |
| this.atoms[atomStr] = atomService.getAtom(atomStr); |
| @@ -456,17 +339,17 @@ var treeView = { |
| getRowProperties: function(row, properties) |
| { |
| if (row < 0 || row >= this.displayedItems.length) |
| return ""; |
| let entry = this.displayedItems[row]; |
| return this.generateProperties([ |
| "selected-" + this.selection.isSelected(row), |
| - "blocked-" + !entry.result |
| + "blocked-" + !(entry.result && entry.result.allow) |
| ], properties); |
| }, |
| getCellProperties: function(row, col, properties) |
| { |
| return this.getRowProperties(row, properties) + " " + this.getColumnProperties(col, properties); |
| }, |
| @@ -526,41 +409,28 @@ var treeView = { |
| performActionOnRow: function() {}, |
| performActionOnCell: function() {}, |
| selectionChanged: function() {}, |
| // |
| // Custom methods |
| // |
| - get ignoreEarlyReturns() |
| - { |
| - return this._ignoreEarlyReturns; |
| - }, |
| - set ignoreEarlyReturns(value) |
| - { |
| - this._ignoreEarlyReturns = value; |
| - this.refilter(); |
| - }, |
| - |
| get filterString() |
| { |
| return this._filterString; |
| }, |
| set filterString(value) |
| { |
| this._filterString = value.toLowerCase(); |
| this.refilter(); |
| }, |
| filter: function(entry) |
| { |
| - if (this._ignoreEarlyReturns && entry.earlyReturn) |
| - return false; |
| - |
| if (this._filterString) |
| { |
| let foundMatch = false; |
| for each (let label in entry.cols) |
| if (label.toLowerCase().indexOf(this._filterString) >= 0) |
| foundMatch = true; |
| if (!foundMatch) |