Bug 764172. Preserve profile when reinstalling webapp over existing installation. r=felipe

This commit is contained in:
Marco Castelluccio 2012-06-27 17:14:55 -07:00
parent ade1e1011b
commit 767bc16ce5

View File

@ -166,7 +166,7 @@ WinNativeApp.prototype = {
*/
install: function() {
// Remove previously installed app (for update purposes)
this._removeInstallation();
this._removeInstallation(true);
try {
this._createDirectoryStructure();
@ -176,7 +176,7 @@ WinNativeApp.prototype = {
this._writeSystemKeys();
this._createAppProfile();
} catch (ex) {
this._removeInstallation();
this._removeInstallation(false);
throw(ex);
}
@ -208,6 +208,15 @@ WinNativeApp.prototype = {
}
this.installDir.append(installDirLeaf);
this.webapprt = this.installDir.clone();
this.webapprt.append(this.appNameAsFilename + ".exe");
this.configJson = this.installDir.clone();
this.configJson.append("webapp.json");
this.webappINI = this.installDir.clone();
this.webappINI.append("webapp.ini");
this.uninstallDir = this.installDir.clone();
this.uninstallDir.append("uninstall");
@ -220,14 +229,6 @@ WinNativeApp.prototype = {
this.iconFile.append("default");
this.iconFile.append("default.ico");
this.desktopShortcut = Services.dirsvc.get("Desk", Ci.nsILocalFile);
this.desktopShortcut.append(this.appNameAsFilename + ".lnk");
this.desktopShortcut.followLinks = false;
this.startMenuShortcut = Services.dirsvc.get("Progs", Ci.nsILocalFile);
this.startMenuShortcut.append(this.appNameAsFilename + ".lnk");
this.startMenuShortcut.followLinks = false;
this.uninstallSubkeyStr = this.launchURI.scheme + "://" +
this.launchURI.hostPort;
},
@ -235,7 +236,7 @@ WinNativeApp.prototype = {
/**
* Remove the current installation
*/
_removeInstallation : function() {
_removeInstallation : function(keepProfile) {
let uninstallKey;
try {
uninstallKey = Cc["@mozilla.org/windows-registry-key;1"]
@ -253,35 +254,33 @@ WinNativeApp.prototype = {
uninstallKey.close();
}
try {
if(this.installDir.exists()) {
let dir = this.installDir.QueryInterface(Ci.nsILocalFile);
// We need to set followLinks to false so that the shortcut
// files can be removed even after the .exe it was pointing
// to was removed.
dir.followLinks = false;
dir.remove(true);
}
} catch(ex) {
let desktopShortcut = Services.dirsvc.get("Desk", Ci.nsILocalFile);
desktopShortcut.append(this.appNameAsFilename + ".lnk");
let startMenuShortcut = Services.dirsvc.get("Progs", Ci.nsILocalFile);
startMenuShortcut.append(this.appNameAsFilename + ".lnk");
let filesToRemove = [desktopShortcut, startMenuShortcut];
if (keepProfile) {
filesToRemove.push(this.iconFile);
filesToRemove.push(this.webapprt);
filesToRemove.push(this.configJson);
filesToRemove.push(this.webappINI);
filesToRemove.push(this.uninstallDir);
} else {
filesToRemove.push(this.installDir);
}
try {
if(this.desktopShortcut && this.desktopShortcut.exists()) {
this.desktopShortcut.remove(false);
}
if(this.startMenuShortcut && this.startMenuShortcut.exists()) {
this.startMenuShortcut.remove(false);
}
} catch(ex) {
}
removeFiles(filesToRemove);
},
/**
* Creates the main directory structure.
*/
_createDirectoryStructure: function() {
this.installDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
if (!this.installDir.exists())
this.installDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
this.uninstallDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
},
@ -295,17 +294,19 @@ WinNativeApp.prototype = {
let profSvc = Cc["@mozilla.org/toolkit/profile-service;1"]
.getService(Ci.nsIToolkitProfileService);
this.appProfile = profSvc.createDefaultProfileForApp(this.installDir.leafName,
null, null);
try {
this.appProfile = profSvc.createDefaultProfileForApp(this.installDir.leafName,
null, null);
} catch (ex if ex.result == Cr.NS_ERROR_ALREADY_INITIALIZED) {}
},
/**
* Copy the pre-built files into their destination folders.
*/
_copyPrebuiltFiles: function() {
let webapprt = this.runtimeFolder.clone();
webapprt.append("webapprt-stub.exe");
webapprt.copyTo(this.installDir, this.appNameAsFilename + ".exe");
let webapprtPre = this.runtimeFolder.clone();
webapprtPre.append("webapprt-stub.exe");
webapprtPre.copyTo(this.installDir, this.webapprt.leafName);
let uninstaller = this.runtimeFolder.clone();
uninstaller.append("webapp-uninstaller.exe");
@ -317,18 +318,13 @@ WinNativeApp.prototype = {
*/
_createConfigFiles: function() {
// ${InstallDir}/webapp.json
let configJson = this.installDir.clone();
configJson.append("webapp.json");
writeToFile(configJson, JSON.stringify(this.webappJson), function() {});
// ${InstallDir}/webapp.ini
let webappINI = this.installDir.clone().QueryInterface(Ci.nsILocalFile);
webappINI.append("webapp.ini");
writeToFile(this.configJson, JSON.stringify(this.webappJson), function() {});
let factory = Cc["@mozilla.org/xpcom/ini-processor-factory;1"]
.getService(Ci.nsIINIParserFactory);
let writer = factory.createINIParser(webappINI).QueryInterface(Ci.nsIINIParserWriter);
// ${InstallDir}/webapp.ini
let writer = factory.createINIParser(this.webappINI).QueryInterface(Ci.nsIINIParserWriter);
writer.setString("Webapp", "Name", this.appName);
writer.setString("Webapp", "Profile", this.installDir.leafName);
writer.setString("Webapp", "Executable", this.appNameAsFilename);
@ -345,9 +341,6 @@ WinNativeApp.prototype = {
writer.setString("TASKBAR", "Migrated", "true");
writer.writeFile(null, Ci.nsIINIParserWriter.WRITE_UTF16);
writer = null;
factory = null;
// ${UninstallDir}/uninstall.log
let uninstallContent =
"File: \\webapp.ini\r\n" +
@ -407,7 +400,7 @@ WinNativeApp.prototype = {
shortcut.append(this.appNameAsFilename + ".lnk");
let target = this.installDir.clone();
target.append(this.appNameAsFilename + ".exe");
target.append(this.webapprt.leafName);
/* function nsILocalFileWin.setShortcut(targetFile, workingDir, args,
description, iconFile, iconIndex) */
@ -458,7 +451,8 @@ WinNativeApp.prototype = {
throw("processIcon - Failure converting icon (" + e + ")");
}
this.iconFile.parent.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
if (!this.iconFile.parent.exists())
this.iconFile.parent.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
let outputStream = FileUtils.openSafeFileOutputStream(this.iconFile);
NetUtil.asyncCopy(iconStream, outputStream);
}
@ -524,24 +518,13 @@ MacNativeApp.prototype = {
},
_removeInstallation: function(keepProfile) {
try {
if(this.installDir.exists()) {
this.installDir.followLinks = false;
this.installDir.remove(true);
}
} catch(ex) {
let filesToRemove = [this.installDir];
if (!keepProfile) {
filesToRemove.push(this.appProfileDir);
}
if (keepProfile)
return;
try {
if(this.appProfileDir.exists()) {
this.appProfileDir.followLinks = false;
this.appProfileDir.remove(true);
}
} catch(ex) {
}
removeFiles(filesToRemove);
},
_createDirectoryStructure: function() {
@ -560,8 +543,10 @@ MacNativeApp.prototype = {
let profSvc = Cc["@mozilla.org/toolkit/profile-service;1"]
.getService(Ci.nsIToolkitProfileService);
this.appProfile = profSvc.createDefaultProfileForApp(this.appProfileDir.leafName,
null, null);
try {
this.appProfile = profSvc.createDefaultProfileForApp(this.appProfileDir.leafName,
null, null);
} catch (ex if ex.result == Cr.NS_ERROR_ALREADY_INITIALIZED) {}
},
_copyPrebuiltFiles: function() {
@ -701,6 +686,12 @@ LinuxNativeApp.prototype = {
this.webapprt = this.installDir.clone();
this.webapprt.append("webapprt-stub");
this.configJson = this.installDir.clone();
this.configJson.append("webapp.json");
this.webappINI = this.installDir.clone();
this.webappINI.append("webapp.ini");
let env = Cc["@mozilla.org/process/environment;1"]
.getService(Ci.nsIEnvironment);
let xdg_data_home_env = env.get("XDG_DATA_HOME");
@ -720,7 +711,7 @@ LinuxNativeApp.prototype = {
},
install: function() {
this._removeInstallation();
this._removeInstallation(true);
try {
this._createDirectoryStructure();
@ -728,26 +719,31 @@ LinuxNativeApp.prototype = {
this._createConfigFiles();
this._createAppProfile();
} catch (ex) {
this._removeInstallation();
this._removeInstallation(false);
throw(ex);
}
getIconForApp(this, function() {});
},
_removeInstallation: function() {
try {
if (this.installDir.exists())
this.installDir.remove(true);
_removeInstallation: function(keepProfile) {
let filesToRemove = [this.desktopINI];
if (this.desktopINI.exists())
this.desktopINI.remove(false);
} catch(ex) {
if (keepProfile) {
filesToRemove.push(this.iconFile);
filesToRemove.push(this.webapprt);
filesToRemove.push(this.configJson);
filesToRemove.push(this.webappINI);
} else {
filesToRemove.push(this.installDir);
}
removeFiles(filesToRemove);
},
_createDirectoryStructure: function() {
this.installDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
if (!this.installDir.exists())
this.installDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
},
_copyPrebuiltFiles: function() {
@ -763,24 +759,21 @@ LinuxNativeApp.prototype = {
let profSvc = Cc["@mozilla.org/toolkit/profile-service;1"]
.getService(Ci.nsIToolkitProfileService);
return profSvc.createDefaultProfileForApp(this.installDir.leafName,
null, null);
try {
this.appProfile = profSvc.createDefaultProfileForApp(this.installDir.leafName,
null, null);
} catch (ex if ex.result == Cr.NS_ERROR_ALREADY_INITIALIZED) {}
},
_createConfigFiles: function() {
// ${InstallDir}/webapp.json
let configJson = this.installDir.clone();
configJson.append("webapp.json");
writeToFile(configJson, JSON.stringify(this.webappJson), function() {});
// ${InstallDir}/webapp.ini
let webappINI = this.installDir.clone();
webappINI.append("webapp.ini");
writeToFile(this.configJson, JSON.stringify(this.webappJson), function() {});
let factory = Cc["@mozilla.org/xpcom/ini-processor-factory;1"]
.getService(Ci.nsIINIParserFactory);
let writer = factory.createINIParser(webappINI).QueryInterface(Ci.nsIINIParserWriter);
// ${InstallDir}/webapp.ini
let writer = factory.createINIParser(this.webappINI).QueryInterface(Ci.nsIINIParserWriter);
writer.setString("Webapp", "Name", this.appName);
writer.setString("Webapp", "Profile", this.uniqueName);
writer.setString("WebappRT", "InstallDir", this.runtimeFolder.path);
@ -917,6 +910,22 @@ function getAvailableFile(aFolder, aName, aExtension) {
return null;
}
/**
* Attempts to remove files or directories.
*
* @param aFiles An array with nsIFile objects to be removed
*/
function removeFiles(aFiles) {
for (let file of aFiles) {
try {
if (file.exists()) {
file.followLinks = false;
file.remove(true);
}
} catch(ex) {}
}
}
function escapeXML(aStr) {
return aStr.toString()
.replace(/&/g, "&")