distribution.js
Go to the documentation of this file.
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 
46  "distribution-customization-complete";
47 const BOOKMARKS_ROOT = "SB:Bookmarks";
48 
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 
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);
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 }
var dirSvc
function enumerate(UTF8Enumerator)
const Cu
Definition: distribution.js:43
const DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC
Definition: distribution.js:45
EXPORTED_SYMBOLS
Definition: distribution.js:38
sidebarFactory createInstance
Definition: nsSidebar.js:351
getService(Ci.sbIFaceplateManager)
const Cr
Definition: distribution.js:42
function enumToObject(UTF8Enumerator)
function DistributionCustomizer()
Definition: distribution.js:49
const BOOKMARKS_ROOT
Definition: distribution.js:47
return null
Definition: FeedWriter.js:1143
return ret
var os
countRef value
Definition: FeedWriter.js:1423
Sanitizer _prefs
Definition: sanitize.js:435
const Ci
Definition: distribution.js:40
__defineGetter__("Application", function(){delete this.Application;return this.Application=Cc["@mozilla.org/fuel/application;1"].getService(Ci.fuelIApplication);})
_getSelectedPageStyle s i
const Cc
Definition: distribution.js:41