| Index: chrome/content/ui/sidebar.js |
| =================================================================== |
| --- a/chrome/content/ui/sidebar.js |
| +++ b/chrome/content/ui/sidebar.js |
| @@ -109,16 +109,24 @@ function init() { |
| types.set(type, Utils.getString("type_label_" + type.toLowerCase())); |
| } |
| // To be called for a detached window when the main window has been closed |
| function mainUnload() { |
| parent.close(); |
| } |
| +function getFilter(item) |
| +{ |
| + if ("filter" in item && item.filter) |
|
tschuster
2015/11/12 15:32:05
"filter" in item is not strictly necessary.
Wladimir Palant
2015/11/12 15:46:55
Yes, I know but I didn't feel like changing that.
|
| + return Filter.fromText(item.filter); |
| + else |
| + return null; |
| +} |
| + |
| // To be called on unload |
| function cleanUp() { |
| flasher.stop(); |
| requestNotifier.shutdown(); |
| FilterNotifier.removeListener(reloadDisabledFilters); |
| Prefs.removeListener(onPrefChange); |
| E("list").view = null; |
| @@ -195,21 +203,27 @@ function onSelectionChange() { |
| } |
| function handleLocationChange() |
| { |
| if (requestNotifier) |
| requestNotifier.shutdown(); |
| treeView.clearData(); |
| + |
| + let {getBrowser, addBrowserLocationListener} = require("appSupport"); |
| + let browser = getBrowser(mainWin); |
| + if ("selectedBrowser" in browser) |
| + browser = browser.selectedBrowser; |
| + let outerWindowID = browser.outerWindowID; |
| treeView.itemToSelect = RequestNotifier.getSelection(window.content); |
| - requestNotifier = new RequestNotifier(window.content, function(wnd, node, item, scanComplete) |
| + requestNotifier = new RequestNotifier(outerWindowID, function(item, scanComplete) |
| { |
| if (item) |
| - treeView.addItem(node, item, scanComplete); |
| + treeView.addItem(item, scanComplete); |
| }); |
| cacheStorage = null; |
| } |
| // Fills a box with text splitting it up into multiple lines if necessary |
| function setMultilineContent(box, text, noRemove) |
| { |
| if (!noRemove) |
| @@ -240,17 +254,17 @@ function fillInTooltip(e) { |
| item = treeView.getItemAt(e.clientX, e.clientY); |
| if (!item) |
| { |
| e.preventDefault(); |
| return; |
| } |
| - let filter = ("filter" in item && item.filter ? item.filter : null); |
| + let filter = getFilter(item); |
| let size = ("tooltip" in item ? null : getItemSize(item)); |
| let subscriptions = (filter ? filter.subscriptions.filter(function(subscription) { return !subscription.disabled; }) : []); |
| E("tooltipDummy").hidden = !("tooltip" in item); |
| E("tooltipAddressRow").hidden = ("tooltip" in item); |
| E("tooltipTypeRow").hidden = ("tooltip" in item); |
| E("tooltipSizeRow").hidden = !size; |
| E("tooltipDocDomainRow").hidden = ("tooltip" in item || !item.docDomain); |
| @@ -296,17 +310,17 @@ function fillInTooltip(e) { |
| sourceElement.removeChild(sourceElement.firstChild); |
| for (let i = 0; i < subscriptions.length; i++) |
| setMultilineContent(sourceElement, subscriptions[i].title, true); |
| } |
| } |
| var showPreview = Prefs.previewimages && !("tooltip" in item); |
| showPreview = showPreview && item.type == "IMAGE"; |
| - showPreview = showPreview && (!item.filter || item.filter.disabled || item.filter instanceof WhitelistFilter); |
| + showPreview = showPreview && (!filter || filter.disabled || filter instanceof WhitelistFilter); |
| E("tooltipPreviewBox").hidden = true; |
| if (showPreview) |
| { |
| if (!cacheStorage) |
| { |
| let {Services} = Cu.import("resource://gre/modules/Services.jsm", null); |
| // Cache v2 API is enabled by default starting with Gecko 32 |
| if (Services.vc.compare(Utils.platformVersion, "32.0a1") >= 0) |
| @@ -389,19 +403,19 @@ function fillInContext(/**Event*/ e) |
| } |
| if (!item || ("tooltip" in item && !("filter" in item))) |
| return false; |
| E("contextDisableFilter").hidden = true; |
| E("contextEnableFilter").hidden = true; |
| E("contextDisableOnSite").hidden = true; |
| - if ("filter" in item && item.filter) |
| + let filter = getFilter(item); |
| + if (filter) |
| { |
| - let filter = item.filter; |
| let menuItem = E(filter.disabled ? "contextEnableFilter" : "contextDisableFilter"); |
| menuItem.setAttribute("label", menuItem.getAttribute("labeltempl").replace(/\?1\?/, filter.text)); |
| menuItem.hidden = false; |
| if (filter instanceof ActiveFilter && !filter.disabled && filter.subscriptions.length && !filter.subscriptions.some(subscription => !(subscription instanceof SpecialSubscription))) |
| { |
| let domain = null; |
| try { |
| @@ -412,38 +426,39 @@ function fillInContext(/**Event*/ e) |
| { |
| menuItem = E("contextDisableOnSite"); |
| menuItem.setAttribute("label", menuItem.getAttribute("labeltempl").replace(/\?1\?/, domain)); |
| menuItem.hidden = false; |
| } |
| } |
| } |
| - E("contextWhitelist").hidden = ("tooltip" in item || !item.filter || item.filter.disabled || item.filter instanceof WhitelistFilter || item.type == "ELEMHIDE"); |
| + E("contextWhitelist").hidden = ("tooltip" in item || !filter || filter.disabled || filter instanceof WhitelistFilter || item.type == "ELEMHIDE"); |
| E("contextBlock").hidden = !E("contextWhitelist").hidden; |
| - E("contextBlock").setAttribute("disabled", "filter" in item && item.filter && !item.filter.disabled); |
| - E("contextEditFilter").setAttribute("disabled", !("filter" in item && item.filter)); |
| + E("contextBlock").setAttribute("disabled", filter && !filter.disabled); |
| + E("contextEditFilter").setAttribute("disabled", !filter); |
| E("contextOpen").setAttribute("disabled", "tooltip" in item || item.type == "ELEMHIDE"); |
| - E("contextFlash").setAttribute("disabled", "tooltip" in item || !(item.type in visual) || (item.filter && !item.filter.disabled && !(item.filter instanceof WhitelistFilter))); |
| - E("contextCopyFilter").setAttribute("disabled", !allItems.some(function(item) {return "filter" in item && item.filter})); |
| + E("contextFlash").setAttribute("disabled", "tooltip" in item || !(item.type in visual) || (filter && !filter.disabled && !(filter instanceof WhitelistFilter))); |
| + E("contextCopyFilter").setAttribute("disabled", !allItems.some(getFilter)); |
| return true; |
| } |
| /** |
| * Processed mouse clicks on the item list. |
| * @param {Event} event |
| */ |
| function handleClick(event) |
| { |
| let item = treeView.getItemAt(event.clientX, event.clientY); |
| if (event.button == 0 && treeView.getColumnAt(event.clientX, event.clientY) == "state") |
| { |
| - if (item.filter) |
| - enableFilter(item.filter, item.filter.disabled); |
| + let filter = getFilter(item); |
| + if (filter) |
| + enableFilter(filter, filter.disabled); |
| event.preventDefault(); |
| } |
| else if (event.button == 1) |
| { |
| openInTab(item, event); |
| event.preventDefault(); |
| } |
| } |
| @@ -473,51 +488,49 @@ function openInTab(item, /**Event*/ even |
| } |
| } |
| function doBlock() { |
| var item = treeView.getSelectedItem(); |
| if (!item || item.type == "ELEMHIDE") |
| return; |
| - var filter = null; |
| - if (item.filter && !item.filter.disabled) |
| - filter = item.filter; |
| - |
| - if (filter && filter instanceof WhitelistFilter) |
| + var filter = getFilter(item); |
| + if (filter && !filter.disabled && filter instanceof WhitelistFilter) |
| return; |
| openDialog("chrome://adblockplus/content/ui/composer.xul", "_blank", "chrome,centerscreen,resizable,dialog=no,dependent", item.nodes, item.orig); |
| } |
| function editFilter() |
| { |
| var item = treeView.getSelectedItem(); |
| if (treeView.data && !treeView.data.length) |
| item = treeView.getDummyTooltip(); |
| - if (!("filter" in item) || !item.filter) |
| + let filter = getFilter(item); |
| + if (!filter) |
| return; |
| - UI.openFiltersDialog(item.filter); |
| + UI.openFiltersDialog(filter); |
| } |
| function enableFilter(filter, enable) { |
| filter.disabled = !enable; |
| treeView.boxObject.invalidate(); |
| } |
| /** |
| * Edits the filter to disable it on a particular domain. |
| */ |
| function disableOnSite() |
| { |
| let item = treeView.getSelectedItem(); |
| - let filter = item.filter; |
| + let filter = getFilter(item); |
| if (!(filter instanceof ActiveFilter) || filter.disabled || !filter.subscriptions.length || filter.subscriptions.some(subscription => !(subscription instanceof SpecialSubscription))) |
| return; |
| let domain; |
| try { |
| domain = Utils.effectiveTLD.getBaseDomainFromHost(item.docDomain).toUpperCase(); |
| } |
| catch (e) |
| @@ -581,38 +594,38 @@ function disableOnSite() |
| let subscription = filter.subscriptions.filter(s => s instanceof SpecialSubscription)[0]; |
| if (subscription) |
| FilterStorage.addFilter(newFilter, subscription, subscription.filters.indexOf(filter)); |
| } |
| FilterStorage.removeFilter(filter); |
| // Update display |
| for (let i = 0; i < treeView.allData.length; i++) |
| - if (treeView.allData[i].filter == filter) |
| + if (getFilter(treeView.allData[i]) == filter) |
| treeView.allData[i].filter = null; |
| treeView.boxObject.invalidate(); |
| } |
| function copyToClipboard() { |
| var items = treeView.getAllSelectedItems(); |
| if (!items.length) |
| return; |
| Utils.clipboardHelper.copyString(items.map(function(item) {return item.location}).join(IO.lineBreak)); |
| } |
| function copyFilter() { |
| - var items = treeView.getAllSelectedItems().filter(function(item) {return item.filter}); |
| + var items = treeView.getAllSelectedItems().filter(getFilter); |
| if (treeView.data && !treeView.data.length) |
| items = [treeView.getDummyTooltip()]; |
| if (!items.length) |
| return; |
| - Utils.clipboardHelper.copyString(items.map(function(item) {return item.filter.text}).join(IO.lineBreak)); |
| + Utils.clipboardHelper.copyString(items.map(function(item) {return item.filter}).join(IO.lineBreak)); |
| } |
| function selectAll() { |
| treeView.selectAll(); |
| } |
| // Saves sidebar's state before detaching/reattaching |
| function saveState() { |
| @@ -651,17 +664,18 @@ function detach(doDetach) |
| myMainWin.document.getElementById("abp-command-sidebar").doCommand(); |
| myPrefs.detachsidebar = doDetach; |
| myMainWin.document.getElementById("abp-command-sidebar").doCommand(); |
| } |
| // Returns items size in the document if available |
| function getItemSize(item) |
| { |
| - if (item.filter && !item.filter.disabled && item.filter instanceof BlockingFilter) |
| + let filter = getFilter(item); |
| + if (filter && !filter.disabled && filter instanceof BlockingFilter) |
| return null; |
| for (let node of item.nodes) |
| { |
| if (node instanceof HTMLImageElement && (node.naturalWidth || node.naturalHeight)) |
| return [node.naturalWidth, node.naturalHeight]; |
| else if (node instanceof HTMLElement && (node.offsetWidth || node.offsetHeight)) |
| return [node.offsetWidth, node.offsetHeight]; |
| @@ -694,27 +708,30 @@ function compareType(item1, item2) { |
| return 0; |
| } |
| function compareFilter(item1, item2) { |
| var hasFilter1 = (item1.filter ? 1 : 0); |
| var hasFilter2 = (item2.filter ? 1 : 0); |
| if (hasFilter1 != hasFilter2) |
| return hasFilter1 - hasFilter2; |
| - else if (hasFilter1 && item1.filter.text < item2.filter.text) |
| + else if (hasFilter1 && item1.filter < item2.filter) |
| return -1; |
| - else if (hasFilter1 && item1.filter.text > item2.filter.text) |
| + else if (hasFilter1 && item1.filter > item2.filter) |
| return 1; |
| else |
| return 0; |
| } |
| -function compareState(item1, item2) { |
| - var state1 = (!item1.filter ? 0 : (item1.filter.disabled ? 1 : (item1.filter instanceof WhitelistFilter ? 2 : 3))); |
| - var state2 = (!item2.filter ? 0 : (item2.filter.disabled ? 1 : (item2.filter instanceof WhitelistFilter ? 2 : 3))); |
| +function compareState(item1, item2) |
| +{ |
| + let filter1 = getFilter(item1); |
| + let filter2 = getFilter(item2); |
| + let state1 = (!filter1 ? 0 : (filter1.disabled ? 1 : (filter1 instanceof WhitelistFilter ? 2 : 3))); |
| + let state2 = (!filter2 ? 0 : (filter2.disabled ? 1 : (filter2 instanceof WhitelistFilter ? 2 : 3))); |
| return state1 - state2; |
| } |
| function compareSize(item1, item2) { |
| var size1 = getItemSize(item1); |
| size1 = size1 ? size1[0] * size1[1] : 0; |
| var size2 = getItemSize(item2); |
| @@ -733,18 +750,20 @@ function compareDocDomain(item1, item2) |
| else if (!item1.thirdParty && item2.thirdParty) |
| return 1; |
| else |
| return 0; |
| } |
| function compareFilterSource(item1, item2) |
| { |
| - let subs1 = item1.filter ? item1.filter.subscriptions.map(s => s.title).join(", ") : ""; |
| - let subs2 = item2.filter ? item2.filter.subscriptions.map(s => s.title).join(", ") : ""; |
| + let filter1 = getFilter(item1); |
| + let filter2 = getFilter(item2); |
| + let subs1 = filter1 ? filter1.subscriptions.map(s => s.title).join(", ") : ""; |
| + let subs2 = filter2 ? filter2.subscriptions.map(s => s.title).join(", ") : ""; |
| if (subs1 < subs2) |
| return -1; |
| else if (subs1 > subs2) |
| return 1; |
| else |
| return 0; |
| } |
| @@ -851,30 +870,31 @@ var treeView = { |
| if (col != "type" && col != "address" && col != "filter" && col != "size" && col != "docDomain" && col != "filterSource") |
| return ""; |
| if (this.data && this.data.length) { |
| if (row >= this.data.length) |
| return ""; |
| if (col == "type") |
| return types.get(this.data[row].type); |
| else if (col == "filter") |
| - return (this.data[row].filter ? this.data[row].filter.text : ""); |
| + return (this.data[row].filter || ""); |
| else if (col == "size") |
| { |
| let size = getItemSize(this.data[row]); |
| return (size ? size.join(" x ") : ""); |
| } |
| else if (col == "docDomain") |
| return this.data[row].docDomain + " " + (this.data[row].thirdParty ? docDomainThirdParty : docDomainFirstParty); |
| else if (col == "filterSource") |
| { |
| - if (!this.data[row].filter) |
| + let filter = getFilter(this.data[row]) |
| + if (!filter) |
| return ""; |
| - return this.data[row].filter.subscriptions.filter(s => !s.disabled).map(s => s.title).join(", "); |
| + return filter.subscriptions.filter(s => !s.disabled).map(s => s.title).join(", "); |
| } |
| else |
| return this.data[row].location; |
| } |
| else { |
| // Empty list, show dummy |
| if (row > 0 || (col != "address" && col != "filter")) |
| return ""; |
| @@ -917,17 +937,17 @@ var treeView = { |
| let list = []; |
| list.push("selected-" + this.selection.isSelected(row)); |
| let state; |
| if (this.data && this.data.length) { |
| list.push("dummy-false"); |
| - let filter = this.data[row].filter; |
| + let filter = getFilter(this.data[row]); |
| if (filter) |
| list.push("filter-disabled-" + filter.disabled); |
| state = "state-regular"; |
| if (filter && !filter.disabled) |
| { |
| if (filter instanceof WhitelistFilter) |
| state = "state-whitelisted"; |
| @@ -1054,41 +1074,44 @@ var treeView = { |
| this.allData = []; |
| this.dataMap = Object.create(null); |
| this.refilter(); |
| this.boxObject.rowCountChanged(0, -oldRows); |
| this.boxObject.rowCountChanged(0, this.rowCount); |
| }, |
| - addItem: function(/**Node*/ node, /**RequestEntry*/ item, /**Boolean*/ scanComplete) |
| + addItem: function(/**RequestEntry*/ item, /**Boolean*/ scanComplete) |
| { |
| // Merge duplicate entries |
| let key = item.location + " " + item.type + " " + item.docDomain; |
| if (key in this.dataMap) |
| { |
| // We know this item already - take over the filter if any and be done with it |
| let existing = this.dataMap[key]; |
| if (item.filter) |
| existing.filter = item.filter; |
| - existing.nodes.push(node); |
| this.invalidateItem(existing); |
| return; |
| } |
| // Add new item to the list |
| // Store original item in orig property - reading out prototype is messed up in Gecko 1.9.2 |
| - item = {__proto__: item, orig: item, nodes: [node]}; |
| + item = {__proto__: item, orig: item, nodes: []}; |
|
Wladimir Palant
2015/11/02 20:01:59
Not having nodes has two side-effects: the Size co
|
| this.allData.push(item); |
| this.dataMap[key] = item; |
| // Show disabled filters if no other filter applies |
| if (!item.filter) |
| - item.filter = disabledMatcher.matchesAny(item.location, RegExpFilter.typeMap[item.type], item.docDomain, item.thirdParty); |
| + { |
| + let disabledMatch = disabledMatcher.matchesAny(item.location, RegExpFilter.typeMap[item.type], item.docDomain, item.thirdParty); |
| + if (disabledMatch) |
| + item.filter = disabledMatch.text; |
| + } |
| if (!this.matchesFilter(item)) |
| return; |
| let index = -1; |
| if (this.sortProc && this.sortColumn && this.sortColumn.id == "size") |
| { |
| // Sorting by size requires accessing content document, and that's |
| @@ -1130,20 +1153,25 @@ var treeView = { |
| else if (!scanComplete && this.selection.currentIndex >= 0) // Keep selected row visible while scanning |
| this.boxObject.ensureRowIsVisible(this.selection.currentIndex); |
| }, |
| updateFilters: function() |
| { |
| for (let item of this.allData) |
| { |
| - if (item.filter instanceof RegExpFilter && item.filter.disabled) |
| + let filter = getFilter(item); |
| + if (filter instanceof RegExpFilter && filter.disabled) |
| delete item.filter; |
| - if (!item.filter) |
| - item.filter = disabledMatcher.matchesAny(item.location, RegExpFilter.typeMap[item.type], item.docDomain, item.thirdParty); |
| + if (!filter) |
| + { |
| + let disabledMatch = disabledMatcher.matchesAny(item.location, RegExpFilter.typeMap[item.type], item.docDomain, item.thirdParty); |
| + if (disabledMatch) |
| + item.filter = disabledMatch.text; |
| + } |
| } |
| this.refilter(); |
| }, |
| /** |
| * Updates the list after a filter or sorting change. |
| */ |
| refilter: function() |
| @@ -1162,17 +1190,17 @@ var treeView = { |
| * @return {Boolean} true if the item should be shown |
| */ |
| matchesFilter: function(item) |
| { |
| if (!this.filter) |
| return true; |
| return (item.location.toLowerCase().indexOf(this.filter) >= 0 || |
| - (item.filter && item.filter.text.toLowerCase().indexOf(this.filter) >= 0) || |
| + (item.filter && item.filter.toLowerCase().indexOf(this.filter) >= 0) || |
| item.type.toLowerCase().indexOf(this.filter.replace(/-/g, "_")) >= 0 || |
| types.get(item.type).toLowerCase().indexOf(this.filter) >= 0 || |
| (item.docDomain && item.docDomain.toLowerCase().indexOf(this.filter) >= 0) || |
| (item.docDomain && item.thirdParty && docDomainThirdParty.toLowerCase().indexOf(this.filter) >= 0) || |
| (item.docDomain && !item.thirdParty && docDomainFirstParty.toLowerCase().indexOf(this.filter) >= 0)); |
| }, |
| setFilter: function(filter) { |
| @@ -1241,17 +1269,17 @@ var treeView = { |
| }, |
| getDummyTooltip: function() { |
| if (!this.data || this.data.length) |
| return null; |
| var filter = Policy.isWindowWhitelisted(window.content); |
| if (filter) |
| - return {tooltip: this.whitelistDummyTooltip, filter: filter}; |
| + return {tooltip: this.whitelistDummyTooltip, filter: filter.text}; |
| else |
| return {tooltip: this.itemsDummyTooltip}; |
| }, |
| invalidateItem: function(item) |
| { |
| let row = this.data.indexOf(item); |
| if (row >= 0) |