browser/components/distribution.js

Wed, 31 Dec 2014 07:53:36 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:53:36 +0100
branch
TOR_BUG_3246
changeset 5
4ab42b5ab56c
permissions
-rw-r--r--

Correct small whitespace inconsistency, lost while renaming variables.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 this.EXPORTED_SYMBOLS = [ "DistributionCustomizer" ];
michael@0 6
michael@0 7 const Ci = Components.interfaces;
michael@0 8 const Cc = Components.classes;
michael@0 9 const Cr = Components.results;
michael@0 10 const Cu = Components.utils;
michael@0 11
michael@0 12 const DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC =
michael@0 13 "distribution-customization-complete";
michael@0 14
michael@0 15 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
michael@0 16 Cu.import("resource://gre/modules/Services.jsm");
michael@0 17 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
michael@0 18 "resource://gre/modules/PlacesUtils.jsm");
michael@0 19
michael@0 20 this.DistributionCustomizer = function DistributionCustomizer() {
michael@0 21 // For parallel xpcshell testing purposes allow loading the distribution.ini
michael@0 22 // file from the profile folder through an hidden pref.
michael@0 23 let loadFromProfile = false;
michael@0 24 try {
michael@0 25 loadFromProfile = Services.prefs.getBoolPref("distribution.testing.loadFromProfile");
michael@0 26 } catch(ex) {}
michael@0 27 let dirSvc = Cc["@mozilla.org/file/directory_service;1"].
michael@0 28 getService(Ci.nsIProperties);
michael@0 29 let iniFile = loadFromProfile ? dirSvc.get("ProfD", Ci.nsIFile)
michael@0 30 : dirSvc.get("XREExeF", Ci.nsIFile);
michael@0 31 iniFile.leafName = "distribution";
michael@0 32 iniFile.append("distribution.ini");
michael@0 33 if (iniFile.exists())
michael@0 34 this._iniFile = iniFile;
michael@0 35 }
michael@0 36
michael@0 37 DistributionCustomizer.prototype = {
michael@0 38 _iniFile: null,
michael@0 39
michael@0 40 get _ini() {
michael@0 41 let ini = Cc["@mozilla.org/xpcom/ini-parser-factory;1"].
michael@0 42 getService(Ci.nsIINIParserFactory).
michael@0 43 createINIParser(this._iniFile);
michael@0 44 this.__defineGetter__("_ini", function() ini);
michael@0 45 return this._ini;
michael@0 46 },
michael@0 47
michael@0 48 get _locale() {
michael@0 49 let locale;
michael@0 50 try {
michael@0 51 locale = this._prefs.getCharPref("general.useragent.locale");
michael@0 52 }
michael@0 53 catch (e) {
michael@0 54 locale = "en-US";
michael@0 55 }
michael@0 56 this.__defineGetter__("_locale", function() locale);
michael@0 57 return this._locale;
michael@0 58 },
michael@0 59
michael@0 60 get _prefSvc() {
michael@0 61 let svc = Cc["@mozilla.org/preferences-service;1"].
michael@0 62 getService(Ci.nsIPrefService);
michael@0 63 this.__defineGetter__("_prefSvc", function() svc);
michael@0 64 return this._prefSvc;
michael@0 65 },
michael@0 66
michael@0 67 get _prefs() {
michael@0 68 let branch = this._prefSvc.getBranch(null);
michael@0 69 this.__defineGetter__("_prefs", function() branch);
michael@0 70 return this._prefs;
michael@0 71 },
michael@0 72
michael@0 73 get _ioSvc() {
michael@0 74 let svc = Cc["@mozilla.org/network/io-service;1"].
michael@0 75 getService(Ci.nsIIOService);
michael@0 76 this.__defineGetter__("_ioSvc", function() svc);
michael@0 77 return this._ioSvc;
michael@0 78 },
michael@0 79
michael@0 80 _makeURI: function DIST__makeURI(spec) {
michael@0 81 return this._ioSvc.newURI(spec, null, null);
michael@0 82 },
michael@0 83
michael@0 84 _parseBookmarksSection:
michael@0 85 function DIST_parseBookmarksSection(parentId, section) {
michael@0 86 let keys = [];
michael@0 87 for (let i in enumerate(this._ini.getKeys(section)))
michael@0 88 keys.push(i);
michael@0 89 keys.sort();
michael@0 90
michael@0 91 let items = {};
michael@0 92 let defaultItemId = -1;
michael@0 93 let maxItemId = -1;
michael@0 94
michael@0 95 for (let i = 0; i < keys.length; i++) {
michael@0 96 let m = /^item\.(\d+)\.(\w+)\.?(\w*)/.exec(keys[i]);
michael@0 97 if (m) {
michael@0 98 let [foo, iid, iprop, ilocale] = m;
michael@0 99 iid = parseInt(iid);
michael@0 100
michael@0 101 if (ilocale)
michael@0 102 continue;
michael@0 103
michael@0 104 if (!items[iid])
michael@0 105 items[iid] = {};
michael@0 106 if (keys.indexOf(keys[i] + "." + this._locale) >= 0) {
michael@0 107 items[iid][iprop] = this._ini.getString(section, keys[i] + "." +
michael@0 108 this._locale);
michael@0 109 } else {
michael@0 110 items[iid][iprop] = this._ini.getString(section, keys[i]);
michael@0 111 }
michael@0 112
michael@0 113 if (iprop == "type" && items[iid]["type"] == "default")
michael@0 114 defaultItemId = iid;
michael@0 115
michael@0 116 if (maxItemId < iid)
michael@0 117 maxItemId = iid;
michael@0 118 } else {
michael@0 119 dump("Key did not match: " + keys[i] + "\n");
michael@0 120 }
michael@0 121 }
michael@0 122
michael@0 123 let prependIndex = 0;
michael@0 124 for (let iid = 0; iid <= maxItemId; iid++) {
michael@0 125 if (!items[iid])
michael@0 126 continue;
michael@0 127
michael@0 128 let index = PlacesUtils.bookmarks.DEFAULT_INDEX;
michael@0 129 let newId;
michael@0 130
michael@0 131 switch (items[iid]["type"]) {
michael@0 132 case "default":
michael@0 133 break;
michael@0 134
michael@0 135 case "folder":
michael@0 136 if (iid < defaultItemId)
michael@0 137 index = prependIndex++;
michael@0 138
michael@0 139 newId = PlacesUtils.bookmarks.createFolder(parentId,
michael@0 140 items[iid]["title"],
michael@0 141 index);
michael@0 142
michael@0 143 this._parseBookmarksSection(newId, "BookmarksFolder-" +
michael@0 144 items[iid]["folderId"]);
michael@0 145
michael@0 146 if (items[iid]["description"])
michael@0 147 PlacesUtils.annotations.setItemAnnotation(newId,
michael@0 148 "bookmarkProperties/description",
michael@0 149 items[iid]["description"], 0,
michael@0 150 PlacesUtils.annotations.EXPIRE_NEVER);
michael@0 151
michael@0 152 break;
michael@0 153
michael@0 154 case "separator":
michael@0 155 if (iid < defaultItemId)
michael@0 156 index = prependIndex++;
michael@0 157 PlacesUtils.bookmarks.insertSeparator(parentId, index);
michael@0 158 break;
michael@0 159
michael@0 160 case "livemark":
michael@0 161 if (iid < defaultItemId)
michael@0 162 index = prependIndex++;
michael@0 163
michael@0 164 // Don't bother updating the livemark contents on creation.
michael@0 165 PlacesUtils.livemarks.addLivemark({ title: items[iid]["title"]
michael@0 166 , parentId: parentId
michael@0 167 , index: index
michael@0 168 , feedURI: this._makeURI(items[iid]["feedLink"])
michael@0 169 , siteURI: this._makeURI(items[iid]["siteLink"])
michael@0 170 }).then(null, Cu.reportError);
michael@0 171 break;
michael@0 172
michael@0 173 case "bookmark":
michael@0 174 default:
michael@0 175 if (iid < defaultItemId)
michael@0 176 index = prependIndex++;
michael@0 177
michael@0 178 newId = PlacesUtils.bookmarks.insertBookmark(parentId,
michael@0 179 this._makeURI(items[iid]["link"]),
michael@0 180 index, items[iid]["title"]);
michael@0 181
michael@0 182 if (items[iid]["description"])
michael@0 183 PlacesUtils.annotations.setItemAnnotation(newId,
michael@0 184 "bookmarkProperties/description",
michael@0 185 items[iid]["description"], 0,
michael@0 186 PlacesUtils.annotations.EXPIRE_NEVER);
michael@0 187
michael@0 188 break;
michael@0 189 }
michael@0 190 }
michael@0 191 },
michael@0 192
michael@0 193 _customizationsApplied: false,
michael@0 194 applyCustomizations: function DIST_applyCustomizations() {
michael@0 195 this._customizationsApplied = true;
michael@0 196 if (!this._iniFile)
michael@0 197 return this._checkCustomizationComplete();
michael@0 198
michael@0 199 // nsPrefService loads very early. Reload prefs so we can set
michael@0 200 // distribution defaults during the prefservice:after-app-defaults
michael@0 201 // notification (see applyPrefDefaults below)
michael@0 202 this._prefSvc.QueryInterface(Ci.nsIObserver);
michael@0 203 this._prefSvc.observe(null, "reload-default-prefs", null);
michael@0 204 },
michael@0 205
michael@0 206 _bookmarksApplied: false,
michael@0 207 applyBookmarks: function DIST_applyBookmarks() {
michael@0 208 this._bookmarksApplied = true;
michael@0 209 if (!this._iniFile)
michael@0 210 return this._checkCustomizationComplete();
michael@0 211
michael@0 212 let sections = enumToObject(this._ini.getSections());
michael@0 213
michael@0 214 // The global section, and several of its fields, is required
michael@0 215 // (we also check here to be consistent with applyPrefDefaults below)
michael@0 216 if (!sections["Global"])
michael@0 217 return this._checkCustomizationComplete();
michael@0 218 let globalPrefs = enumToObject(this._ini.getKeys("Global"));
michael@0 219 if (!(globalPrefs["id"] && globalPrefs["version"] && globalPrefs["about"]))
michael@0 220 return this._checkCustomizationComplete();
michael@0 221
michael@0 222 let bmProcessedPref;
michael@0 223 try {
michael@0 224 bmProcessedPref = this._ini.getString("Global",
michael@0 225 "bookmarks.initialized.pref");
michael@0 226 }
michael@0 227 catch (e) {
michael@0 228 bmProcessedPref = "distribution." +
michael@0 229 this._ini.getString("Global", "id") + ".bookmarksProcessed";
michael@0 230 }
michael@0 231
michael@0 232 let bmProcessed = false;
michael@0 233 try {
michael@0 234 bmProcessed = this._prefs.getBoolPref(bmProcessedPref);
michael@0 235 }
michael@0 236 catch (e) {}
michael@0 237
michael@0 238 if (!bmProcessed) {
michael@0 239 if (sections["BookmarksMenu"])
michael@0 240 this._parseBookmarksSection(PlacesUtils.bookmarksMenuFolderId,
michael@0 241 "BookmarksMenu");
michael@0 242 if (sections["BookmarksToolbar"])
michael@0 243 this._parseBookmarksSection(PlacesUtils.toolbarFolderId,
michael@0 244 "BookmarksToolbar");
michael@0 245 this._prefs.setBoolPref(bmProcessedPref, true);
michael@0 246 }
michael@0 247 return this._checkCustomizationComplete();
michael@0 248 },
michael@0 249
michael@0 250 _prefDefaultsApplied: false,
michael@0 251 applyPrefDefaults: function DIST_applyPrefDefaults() {
michael@0 252 this._prefDefaultsApplied = true;
michael@0 253 if (!this._iniFile)
michael@0 254 return this._checkCustomizationComplete();
michael@0 255
michael@0 256 let sections = enumToObject(this._ini.getSections());
michael@0 257
michael@0 258 // The global section, and several of its fields, is required
michael@0 259 if (!sections["Global"])
michael@0 260 return this._checkCustomizationComplete();
michael@0 261 let globalPrefs = enumToObject(this._ini.getKeys("Global"));
michael@0 262 if (!(globalPrefs["id"] && globalPrefs["version"] && globalPrefs["about"]))
michael@0 263 return this._checkCustomizationComplete();
michael@0 264
michael@0 265 let defaults = this._prefSvc.getDefaultBranch(null);
michael@0 266
michael@0 267 // Global really contains info we set as prefs. They're only
michael@0 268 // separate because they are "special" (read: required)
michael@0 269
michael@0 270 defaults.setCharPref("distribution.id", this._ini.getString("Global", "id"));
michael@0 271 defaults.setCharPref("distribution.version",
michael@0 272 this._ini.getString("Global", "version"));
michael@0 273
michael@0 274 let partnerAbout = Cc["@mozilla.org/supports-string;1"].
michael@0 275 createInstance(Ci.nsISupportsString);
michael@0 276 try {
michael@0 277 if (globalPrefs["about." + this._locale]) {
michael@0 278 partnerAbout.data = this._ini.getString("Global", "about." + this._locale);
michael@0 279 } else {
michael@0 280 partnerAbout.data = this._ini.getString("Global", "about");
michael@0 281 }
michael@0 282 defaults.setComplexValue("distribution.about",
michael@0 283 Ci.nsISupportsString, partnerAbout);
michael@0 284 } catch (e) {
michael@0 285 /* ignore bad prefs due to bug 895473 and move on */
michael@0 286 Cu.reportError(e);
michael@0 287 }
michael@0 288
michael@0 289 if (sections["Preferences"]) {
michael@0 290 for (let key in enumerate(this._ini.getKeys("Preferences"))) {
michael@0 291 try {
michael@0 292 let value = eval(this._ini.getString("Preferences", key));
michael@0 293 switch (typeof value) {
michael@0 294 case "boolean":
michael@0 295 defaults.setBoolPref(key, value);
michael@0 296 break;
michael@0 297 case "number":
michael@0 298 defaults.setIntPref(key, value);
michael@0 299 break;
michael@0 300 case "string":
michael@0 301 defaults.setCharPref(key, value);
michael@0 302 break;
michael@0 303 case "undefined":
michael@0 304 defaults.setCharPref(key, value);
michael@0 305 break;
michael@0 306 }
michael@0 307 } catch (e) { /* ignore bad prefs and move on */ }
michael@0 308 }
michael@0 309 }
michael@0 310
michael@0 311 // We eval() the localizable prefs as well (even though they'll
michael@0 312 // always get set as a string) to keep the INI format consistent:
michael@0 313 // string prefs always need to be in quotes
michael@0 314
michael@0 315 let localizedStr = Cc["@mozilla.org/pref-localizedstring;1"].
michael@0 316 createInstance(Ci.nsIPrefLocalizedString);
michael@0 317
michael@0 318 if (sections["LocalizablePreferences"]) {
michael@0 319 for (let key in enumerate(this._ini.getKeys("LocalizablePreferences"))) {
michael@0 320 try {
michael@0 321 let value = eval(this._ini.getString("LocalizablePreferences", key));
michael@0 322 value = value.replace("%LOCALE%", this._locale, "g");
michael@0 323 localizedStr.data = "data:text/plain," + key + "=" + value;
michael@0 324 defaults.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr);
michael@0 325 } catch (e) { /* ignore bad prefs and move on */ }
michael@0 326 }
michael@0 327 }
michael@0 328
michael@0 329 if (sections["LocalizablePreferences-" + this._locale]) {
michael@0 330 for (let key in enumerate(this._ini.getKeys("LocalizablePreferences-" + this._locale))) {
michael@0 331 try {
michael@0 332 let value = eval(this._ini.getString("LocalizablePreferences-" + this._locale, key));
michael@0 333 localizedStr.data = "data:text/plain," + key + "=" + value;
michael@0 334 defaults.setComplexValue(key, Ci.nsIPrefLocalizedString, localizedStr);
michael@0 335 } catch (e) { /* ignore bad prefs and move on */ }
michael@0 336 }
michael@0 337 }
michael@0 338
michael@0 339 return this._checkCustomizationComplete();
michael@0 340 },
michael@0 341
michael@0 342 _checkCustomizationComplete: function DIST__checkCustomizationComplete() {
michael@0 343 let prefDefaultsApplied = this._prefDefaultsApplied || !this._iniFile;
michael@0 344 if (this._customizationsApplied && this._bookmarksApplied &&
michael@0 345 prefDefaultsApplied) {
michael@0 346 let os = Cc["@mozilla.org/observer-service;1"].
michael@0 347 getService(Ci.nsIObserverService);
michael@0 348 os.notifyObservers(null, DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC, null);
michael@0 349 }
michael@0 350 }
michael@0 351 };
michael@0 352
michael@0 353 function enumerate(UTF8Enumerator) {
michael@0 354 while (UTF8Enumerator.hasMore())
michael@0 355 yield UTF8Enumerator.getNext();
michael@0 356 }
michael@0 357
michael@0 358 function enumToObject(UTF8Enumerator) {
michael@0 359 let ret = {};
michael@0 360 for (let i in enumerate(UTF8Enumerator))
michael@0 361 ret[i] = 1;
michael@0 362 return ret;
michael@0 363 }

mercurial