Backed out 4 changesets (bug 747428, bug 907324, bug 899353, bug 747552) for mochitest-other assertions.

Backed out changeset ee2bf84036fb (bug 907324)
Backed out changeset 17f932a5856d (bug 899353)
Backed out changeset b277e7b08f88 (bug 747552)
Backed out changeset 6ae3b1195542 (bug 747428)
This commit is contained in:
Ryan VanderMeulen 2013-08-26 12:25:49 -04:00
Родитель c9616779fa
Коммит f0ff0e5947
10 изменённых файлов: 229 добавлений и 294 удалений

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

@ -50,13 +50,6 @@
</popupnotificationcontent>
</popupnotification>
<popupnotification id="webapps-install-progress-notification" hidden="true">
<popupnotificationcontent orient="vertical" align="start">
<separator class="thin"/>
<progressmeter id="webapps-progressmeter" mode="undetermined"/>
</popupnotificationcontent>
</popupnotification>
<popupnotification id="mixed-content-blocked-notification" hidden="true">
<popupnotificationcontent orient="vertical" align="start">
<separator/>

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

@ -407,7 +407,6 @@ webapps.install.accesskey = I
#LOCALIZATION NOTE (webapps.requestInstall) %1$S is the web app name, %2$S is the site from which the web app is installed
webapps.requestInstall = Do you want to install "%1$S" from this site (%2$S)?
webapps.install.success = Application Installed
webapps.install.inprogress = Installation in progress
# LOCALIZATION NOTE (fullscreen.entered): displayed when we enter HTML5 fullscreen mode, %S is the domain name of the focused website (e.g. mozilla.com).
fullscreen.entered=%S is now fullscreen.

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

@ -14,36 +14,18 @@ Cu.import("resource://gre/modules/Webapps.jsm");
Cu.import("resource://gre/modules/AppsUtils.jsm");
Cu.import("resource://gre/modules/WebappsInstaller.jsm");
Cu.import("resource://gre/modules/WebappOSUtils.jsm");
Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource://gre/modules/Promise.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
"@mozilla.org/childprocessmessagemanager;1",
"nsIMessageSender");
this.webappsUI = {
downloads: {},
init: function webappsUI_init() {
Services.obs.addObserver(this, "webapps-ask-install", false);
Services.obs.addObserver(this, "webapps-launch", false);
Services.obs.addObserver(this, "webapps-uninstall", false);
cpmm.addMessageListener("Webapps:OfflineCache", this);
},
uninit: function webappsUI_uninit() {
Services.obs.removeObserver(this, "webapps-ask-install");
Services.obs.removeObserver(this, "webapps-launch");
Services.obs.removeObserver(this, "webapps-uninstall");
cpmm.removeMessageListener("Webapps:OfflineCache", this);
},
receiveMessage: function(aMessage) {
let data = aMessage.data;
if (aMessage.name == "Webapps:OfflineCache" && data.installState == "installed") {
this.downloads[data.manifest].resolve();
}
},
observe: function webappsUI_observe(aSubject, aTopic, aData) {
@ -121,18 +103,7 @@ this.webappsUI = {
let mainAction = {
label: bundle.getString("webapps.install"),
accessKey: bundle.getString("webapps.install.accesskey"),
callback: () => {
let notification = chromeWin.PopupNotifications.
show(browser,
"webapps-install-progress",
bundle.getString("webapps.install.inprogress"),
"webapps-notification-icon");
let manifestURL = aData.app.manifestURL;
if (aData.app.manifest && aData.app.manifest.appcache_path) {
this.downloads[manifestURL] = Promise.defer();
}
callback: function() {
let app = WebappsInstaller.init(aData);
if (app) {
@ -142,23 +113,12 @@ this.webappsUI = {
}
DOMApplicationRegistry.confirmInstall(aData, false, localDir, null,
(aManifest) => {
Task.spawn(function() {
try {
yield WebappsInstaller.install(aData, aManifest);
if (this.downloads[manifestURL]) {
yield this.downloads[manifestURL].promise;
}
installationSuccessNotification(aData, app, bundle);
} catch (ex) {
Cu.reportError("Error installing webapp: " + ex);
// TODO: Notify user that the installation has failed
} finally {
notification.remove();
delete this.downloads[manifestURL];
}
}.bind(this));
});
function (aManifest) {
if (WebappsInstaller.install(aData, aManifest)) {
installationSuccessNotification(aData, app, chromeWin);
}
}
);
} else {
DOMApplicationRegistry.denyInstall(aData);
}
@ -185,7 +145,7 @@ this.webappsUI = {
}
}
function installationSuccessNotification(aData, app, aBundle) {
function installationSuccessNotification(aData, app, aWindow) {
let launcher = {
observe: function(aSubject, aTopic) {
if (aTopic == "alertclickcallback") {
@ -194,13 +154,19 @@ function installationSuccessNotification(aData, app, aBundle) {
}
};
try {
let notifier = Cc["@mozilla.org/alerts-service;1"].
getService(Ci.nsIAlertsService);
let bundle = aWindow.gNavigatorBundle;
notifier.showAlertNotification(app.iconURI.spec,
aBundle.getString("webapps.install.success"),
app.appNameAsFilename,
true, null, launcher);
} catch (ex) {}
if (("@mozilla.org/alerts-service;1" in Cc)) {
let notifier;
try {
notifier = Cc["@mozilla.org/alerts-service;1"].
getService(Ci.nsIAlertsService);
notifier.showAlertNotification(app.iconURI.spec,
bundle.getString("webapps.install.success"),
app.appNameAsFilename,
true, null, launcher);
} catch (ex) {}
}
}

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

@ -1184,7 +1184,6 @@ toolbar[iconsize="small"] #webrtc-status-button {
list-style-image: url(chrome://mozapps/skin/passwordmgr/key-64.png);
}
.popup-notification-icon[popupid="webapps-install-progress"],
.popup-notification-icon[popupid="webapps-install"] {
list-style-image: url(chrome://global/skin/icons/webapps-64.png);
}

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

@ -3405,7 +3405,6 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker {
list-style-image: url(chrome://mozapps/skin/passwordmgr/key-64.png);
}
.popup-notification-icon[popupid="webapps-install-progress"],
.popup-notification-icon[popupid="webapps-install"] {
list-style-image: url(chrome://global/skin/icons/webapps-64.png);
}

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

@ -2458,7 +2458,6 @@ toolbarbutton.bookmark-item[dragover="true"][open="true"] {
list-style-image: url(chrome://mozapps/skin/passwordmgr/key-64.png);
}
.popup-notification-icon[popupid="webapps-install-progress"],
.popup-notification-icon[popupid="webapps-install"] {
list-style-image: url(chrome://global/skin/icons/webapps-64.png);
}

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

@ -2,8 +2,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
const DEFAULT_ICON_URL = "chrome://global/skin/icons/webapps-64.png";
/**
* This function receives a list of icon sizes
* and URLs and returns the url string for the biggest icon.
@ -19,83 +17,95 @@ const DEFAULT_ICON_URL = "chrome://global/skin/icons/webapps-64.png";
*/
function getBiggestIconURL(aIcons) {
if (!aIcons) {
return DEFAULT_ICON_URL;
return "chrome://global/skin/icons/webapps-64.png";
}
let iconSizes = Object.keys(aIcons);
if (iconSizes.length == 0) {
return DEFAULT_ICON_URL;
return "chrome://global/skin/icons/webapps-64.png";
}
iconSizes.sort(function(a, b) a - b);
return aIcons[iconSizes.pop()];
}
// Download an icon using either a temp file or a pipe.
function downloadIcon(aIconURI) {
let deferred = Promise.defer();
/**
* This function retrieves the icon for an app as specified
* in the iconURI on the shell object.
* Upon completion it will call aShell.processIcon()
*
* @param aShell The shell that specifies the properties
* of the native app. Three properties from this
* shell will be used in this function:
* - iconURI
* - useTmpForIcon
* - processIcon()
*/
function getIconForApp(aShell, callback) {
let iconURI = aShell.iconURI;
let mimeService = Cc["@mozilla.org/mime;1"]
.getService(Ci.nsIMIMEService);
let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
let mimeType;
try {
let tIndex = aIconURI.path.indexOf(";");
if("data" == aIconURI.scheme && tIndex != -1) {
mimeType = aIconURI.path.substring(0, tIndex);
let tIndex = iconURI.path.indexOf(";");
if("data" == iconURI.scheme && tIndex != -1) {
mimeType = iconURI.path.substring(0, tIndex);
} else {
mimeType = mimeService.getTypeFromURI(aIconURI);
}
} catch(e) {
deferred.reject("Failed to determine icon MIME type: " + e);
return deferred.promise;
}
function onIconDownloaded(aStatusCode, aIcon) {
if (Components.isSuccessCode(aStatusCode)) {
deferred.resolve([ mimeType, aIcon ]);
} else {
deferred.reject("Failure downloading icon: " + aStatusCode);
mimeType = mimeService.getTypeFromURI(iconURI);
}
} catch(e) {
throw("getIconFromURI - Failed to determine MIME type");
}
try {
#ifdef XP_MACOSX
let downloadObserver = {
onDownloadComplete: function(downloader, request, cx, aStatus, file) {
onIconDownloaded(aStatus, file);
}
};
let listener;
if(aShell.useTmpForIcon) {
let downloadObserver = {
onDownloadComplete: function(downloader, request, cx, aStatus, file) {
// pass downloader just to keep reference around
onIconDownloaded(aShell, mimeType, aStatus, file, callback, downloader);
}
};
let tmpIcon = Services.dirsvc.get("TmpD", Ci.nsIFile);
tmpIcon.append("tmpicon." + mimeService.getPrimaryExtension(mimeType, ""));
tmpIcon.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, parseInt("666", 8));
let tmpIcon = Services.dirsvc.get("TmpD", Ci.nsIFile);
tmpIcon.append("tmpicon." + mimeService.getPrimaryExtension(mimeType, ""));
tmpIcon.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666);
let listener = Cc["@mozilla.org/network/downloader;1"]
.createInstance(Ci.nsIDownloader);
listener.init(downloadObserver, tmpIcon);
#else
let pipe = Cc["@mozilla.org/pipe;1"]
.createInstance(Ci.nsIPipe);
pipe.init(true, true, 0, 0xffffffff, null);
listener = Cc["@mozilla.org/network/downloader;1"]
.createInstance(Ci.nsIDownloader);
listener.init(downloadObserver, tmpIcon);
} else {
let pipe = Cc["@mozilla.org/pipe;1"]
.createInstance(Ci.nsIPipe);
pipe.init(true, true, 0, 0xffffffff, null);
let listener = Cc["@mozilla.org/network/simple-stream-listener;1"]
.createInstance(Ci.nsISimpleStreamListener);
listener.init(pipe.outputStream, {
onStartRequest: function() {},
onStopRequest: function(aRequest, aContext, aStatusCode) {
pipe.outputStream.close();
onIconDownloaded(aStatusCode, pipe.inputStream);
}
});
#endif
listener = Cc["@mozilla.org/network/simple-stream-listener;1"]
.createInstance(Ci.nsISimpleStreamListener);
listener.init(pipe.outputStream, {
onStartRequest: function() {},
onStopRequest: function(aRequest, aContext, aStatusCode) {
pipe.outputStream.close();
onIconDownloaded(aShell, mimeType, aStatusCode, pipe.inputStream, callback);
}
});
}
let channel = NetUtil.newChannel(aIconURI);
let { BadCertHandler } = Cu.import("resource://gre/modules/CertUtils.jsm", {});
let channel = NetUtil.newChannel(iconURI);
let CertUtils = { };
Cu.import("resource://gre/modules/CertUtils.jsm", CertUtils);
// Pass true to avoid optional redirect-cert-checking behavior.
channel.notificationCallbacks = new BadCertHandler(true);
channel.notificationCallbacks = new CertUtils.BadCertHandler(true);
channel.asyncOpen(listener, null);
} catch(e) {
deferred.reject("Failure initiating download of icon: " + e);
throw("getIconFromURI - Failure getting icon (" + e + ")");
}
}
function onIconDownloaded(aShell, aMimeType, aStatusCode, aIcon, aCallback) {
if (Components.isSuccessCode(aStatusCode)) {
aShell.processIcon(aMimeType, aIcon, aCallback);
} else {
aCallback.call(aShell);
}
return deferred.promise;
}

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

@ -16,7 +16,6 @@ Cu.import("resource://gre/modules/osfile.jsm");
Cu.import("resource://gre/modules/WebappOSUtils.jsm");
Cu.import("resource://gre/modules/AppsUtils.jsm");
Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource://gre/modules/Promise.jsm");
this.WebappsInstaller = {
shell: null,
@ -61,27 +60,35 @@ this.WebappsInstaller = {
*
* @param aData the data provided to the install function
* @param aManifest the manifest data provided by the web app
*
* @returns true on success, false if an error was thrown
*/
install: function(aData, aManifest) {
try {
if (Services.prefs.getBoolPref("browser.mozApps.installer.dry_run")) {
return Promise.resolve();
return true;
}
} catch (ex) {}
this.shell.init(aData, aManifest);
return this.shell.install().then(() => {
let data = {
"installDir": this.shell.installDir.path,
"app": {
"manifest": aManifest,
"origin": aData.app.origin
}
};
try {
this.shell.install();
} catch (ex) {
Cu.reportError("Error installing app: " + ex);
return false;
}
Services.obs.notifyObservers(null, "webapp-installed", JSON.stringify(data));
});
let data = {
"installDir": this.shell.installDir.path,
"app": {
"manifest": aManifest,
"origin": aData.app.origin
}
};
Services.obs.notifyObservers(null, "webapp-installed", JSON.stringify(data));
return true;
}
}
@ -115,7 +122,6 @@ NativeApp.prototype = {
categories: null,
webappJson: null,
runtimeFolder: null,
manifest: null,
/**
* This function reads and parses the data from the app
@ -126,8 +132,7 @@ NativeApp.prototype = {
*
*/
init: function(aData, aManifest) {
let manifest = this.manifest = new ManifestHelper(aManifest,
aData.app.origin);
let manifest = new ManifestHelper(aManifest, aData.app.origin);
let origin = Services.io.newURI(aData.app.origin, null, null);
@ -146,16 +151,10 @@ NativeApp.prototype = {
catch (ex) {}
}
if (manifest.developer) {
if (manifest.developer.name) {
let devName = sanitize(manifest.developer.name.substr(0, 128));
if (devName) {
this.developerName = devName;
}
}
if (manifest.developer.url) {
this.developerUrl = manifest.developer.url;
if (manifest.developer && manifest.developer.name) {
let devName = sanitize(manifest.developer.name.substr(0, 128));
if (devName) {
this.developerName = devName;
}
}
@ -185,30 +184,7 @@ NativeApp.prototype = {
};
this.runtimeFolder = Services.dirsvc.get("GreD", Ci.nsIFile);
},
/**
* This function retrieves the icon for an app.
* If the retrieving fails, it uses the default chrome icon.
*/
getIcon: function() {
try {
let [ mimeType, icon ] = yield downloadIcon(this.iconURI);
yield this.processIcon(mimeType, icon);
}
catch(e) {
Cu.reportError("Failure retrieving icon: " + e);
let iconURI = Services.io.newURI(DEFAULT_ICON_URL, null, null);
let [ mimeType, icon ] = yield downloadIcon(iconURI);
yield this.processIcon(mimeType, icon);
// Set the iconURI property so that the user notification will have the
// correct icon.
this.iconURI = iconURI;
}
},
}
};
#ifdef XP_WIN
@ -242,35 +218,28 @@ NativeApp.prototype = {
*/
function WinNativeApp(aData) {
NativeApp.call(this, aData);
if (aData.isPackage) {
this.size = aData.app.updateManifest.size / 1024;
}
this._init();
}
WinNativeApp.prototype = {
__proto__: NativeApp.prototype,
size: null,
/**
* Install the app in the system
*
*/
install: function() {
return Task.spawn(function() {
try {
this._copyPrebuiltFiles();
this._createShortcutFiles();
this._createConfigFiles();
this._writeSystemKeys();
yield this.getIcon();
} catch (ex) {
this._removeInstallation(false);
throw(ex);
}
}.bind(this));
try {
this._copyPrebuiltFiles();
this._createShortcutFiles();
this._createConfigFiles();
this._writeSystemKeys();
} catch (ex) {
this._removeInstallation(false);
throw(ex);
}
getIconForApp(this, function() {});
},
/**
@ -483,28 +452,6 @@ WinNativeApp.prototype = {
subKey.writeStringValue("DisplayIcon", this.iconFile.path);
}
let date = new Date();
let year = date.getYear().toString();
let month = date.getMonth();
if (month < 10) {
month = "0" + month;
}
let day = date.getDate();
if (day < 10) {
day = "0" + day;
}
subKey.writeStringValue("InstallDate", year + month + day);
if (this.manifest.version) {
subKey.writeStringValue("DisplayVersion", this.manifest.version);
}
if (this.developerName) {
subKey.writeStringValue("Publisher", this.developerName);
}
subKey.writeStringValue("URLInfoAbout", this.developerUrl);
if (this.size) {
subKey.writeIntValue("EstimatedSize", this.size);
}
subKey.writeIntValue("NoModify", 1);
subKey.writeIntValue("NoRepair", 1);
} catch(ex) {
@ -543,6 +490,14 @@ WinNativeApp.prototype = {
shortcut.remove(false);
},
/**
* 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: false,
/**
* Process the icon from the imageStream as retrieved from
* the URL by getIconForApp(). This will save the icon to the
@ -550,31 +505,28 @@ WinNativeApp.prototype = {
*
* @param aMimeType ahe icon mimetype
* @param aImageStream the stream for the image data
* @param aCallback a callback function to be called
* after the process finishes
*/
processIcon: function(aMimeType, aImageStream) {
let deferred = Promise.defer();
processIcon: function(aMimeType, aImageStream, aCallback) {
let iconStream;
try {
let imgTools = Cc["@mozilla.org/image/tools;1"]
.createInstance(Ci.imgITools);
let imgContainer = { value: null };
let imgTools = Cc["@mozilla.org/image/tools;1"]
.createInstance(Ci.imgITools);
let imgContainer = imgTools.decodeImage(aImageStream, aMimeType);
let iconStream = imgTools.encodeImage(imgContainer,
"image/vnd.microsoft.icon",
"format=bmp;bpp=32");
if (!this.iconFile.parent.exists()) {
this.iconFile.parent.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("0755", 8));
imgTools.decodeImageData(aImageStream, aMimeType, imgContainer);
iconStream = imgTools.encodeImage(imgContainer.value,
"image/vnd.microsoft.icon",
"format=bmp;bpp=32");
} catch (e) {
throw("processIcon - Failure converting icon (" + e + ")");
}
let outputStream = FileUtils.openSafeFileOutputStream(this.iconFile);
NetUtil.asyncCopy(iconStream, outputStream, function(aResult) {
if (Components.isSuccessCode(aResult)) {
deferred.resolve();
} else {
deferred.reject("Failure copying icon: " + aResult);
}
});
return deferred.promise;
if (!this.iconFile.parent.exists())
this.iconFile.parent.create(Ci.nsIFile.DIRECTORY_TYPE, 0755);
let outputStream = FileUtils.openSafeFileOutputStream(this.iconFile);
NetUtil.asyncCopy(iconStream, outputStream);
}
}
@ -625,17 +577,15 @@ MacNativeApp.prototype = {
},
install: function() {
return Task.spawn(function() {
try {
this._copyPrebuiltFiles();
this._createConfigFiles();
yield this.getIcon();
this._moveToApplicationsFolder();
} catch (ex) {
this._removeInstallation(false);
throw(ex);
}
}.bind(this));
try {
this._copyPrebuiltFiles();
this._createConfigFiles();
} catch (ex) {
this._removeInstallation(false);
throw(ex);
}
getIconForApp(this, this._moveToApplicationsFolder);
},
_removeInstallation: function(keepProfile) {
@ -736,11 +686,19 @@ MacNativeApp.prototype = {
this.appNameAsFilename,
".app");
if (!destinationName) {
throw("No available filename");
return false;
}
this.installDir.moveTo(appDir, destinationName);
},
/**
* 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,
/**
* Process the icon from the imageStream as retrieved from
* the URL by getIconForApp(). This will bundle the icon to the
@ -748,33 +706,29 @@ MacNativeApp.prototype = {
*
* @param aMimeType the icon mimetype
* @param aImageStream the stream for the image data
* @param aCallback a callback function to be called
* after the process finishes
*/
processIcon: function(aMimeType, aIcon) {
let deferred = Promise.defer();
processIcon: function(aMimeType, aIcon, aCallback) {
try {
let process = Cc["@mozilla.org/process/util;1"]
.createInstance(Ci.nsIProcess);
let sipsFile = Cc["@mozilla.org/file/local;1"]
.createInstance(Ci.nsILocalFile);
sipsFile.initWithPath("/usr/bin/sips");
function conversionDone(aSubject, aTopic) {
if (aTopic == "process-finished") {
deferred.resolve();
} else {
deferred.reject("Failure converting icon.");
}
process.init(sipsFile);
process.run(true, ["-s",
"format", "icns",
aIcon.path,
"--out", this.iconFile.path,
"-z", "128", "128"],
9);
} catch(e) {
throw(e);
} finally {
aCallback.call(this);
}
let process = Cc["@mozilla.org/process/util;1"].
createInstance(Ci.nsIProcess);
let sipsFile = Cc["@mozilla.org/file/local;1"].
createInstance(Ci.nsILocalFile);
sipsFile.initWithPath("/usr/bin/sips");
process.init(sipsFile);
process.runAsync(["-s",
"format", "icns",
aIcon.path,
"--out", this.iconFile.path,
"-z", "128", "128"],
9, conversionDone);
return deferred.promise;
}
}
@ -832,16 +786,15 @@ LinuxNativeApp.prototype = {
},
install: function() {
return Task.spawn(function() {
try {
this._copyPrebuiltFiles();
this._createConfigFiles();
yield this.getIcon();
} catch (ex) {
this._removeInstallation(false);
throw(ex);
}
}.bind(this));
try {
this._copyPrebuiltFiles();
this._createConfigFiles();
} catch (ex) {
this._removeInstallation(false);
throw(ex);
}
getIconForApp(this, function() {});
},
_removeInstallation: function(keepProfile) {
@ -960,32 +913,38 @@ LinuxNativeApp.prototype = {
writer.writeFile();
},
/**
* 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: false,
/**
* Process the icon from the imageStream as retrieved from
* the URL by getIconForApp().
*
* @param aMimeType ahe icon mimetype
* @param aImageStream the stream for the image data
* @param aCallback a callback function to be called
* after the process finishes
*/
processIcon: function(aMimeType, aImageStream) {
let deferred = Promise.defer();
processIcon: function(aMimeType, aImageStream, aCallback) {
let iconStream;
try {
let imgTools = Cc["@mozilla.org/image/tools;1"]
.createInstance(Ci.imgITools);
let imgContainer = { value: null };
let imgTools = Cc["@mozilla.org/image/tools;1"]
.createInstance(Ci.imgITools);
let imgContainer = imgTools.decodeImage(aImageStream, aMimeType);
let iconStream = imgTools.encodeImage(imgContainer, "image/png");
imgTools.decodeImageData(aImageStream, aMimeType, imgContainer);
iconStream = imgTools.encodeImage(imgContainer.value, "image/png");
} catch (e) {
throw("processIcon - Failure converting icon (" + e + ")");
}
let outputStream = FileUtils.openSafeFileOutputStream(this.iconFile);
NetUtil.asyncCopy(iconStream, outputStream, function(aResult) {
if (Components.isSuccessCode(aResult)) {
deferred.resolve();
} else {
deferred.reject("Failure copying icon: " + aResult);
}
});
return deferred.promise;
NetUtil.asyncCopy(iconStream, outputStream);
}
}

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

@ -216,5 +216,15 @@ nsContextMenu.prototype = {
this.hasPageMenu = PageMenu.maybeBuildAndAttachMenu(document.popupNode,
aXULMenu);
this.shouldDisplay = this.hasPageMenu;
this.showItem("page-menu-separator", this.hasPageMenu);
},
showItem: function(aItemOrID, aShow) {
let item = aItemOrID.constructor == String ?
document.getElementById(aItemOrID) : aItemOrID;
if (item) {
item.hidden = !aShow;
}
}
};

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

@ -157,6 +157,7 @@
<browser type="content-primary" id="content" flex="1" context="contentAreaContextMenu" />
<popupset>
<menuseparator id="page-menu-separator"/>
<menupopup id="contentAreaContextMenu" pagemenu="start"
onpopupshowing="return showContextMenu(event, this)"
onpopuphiding="hideContextMenu(event, this)">