Remove unused variable. bug 420966
[mozilla-1.9.git] / xulrunner / setup / nsXULAppInstall.js
blobc467e17f5bd945c54c3bf9cdd890ba347a6ff5cb
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 #filter substitution
3 #if 0
4 /* ***** BEGIN LICENSE BLOCK *****
5  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is Mozilla XULRunner.
18  *
19  * The Initial Developer of the Original Code is
20  * Benjamin Smedberg <benjamin@smedbergs.us>
21  *
22  * Portions created by the Initial Developer are Copyright (C) 2005
23  * the Mozilla Foundation <http://www.mozilla.org/>. All Rights Reserved.
24  *
25  * Contributor(s):
26  *
27  * Alternatively, the contents of this file may be used under the terms of
28  * either the GNU General Public License Version 2 or later (the "GPL"), or
29  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30  * in which case the provisions of the GPL or the LGPL are applicable instead
31  * of those above. If you wish to allow use of your version of this file only
32  * under the terms of either the GPL or the LGPL, and not to allow others to
33  * use your version of this file under the terms of the MPL, indicate your
34  * decision by deleting the provisions above and replace them with the notice
35  * and other provisions required by the GPL or the LGPL. If you do not delete
36  * the provisions above, a recipient may use your version of this file under
37  * the terms of any one of the MPL, the GPL or the LGPL.
38  *
39  * ***** END LICENSE BLOCK ***** */
40 #endif
42 const nsIFile             = Components.interfaces.nsIFile;
43 const nsIINIParser        = Components.interfaces.nsIINIParser;
44 const nsIINIParserFactory = Components.interfaces.nsIINIParserFactory;
45 const nsILocalFile        = Components.interfaces.nsILocalFile;
46 const nsISupports         = Components.interfaces.nsISupports;
47 const nsIXULAppInstall    = Components.interfaces.nsIXULAppInstall;
48 const nsIZipReader        = Components.interfaces.nsIZipReader;
50 function getDirectoryKey(aKey) {
51   try {
52     return Components.classes["@mozilla.org/file/directory_service;1"].
53       getService(Components.interfaces.nsIProperties).
54       get(aKey, nsIFile);
55   }
56   catch (e) {
57     throw "Couln't get directory service key: " + aKey;
58   }
61 function createINIParser(aFile) {
62   return Components.manager.
63     getClassObjectByContractID("@mozilla.org/xpcom/ini-parser-factory;1",
64                                nsIINIParserFactory).
65     createINIParser(aFile);
68 function copy_recurse(aSource, aDest) {
69   var e = aSource.directoryEntries;
71   while (e.hasMoreElements()) {
72     var f = e.getNext().QueryInterface(nsIFile);
73     var leaf = f.leafName;
75     var ddest = aDest.clone();
76     ddest.append(leaf);
78     if (f.isDirectory()) {
79       copy_recurse(f, ddest);
80     }
81     else {
82       if (ddest.exists())
83         ddest.remove(false);
85       f.copyTo(aDest, leaf);
86     }
87   }
90 const PR_WRONLY = 0x02;
91 const PR_CREATE_FILE = 0x08;
92 const PR_TRUNCATE = 0x20;
94 function openFileOutputStream(aFile) {
95   var s = Components.classes["@mozilla.org/network/file-output-stream;1"].
96     createInstance(Components.interfaces.nsIFileOutputStream);
97   s.init(aFile, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0644, 0);
98   return s;
102  * An extractor implements the following prototype:
103  * readonly attribute nsIINIPaser iniParser;
104  * void copyTo(in nsILocalFile root);
105  */
107 function directoryExtractor(aFile) {
108   this.mDirectory = aFile;
111 directoryExtractor.prototype = {
112   mINIParser : null,
114   get iniParser() {
115     if (!this.mINIParser) {
116       var iniFile = this.mDirectory.clone();
117       iniFile.append("application.ini");
119       this.mINIParser = createINIParser(iniFile);
120     }
121     return this.mINIParser;
122   },
124   copyTo : function de_copyTo(aDest) {
125     // Assume the root already exists
126     copy_recurse(this.mDirectory, aDest);
127   }
130 function zipExtractor(aFile) {
131   this.mZipReader = Components.classes["@mozilla.org/libjar/zip-reader;1"].
132     createInstance(nsIZipReader);
133   this.mZipReader.open(aFile);
134   this.mZipReader.test(null);
137 zipExtractor.prototype = {
138   mINIParser : null,
140   get iniParser() {
141     if (!this.mINIParser) {
142       // XXXbsmedberg: this is not very unique, guessing could be a problem
143       var f = getDirectoryKey("TmpD");
144       f.append("application.ini");
145       f.createUnique(nsIFile.NORMAL_FILE_TYPE, 0600);
147       try {
148         this.mZipReader.extract("application.ini", f);
149         this.mINIParser = createINIParser(f);
150       }
151       catch (e) {
152         try {
153           f.remove();
154         }
155         catch (ee) { }
157         throw e;
158       }
159       try {
160         f.remove();
161       }
162       catch (e) { }
163     }
164     return this.mINIParser;
165   },
167   copyTo : function ze_CopyTo(aDest) {
168     var entries = this.mZipReader.findEntries(null);
169     while (entries.hasMore()) {
170       var entryName = entries.getNext();
172       this._installZipEntry(this.mZipReader, entryName, aDest);
173     }
174   },
176   _installZipEntry : function ze_installZipEntry(aZipReader, aZipEntry,
177                                                  aDestination) {
178     var file = aDestination.clone();
180     var dirs = aZipEntry.split(/\//);
181     var isDirectory = /\/$/.test(aZipEntry);
183     var end = dirs.length;
184     if (!isDirectory)
185       --end;
187     for (var i = 0; i < end; ++i) {
188       file.append(dirs[i]);
189       if (!file.exists()) {
190         file.create(nsIFile.DIRECTORY_TYPE, 0755);
191       }
192     }
194     if (!isDirectory) {
195       file.append(dirs[end]);
196       aZipReader.extract(aZipEntry, file);
197     }
198   }
201 function createExtractor(aFile) {
202   if (aFile.isDirectory())
203     return new directoryExtractor(aFile);
205   return new zipExtractor(aFile);
208 const AppInstall = {
210   /* nsISupports */
211   QueryInterface : function ai_QI(iid) {
212     if (iid.equals(nsIXULAppInstall) ||
213         iid.equals(nsISupports))
214       return this;
216     throw Components.result.NS_ERROR_NO_INTERFACE;
217   },
219   /* nsIXULAppInstall */
220   installApplication : function ai_IA(aAppFile, aDirectory, aLeafName) {
221     var extractor = createExtractor(aAppFile);
222     var iniParser = extractor.iniParser;
224     var appName = iniParser.getString("App", "Name");
226     // vendor is optional
227     var vendor;
228     try {
229       vendor = iniParser.getString("App", "Vendor");
230     }
231     catch (e) { }
233     if (aDirectory == null) {
234 #ifdef XP_WIN
235       aDirectory = getDirectoryKey("ProgF");
236       if (vendor)
237         aDirectory.append(vendor);
238 #else
239 #ifdef XP_MACOSX
240       aDirectory = getDirectoryKey("LocApp");
241       if (vendor)
242         aDirectory.append(vendor);
243 #else
244       aDirectory = Components.classes["@mozilla.org/file/local;1"].
245         createInstance(nsILocalFile);
246       aDirectory.initWithPath("/usr/lib");
247       if (vendor)
248         aDirectory.append(vendor.toLowerCase());
249 #endif
250 #endif
251     }
252     else {
253       aDirectory = aDirectory.clone();
254     }
256     if (!aDirectory.exists()) {
257       aDirectory.create(nsIFile.DIRECTORY_TYPE, 0755);
258     }
260     if (aLeafName == "") {
261 #ifdef XP_MACOSX
262       aLeafName = appName + ".app";
263 #else
264 #ifdef XP_WIN
265       aLeafName = appName;
266 #else
267       aLeafName = appName.toLowerCase();
268 #endif
269 #endif
270     }
272     aDirectory.append(aLeafName);
273     if (!aDirectory.exists()) {
274       aDirectory.create(nsIFile.DIRECTORY_TYPE, 0755);
275     }
277 #ifdef XP_MACOSX
278     aDirectory.append("Contents");
279     if (!aDirectory.exists()) {
280       aDirectory.create(nsIFile.DIRECTORY_TYPE, 0755);
281     }
283     var version = iniParser.getString("App", "Version");
284     var buildID = iniParser.getString("App", "BuildID");
286     var infoString = "";
287     if (vendor) {
288       infoString = vendor + " ";
289     }
290     infoString += appName + " " + version;
292     var plistFile = aDirectory.clone();
293     plistFile.append("Info.plist");
294     var ostream = openFileOutputStream(plistFile);
296     var contents =
297     "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
298     "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" +
299     "<plist version=\"1.0\">\n" +
300     "<dict>\n" +
301     "<key>CFBundleInfoDictionaryVersion</key>\n" +
302     "<string>6.0</string>\n" +
303     "<key>CFBundlePackageType</key>\n" +
304     "<string>APPL</string>\n" +
305     "<key>CFBundleExecutable</key>\n" +
306     "<string>xulrunner</string>\n" +
307     "<key>NSAppleScriptEnabled</key>\n" +
308     "<true/>\n" +
309     "<key>CFBundleGetInfoString</key>\n" +
310     "<string>" + infoString + "</string>\n" +
311     "<key>CFBundleName</key>\n" +
312     "<string>" + appName + "</string>\n" +
313     "<key>CFBundleShortVersionString</key>\n" +
314     "<string>" + version + "</string>\n" +
315     "<key>CFBundleVersion</key>\n" +
316     "<string>" + version + "." + buildID + "</string>\n" +
317     "</dict>\n" +
318     "</plist>";
320     // "<key>CFBundleIdentifier</key>\n" +
321     // "<string>org.%s.%s</string>\n" +
322     // "<key>CFBundleSignature</key>\n" +
323     // "<string>MOZB</string>\n" +
324     // "<key>CFBundleIconFile</key>\n" +
325     // "<string>document.icns</string>\n" +
327     ostream.write(contents, contents.length);
328     ostream.close();
330     var contentsDir = aDirectory.clone();
331     contentsDir.append("MacOS");
333     var xulrunnerBinary = getDirectoryKey("XCurProcD");
334     xulrunnerBinary.append("xulrunner");
336     xulrunnerBinary.copyTo(contentsDir, "xulrunner");
338     aDirectory.append("Resources");
339     extractor.copyTo(aDirectory);
340 #else
341     extractor.copyTo(aDirectory);
343     var xulrunnerBinary = getDirectoryKey("XCurProcD");
344     xulrunnerBinary.append("xulrunner-stub@BIN_SUFFIX@");
346     xulrunnerBinary.copyTo(aDirectory, appName.toLowerCase() + "@BIN_SUFFIX@");
347 #endif
348   }
351 const AppInstallFactory = {
352   /* nsISupports */
353   QueryInterface : function aif_QI(iid) {
354     if (iid.equals(Components.interfaces.nsIFactory) ||
355         iid.equals(nsISupports))
356       return this;
358     throw Components.results.NS_ERROR_NO_INTERFACE;
359   },
361   /* nsIFactory */
362   createInstance : function aif_CI(aOuter, aIID) {
363     if (aOuter)
364       throw Components.results.NS_ERROR_NO_AGGREGATION;
366     return AppInstall.QueryInterface(aIID);
367   },
369   lockFactory : function aif_lock(aLock) { }
372 const AppInstallContractID = "@mozilla.org/xulrunner/app-install-service;1";
373 const AppInstallCID = Components.ID("{00790a19-27e2-4d9a-bef0-244080feabfd}");
375 const AppInstallModule = {
376   /* nsISupports */
377   QueryInterface : function mod_QI(iid) {
378     if (iid.equals(Components.interfaces.nsIModule) ||
379         iid.equals(nsISupports))
380       return this;
382     throw Components.results.NS_ERROR_NO_INTERFACE;
383   },
385   /* nsIModule */
386   getClassObject : function mod_gco(aCompMgr, aClass, aIID) {
387     if (aClass.equals(AppInstallCID))
388       return AppInstallFactory.QueryInterface(aIID);
390     return Components.results.NS_ERROR_FACTORY_NOT_REGISTERED;
391   },
393   registerSelf : function mod_regself(aCompMgr, aLocation,
394                                       aLoaderStr, aType) {
395     var reg = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
396     reg.registerFactoryLocation(AppInstallCID,
397                                 "nsXULAppInstall",
398                                 AppInstallContractID,
399                                 aLocation,
400                                 aLoaderStr,
401                                 aType);
402   },
404   unregisterSelf : function mod_unreg(aCompMgr, aLocation, aLoaderStr) {
405     var reg = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
406     reg.unregisterFactoryLocation(AppInstallCID,
407                                   aLocation);
408   },
410   canUnload : function mod_unload(aCompMgr) {
411     return true;
412   }
415 function NSGetModule(compMgr, fileSpec) {
416   return AppInstallModule;