Add ABPrime to the repository

custom-2020
Matt A. Tobin 4 years ago committed by Roy Tam
parent 1b26c8618e
commit b959b204ba
  1. 32
      abprime/addon/adblockplus.js
  2. BIN
      abprime/addon/icon.png
  3. BIN
      abprime/addon/icon64.png
  4. 50
      abprime/addon/install.rdf
  5. 27
      abprime/addon/jar.mn
  6. 16
      abprime/addon/moz.build
  7. 2
      abprime/addon/patterns.ini
  8. 8
      abprime/app.mozbuild
  9. 7
      abprime/build.mk
  10. 94
      abprime/components/Initializer.js
  11. 5
      abprime/components/components.manifest
  12. 8
      abprime/components/moz.build
  13. 164
      abprime/content/about.js
  14. 62
      abprime/content/about.xul
  15. 401
      abprime/content/composer.js
  16. 107
      abprime/content/composer.xul
  17. 96
      abprime/content/errors.html
  18. 331
      abprime/content/filters-backup.js
  19. 539
      abprime/content/filters-filteractions.js
  20. 820
      abprime/content/filters-filterview.js
  21. 263
      abprime/content/filters-search.js
  22. 592
      abprime/content/filters-subscriptionactions.js
  23. 288
      abprime/content/filters-subscriptionview.js
  24. 210
      abprime/content/filters.js
  25. 395
      abprime/content/filters.xul
  26. 98
      abprime/content/firstRun.js
  27. 43
      abprime/content/firstRun.xul
  28. 104
      abprime/content/flasher.js
  29. 40
      abprime/content/jar.mn
  30. 6
      abprime/content/moz.build
  31. 59
      abprime/content/navigatorOverlay.xul
  32. 71
      abprime/content/objtabs.css
  33. 30
      abprime/content/overlay.js
  34. 97
      abprime/content/overlayGeneral.xul
  35. 56
      abprime/content/phoenixOverlay.xul
  36. 154
      abprime/content/progressBar.xml
  37. 1467
      abprime/content/sendReport.js
  38. 248
      abprime/content/sendReport.xul
  39. 29
      abprime/content/settings.xul
  40. 1226
      abprime/content/sidebar.js
  41. 128
      abprime/content/sidebar.xul
  42. 39
      abprime/content/sidebarDetached.xul
  43. 296
      abprime/content/subscriptionSelection.js
  44. 64
      abprime/content/subscriptionSelection.xul
  45. 28
      abprime/content/subscriptions.xml
  46. 36
      abprime/content/utils.js
  47. 16
      abprime/locale/about.dtd
  48. 53
      abprime/locale/composer.dtd
  49. 116
      abprime/locale/filters.dtd
  50. 27
      abprime/locale/firstRun.dtd
  51. 60
      abprime/locale/global.properties
  52. 17
      abprime/locale/jar.mn
  53. 6
      abprime/locale/moz.build
  54. 54
      abprime/locale/overlay.dtd
  55. 201
      abprime/locale/sendReport.dtd
  56. 44
      abprime/locale/sidebar.dtd
  57. 27
      abprime/locale/subscriptionSelection.dtd
  58. 1667
      abprime/modules/AppIntegration.jsm
  59. 167
      abprime/modules/Bootstrap.jsm
  60. 634
      abprime/modules/ContentPolicy.jsm
  61. 265
      abprime/modules/ContentPolicyRemote.jsm
  62. 447
      abprime/modules/ElemHide.jsm
  63. 186
      abprime/modules/ElemHideRemote.jsm
  64. 813
      abprime/modules/FilterClasses.jsm
  65. 269
      abprime/modules/FilterListener.jsm
  66. 70
      abprime/modules/FilterNotifier.jsm
  67. 776
      abprime/modules/FilterStorage.jsm
  68. 317
      abprime/modules/IO.jsm
  69. 410
      abprime/modules/Matcher.jsm
  70. 504
      abprime/modules/ObjectTabs.jsm
  71. 313
      abprime/modules/Prefs.jsm
  72. 185
      abprime/modules/Public.jsm
  73. 346
      abprime/modules/RequestNotifier.jsm
  74. 560
      abprime/modules/SubscriptionClasses.jsm
  75. 425
      abprime/modules/Sync.jsm
  76. 594
      abprime/modules/Synchronizer.jsm
  77. 153
      abprime/modules/TimeLine.jsm
  78. 820
      abprime/modules/Utils.jsm
  79. 29
      abprime/modules/moz.build
  80. 14
      abprime/moz.build
  81. 68
      abprime/moz.configure
  82. 40
      abprime/skin/about.css
  83. BIN
      abprime/skin/abp-icon-big.png
  84. BIN
      abprime/skin/abp-status-16.png
  85. BIN
      abprime/skin/abp-status.png
  86. BIN
      abprime/skin/checkbox.png
  87. BIN
      abprime/skin/close.png
  88. 66
      abprime/skin/composer.css
  89. 208
      abprime/skin/filters.css
  90. 52
      abprime/skin/firstRun.css
  91. BIN
      abprime/skin/item-state.png
  92. 25
      abprime/skin/jar.mn
  93. 6
      abprime/skin/moz.build
  94. 165
      abprime/skin/overlay.css
  95. 111
      abprime/skin/sendReport.css
  96. 99
      abprime/skin/sidebar.css
  97. BIN
      abprime/skin/slow.png
  98. 58
      abprime/skin/subscriptionSelection.css

@ -0,0 +1,32 @@
#filter substitution
pref("extensions.@ADDON_CHROME_NAME@.currentVersion", "0.0");
pref("extensions.@ADDON_CHROME_NAME@.enabled", true);
pref("extensions.@ADDON_CHROME_NAME@.frameobjects", true);
pref("extensions.@ADDON_CHROME_NAME@.fastcollapse", false);
pref("extensions.@ADDON_CHROME_NAME@.showinstatusbar", false);
pref("extensions.@ADDON_CHROME_NAME@.detachsidebar", false);
pref("extensions.@ADDON_CHROME_NAME@.defaulttoolbaraction", 0);
pref("extensions.@ADDON_CHROME_NAME@.defaultstatusbaraction", 0);
pref("extensions.@ADDON_CHROME_NAME@.sidebar_key", "Accel Shift V, Accel Shift U");
pref("extensions.@ADDON_CHROME_NAME@.sendReport_key", "");
pref("extensions.@ADDON_CHROME_NAME@.filters_key", "Accel Shift E, Accel Shift F, Accel Shift O");
pref("extensions.@ADDON_CHROME_NAME@.enable_key", "");
pref("extensions.@ADDON_CHROME_NAME@.flash_scrolltoitem", true);
pref("extensions.@ADDON_CHROME_NAME@.previewimages", true);
pref("extensions.@ADDON_CHROME_NAME@.data_directory", "adblockplus");
pref("extensions.@ADDON_CHROME_NAME@.patternsbackups", 5);
pref("extensions.@ADDON_CHROME_NAME@.patternsbackupinterval", 24);
pref("extensions.@ADDON_CHROME_NAME@.whitelistschemes", "about chrome file irc moz-safe-about news resource snews x-jsd addbook cid imap mailbox nntp pop data javascript moz-icon");
pref("extensions.@ADDON_CHROME_NAME@.hideimagemanager", true);
pref("extensions.@ADDON_CHROME_NAME@.subscriptions_autoupdate", true);
pref("extensions.@ADDON_CHROME_NAME@.subscriptions_listurl", "https://adblockplus.org/subscriptions2.xml");
pref("extensions.@ADDON_CHROME_NAME@.subscriptions_fallbackurl", "https://adblockplus.org/getSubscription?version=%VERSION%&url=%SUBSCRIPTION%&downloadURL=%URL%&error=%ERROR%&channelStatus=%CHANNELSTATUS%&responseStatus=%RESPONSESTATUS%");
pref("extensions.@ADDON_CHROME_NAME@.subscriptions_fallbackerrors", 5);
pref("extensions.@ADDON_CHROME_NAME@.documentation_link", "https://adblockplus.org/redirect?link=%LINK%&lang=%LANG%");
pref("extensions.@ADDON_CHROME_NAME@.savestats", true);
pref("extensions.@ADDON_CHROME_NAME@.composer_default", 2);
pref("extensions.@ADDON_CHROME_NAME@.clearStatsOnHistoryPurge", true);
pref("extensions.@ADDON_CHROME_NAME@.report_submiturl", "");
pref("extensions.@ADDON_CHROME_NAME@.recentReports", "[]");
pref("services.sync.engine.@ADDON_CHROME_NAME@", false);

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

@ -0,0 +1,50 @@
<?xml version="1.0"?>
<!-- This Source Code is subject to the terms of the Mozilla Public License
- version 2.0 (the "License"). You can obtain a copy of the License at
- http://mozilla.org/MPL/2.0/. -->
#filter substitution
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>@ADDON_ID@</em:id>
<em:version>@ADDON_VERSION@</em:version>
<em:name>@ADDON_NAME@</em:name>
<em:description>@ADDON_SHORT_DESC@</em:description>
<em:creator>@ADDON_AUTHOR@</em:creator>
#ifdef ADDON_URL
<em:homepageURL>@ADDON_URL@</em:homepageURL>
#endif
<em:type>2</em:type>
<em:targetApplication>
<Description>
<!-- @ADDON_TARGET_APP_NAME@ -->
<em:id>@ADDON_TARGET_APP_ID@</em:id>
<em:minVersion>@ADDON_TARGET_APP_MINVER@</em:minVersion>
<em:maxVersion>@ADDON_TARGET_APP_MAXVER@</em:maxVersion>
</Description>
</em:targetApplication>
#ifdef ADDON_TARGET_BASILISK
<em:targetApplication>
<Description>
<!-- Basilisk -->
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>52.0</em:minVersion>
<em:maxVersion>55.*</em:maxVersion>
<em:basilisk>true</em:basilisk>
</Description>
</em:targetApplication>
#endif
<em:targetApplication>
<Description>
<!-- Borealis (Navigator) -->
<em:id>{a3210b97-8e8a-4737-9aa0-aa0e607640b9}</em:id>
<em:minVersion>1.0.0a1</em:minVersion>
<em:maxVersion>2.*</em:maxVersion>
</Description>
</em:targetApplication>
</Description>
</RDF>

@ -0,0 +1,27 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#filter substitution
# We are seperating out the additional chrome.manifest directives to here because it keeps the others cleaner
# Though, properly we SHOULD keep relevent ones in the relevant jar.mn files.. idc
[.] chrome.jar:
#ifdef ADDON_TARGET_BASILISK
% overlay chrome://browser/content/browser.xul chrome://@ADDON_CHROME_NAME@/content/phoenixOverlay.xul application=@ADDON_TARGET_APP_ID@ application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
#else
% overlay chrome://browser/content/browser.xul chrome://@ADDON_CHROME_NAME@/content/phoenixOverlay.xul application=@ADDON_TARGET_APP_ID@
#endif
% overlay chrome://navigator/content/navigator.xul chrome://@ADDON_CHROME_NAME@/content/navigatorOverlay.xul application={a3210b97-8e8a-4737-9aa0-aa0e607640b9}
# Hack to prevent .Net Framework Assistant from messing up the browser
% override chrome://dotnetassistant/content/bootstrap.xul data:text/xml,<nada/>
% resource @ADDON_CHROME_NAME@ /
# Component registration
% component {d32a3c00-4ed3-11de-8a39-0800200c9a66} components/Initializer.js
% contract @adblockplus.org/abp/startup;1 {d32a3c00-4ed3-11de-8a39-0800200c9a66}
% category profile-after-change @adblockplus.org/abp/startup;1 @adblockplus.org/abp/startup;1

@ -0,0 +1,16 @@
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
FINAL_TARGET_FILES += [
'icon.png',
'icon64.png',
]
FINAL_TARGET_PP_FILES += ['install.rdf']
FINAL_TARGET_PP_FILES.defaults += ['patterns.ini']
FINAL_TARGET_PP_FILES.defaults.preferences += ['adblockplus.js']
JAR_MANIFESTS += ['jar.mn']

@ -0,0 +1,2 @@
# Adblock Plus preferences
version=4

@ -0,0 +1,8 @@
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# Never add tier dirs after the application srcdir because they
# apparently won't get packaged properly on Mac.
DIRS += ['/abprime']

@ -0,0 +1,7 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
package:
cd $(DIST)/bin; \
zip -Dr9X ../${ADDON_XPI_NAME}-${ADDON_VERSION}.xpi * -x \*/.mkdir.done; \

@ -0,0 +1,94 @@
/*
* This Source Code is subject to the terms of the Mozilla Public License
* version 2.0 (the "License"). You can obtain a copy of the License at
* http://mozilla.org/MPL/2.0/.
*/
#filter substitution
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
// Gecko 1.9.0/1.9.1 compatibility - add XPCOMUtils.defineLazyServiceGetter
if (!("defineLazyServiceGetter" in XPCOMUtils))
{
XPCOMUtils.defineLazyServiceGetter = function XPCU_defineLazyServiceGetter(obj, prop, contract, iface)
{
obj.__defineGetter__(prop, function XPCU_serviceGetter()
{
delete obj[prop];
return obj[prop] = Cc[contract].getService(Ci[iface]);
});
};
}
/**
* Application startup/shutdown observer, triggers init()/shutdown() methods in Bootstrap.jsm module.
* @constructor
*/
function Initializer() {}
Initializer.prototype =
{
classDescription: "Adblock Plus initializer",
contractID: "@adblockplus.org/abp/startup;1",
classID: Components.ID("{d32a3c00-4ed3-11de-8a39-0800200c9a66}"),
_xpcom_categories: [{ category: "app-startup", service: true }],
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
observe: function(subject, topic, data)
{
let observerService = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
switch (topic)
{
case "app-startup":
observerService.addObserver(this, "profile-after-change", true);
break;
case "profile-after-change":
observerService.addObserver(this, "quit-application", true);
// Don't init in Fennec, initialization will happen when UI is ready
let appInfo = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo);
if (appInfo.ID != "{a23983c0-fd0e-11dc-95ff-0800200c9a66}" && appInfo.ID != "{aa3c5121-dab2-40e2-81ca-7ea25febc110}")
{
try
{
// Gecko 2.0 and higher - chrome URLs can be loaded directly
Cu.import("resource://@ADDON_CHROME_NAME@/modules/Bootstrap.jsm");
}
catch (e)
{
// Gecko 1.9.x - have to convert chrome URLs to file URLs first
let chromeRegistry = Cc["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIChromeRegistry);
let ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
let bootstrapURL = chromeRegistry.convertChromeURL(ioService.newURI("resource://@ADDON_CHROME_NAME@/modules/Bootstrap.jsm", null, null));
Cu.import(bootstrapURL.spec);
}
Bootstrap.startup();
}
break;
case "quit-application":
try {
// This will fail if component was added via chrome.manifest (Gecko 2.0)
observerService.removeObserver(this, "profile-after-change");
}catch(e) {}
observerService.removeObserver(this, "quit-application");
if ("@adblockplus.org/abp/private;1" in Cc)
{
let baseURL = Cc["@adblockplus.org/abp/private;1"].getService(Ci.nsIURI);
Cu.import(baseURL.spec + "Bootstrap.jsm");
Bootstrap.shutdown(false);
}
break;
}
}
};
if (XPCOMUtils.generateNSGetFactory)
var NSGetFactory = XPCOMUtils.generateNSGetFactory([Initializer]);
else
var NSGetModule = XPCOMUtils.generateNSGetModule([Initializer]);

@ -0,0 +1,5 @@
# Normally it doesn't quite matter WHEN the components load as long as they load..
# However, ABPrime wants everything to be initallized well before the main window
# spawns so we put the component registration in the main chrome.manifest elsewhere.
# The build system demands to have a manifest file along side any components though,
# so here it is to keep it from not bitching.

@ -0,0 +1,8 @@
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
EXTRA_COMPONENTS += ['components.manifest']
EXTRA_PP_COMPONENTS += ['Initializer.js']

@ -0,0 +1,164 @@
/*
* This Source Code is subject to the terms of the Mozilla Public License
* version 2.0 (the "License"). You can obtain a copy of the License at
* http://mozilla.org/MPL/2.0/.
*/
#filter substitution
try
{
Cu.import("resource://gre/modules/AddonManager.jsm");
}
catch (e) {}
function init()
{
let ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
if (typeof AddonManager != "undefined")
{
let addon = AddonManager.getAddonByID(Utils.addonID, function(addon)
{
loadInstallManifest(addon.getResourceURI("install.rdf"), addon.name, addon.homepageURL);
});
}
else if ("@mozilla.org/extensions/manager;1" in Cc)
{
let extensionManager = Cc["@mozilla.org/extensions/manager;1"].getService(Ci.nsIExtensionManager);
let rdf = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
let root = rdf.GetResource("urn:mozilla:item:" + Utils.addonID);
function emResource(prop)
{
return rdf.GetResource("http://www.mozilla.org/2004/em-rdf#" + prop);
}
function getTarget(prop)
{
let target = extensionManager.datasource.GetTarget(root, emResource(prop), true);
if (target)
return target.QueryInterface(Ci.nsIRDFLiteral).Value;
else
return null;
}
let installLocation = extensionManager.getInstallLocation(Utils.addonID);
let installManifestFile = installLocation.getItemFile(Utils.addonID, "install.rdf");
loadInstallManifest(ioService.newFileURI(installManifestFile), getTarget("name"), getTarget("homepageURL"));
}
else
{
// No add-on manager, no extension manager - we must be running in K-Meleon.
// Load Manifest.jsm as last solution.
Cu.import(baseURL + "Manifest.jsm");
setExtensionData(manifest.name, manifest.version, manifest.homepage, [manifest.creator], manifest.contributors, manifest.translators);
}
}
function loadInstallManifest(installManifestURI, name, homepage)
{
let rdf = Cc["@mozilla.org/rdf/rdf-service;1"].getService(Ci.nsIRDFService);
let ds = rdf.GetDataSource(installManifestURI.spec);
let root = rdf.GetResource("urn:mozilla:install-manifest");
function emResource(prop)
{
return rdf.GetResource("http://www.mozilla.org/2004/em-rdf#" + prop);
}
function getTargets(prop)
{
let targets = ds.GetTargets(root, emResource(prop), true);
let result = [];
while (targets.hasMoreElements())
result.push(targets.getNext().QueryInterface(Ci.nsIRDFLiteral).Value);
return result;
}
function dataSourceLoaded()
{
setExtensionData(name, getTargets("version")[0],
homepage, getTargets("creator"),
getTargets("contributor"), getTargets("translator"));
}
if (ds instanceof Ci.nsIRDFRemoteDataSource && ds.loaded)
dataSourceLoaded();
else
{
let sink = ds.QueryInterface(Ci.nsIRDFXMLSink);
sink.addXMLSinkObserver({
onBeginLoad: function() {},
onInterrupt: function() {},
onResume: function() {},
onEndLoad: function() {
sink.removeXMLSinkObserver(this);
dataSourceLoaded();
},
onError: function() {},
});
}
}
function cmpNoCase(a, b)
{
let aLC = a.toLowerCase();
let bLC = b.toLowerCase();
if (aLC < bLC)
return -1;
else if (aLC > bLC)
return 1;
else
return 0;
}
function setExtensionData(name, version, homepage, authors, contributors, translators)
{
authors.sort(cmpNoCase);
contributors.sort(cmpNoCase);
translators.sort(cmpNoCase);
E("title").value = name;
E("version").value = version;
E("homepage").value = homepage;
E("authors").textContent = authors.join(", ");
E("contributors").textContent = contributors.join(", ");
E("translators").textContent = translators.join(", ");
let request = new XMLHttpRequest();
request.open("GET", "chrome://@ADDON_CHROME_NAME@/content/subscriptions.xml");
request.addEventListener("load", setSubscriptionAuthors, false);
request.send(null);
}
function setSubscriptionAuthors()
{
let doc = this.responseXML;
if (!doc || doc.documentElement.localName != "subscriptions")
return;
let authors = {__proto__: null};
for (let node = doc.documentElement.firstChild; node; node = node.nextSibling)
{
if (node.localName != "subscription" || !node.hasAttribute("author"))
continue;
for each (let author in node.getAttribute("author").split(","))
{
author = author.replace(/^\s+/, "").replace(/\s+$/, "");
if (author == "")
continue;
authors[author] = true;
}
}
let list = [];
for (let author in authors)
list.push(author);
list.sort(cmpNoCase)
E("subscriptionAuthors").textContent = list.join(", ");
E("mainBox").setAttribute("loaded", "true");
}

@ -0,0 +1,62 @@
<?xml version="1.0"?>
<!-- This Source Code is subject to the terms of the Mozilla Public License
- version 2.0 (the "License"). You can obtain a copy of the License at
- http://mozilla.org/MPL/2.0/. -->
#filter substitution
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://@ADDON_CHROME_NAME@/skin/about.css" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://@ADDON_CHROME_NAME@/locale/about.dtd">
<dialog
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="&dialog.title;"
id="adblockAboutWindow"
windowtype="abp:about"
onload="init()"
buttons="accept">
<script type="application/x-javascript;version=1.7" src="utils.js"/>
<script type="application/x-javascript;version=1.7" src="about.js"/>
<vbox id="mainBox">
<description id="title" value=" "/>
<hbox align="baseline">
<label control="version" value="&version.title;"/>
<textbox id="version" flex="1" class="plain" readonly="true" tabindex="-1"/>
</hbox>
<groupbox id="mainGroup" flex="1">
<description id="description">
&description;
</description>
<description id="homepageTitle" value="&homepage.label;"/>
<description id="homepage" class="text-link" onclick="Utils.loadInBrowser(this.getAttribute('value'))"/>
<vbox id="authorsBox" align="top">
<label id="authorsTitle" control="authors" value="&author.label;"/>
<description id="authors"/>
</vbox>
<vbox id="contributorsBox" align="top">
<label id="contributorsTitle" control="contributors" value="&contributors.label;"/>
<description id="contributors"/>
</vbox>
<vbox id="subscriptionAuthorsBox" align="top">
<label id="subscriptionAuthorsTitle" control="subscriptionAuthors" value="&subscriptionAuthors.label;"/>
<description id="subscriptionAuthors"/>
</vbox>
<vbox id="translatorsBox">
<label id="translatorsTitle" control="translators" value="&translators.label;"/>
<description id="translators"/>
</vbox>
</groupbox>
</vbox>
</dialog>

@ -0,0 +1,401 @@
/*
* This Source Code is subject to the terms of the Mozilla Public License
* version 2.0 (the "License"). You can obtain a copy of the License at
* http://mozilla.org/MPL/2.0/.
*/
let nodes = null;
let item = null;
let advancedMode = false;
function init()
{
[nodes, item] = window.arguments;
E("filterType").value = (!item.filter || item.filter.disabled || item.filter instanceof WhitelistFilter ? "filterlist" : "whitelist");
E("customPattern").value = item.location;
let insertionPoint = E("customPatternBox");
let addSuggestion = function(address)
{
// Always drop protocol and www. from the suggestion
address = address.replace(/^[\w\-]+:\/+(?:www\.)?/, "");
let suggestion = document.createElement("radio");
suggestion.setAttribute("value", address);
suggestion.setAttribute("label", address);
suggestion.setAttribute("crop", "center");
suggestion.setAttribute("class", "suggestion");
insertionPoint.parentNode.insertBefore(suggestion, insertionPoint);
return address;
}
let ioService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
try
{
let suggestions = [""];
let url = ioService.newURI(item.location, null, null)
.QueryInterface(Ci.nsIURL);
let suffix = (url.query ? "?*" : "");
url.query = "";
suggestions[1] = addSuggestion(url.spec + suffix);
let parentURL = ioService.newURI(url.fileName == "" ? ".." : ".", null, url);
if (!parentURL.equals(url))
suggestions[2] = addSuggestion(parentURL.spec + "*");
else
suggestions[2] = suggestions[1];
let rootURL = ioService.newURI("/", null, url);
if (!rootURL.equals(parentURL) && !rootURL.equals(url))
suggestions[3] = addSuggestion(rootURL.spec + "*");
else
suggestions[3] = suggestions[2];
try
{
suggestions[4] = addSuggestion(url.host.replace(/^www\./, "") + "^");
// Prefer example.com^ to example.com/*
let undesired = suggestions[4].replace(/\^$/, "/*");
for (let i = 0; i < suggestions.length - 1; i++)
if (suggestions[i] == undesired)
suggestions[i] = suggestions[4];
for (let child = insertionPoint.parentNode.firstChild; child; child = child.nextSibling)
{
if (child.localName == "radio" && child.getAttribute("value") == undesired)
{
child.parentNode.removeChild(child);
break;
}
}
}
catch (e)
{
suggestions[4] = suggestions[3];
}
try
{
let effectiveTLD = Cc["@mozilla.org/network/effective-tld-service;1"].getService(Ci.nsIEffectiveTLDService);
let host = url.host;
let baseDomain = effectiveTLD.getBaseDomainFromHost(host);
if (baseDomain != host.replace(/^www\./, ""))
suggestions[5] = addSuggestion(baseDomain + "^");
else
suggestions[5] = suggestions[4];
}
catch (e)
{
suggestions[5] = suggestions[4];
}
E("patternGroup").value = (Prefs.composer_default in suggestions ? suggestions[Prefs.composer_default] : suggestions[1]);
}
catch (e)
{
// IOService returned nsIURI - not much we can do with it
addSuggestion(item.location);
E("patternGroup").value = "";
}
if (Prefs.composer_default == 0)
E("customPattern").focus();
else
E("patternGroup").focus();
let types = [];
for (let type in Policy.localizedDescr)
{
types.push(parseInt(type));
}
types.sort(function(a, b) {
if (a < b)
return -1;
else if (a > b)
return 1;
else
return 0;
});
let docDomain = item.docDomain;
let thirdParty = item.thirdParty;
if (docDomain)
docDomain = docDomain.replace(/^www\./i, "").replace(/\.+$/, "");
if (docDomain)
E("domainRestriction").value = docDomain;
E("thirdParty").hidden = !thirdParty;
E("firstParty").hidden = thirdParty;
let typeGroup = E("typeGroup");
let defaultTypes = RegExpFilter.prototype.contentType & ~RegExpFilter.typeMap.DOCUMENT;
let isDefaultType = (RegExpFilter.typeMap[item.typeDescr] & defaultTypes) != 0;
for each (let type in types)
{
if (type == Policy.type.ELEMHIDE)
continue;
let typeNode = document.createElement("checkbox");
typeNode.setAttribute("value", Policy.typeDescr[type].toLowerCase().replace(/\_/g, "-"));
typeNode.setAttribute("label", Policy.localizedDescr[type].toLowerCase());
let typeMask = RegExpFilter.typeMap[Policy.typeDescr[type]];
typeNode._defaultType = (typeMask & defaultTypes) != 0;
if ((isDefaultType && typeNode._defaultType) || (!isDefaultType && item.type == type))
typeNode.setAttribute("checked", "true");
if (item.type == type)
typeNode.setAttribute("disabled", "true");
typeNode.addEventListener("command", function() checkboxUpdated(this), false);
typeGroup.appendChild(typeNode);
}
let collapseDefault = E("collapseDefault");
collapseDefault.label = collapseDefault.getAttribute(Prefs.fastcollapse ? "label_no" : "label_yes");
E("collapse").value = "";
E("collapse").setAttribute("label", collapseDefault.label);
let warning = E("disabledWarning");
generateLinkText(warning);
warning.hidden = Prefs.enabled;
updatePatternSelection();
}
function checkboxUpdated(checkbox)
{
checkbox._lastChange = Date.now();
updateFilter();
}
function updateFilter()
{
let filter = "";
let type = E("filterType").value
if (type == "whitelist")
filter += "@@";
let pattern = E("patternGroup").value;
if (pattern == "")
pattern = E("customPattern").value;
if (E("anchorStart").checked)
filter += E("anchorStart").flexibleAnchor ? "||" : "|";
filter += pattern;
if (E("anchorEnd").checked)
filter += "|";
if (advancedMode)
{
let options = [];
if (E("domainRestrictionEnabled").checked)
{
let domainRestriction = E("domainRestriction").value.replace(/[,\s]/g, "").replace(/\.+$/, "");
if (domainRestriction)
options.push([E("domainRestrictionEnabled")._lastChange || 0, "domain=" + domainRestriction]);
}
if (E("firstParty").checked)
options.push([E("firstParty")._lastChange || 0, "~third-party"]);
if (E("thirdParty").checked)
options.push([E("thirdParty")._lastChange || 0, "third-party"]);
if (E("matchCase").checked)
options.push([E("matchCase")._lastChange || 0, "match-case"]);
let collapse = E("collapse");
disableElement(collapse, type == "whitelist", "value", "");
if (collapse.value != "")
options.push([collapse._lastChange, collapse.value]);
let enabledTypes = [];
let disabledTypes = [];
let forceEnabledTypes = [];
for (let typeNode = E("typeGroup").firstChild; typeNode; typeNode = typeNode.nextSibling)
{
let value = typeNode.getAttribute("value");
if (value == "document")
disableElement(typeNode, type != "whitelist", "checked", false);
if (!typeNode._defaultType)
{
if (typeNode.getAttribute("checked") == "true")
forceEnabledTypes.push([typeNode._lastChange || 0, value]);
}
else if (typeNode.getAttribute("checked") == "true")
enabledTypes.push([typeNode._lastChange || 0, value]);
else
disabledTypes.push([typeNode._lastChange || 0, "~" + value]);
}
if (!forceEnabledTypes.length && disabledTypes.length < enabledTypes.length)
options.push.apply(options, disabledTypes);
else
options.push.apply(options, enabledTypes);
options.push.apply(options, forceEnabledTypes);
if (options.length)
{
options.sort(function(a, b) a[0] - b[0]);
filter += "$" + options.map(function(o) o[1]).join(",");
}
}
else
{
let defaultTypes = RegExpFilter.prototype.contentType & ~RegExpFilter.typeMap.DOCUMENT;
let isDefaultType = (RegExpFilter.typeMap[item.typeDescr] & defaultTypes) != 0;
if (!isDefaultType)
filter += "$" + item.typeDescr.toLowerCase().replace(/\_/g, "-");
}
filter = Filter.normalize(filter);
E("regexpWarning").hidden = !Filter.regexpRegExp.test(filter);
let isSlow = false;
let compiledFilter = Filter.fromText(filter);
if (E("regexpWarning").hidden)
{
if (compiledFilter instanceof RegExpFilter && defaultMatcher.isSlowFilter(compiledFilter))
isSlow = true;
}
E("shortpatternWarning").hidden = !isSlow;
E("matchWarning").hidden = compiledFilter instanceof RegExpFilter && compiledFilter.matches(item.location, item.typeDescr, item.docDomain, item.thirdParty);
E("filter").value = filter;
}
function generateLinkText(element, replacement)
{
let template = element.getAttribute("textTemplate");
if (typeof replacement != "undefined")
template = template.replace(/\?1\?/g, replacement)
let [, beforeLink, linkText, afterLink] = /(.*)\[link\](.*)\[\/link\](.*)/.exec(template) || [null, "", template, ""];
while (element.firstChild && element.firstChild.nodeType != Node.ELEMENT_NODE)
element.removeChild(element.firstChild);
while (element.lastChild && element.lastChild.nodeType != Node.ELEMENT_NODE)
element.removeChild(element.lastChild);
if (!element.firstChild)
return;
element.firstChild.textContent = linkText;
element.insertBefore(document.createTextNode(beforeLink), element.firstChild);
element.appendChild(document.createTextNode(afterLink));
}
function updatePatternSelection()
{
let pattern = E("patternGroup").value;
if (pattern == "")
{
pattern = E("customPattern").value;
}
else
{
E("anchorStart").checked = true;
E("anchorEnd").checked = false;
}
function testFilter(/**String*/ filter) /**Boolean*/
{
return RegExpFilter.fromText(filter + "$" + item.typeDescr).matches(item.location, item.typeDescr, item.docDomain, item.thirdParty);
}
let anchorStartCheckbox = E("anchorStart");
if (!/^\*/.test(pattern) && testFilter("||" + pattern))
{
disableElement(anchorStartCheckbox, false, "checked", false);
anchorStartCheckbox.setAttribute("label", anchorStartCheckbox.getAttribute("labelFlexible"));
anchorStartCheckbox.accessKey = anchorStartCheckbox.getAttribute("accesskeyFlexible");
anchorStartCheckbox.flexibleAnchor = true;
}
else
{
disableElement(anchorStartCheckbox, /^\*/.test(pattern) || !testFilter("|" + pattern), "checked", false);
anchorStartCheckbox.setAttribute("label", anchorStartCheckbox.getAttribute("labelRegular"));
anchorStartCheckbox.accessKey = anchorStartCheckbox.getAttribute("accesskeyRegular");
anchorStartCheckbox.flexibleAnchor = false;
}
disableElement(E("anchorEnd"), /[\*\^]$/.test(pattern) || !testFilter(pattern + "|"), "checked", false);
updateFilter();
setAdvancedMode(document.documentElement.getAttribute("advancedMode") == "true");
}
function updateCustomPattern()
{
E("patternGroup").value = "";
updatePatternSelection();
}
function addFilter() {
let filter = Filter.fromText(document.getElementById("filter").value);
filter.disabled = false;
FilterStorage.addFilter(filter);
if (nodes)
Policy.refilterNodes(nodes, item);
return true;
}
function setAdvancedMode(mode) {
advancedMode = mode;
var dialog = document.documentElement;
dialog.setAttribute("advancedMode", advancedMode);
var button = dialog.getButton("disclosure");
button.setAttribute("label", dialog.getAttribute(advancedMode ? "buttonlabeldisclosure_off" : "buttonlabeldisclosure_on"));
updateFilter();
}
function disableElement(element, disable, valueProperty, disabledValue) {
if ((element.getAttribute("disabled") == "true") == disable)
return;
if (disable)
{
element.setAttribute("disabled", "true");
element._abpStoredValue = element[valueProperty];
element[valueProperty] = disabledValue;
}
else
{
element.removeAttribute("disabled");
if ("_abpStoredValue" in element)
element[valueProperty] = element._abpStoredValue;
delete element._abpStoredValue;
}
}
function openPreferences() {
Utils.openFiltersDialog(Filter.fromText(E("filter").value));
}
function doEnable() {
Prefs.enabled = true;
E("disabledWarning").hidden = true;
}
/**
* Selects or unselects all type checkboxes except those
* that are disabled.
*/
function selectAllTypes(/**Boolean*/ select)
{
for (let typeNode = E("typeGroup").firstChild; typeNode; typeNode = typeNode.nextSibling)
if (typeNode.getAttribute("disabled") != "true")
typeNode.checked = select;
updateFilter();
}

@ -0,0 +1,107 @@
<?xml version="1.0"?>
<!-- This Source Code is subject to the terms of the Mozilla Public License
- version 2.0 (the "License"). You can obtain a copy of the License at
- http://mozilla.org/MPL/2.0/. -->
#filter substitution
<!DOCTYPE overlay SYSTEM "chrome://@ADDON_CHROME_NAME@/locale/composer.dtd">
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://@ADDON_CHROME_NAME@/skin/composer.css" type="text/css"?>
<dialog id="abp-composer"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="&dialog.title;"
onload="init()"
ondialogaccept="return addFilter()"
ondialogdisclosure="setAdvancedMode(!advancedMode)"
buttons="accept,cancel,disclosure"
width="800px"
height="400px"
persist="screenX screenY width height sizemode advancedMode"
advancedMode="false"
buttonlabelaccept="&accept.label;"
buttonlabeldisclosure="&advanced.label;"
buttonlabeldisclosure_on="&advanced.label;"
buttonlabeldisclosure_off="&basic.label;"
windowtype="abp:composer">
<script type="application/x-javascript;version=1.7" src="utils.js"/>
<script type="application/x-javascript;version=1.7" src="composer.js"/>
<popupset>
<tooltip id="domainRestrictionHelp" label="&domainRestriction.help;"/>
</popupset>
<description id="disabledWarning" hidden="true" textTemplate="&disabled.warning;">
<label class="text-link" onclick="doEnable()"/>
</description>
<hbox id="filterBox" align="center">
<label control="filter" value="&filter.label;" accesskey="&filter.accesskey;"/>
<textbox id="filter" flex="1" tabindex="-1" readonly="true"/>
<button id="preferences" label="&preferences.label;" accesskey="&preferences.accesskey;" oncommand="openPreferences()"/>
</hbox>
<radiogroup orient="horizontal" id="filterType" oncommand="updateFilter()">
<radio label="&type.filter.label;" accesskey="&type.filter.accesskey;" value="filterlist" flex="1"/>
<radio label="&type.whitelist.label;" accesskey="&type.whitelist.accesskey;" value="whitelist" flex="1"/>
</radiogroup>
<hbox flex="1">
<groupbox id="pattern" flex="1">
<caption label="&pattern.label;"/>
<radiogroup id="patternGroup" flex="1" oncommand="updatePatternSelection()" style="overflow: auto;">
<description id="patternExplanation">&pattern.explanation;</description>
<description id="regexpWarning" hidden="true">&regexp.warning;</description>
<description id="shortpatternWarning" hidden="true">&shortpattern.warning;</description>
<description id="matchWarning" hidden="true">&match.warning;</description>
<hbox id="customPatternBox">
<radio id="customPatternRadio" label="&custom.pattern.label;" accesskey="&custom.pattern.accesskey;" value="" control="customPattern"/>
<textbox id="customPattern" flex="1" oninput="updateCustomPattern()"/>
</hbox>
</radiogroup>
<hbox id="anchorGroup" pack="start" align="baseline">
<label value="&anchors.label;"/>
<description flex="1" style="margin: 0; padding: 0;">
<checkbox id="anchorStart" labelRegular="&anchor.start.label;" accesskeyRegular="&anchor.start.accesskey;"
labelFlexible="&anchor.start.flexible.label;" accesskeyFlexible="&anchor.start.flexible.accesskey;"
oncommand="updateFilter()"/>
<checkbox id="anchorEnd" label="&anchor.end.label;" accesskey="&anchor.end.accesskey;" oncommand="updateFilter()"/>
</description>
</hbox>
</groupbox>
<groupbox id="options">
<caption label="&options.label;"/>
<checkbox id="firstParty" label="&firstParty.label;" accesskey="&firstParty.accesskey;" oncommand="checkboxUpdated(this);"/>
<checkbox id="thirdParty" label="&thirdParty.label;" accesskey="&thirdParty.accesskey;" oncommand="checkboxUpdated(this);"/>
<checkbox id="matchCase" label="&matchCase.label;" accesskey="&matchCase.accesskey;" oncommand="checkboxUpdated(this);"/>
<hbox align="baseline">
<checkbox id="domainRestrictionEnabled" label="&domainRestriction.label;" accesskey="&domainRestriction.accesskey;" oncommand="checkboxUpdated(this);"/>
<description class="help" value="?" tooltip="domainRestrictionHelp"/>
</hbox>
<textbox id="domainRestriction" oninput="updateFilter()"/>
<label id="typeGroupLabel" value="&types.label;"/>
<hbox>
<label id="selectAllTypes" class="text-link" value="&selectAllTypes.label;" onclick="selectAllTypes(true)"/>
<spacer flex="1"/>
<label id="unselectAllTypes" class="text-link" value="&unselectAllTypes.label;" onclick="selectAllTypes(false)"/>
</hbox>
<vbox flex="1" id="typeGroup"/>
<vbox>
<label control="collapse" value="&collapse.label;" accesskey="&collapse.accesskey;"/>
<menulist id="collapse" oncommand="updateFilter()">
<menupopup>
<menuitem id="collapseDefault" value="" label_yes="&collapse.default.yes.label;" label_no="&collapse.default.no.label;" selected="true"/>
<menuitem label="&collapse.yes.label;" value="collapse"/>
<menuitem label="&collapse.no.label;" value="~collapse"/>
</menupopup>
</menulist>
</vbox>
</groupbox>
</hbox>
</dialog>

@ -0,0 +1,96 @@
<html>
<head>
<title>Adblock Plus Errors</title>
<style type="text/css">
.warning, .error
{
border: 1px dashed black;
margin: 5px;
padding: 2px;
white-space: pre-wrap;
}
.error
{
background-color: #fff0f0;
}
.warning
{
background-color: #ffffe0;
}
button
{
float: right;
}
</style>
</head>
<body>
<button onclick="window.location.reload();">Refresh</button>
<button onclick="clearErrors();">Clear errors</button>
<script type="application/x-javascript;version=1.7">
try {
Components.utils.import("chrome://adblockplus-modules/content/Utils.jsm");
let text = "You are running Adblock Plus " + Utils.addonVersion;
let build = Utils.addonBuild;
if (build)
text += ", build " + build;
text += ".";
document.write("<p>" + text + "</p>");
} catch (e) {}
let messages = {};
Components.classes["@mozilla.org/consoleservice;1"]
.getService(Components.interfaces.nsIConsoleService)
.getMessageArray(messages, {});
messages = messages.value || [];
messages = messages.filter(function(message)
{
return (message instanceof Components.interfaces.nsIScriptError &&
!/^https?:/i.test(message.sourceName) &&
(/adblock/i.test(message.errorMessage) || /adblock/i.test(message.sourceName)));
});
if (messages.length)
{
document.write("<p>Errors related to Adblock Plus:</p>");
for each (let message in messages)
{
let type = (message.flags & Components.interfaces.nsIScriptError.warningFlag ? "warning" : "error");
let html = "<b>" + (type == "warning" ? "Warning:" : "Error:") + "</b><br>";
html += encodeHTML(message.errorMessage) + "<br><br>";
if (message.sourceLine)
html += "Source line: " + encodeHTML(message.sourceLine) + "<br>";
if (message.sourceName)
html += "Location: " + encodeHTML(message.sourceName) + " line " + message.lineNumber + "<br>";
html = html.replace(/(<br>)+$/, "");
document.write("<div class='" + type + "'>" +
html +
"</div>");
}
}
else
{
document.write("<p>No errors found.</p>");
}
function encodeHTML(string)
{
return string.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
}
function clearErrors()
{
Components.classes["@mozilla.org/consoleservice;1"]
.getService(Components.interfaces.nsIConsoleService)
.reset();
window.location.reload();
}
</script>
</body>
</html>

@ -0,0 +1,331 @@
/*
* This Source Code is subject to the terms of the Mozilla Public License
* version 2.0 (the "License"). You can obtain a copy of the License at
* http://mozilla.org/MPL/2.0/.
*/
Cu.import("resource://gre/modules/FileUtils.jsm");
/**
* Implementation of backup and restore functionality.
* @class
*/
var Backup =
{
/**
* Template for menu items to be displayed in the Restore menu (for automated
* backups).
* @type Element
*/
restoreTemplate: null,
/**
* Element after which restore items should be inserted.
* @type Element
*/
restoreInsertionPoint: null,
/**
* Regular expression to recognize checksum comments.
*/
CHECKSUM_REGEXP: /^!\s*checksum[\s\-:]+([\w\+\/]+)/i,
/**
* Regular expression to recognize group title comments.
*/
GROUPTITLE_REGEXP: /^!\s*\[(.*)\]((?:\/\w+)*)\s*$/,
/**
* Initializes backup UI.
*/
init: function()
{
this.restoreTemplate = E("restoreBackupTemplate");
this.restoreInsertionPoint = this.restoreTemplate.previousSibling;
this.restoreTemplate.parentNode.removeChild(this.restoreTemplate);
this.restoreTemplate.removeAttribute("id");
this.restoreTemplate.removeAttribute("hidden");
},
/**
* Gets the default download dir, as used by the browser itself.
*/
getDefaultDir: function() /**nsIFile*/
{
try
{
return Utils.prefService.getComplexValue("browser.download.lastDir", Ci.nsILocalFile);
}
catch (e)
{
// No default download location. Default to desktop.
return FileUtils.getDir("Desk", [], false);
}
},
/**
* Saves new default download dir after the user chose a different directory to
* save his files to.
*/
saveDefaultDir: function(/**nsIFile*/ dir)
{
try
{
Utils.prefService.setComplexValue("browser.download.lastDir", Ci.nsILocalFile, dir);
} catch(e) {};
},
/**
* Called when the Restore menu is being opened, fills in "Automated backup"
* entries.
*/
fillRestorePopup: function()
{
while (this.restoreInsertionPoint.nextSibling && !this.restoreInsertionPoint.nextSibling.id)
this.restoreInsertionPoint.parentNode.removeChild(this.restoreInsertionPoint.nextSibling);
let files = FilterStorage.getBackupFiles().reverse();
for (let i = 0; i < files.length; i++)
{
let file = files[i];
let item = this.restoreTemplate.cloneNode(true);
let label = item.getAttribute("label");
label = label.replace(/\?1\?/, Utils.formatTime(file.lastModifiedTime));
item.setAttribute("label", label);
item.addEventListener("command", function()
{
Backup.restoreAllData(file);
}, false);
this.restoreInsertionPoint.parentNode.insertBefore(item, this.restoreInsertionPoint.nextSibling);
}
},
/**
* Lets the user choose a file to restore filters from.
*/
restoreFromFile: function()
{
let picker = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
picker.init(window, E("backupButton").getAttribute("_restoreDialogTitle"), picker.modeOpen);
picker.defaultExtension = ".ini";
picker.appendFilter(E("backupButton").getAttribute("_fileFilterComplete"), "*.ini");
picker.appendFilter(E("backupButton").getAttribute("_fileFilterCustom"), "*.txt");
if (picker.show() != picker.returnCancel)
{
this.saveDefaultDir(picker.file.parent);
if (picker.filterIndex == 0)
this.restoreAllData(picker.file);
else
this.restoreCustomFilters(picker.file);
}
},
/**
* Restores patterns.ini from a file.
*/
restoreAllData: function(/**nsIFile*/ file)
{
let stream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance(Ci.nsIFileInputStream);
stream.init(file, FileUtils.MODE_RDONLY, FileUtils.PERMS_FILE, 0);
stream.QueryInterface(Ci.nsILineInputStream);
let lines = [];
let line = {value: null};
if (stream.readLine(line))
lines.push(line.value);
if (stream.readLine(line))
lines.push(line.value);
stream.close();
let match;
if (lines.length < 2 || lines[0] != "# Adblock Plus preferences" || !(match = /version=(\d+)/.exec(lines[1])))
{
Utils.alert(window, E("backupButton").getAttribute("_restoreError"), E("backupButton").getAttribute("_restoreDialogTitle"));
return;
}
let warning = E("backupButton").getAttribute("_restoreCompleteWarning");
let minVersion = parseInt(match[1], 10);
if (minVersion > FilterStorage.formatVersion)
warning += "\n\n" + E("backupButton").getAttribute("_restoreVersionWarning");
if (!Utils.confirm(window, warning, E("backupButton").getAttribute("_restoreDialogTitle")))
return;
FilterStorage.loadFromDisk(file);
},
/**
* Restores custom filters from a file.
*/
restoreCustomFilters: function(/**nsIFile*/ file)
{
IO.readFromFile(file, true, {
seenHeader: false,
subscription: null,
process: function(line)
{
if (!this.seenHeader)
{
// This should be a header
this.seenHeader = true;
let match = /\[Adblock(?:\s*Plus\s*([\d\.]+)?)?\]/i.exec(line);
if (match)
{
let warning = E("backupButton").getAttribute("_restoreCustomWarning");
let minVersion = match[1];
if (minVersion && Utils.versionComparator.compare(minVersion, Utils.addonVersion) > 0)
warning += "\n\n" + E("backupButton").getAttribute("_restoreVersionWarning");
if (Utils.confirm(window, warning, E("backupButton").getAttribute("_restoreDialogTitle")))
{
let subscriptions = FilterStorage.subscriptions.filter(function(s) s instanceof SpecialSubscription);
for (let i = 0; i < subscriptions.length; i++)
FilterStorage.removeSubscription(subscriptions[i]);
return;
}
else
throw Cr.NS_BASE_STREAM_WOULD_BLOCK;
}
else
throw new Error("Invalid file");
}
else if (line === null)
{
// End of file
if (this.subscription)
FilterStorage.addSubscription(this.subscription);
E("tabs").selectedIndex = 1;
}
else if (Backup.CHECKSUM_REGEXP.test(line))
{
// Ignore checksums
}
else if (Backup.GROUPTITLE_REGEXP.test(line))
{
// New group start
if (this.subscription)
FilterStorage.addSubscription(this.subscription);
let [, title, options] = Backup.GROUPTITLE_REGEXP.exec(line);
this.subscription = SpecialSubscription.create(title);
let defaults = [];
if (options)
options = options.split("/");
for (let j = 0; j < options.length; j++)
if (options[j] in SpecialSubscription.defaultsMap)
defaults.push(options[j]);
if (defaults.length)
this.subscription.defaults = defaults;
}
else
{
// Regular filter
let filter = Filter.fromText(Filter.normalize(line));
if (filter)
{
if (!this.subscription)
this.subscription = SpecialSubscription.create(Utils.getString("newGroup_title"));
this.subscription.filters.push(filter);
}
}
}
}, function(e)
{
if (e && e.result != Cr.NS_BASE_STREAM_WOULD_BLOCK)
{
Cu.reportError(e);
Utils.alert(window, E("backupButton").getAttribute("_restoreError"), E("backupButton").getAttribute("_restoreDialogTitle"));