!import
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /*
3 //@line 40 "/home/visbrero/mnt/roisin/rev_control/hg/mozilla/toolkit/mozapps/extensions/src/nsBlocklistService.js"
4 */
5
6 const Cc = Components.classes;
7 const Ci = Components.interfaces;
8 const Cr = Components.results;
9
10 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
11
12 const TOOLKIT_ID = "toolkit@mozilla.org"
13 const KEY_PROFILEDIR = "ProfD";
14 const KEY_APPDIR = "XCurProcD";
15 const FILE_BLOCKLIST = "blocklist.xml";
16 const PREF_BLOCKLIST_URL = "extensions.blocklist.url";
17 const PREF_BLOCKLIST_ENABLED = "extensions.blocklist.enabled";
18 const PREF_BLOCKLIST_INTERVAL = "extensions.blocklist.interval";
19 const PREF_GENERAL_USERAGENT_LOCALE = "general.useragent.locale";
20 const PREF_PARTNER_BRANCH = "app.partner.";
21 const PREF_APP_DISTRIBUTION = "distribution.id";
22 const PREF_APP_DISTRIBUTION_VERSION = "distribution.version";
23 const PREF_APP_UPDATE_CHANNEL = "app.update.channel";
24 const PREF_EM_LOGGING_ENABLED = "extensions.logging.enabled";
25 const XMLURI_BLOCKLIST = "http://www.mozilla.org/2006/addons-blocklist";
26 const XMLURI_PARSE_ERROR = "http://www.mozilla.org/newlayout/xml/parsererror.xml"
27 const UNKNOWN_XPCOM_ABI = "unknownABI";
28
29 const MODE_RDONLY = 0x01;
30 const MODE_WRONLY = 0x02;
31 const MODE_CREATE = 0x08;
32 const MODE_APPEND = 0x10;
33 const MODE_TRUNCATE = 0x20;
34
35 const PERMS_FILE = 0644;
36 const PERMS_DIRECTORY = 0755;
37
38 var gApp = null;
39 var gPref = null;
40 var gOS = null;
41 var gConsole = null;
42 var gVersionChecker = null;
43 var gLoggingEnabled = null;
44 var gABI = null;
45 var gOSVersion = null;
46
47 // shared code for suppressing bad cert dialogs
48 //@line 40 "/home/visbrero/mnt/roisin/rev_control/hg/mozilla/toolkit/mozapps/shared/src/badCertHandler.js"
49
50 /**
51 * Only allow built-in certs for HTTPS connections. See bug 340198.
52 */
checkCert
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
53 function checkCert(channel) {
54 if (!channel.originalURI.schemeIs("https")) // bypass
55 return;
56
57 const Ci = Components.interfaces;
58 var cert =
59 channel.securityInfo.QueryInterface(Ci.nsISSLStatusProvider).
60 SSLStatus.QueryInterface(Ci.nsISSLStatus).serverCert;
61
62 var issuer = cert.issuer;
63 while (issuer && !cert.equals(issuer)) {
64 cert = issuer;
65 issuer = cert.issuer;
66 }
67
68 if (!issuer || issuer.tokenName != "Builtin Object Token")
69 throw "cert issuer is not built-in";
70 }
71
72 /**
73 * This class implements nsIBadCertListener. It's job is to prevent "bad cert"
74 * security dialogs from being shown to the user. It is better to simply fail
75 * if the certificate is bad. See bug 304286.
76 */
BadCertHandler
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
77 function BadCertHandler() {
78 }
79 BadCertHandler.prototype = {
80
81 // nsIChannelEventSink
onChannelRedirect
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
82 onChannelRedirect: function(oldChannel, newChannel, flags) {
83 // make sure the certificate of the old channel checks out before we follow
84 // a redirect from it. See bug 340198.
85 checkCert(oldChannel);
86 },
87
88 // Suppress any certificate errors
notifyCertProblem
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
89 notifyCertProblem: function(socketInfo, status, targetSite) {
90 return true;
91 },
92
93 // Suppress any ssl errors
notifySSLError
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
94 notifySSLError: function(socketInfo, error, targetSite) {
95 return true;
96 },
97
98 // nsIInterfaceRequestor
getInterface
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
99 getInterface: function(iid) {
100 return this.QueryInterface(iid);
101 },
102
103 // nsISupports
QueryInterface
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
104 QueryInterface: function(iid) {
105 if (!iid.equals(Components.interfaces.nsIChannelEventSink) &&
106 !iid.equals(Components.interfaces.nsIBadCertListener2) &&
107 !iid.equals(Components.interfaces.nsISSLErrorListener) &&
108 !iid.equals(Components.interfaces.nsIInterfaceRequestor) &&
109 !iid.equals(Components.interfaces.nsISupports))
110 throw Components.results.NS_ERROR_NO_INTERFACE;
111 return this;
112 }
113 };
114 //@line 85 "/home/visbrero/mnt/roisin/rev_control/hg/mozilla/toolkit/mozapps/extensions/src/nsBlocklistService.js"
115
116 /**
117 * Logs a string to the error console.
118 * @param string
119 * The string to write to the error console..
120 */
LOG
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
121 function LOG(string) {
122 if (gLoggingEnabled) {
123 dump("*** " + string + "\n");
124 if (gConsole)
125 gConsole.logStringMessage(string);
126 }
127 }
128
129 /**
130 * Gets a preference value, handling the case where there is no default.
131 * @param func
132 * The name of the preference function to call, on nsIPrefBranch
133 * @param preference
134 * The name of the preference
135 * @param defaultValue
136 * The default value to return in the event the preference has
137 * no setting
138 * @returns The value of the preference, or undefined if there was no
139 * user or default value.
140 */
getPref
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
141 function getPref(func, preference, defaultValue) {
142 try {
143 return gPref[func](preference);
144 }
145 catch (e) {
146 }
147 return defaultValue;
148 }
149
150 /**
151 * Gets the file at the specified hierarchy under a Directory Service key.
152 * @param key
153 * The Directory Service Key to start from
154 * @param pathArray
155 * An array of path components to locate beneath the directory
156 * specified by |key|. The last item in this array must be the
157 * leaf name of a file.
158 * @return nsIFile object for the file specified. The file is NOT created
159 * if it does not exist, however all required directories along
160 * the way are.
161 */
getFile
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
162 function getFile(key, pathArray) {
163 var fileLocator = Cc["@mozilla.org/file/directory_service;1"].
164 getService(Ci.nsIProperties);
165 var file = fileLocator.get(key, Ci.nsILocalFile);
166 for (var i = 0; i < pathArray.length - 1; ++i) {
167 file.append(pathArray[i]);
168 if (!file.exists())
169 file.create(Ci.nsILocalFile.DIRECTORY_TYPE, PERMS_DIRECTORY);
170 }
171 file.followLinks = false;
172 file.append(pathArray[pathArray.length - 1]);
173 return file;
174 }
175
176 /**
177 * Opens a safe file output stream for writing.
178 * @param file
179 * The file to write to.
180 * @param modeFlags
181 * (optional) File open flags. Can be undefined.
182 * @returns nsIFileOutputStream to write to.
183 */
openSafeFileOutputStream
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
184 function openSafeFileOutputStream(file, modeFlags) {
185 var fos = Cc["@mozilla.org/network/safe-file-output-stream;1"].
186 createInstance(Ci.nsIFileOutputStream);
187 if (modeFlags === undefined)
188 modeFlags = MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE;
189 if (!file.exists())
190 file.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, PERMS_FILE);
191 fos.init(file, modeFlags, PERMS_FILE, 0);
192 return fos;
193 }
194
195 /**
196 * Closes a safe file output stream.
197 * @param stream
198 * The stream to close.
199 */
closeSafeFileOutputStream
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
200 function closeSafeFileOutputStream(stream) {
201 if (stream instanceof Ci.nsISafeOutputStream)
202 stream.finish();
203 else
204 stream.close();
205 }
206
207 /**
208 * Constructs a URI to a spec.
209 * @param spec
210 * The spec to construct a URI to
211 * @returns The nsIURI constructed.
212 */
newURI
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
213 function newURI(spec) {
214 var ioServ = Cc["@mozilla.org/network/io-service;1"].
215 getService(Ci.nsIIOService);
216 return ioServ.newURI(spec, null, null);
217 }
218
219 /**
220 * Checks whether this blocklist element is valid for the current OS and ABI.
221 * If the element has an "os" attribute then the current OS must appear in
222 * it's comma separated list for the element to be valid. Similarly for the
223 * xpcomabi attribute.
224 */
matchesOSABI
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
225 function matchesOSABI(blocklistElement) {
226 if (blocklistElement.hasAttribute("os")) {
227 var choices = blocklistElement.getAttribute("os").split(",");
228 if (choices.length > 0 && choices.indexOf(gApp.OS) < 0)
229 return false;
230 }
231
232 if (blocklistElement.hasAttribute("xpcomabi")) {
233 choices = blocklistElement.getAttribute("xpcomabi").split(",");
234 if (choices.length > 0 && choices.indexOf(gApp.XPCOMABI) < 0)
235 return false;
236 }
237
238 return true;
239 }
240
241 /**
242 * Gets the current value of the locale. It's possible for this preference to
243 * be localized, so we have to do a little extra work here. Similar code
244 * exists in nsHttpHandler.cpp when building the UA string.
245 */
getLocale
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
246 function getLocale() {
247 try {
248 // Get the default branch
249 var prefs = Components.classes["@mozilla.org/preferences-service;1"]
250 .getService(Components.interfaces.nsIPrefService);
251 var defaultPrefs = prefs.getDefaultBranch(null);
252 return defaultPrefs.getCharPref(PREF_GENERAL_USERAGENT_LOCALE);
253 } catch (e) {}
254
255 return gPref.getCharPref(PREF_GENERAL_USERAGENT_LOCALE);
256 }
257
258 /**
259 * Read the update channel from defaults only. We do this to ensure that
260 * the channel is tightly coupled with the application and does not apply
261 * to other installations of the application that may use the same profile.
262 */
getUpdateChannel
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
263 function getUpdateChannel() {
264 var channel = "default";
265 var prefName;
266 var prefValue;
267
268 var defaults =
269 gPref.QueryInterface(Components.interfaces.nsIPrefService).
270 getDefaultBranch(null);
271 try {
272 channel = defaults.getCharPref(PREF_APP_UPDATE_CHANNEL);
273 } catch (e) {
274 // use default when pref not found
275 }
276
277 try {
278 var partners = gPref.getChildList(PREF_PARTNER_BRANCH, { });
279 if (partners.length) {
280 channel += "-cck";
281 partners.sort();
282
283 for each (prefName in partners) {
284 prefValue = gPref.getCharPref(prefName);
285 channel += "-" + prefValue;
286 }
287 }
288 }
289 catch (e) {
290 Components.utils.reportError(e);
291 }
292
293 return channel;
294 }
295
296 /* Get the distribution pref values, from defaults only */
getDistributionPrefValue
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
297 function getDistributionPrefValue(aPrefName) {
298 var prefValue = "default";
299
300 var defaults =
301 gPref.QueryInterface(Components.interfaces.nsIPrefService).
302 getDefaultBranch(null);
303 try {
304 prefValue = defaults.getCharPref(aPrefName);
305 } catch (e) {
306 // use default when pref not found
307 }
308
309 return prefValue;
310 }
311
312 /**
313 * Manages the Blocklist. The Blocklist is a representation of the contents of
314 * blocklist.xml and allows us to remotely disable / re-enable blocklisted
315 * items managed by the Extension Manager with an item's appDisabled property.
316 * It also blocklists plugins with data from blocklist.xml.
317 */
318
Blocklist
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
319 function Blocklist() {
320 gApp = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo);
321 gApp.QueryInterface(Ci.nsIXULRuntime);
322 gPref = Cc["@mozilla.org/preferences-service;1"].
323 getService(Ci.nsIPrefBranch2);
324 gVersionChecker = Cc["@mozilla.org/xpcom/version-comparator;1"].
325 getService(Ci.nsIVersionComparator);
326 gConsole = Cc["@mozilla.org/consoleservice;1"].
327 getService(Ci.nsIConsoleService);
328
329 gOS = Cc["@mozilla.org/observer-service;1"].
330 getService(Ci.nsIObserverService);
331 gOS.addObserver(this, "xpcom-shutdown", false);
332
333 // Not all builds have a known ABI
334 try {
335 gABI = gApp.XPCOMABI;
336 }
337 catch (e) {
338 LOG("Blocklist: XPCOM ABI unknown.");
339 gABI = UNKNOWN_XPCOM_ABI;
340 }
341
342 var osVersion;
343 var sysInfo = Components.classes["@mozilla.org/system-info;1"]
344 .getService(Components.interfaces.nsIPropertyBag2);
345 try {
346 osVersion = sysInfo.getProperty("name") + " " + sysInfo.getProperty("version");
347 }
348 catch (e) {
349 LOG("Blocklist: OS Version unknown.");
350 }
351
352 if (osVersion) {
353 try {
354 osVersion += " (" + sysInfo.getProperty("secondaryLibrary") + ")";
355 }
356 catch (e) {
357 // Not all platforms have a secondary widget library, so an error is nothing to worry about.
358 }
359 gOSVersion = encodeURIComponent(osVersion);
360 }
361
362 //@line 333 "/home/visbrero/mnt/roisin/rev_control/hg/mozilla/toolkit/mozapps/extensions/src/nsBlocklistService.js"
363 // Mac universal build should report a different ABI than either macppc
364 // or mactel.
365 var macutils = Components.classes["@mozilla.org/xpcom/mac-utils;1"]
366 .getService(Components.interfaces.nsIMacUtils);
367
368 if (macutils.isUniversalBinary)
369 gABI = "Universal-gcc3";
370 //@line 341 "/home/visbrero/mnt/roisin/rev_control/hg/mozilla/toolkit/mozapps/extensions/src/nsBlocklistService.js"
371 }
372
373 Blocklist.prototype = {
374 /**
375 * Extension ID -> array of Version Ranges
376 * Each value in the version range array is a JS Object that has the
377 * following properties:
378 * "minVersion" The minimum version in a version range (default = 0)
379 * "maxVersion" The maximum version in a version range (default = *)
380 * "targetApps" Application ID -> array of Version Ranges
381 * (default = current application ID)
382 * Each value in the version range array is a JS Object that
383 * has the following properties:
384 * "minVersion" The minimum version in a version range
385 * (default = 0)
386 * "maxVersion" The maximum version in a version range
387 * (default = *)
388 */
389 _addonEntries: null,
390 _pluginEntries: null,
391
observe
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
392 observe: function (aSubject, aTopic, aData) {
393 switch (aTopic) {
394 case "app-startup":
395 gOS.addObserver(this, "plugins-list-updated", false);
396 gOS.addObserver(this, "profile-after-change", false);
397 gOS.addObserver(this, "quit-application", false);
398 break;
399 case "profile-after-change":
400 gLoggingEnabled = getPref("getBoolPref", PREF_EM_LOGGING_ENABLED, false);
401 var tm = Cc["@mozilla.org/updates/timer-manager;1"].
402 getService(Ci.nsIUpdateTimerManager);
403 var interval = getPref("getIntPref", PREF_BLOCKLIST_INTERVAL, 86400);
404 tm.registerTimer("blocklist-background-update-timer", this, interval);
405 break;
406 case "plugins-list-updated":
407 this._checkPluginsList();
408 break;
409 case "quit-application":
410 gOS.removeObserver(this, "plugins-list-updated");
411 gOS.removeObserver(this, "profile-after-change");
412 gOS.removeObserver(this, "quit-application");
413 break;
414 case "xpcom-shutdown":
415 gOS.removeObserver(this, "xpcom-shutdown");
416 gOS = null;
417 gPref = null;
418 gConsole = null;
419 gVersionChecker = null;
420 gApp = null;
421 break;
422 }
423 },
424
isAddonBlocklisted
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
425 isAddonBlocklisted: function(id, version, appVersion, toolkitVersion) {
426 if (!this._addonEntries)
427 this._loadBlocklist();
428 if (!appVersion)
429 appVersion = gApp.version;
430 if (!toolkitVersion)
431 toolkitVersion = gApp.platformVersion;
432
433 var blItem = this._addonEntries[id];
434 if (!blItem)
435 return false;
436
437 for (var i = 0; i < blItem.length; ++i) {
438 if (gVersionChecker.compare(version, blItem[i].minVersion) < 0 ||
439 gVersionChecker.compare(version, blItem[i].maxVersion) > 0)
440 continue;
441
442 var blTargetApp = blItem[i].targetApps[gApp.ID];
443 if (blTargetApp) {
444 for (var x = 0; x < blTargetApp.length; ++x) {
445 if (gVersionChecker.compare(appVersion, blTargetApp[x].minVersion) < 0 ||
446 gVersionChecker.compare(appVersion, blTargetApp[x].maxVersion) > 0)
447 continue;
448 return true;
449 }
450 }
451
452 blTargetApp = blItem[i].targetApps[TOOLKIT_ID];
453 if (!blTargetApp)
454 return false;
455 for (x = 0; x < blTargetApp.length; ++x) {
456 if (gVersionChecker.compare(toolkitVersion, blTargetApp[x].minVersion) < 0 ||
457 gVersionChecker.compare(toolkitVersion, blTargetApp[x].maxVersion) > 0)
458 continue;
459 return true;
460 }
461 }
462 return false;
463 },
464
notify
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
465 notify: function(aTimer) {
466 if (getPref("getBoolPref", PREF_BLOCKLIST_ENABLED, true) == false)
467 return;
468
469 try {
470 var dsURI = gPref.getCharPref(PREF_BLOCKLIST_URL);
471 }
472 catch (e) {
473 LOG("Blocklist::notify: The " + PREF_BLOCKLIST_URL + " preference" +
474 " is missing!");
475 return;
476 }
477
478 dsURI = dsURI.replace(/%APP_ID%/g, gApp.ID);
479 dsURI = dsURI.replace(/%APP_VERSION%/g, gApp.version);
480 dsURI = dsURI.replace(/%PRODUCT%/g, gApp.name);
481 dsURI = dsURI.replace(/%VERSION%/g, gApp.version);
482 dsURI = dsURI.replace(/%BUILD_ID%/g, gApp.appBuildID);
483 dsURI = dsURI.replace(/%BUILD_TARGET%/g, gApp.OS + "_" + gABI);
484 dsURI = dsURI.replace(/%OS_VERSION%/g, gOSVersion);
485 dsURI = dsURI.replace(/%LOCALE%/g, getLocale());
486 dsURI = dsURI.replace(/%CHANNEL%/g, getUpdateChannel());
487 dsURI = dsURI.replace(/%PLATFORM_VERSION%/g, gApp.platformVersion);
488 dsURI = dsURI.replace(/%DISTRIBUTION%/g,
489 getDistributionPrefValue(PREF_APP_DISTRIBUTION));
490 dsURI = dsURI.replace(/%DISTRIBUTION_VERSION%/g,
491 getDistributionPrefValue(PREF_APP_DISTRIBUTION_VERSION));
492 dsURI = dsURI.replace(/\+/g, "%2B");
493
494 // Verify that the URI is valid
495 try {
496 var uri = newURI(dsURI);
497 }
498 catch (e) {
499 LOG("Blocklist::notify: There was an error creating the blocklist URI\r\n" +
500 "for: " + dsURI + ", error: " + e);
501 return;
502 }
503
504 var request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
505 createInstance(Ci.nsIXMLHttpRequest);
506 request.open("GET", uri.spec, true);
507 request.channel.notificationCallbacks = new BadCertHandler();
508 request.overrideMimeType("text/xml");
509 request.setRequestHeader("Cache-Control", "no-cache");
510 request.QueryInterface(Components.interfaces.nsIJSXMLHttpRequest);
511
512 var self = this;
anon:513:22
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
513 request.onerror = function(event) { self.onXMLError(event); };
anon:514:22
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
514 request.onload = function(event) { self.onXMLLoad(event); };
515 request.send(null);
516 },
517
onXMLLoad
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
518 onXMLLoad: function(aEvent) {
519 var request = aEvent.target;
520 try {
521 checkCert(request.channel);
522 }
523 catch (e) {
524 LOG("Blocklist::onXMLLoad: " + e);
525 return;
526 }
527 var responseXML = request.responseXML;
528 if (!responseXML || responseXML.documentElement.namespaceURI == XMLURI_PARSE_ERROR ||
529 (request.status != 200 && request.status != 0)) {
530 LOG("Blocklist::onXMLLoad: there was an error during load");
531 return;
532 }
533 var blocklistFile = getFile(KEY_PROFILEDIR, [FILE_BLOCKLIST]);
534 if (blocklistFile.exists())
535 blocklistFile.remove(false);
536 var fos = openSafeFileOutputStream(blocklistFile);
537 fos.write(request.responseText, request.responseText.length);
538 closeSafeFileOutputStream(fos);
539 this._loadBlocklistFromFile(getFile(KEY_PROFILEDIR, [FILE_BLOCKLIST]));
540 var em = Cc["@mozilla.org/extensions/manager;1"].
541 getService(Ci.nsIExtensionManager);
542 em.checkForBlocklistChanges();
543 this._checkPluginsList();
544 },
545
onXMLError
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
546 onXMLError: function(aEvent) {
547 try {
548 var request = aEvent.target;
549 // the following may throw (e.g. a local file or timeout)
550 var status = request.status;
551 }
552 catch (e) {
553 request = aEvent.target.channel.QueryInterface(Ci.nsIRequest);
554 status = request.status;
555 }
556 var statusText = request.statusText;
557 // When status is 0 we don't have a valid channel.
558 if (status == 0)
559 statusText = "nsIXMLHttpRequest channel unavailable";
560 LOG("Blocklist:onError: There was an error loading the blocklist file\r\n" +
561 statusText);
562 },
563
564 /**
565 * Finds the newest blocklist file from the application and the profile and
566 * load it or does nothing if neither exist.
567 */
_loadBlocklist
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
568 _loadBlocklist: function() {
569 this._addonEntries = { };
570 this._pluginEntries = { };
571 var profFile = getFile(KEY_PROFILEDIR, [FILE_BLOCKLIST]);
572 if (profFile.exists()) {
573 this._loadBlocklistFromFile(profFile);
574 return;
575 }
576 var appFile = getFile(KEY_APPDIR, [FILE_BLOCKLIST]);
577 if (appFile.exists()) {
578 this._loadBlocklistFromFile(appFile);
579 return;
580 }
581 LOG("Blocklist::_loadBlocklist: no XML File found");
582 },
583
584 /**
585 //@line 604 "/home/visbrero/mnt/roisin/rev_control/hg/mozilla/toolkit/mozapps/extensions/src/nsBlocklistService.js"
586 */
587
_loadBlocklistFromFile
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
588 _loadBlocklistFromFile: function(file) {
589 if (getPref("getBoolPref", PREF_BLOCKLIST_ENABLED, true) == false) {
590 LOG("Blocklist::_loadBlocklistFromFile: blocklist is disabled");
591 return;
592 }
593
594 if (!file.exists()) {
595 LOG("Blocklist::_loadBlocklistFromFile: XML File does not exist");
596 return;
597 }
598
599 var fileStream = Components.classes["@mozilla.org/network/file-input-stream;1"]
600 .createInstance(Components.interfaces.nsIFileInputStream);
601 fileStream.init(file, MODE_RDONLY, PERMS_FILE, 0);
602 try {
603 var parser = Cc["@mozilla.org/xmlextras/domparser;1"].
604 createInstance(Ci.nsIDOMParser);
605 var doc = parser.parseFromStream(fileStream, "UTF-8", file.fileSize, "text/xml");
606 if (doc.documentElement.namespaceURI != XMLURI_BLOCKLIST) {
607 LOG("Blocklist::_loadBlocklistFromFile: aborting due to incorrect " +
608 "XML Namespace.\r\nExpected: " + XMLURI_BLOCKLIST + "\r\n" +
609 "Received: " + doc.documentElement.namespaceURI);
610 return;
611 }
612
613 var childNodes = doc.documentElement.childNodes;
614 this._addonEntries = this._processItemNodes(childNodes, "em",
615 this._handleEmItemNode);
616 this._pluginEntries = this._processItemNodes(childNodes, "plugin",
617 this._handlePluginItemNode);
618 }
619 catch (e) {
620 LOG("Blocklist::_loadBlocklistFromFile: Error constructing blocklist " + e);
621 return;
622 }
623 fileStream.close();
624 },
625
_processItemNodes
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
626 _processItemNodes: function(deChildNodes, prefix, handler) {
627 var result = [];
628 var itemNodes;
629 var containerName = prefix + "Items";
630 for (var i = 0; i < deChildNodes.length; ++i) {
631 var emItemsElement = deChildNodes.item(i);
632 if (emItemsElement instanceof Ci.nsIDOMElement &&
633 emItemsElement.localName == containerName) {
634 itemNodes = emItemsElement.childNodes;
635 break;
636 }
637 }
638 if (!itemNodes)
639 return result;
640
641 var itemName = prefix + "Item";
642 for (var i = 0; i < itemNodes.length; ++i) {
643 var blocklistElement = itemNodes.item(i);
644 if (!(blocklistElement instanceof Ci.nsIDOMElement) ||
645 blocklistElement.localName != itemName)
646 continue;
647
648 handler(blocklistElement, result);
649 }
650 return result;
651 },
652
_handleEmItemNode
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
653 _handleEmItemNode: function(blocklistElement, result) {
654 if (!matchesOSABI(blocklistElement))
655 return;
656
657 var versionNodes = blocklistElement.childNodes;
658 var id = blocklistElement.getAttribute("id");
659 result[id] = [];
660 for (var x = 0; x < versionNodes.length; ++x) {
661 var versionRangeElement = versionNodes.item(x);
662 if (!(versionRangeElement instanceof Ci.nsIDOMElement) ||
663 versionRangeElement.localName != "versionRange")
664 continue;
665
666 result[id].push(new BlocklistItemData(versionRangeElement));
667 }
668 // if only the extension ID is specified block all versions of the
669 // extension for the current application.
670 if (result[id].length == 0)
671 result[id].push(new BlocklistItemData(null));
672 },
673
_handlePluginItemNode
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
674 _handlePluginItemNode: function(blocklistElement, result) {
675 if (!matchesOSABI(blocklistElement))
676 return;
677
678 var matchNodes = blocklistElement.childNodes;
679 var matchList;
680 for (var x = 0; x < matchNodes.length; ++x) {
681 var matchElement = matchNodes.item(x);
682 if (!(matchElement instanceof Ci.nsIDOMElement) ||
683 matchElement.localName != "match")
684 continue;
685
686 var name = matchElement.getAttribute("name");
687 var exp = matchElement.getAttribute("exp");
688 if (!matchList)
689 matchList = { };
690 matchList[name] = new RegExp(exp, "m");
691 }
692 if (matchList)
693 result.push(matchList);
694 },
695
_checkPlugin
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
696 _checkPlugin: function(plugin) {
697 for each (var matchList in this._pluginEntries) {
698 var matchFailed = false;
699 for (var name in matchList) {
700 if (typeof(plugin[name]) != "string" ||
701 !matchList[name].test(plugin[name])) {
702 matchFailed = true;
703 break;
704 }
705 }
706
707 if (!matchFailed) {
708 plugin.blocklisted = true;
709 return;
710 }
711 }
712 plugin.blocklisted = false;
713 },
714
_checkPluginsList
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
715 _checkPluginsList: function() {
716 if (!this._addonEntries)
717 this._loadBlocklist();
718 var phs = Cc["@mozilla.org/plugin/host;1"].
719 getService(Ci.nsIPluginHost);
720 phs.getPluginTags({ }).forEach(this._checkPlugin, this);
721 },
722
723 classDescription: "Blocklist Service",
724 contractID: "@mozilla.org/extensions/blocklist;1",
725 classID: Components.ID("{66354bc9-7ed1-4692-ae1d-8da97d6b205e}"),
726 QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
727 Ci.nsIBlocklistService,
728 Ci.nsITimerCallback]),
729 _xpcom_categories: [{
730 category: "app-startup",
731 service: true
732 }]
733 };
734
735 /**
736 * Helper for constructing a blocklist.
737 */
BlocklistItemData
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
738 function BlocklistItemData(versionRangeElement) {
739 var versionRange = this.getBlocklistVersionRange(versionRangeElement);
740 this.minVersion = versionRange.minVersion;
741 this.maxVersion = versionRange.maxVersion;
742 this.targetApps = { };
743 var found = false;
744
745 if (versionRangeElement) {
746 for (var i = 0; i < versionRangeElement.childNodes.length; ++i) {
747 var targetAppElement = versionRangeElement.childNodes.item(i);
748 if (!(targetAppElement instanceof Ci.nsIDOMElement) ||
749 targetAppElement.localName != "targetApplication")
750 continue;
751 found = true;
752 // default to the current application if id is not provided.
753 var appID = targetAppElement.hasAttribute("id") ? targetAppElement.getAttribute("id") : gApp.ID;
754 this.targetApps[appID] = this.getBlocklistAppVersions(targetAppElement);
755 }
756 }
757 // Default to all versions of the extension and the current application when
758 // versionRange is not defined.
759 if (!found)
760 this.targetApps[gApp.ID] = this.getBlocklistAppVersions(null);
761 }
762
763 BlocklistItemData.prototype = {
764 /**
765 * Retrieves a version range (e.g. minVersion and maxVersion) for a
766 * blocklist item's targetApplication element.
767 * @param targetAppElement
768 * A targetApplication blocklist element.
769 * @returns An array of JS objects with the following properties:
770 * "minVersion" The minimum version in a version range (default = 0).
771 * "maxVersion" The maximum version in a version range (default = *).
772 */
getBlocklistAppVersions
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
773 getBlocklistAppVersions: function(targetAppElement) {
774 var appVersions = [ ];
775 var found = false;
776
777 if (targetAppElement) {
778 for (var i = 0; i < targetAppElement.childNodes.length; ++i) {
779 var versionRangeElement = targetAppElement.childNodes.item(i);
780 if (!(versionRangeElement instanceof Ci.nsIDOMElement) ||
781 versionRangeElement.localName != "versionRange")
782 continue;
783 found = true;
784 appVersions.push(this.getBlocklistVersionRange(versionRangeElement));
785 }
786 }
787 // return minVersion = 0 and maxVersion = * if not available
788 if (!found)
789 return [ this.getBlocklistVersionRange(null) ];
790 return appVersions;
791 },
792
793 /**
794 * Retrieves a version range (e.g. minVersion and maxVersion) for a blocklist
795 * versionRange element.
796 * @param versionRangeElement
797 * The versionRange blocklist element.
798 * @returns A JS object with the following properties:
799 * "minVersion" The minimum version in a version range (default = 0).
800 * "maxVersion" The maximum version in a version range (default = *).
801 */
getBlocklistVersionRange
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
802 getBlocklistVersionRange: function(versionRangeElement) {
803 var minVersion = "0";
804 var maxVersion = "*";
805 if (!versionRangeElement)
806 return { minVersion: minVersion, maxVersion: maxVersion };
807
808 if (versionRangeElement.hasAttribute("minVersion"))
809 minVersion = versionRangeElement.getAttribute("minVersion");
810 if (versionRangeElement.hasAttribute("maxVersion"))
811 maxVersion = versionRangeElement.getAttribute("maxVersion");
812
813 return { minVersion: minVersion, maxVersion: maxVersion };
814 }
815 };
816
NSGetModule
(0 calls, 0 incl. v-uS, 0 excl. v-uS)
817 function NSGetModule(aCompMgr, aFileSpec) {
818 return XPCOMUtils.generateModule([Blocklist]);
819 }