home *** CD-ROM | disk | FTP | other *** search
/ Chip 2011 November / CHIP_2011_11.iso / Programy / Narzedzia / AIMP2 / aimp_2.61.583.exe / $TEMP / YandexPackSetup.msi / filF80E64777D170EF008A89B10182349C6 < prev    next >
Text File  |  2010-07-12  |  19KB  |  529 lines

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3.  *
  4.  * The contents of this file are subject to the Mozilla Public License Version
  5.  * 1.1 (the "License"); you may not use this file except in compliance with
  6.  * the License. You may obtain a copy of the License at
  7.  * http://www.mozilla.org/MPL/
  8.  *
  9.  * Software distributed under the License is distributed on an "AS IS" basis,
  10.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11.  * for the specific language governing rights and limitations under the
  12.  * License.
  13.  *
  14.  * The Original Code is Preferences.
  15.  *
  16.  * The Initial Developer of the Original Code is Mozilla.
  17.  * Portions created by the Initial Developer are Copyright (C) 2008
  18.  * the Initial Developer. All Rights Reserved.
  19.  *
  20.  * Contributor(s):
  21.  *   Myk Melez <myk@mozilla.org>
  22.  *   Daniel Aquino <mr.danielaquino@gmail.com>
  23.  *
  24.  * Alternatively, the contents of this file may be used under the terms of
  25.  * either the GNU General Public License Version 2 or later (the "GPL"), or
  26.  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27.  * in which case the provisions of the GPL or the LGPL are applicable instead
  28.  * of those above. If you wish to allow use of your version of this file only
  29.  * under the terms of either the GPL or the LGPL, and not to allow others to
  30.  * use your version of this file under the terms of the MPL, indicate your
  31.  * decision by deleting the provisions above and replace them with the notice
  32.  * and other provisions required by the GPL or the LGPL. If you do not delete
  33.  * the provisions above, a recipient may use your version of this file under
  34.  * the terms of any one of the MPL, the GPL or the LGPL.
  35.  *
  36.  * ***** END LICENSE BLOCK ***** */
  37.  
  38. let EXPORTED_SYMBOLS = ["Preferences", "Prefs"];
  39.  
  40. const Cc = Components.classes;
  41. const Ci = Components.interfaces;
  42. const Cr = Components.results;
  43. const Cu = Components.utils;
  44.  
  45. Cu.import("resource://gre/modules/XPCOMUtils.jsm");
  46. Cu.import("resource://yasearch/ExtConstants.jsm");
  47.  
  48. // The minimum and maximum integers that can be set as preferences.
  49. // The range of valid values is narrower than the range of valid JS values
  50. // because the native preferences code treats integers as NSPR PRInt32s,
  51. // which are 32-bit signed integers on all platforms.
  52. const MAX_INT = Math.pow(2, 31) - 1;
  53. const MIN_INT = -MAX_INT;
  54.  
  55. function Preferences(args) {
  56.     if (isObject(args)) {
  57.       if (args.branch)
  58.         this._prefBranch = args.branch;
  59.       if (args.site)
  60.         this._site = args.site;
  61.     }
  62.     else if (args)
  63.       this._prefBranch = args;
  64. }
  65.  
  66. Preferences.prototype = {
  67.   /**
  68.    * Get the value of a pref, if any; otherwise return the default value.
  69.    *
  70.    * @param   prefName  {String|Array}
  71.    *          the pref to get, or an array of prefs to get
  72.    *
  73.    * @param   defaultValue
  74.    *          the default value, if any, for prefs that don't have one
  75.    *
  76.    * @returns the value of the pref, if any; otherwise the default value
  77.    */
  78.   get: function(prefName, defaultValue) {
  79.     if (isArray(prefName))
  80.       return prefName.map(function(v) this.get(v, defaultValue), this);
  81.  
  82.     if (this._site)
  83.       return this._siteGet(prefName, defaultValue);
  84.     else
  85.       return this._get(prefName, defaultValue);
  86.   },
  87.  
  88.   _get: function(prefName, defaultValue) {
  89.     switch (this._prefSvc.getPrefType(prefName)) {
  90.       case Ci.nsIPrefBranch.PREF_STRING:
  91.         return this._prefSvc.getComplexValue(prefName, Ci.nsISupportsString).data;
  92.  
  93.       case Ci.nsIPrefBranch.PREF_INT:
  94.         return this._prefSvc.getIntPref(prefName);
  95.  
  96.       case Ci.nsIPrefBranch.PREF_BOOL:
  97.         return this._prefSvc.getBoolPref(prefName);
  98.  
  99.       case Ci.nsIPrefBranch.PREF_INVALID:
  100.         return defaultValue;
  101.  
  102.       default:
  103.         // This should never happen.
  104.         throw "Error getting pref " + prefName + "; its value's type is " +
  105.               this._prefSvc.getPrefType(prefName) + ", which I don't know " +
  106.               "how to handle.";
  107.     }
  108.   },
  109.  
  110.   _siteGet: function(prefName, defaultValue) {
  111.     let value = this._contentPrefSvc.getPref(this._site, this._prefBranch + prefName);
  112.     return typeof value != "undefined" ? value : defaultValue;
  113.   },
  114.  
  115.   /**
  116.    * Set a preference to a value.
  117.    *
  118.    * You can set multiple prefs by passing an object as the only parameter.
  119.    * In that case, this method will treat the properties of the object
  120.    * as preferences to set, where each property name is the name of a pref
  121.    * and its corresponding property value is the value of the pref.
  122.    *
  123.    * @param   prefName  {String|Object}
  124.    *          the name of the pref to set; or an object containing a set
  125.    *          of prefs to set
  126.    *
  127.    * @param   prefValue {String|Number|Boolean}
  128.    *          the value to which to set the pref
  129.    *
  130.    * Note: Preferences cannot store non-integer numbers or numbers outside
  131.    * the signed 32-bit range -(2^31-1) to 2^31-1, If you have such a number,
  132.    * store it as a string by calling toString() on the number before passing
  133.    * it to this method, i.e.:
  134.    *   Preferences.set("pi", 3.14159.toString())
  135.    *   Preferences.set("big", Math.pow(2, 31).toString()).
  136.    */
  137.   set: function(prefName, prefValue) {
  138.     if (isObject(prefName)) {
  139.       for (let [name, value] in Iterator(prefName))
  140.         this.set(name, value);
  141.       return;
  142.     }
  143.  
  144.     if (this._site)
  145.       this._siteSet(prefName, prefValue);
  146.     else
  147.       this._set(prefName, prefValue);
  148.   },
  149.  
  150.   _set: function(prefName, prefValue) {
  151.     let prefType;
  152.     if (typeof prefValue != "undefined" && prefValue != null)
  153.       prefType = prefValue.constructor.name;
  154.  
  155.     switch (prefType) {
  156.       case "String":
  157.         {
  158.           let string = Cc["@mozilla.org/supports-string;1"].
  159.                        createInstance(Ci.nsISupportsString);
  160.           string.data = prefValue;
  161.           this._prefSvc.setComplexValue(prefName, Ci.nsISupportsString, string);
  162.         }
  163.         break;
  164.  
  165.       case "Number":
  166.         // We throw if the number is outside the range, since the result
  167.         // will never be what the consumer wanted to store, but we only warn
  168.         // if the number is non-integer, since the consumer might not mind
  169.         // the loss of precision.
  170.         if (prefValue > MAX_INT || prefValue < MIN_INT)
  171.           throw("you cannot set the " + prefName + " pref to the number " +
  172.                 prefValue + ", as number pref values must be in the signed " +
  173.                 "32-bit integer range -(2^31-1) to 2^31-1.  To store numbers " +
  174.                 "outside that range, store them as strings.");
  175.         this._prefSvc.setIntPref(prefName, prefValue);
  176.         if (prefValue % 1 != 0)
  177.           Cu.reportError("Warning: setting the " + prefName + " pref to the " +
  178.                          "non-integer number " + prefValue + " converted it " +
  179.                          "to the integer number " + this.get(prefName) +
  180.                          "; to retain fractional precision, store non-integer " +
  181.                          "numbers as strings.");
  182.         break;
  183.  
  184.       case "Boolean":
  185.         this._prefSvc.setBoolPref(prefName, prefValue);
  186.         break;
  187.  
  188.       default:
  189.         throw "can't set pref " + prefName + " to value '" + prefValue +
  190.               "'; it isn't a String, Number, or Boolean";
  191.     }
  192.   },
  193.  
  194.   _siteSet: function(prefName, prefValue) {
  195.     this._contentPrefSvc.setPref(this._site, this._prefBranch + prefName, prefValue);
  196.   },
  197.  
  198.   /**
  199.    * Whether or not the given pref has a value.  This is different from isSet
  200.    * because it returns true whether the value of the pref is a default value
  201.    * or a user-set value, while isSet only returns true if the value
  202.    * is a user-set value.
  203.    *
  204.    * @param   prefName  {String|Array}
  205.    *          the pref to check, or an array of prefs to check
  206.    *
  207.    * @returns {Boolean|Array}
  208.    *          whether or not the pref has a value; or, if the caller provided
  209.    *          an array of pref names, an array of booleans indicating whether
  210.    *          or not the prefs have values
  211.    */
  212.   has: function(prefName) {
  213.     if (isArray(prefName))
  214.       return prefName.map(this.has, this);
  215.  
  216.     if (this._site)
  217.       return this._siteHas(prefName);
  218.     else
  219.       return this._has(prefName);
  220.   },
  221.  
  222.   _has: function(prefName) {
  223.     return (this._prefSvc.getPrefType(prefName) != Ci.nsIPrefBranch.PREF_INVALID);
  224.   },
  225.  
  226.   _siteHas: function(prefName) {
  227.     return this._contentPrefSvc.hasPref(this._site, this._prefBranch + prefName);
  228.   },
  229.  
  230.   /**
  231.    * Whether or not the given pref has a user-set value.  This is different
  232.    * from |has| because it returns true only if the value of the pref is a user-
  233.    * set value, while |has| returns true if the value of the pref is a default
  234.    * value or a user-set value.
  235.    *
  236.    * @param   prefName  {String|Array}
  237.    *          the pref to check, or an array of prefs to check
  238.    *
  239.    * @returns {Boolean|Array}
  240.    *          whether or not the pref has a user-set value; or, if the caller
  241.    *          provided an array of pref names, an array of booleans indicating
  242.    *          whether or not the prefs have user-set values
  243.    */
  244.   isSet: function(prefName) {
  245.     if (isArray(prefName))
  246.       return prefName.map(this.isSet, this);
  247.  
  248.     return (this.has(prefName) && this._prefSvc.prefHasUserValue(prefName));
  249.   },
  250.  
  251.   /**
  252.    * Whether or not the given pref has a user-set value. Use isSet instead,
  253.    * which is equivalent.
  254.    * @deprecated
  255.    */
  256.   modified: function(prefName) { return this.isSet(prefName) },
  257.  
  258.   reset: function(prefName) {
  259.     if (isArray(prefName)) {
  260.       prefName.map(function(v) this.reset(v), this);
  261.       return;
  262.     }
  263.  
  264.     if (this._site)
  265.       this._siteReset(prefName);
  266.     else
  267.       this._reset(prefName);
  268.   },
  269.   
  270.   _reset: function(prefName) {
  271.     try {
  272.       this._prefSvc.clearUserPref(prefName);
  273.     }
  274.     catch(ex) {
  275.       // The pref service throws NS_ERROR_UNEXPECTED when the caller tries
  276.       // to reset a pref that doesn't exist or is already set to its default
  277.       // value.  This interface fails silently in those cases, so callers
  278.       // can unconditionally reset a pref without having to check if it needs
  279.       // resetting first or trap exceptions after the fact.  It passes through
  280.       // other exceptions, however, so callers know about them, since we don't
  281.       // know what other exceptions might be thrown and what they might mean.
  282.       if (ex.result != Cr.NS_ERROR_UNEXPECTED)
  283.         throw ex;
  284.     }
  285.   },
  286.  
  287.   _siteReset: function(prefName) {
  288.     return this._contentPrefSvc.removePref(this._site, this._prefBranch + prefName);
  289.   },
  290.  
  291.   /**
  292.    * Lock a pref so it can't be changed.
  293.    *
  294.    * @param   prefName  {String|Array}
  295.    *          the pref to lock, or an array of prefs to lock
  296.    */
  297.   lock: function(prefName) {
  298.     if (isArray(prefName))
  299.       prefName.map(this.lock, this);
  300.  
  301.     this._prefSvc.lockPref(prefName);
  302.   },
  303.  
  304.   /**
  305.    * Unlock a pref so it can be changed.
  306.    *
  307.    * @param   prefName  {String|Array}
  308.    *          the pref to lock, or an array of prefs to lock
  309.    */
  310.   unlock: function(prefName) {
  311.     if (isArray(prefName))
  312.       prefName.map(this.unlock, this);
  313.  
  314.     this._prefSvc.unlockPref(prefName);
  315.   },
  316.  
  317.   /**
  318.    * Whether or not the given pref is locked against changes.
  319.    *
  320.    * @param   prefName  {String|Array}
  321.    *          the pref to check, or an array of prefs to check
  322.    *
  323.    * @returns {Boolean|Array}
  324.    *          whether or not the pref has a user-set value; or, if the caller
  325.    *          provided an array of pref names, an array of booleans indicating
  326.    *          whether or not the prefs have user-set values
  327.    */
  328.   locked: function(prefName) {
  329.     if (isArray(prefName))
  330.       return prefName.map(this.locked, this);
  331.  
  332.     return this._prefSvc.prefIsLocked(prefName);
  333.   },
  334.  
  335.   /**
  336.    * Start observing a pref.
  337.    *
  338.    * The callback can be a function or any object that implements nsIObserver.
  339.    * When the callback is a function and thisObject is provided, it gets called
  340.    * as a method of thisObject.
  341.    *
  342.    * @param   prefName    {String}
  343.    *          the name of the pref to observe
  344.    *
  345.    * @param   callback    {Function|Object}
  346.    *          the code to notify when the pref changes;
  347.    *
  348.    * @param   thisObject  {Object}  [optional]
  349.    *          the object to use as |this| when calling a Function callback;
  350.    *
  351.    * @returns the wrapped observer
  352.    */
  353.   observe: function(prefName, callback, thisObject) {
  354.     let fullPrefName = this._prefBranch + (prefName || "");
  355.  
  356.     let observer = new PrefObserver(fullPrefName, callback, thisObject);
  357.     Preferences._prefSvc.addObserver(fullPrefName, observer, true);
  358.     observers.push(observer);
  359.  
  360.     return observer;
  361.   },
  362.  
  363.   /**
  364.    * Stop observing a pref.
  365.    *
  366.    * You must call this method with the same prefName, callback, and thisObject
  367.    * with which you originally registered the observer.  However, you don't have
  368.    * to call this method on the same exact instance of Preferences; you can call
  369.    * it on any instance.  For example, the following code first starts and then
  370.    * stops observing the "foo.bar.baz" preference:
  371.    *
  372.    *   let observer = function() {...};
  373.    *   Preferences.observe("foo.bar.baz", observer);
  374.    *   new Preferences("foo.bar.").ignore("baz", observer);
  375.    *
  376.    * @param   prefName    {String}
  377.    *          the name of the pref being observed
  378.    *
  379.    * @param   callback    {Function|Object}
  380.    *          the code being notified when the pref changes
  381.    *
  382.    * @param   thisObject  {Object}  [optional]
  383.    *          the object being used as |this| when calling a Function callback
  384.    */
  385.   ignore: function(prefName, callback, thisObject) {
  386.     let fullPrefName = this._prefBranch + (prefName || "");
  387.  
  388.     // This seems fairly inefficient, but I'm not sure how much better we can
  389.     // make it.  We could index by fullBranch, but we can't index by callback
  390.     // or thisObject, as far as I know, since the keys to JavaScript hashes
  391.     // (a.k.a. objects) can apparently only be primitive values.
  392.     let [observer] = observers.filter(function(v) v.prefName   == fullPrefName &&
  393.                                                   v.callback   == callback &&
  394.                                                   v.thisObject == thisObject);
  395.  
  396.     if (observer) {
  397.       Preferences._prefSvc.removeObserver(fullPrefName, observer);
  398.       observers.splice(observers.indexOf(observer), 1);
  399.     }
  400.   },
  401.  
  402.   resetBranch: function(prefBranch) {
  403.     try {
  404.       this._prefSvc.resetBranch(prefBranch);
  405.     }
  406.     catch(ex) {
  407.       // The current implementation of nsIPrefBranch in Mozilla
  408.       // doesn't implement resetBranch, so we do it ourselves.
  409.       if (ex.result == Cr.NS_ERROR_NOT_IMPLEMENTED)
  410.         this.reset(this._prefSvc.getChildList(prefBranch, []));
  411.       else
  412.         throw ex;
  413.     }
  414.   },
  415.  
  416.   /**
  417.    * The branch of the preferences tree to which this instance provides access.
  418.    * @private
  419.    */
  420.   _prefBranch: "",
  421.  
  422.   site: function(site) {
  423.     if (!(site instanceof Ci.nsIURI))
  424.       site = this._ioSvc.newURI("http://" + site, null, null);
  425.     return new Preferences({ branch: this._prefBranch, site: site });
  426.   },
  427.  
  428.   /**
  429.    * Preferences Service
  430.    * @private
  431.    */
  432.   get _prefSvc() {
  433.     let prefSvc = Cc["@mozilla.org/preferences-service;1"].
  434.                   getService(Ci.nsIPrefService).
  435.                   getBranch(this._prefBranch).
  436.                   QueryInterface(Ci.nsIPrefBranch2);
  437.     this.__defineGetter__("_prefSvc", function() prefSvc);
  438.     return this._prefSvc;
  439.   },
  440.  
  441.   /**
  442.    * IO Service
  443.    * @private
  444.    */
  445.   get _ioSvc() {
  446.     let ioSvc = Cc["@mozilla.org/network/io-service;1"].
  447.                 getService(Ci.nsIIOService);
  448.     this.__defineGetter__("_ioSvc", function() ioSvc);
  449.     return this._ioSvc;
  450.   },
  451.  
  452.   /**
  453.    * Site Preferences Service
  454.    * @private
  455.    */
  456.   get _contentPrefSvc() {
  457.     let contentPrefSvc = Cc["@mozilla.org/content-pref/service;1"].
  458.                          getService(Ci.nsIContentPrefService);
  459.     this.__defineGetter__("_contentPrefSvc", function() contentPrefSvc);
  460.     return this._contentPrefSvc;
  461.   }
  462.  
  463. };
  464.  
  465. // Give the constructor the same prototype as its instances, so users can access
  466. // preferences directly via the constructor without having to create an instance
  467. // first.
  468. Preferences.__proto__ = Preferences.prototype;
  469.  
  470. // Preferences of extension.
  471. var Prefs = new Preferences(ExtConstants.PREFERENCES_PREFIX);
  472.  
  473. /**
  474.  * A cache of pref observers.
  475.  *
  476.  * We use this to remove observers when a caller calls Preferences::ignore.
  477.  *
  478.  * All Preferences instances share this object, because we want callers to be
  479.  * able to remove an observer using a different Preferences object than the one
  480.  * with which they added it.  That means we have to identify the observers
  481.  * in this object by their complete pref name, not just their name relative to
  482.  * the root branch of the Preferences object with which they were created.
  483.  */
  484. let observers = [];
  485.  
  486. function PrefObserver(prefName, callback, thisObject) {
  487.   this.prefName = prefName;
  488.   this.callback = callback;
  489.   this.thisObject = thisObject;
  490. }
  491.  
  492. PrefObserver.prototype = {
  493.   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
  494.  
  495.   observe: function(subject, topic, data) {
  496.     // The pref service only observes whole branches, but we only observe
  497.     // individual preferences, so we check here that the pref that changed
  498.     // is the exact one we're observing (and not some sub-pref on the branch).
  499.     if (data != this.prefName)
  500.       return;
  501.  
  502.     if (typeof this.callback == "function") {
  503.       let prefValue = Preferences.get(this.prefName);
  504.  
  505.       if (this.thisObject)
  506.         this.callback.call(this.thisObject, prefValue);
  507.       else
  508.         this.callback(prefValue);
  509.     }
  510.     else // typeof this.callback == "object" (nsIObserver)
  511.       this.callback.observe(subject, topic, data);
  512.   }
  513. };
  514.  
  515. function isArray(val) {
  516.   // We can't check for |val.constructor == Array| here, since the value
  517.   // might be from a different context whose Array constructor is not the same
  518.   // as ours, so instead we match based on the name of the constructor.
  519.   return (typeof val != "undefined" && val != null && typeof val == "object" &&
  520.           val.constructor.name == "Array");
  521. }
  522.  
  523. function isObject(val) {
  524.   // We can't check for |val.constructor == Object| here, since the value
  525.   // might be from a different context whose Object constructor is not the same
  526.   // as ours, so instead we match based on the name of the constructor.
  527.   return (typeof val != "undefined" && val != null && typeof val == "object" &&
  528.           val.constructor.name == "Object");
  529. }