Bug 774144 - Webapp uninstallation on Windows through mozapps uninstall function. r=tabraldes

This commit is contained in:
Marco Castelluccio 2014-04-13 14:18:02 -04:00
Родитель dfbb9f005d
Коммит 199f8df743
2 изменённых файлов: 120 добавлений и 50 удалений

Просмотреть файл

@ -10,6 +10,7 @@ const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");
Cu.import("resource://gre/modules/osfile.jsm");
Cu.import("resource://gre/modules/Promise.jsm");
this.EXPORTED_SYMBOLS = ["WebappOSUtils"];
@ -43,6 +44,38 @@ this.WebappOSUtils = {
computeHash(aApp.manifestURL);
},
#ifdef XP_WIN
/**
* Returns the registry key associated to the given app and a boolean that
* specifies whether we're using the old naming scheme or the new one.
*/
getAppRegKey: function(aApp) {
let regKey = Cc["@mozilla.org/windows-registry-key;1"].
createInstance(Ci.nsIWindowsRegKey);
try {
regKey.open(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" +
this.getUniqueName(aApp), Ci.nsIWindowsRegKey.ACCESS_READ);
return { value: regKey,
namingSchemeVersion: 2};
} catch (ex) {}
// Fall back to the old installation naming scheme
try {
regKey.open(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" +
aApp.origin, Ci.nsIWindowsRegKey.ACCESS_READ);
return { value: regKey,
namingSchemeVersion: 1 };
} catch (ex) {}
return null;
},
#endif
/**
* Returns the executable of the given app, identifying it by its unique name,
* which is in either the new format or the old format.
@ -53,42 +86,26 @@ this.WebappOSUtils = {
* which is only unique until we support multiple apps per origin.
*/
getLaunchTarget: function(aApp) {
let uniqueName = this.getUniqueName(aApp);
#ifdef XP_WIN
let isOldNamingScheme = false;
let appRegKey;
try {
let open = CC("@mozilla.org/windows-registry-key;1",
"nsIWindowsRegKey", "open");
appRegKey = open(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" +
uniqueName, Ci.nsIWindowsRegKey.ACCESS_READ);
} catch (ex) {
// Fall back to the old installation naming scheme
try {
appRegKey = open(Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" +
aApp.origin, Ci.nsIWindowsRegKey.ACCESS_READ);
isOldNamingScheme = true;
} catch (ex) {
return null;
}
let appRegKey = this.getAppRegKey(aApp);
if (!appRegKey) {
return null;
}
let appFilename, installLocation;
try {
appFilename = appRegKey.readStringValue("AppFilename");
installLocation = appRegKey.readStringValue("InstallLocation");
appFilename = appRegKey.value.readStringValue("AppFilename");
installLocation = appRegKey.value.readStringValue("InstallLocation");
} catch (ex) {
return null;
} finally {
appRegKey.close();
appRegKey.value.close();
}
installLocation = installLocation.substring(1, installLocation.length - 1);
if (isOldNamingScheme &&
if (appRegKey.namingSchemeVersion == 1 &&
!this.isOldInstallPathValid(aApp, installLocation)) {
return null;
}
@ -100,6 +117,8 @@ this.WebappOSUtils = {
return launchTarget;
#elifdef XP_MACOSX
let uniqueName = this.getUniqueName(aApp);
let mwaUtils = Cc["@mozilla.org/widget/mac-web-app-utils;1"]
.createInstance(Ci.nsIMacWebAppUtils);
@ -121,6 +140,8 @@ this.WebappOSUtils = {
return [ null, null ];
#elifdef XP_UNIX
let uniqueName = this.getUniqueName(aApp);
let exeFile = Services.dirsvc.get("Home", Ci.nsIFile);
exeFile.append("." + uniqueName);
exeFile.append("webapprt-stub");
@ -222,16 +243,16 @@ this.WebappOSUtils = {
let uniqueName = this.getUniqueName(aApp);
#ifdef XP_WIN
let initProcess = CC("@mozilla.org/process/util;1",
"nsIProcess", "init");
let launchTarget = this.getLaunchTarget(aApp);
if (!launchTarget) {
return false;
}
try {
let process = initProcess(launchTarget);
let process = Cc["@mozilla.org/process/util;1"].
createInstance(Ci.nsIProcess);
process.init(launchTarget);
process.runwAsync([], 0);
} catch (e) {
return false;
@ -275,27 +296,67 @@ this.WebappOSUtils = {
},
uninstall: function(aApp) {
let uniqueName = this.getUniqueName(aApp);
#ifdef XP_WIN
let appRegKey = this.getAppRegKey(aApp);
#ifdef XP_UNIX
#ifndef XP_MACOSX
if (!appRegKey) {
return Promise.reject("App registry key not found");
}
let deferred = Promise.defer();
try {
let uninstallerPath = appRegKey.value.readStringValue("UninstallString");
uninstallerPath = uninstallerPath.substring(1, uninstallerPath.length - 1);
let uninstaller = Cc["@mozilla.org/file/local;1"].
createInstance(Ci.nsIFile);
uninstaller.initWithPath(uninstallerPath);
let process = Cc["@mozilla.org/process/util;1"].
createInstance(Ci.nsIProcess);
process.init(uninstaller);
process.runwAsync(["/S"], 1, (aSubject, aTopic) => {
if (aTopic == "process-finished") {
deferred.resolve(true);
} else {
deferred.reject("Uninstaller failed with exit code: " + aSubject.exitValue);
}
});
} catch (e) {
deferred.reject(e);
} finally {
appRegKey.value.close();
}
return deferred.promise;
#elifdef XP_MACOSX
return Promise.reject("Uninstallation not yet implemented");
#elifdef XP_UNIX
let exeFile = this.getLaunchTarget(aApp);
if (!exeFile) {
return false;
return Promise.reject("App executable file not found");
}
let deferred = Promise.defer();
try {
let process = Cc["@mozilla.org/process/util;1"]
.createInstance(Ci.nsIProcess);
process.init(exeFile);
process.runAsync(["-remove"], 1);
process.runAsync(["-remove"], 1, (aSubject, aTopic) => {
if (aTopic == "process-finished") {
deferred.resolve(true);
} else {
deferred.reject("Uninstaller failed with exit code: " + aSubject.exitValue);
}
});
} catch (e) {
return false;
deferred.reject(e);
}
return true;
#endif
return deferred.promise;
#endif
},

Просмотреть файл

@ -8,10 +8,7 @@
; Set verbosity to 3 (e.g. no script) to lessen the noise in the build logs
!verbose 3
; 7-Zip provides better compression than the lzma from NSIS so we add the files
; uncompressed and let the application installer compress it.
SetDatablockOptimize on
SetCompress off
CRCCheck on
SilentInstall silent
@ -70,18 +67,16 @@ UninstPage custom un.blankPage
################################################################################
# Install Sections
# The "installer" that is generated by this file will be run during the build
# process to generate an uninstaller. We call `WriteUninstaller` during
# `onInit` so this section is empty.
# The "installer" that is generated by this file is a stub that generates the
# uninstaller at runtime in a temp directory and launches it.
# We call `WriteUninstaller` during `onInit` so this section is empty.
Section ""
SectionEnd
################################################################################
# This is where uninstallation happens
################################################################################
Function un.blankPage
MessageBox MB_OKCANCEL "$(UN_CONFIRM_UNINSTALL)" /SD IDOK IDCANCEL done
Function un.webappUninstall
; Delete the app exe to prevent launching the app while we are uninstalling.
ClearErrors
${DeleteFile} "$INSTDIR\${FileMainEXE}"
@ -92,7 +87,6 @@ Function un.blankPage
ClearErrors
${EndIf}
SetShellVarContext current ; Set SHCTX to HKCU
; Remove our entry in the "Uninstall" key
@ -105,14 +99,25 @@ Function un.blankPage
; files / directories this install is responsible for.
${un.ParseUninstallLog}
; Remove the uninstall directory that we control
RmDir /r "$INSTDIR\uninstall"
; Remove the uninstall directory that we control.
; The installer is in the uninstall directory, it generates
; the uninstaller in a temp directory and waits for its
; execution. Thus, we can't remove the uninstall directory
; now and need to wait for a restart.
; See bug 994965.
RmDir /r /REBOOTOK "$INSTDIR\uninstall"
; Remove the installation directory if it is empty
${RemoveDir} "$INSTDIR"
; Refresh shell icons to reflect the changes we've made
${un.RefreshShellIcons}
FunctionEnd
Function un.blankPage
MessageBox MB_OKCANCEL "$(UN_CONFIRM_UNINSTALL)" /SD IDOK IDCANCEL done
Call un.webappUninstall
done:
FunctionEnd
@ -144,8 +149,8 @@ Function .onInit
WriteUninstaller "$1"
${GetParameters} $2
StrCpy $2 "_?=$EXEDIR $2"
Exec '"$1" $2'
StrCpy $2 "$2 _?=$EXEDIR"
ExecWait '"$1" $2'
Quit
FunctionEnd
@ -168,4 +173,8 @@ Function un.onInit
StrCpy $AppRTTempDir "$TEMP\moz_webapprt"
RmDir /r "$AppRTTempDir"
${If} ${Silent}
Call un.webappUninstall
${EndIf}
FunctionEnd