mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-29 20:07:30 +09:00
[PALEMOON] Bug 723951 - Popup notification does not continue when the tab move to other window
Issue #121
This commit is contained in:
parent
da15587e4a
commit
690b0039c9
2 changed files with 136 additions and 56 deletions
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -130,62 +130,14 @@ 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 ]);
|
||||||
|
|
||||||
function listDevices(menupopup, devices) {
|
|
||||||
while (menupopup.lastChild)
|
|
||||||
menupopup.removeChild(menupopup.lastChild);
|
|
||||||
|
|
||||||
let deviceIndex = 0;
|
|
||||||
for (let device of devices) {
|
|
||||||
addDeviceToList(menupopup, device.name, deviceIndex);
|
|
||||||
deviceIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function addDeviceToList(menupopup, deviceName, deviceIndex) {
|
|
||||||
let menuitem = chromeDoc.createElement("menuitem");
|
|
||||||
menuitem.setAttribute("value", deviceIndex);
|
|
||||||
menuitem.setAttribute("label", deviceName);
|
|
||||||
menuitem.setAttribute("tooltiptext", deviceName);
|
|
||||||
menupopup.appendChild(menuitem);
|
|
||||||
}
|
|
||||||
|
|
||||||
chromeDoc.getElementById("webRTC-selectCamera").hidden = !videoDevices.length;
|
|
||||||
chromeDoc.getElementById("webRTC-selectMicrophone").hidden = !audioDevices.length;
|
|
||||||
|
|
||||||
let camMenupopup = chromeDoc.getElementById("webRTC-selectCamera-menupopup");
|
|
||||||
let micMenupopup = chromeDoc.getElementById("webRTC-selectMicrophone-menupopup");
|
|
||||||
listDevices(camMenupopup, videoDevices);
|
|
||||||
listDevices(micMenupopup, audioDevices);
|
|
||||||
if (requestType == "CameraAndMicrophone") {
|
|
||||||
addDeviceToList(camMenupopup, stringBundle.getString("getUserMedia.noVideo.label"), "-1");
|
|
||||||
addDeviceToList(micMenupopup, stringBundle.getString("getUserMedia.noAudio.label"), "-1");
|
|
||||||
}
|
|
||||||
|
|
||||||
let mainAction = {
|
let mainAction = {
|
||||||
label: PluralForm.get(requestType == "CameraAndMicrophone" ? 2 : 1,
|
label: PluralForm.get(requestType == "CameraAndMicrophone" ? 2 : 1,
|
||||||
stringBundle.getString("getUserMedia.shareSelectedDevices.label")),
|
stringBundle.getString("getUserMedia.shareSelectedDevices.label")),
|
||||||
accessKey: stringBundle.getString("getUserMedia.shareSelectedDevices.accesskey"),
|
accessKey: stringBundle.getString("getUserMedia.shareSelectedDevices.accesskey"),
|
||||||
callback: function () {
|
// The real callback will be set during the "showing" event. The
|
||||||
let allowedDevices = Cc["@mozilla.org/supports-array;1"]
|
// empty function here is so that PopupNotifications.show doesn't
|
||||||
.createInstance(Ci.nsISupportsArray);
|
// reject the action.
|
||||||
if (videoDevices.length) {
|
callback: function() {}
|
||||||
let videoDeviceIndex = chromeDoc.getElementById("webRTC-selectCamera-menulist").value;
|
|
||||||
if (videoDeviceIndex != "-1")
|
|
||||||
allowedDevices.AppendElement(videoDevices[videoDeviceIndex]);
|
|
||||||
}
|
|
||||||
if (audioDevices.length) {
|
|
||||||
let audioDeviceIndex = chromeDoc.getElementById("webRTC-selectMicrophone-menulist").value;
|
|
||||||
if (audioDeviceIndex != "-1")
|
|
||||||
allowedDevices.AppendElement(audioDevices[audioDeviceIndex]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (allowedDevices.Count() == 0) {
|
|
||||||
denyRequest(aCallID);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Services.obs.notifyObservers(allowedDevices, "getUserMedia:response:allow", aCallID);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let secondaryActions = [{
|
let secondaryActions = [{
|
||||||
|
|
@ -196,7 +148,72 @@ function prompt(aWindowID, aCallID, aAudioRequested, aVideoRequested, aDevices)
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let options = null;
|
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) {
|
||||||
|
while (menupopup.lastChild)
|
||||||
|
menupopup.removeChild(menupopup.lastChild);
|
||||||
|
|
||||||
|
let deviceIndex = 0;
|
||||||
|
for (let device of devices) {
|
||||||
|
addDeviceToList(menupopup, device.name, deviceIndex);
|
||||||
|
deviceIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addDeviceToList(menupopup, deviceName, deviceIndex) {
|
||||||
|
let menuitem = chromeDoc.createElement("menuitem");
|
||||||
|
menuitem.setAttribute("value", deviceIndex);
|
||||||
|
menuitem.setAttribute("label", deviceName);
|
||||||
|
menuitem.setAttribute("tooltiptext", deviceName);
|
||||||
|
menupopup.appendChild(menuitem);
|
||||||
|
}
|
||||||
|
|
||||||
|
chromeDoc.getElementById("webRTC-selectCamera").hidden = !videoDevices.length;
|
||||||
|
chromeDoc.getElementById("webRTC-selectMicrophone").hidden = !audioDevices.length;
|
||||||
|
|
||||||
|
let camMenupopup = chromeDoc.getElementById("webRTC-selectCamera-menupopup");
|
||||||
|
let micMenupopup = chromeDoc.getElementById("webRTC-selectMicrophone-menupopup");
|
||||||
|
listDevices(camMenupopup, videoDevices);
|
||||||
|
listDevices(micMenupopup, audioDevices);
|
||||||
|
if (requestType == "CameraAndMicrophone") {
|
||||||
|
let stringBundle = chromeDoc.defaultView.gNavigatorBundle;
|
||||||
|
addDeviceToList(camMenupopup, stringBundle.getString("getUserMedia.noVideo.label"), "-1");
|
||||||
|
addDeviceToList(micMenupopup, stringBundle.getString("getUserMedia.noAudio.label"), "-1");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.mainAction.callback = function() {
|
||||||
|
let allowedDevices = Cc["@mozilla.org/supports-array;1"]
|
||||||
|
.createInstance(Ci.nsISupportsArray);
|
||||||
|
if (videoDevices.length) {
|
||||||
|
let videoDeviceIndex = chromeDoc.getElementById("webRTC-selectCamera-menulist").value;
|
||||||
|
if (videoDeviceIndex != "-1")
|
||||||
|
allowedDevices.AppendElement(videoDevices[videoDeviceIndex]);
|
||||||
|
}
|
||||||
|
if (audioDevices.length) {
|
||||||
|
let audioDeviceIndex = chromeDoc.getElementById("webRTC-selectMicrophone-menulist").value;
|
||||||
|
if (audioDeviceIndex != "-1")
|
||||||
|
allowedDevices.AppendElement(audioDevices[audioDeviceIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allowedDevices.Count() == 0) {
|
||||||
|
denyRequest(aCallID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Services.obs.notifyObservers(allowedDevices, "getUserMedia:response:allow", aCallID);
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
chromeWin.PopupNotifications.show(browser, "webRTC-shareDevices", message,
|
chromeWin.PopupNotifications.show(browser, "webRTC-shareDevices", message,
|
||||||
"webRTC-shareDevices-notification-icon", mainAction,
|
"webRTC-shareDevices-notification-icon", mainAction,
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue