| OLD | NEW |
| 1 /* This Source Code Form is subject to the terms of the Mozilla Public | 1 /* This Source Code Form is subject to the terms of the Mozilla Public |
| 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, | 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
| 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ | 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| 4 | 4 |
| 5 Cu.import("resource://gre/modules/Services.jsm"); | 5 Cu.import("resource://gre/modules/Services.jsm"); |
| 6 Cu.import("resource://gre/modules/FileUtils.jsm"); | 6 Cu.import("resource://gre/modules/FileUtils.jsm"); |
| 7 | 7 |
| 8 let {Prefs} = require("prefs"); | 8 let {Prefs} = require("prefs"); |
| 9 | 9 |
| 10 let RULES_VERSION = 2; | 10 let RULES_VERSION = 2; |
| 11 | 11 |
| 12 let CUSTOM_RULE_PRIORITY = 0x7FFFFFFF; |
| 13 |
| 12 let rules = {expressions: []}; | 14 let rules = {expressions: []}; |
| 13 | 15 |
| 14 loadRules(); | 16 loadRules(); |
| 15 | 17 |
| 16 // Make first attempt to update rules after five minutes | 18 // Make first attempt to update rules after five minutes |
| 17 let updateTimer = null; | 19 let updateTimer = null; |
| 18 updateTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); | 20 updateTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); |
| 19 updateTimer.initWithCallback(onTimer, 1000 * 60 * 5, Ci.nsITimer.TYPE_REPEATING_
SLACK); | 21 updateTimer.initWithCallback(onTimer, 1000 * 60 * 5, Ci.nsITimer.TYPE_REPEATING_
SLACK); |
| 20 onShutdown.add(function() updateTimer.cancel()); | 22 onShutdown.add(function() updateTimer.cancel()); |
| 21 | 23 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 39 request.addEventListener("load", function() | 41 request.addEventListener("load", function() |
| 40 { | 42 { |
| 41 try | 43 try |
| 42 { | 44 { |
| 43 // Remove comments from the file if any | 45 // Remove comments from the file if any |
| 44 let data = JSON.parse(request.responseText.replace(/^\s*\/\/.*/mg, "")); | 46 let data = JSON.parse(request.responseText.replace(/^\s*\/\/.*/mg, "")); |
| 45 if (ignoreVersion || data.version == RULES_VERSION) | 47 if (ignoreVersion || data.version == RULES_VERSION) |
| 46 { | 48 { |
| 47 rules = data; | 49 rules = data; |
| 48 callback(true); | 50 callback(true); |
| 51 |
| 52 // Add user-defined rules after calling the callback - if the callback |
| 53 // saves the rules then the custom rules won't be included. |
| 54 addCustomRules(); |
| 49 } | 55 } |
| 50 else | 56 else |
| 51 callback(false); | 57 callback(false); |
| 52 } | 58 } |
| 53 catch (e) | 59 catch (e) |
| 54 { | 60 { |
| 55 Cu.reportError(e); | 61 Cu.reportError(e); |
| 56 callback(false); | 62 callback(false); |
| 57 } | 63 } |
| 58 }, false); | 64 }, false); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 74 } | 80 } |
| 75 | 81 |
| 76 function getRuleFile() | 82 function getRuleFile() |
| 77 { | 83 { |
| 78 let result = FileUtils.getFile("ProfD", ["url-fixer-rules.json"]); | 84 let result = FileUtils.getFile("ProfD", ["url-fixer-rules.json"]); |
| 79 | 85 |
| 80 getRuleFile = function() result; | 86 getRuleFile = function() result; |
| 81 return getRuleFile(); | 87 return getRuleFile(); |
| 82 } | 88 } |
| 83 | 89 |
| 90 function addCustomRules() |
| 91 { |
| 92 for (let domain in Prefs.whitelist) |
| 93 onWhitelistEntryAdded(domain); |
| 94 } |
| 95 |
| 96 function onWhitelistEntryAdded(domain) |
| 97 { |
| 98 let reverse = domain.split("").reverse().join(""); |
| 99 addSuffix(rules.domain, reverse, CUSTOM_RULE_PRIORITY); |
| 100 } |
| 101 exports.onWhitelistEntryAdded = onWhitelistEntryAdded; |
| 102 |
| 103 function onWhitelistEntryRemoved(domain) |
| 104 { |
| 105 let reverse = domain.split("").reverse().join(""); |
| 106 removeSuffix(rules.domain, reverse, CUSTOM_RULE_PRIORITY); |
| 107 } |
| 108 exports.onWhitelistEntryRemoved = onWhitelistEntryRemoved; |
| 109 |
| 110 function addSuffix(tree, suffix, priority) |
| 111 { |
| 112 if (suffix.length == 0) |
| 113 { |
| 114 // We are at the last character, just put our priority here |
| 115 tree[""] = " " + priority; |
| 116 return; |
| 117 } |
| 118 |
| 119 let c = suffix[0]; |
| 120 if (c in tree) |
| 121 { |
| 122 let existing = tree[c]; |
| 123 if (typeof existing == "string") |
| 124 { |
| 125 // Single choice for this suffix, maybe the same entry? |
| 126 if (existing.substr(0, suffix.length - 1) == suffix.substr(1) && existing[
suffix.length - 1] == " ") |
| 127 { |
| 128 // Same entry, simply replace it by new priority |
| 129 tree[c] = suffix.substr(1) + " " + priority; |
| 130 } |
| 131 else |
| 132 { |
| 133 // Different entry, need to add a new branching point and go deeper |
| 134 if (existing[0] == " ") |
| 135 tree[c] = {"": existing}; |
| 136 else |
| 137 { |
| 138 tree[c] = {}; |
| 139 tree[c][existing[0]] = existing.substr(1); |
| 140 } |
| 141 addSuffix(tree[c], suffix.substr(1), priority); |
| 142 } |
| 143 } |
| 144 else |
| 145 { |
| 146 // Multiple choices for this suffix - go deeper |
| 147 addSuffix(existing, suffix.substr(1), priority); |
| 148 } |
| 149 } |
| 150 else |
| 151 { |
| 152 // No existing entry yet, just add ours |
| 153 tree[c] = suffix.substr(1) + " " + priority; |
| 154 } |
| 155 } |
| 156 |
| 157 function removeSuffix(tree, suffix, priority) |
| 158 { |
| 159 if (suffix.length == 0) |
| 160 { |
| 161 // We are at the last character, check whether there is an entry with |
| 162 // matching priority |
| 163 if ("" in tree && tree[""] == " " + priority) |
| 164 delete tree[""]; |
| 165 return; |
| 166 } |
| 167 |
| 168 let c = suffix[0]; |
| 169 if (!(c in tree)) |
| 170 return; |
| 171 |
| 172 if (typeof tree[c] == "string") |
| 173 { |
| 174 // Single entry - check whether it is the right one |
| 175 if (tree[c] == suffix.substr(1) + " " + priority) |
| 176 delete tree[c]; |
| 177 } |
| 178 else |
| 179 { |
| 180 // Multiple entries, need to go deeper |
| 181 removeSuffix(tree[c], suffix.substr(1), priority); |
| 182 } |
| 183 } |
| 184 |
| 84 function onTimer() | 185 function onTimer() |
| 85 { | 186 { |
| 86 // Next check in 1 hour | 187 // Next check in 1 hour |
| 87 updateTimer.delay = 1000 * 60 * 60; | 188 updateTimer.delay = 1000 * 60 * 60; |
| 88 | 189 |
| 89 // Only download rules every three days | 190 // Only download rules every three days |
| 90 let nextUpdate = Prefs.lastRuleUpdate + 60 * 60 * 24 * 3; | 191 let nextUpdate = Prefs.lastRuleUpdate + 60 * 60 * 24 * 3; |
| 91 if (nextUpdate > Date.now() / 1000) | 192 if (nextUpdate > Date.now() / 1000) |
| 92 return; | 193 return; |
| 93 | 194 |
| 94 loadRulesFrom("http://urlfixer.org/download/rules.json?version=" + RULES_VERSI
ON, false, function(success) | 195 loadRulesFrom("http://urlfixer.org/download/rules.json?version=" + RULES_VERSI
ON, false, function(success) |
| 95 { | 196 { |
| 96 if (success) | 197 if (success) |
| 97 { | 198 { |
| 98 rules.timestamp = Date.now(); | 199 rules.timestamp = Date.now(); |
| 99 | 200 |
| 100 var dynRules = require("updateRules").updateRules(); | |
| 101 for(var i in dynRules) | |
| 102 { | |
| 103 rules[i] = dynRules[i]; | |
| 104 } | |
| 105 | |
| 106 try | 201 try |
| 107 { | 202 { |
| 108 // Save the rules to file. | 203 // Save the rules to file. |
| 109 let rulesText = JSON.stringify(rules); | 204 let rulesText = JSON.stringify(rules); |
| 110 let fileStream = FileUtils.openSafeFileOutputStream(getRuleFile()); | 205 let fileStream = FileUtils.openSafeFileOutputStream(getRuleFile()); |
| 111 let stream = Cc["@mozilla.org/intl/converter-output-stream;1"].createIns
tance(Ci.nsIConverterOutputStream); | 206 let stream = Cc["@mozilla.org/intl/converter-output-stream;1"].createIns
tance(Ci.nsIConverterOutputStream); |
| 112 stream.init(fileStream, "UTF-8", 16384, Ci.nsIConverterInputStream.DEFAU
LT_REPLACEMENT_CHARACTER); | 207 stream.init(fileStream, "UTF-8", 16384, Ci.nsIConverterInputStream.DEFAU
LT_REPLACEMENT_CHARACTER); |
| 113 stream.writeString(rulesText); | 208 stream.writeString(rulesText); |
| 114 stream.flush(); | 209 stream.flush(); |
| 115 FileUtils.closeSafeFileOutputStream(fileStream); | 210 FileUtils.closeSafeFileOutputStream(fileStream); |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 bestSuggestionDistance = distance; | 400 bestSuggestionDistance = distance; |
| 306 bestSuggestionMatched = matchedLen; | 401 bestSuggestionMatched = matchedLen; |
| 307 bestSuggestionPriority = priority; | 402 bestSuggestionPriority = priority; |
| 308 } | 403 } |
| 309 } | 404 } |
| 310 if (bestSuggestion) | 405 if (bestSuggestion) |
| 311 return input.substr(0, input.length - bestSuggestionMatched) + bestSuggestio
n; | 406 return input.substr(0, input.length - bestSuggestionMatched) + bestSuggestio
n; |
| 312 else | 407 else |
| 313 return input; | 408 return input; |
| 314 } | 409 } |
| OLD | NEW |