| Index: chrome/content/ui/filters-backup.js | 
| =================================================================== | 
| --- a/chrome/content/ui/filters-backup.js | 
| +++ b/chrome/content/ui/filters-backup.js | 
| @@ -103,17 +103,17 @@ var Backup = | 
| for (let backup of backups) | 
| { | 
| let item = this.restoreTemplate.cloneNode(true); | 
| let label = item.getAttribute("label"); | 
| label = label.replace(/\?1\?/, Utils.formatTime(backup.lastModified)); | 
| item.setAttribute("label", label); | 
| item.addEventListener("command", function() | 
| { | 
| - Backup.restoreAllData(backup.file); | 
| + FilterStorage.restoreBackup(backup.index); | 
| }, false); | 
| this.restoreInsertionPoint.parentNode.insertBefore(item, this.restoreInsertionPoint.nextSibling); | 
| } | 
| }); | 
| }, | 
| /** | 
| * Lets the user choose a file to restore filters from. | 
| @@ -136,44 +136,50 @@ var Backup = | 
| } | 
| }, | 
| /** | 
| * 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 sink = FilterStorage.importData(); | 
| let lines = []; | 
| - let line = {value: null}; | 
| - if (stream.readLine(line)) | 
| - lines.push(line.value); | 
| - if (stream.readLine(line)) | 
| - lines.push(line.value); | 
| - stream.close(); | 
| + IO.readFromFile(file, { | 
| + process(line) | 
| + { | 
| + if (line === null) | 
| + { | 
| + 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 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"); | 
| - 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; | 
| + } | 
| + else if (lines.length < 2) | 
| + lines.push(line); | 
| - if (!Utils.confirm(window, warning, E("backupButton").getAttribute("_restoreDialogTitle"))) | 
| - return; | 
| - | 
| - FilterStorage.loadFromDisk(file); | 
| + sink(line); | 
| + } | 
| + }, error => | 
| + { | 
| + if (error) | 
| + alert(error); | 
| + else | 
| + FilterStorage.saveToDisk(); | 
| + }); | 
| }, | 
| /** | 
| * Restores custom filters from a file. | 
| */ | 
| restoreCustomFilters: function(/**nsIFile*/ file) | 
| { | 
| IO.readFromFile(file, { | 
| @@ -279,17 +285,21 @@ var Backup = | 
| } | 
| }, | 
| /** | 
| * Writes all patterns.ini data to a file. | 
| */ | 
| backupAllData: function(/**nsIFile*/ file) | 
| { | 
| - FilterStorage.saveToDisk(file); | 
| + IO.writeToFile(file, FilterStorage.exportData(), error => | 
| + { | 
| + if (error) | 
| + alert(error); | 
| + }); | 
| }, | 
| /** | 
| * Writes user's custom filters to a file. | 
| */ | 
| backupCustomFilters: function(/**nsIFile*/ file) | 
| { | 
| let subscriptions = FilterStorage.subscriptions.filter(s => s instanceof SpecialSubscription); |