home *** CD-ROM | disk | FTP | other *** search
/ Freelog 112 / FreelogNo112-NovembreDecembre2012.iso / Multimedia / Songbird / Songbird_2.0.0-2311_windows-i686-msvc8.exe / jsmodules / Distribution.jsm < prev    next >
Text File  |  2012-06-08  |  13KB  |  391 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 the Firefox Distribution Customizations.
  15.  *
  16.  * The Initial Developer of the Original Code is Mozilla Foundation.
  17.  * Portions created by the Initial Developer are Copyright (C) 2007
  18.  * the Initial Developer. All Rights Reserved.
  19.  *
  20.  * Contributor(s):
  21.  *   Dan Mills <thunder@mozilla.com>
  22.  *   Marco Bonardo <mak77@bonardo.net>
  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. EXPORTED_SYMBOLS = [ "DistributionCustomizer" ];
  39.  
  40. const Ci = Components.interfaces;
  41. const Cc = Components.classes;
  42. const Cr = Components.results;
  43. const Cu = Components.utils;
  44.  
  45. const DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC =
  46.   "distribution-customization-complete";
  47. const BOOKMARKS_ROOT = "SB:Bookmarks";
  48.  
  49. function DistributionCustomizer() {
  50.   let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
  51.                getService(Ci.nsIProperties);
  52.   let iniFile = dirSvc.get("XCurProcD", Ci.nsIFile);
  53.   iniFile.append("distribution");
  54.   iniFile.append("distribution.ini");
  55.   if (iniFile.exists())
  56.     this._iniFile = iniFile;
  57. }
  58.  
  59. DistributionCustomizer.prototype = {
  60.   _iniFile: null,
  61.  
  62.   get _ini() {
  63.     let ini = Cc["@mozilla.org/xpcom/ini-parser-factory;1"].
  64.               getService(Ci.nsIINIParserFactory).
  65.               createINIParser(this._iniFile);
  66.     this.__defineGetter__("_ini", function() ini);
  67.     return this._ini;
  68.   },
  69.  
  70.   get _locale() {
  71.     let locale;
  72.     try {
  73.       locale = this._prefs.getCharPref("general.useragent.locale");
  74.     }
  75.     catch (e) {
  76.       locale = "en-US";
  77.     }
  78.     this.__defineGetter__("_locale", function() locale);
  79.     return this._locale;
  80.   },
  81.  
  82.   get _bmSvc() {
  83.     let svc = Cc["@songbirdnest.com/servicepane/bookmarks;1"]
  84.                 .getService(Ci.sbIBookmarks);
  85.     this.__defineGetter__("_bmSvc", function() svc);
  86.     return this._bmSvc;
  87.   },
  88.  
  89.   get _spsSvc() {
  90.     let svc = Cc["@songbirdnest.com/servicepane/service;1"]
  91.                 .getService(Ci.sbIServicePaneService);
  92.     this.__defineGetter__("_spsSvc", function() svc);
  93.     return this._spsSvc;
  94.   },
  95.  
  96.   get _prefSvc() {
  97.     let svc = Cc["@mozilla.org/preferences-service;1"].
  98.               getService(Ci.nsIPrefService);
  99.     this.__defineGetter__("_prefSvc", function() svc);
  100.     return this._prefSvc;
  101.   },
  102.  
  103.   get _prefs() {
  104.     let branch = this._prefSvc.getBranch(null);
  105.     this.__defineGetter__("_prefs", function() branch);
  106.     return this._prefs;
  107.   },
  108.  
  109.   get _ioSvc() {
  110.     let svc = Cc["@mozilla.org/network/io-service;1"].
  111.               getService(Ci.nsIIOService);
  112.     this.__defineGetter__("_ioSvc", function() svc);
  113.     return this._ioSvc;
  114.   },
  115.  
  116.   _makeURI: function DIST__makeURI(spec) {
  117.     return this._ioSvc.newURI(spec, null, null);
  118.   },
  119.  
  120.   _parseBookmarksSection:
  121.   function DIST_parseBookmarksSection(aParentNode, section) {
  122.     var parentNode = aParentNode;
  123.     if (!(parentNode instanceof Ci.sbIServicePaneNode)) {
  124.       parentNode = this._spsSvc.getNode(aParentNode);
  125.       if (!parentNode) {
  126.         throw "Failed to find parent node " + aParentNode;
  127.       }
  128.     }
  129.  
  130.     let keys = [];
  131.     for (let i in enumerate(this._ini.getKeys(section)))
  132.       keys.push(i);
  133.     keys.sort();
  134.  
  135.     let items = {};
  136.     let defaultItemId = -1;
  137.     let maxItemId = -1;
  138.  
  139.     // read the items from the ini file
  140.     for (let i = 0; i < keys.length; i++) {
  141.       let m = /^item\.(\d+)\.(\w+)\.?(\w*)/.exec(keys[i]);
  142.       if (m) {
  143.         let [foo, iid, iprop, ilocale] = m;
  144.         iid = parseInt(iid);
  145.  
  146.         if (ilocale)
  147.           continue;
  148.  
  149.         if (!items[iid])
  150.           items[iid] = {};
  151.         if (keys.indexOf(keys[i] + "." + this._locale) >= 0) {
  152.           items[iid][iprop] = this._ini.getString(section, keys[i] + "." +
  153.                                                   this._locale);
  154.         } else {
  155.           items[iid][iprop] = this._ini.getString(section, keys[i]);
  156.         }
  157.  
  158.         if (maxItemId < iid)
  159.           maxItemId = iid;
  160.       } else {
  161.         dump("Key did not match: " + keys[i] + "\n");
  162.       }
  163.     }
  164.  
  165.     // actually insert the items
  166.     for (let iid = 0; iid <= maxItemId; iid++) {
  167.       if (!items[iid])
  168.         continue;
  169.  
  170.       if (!("title" in items[iid])) {
  171.         dump("Distribution.ini: missing title in '" + iid + "'\n");
  172.         continue;
  173.       }
  174.  
  175.       let newNode;
  176.  
  177.       switch(items[iid]["type"]) {
  178.         case "folder":
  179.           if (!("folderId" in items[iid])) {
  180.             dump("Distribution.ini: missing folderId in '" + iid + "'\n");
  181.             continue;
  182.           }
  183.           newNode = this._bmSvc.addFolder(items[iid]["title"]);
  184.           this._parseBookmarksSection(newNode,
  185.                                       "BookmarksFolder-" + items[iid]["folderId"]);
  186.           break;
  187.         
  188.         default:
  189.           if ("type" in items[iid]) {
  190.             dump("Distribution.ini: unknown type '" + items[iid]["type"] +
  191.                  "' for '" + iid + "'\n");
  192.             continue;
  193.           }
  194.           // fall through to bookmarks when no type given
  195.         case "bookmark":
  196.           if (!("link" in items[iid])) {
  197.             dump("Distribution.ini: missing link in '" + iid + "'\n");
  198.             continue;
  199.           }
  200.           let icon = items[iid]["icon"];
  201.           if ("icon" in items[iid]) {
  202.             try {
  203.               // attempt to make sure this is a valid url; no need to keep it.
  204.               this._makeURI(items[iid]["icon"]);
  205.             } catch (e) {
  206.               dump("Distribution.ini: invalid icon URL '" + items[iid]["icon"] +
  207.                    "' for '" + iid + "'\n");
  208.               continue;
  209.             }
  210.           } else {
  211.             icon = null;
  212.           }
  213.           newNode = this._bmSvc.addBookmarkAt(items[iid]["link"],
  214.                                               items[iid]["title"],
  215.                                               icon,
  216.                                               parentNode,
  217.                                               null);
  218.           break;
  219.       }
  220.  
  221.       if ("weight" in items[iid]) {
  222.         // weight was given, sort it
  223.         this._spsSvc.sortNode(newNode);
  224.       }
  225.     }
  226.     return this._checkCustomizationComplete();
  227.   },
  228.  
  229.   _customizationsApplied: false,
  230.   applyCustomizations: function DIST_applyCustomizations() {
  231.     this._customizationsApplied = true;
  232.     if (!this._iniFile)
  233.       return this._checkCustomizationComplete();
  234.  
  235.     // nsPrefService loads very early.  Reload prefs so we can set
  236.     // distribution defaults during the prefservice:after-app-defaults
  237.     // notification (see applyPrefDefaults below)
  238.     this._prefSvc.QueryInterface(Ci.nsIObserver);
  239.     this._prefSvc.observe(null, "reload-default-prefs", null);
  240.   },
  241.  
  242.   _bookmarksApplied: false,
  243.   applyBookmarks: function DIST_applyBookarks() {
  244.     this._bookmarksApplied = true;
  245.     if (!this._iniFile)
  246.       return this._checkCustomizationComplete();
  247.  
  248.     let sections = enumToObject(this._ini.getSections());
  249.  
  250.     // The global section, and several of its fields, is required
  251.     // (we also check here to be consistent with applyPrefDefaults below)
  252.     if (!sections["Global"])
  253.       return this._checkCustomizationComplete();
  254.     let globalPrefs = enumToObject(this._ini.getKeys("Global"));
  255.     if (!(globalPrefs["id"] && globalPrefs["version"] && globalPrefs["about"]))
  256.       return this._checkCustomizationComplete();
  257.  
  258.     let bmProcessedPref;
  259.     try {
  260.       bmProcessedPref = this._ini.getString("Global",
  261.                                             "bookmarks.initialized.pref");
  262.     }
  263.     catch (e) {
  264.       bmProcessedPref = "distribution." +
  265.         this._ini.getString("Global", "id") + ".bookmarksProcessed";
  266.     }
  267.  
  268.     let bmProcessed = false;
  269.     try {
  270.       bmProcessed = this._prefs.getBoolPref(bmProcessedPref);
  271.     }
  272.     catch (e) {}
  273.  
  274.     if (!bmProcessed) {
  275.       if (sections["Bookmarks"])
  276.         this._parseBookmarksSection(BOOKMARKS_ROOT, "Bookmarks");
  277.       this._prefs.setBoolPref(bmProcessedPref, true);
  278.     }
  279.     return this._checkCustomizationComplete();
  280.   },
  281.  
  282.   _prefDefaultsApplied: false,
  283.   applyPrefDefaults: function DIST_applyPrefDefaults() {
  284.     this._prefDefaultsApplied = true;
  285.     if (!this._iniFile)
  286.       return this._checkCustomizationComplete();
  287.  
  288.     let sections = enumToObject(this._ini.getSections());
  289.  
  290.     // The global section, and several of its fields, is required
  291.     if (!sections["Global"])
  292.       return this._checkCustomizationComplete();
  293.     let globalPrefs = enumToObject(this._ini.getKeys("Global"));
  294.     if (!(globalPrefs["id"] && globalPrefs["version"] && globalPrefs["about"]))
  295.       return this._checkCustomizationComplete();
  296.  
  297.     let defaults = this._prefSvc.getDefaultBranch(null);
  298.  
  299.     // Global really contains info we set as prefs.  They're only
  300.     // separate because they are "special" (read: required)
  301.  
  302.     defaults.setCharPref("distribution.id", this._ini.getString("Global", "id"));
  303.     defaults.setCharPref("distribution.version",
  304.                          this._ini.getString("Global", "version"));
  305.  
  306.     let partnerAbout = Cc["@mozilla.org/supports-string;1"].
  307.       createInstance(Ci.nsISupportsString);
  308.     if (globalPrefs["about." + this._locale]) {
  309.       partnerAbout.data = this._ini.getString("Global", "about." + this._locale);
  310.     } else {
  311.       partnerAbout.data = this._ini.getString("Global", "about");
  312.     }
  313.     defaults.setComplexValue("distribution.about",
  314.                              Ci.nsISupportsString, partnerAbout);
  315.  
  316.     if (sections["Preferences"]) {
  317.       for (let key in enumerate(this._ini.getKeys("Preferences"))) {
  318.         try {
  319.           let value = eval(this._ini.getString("Preferences", key));
  320.           switch (typeof value) {
  321.           case "boolean":
  322.             defaults.setBoolPref(key, value);
  323.             break;
  324.           case "number":
  325.             defaults.setIntPref(key, value);
  326.             break;
  327.           case "string":
  328.             defaults.setCharPref(key, value);
  329.             break;
  330.           case "undefined":
  331.             defaults.setCharPref(key, value);
  332.             break;
  333.           }
  334.         } catch (e) { /* ignore bad prefs and move on */ }
  335.       }
  336.     }
  337.  
  338.     // We eval() the localizable prefs as well (even though they'll
  339.     // always get set as a string) to keep the INI format consistent:
  340.     // string prefs always need to be in quotes
  341.  
  342.     let localizedStr = Cc["@mozilla.org/pref-localizedstring;1"].
  343.       createInstance(Ci.nsIPrefLocalizedString);
  344.  
  345.     if (sections["LocalizablePreferences"]) {
  346.       for (let key in enumerate(this._ini.getKeys("LocalizablePreferences"))) {
  347.         try {
  348.           let value = eval(this._ini.getString("LocalizablePreferences", key));
  349.           value = value.replace("%LOCALE%", this._locale, "g");
  350.           localizedStr.data = "data:text/plain," + key + "=" + value;
  351.           defaults.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr);
  352.         } catch (e) { /* ignore bad prefs and move on */ }
  353.       }
  354.     }
  355.  
  356.     if (sections["LocalizablePreferences-" + this._locale]) {
  357.       for (let key in enumerate(this._ini.getKeys("LocalizablePreferences-" + this._locale))) {
  358.         try {
  359.           let value = eval(this._ini.getString("LocalizablePreferences-" + this._locale, key));
  360.           localizedStr.data = "data:text/plain," + key + "=" + value;
  361.           defaults.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr);
  362.         } catch (e) { /* ignore bad prefs and move on */ }
  363.       }
  364.     }
  365.  
  366.     return this._checkCustomizationComplete();
  367.   },
  368.  
  369.   _checkCustomizationComplete: function DIST__checkCustomizationComplete() {
  370.     let prefDefaultsApplied = this._prefDefaultsApplied || !this._iniFile;
  371.     if (this._customizationsApplied && this._bookmarksApplied &&
  372.         prefDefaultsApplied) {
  373.       let os = Cc["@mozilla.org/observer-service;1"].
  374.                getService(Ci.nsIObserverService);
  375.       os.notifyObservers(null, DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC, null);
  376.     }
  377.   }
  378. };
  379.  
  380. function enumerate(UTF8Enumerator) {
  381.   while (UTF8Enumerator.hasMore())
  382.     yield UTF8Enumerator.getNext();
  383. }
  384.  
  385. function enumToObject(UTF8Enumerator) {
  386.   let ret = {};
  387.   for (let i in enumerate(UTF8Enumerator))
  388.     ret[i] = 1;
  389.   return ret;
  390. }
  391.