[PALEMOON] Bug 723951 - Popup notification does not continue when the tab move to other window

Issue #121
This commit is contained in:
janekptacijarabaci 2018-04-26 23:12:13 +02:00 • committed by Roy Tam
commit 690b0039c9
2 changed files with 136 additions and 56 deletions

View file

@ -12,6 +12,7 @@ const NOTIFICATION_EVENT_DISMISSED = "dismissed";
const NOTIFICATION_EVENT_REMOVED = "removed"; const NOTIFICATION_EVENT_REMOVED = "removed";
const NOTIFICATION_EVENT_SHOWING = "showing"; const NOTIFICATION_EVENT_SHOWING = "showing";
const NOTIFICATION_EVENT_SHOWN = "shown"; const NOTIFICATION_EVENT_SHOWN = "shown";
const NOTIFICATION_EVENT_SWAPPING = "swapping";
const ICON_SELECTOR = ".notification-anchor-icon"; const ICON_SELECTOR = ".notification-anchor-icon";
const ICON_ATTRIBUTE_SHOWING = "showing"; const ICON_ATTRIBUTE_SHOWING = "showing";
@ -237,9 +238,23 @@ PopupNotifications.prototype = {
* tabs) * tabs)
* "removed": notification has been removed (due to * "removed": notification has been removed (due to
* location change or user action) * location change or user action)
* "showing": notification is about to be shown
* (this can be fired multiple times as
* notifications are dismissed and re-shown)
* "shown": notification has been shown (this can be fired * "shown": notification has been shown (this can be fired
* multiple times as notifications are dismissed * multiple times as notifications are dismissed
* and re-shown) * and re-shown)
* "swapping": the docshell of the browser that created
* the notification is about to be swapped to
* another browser. A second parameter contains
* the browser that is receiving the docshell,
* so that the event callback can transfer stuff
* specific to this notification.
* If the callback returns true, the notification
* will be moved to the new browser.
* If the callback isn't implemented, returns false,
* or doesn't return any value, the notification
* will be removed.
* neverShow: Indicate that no popup should be shown for this * neverShow: Indicate that no popup should be shown for this
* notification. Useful for just showing the anchor icon. * notification. Useful for just showing the anchor icon.
* removeOnDismissal: * removeOnDismissal:
@ -829,13 +844,60 @@ PopupNotifications.prototype = {
this._update(notifications, anchor); this._update(notifications, anchor);
}, },
_fireCallback: function PopupNotifications_fireCallback(n, event) { _swapBrowserNotifications: function PopupNotifications_swapBrowserNoficications(ourBrowser, otherBrowser) {
// When swaping browser docshells (e.g. dragging tab to new window) we need
// to update our notification map.
let ourNotifications = this._getNotificationsForBrowser(ourBrowser);
let other = otherBrowser.ownerDocument.defaultView.PopupNotifications;
if (!other) {
if (ourNotifications.length > 0)
Cu.reportError("unable to swap notifications: otherBrowser doesn't support notifications");
return;
}
let otherNotifications = other._getNotificationsForBrowser(otherBrowser);
if (ourNotifications.length < 1 && otherNotifications.length < 1) {
// No notification to swap.
return;
}
otherNotifications = otherNotifications.filter(n => {
if (this._fireCallback(n, NOTIFICATION_EVENT_SWAPPING, ourBrowser)) {
n.browser = ourBrowser;
n.owner = this;
return true;
}
other._fireCallback(n, NOTIFICATION_EVENT_REMOVED);
return false;
});
ourNotifications = ourNotifications.filter(n => {
if (this._fireCallback(n, NOTIFICATION_EVENT_SWAPPING, otherBrowser)) {
n.browser = otherBrowser;
n.owner = other;
return true;
}
this._fireCallback(n, NOTIFICATION_EVENT_REMOVED);
return false;
});
this._setNotificationsForBrowser(otherBrowser, ourNotifications);
other._setNotificationsForBrowser(ourBrowser, otherNotifications);
if (otherNotifications.length > 0)
this._update(otherNotifications, otherNotifications[0].anchorElement);
if (ourNotifications.length > 0)
other._update(ourNotifications, ourNotifications[0].anchorElement);
},
_fireCallback: function PopupNotifications_fireCallback(n, event, ...args) {
try { try {
if (n.options.eventCallback) if (n.options.eventCallback)
n.options.eventCallback.call(n, event); return n.options.eventCallback.call(n, event, ...args);
} catch (error) { } catch (error) {
Cu.reportError(error); Cu.reportError(error);
} }
return undefined;
}, },
_onPopupHidden: function PopupNotifications_onPopupHidden(event) { _onPopupHidden: function PopupNotifications_onPopupHidden(event) {

View file

@ -130,6 +130,34 @@ function prompt(aWindowID, aCallID, aAudioRequested, aVideoRequested, aDevices)
let message = stringBundle.getFormattedString("getUserMedia.share" + requestType + ".message", let message = stringBundle.getFormattedString("getUserMedia.share" + requestType + ".message",
[ host ]); [ host ]);
let mainAction = {
label: PluralForm.get(requestType == "CameraAndMicrophone" ? 2 : 1,
stringBundle.getString("getUserMedia.shareSelectedDevices.label")),
accessKey: stringBundle.getString("getUserMedia.shareSelectedDevices.accesskey"),
// The real callback will be set during the "showing" event. The
// empty function here is so that PopupNotifications.show doesn't
// reject the action.
callback: function() {}
};
let secondaryActions = [{
label: stringBundle.getString("getUserMedia.denyRequest.label"),
accessKey: stringBundle.getString("getUserMedia.denyRequest.accesskey"),
callback: function () {
denyRequest(aCallID);
}
}];
let options = {
eventCallback: function(aTopic, aNewBrowser) {
if (aTopic == "swapping")
return true;
if (aTopic != "showing")
return false;
let chromeDoc = this.browser.ownerDocument;
function listDevices(menupopup, devices) { function listDevices(menupopup, devices) {
while (menupopup.lastChild) while (menupopup.lastChild)
menupopup.removeChild(menupopup.lastChild); menupopup.removeChild(menupopup.lastChild);
@ -157,15 +185,12 @@ function prompt(aWindowID, aCallID, aAudioRequested, aVideoRequested, aDevices)
listDevices(camMenupopup, videoDevices); listDevices(camMenupopup, videoDevices);
listDevices(micMenupopup, audioDevices); listDevices(micMenupopup, audioDevices);
if (requestType == "CameraAndMicrophone") { if (requestType == "CameraAndMicrophone") {
let stringBundle = chromeDoc.defaultView.gNavigatorBundle;
addDeviceToList(camMenupopup, stringBundle.getString("getUserMedia.noVideo.label"), "-1"); addDeviceToList(camMenupopup, stringBundle.getString("getUserMedia.noVideo.label"), "-1");
addDeviceToList(micMenupopup, stringBundle.getString("getUserMedia.noAudio.label"), "-1"); addDeviceToList(micMenupopup, stringBundle.getString("getUserMedia.noAudio.label"), "-1");
} }
let mainAction = { this.mainAction.callback = function() {
label: PluralForm.get(requestType == "CameraAndMicrophone" ? 2 : 1,
stringBundle.getString("getUserMedia.shareSelectedDevices.label")),
accessKey: stringBundle.getString("getUserMedia.shareSelectedDevices.accesskey"),
callback: function () {
let allowedDevices = Cc["@mozilla.org/supports-array;1"] let allowedDevices = Cc["@mozilla.org/supports-array;1"]
.createInstance(Ci.nsISupportsArray); .createInstance(Ci.nsISupportsArray);
if (videoDevices.length) { if (videoDevices.length) {
@ -185,19 +210,11 @@ function prompt(aWindowID, aCallID, aAudioRequested, aVideoRequested, aDevices)
} }
Services.obs.notifyObservers(allowedDevices, "getUserMedia:response:allow", aCallID); Services.obs.notifyObservers(allowedDevices, "getUserMedia:response:allow", aCallID);
};
return true;
} }
}; };
let secondaryActions = [{
label: stringBundle.getString("getUserMedia.denyRequest.label"),
accessKey: stringBundle.getString("getUserMedia.denyRequest.accesskey"),
callback: function () {
denyRequest(aCallID);
}
}];
let options = null;
chromeWin.PopupNotifications.show(browser, "webRTC-shareDevices", message, chromeWin.PopupNotifications.show(browser, "webRTC-shareDevices", message,
"webRTC-shareDevices-notification-icon", mainAction, "webRTC-shareDevices-notification-icon", mainAction,
secondaryActions, options); secondaryActions, options);
@ -256,7 +273,8 @@ function showBrowserSpecificIndicator(aBrowser) {
}]; }];
let options = { let options = {
hideNotNow: true, hideNotNow: true,
dismissed: true dismissed: true,
eventCallback: function(aTopic) aTopic == "swapping"
}; };
chromeWin.PopupNotifications.show(aBrowser, "webRTC-sharingDevices", message, chromeWin.PopupNotifications.show(aBrowser, "webRTC-sharingDevices", message,
"webRTC-sharingDevices-notification-icon", mainAction, "webRTC-sharingDevices-notification-icon", mainAction,