Backed out changeset 7362e63c648e (relanding bug 449422)
[wine-gecko.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
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/
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.
17 * The Original Code is Mozilla XULRunner.
19 * The Initial Developer of the Original Code is
20 * Benjamin Smedberg <benjamin@smedbergs.us>
22 * Portions created by the Initial Developer are Copyright (C) 2005
23 * the Mozilla Foundation <http://www.mozilla.org/>. All Rights Reserved.
25 * Contributor(s):
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.
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);
56 catch (e) {
57 throw "Couln't get directory service key: " + aKey;
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);
81 else {
82 if (ddest.exists())
83 ddest.remove(false);
85 f.copyTo(aDest, leaf);
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);
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);
121 return this.mINIParser;
124 copyTo : function de_copyTo(aDest) {
125 // Assume the root already exists
126 copy_recurse(this.mDirectory, aDest);
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);
151 catch (e) {
152 try {
153 f.remove();
155 catch (ee) { }
157 throw e;
159 try {
160 f.remove();
162 catch (e) { }
164 return this.mINIParser;
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);
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);
194 if (!isDirectory) {
195 file.append(dirs[end]);
196 aZipReader.extract(aZipEntry, file);
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;
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");
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
252 else {
253 aDirectory = aDirectory.clone();
256 if (!aDirectory.exists()) {
257 aDirectory.create(nsIFile.DIRECTORY_TYPE, 0755);
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
272 aDirectory.append(aLeafName);
273 if (!aDirectory.exists()) {
274 aDirectory.create(nsIFile.DIRECTORY_TYPE, 0755);
277 #ifdef XP_MACOSX
278 aDirectory.append("Contents");
279 if (!aDirectory.exists()) {
280 aDirectory.create(nsIFile.DIRECTORY_TYPE, 0755);
283 var version = iniParser.getString("App", "Version");
284 var buildID = iniParser.getString("App", "BuildID");
286 var infoString = "";
287 if (vendor) {
288 infoString = vendor + " ";
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
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;
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);
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;
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;
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);
404 unregisterSelf : function mod_unreg(aCompMgr, aLocation, aLoaderStr) {
405 var reg = aCompMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
406 reg.unregisterFactoryLocation(AppInstallCID,
407 aLocation);
410 canUnload : function mod_unload(aCompMgr) {
411 return true;
415 function NSGetModule(compMgr, fileSpec) {
416 return AppInstallModule;