mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 352762 - Allow PFS to launch an executable file to run plugins, instead of installing an XPI. This fixes Windows Vista permissions errors in XPInstall, r=doron
This commit is contained in:
parent
77a82790dc
commit
bcbbe43a8f
@ -126,6 +126,8 @@ nsRDFItemUpdater.prototype = {
|
||||
pid: getPFSValueFromRDF("guid"),
|
||||
version: getPFSValueFromRDF("version"),
|
||||
IconUrl: getPFSValueFromRDF("IconUrl"),
|
||||
InstallerLocation: getPFSValueFromRDF("InstallerLocation"),
|
||||
InstallerHash: getPFSValueFromRDF("InstallerHash"),
|
||||
XPILocation: getPFSValueFromRDF("XPILocation"),
|
||||
XPIHash: getPFSValueFromRDF("XPIHash"),
|
||||
InstallerShowsUI: getPFSValueFromRDF("InstallerShowsUI"),
|
||||
@ -145,7 +147,7 @@ nsRDFItemUpdater.prototype = {
|
||||
onDatasourceError: function pfs_onDatasourceError (aPluginRequestItem, aError){
|
||||
this._os.notifyObservers(aPluginRequestItem, "error", aError);
|
||||
gPluginInstaller.pluginInfoReceived(null);
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
function nsPluginXMLRDFDSObserver(aUpdater, aPluginRequestItem){
|
||||
|
@ -35,33 +35,222 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
var PluginInstallService = {
|
||||
|
||||
init: function ()
|
||||
const nsIXPIProgressDialog = Components.interfaces.nsIXPIProgressDialog;
|
||||
|
||||
function getLocalizedError(key)
|
||||
{
|
||||
return document.getElementById("xpinstallStrings").getString(key);
|
||||
}
|
||||
|
||||
function binaryToHex(input)
|
||||
{
|
||||
return [('0' + input.charCodeAt(i).toString(16)).slice(-2)
|
||||
for (i in input)].join('');
|
||||
}
|
||||
|
||||
function verifyHash(aFile, aHash)
|
||||
{
|
||||
try {
|
||||
var [, method, hash] = /^([A-Za-z0-9]+):(.*)$/.exec(aHash);
|
||||
|
||||
var fis = Components.classes['@mozilla.org/network/file-input-stream;1'].
|
||||
createInstance(Components.interfaces.nsIFileInputStream);
|
||||
fis.init(aFile, -1, -1, 0);
|
||||
|
||||
var hasher = Components.classes['@mozilla.org/security/hash;1'].
|
||||
createInstance(Components.interfaces.nsICryptoHash);
|
||||
hasher.initWithString(method);
|
||||
hasher.updateFromStream(fis, -1);
|
||||
dlhash = binaryToHex(hasher.finish(false));
|
||||
return dlhash == hash;
|
||||
}
|
||||
catch (e) {
|
||||
Components.utils.reportError(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function InstallerObserver(aPlugin)
|
||||
{
|
||||
this._plugin = aPlugin;
|
||||
this._init();
|
||||
}
|
||||
|
||||
InstallerObserver.prototype = {
|
||||
_init: function()
|
||||
{
|
||||
try {
|
||||
var ios = Components.classes["@mozilla.org/network/io-service;1"].
|
||||
getService(Components.interfaces.nsIIOService);
|
||||
var uri = ios.newURI(this._plugin.InstallerLocation, null, null);
|
||||
uri.QueryInterface(Components.interfaces.nsIURL);
|
||||
|
||||
var leafName = uri.fileName;
|
||||
if (leafName.indexOf('.') == -1)
|
||||
throw "Filename needs to contain a dot for platform-native launching to work correctly.";
|
||||
|
||||
var dirs = Components.classes["@mozilla.org/file/directory_service;1"].
|
||||
getService(Components.interfaces.nsIProperties);
|
||||
|
||||
var resultFile = dirs.get("TmpD", Components.interfaces.nsIFile);
|
||||
resultFile.append(leafName);
|
||||
resultFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE,
|
||||
0x770);
|
||||
|
||||
var channel = ios.newChannelFromURI(uri);
|
||||
this._downloader =
|
||||
Components.classes["@mozilla.org/network/downloader;1"].
|
||||
createInstance(Components.interfaces.nsIDownloader);
|
||||
this._downloader.init(this, resultFile);
|
||||
channel.notificationCallbacks = this;
|
||||
|
||||
this._fireNotification(nsIXPIProgressDialog.DOWNLOAD_START, null);
|
||||
|
||||
channel.asyncOpen(this._downloader, null);
|
||||
}
|
||||
catch (e) {
|
||||
this._fireNotification(nsIXPIProgressDialog.INSTALL_DONE,
|
||||
getLocalizedError("error-228"));
|
||||
if (resultFile && resultFile.exists())
|
||||
resultfile.remove(false);
|
||||
}
|
||||
},
|
||||
|
||||
pluginPidArray: null,
|
||||
/**
|
||||
* Inform the gPluginInstaller about what's going on.
|
||||
*/
|
||||
_fireNotification: function(aStatus, aErrorMsg)
|
||||
{
|
||||
gPluginInstaller.pluginInstallationProgress(this._plugin.pid,
|
||||
aStatus, aErrorMsg);
|
||||
|
||||
startPluginInstallation: function (aPluginXPIUrlsArray,
|
||||
aPluginHashes,
|
||||
aPluginPidArray) {
|
||||
this.pluginPidArray = aPluginPidArray;
|
||||
if (aStatus == nsIXPIProgressDialog.INSTALL_DONE) {
|
||||
--PluginInstallService._installersPending;
|
||||
PluginInstallService._fireFinishedNotification();
|
||||
}
|
||||
},
|
||||
|
||||
var xpiManager = Components.classes["@mozilla.org/xpinstall/install-manager;1"]
|
||||
.createInstance(Components.interfaces.nsIXPInstallManager);
|
||||
xpiManager.initManagerWithHashes(aPluginXPIUrlsArray, aPluginHashes,
|
||||
aPluginXPIUrlsArray.length, this);
|
||||
QueryInterface: function(iid)
|
||||
{
|
||||
if (iid.equals(Components.interfaces.nsISupports) ||
|
||||
iid.equals(Components.interfaces.nsIInterfaceRequestor) ||
|
||||
iid.equals(Components.interfaces.nsIDownloadObserver) ||
|
||||
iid.equals(Components.interfaces.nsIProgressEventSink))
|
||||
return this;
|
||||
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
},
|
||||
|
||||
getInterface: function(iid)
|
||||
{
|
||||
if (iid.equals(Components.interfaces.nsIProgressEventSink))
|
||||
return this;
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
onDownloadComplete: function(downloader, request, ctxt, status, result)
|
||||
{
|
||||
if (!Components.isSuccessCode(status)) {
|
||||
// xpinstall error 228 is "Download Error"
|
||||
this._fireNotification(nsIXPIProgressDialog.INSTALL_DONE,
|
||||
getLocalizedError("error-228"));
|
||||
result.remove(false);
|
||||
return;
|
||||
}
|
||||
|
||||
this._fireNotification(nsIXPIProgressDialog.DOWNLOAD_DONE);
|
||||
|
||||
if (this._plugin.InstallerHash &&
|
||||
!verifyHash(result, this._plugin.InstallerHash)) {
|
||||
// xpinstall error 261 is "Invalid file hash..."
|
||||
this._fireNotification(nsIXPIProgressDialog.INSTALL_DONE,
|
||||
getLocalizedError("error-261"));
|
||||
result.remove(false);
|
||||
return;
|
||||
}
|
||||
|
||||
this._fireNotification(nsIXPIProgressDialog.INSTALL_START);
|
||||
|
||||
result.QueryInterface(Components.interfaces.nsILocalFile);
|
||||
try {
|
||||
result.launch();
|
||||
this._fireNotification(nsIXPIProgressDialog.INSTALL_DONE, null);
|
||||
// It would be nice to remove the tempfile, but we don't have
|
||||
// any way to know when it will stop being used :-(
|
||||
}
|
||||
catch (e) {
|
||||
Components.utils.reportError(e);
|
||||
this._fireNotification(nsIXPIProgressDialog.INSTALL_DONE,
|
||||
getLocalizedError("error-207"));
|
||||
result.remove(false);
|
||||
}
|
||||
},
|
||||
|
||||
onProgress: function(aRequest, aContext, aProgress, aProgressMax)
|
||||
{
|
||||
gPluginInstaller.pluginInstallationProgressMeter(this._plugin.pid,
|
||||
aProgress,
|
||||
aProgressMax);
|
||||
},
|
||||
|
||||
onStatus: function(aRequest, aContext, aStatus, aStatusArg)
|
||||
{
|
||||
/* pass */
|
||||
}
|
||||
};
|
||||
|
||||
var PluginInstallService = {
|
||||
|
||||
/**
|
||||
* Start installation of installers and XPI plugins.
|
||||
* @param aInstallerPlugins An array of objects which should have the
|
||||
* properties "pid", "InstallerLocation",
|
||||
* and "InstallerHash"
|
||||
* @param aXPIPlugins An array of objects which should have the
|
||||
* properties "pid", "XPILocation",
|
||||
* and "XPIHash"
|
||||
*/
|
||||
startPluginInstallation: function (aInstallerPlugins,
|
||||
aXPIPlugins)
|
||||
{
|
||||
this._installerPlugins = [new InstallerObserver(plugin)
|
||||
for each (plugin in aInstallerPlugins)];
|
||||
this._installersPending = this._installerPlugins.length;
|
||||
|
||||
this._xpiPlugins = aXPIPlugins;
|
||||
|
||||
if (this._xpiPlugins.length > 0) {
|
||||
this._xpisDone = false;
|
||||
|
||||
var xpiManager = Components.classes["@mozilla.org/xpinstall/install-manager;1"]
|
||||
.createInstance(Components.interfaces.nsIXPInstallManager);
|
||||
xpiManager.initManagerWithHashes(
|
||||
[plugin.XPILocation for each (plugin in this._xpiPlugins)],
|
||||
[plugin.XPIHash for each (plugin in this._xpiPlugins)],
|
||||
this._xpiPlugins.length, this);
|
||||
}
|
||||
else {
|
||||
this._xpisDone = true;
|
||||
}
|
||||
},
|
||||
|
||||
_fireFinishedNotification: function()
|
||||
{
|
||||
if (this._installersPending == 0 && this._xpisDone)
|
||||
gPluginInstaller.
|
||||
pluginInstallationProgress(null, nsIXPIProgressDialog.DIALOG_CLOSE,
|
||||
null);
|
||||
},
|
||||
|
||||
// XPI progress listener stuff
|
||||
onStateChange: function (aIndex, aState, aValue)
|
||||
{
|
||||
// get the pid to return to the wizard
|
||||
var pid = this.pluginPidArray[aIndex];
|
||||
var pid = this._xpiPlugins[aIndex].pid;
|
||||
var errorMsg;
|
||||
|
||||
if (aState == Components.interfaces.nsIXPIProgressDialog.INSTALL_DONE) {
|
||||
if (aState == nsIXPIProgressDialog.INSTALL_DONE) {
|
||||
if (aValue != 0) {
|
||||
var xpinstallStrings = document.getElementById("xpinstallStrings");
|
||||
try {
|
||||
@ -73,15 +262,19 @@ var PluginInstallService = {
|
||||
}
|
||||
}
|
||||
|
||||
gPluginInstaller.pluginInstallationProgress(pid, aState, errorMsg);
|
||||
|
||||
if (aState == nsIXPIProgressDialog.DIALOG_CLOSE) {
|
||||
this._xpisDone = true;
|
||||
this._fireFinishedNotification();
|
||||
}
|
||||
else {
|
||||
gPluginInstaller.pluginInstallationProgress(pid, aState, errorMsg);
|
||||
}
|
||||
},
|
||||
|
||||
onProgress: function (aIndex, aValue, aMaxValue)
|
||||
{
|
||||
// get the pid to return to the wizard
|
||||
var pid = this.pluginPidArray[aIndex];
|
||||
|
||||
var pid = this._xpiPlugins[aIndex].pid;
|
||||
gPluginInstaller.pluginInstallationProgressMeter(pid, aValue, aMaxValue);
|
||||
}
|
||||
}
|
||||
|
@ -337,30 +337,23 @@ nsPluginInstallerWizard.prototype.startPluginInstallation = function (){
|
||||
this.canAdvance(false);
|
||||
this.canRewind(false);
|
||||
|
||||
// since the user can choose what plugins to install, we need to store
|
||||
// which ones were choosen, as nsIXPInstallManager returns an index and not the
|
||||
// mimetype. So store the pids.
|
||||
|
||||
var pluginURLArray = new Array();
|
||||
var pluginHashArray = new Array();
|
||||
var pluginPidArray = new Array();
|
||||
var installerPlugins = [];
|
||||
var xpiPlugins = [];
|
||||
|
||||
for (pluginInfoItem in this.mPluginInfoArray){
|
||||
var pluginItem = this.mPluginInfoArray[pluginInfoItem];
|
||||
|
||||
// only push to the array if it has an XPILocation, else nsIXPInstallManager
|
||||
// will complain.
|
||||
if (pluginItem.toBeInstalled && pluginItem.XPILocation && pluginItem.licenseAccepted) {
|
||||
pluginURLArray.push(pluginItem.XPILocation);
|
||||
pluginHashArray.push(pluginItem.XPIHash);
|
||||
pluginPidArray.push(pluginItem.pid);
|
||||
if (pluginItem.toBeInstalled && pluginItem.licenseAccepted) {
|
||||
if (pluginItem.InstallerLocation)
|
||||
installerPlugins.push(pluginItem);
|
||||
else if (pluginItem.XPILocation)
|
||||
xpiPlugins.push(pluginItem);
|
||||
}
|
||||
}
|
||||
|
||||
if (pluginURLArray.length > 0)
|
||||
PluginInstallService.startPluginInstallation(pluginURLArray,
|
||||
pluginHashArray,
|
||||
pluginPidArray);
|
||||
if (installerPlugins.length > 0 || xpiPlugins.length > 0)
|
||||
PluginInstallService.startPluginInstallation(installerPlugins,
|
||||
xpiPlugins);
|
||||
else
|
||||
this.advancePage(null, true, false, false);
|
||||
}
|
||||
@ -622,6 +615,8 @@ function PluginInfo(aResult) {
|
||||
this.pid = aResult.pid;
|
||||
this.version = aResult.version;
|
||||
this.IconUrl = aResult.IconUrl;
|
||||
this.InstallerLocation = aResult.InstallerLocation;
|
||||
this.InstallerHash = aResult.InstallerHash;
|
||||
this.XPILocation = aResult.XPILocation;
|
||||
this.XPIHash = aResult.XPIHash;
|
||||
this.InstallerShowsUI = aResult.InstallerShowsUI;
|
||||
|
Loading…
Reference in New Issue
Block a user