Left: | ||
Right: |
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 = Array.prototype.slice.call(domain).reverse().join(""); | |
Thomas Greiner
2012/09/26 15:59:35
also in onWhitelistEntryAdded function
| |
99 addSuffix(rules.domain, reverse, CUSTOM_RULE_PRIORITY); | |
100 } | |
101 exports.onWhitelistEntryAdded = onWhitelistEntryAdded; | |
102 | |
103 function onWhitelistEntryRemoved(domain) | |
104 { | |
105 let reverse = Array.prototype.slice.call(domain).reverse().join(""); | |
Thomas Greiner
2012/09/26 15:49:13
It looks less confusing if you do it this way:
le
Wladimir Palant
2012/09/27 14:55:06
domain is a string - string.slice() returns anothe
| |
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 27 matching lines...) Expand all Loading... | |
143 let customRules = Prefs.custom_replace; | 238 let customRules = Prefs.custom_replace; |
144 for (let searchString in customRules) | 239 for (let searchString in customRules) |
145 { | 240 { |
146 let replacement = customRules[searchString]; | 241 let replacement = customRules[searchString]; |
147 searchString = searchString.toLowerCase(); | 242 searchString = searchString.toLowerCase(); |
148 if (/^re:+/.test(searchString)) | 243 if (/^re:+/.test(searchString)) |
149 domain = domain.replace(new RegExp(RegExp.rightContext, "g"), replacement) ; | 244 domain = domain.replace(new RegExp(RegExp.rightContext, "g"), replacement) ; |
150 else | 245 else |
151 domain = domain.replace(searchString, replacement); | 246 domain = domain.replace(searchString, replacement); |
152 } | 247 } |
153 | |
154 // Apply user's whitelist | |
155 let whitelist = Prefs.whitelist; | |
156 if (whitelist.hasOwnProperty(domain) || /^www\./.test(domain) && whitelist.has OwnProperty(domain.substr(4))) | |
157 { | |
158 return domain; | |
159 } | |
160 | 248 |
161 // Now apply our rules on the domain name | 249 // Now apply our rules on the domain name |
162 for (let i = 0, l = rules.expressions.length; i < l; i++) | 250 for (let i = 0, l = rules.expressions.length; i < l; i++) |
163 domain = applyExpression(domain, rules.expressions[i]); | 251 domain = applyExpression(domain, rules.expressions[i]); |
164 | 252 |
165 // Find similar known domains, test domains without the www. prefix | 253 // Find similar known domains, test domains without the www. prefix |
166 if (domain.substr(0, 4) == "www.") | 254 if (domain.substr(0, 4) == "www.") |
167 domain = "www." + getBestMatch(domain.substr(4), rules.domain, 1, "."); | 255 domain = "www." + getBestMatch(domain.substr(4), rules.domain, 1, "."); |
168 else | 256 else |
169 domain = getBestMatch(domain, rules.domain, 1, "."); | 257 domain = getBestMatch(domain, rules.domain, 1, "."); |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
312 bestSuggestionDistance = distance; | 400 bestSuggestionDistance = distance; |
313 bestSuggestionMatched = matchedLen; | 401 bestSuggestionMatched = matchedLen; |
314 bestSuggestionPriority = priority; | 402 bestSuggestionPriority = priority; |
315 } | 403 } |
316 } | 404 } |
317 if (bestSuggestion) | 405 if (bestSuggestion) |
318 return input.substr(0, input.length - bestSuggestionMatched) + bestSuggestio n; | 406 return input.substr(0, input.length - bestSuggestionMatched) + bestSuggestio n; |
319 else | 407 else |
320 return input; | 408 return input; |
321 } | 409 } |
OLD | NEW |