1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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
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.
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 ***** */
42 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
44 const nsIFile = Components.interfaces.nsIFile;
45 const nsIINIParser = Components.interfaces.nsIINIParser;
46 const nsIINIParserFactory = Components.interfaces.nsIINIParserFactory;
47 const nsILocalFile = Components.interfaces.nsILocalFile;
48 const nsISupports = Components.interfaces.nsISupports;
49 const nsIXULAppInstall = Components.interfaces.nsIXULAppInstall;
50 const nsIZipReader = Components.interfaces.nsIZipReader;
52 function getDirectoryKey(aKey) {
54 return Components.classes["@mozilla.org/file/directory_service;1"].
55 getService(Components.interfaces.nsIProperties).
59 throw "Couln't get directory service key: " + aKey;
63 function createINIParser(aFile) {
64 return Components.manager.
65 getClassObjectByContractID("@mozilla.org/xpcom/ini-parser-factory;1",
67 createINIParser(aFile);
70 function copy_recurse(aSource, aDest) {
71 var e = aSource.directoryEntries;
73 while (e.hasMoreElements()) {
74 var f = e.getNext().QueryInterface(nsIFile);
75 var leaf = f.leafName;
77 var ddest = aDest.clone();
80 if (f.isDirectory()) {
81 copy_recurse(f, ddest);
87 f.copyTo(aDest, leaf);
92 const PR_WRONLY = 0x02;
93 const PR_CREATE_FILE = 0x08;
94 const PR_TRUNCATE = 0x20;
96 function openFileOutputStream(aFile) {
97 var s = Components.classes["@mozilla.org/network/file-output-stream;1"].
98 createInstance(Components.interfaces.nsIFileOutputStream);
99 s.init(aFile, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE, 0644, 0);
104 * An extractor implements the following prototype:
105 * readonly attribute nsIINIPaser iniParser;
106 * void copyTo(in nsILocalFile root);
109 function directoryExtractor(aFile) {
110 this.mDirectory = aFile;
113 directoryExtractor.prototype = {
117 if (!this.mINIParser) {
118 var iniFile = this.mDirectory.clone();
119 iniFile.append("application.ini");
121 this.mINIParser = createINIParser(iniFile);
123 return this.mINIParser;
126 copyTo : function de_copyTo(aDest) {
127 // Assume the root already exists
128 copy_recurse(this.mDirectory, aDest);
132 function zipExtractor(aFile) {
133 this.mZipReader = Components.classes["@mozilla.org/libjar/zip-reader;1"].
134 createInstance(nsIZipReader);
135 this.mZipReader.open(aFile);
136 this.mZipReader.test(null);
139 zipExtractor.prototype = {
143 if (!this.mINIParser) {
144 // XXXbsmedberg: this is not very unique, guessing could be a problem
145 var f = getDirectoryKey("TmpD");
146 f.append("application.ini");
147 f.createUnique(nsIFile.NORMAL_FILE_TYPE, 0600);
150 this.mZipReader.extract("application.ini", f);
151 this.mINIParser = createINIParser(f);
166 return this.mINIParser;
169 copyTo : function ze_CopyTo(aDest) {
170 var entries = this.mZipReader.findEntries(null);
171 while (entries.hasMore()) {
172 var entryName = entries.getNext();
174 this._installZipEntry(this.mZipReader, entryName, aDest);
178 _installZipEntry : function ze_installZipEntry(aZipReader, aZipEntry,
180 var file = aDestination.clone();
182 var dirs = aZipEntry.split(/\//);
183 var isDirectory = /\/$/.test(aZipEntry);
185 var end = dirs.length;
189 for (var i = 0; i < end; ++i) {
190 file.append(dirs[i]);
191 if (!file.exists()) {
192 file.create(nsIFile.DIRECTORY_TYPE, 0755);
197 file.append(dirs[end]);
198 aZipReader.extract(aZipEntry, file);
203 function createExtractor(aFile) {
204 if (aFile.isDirectory())
205 return new directoryExtractor(aFile);
207 return new zipExtractor(aFile);
210 function AppInstall() {
213 AppInstall.prototype = {
214 classID: Components.ID("{00790a19-27e2-4d9a-bef0-244080feabfd}"),
217 QueryInterface : XPCOMUtils.generateQI([nsIXULAppInstall]),
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
229 vendor = iniParser.getString("App", "Vendor");
233 if (aDirectory == null) {
235 aDirectory = getDirectoryKey("ProgF");
237 aDirectory.append(vendor);
240 aDirectory = getDirectoryKey("LocApp");
242 aDirectory.append(vendor);
244 aDirectory = Components.classes["@mozilla.org/file/local;1"].
245 createInstance(nsILocalFile);
246 aDirectory.initWithPath("/usr/local/lib");
248 aDirectory.append(vendor.toLowerCase());
253 aDirectory = aDirectory.clone();
256 if (!aDirectory.exists()) {
257 aDirectory.create(nsIFile.DIRECTORY_TYPE, 0755);
260 if (aLeafName == "") {
262 aLeafName = appName + ".app";
267 aLeafName = appName.toLowerCase();
272 aDirectory.append(aLeafName);
273 if (!aDirectory.exists()) {
274 aDirectory.create(nsIFile.DIRECTORY_TYPE, 0755);
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");
288 infoString = vendor + " ";
290 infoString += appName + " " + version;
292 var plistFile = aDirectory.clone();
293 plistFile.append("Info.plist");
294 var ostream = openFileOutputStream(plistFile);
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" +
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" +
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" +
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);
330 var contentsDir = aDirectory.clone();
331 contentsDir.append("MacOS");
333 var xulrunnerBinary = getDirectoryKey("GreD");
334 xulrunnerBinary.append("xulrunner");
336 xulrunnerBinary.copyTo(contentsDir, "xulrunner");
338 aDirectory.append("Resources");
339 extractor.copyTo(aDirectory);
341 extractor.copyTo(aDirectory);
343 var xulrunnerBinary = getDirectoryKey("GreD");
344 xulrunnerBinary.append("xulrunner-stub@BIN_SUFFIX@");
346 xulrunnerBinary.copyTo(aDirectory, appName.toLowerCase() + "@BIN_SUFFIX@");
351 const NSGetFactory = XPCOMUtils.generateNSGetFactory([AppInstall]);