зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1037405 - implement the doorhanger prompting the user to share a screen/window, r=Gijs.
--HG-- extra : rebase_source : 394a06b14a7561ea1f43d3c7a8ce52ad4a4fe447
This commit is contained in:
Родитель
00baa84dff
Коммит
4d36509871
|
@ -18,6 +18,17 @@
|
|||
<menupopup id="webRTC-selectCamera-menupopup"/>
|
||||
</menulist>
|
||||
</popupnotificationcontent>
|
||||
|
||||
<popupnotificationcontent id="webRTC-selectWindowOrScreen" orient="vertical">
|
||||
<separator class="thin"/>
|
||||
<label value="&getUserMedia.selectWindowOrScreen.label;"
|
||||
accesskey="&getUserMedia.selectWindowOrScreen.accesskey;"
|
||||
control="webRTC-selectWindow-menulist"/>
|
||||
<menulist id="webRTC-selectWindow-menulist">
|
||||
<menupopup id="webRTC-selectWindow-menupopup"/>
|
||||
</menulist>
|
||||
</popupnotificationcontent>
|
||||
|
||||
<popupnotificationcontent id="webRTC-selectMicrophone" orient="vertical">
|
||||
<separator class="thin"/>
|
||||
<label value="&getUserMedia.selectMicrophone.label;"
|
||||
|
|
|
@ -709,6 +709,8 @@ just addresses the organization to follow, e.g. "This site is run by " -->
|
|||
|
||||
<!ENTITY getUserMedia.selectCamera.label "Camera to share:">
|
||||
<!ENTITY getUserMedia.selectCamera.accesskey "C">
|
||||
<!ENTITY getUserMedia.selectWindowOrScreen.label "Window or screen to share:">
|
||||
<!ENTITY getUserMedia.selectWindowOrScreen.accesskey "W">
|
||||
<!ENTITY getUserMedia.selectMicrophone.label "Microphone to share:">
|
||||
<!ENTITY getUserMedia.selectMicrophone.accesskey "M">
|
||||
|
||||
|
|
|
@ -484,16 +484,23 @@ identity.loggedIn.description = Signed in as: %S
|
|||
identity.loggedIn.signOut.label = Sign Out
|
||||
identity.loggedIn.signOut.accessKey = O
|
||||
|
||||
# LOCALIZATION NOTE (getUserMedia.shareCamera.message, getUserMedia.shareMicrophone.message, getUserMedia.shareCameraAndMicrophone.message): %S is the website origin (e.g. www.mozilla.org)
|
||||
# LOCALIZATION NOTE (getUserMedia.shareCamera.message, getUserMedia.shareMicrophone.message,
|
||||
# getUserMedia.shareScreen.message, getUserMedia.shareCameraAndMicrophone.message,
|
||||
# getUserMedia.shareScreenAndMicrophone.message):
|
||||
# %S is the website origin (e.g. www.mozilla.org)
|
||||
getUserMedia.shareCamera.message = Would you like to share your camera with %S?
|
||||
getUserMedia.shareMicrophone.message = Would you like to share your microphone with %S?
|
||||
getUserMedia.shareScreen.message = Would you like to share your screen with %S?
|
||||
getUserMedia.shareCameraAndMicrophone.message = Would you like to share your camera and microphone with %S?
|
||||
getUserMedia.shareScreenAndMicrophone.message = Would you like to share your microphone and screen with %S?
|
||||
getUserMedia.noVideo.label = No Video
|
||||
getUserMedia.noWindowOrScreen.label = No Window or Screen
|
||||
getUserMedia.noAudio.label = No Audio
|
||||
getUserMedia.shareEntireScreen.label = Entire screen
|
||||
# LOCALIZATION NOTE (getUserMedia.shareSelectedDevices.label):
|
||||
# Semicolon-separated list of plural forms. See:
|
||||
# http://developer.mozilla.org/en/docs/Localization_and_Plurals
|
||||
# The number of devices can be either one or two.
|
||||
getUserMedia.shareCamera.message = Would you like to share your camera with %S?
|
||||
getUserMedia.shareMicrophone.message = Would you like to share your microphone with %S?
|
||||
getUserMedia.shareCameraAndMicrophone.message = Would you like to share your camera and microphone with %S?
|
||||
getUserMedia.noVideo.label = No Video
|
||||
getUserMedia.noAudio.label = No Audio
|
||||
getUserMedia.shareSelectedDevices.label = Share Selected Device;Share Selected Devices
|
||||
getUserMedia.shareSelectedDevices.accesskey = S
|
||||
getUserMedia.always.label = Always Share
|
||||
|
|
|
@ -94,31 +94,36 @@ function denyRequest(aCallID, aError) {
|
|||
Services.obs.notifyObservers(msg, "getUserMedia:response:deny", aCallID);
|
||||
}
|
||||
|
||||
function prompt(aContentWindow, aCallID, aAudioRequested, aVideoRequested, aDevices, aSecure) {
|
||||
function prompt(aContentWindow, aCallID, aAudio, aVideo, aDevices, aSecure) {
|
||||
let audioDevices = [];
|
||||
let videoDevices = [];
|
||||
|
||||
// MediaStreamConstraints defines video as 'boolean or MediaTrackConstraints'.
|
||||
let sharingScreen = aVideo && typeof(aVideo) != "boolean" &&
|
||||
aVideo.mediaSource != "camera";
|
||||
for (let device of aDevices) {
|
||||
device = device.QueryInterface(Ci.nsIMediaDevice);
|
||||
switch (device.type) {
|
||||
case "audio":
|
||||
if (aAudioRequested)
|
||||
if (aAudio)
|
||||
audioDevices.push(device);
|
||||
break;
|
||||
case "video":
|
||||
if (aVideoRequested)
|
||||
// Verify that if we got a camera, we haven't requested a screen share,
|
||||
// or that if we requested a screen share we aren't getting a camera.
|
||||
if (aVideo && (device.mediaSource == "camera") != sharingScreen)
|
||||
videoDevices.push(device);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let requestType;
|
||||
if (audioDevices.length && videoDevices.length)
|
||||
requestType = "CameraAndMicrophone";
|
||||
else if (audioDevices.length)
|
||||
requestType = "Microphone";
|
||||
else if (videoDevices.length)
|
||||
requestType = "Camera";
|
||||
else {
|
||||
let requestTypes = [];
|
||||
if (videoDevices.length)
|
||||
requestTypes.push(sharingScreen ? "Screen" : "Camera");
|
||||
if (audioDevices.length)
|
||||
requestTypes.push("Microphone");
|
||||
|
||||
if (!requestTypes.length) {
|
||||
denyRequest(aCallID, "NO_DEVICES_FOUND");
|
||||
return;
|
||||
}
|
||||
|
@ -128,11 +133,11 @@ function prompt(aContentWindow, aCallID, aAudioRequested, aVideoRequested, aDevi
|
|||
let chromeDoc = browser.ownerDocument;
|
||||
let chromeWin = chromeDoc.defaultView;
|
||||
let stringBundle = chromeWin.gNavigatorBundle;
|
||||
let message = stringBundle.getFormattedString("getUserMedia.share" + requestType + ".message",
|
||||
[ uri.host ]);
|
||||
let stringId = "getUserMedia.share" + requestTypes.join("And") + ".message";
|
||||
let message = stringBundle.getFormattedString(stringId, [uri.host]);
|
||||
|
||||
let mainAction = {
|
||||
label: PluralForm.get(requestType == "CameraAndMicrophone" ? 2 : 1,
|
||||
label: PluralForm.get(requestTypes.length,
|
||||
stringBundle.getString("getUserMedia.shareSelectedDevices.label")),
|
||||
accessKey: stringBundle.getString("getUserMedia.shareSelectedDevices.accesskey"),
|
||||
// The real callback will be set during the "showing" event. The
|
||||
|
@ -148,8 +153,11 @@ function prompt(aContentWindow, aCallID, aAudioRequested, aVideoRequested, aDevi
|
|||
callback: function () {
|
||||
denyRequest(aCallID);
|
||||
}
|
||||
},
|
||||
{
|
||||
}
|
||||
];
|
||||
|
||||
if (!sharingScreen) { // Bug 1037438: implement 'never' for screen sharing.
|
||||
secondaryActions.push({
|
||||
label: stringBundle.getString("getUserMedia.never.label"),
|
||||
accessKey: stringBundle.getString("getUserMedia.never.accesskey"),
|
||||
callback: function () {
|
||||
|
@ -162,11 +170,13 @@ function prompt(aContentWindow, aCallID, aAudioRequested, aVideoRequested, aDevi
|
|||
if (videoDevices.length)
|
||||
perms.add(uri, "camera", perms.DENY_ACTION);
|
||||
}
|
||||
});
|
||||
}
|
||||
];
|
||||
|
||||
if (aSecure) {
|
||||
// Don't show the 'Always' action if the connection isn't secure.
|
||||
if (aSecure && !sharingScreen) {
|
||||
// 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).
|
||||
secondaryActions.unshift({
|
||||
label: stringBundle.getString("getUserMedia.always.label"),
|
||||
accessKey: stringBundle.getString("getUserMedia.always.accesskey"),
|
||||
|
@ -185,7 +195,9 @@ function prompt(aContentWindow, aCallID, aAudioRequested, aVideoRequested, aDevi
|
|||
|
||||
if (aTopic == "shown") {
|
||||
let PopupNotifications = chromeDoc.defaultView.PopupNotifications;
|
||||
let popupId = requestType == "Microphone" ? "Microphone" : "Devices";
|
||||
let popupId = "Devices";
|
||||
if (requestTypes.length == 1 && requestTypes[0] == "Microphone")
|
||||
popupId = "Microphone";
|
||||
PopupNotifications.panel.firstChild.setAttribute("popupid", "webRTC-share" + popupId);
|
||||
}
|
||||
|
||||
|
@ -206,6 +218,10 @@ function prompt(aContentWindow, aCallID, aAudioRequested, aVideoRequested, aDevi
|
|||
if (camPerm == perms.PROMPT_ACTION)
|
||||
camPerm = perms.UNKNOWN_ACTION;
|
||||
|
||||
// Screen sharing shouldn't follow the camera permissions.
|
||||
if (videoDevices.length && sharingScreen)
|
||||
camPerm = perms.UNKNOWN_ACTION;
|
||||
|
||||
// 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,
|
||||
|
@ -235,6 +251,40 @@ function prompt(aContentWindow, aCallID, aAudioRequested, aVideoRequested, aDevi
|
|||
}
|
||||
}
|
||||
|
||||
function listScreenShareDevices(menupopup, devices) {
|
||||
while (menupopup.lastChild)
|
||||
menupopup.removeChild(menupopup.lastChild);
|
||||
|
||||
// "No Window or Screen" is the default because we can't pick a
|
||||
// 'default' window to share.
|
||||
addDeviceToList(menupopup,
|
||||
stringBundle.getString("getUserMedia.noWindowOrScreen.label"),
|
||||
"-1");
|
||||
|
||||
// Then add the 'Entire screen' item if mozGetUserMediaDevices returned it.
|
||||
for (let i = 0; i < devices.length; ++i) {
|
||||
if (devices[i].mediaSource == "screen") {
|
||||
menupopup.appendChild(chromeDoc.createElement("menuseparator"));
|
||||
addDeviceToList(menupopup,
|
||||
stringBundle.getString("getUserMedia.shareEntireScreen.label"),
|
||||
i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Finally add all the window names.
|
||||
let separatorNeeded = true;
|
||||
for (let i = 0; i < devices.length; ++i) {
|
||||
if (devices[i].mediaSource == "window") {
|
||||
if (separatorNeeded) {
|
||||
menupopup.appendChild(chromeDoc.createElement("menuseparator"));
|
||||
separatorNeeded = false;
|
||||
}
|
||||
addDeviceToList(menupopup, devices[i].name, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addDeviceToList(menupopup, deviceName, deviceIndex) {
|
||||
let menuitem = chromeDoc.createElement("menuitem");
|
||||
menuitem.setAttribute("value", deviceIndex);
|
||||
|
@ -243,15 +293,21 @@ function prompt(aContentWindow, aCallID, aAudioRequested, aVideoRequested, aDevi
|
|||
menupopup.appendChild(menuitem);
|
||||
}
|
||||
|
||||
chromeDoc.getElementById("webRTC-selectCamera").hidden = !videoDevices.length;
|
||||
chromeDoc.getElementById("webRTC-selectCamera").hidden = !videoDevices.length || sharingScreen;
|
||||
chromeDoc.getElementById("webRTC-selectWindowOrScreen").hidden = !sharingScreen || !videoDevices.length;
|
||||
chromeDoc.getElementById("webRTC-selectMicrophone").hidden = !audioDevices.length;
|
||||
|
||||
let camMenupopup = chromeDoc.getElementById("webRTC-selectCamera-menupopup");
|
||||
let windowMenupopup = chromeDoc.getElementById("webRTC-selectWindow-menupopup");
|
||||
let micMenupopup = chromeDoc.getElementById("webRTC-selectMicrophone-menupopup");
|
||||
if (sharingScreen)
|
||||
listScreenShareDevices(windowMenupopup, videoDevices);
|
||||
else
|
||||
listDevices(camMenupopup, videoDevices);
|
||||
listDevices(micMenupopup, audioDevices);
|
||||
if (requestType == "CameraAndMicrophone") {
|
||||
if (requestTypes.length == 2) {
|
||||
let stringBundle = chromeDoc.defaultView.gNavigatorBundle;
|
||||
if (!sharingScreen)
|
||||
addDeviceToList(camMenupopup, stringBundle.getString("getUserMedia.noVideo.label"), "-1");
|
||||
addDeviceToList(micMenupopup, stringBundle.getString("getUserMedia.noAudio.label"), "-1");
|
||||
}
|
||||
|
@ -261,7 +317,8 @@ function prompt(aContentWindow, aCallID, aAudioRequested, aVideoRequested, aDevi
|
|||
.createInstance(Ci.nsISupportsArray);
|
||||
let perms = Services.perms;
|
||||
if (videoDevices.length) {
|
||||
let videoDeviceIndex = chromeDoc.getElementById("webRTC-selectCamera-menulist").value;
|
||||
let listId = "webRTC-select" + (sharingScreen ? "Window" : "Camera") + "-menulist";
|
||||
let videoDeviceIndex = chromeDoc.getElementById(listId).value;
|
||||
let allowCamera = videoDeviceIndex != "-1";
|
||||
if (allowCamera)
|
||||
allowedDevices.AppendElement(videoDevices[videoDeviceIndex]);
|
||||
|
@ -292,8 +349,9 @@ function prompt(aContentWindow, aCallID, aAudioRequested, aVideoRequested, aDevi
|
|||
}
|
||||
};
|
||||
|
||||
let anchorId = requestType == "Microphone" ? "webRTC-shareMicrophone-notification-icon"
|
||||
: "webRTC-shareDevices-notification-icon";
|
||||
let anchorId = "webRTC-shareDevices-notification-icon";
|
||||
if (requestTypes.length == 1 && requestTypes[0] == "Microphone")
|
||||
anchorId = "webRTC-shareMicrophone-notification-icon";
|
||||
chromeWin.PopupNotifications.show(browser, "webRTC-shareDevices", message,
|
||||
anchorId, mainAction, secondaryActions, options);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче