author | Felipe Gomes <felipc@gmail.com> |
Thu, 26 Apr 2012 07:37:34 -0700 | |
changeset 92487 | 8180e2442cd20eadbb11edfba07936b448fe0b24 |
parent 92486 | 2b118a11328b3ca67541660f4c6b612c161c8c34 |
child 92488 | b952bb042f129b3ac3083209ecc447b080c3ed6d |
push id | 22535 |
push user | felipc@gmail.com |
push date | Thu, 26 Apr 2012 14:43:16 +0000 |
treeherder | mozilla-central@b952bb042f12 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mstange |
bugs | 748199 |
milestone | 15.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/browser/modules/WebappsInstaller.jsm +++ b/browser/modules/WebappsInstaller.jsm @@ -462,18 +462,19 @@ MacNativeApp.prototype = { // host of the app origin + ";" + // protocol + ";" + // port (-1 for default port) this.appProfileDir = this.appSupportDir.clone(); this.appProfileDir.append(this.launchURI.host + ";" + this.launchURI.scheme + ";" + this.launchURI.port); - this.installDir = Services.dirsvc.get("LocApp", Ci.nsILocalFile); + this.installDir = Services.dirsvc.get("TmpD", Ci.nsILocalFile); this.installDir.append(this.appNameAsFilename + ".app"); + this.installDir.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0755); this.contentsDir = this.installDir.clone(); this.contentsDir.append("Contents"); this.macOSDir = this.contentsDir.clone(); this.macOSDir.append("MacOS"); this.resourcesDir = this.contentsDir.clone(); @@ -491,17 +492,17 @@ MacNativeApp.prototype = { this._createDirectoryStructure(); this._copyPrebuiltFiles(); this._createConfigFiles(); } catch (ex) { this._removeInstallation(false); throw(ex); } - getIconForApp(this, this._createPListFile); + getIconForApp(this, this._moveToApplicationsFolder); }, _removeInstallation: function(keepProfile) { try { if(this.installDir.exists()) { this.installDir.followLinks = false; this.installDir.remove(true); } @@ -519,17 +520,16 @@ MacNativeApp.prototype = { } catch(ex) { } }, _createDirectoryStructure: function() { if (!this.appProfileDir.exists()) this.appProfileDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755); - this.installDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755); this.contentsDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755); this.macOSDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755); this.resourcesDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755); }, _copyPrebuiltFiles: function() { let webapprt = this.processFolder.clone(); webapprt.append("webapprt-stub"); @@ -557,19 +557,17 @@ MacNativeApp.prototype = { let factory = Cc["@mozilla.org/xpcom/ini-processor-factory;1"] .getService(Ci.nsIINIParserFactory); let writer = factory.createINIParser(applicationINI).QueryInterface(Ci.nsIINIParserWriter); writer.setString("Webapp", "Name", this.appName); writer.setString("Webapp", "Profile", this.appProfileDir.leafName); writer.writeFile(); - }, - _createPListFile: function() { // ${InstallDir}/Contents/Info.plist let infoPListContent = '<?xml version="1.0" encoding="UTF-8"?>\n\ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n\ <plist version="1.0">\n\ <dict>\n\ <key>CFBundleDevelopmentRegion</key>\n\ <string>English</string>\n\ <key>CFBundleDisplayName</key>\n\ @@ -597,16 +595,27 @@ MacNativeApp.prototype = { </dict>\n\ </plist>'; let infoPListFile = this.contentsDir.clone(); infoPListFile.append("Info.plist"); writeToFile(infoPListFile, infoPListContent, function() {}); }, + _moveToApplicationsFolder: function() { + let appDir = Services.dirsvc.get("LocApp", Ci.nsILocalFile); + let destination = getAvailableFile(appDir, + this.appNameAsFilename, + ".app"); + if (!destination) { + return false; + } + this.installDir.moveTo(destination.parent, destination.leafName); + }, + /** * This variable specifies if the icon retrieval process should * use a temporary file in the system or a binary stream. This * is accessed by a common function in WebappsIconHelpers.js and * is different for each platform. */ useTmpForIcon: true, @@ -681,16 +690,57 @@ function stripStringForFilename(aPossibl let stripFrontRE = new RegExp("^\\W*","gi"); let stripBackRE = new RegExp("\\W*$","gi"); let stripped = aPossiblyBadFilenameString.replace(stripFrontRE, ""); stripped = stripped.replace(stripBackRE, ""); return stripped; } +/** + * Finds a unique name available in a folder (i.e., non-existent file) + * + * @param aFolder nsIFile that represents the directory where we want to write + * @param aName string with the filename (minus the extension) desired + * @param aExtension string with the file extension, including the dot + + * @return nsILocalFile or null if folder is unwritable or unique name + * was not available + */ +function getAvailableFile(aFolder, aName, aExtension) { + let folder = aFolder.QueryInterface(Ci.nsILocalFile); + folder.followLinks = false; + if (!folder.isDirectory() || !folder.isWritable()) { + return null; + } + + let file = folder.clone(); + file.append(aName + aExtension); + + if (!file.exists()) { + return file; + } + + for (let i = 2; i < 10; i++) { + file.leafName = aName + " (" + i + ")" + aExtension; + if (!file.exists()) { + return file; + } + } + + for (let i = 10; i < 100; i++) { + file.leafName = aName + "-" + i + aExtension; + if (!file.exists()) { + return file; + } + } + + return null; +} + function escapeXML(aStr) { return aStr.toString() .replace(/&/g, "&") .replace(/"/g, """) .replace(/'/g, "'") .replace(/</g, "<") .replace(/>/g, ">"); }