2012-10-05 02:37:00 -07:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* 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/. */
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
2012-10-31 09:13:28 -07:00
|
|
|
this.EXPORTED_SYMBOLS = ["webrtcUI"];
|
2012-10-05 02:37:00 -07:00
|
|
|
|
|
|
|
const Cu = Components.utils;
|
2012-12-21 13:05:45 -08:00
|
|
|
const Cc = Components.classes;
|
2012-10-05 02:37:00 -07:00
|
|
|
const Ci = Components.interfaces;
|
|
|
|
|
|
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
2012-12-28 01:25:59 -08:00
|
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
|
|
|
2014-04-22 20:19:12 -07:00
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
|
|
|
|
"resource://gre/modules/PluralForm.jsm");
|
|
|
|
|
2012-10-31 09:13:28 -07:00
|
|
|
this.webrtcUI = {
|
2012-10-05 02:37:00 -07:00
|
|
|
init: function () {
|
2014-08-08 05:34:46 -07:00
|
|
|
Services.obs.addObserver(maybeAddMenuIndicator, "browser-delayed-startup-finished", false);
|
2014-09-22 11:39:57 -07:00
|
|
|
|
|
|
|
let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
|
|
|
|
.getService(Ci.nsIMessageBroadcaster);
|
2014-10-01 03:39:52 -07:00
|
|
|
ppmm.addMessageListener("webrtc:UpdatingIndicators", this);
|
2014-09-22 11:39:57 -07:00
|
|
|
ppmm.addMessageListener("webrtc:UpdateGlobalIndicators", this);
|
|
|
|
|
|
|
|
let mm = Cc["@mozilla.org/globalmessagemanager;1"]
|
|
|
|
.getService(Ci.nsIMessageListenerManager);
|
2014-09-22 11:39:58 -07:00
|
|
|
mm.addMessageListener("webrtc:Request", this);
|
2014-09-22 11:39:57 -07:00
|
|
|
mm.addMessageListener("webrtc:UpdateBrowserIndicators", this);
|
2012-10-05 02:37:00 -07:00
|
|
|
},
|
2012-12-28 01:25:59 -08:00
|
|
|
|
2012-10-05 02:37:00 -07:00
|
|
|
uninit: function () {
|
2014-08-08 05:34:46 -07:00
|
|
|
Services.obs.removeObserver(maybeAddMenuIndicator, "browser-delayed-startup-finished");
|
2014-09-22 11:39:57 -07:00
|
|
|
|
|
|
|
let ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"]
|
|
|
|
.getService(Ci.nsIMessageBroadcaster);
|
2014-10-01 03:39:52 -07:00
|
|
|
ppmm.removeMessageListener("webrtc:UpdatingIndicators", this);
|
2014-09-22 11:39:57 -07:00
|
|
|
ppmm.removeMessageListener("webrtc:UpdateGlobalIndicators", this);
|
|
|
|
|
|
|
|
let mm = Cc["@mozilla.org/globalmessagemanager;1"]
|
|
|
|
.getService(Ci.nsIMessageListenerManager);
|
2014-09-22 11:39:58 -07:00
|
|
|
mm.removeMessageListener("webrtc:Request", this);
|
2014-09-22 11:39:57 -07:00
|
|
|
mm.removeMessageListener("webrtc:UpdateBrowserIndicators", this);
|
2012-12-28 01:25:59 -08:00
|
|
|
},
|
|
|
|
|
|
|
|
showGlobalIndicator: false,
|
2014-07-18 17:49:18 -07:00
|
|
|
showCameraIndicator: false,
|
|
|
|
showMicrophoneIndicator: false,
|
2014-08-27 07:52:22 -07:00
|
|
|
showScreenSharingIndicator: "", // either "Application", "Screen" or "Window"
|
2012-12-28 01:25:59 -08:00
|
|
|
|
2014-10-01 03:39:52 -07:00
|
|
|
_streams: [],
|
2014-07-18 17:49:19 -07:00
|
|
|
// The boolean parameters indicate which streams should be included in the result.
|
|
|
|
getActiveStreams: function(aCamera, aMicrophone, aScreen) {
|
2014-10-01 03:39:52 -07:00
|
|
|
return webrtcUI._streams.filter(aStream => {
|
|
|
|
let state = aStream.state;
|
|
|
|
return aCamera && state.camera ||
|
|
|
|
aMicrophone && state.microphone ||
|
|
|
|
aScreen && state.screen;
|
|
|
|
}).map(aStream => {
|
|
|
|
let state = aStream.state;
|
|
|
|
let types = {camera: state.camera, microphone: state.microphone,
|
|
|
|
screen: state.screen};
|
|
|
|
let browser = aStream.browser;
|
2013-06-05 10:15:14 -07:00
|
|
|
let browserWindow = browser.ownerDocument.defaultView;
|
2012-12-28 01:25:59 -08:00
|
|
|
let tab = browserWindow.gBrowser &&
|
2014-10-09 16:26:11 -07:00
|
|
|
browserWindow.gBrowser.getTabForBrowser(browser);
|
2014-10-01 03:39:52 -07:00
|
|
|
return {uri: state.documentURI, tab: tab, browser: browser, types: types};
|
|
|
|
});
|
2014-07-18 03:14:29 -07:00
|
|
|
},
|
|
|
|
|
2014-07-18 17:49:19 -07:00
|
|
|
showSharingDoorhanger: function(aActiveStream, aType) {
|
|
|
|
let browserWindow = aActiveStream.browser.ownerDocument.defaultView;
|
|
|
|
if (aActiveStream.tab) {
|
|
|
|
browserWindow.gBrowser.selectedTab = aActiveStream.tab;
|
|
|
|
} else {
|
|
|
|
aActiveStream.browser.focus();
|
|
|
|
}
|
|
|
|
browserWindow.focus();
|
|
|
|
let PopupNotifications = browserWindow.PopupNotifications;
|
|
|
|
let notif = PopupNotifications.getNotification("webRTC-sharing" + aType,
|
|
|
|
aActiveStream.browser);
|
2014-08-14 10:30:52 -07:00
|
|
|
#ifdef XP_MACOSX
|
|
|
|
if (!Services.focus.activeWindow) {
|
|
|
|
browserWindow.addEventListener("activate", function onActivate() {
|
|
|
|
browserWindow.removeEventListener("activate", onActivate);
|
|
|
|
Services.tm.mainThread.dispatch(function() {
|
|
|
|
notif.reshow();
|
|
|
|
}, Ci.nsIThread.DISPATCH_NORMAL);
|
|
|
|
});
|
|
|
|
Cc["@mozilla.org/widget/macdocksupport;1"].getService(Ci.nsIMacDockSupport)
|
|
|
|
.activateApplication(true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
2014-07-18 17:49:19 -07:00
|
|
|
notif.reshow();
|
|
|
|
},
|
|
|
|
|
2014-07-18 03:14:29 -07:00
|
|
|
updateMainActionLabel: function(aMenuList) {
|
|
|
|
let type = aMenuList.selectedItem.getAttribute("devicetype");
|
|
|
|
let document = aMenuList.ownerDocument;
|
|
|
|
document.getElementById("webRTC-all-windows-shared").hidden = type != "Screen";
|
|
|
|
|
|
|
|
// If we are also requesting audio in addition to screen sharing,
|
|
|
|
// always use a generic label.
|
|
|
|
if (!document.getElementById("webRTC-selectMicrophone").hidden)
|
|
|
|
type = "";
|
|
|
|
|
|
|
|
let bundle = document.defaultView.gNavigatorBundle;
|
|
|
|
let stringId = "getUserMedia.share" + (type || "SelectedItems") + ".label";
|
|
|
|
let popupnotification = aMenuList.parentNode.parentNode;
|
|
|
|
popupnotification.setAttribute("buttonlabel", bundle.getString(stringId));
|
2014-09-22 11:39:57 -07:00
|
|
|
},
|
2012-10-05 02:37:00 -07:00
|
|
|
|
2014-09-22 11:39:57 -07:00
|
|
|
receiveMessage: function(aMessage) {
|
|
|
|
switch (aMessage.name) {
|
2014-09-22 11:39:58 -07:00
|
|
|
case "webrtc:Request":
|
|
|
|
prompt(aMessage.target, aMessage.data);
|
|
|
|
break;
|
2014-10-01 03:39:52 -07:00
|
|
|
case "webrtc:UpdatingIndicators":
|
|
|
|
webrtcUI._streams = [];
|
|
|
|
break;
|
2014-09-22 11:39:57 -07:00
|
|
|
case "webrtc:UpdateGlobalIndicators":
|
|
|
|
updateIndicators(aMessage.data)
|
|
|
|
break;
|
|
|
|
case "webrtc:UpdateBrowserIndicators":
|
2014-10-01 03:39:52 -07:00
|
|
|
webrtcUI._streams.push({browser: aMessage.target, state: aMessage.data});
|
2014-09-22 11:39:57 -07:00
|
|
|
updateBrowserSpecificIndicator(aMessage.target, aMessage.data);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2013-05-30 11:02:49 -07:00
|
|
|
|
|
|
|
function getBrowserForWindow(aContentWindow) {
|
|
|
|
return aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
|
|
.getInterface(Ci.nsIWebNavigation)
|
|
|
|
.QueryInterface(Ci.nsIDocShell)
|
|
|
|
.chromeEventHandler;
|
2013-02-16 02:10:41 -08:00
|
|
|
}
|
2012-10-05 02:37:00 -07:00
|
|
|
|
2014-09-22 11:39:58 -07:00
|
|
|
function denyRequest(aBrowser, aRequest) {
|
|
|
|
aBrowser.messageManager.sendAsyncMessage("webrtc:Deny",
|
|
|
|
{callID: aRequest.callID,
|
|
|
|
windowID: aRequest.windowID});
|
2013-02-23 03:56:23 -08:00
|
|
|
}
|
|
|
|
|
2014-09-22 11:39:58 -07:00
|
|
|
function prompt(aBrowser, aRequest) {
|
|
|
|
let {audioDevices: audioDevices, videoDevices: videoDevices,
|
|
|
|
sharingScreen: sharingScreen, requestTypes: requestTypes} = aRequest;
|
|
|
|
let uri = Services.io.newURI(aRequest.documentURI, null, null);
|
|
|
|
let chromeDoc = aBrowser.ownerDocument;
|
2012-12-21 13:05:45 -08:00
|
|
|
let chromeWin = chromeDoc.defaultView;
|
2012-10-05 02:37:00 -07:00
|
|
|
let stringBundle = chromeWin.gNavigatorBundle;
|
2014-07-07 00:08:00 -07:00
|
|
|
let stringId = "getUserMedia.share" + requestTypes.join("And") + ".message";
|
|
|
|
let message = stringBundle.getFormattedString(stringId, [uri.host]);
|
2012-10-05 02:37:00 -07:00
|
|
|
|
2014-07-18 03:14:29 -07:00
|
|
|
let mainLabel;
|
|
|
|
if (sharingScreen) {
|
|
|
|
mainLabel = stringBundle.getString("getUserMedia.shareSelectedItems.label");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
let string = stringBundle.getString("getUserMedia.shareSelectedDevices.label");
|
|
|
|
mainLabel = PluralForm.get(requestTypes.length, string);
|
|
|
|
}
|
2012-10-05 02:37:00 -07:00
|
|
|
let mainAction = {
|
2014-07-18 03:14:29 -07:00
|
|
|
label: mainLabel,
|
2012-12-21 13:05:45 -08:00
|
|
|
accessKey: stringBundle.getString("getUserMedia.shareSelectedDevices.accesskey"),
|
2013-12-19 13:16:10 -08:00
|
|
|
// 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() {}
|
2012-10-05 02:37:00 -07:00
|
|
|
};
|
|
|
|
|
2014-02-25 03:50:42 -08:00
|
|
|
let secondaryActions = [
|
|
|
|
{
|
|
|
|
label: stringBundle.getString("getUserMedia.denyRequest.label"),
|
|
|
|
accessKey: stringBundle.getString("getUserMedia.denyRequest.accesskey"),
|
|
|
|
callback: function () {
|
2014-09-22 11:39:58 -07:00
|
|
|
denyRequest(aBrowser, aRequest);
|
2014-02-25 03:50:42 -08:00
|
|
|
}
|
2014-07-07 00:08:00 -07:00
|
|
|
}
|
|
|
|
];
|
|
|
|
|
|
|
|
if (!sharingScreen) { // Bug 1037438: implement 'never' for screen sharing.
|
|
|
|
secondaryActions.push({
|
2014-02-25 03:50:42 -08:00
|
|
|
label: stringBundle.getString("getUserMedia.never.label"),
|
|
|
|
accessKey: stringBundle.getString("getUserMedia.never.accesskey"),
|
|
|
|
callback: function () {
|
2014-09-22 11:39:58 -07:00
|
|
|
denyRequest(aBrowser, aRequest);
|
2014-04-17 15:37:59 -07:00
|
|
|
// Let someone save "Never" for http sites so that they can be stopped from
|
|
|
|
// bothering you with doorhangers.
|
2014-02-25 03:50:42 -08:00
|
|
|
let perms = Services.perms;
|
|
|
|
if (audioDevices.length)
|
|
|
|
perms.add(uri, "microphone", perms.DENY_ACTION);
|
|
|
|
if (videoDevices.length)
|
|
|
|
perms.add(uri, "camera", perms.DENY_ACTION);
|
|
|
|
}
|
2014-07-07 00:08:00 -07:00
|
|
|
});
|
|
|
|
}
|
2012-10-05 02:37:00 -07:00
|
|
|
|
2014-09-22 11:39:58 -07:00
|
|
|
if (aRequest.secure && !sharingScreen) {
|
2014-07-07 00:08:00 -07:00
|
|
|
// Don't show the 'Always' action if the connection isn't secure, or for
|
|
|
|
// screen sharing (because we can't guess which window the user wants to
|
|
|
|
// share without prompting).
|
2014-04-17 15:37:59 -07:00
|
|
|
secondaryActions.unshift({
|
|
|
|
label: stringBundle.getString("getUserMedia.always.label"),
|
|
|
|
accessKey: stringBundle.getString("getUserMedia.always.accesskey"),
|
|
|
|
callback: function () {
|
|
|
|
mainAction.callback(true);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2013-12-19 13:16:10 -08:00
|
|
|
let options = {
|
|
|
|
eventCallback: function(aTopic, aNewBrowser) {
|
|
|
|
if (aTopic == "swapping")
|
|
|
|
return true;
|
|
|
|
|
2014-02-28 09:47:18 -08:00
|
|
|
let chromeDoc = this.browser.ownerDocument;
|
|
|
|
|
|
|
|
if (aTopic == "shown") {
|
|
|
|
let PopupNotifications = chromeDoc.defaultView.PopupNotifications;
|
2014-07-07 00:08:00 -07:00
|
|
|
let popupId = "Devices";
|
|
|
|
if (requestTypes.length == 1 && requestTypes[0] == "Microphone")
|
|
|
|
popupId = "Microphone";
|
2014-07-18 03:14:29 -07:00
|
|
|
if (requestTypes.indexOf("Screen") != -1)
|
|
|
|
popupId = "Screen";
|
2014-02-28 09:47:18 -08:00
|
|
|
PopupNotifications.panel.firstChild.setAttribute("popupid", "webRTC-share" + popupId);
|
|
|
|
}
|
|
|
|
|
2013-12-19 13:16:10 -08:00
|
|
|
if (aTopic != "showing")
|
|
|
|
return false;
|
|
|
|
|
2014-06-13 05:51:12 -07:00
|
|
|
// DENY_ACTION is handled immediately by MediaManager, but handling
|
|
|
|
// of ALLOW_ACTION is delayed until the popupshowing event
|
|
|
|
// to avoid granting permissions automatically to background tabs.
|
2014-09-22 11:39:58 -07:00
|
|
|
if (aRequest.secure) {
|
2014-06-13 05:51:12 -07:00
|
|
|
let perms = Services.perms;
|
|
|
|
|
|
|
|
let micPerm = perms.testExactPermission(uri, "microphone");
|
|
|
|
if (micPerm == perms.PROMPT_ACTION)
|
|
|
|
micPerm = perms.UNKNOWN_ACTION;
|
|
|
|
|
|
|
|
let camPerm = perms.testExactPermission(uri, "camera");
|
|
|
|
if (camPerm == perms.PROMPT_ACTION)
|
|
|
|
camPerm = perms.UNKNOWN_ACTION;
|
|
|
|
|
2014-07-07 00:08:00 -07:00
|
|
|
// Screen sharing shouldn't follow the camera permissions.
|
|
|
|
if (videoDevices.length && sharingScreen)
|
|
|
|
camPerm = perms.UNKNOWN_ACTION;
|
|
|
|
|
2014-06-13 05:51:12 -07:00
|
|
|
// We don't check that permissions are set to ALLOW_ACTION in this
|
|
|
|
// test; only that they are set. This is because if audio is allowed
|
|
|
|
// and video is denied persistently, we don't want to show the prompt,
|
|
|
|
// and will grant audio access immediately.
|
|
|
|
if ((!audioDevices.length || micPerm) && (!videoDevices.length || camPerm)) {
|
|
|
|
// All permissions we were about to request are already persistently set.
|
2014-09-22 11:39:58 -07:00
|
|
|
let allowedDevices = [];
|
2014-06-13 05:51:12 -07:00
|
|
|
if (videoDevices.length && camPerm == perms.ALLOW_ACTION)
|
2014-09-22 11:39:58 -07:00
|
|
|
allowedDevices.push(videoDevices[0].deviceIndex);
|
2014-06-13 05:51:12 -07:00
|
|
|
if (audioDevices.length && micPerm == perms.ALLOW_ACTION)
|
2014-09-22 11:39:58 -07:00
|
|
|
allowedDevices.push(audioDevices[0].deviceIndex);
|
|
|
|
aBrowser.messageManager.sendAsyncMessage("webrtc:Allow",
|
|
|
|
{callID: aRequest.callID,
|
|
|
|
windowID: aRequest.windowID,
|
|
|
|
devices: allowedDevices});
|
2014-06-13 05:51:12 -07:00
|
|
|
this.remove();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-19 13:16:10 -08:00
|
|
|
function listDevices(menupopup, devices) {
|
|
|
|
while (menupopup.lastChild)
|
|
|
|
menupopup.removeChild(menupopup.lastChild);
|
|
|
|
|
2014-09-22 11:39:58 -07:00
|
|
|
for (let device of devices)
|
|
|
|
addDeviceToList(menupopup, device.name, device.deviceIndex);
|
2013-12-19 13:16:10 -08:00
|
|
|
}
|
|
|
|
|
2014-07-07 00:08:00 -07:00
|
|
|
function listScreenShareDevices(menupopup, devices) {
|
|
|
|
while (menupopup.lastChild)
|
|
|
|
menupopup.removeChild(menupopup.lastChild);
|
|
|
|
|
2014-08-27 07:52:22 -07:00
|
|
|
let type = devices[0].mediaSource;
|
|
|
|
let typeName = type.charAt(0).toUpperCase() + type.substr(1);
|
|
|
|
|
|
|
|
let label = chromeDoc.getElementById("webRTC-selectWindow-label");
|
|
|
|
let stringId = "getUserMedia.select" + typeName;
|
|
|
|
label.setAttribute("value",
|
|
|
|
stringBundle.getString(stringId + ".label"));
|
|
|
|
label.setAttribute("accesskey",
|
|
|
|
stringBundle.getString(stringId + ".accesskey"));
|
|
|
|
|
|
|
|
// "No <type>" is the default because we can't pick a
|
2014-07-07 00:08:00 -07:00
|
|
|
// 'default' window to share.
|
|
|
|
addDeviceToList(menupopup,
|
2014-08-27 07:52:22 -07:00
|
|
|
stringBundle.getString("getUserMedia.no" + typeName + ".label"),
|
2014-07-07 00:08:00 -07:00
|
|
|
"-1");
|
2014-08-27 07:52:22 -07:00
|
|
|
menupopup.appendChild(chromeDoc.createElement("menuseparator"));
|
2014-07-07 00:08:00 -07:00
|
|
|
|
2014-08-27 07:52:22 -07:00
|
|
|
// Build the list of 'devices'.
|
2014-07-07 00:08:00 -07:00
|
|
|
for (let i = 0; i < devices.length; ++i) {
|
2014-08-27 07:52:22 -07:00
|
|
|
let name;
|
|
|
|
// Screen has a special treatment because we currently only support
|
|
|
|
// sharing the primary screen and want to display a localized string.
|
2014-08-27 07:52:22 -07:00
|
|
|
if (type == "screen") {
|
2014-08-27 07:52:22 -07:00
|
|
|
name = stringBundle.getString("getUserMedia.shareEntireScreen.label");
|
2014-08-27 07:52:22 -07:00
|
|
|
}
|
|
|
|
else {
|
2014-08-27 07:52:22 -07:00
|
|
|
name = devices[i].name;
|
2014-08-27 07:52:22 -07:00
|
|
|
if (type == "application") {
|
|
|
|
// The application names returned by the platform are of the form:
|
|
|
|
// <window count>\x1e<application name>
|
|
|
|
let sepIndex = name.indexOf("\x1e");
|
|
|
|
let count = name.slice(0, sepIndex);
|
|
|
|
let stringId = "getUserMedia.shareApplicationWindowCount.label";
|
|
|
|
name = PluralForm.get(parseInt(count), stringBundle.getString(stringId))
|
|
|
|
.replace("#1", name.slice(sepIndex + 1))
|
|
|
|
.replace("#2", count);
|
|
|
|
}
|
|
|
|
}
|
2014-08-27 07:52:22 -07:00
|
|
|
addDeviceToList(menupopup, name, i, typeName);
|
2014-07-07 00:08:00 -07:00
|
|
|
}
|
|
|
|
|
2014-08-27 07:52:22 -07:00
|
|
|
// Always re-select the "No <type>" item.
|
2014-07-18 03:14:29 -07:00
|
|
|
chromeDoc.getElementById("webRTC-selectWindow-menulist").removeAttribute("value");
|
|
|
|
chromeDoc.getElementById("webRTC-all-windows-shared").hidden = true;
|
2014-07-07 00:08:00 -07:00
|
|
|
}
|
|
|
|
|
2014-07-18 03:14:29 -07:00
|
|
|
function addDeviceToList(menupopup, deviceName, deviceIndex, type) {
|
2013-12-19 13:16:10 -08:00
|
|
|
let menuitem = chromeDoc.createElement("menuitem");
|
|
|
|
menuitem.setAttribute("value", deviceIndex);
|
|
|
|
menuitem.setAttribute("label", deviceName);
|
|
|
|
menuitem.setAttribute("tooltiptext", deviceName);
|
2014-07-18 03:14:29 -07:00
|
|
|
if (type)
|
|
|
|
menuitem.setAttribute("devicetype", type);
|
2013-12-19 13:16:10 -08:00
|
|
|
menupopup.appendChild(menuitem);
|
|
|
|
}
|
|
|
|
|
2014-07-07 00:08:00 -07:00
|
|
|
chromeDoc.getElementById("webRTC-selectCamera").hidden = !videoDevices.length || sharingScreen;
|
|
|
|
chromeDoc.getElementById("webRTC-selectWindowOrScreen").hidden = !sharingScreen || !videoDevices.length;
|
2013-12-19 13:16:10 -08:00
|
|
|
chromeDoc.getElementById("webRTC-selectMicrophone").hidden = !audioDevices.length;
|
|
|
|
|
|
|
|
let camMenupopup = chromeDoc.getElementById("webRTC-selectCamera-menupopup");
|
2014-07-07 00:08:00 -07:00
|
|
|
let windowMenupopup = chromeDoc.getElementById("webRTC-selectWindow-menupopup");
|
2013-12-19 13:16:10 -08:00
|
|
|
let micMenupopup = chromeDoc.getElementById("webRTC-selectMicrophone-menupopup");
|
2014-07-07 00:08:00 -07:00
|
|
|
if (sharingScreen)
|
|
|
|
listScreenShareDevices(windowMenupopup, videoDevices);
|
|
|
|
else
|
|
|
|
listDevices(camMenupopup, videoDevices);
|
2013-12-19 13:16:10 -08:00
|
|
|
listDevices(micMenupopup, audioDevices);
|
2014-07-07 00:08:00 -07:00
|
|
|
if (requestTypes.length == 2) {
|
2013-12-19 13:16:10 -08:00
|
|
|
let stringBundle = chromeDoc.defaultView.gNavigatorBundle;
|
2014-07-07 00:08:00 -07:00
|
|
|
if (!sharingScreen)
|
|
|
|
addDeviceToList(camMenupopup, stringBundle.getString("getUserMedia.noVideo.label"), "-1");
|
2013-12-19 13:16:10 -08:00
|
|
|
addDeviceToList(micMenupopup, stringBundle.getString("getUserMedia.noAudio.label"), "-1");
|
|
|
|
}
|
|
|
|
|
2014-02-25 03:50:42 -08:00
|
|
|
this.mainAction.callback = function(aRemember) {
|
2014-09-22 11:39:58 -07:00
|
|
|
let allowedDevices = [];
|
2014-02-25 03:50:42 -08:00
|
|
|
let perms = Services.perms;
|
2013-12-19 13:16:10 -08:00
|
|
|
if (videoDevices.length) {
|
2014-07-07 00:08:00 -07:00
|
|
|
let listId = "webRTC-select" + (sharingScreen ? "Window" : "Camera") + "-menulist";
|
|
|
|
let videoDeviceIndex = chromeDoc.getElementById(listId).value;
|
2014-02-25 03:50:42 -08:00
|
|
|
let allowCamera = videoDeviceIndex != "-1";
|
|
|
|
if (allowCamera)
|
2014-09-22 11:39:58 -07:00
|
|
|
allowedDevices.push(videoDeviceIndex);
|
2014-02-25 03:50:42 -08:00
|
|
|
if (aRemember) {
|
|
|
|
perms.add(uri, "camera",
|
|
|
|
allowCamera ? perms.ALLOW_ACTION : perms.DENY_ACTION);
|
|
|
|
}
|
2013-12-19 13:16:10 -08:00
|
|
|
}
|
|
|
|
if (audioDevices.length) {
|
|
|
|
let audioDeviceIndex = chromeDoc.getElementById("webRTC-selectMicrophone-menulist").value;
|
2014-02-25 03:50:42 -08:00
|
|
|
let allowMic = audioDeviceIndex != "-1";
|
|
|
|
if (allowMic)
|
2014-09-22 11:39:58 -07:00
|
|
|
allowedDevices.push(audioDeviceIndex);
|
2014-02-25 03:50:42 -08:00
|
|
|
if (aRemember) {
|
|
|
|
perms.add(uri, "microphone",
|
|
|
|
allowMic ? perms.ALLOW_ACTION : perms.DENY_ACTION);
|
|
|
|
}
|
2013-12-19 13:16:10 -08:00
|
|
|
}
|
|
|
|
|
2014-09-22 11:39:58 -07:00
|
|
|
if (!allowedDevices.length) {
|
|
|
|
denyRequest(aBrowser, aRequest);
|
2013-12-19 13:16:10 -08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-09-22 11:39:58 -07:00
|
|
|
aBrowser.messageManager.sendAsyncMessage("webrtc:Allow",
|
|
|
|
{callID: aRequest.callID,
|
|
|
|
windowID: aRequest.windowID,
|
|
|
|
devices: allowedDevices});
|
2013-12-19 13:16:10 -08:00
|
|
|
};
|
2014-04-07 10:37:50 -07:00
|
|
|
return false;
|
2013-12-19 13:16:10 -08:00
|
|
|
}
|
|
|
|
};
|
2012-10-05 02:37:00 -07:00
|
|
|
|
2014-07-07 00:08:00 -07:00
|
|
|
let anchorId = "webRTC-shareDevices-notification-icon";
|
|
|
|
if (requestTypes.length == 1 && requestTypes[0] == "Microphone")
|
|
|
|
anchorId = "webRTC-shareMicrophone-notification-icon";
|
2014-07-18 03:14:29 -07:00
|
|
|
if (requestTypes.indexOf("Screen") != -1)
|
|
|
|
anchorId = "webRTC-shareScreen-notification-icon";
|
2014-09-22 11:39:58 -07:00
|
|
|
chromeWin.PopupNotifications.show(aBrowser, "webRTC-shareDevices", message,
|
2014-02-28 09:47:18 -08:00
|
|
|
anchorId, mainAction, secondaryActions, options);
|
2012-10-05 02:37:00 -07:00
|
|
|
}
|
2012-12-28 01:25:59 -08:00
|
|
|
|
2014-07-18 17:49:19 -07:00
|
|
|
function getGlobalIndicator() {
|
|
|
|
#ifndef XP_MACOSX
|
|
|
|
const INDICATOR_CHROME_URI = "chrome://browser/content/webrtcIndicator.xul";
|
|
|
|
const features = "chrome,dialog=yes,titlebar=no,popup=yes";
|
|
|
|
|
|
|
|
return Services.ww.openWindow(null, INDICATOR_CHROME_URI, "_blank", features, []);
|
|
|
|
#else
|
|
|
|
let indicator = {
|
|
|
|
_camera: null,
|
|
|
|
_microphone: null,
|
|
|
|
_screen: null,
|
|
|
|
|
|
|
|
_hiddenDoc: Cc["@mozilla.org/appshell/appShellService;1"]
|
|
|
|
.getService(Ci.nsIAppShellService)
|
|
|
|
.hiddenDOMWindow.document,
|
|
|
|
_statusBar: Cc["@mozilla.org/widget/macsystemstatusbar;1"]
|
|
|
|
.getService(Ci.nsISystemStatusBar),
|
|
|
|
|
|
|
|
_command: function(aEvent) {
|
|
|
|
let type = this.getAttribute("type");
|
|
|
|
if (type == "Camera" || type == "Microphone")
|
|
|
|
type = "Devices";
|
2014-08-27 07:52:22 -07:00
|
|
|
else if (type == "Window" || type == "Application")
|
2014-07-18 17:49:19 -07:00
|
|
|
type = "Screen";
|
|
|
|
webrtcUI.showSharingDoorhanger(aEvent.target.stream, type);
|
|
|
|
},
|
|
|
|
|
|
|
|
_popupShowing: function(aEvent) {
|
|
|
|
let type = this.getAttribute("type");
|
|
|
|
let activeStreams;
|
|
|
|
if (type == "Camera") {
|
|
|
|
activeStreams = webrtcUI.getActiveStreams(true, false, false);
|
|
|
|
}
|
|
|
|
else if (type == "Microphone") {
|
|
|
|
activeStreams = webrtcUI.getActiveStreams(false, true, false);
|
|
|
|
}
|
|
|
|
else if (type == "Screen") {
|
|
|
|
activeStreams = webrtcUI.getActiveStreams(false, false, true);
|
|
|
|
type = webrtcUI.showScreenSharingIndicator;
|
|
|
|
}
|
|
|
|
|
|
|
|
let bundle =
|
|
|
|
Services.strings.createBundle("chrome://browser/locale/webrtcIndicator.properties");
|
|
|
|
|
|
|
|
if (activeStreams.length == 1) {
|
|
|
|
let stream = activeStreams[0];
|
|
|
|
|
|
|
|
let menuitem = this.ownerDocument.createElement("menuitem");
|
|
|
|
let labelId = "webrtcIndicator.sharing" + type + "With.menuitem";
|
|
|
|
let label = stream.browser.contentTitle || stream.uri;
|
|
|
|
menuitem.setAttribute("label", bundle.formatStringFromName(labelId, [label], 1));
|
|
|
|
menuitem.setAttribute("disabled", "true");
|
|
|
|
this.appendChild(menuitem);
|
|
|
|
|
|
|
|
menuitem = this.ownerDocument.createElement("menuitem");
|
|
|
|
menuitem.setAttribute("label",
|
|
|
|
bundle.GetStringFromName("webrtcIndicator.controlSharing.menuitem"));
|
|
|
|
menuitem.setAttribute("type", type);
|
|
|
|
menuitem.stream = stream;
|
|
|
|
menuitem.addEventListener("command", indicator._command);
|
|
|
|
|
|
|
|
this.appendChild(menuitem);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We show a different menu when there are several active streams.
|
|
|
|
let menuitem = this.ownerDocument.createElement("menuitem");
|
|
|
|
let labelId = "webrtcIndicator.sharing" + type + "WithNTabs.menuitem";
|
|
|
|
let count = activeStreams.length;
|
|
|
|
let label = PluralForm.get(count, bundle.GetStringFromName(labelId)).replace("#1", count);
|
|
|
|
menuitem.setAttribute("label", label);
|
|
|
|
menuitem.setAttribute("disabled", "true");
|
|
|
|
this.appendChild(menuitem);
|
|
|
|
|
|
|
|
for (let stream of activeStreams) {
|
|
|
|
let item = this.ownerDocument.createElement("menuitem");
|
|
|
|
let labelId = "webrtcIndicator.controlSharingOn.menuitem";
|
|
|
|
let label = stream.browser.contentTitle || stream.uri;
|
|
|
|
item.setAttribute("label", bundle.formatStringFromName(labelId, [label], 1));
|
|
|
|
item.setAttribute("type", type);
|
|
|
|
item.stream = stream;
|
|
|
|
item.addEventListener("command", indicator._command);
|
|
|
|
this.appendChild(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
|
|
|
|
_popupHiding: function(aEvent) {
|
|
|
|
while (this.firstChild)
|
|
|
|
this.firstChild.remove();
|
|
|
|
},
|
|
|
|
|
|
|
|
_setIndicatorState: function(aName, aState) {
|
|
|
|
let field = "_" + aName.toLowerCase();
|
|
|
|
if (aState && !this[field]) {
|
|
|
|
let menu = this._hiddenDoc.createElement("menu");
|
2014-08-01 06:17:51 -07:00
|
|
|
menu.setAttribute("id", "webRTC-sharing" + aName + "-menu");
|
|
|
|
|
|
|
|
// The CSS will only be applied if the menu is actually inserted in the DOM.
|
|
|
|
this._hiddenDoc.documentElement.appendChild(menu);
|
|
|
|
|
2014-07-18 17:49:19 -07:00
|
|
|
this._statusBar.addItem(menu);
|
|
|
|
|
|
|
|
let menupopup = this._hiddenDoc.createElement("menupopup");
|
|
|
|
menupopup.setAttribute("type", aName);
|
|
|
|
menupopup.addEventListener("popupshowing", this._popupShowing);
|
|
|
|
menupopup.addEventListener("popuphiding", this._popupHiding);
|
|
|
|
menupopup.addEventListener("command", this._command);
|
|
|
|
menu.appendChild(menupopup);
|
|
|
|
|
|
|
|
this[field] = menu;
|
|
|
|
}
|
|
|
|
else if (this[field] && !aState) {
|
|
|
|
this._statusBar.removeItem(this[field]);
|
2014-08-01 06:17:51 -07:00
|
|
|
this[field].remove();
|
2014-07-18 17:49:19 -07:00
|
|
|
this[field] = null
|
|
|
|
}
|
|
|
|
},
|
|
|
|
updateIndicatorState: function() {
|
|
|
|
this._setIndicatorState("Camera", webrtcUI.showCameraIndicator);
|
|
|
|
this._setIndicatorState("Microphone", webrtcUI.showMicrophoneIndicator);
|
|
|
|
this._setIndicatorState("Screen", webrtcUI.showScreenSharingIndicator);
|
|
|
|
},
|
|
|
|
close: function() {
|
|
|
|
this._setIndicatorState("Camera", false);
|
|
|
|
this._setIndicatorState("Microphone", false);
|
|
|
|
this._setIndicatorState("Screen", false);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
indicator.updateIndicatorState();
|
|
|
|
return indicator;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-08-08 05:34:46 -07:00
|
|
|
function onTabSharingMenuPopupShowing(e) {
|
|
|
|
let streams = webrtcUI.getActiveStreams(true, true, true);
|
|
|
|
for (let streamInfo of streams) {
|
|
|
|
let stringName = "getUserMedia.sharingMenu";
|
2014-08-27 07:52:22 -07:00
|
|
|
let types = streamInfo.types;
|
2014-10-01 03:39:52 -07:00
|
|
|
if (types.camera)
|
2014-08-27 07:52:22 -07:00
|
|
|
stringName += "Camera";
|
2014-10-01 03:39:52 -07:00
|
|
|
if (types.microphone)
|
2014-08-27 07:52:22 -07:00
|
|
|
stringName += "Microphone";
|
2014-10-01 03:39:52 -07:00
|
|
|
if (types.screen)
|
|
|
|
stringName += types.screen;
|
2014-08-08 05:34:46 -07:00
|
|
|
|
|
|
|
let doc = e.target.ownerDocument;
|
|
|
|
let bundle = doc.defaultView.gNavigatorBundle;
|
|
|
|
|
|
|
|
let origin;
|
|
|
|
let uri;
|
|
|
|
let href = streamInfo.uri;
|
|
|
|
try {
|
|
|
|
uri = Services.io.newURI(href, null, null);
|
|
|
|
origin = uri.asciiHost;
|
|
|
|
} catch (ex) {};
|
|
|
|
if (!origin) {
|
|
|
|
if (uri && uri.scheme == "about") {
|
|
|
|
// For about URIs, just use the full spec, without any #hash parts
|
|
|
|
origin = uri.specIgnoringRef;
|
|
|
|
} else {
|
|
|
|
// This is unfortunate, but we should display *something*...
|
|
|
|
origin = bundle.getString("getUserMedia.sharingMenuUnknownHost");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let menuitem = doc.createElement("menuitem");
|
|
|
|
menuitem.setAttribute("label", bundle.getFormattedString(stringName, [origin]));
|
|
|
|
menuitem.stream = streamInfo;
|
|
|
|
|
|
|
|
// We can only open 1 doorhanger at a time. Guessing that users would be
|
2014-08-27 07:52:22 -07:00
|
|
|
// most eager to control screen/window/app sharing, and only then
|
2014-08-08 05:34:46 -07:00
|
|
|
// camera/microphone sharing, in that (decreasing) order of priority.
|
|
|
|
let doorhangerType;
|
2014-08-27 07:52:22 -07:00
|
|
|
if ((/Screen|Window|Application/).test(stringName)) {
|
2014-08-08 05:34:46 -07:00
|
|
|
doorhangerType = "Screen";
|
|
|
|
} else {
|
|
|
|
doorhangerType = "Devices";
|
|
|
|
}
|
|
|
|
menuitem.setAttribute("doorhangertype", doorhangerType);
|
|
|
|
menuitem.addEventListener("command", onTabSharingMenuPopupCommand);
|
|
|
|
e.target.appendChild(menuitem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function onTabSharingMenuPopupHiding(e) {
|
|
|
|
while (this.lastChild)
|
|
|
|
this.lastChild.remove();
|
|
|
|
}
|
|
|
|
|
|
|
|
function onTabSharingMenuPopupCommand(e) {
|
|
|
|
let type = e.target.getAttribute("doorhangertype");
|
|
|
|
webrtcUI.showSharingDoorhanger(e.target.stream, type);
|
|
|
|
}
|
|
|
|
|
|
|
|
function showOrCreateMenuForWindow(aWindow) {
|
|
|
|
let document = aWindow.document;
|
|
|
|
let menu = document.getElementById("tabSharingMenu");
|
|
|
|
if (!menu) {
|
|
|
|
let stringBundle = aWindow.gNavigatorBundle;
|
|
|
|
menu = document.createElement("menu");
|
|
|
|
menu.id = "tabSharingMenu";
|
|
|
|
let labelStringId = "getUserMedia.sharingMenu.label";
|
|
|
|
menu.setAttribute("label", stringBundle.getString(labelStringId));
|
|
|
|
#ifdef XP_MACOSX
|
|
|
|
let container = document.getElementById("windowPopup");
|
|
|
|
let insertionPoint = document.getElementById("sep-window-list");
|
|
|
|
let separator = document.createElement("menuseparator");
|
|
|
|
separator.id = "tabSharingSeparator";
|
|
|
|
container.insertBefore(separator, insertionPoint);
|
|
|
|
#else
|
|
|
|
let accesskeyStringId = "getUserMedia.sharingMenu.accesskey";
|
|
|
|
menu.setAttribute("accesskey", stringBundle.getString(accesskeyStringId));
|
|
|
|
let container = document.getElementById("main-menubar");
|
|
|
|
let insertionPoint = document.getElementById("helpMenu");
|
|
|
|
#endif
|
|
|
|
let popup = document.createElement("menupopup");
|
|
|
|
popup.id = "tabSharingMenuPopup";
|
|
|
|
popup.addEventListener("popupshowing", onTabSharingMenuPopupShowing);
|
|
|
|
popup.addEventListener("popuphiding", onTabSharingMenuPopupHiding);
|
|
|
|
menu.appendChild(popup);
|
|
|
|
container.insertBefore(menu, insertionPoint);
|
|
|
|
} else {
|
|
|
|
menu.hidden = false;
|
|
|
|
#ifdef XP_MACOSX
|
|
|
|
document.getElementById("tabSharingSeparator").hidden = false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function maybeAddMenuIndicator(window) {
|
|
|
|
if (webrtcUI.showGlobalIndicator) {
|
|
|
|
showOrCreateMenuForWindow(window);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-18 17:49:19 -07:00
|
|
|
var gIndicatorWindow = null;
|
|
|
|
|
2014-09-22 11:39:57 -07:00
|
|
|
function updateIndicators(data) {
|
|
|
|
webrtcUI.showGlobalIndicator = data.showGlobalIndicator;
|
|
|
|
webrtcUI.showCameraIndicator = data.showCameraIndicator;
|
|
|
|
webrtcUI.showMicrophoneIndicator = data.showMicrophoneIndicator;
|
|
|
|
webrtcUI.showScreenSharingIndicator = data.showScreenSharingIndicator;
|
2014-07-18 17:49:19 -07:00
|
|
|
|
2014-08-08 05:34:46 -07:00
|
|
|
let browserWindowEnum = Services.wm.getEnumerator("navigator:browser");
|
|
|
|
while (browserWindowEnum.hasMoreElements()) {
|
|
|
|
let chromeWin = browserWindowEnum.getNext();
|
|
|
|
if (webrtcUI.showGlobalIndicator) {
|
|
|
|
showOrCreateMenuForWindow(chromeWin);
|
|
|
|
} else {
|
|
|
|
let doc = chromeWin.document;
|
|
|
|
let existingMenu = doc.getElementById("tabSharingMenu");
|
|
|
|
if (existingMenu) {
|
|
|
|
existingMenu.hidden = true;
|
|
|
|
}
|
|
|
|
#ifdef XP_MACOSX
|
|
|
|
let separator = doc.getElementById("tabSharingSeparator");
|
|
|
|
if (separator) {
|
|
|
|
separator.hidden = true;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-07-18 17:49:19 -07:00
|
|
|
if (webrtcUI.showGlobalIndicator) {
|
2014-07-18 17:49:19 -07:00
|
|
|
if (!gIndicatorWindow)
|
|
|
|
gIndicatorWindow = getGlobalIndicator();
|
|
|
|
else
|
2014-07-18 17:49:19 -07:00
|
|
|
gIndicatorWindow.updateIndicatorState();
|
|
|
|
} else if (gIndicatorWindow) {
|
|
|
|
gIndicatorWindow.close();
|
|
|
|
gIndicatorWindow = null;
|
|
|
|
}
|
2013-03-01 01:28:01 -08:00
|
|
|
}
|
|
|
|
|
2014-09-22 11:39:57 -07:00
|
|
|
function updateBrowserSpecificIndicator(aBrowser, aState) {
|
2013-03-01 01:28:01 -08:00
|
|
|
let captureState;
|
2014-09-22 11:39:57 -07:00
|
|
|
if (aState.camera && aState.microphone) {
|
2013-03-01 01:28:01 -08:00
|
|
|
captureState = "CameraAndMicrophone";
|
2014-09-22 11:39:57 -07:00
|
|
|
} else if (aState.camera) {
|
2013-03-01 01:28:01 -08:00
|
|
|
captureState = "Camera";
|
2014-09-22 11:39:57 -07:00
|
|
|
} else if (aState.microphone) {
|
2013-03-01 01:28:01 -08:00
|
|
|
captureState = "Microphone";
|
|
|
|
}
|
|
|
|
|
|
|
|
let chromeWin = aBrowser.ownerDocument.defaultView;
|
|
|
|
let stringBundle = chromeWin.gNavigatorBundle;
|
|
|
|
|
2014-09-22 11:39:57 -07:00
|
|
|
let windowId = aState.windowId;
|
2014-01-23 02:50:03 -08:00
|
|
|
let mainAction = {
|
|
|
|
label: stringBundle.getString("getUserMedia.continueSharing.label"),
|
|
|
|
accessKey: stringBundle.getString("getUserMedia.continueSharing.accesskey"),
|
|
|
|
callback: function () {},
|
|
|
|
dismiss: true
|
|
|
|
};
|
|
|
|
let secondaryActions = [{
|
|
|
|
label: stringBundle.getString("getUserMedia.stopSharing.label"),
|
|
|
|
accessKey: stringBundle.getString("getUserMedia.stopSharing.accesskey"),
|
|
|
|
callback: function () {
|
2014-09-22 11:39:57 -07:00
|
|
|
let uri = Services.io.newURI(aState.documentURI, null, null);
|
2014-02-25 03:50:42 -08:00
|
|
|
let perms = Services.perms;
|
2014-09-22 11:39:57 -07:00
|
|
|
if (aState.camera &&
|
2014-02-25 03:50:42 -08:00
|
|
|
perms.testExactPermission(uri, "camera") == perms.ALLOW_ACTION)
|
|
|
|
perms.remove(uri.host, "camera");
|
2014-09-22 11:39:57 -07:00
|
|
|
if (aState.microphone &&
|
2014-02-25 03:50:42 -08:00
|
|
|
perms.testExactPermission(uri, "microphone") == perms.ALLOW_ACTION)
|
|
|
|
perms.remove(uri.host, "microphone");
|
|
|
|
|
2014-09-22 11:39:57 -07:00
|
|
|
aBrowser.messageManager.sendAsyncMessage("webrtc:StopSharing", windowId);
|
2014-01-23 02:50:03 -08:00
|
|
|
}
|
|
|
|
}];
|
2013-03-01 01:28:01 -08:00
|
|
|
let options = {
|
2014-01-23 02:50:03 -08:00
|
|
|
hideNotNow: true,
|
2013-12-19 13:16:10 -08:00
|
|
|
dismissed: true,
|
2014-02-28 09:47:18 -08:00
|
|
|
eventCallback: function(aTopic) {
|
|
|
|
if (aTopic == "shown") {
|
|
|
|
let PopupNotifications = this.browser.ownerDocument.defaultView.PopupNotifications;
|
|
|
|
let popupId = captureState == "Microphone" ? "Microphone" : "Devices";
|
|
|
|
PopupNotifications.panel.firstChild.setAttribute("popupid", "webRTC-sharing" + popupId);
|
|
|
|
}
|
|
|
|
return aTopic == "swapping";
|
|
|
|
}
|
2013-03-01 01:28:01 -08:00
|
|
|
};
|
2014-07-18 03:14:29 -07:00
|
|
|
if (captureState) {
|
|
|
|
let anchorId = captureState == "Microphone" ? "webRTC-sharingMicrophone-notification-icon"
|
|
|
|
: "webRTC-sharingDevices-notification-icon";
|
|
|
|
let message = stringBundle.getString("getUserMedia.sharing" + captureState + ".message2");
|
|
|
|
chromeWin.PopupNotifications.show(aBrowser, "webRTC-sharingDevices", message,
|
|
|
|
anchorId, mainAction, secondaryActions, options);
|
|
|
|
}
|
2014-08-14 10:29:49 -07:00
|
|
|
else {
|
|
|
|
removeBrowserNotification(aBrowser,"webRTC-sharingDevices");
|
|
|
|
}
|
2014-07-18 03:14:29 -07:00
|
|
|
|
|
|
|
// Now handle the screen sharing indicator.
|
2014-09-22 11:39:57 -07:00
|
|
|
if (!aState.screen) {
|
2014-08-14 10:29:49 -07:00
|
|
|
removeBrowserNotification(aBrowser,"webRTC-sharingScreen");
|
2014-07-18 03:14:29 -07:00
|
|
|
return;
|
2014-08-14 10:29:49 -07:00
|
|
|
}
|
2014-07-18 03:14:29 -07:00
|
|
|
|
|
|
|
options = {
|
|
|
|
hideNotNow: true,
|
|
|
|
dismissed: true,
|
|
|
|
eventCallback: function(aTopic) {
|
|
|
|
if (aTopic == "shown") {
|
|
|
|
let PopupNotifications = this.browser.ownerDocument.defaultView.PopupNotifications;
|
|
|
|
PopupNotifications.panel.firstChild.setAttribute("popupid", "webRTC-sharingScreen");
|
|
|
|
}
|
|
|
|
return aTopic == "swapping";
|
|
|
|
}
|
|
|
|
};
|
2014-08-22 02:27:19 -07:00
|
|
|
secondaryActions = [{
|
|
|
|
label: stringBundle.getString("getUserMedia.stopSharing.label"),
|
|
|
|
accessKey: stringBundle.getString("getUserMedia.stopSharing.accesskey"),
|
|
|
|
callback: function () {
|
2014-09-22 11:39:57 -07:00
|
|
|
aBrowser.messageManager.sendAsyncMessage("webrtc:StopSharing",
|
|
|
|
"screen:" + windowId);
|
2014-08-22 02:27:19 -07:00
|
|
|
}
|
|
|
|
}];
|
2014-09-22 11:39:57 -07:00
|
|
|
// If we are sharing both a window and the screen, we show 'Screen'.
|
|
|
|
let stringId = "getUserMedia.sharing" + aState.screen;
|
2014-07-18 03:14:29 -07:00
|
|
|
chromeWin.PopupNotifications.show(aBrowser, "webRTC-sharingScreen",
|
2014-08-27 07:52:22 -07:00
|
|
|
stringBundle.getString(stringId + ".message"),
|
2014-07-18 03:14:29 -07:00
|
|
|
"webRTC-sharingScreen-notification-icon",
|
|
|
|
mainAction, secondaryActions, options);
|
2012-12-28 01:25:59 -08:00
|
|
|
}
|
2013-02-16 02:10:41 -08:00
|
|
|
|
2014-08-14 10:29:49 -07:00
|
|
|
function removeBrowserNotification(aBrowser, aNotificationId) {
|
|
|
|
let win = aBrowser.ownerDocument.defaultView;
|
|
|
|
let notification =
|
|
|
|
win.PopupNotifications.getNotification(aNotificationId, aBrowser);
|
|
|
|
if (notification)
|
|
|
|
win.PopupNotifications.remove(notification);
|
|
|
|
}
|