xulrunner/app/install_app.py

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 #!/usr/bin/env python
michael@0 2
michael@0 3 # This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
michael@0 5 # You can obtain one at http://mozilla.org/MPL/2.0/.
michael@0 6
michael@0 7 # Min version of python is 2.7
michael@0 8 import sys
michael@0 9 if ((sys.version_info.major != 2) or (sys.version_info.minor < 7)):
michael@0 10 raise Exception("You need to use Python version 2.7 or higher")
michael@0 11
michael@0 12 import os, shutil, re, zipfile
michael@0 13 from ConfigParser import SafeConfigParser
michael@0 14
michael@0 15 # Platform-specific support
michael@0 16 # see https://developer.mozilla.org/en/XULRunner/Deploying_XULRunner_1.8
michael@0 17 if sys.platform.startswith('linux') or sys.platform == "win32":
michael@0 18 def installApp(appLocation, installDir, appName, greDir):
michael@0 19 zipApp, iniParser, appName = validateArguments(appLocation, installDir, appName, greDir)
michael@0 20 if (zipApp):
michael@0 21 zipApp.extractAll(installDir)
michael@0 22 else:
michael@0 23 shutil.copytree(appLocation, installDir)
michael@0 24 shutil.copy2(os.path.join(greDir, xulrunnerStubName),
michael@0 25 os.path.join(installDir, appName))
michael@0 26 copyGRE(greDir, os.path.join(installDir, "xulrunner"))
michael@0 27
michael@0 28 if sys.platform.startswith('linux'):
michael@0 29 xulrunnerStubName = "xulrunner-stub"
michael@0 30
michael@0 31 def makeAppName(leafName):
michael@0 32 return leafName.lower()
michael@0 33
michael@0 34 elif sys.platform == "win32":
michael@0 35 xulrunnerStubName = "xulrunner-stub.exe"
michael@0 36
michael@0 37 def makeAppName(leafName):
michael@0 38 return leafName + ".exe"
michael@0 39
michael@0 40 elif sys.platform == "darwin":
michael@0 41 xulrunnerStubName = "xulrunner"
michael@0 42
michael@0 43 def installApp(appLocation, installDir, appName, greDir):
michael@0 44 zipApp, iniparser, appName = validateArguments(appLocation, installDir, appName, greDir)
michael@0 45 installDir += "/" + appName + ".app"
michael@0 46 resourcesDir = os.path.join(installDir, "Contents/Resources")
michael@0 47 if (zipApp):
michael@0 48 zipApp.extractAll(resourcesDir)
michael@0 49 else:
michael@0 50 shutil.copytree(appLocation, resourcesDir)
michael@0 51 MacOSDir = os.path.join(installDir, "Contents/MacOS")
michael@0 52 os.makedirs(MacOSDir)
michael@0 53 shutil.copy2(os.path.join(greDir, xulrunnerStubName), MacOSDir)
michael@0 54 copyGRE(greDir,
michael@0 55 os.path.join(installDir, "Contents/Frameworks/XUL.framework"))
michael@0 56
michael@0 57 # Contents/Info.plist
michael@0 58 contents = """<?xml version="1.0" encoding="UTF-8"?>
michael@0 59 <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
michael@0 60 <plist version="1.0">
michael@0 61 <dict>
michael@0 62 <key>CFBundleInfoDictionaryVersion</key>
michael@0 63 <string>6.0</string>
michael@0 64 <key>CFBundlePackageType</key>
michael@0 65 <string>APPL</string>
michael@0 66 <key>CFBundleSignature</key>
michael@0 67 <string>????</string>
michael@0 68 <key>CFBundleExecutable</key>
michael@0 69 <string>xulrunner</string>
michael@0 70 <key>NSAppleScriptEnabled</key>
michael@0 71 <true/>
michael@0 72 <key>CFBundleGetInfoString</key>
michael@0 73 <string>$infoString</string>
michael@0 74 <key>CFBundleName</key>
michael@0 75 <string>$appName</string>
michael@0 76 <key>CFBundleShortVersionString</key>
michael@0 77 <string>$version</string>
michael@0 78 <key>CFBundleVersion</key>
michael@0 79 <string>$version.$buildID</string>
michael@0 80 <key>CFBundleIdentifier</key>
michael@0 81 <string>$reverseVendor</string>
michael@0 82 </dict>
michael@0 83 </plist>
michael@0 84 """
michael@0 85 version = iniparser.get("App", "Version")
michael@0 86 buildID = iniparser.get("App", "BuildID")
michael@0 87 infoString = appName + " " + version
michael@0 88 reverseVendor = "com.vendor.unknown"
michael@0 89 appID = iniparser.get("App", "ID")
michael@0 90 colonIndex = appID.find("@") + 1
michael@0 91 if (colonIndex != 0):
michael@0 92 vendor = appID[colonIndex:]
michael@0 93 reverseVendor = ".".join(vendor.split(".")[::-1])
michael@0 94 contents = contents.replace("$infoString", infoString)
michael@0 95 contents = contents.replace("$appName", appName)
michael@0 96 contents = contents.replace("$version", version)
michael@0 97 contents = contents.replace("$buildID", buildID)
michael@0 98 contents = contents.replace("$reverseVendor", reverseVendor)
michael@0 99 infoPList = open(os.path.join(installDir, "Contents/Info.plist"), "w+b")
michael@0 100 infoPList.write(contents)
michael@0 101 infoPList.close()
michael@0 102
michael@0 103 def makeAppName(leafName):
michael@0 104 return leafName
michael@0 105
michael@0 106 else:
michael@0 107 # Implement xulrunnerStubName, installApp and makeAppName as above.
michael@0 108 raise Exception("This operating system isn't supported for install_app.py yet!")
michael@0 109 # End platform-specific support
michael@0 110
michael@0 111 def resolvePath(path):
michael@0 112 return os.path.realpath(path)
michael@0 113
michael@0 114 def requireINIOption(iniparser, section, option):
michael@0 115 if not (iniparser.has_option(section, option)):
michael@0 116 raise Exception("application.ini must have a " + option + " option under the " + section + " section")
michael@0 117
michael@0 118 def checkAppINI(appLocation):
michael@0 119 if (os.path.isdir(appLocation)):
michael@0 120 zipApp = None
michael@0 121 appINIPath = os.path.join(appLocation, "application.ini")
michael@0 122 if not (os.path.isfile(appINIPath)):
michael@0 123 raise Exception(appINIPath + " does not exist")
michael@0 124 appINI = open(appINIPath)
michael@0 125 elif (zipfile.is_zipfile(appLocation)):
michael@0 126 zipApp = zipfile.ZipFile(appLocation)
michael@0 127 if not ("application.ini" in zipApp.namelist()):
michael@0 128 raise Exception("jar:" + appLocation + "!/application.ini does not exist")
michael@0 129 appINI = zipApp.open("application.ini")
michael@0 130 else:
michael@0 131 raise Exception("appLocation must be a directory containing application.ini or a zip file with application.ini at its root")
michael@0 132
michael@0 133 # application.ini verification
michael@0 134 iniparser = SafeConfigParser()
michael@0 135 iniparser.readfp(appINI)
michael@0 136 if not (iniparser.has_section("App")):
michael@0 137 raise Exception("application.ini must have an App section")
michael@0 138 if not (iniparser.has_section("Gecko")):
michael@0 139 raise Exception("application.ini must have a Gecko section")
michael@0 140 requireINIOption(iniparser, "App", "Name")
michael@0 141 requireINIOption(iniparser, "App", "Version")
michael@0 142 requireINIOption(iniparser, "App", "BuildID")
michael@0 143 requireINIOption(iniparser, "App", "ID")
michael@0 144 requireINIOption(iniparser, "Gecko", "MinVersion")
michael@0 145
michael@0 146 return zipApp, iniparser
michael@0 147 pass
michael@0 148
michael@0 149 def copyGRE(greDir, targetDir):
michael@0 150 shutil.copytree(greDir, targetDir, symlinks=True)
michael@0 151
michael@0 152 def validateArguments(appLocation, installDir, appName, greDir):
michael@0 153 # application directory / zip verification
michael@0 154 appLocation = resolvePath(appLocation)
michael@0 155
michael@0 156 # target directory
michael@0 157 installDir = resolvePath(installDir)
michael@0 158
michael@0 159 if (os.path.exists(installDir)):
michael@0 160 raise Exception("installDir must not exist: " + cmds.installDir)
michael@0 161
michael@0 162 greDir = resolvePath(greDir)
michael@0 163 xulrunnerStubPath = os.path.isfile(os.path.join(greDir, xulrunnerStubName))
michael@0 164 if not xulrunnerStubPath:
michael@0 165 raise Exception("XULRunner stub executable not found: " + os.path.join(greDir, xulrunnerStubName))
michael@0 166
michael@0 167 # appName
michael@0 168 zipApp, iniparser = checkAppINI(appLocation)
michael@0 169 if not appName:
michael@0 170 appName = iniparser.get("App", "Name")
michael@0 171 appName = makeAppName(appName)
michael@0 172 pattern = re.compile("[\\\/\:*?\"<>|\x00]")
michael@0 173 if pattern.search(appName):
michael@0 174 raise Exception("App name has illegal characters for at least one operating system")
michael@0 175 return zipApp, iniparser, appName
michael@0 176
michael@0 177 def handleCommandLine():
michael@0 178 import argparse
michael@0 179
michael@0 180 # Argument parsing.
michael@0 181 parser = argparse.ArgumentParser(
michael@0 182 description="XULRunner application installer",
michael@0 183 usage="""install_app.py appLocation installDir greDir [--appName APPNAME]
michael@0 184 install_app.py -h
michael@0 185 install_app.py --version
michael@0 186 """
michael@0 187 )
michael@0 188 parser.add_argument(
michael@0 189 "appLocation",
michael@0 190 action="store",
michael@0 191 help="The directory or ZIP file containing application.ini as a top-level child file"
michael@0 192 )
michael@0 193 parser.add_argument(
michael@0 194 "installDir",
michael@0 195 action="store",
michael@0 196 help="The directory to install the application to"
michael@0 197 )
michael@0 198 parser.add_argument(
michael@0 199 "--greDir",
michael@0 200 action="store",
michael@0 201 help="The directory containing the Gecko SDK (usually where this Python script lives)",
michael@0 202 default=os.path.dirname(sys.argv[0])
michael@0 203 )
michael@0 204 parser.add_argument(
michael@0 205 "--appName",
michael@0 206 action="store",
michael@0 207 help="The name of the application to install"
michael@0 208 )
michael@0 209 parser.add_argument("--version", action="version", version="%(prog)s 1.0")
michael@0 210
michael@0 211 # The command code.
michael@0 212 cmds = parser.parse_args()
michael@0 213 try:
michael@0 214 installApp(cmds.appLocation, cmds.installDir, cmds.appName, cmds.greDir)
michael@0 215 except exn:
michael@0 216 shutil.rmtree(cmds.installDir)
michael@0 217 raise exn
michael@0 218 print cmds.appName + " application installed to " + cmds.installDir
michael@0 219
michael@0 220 if __name__ == '__main__':
michael@0 221 handleCommandLine()

mercurial