mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1015486 Bypass the video and audio permission prompts for Loop, as Loop will provide its own mechanisms. Patch by abr, tests by Standard8. r=jesup,r=florian
This commit is contained in:
parent
73ef4ef1b2
commit
a130efd232
@ -282,7 +282,9 @@ skip-if = e10s # Bug ????? - thumbnail captures need e10s love (tabPreviews_capt
|
|||||||
[browser_datareporting_notification.js]
|
[browser_datareporting_notification.js]
|
||||||
run-if = datareporting
|
run-if = datareporting
|
||||||
[browser_devices_get_user_media.js]
|
[browser_devices_get_user_media.js]
|
||||||
skip-if = (os == "linux" && debug) || e10s # linux: bug 976544; e10s: Bug ?????? - appears user media notifications only happen in the child and don't make their way to the parent?
|
skip-if = (os == "linux" && debug) || e10s # linux: bug 976544; e10s: Bug 973001 - appears user media notifications only happen in the child and don't make their way to the parent?
|
||||||
|
[browser_devices_get_user_media_about_urls.js]
|
||||||
|
skip-if = e10s # Bug 973001 - appears user media notifications only happen in the child and don't make their way to the parent?
|
||||||
[browser_discovery.js]
|
[browser_discovery.js]
|
||||||
skip-if = e10s # Bug 918663 - DOMLinkAdded events don't make their way to chrome
|
skip-if = e10s # Bug 918663 - DOMLinkAdded events don't make their way to chrome
|
||||||
[browser_duplicateIDs.js]
|
[browser_duplicateIDs.js]
|
||||||
|
@ -0,0 +1,260 @@
|
|||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
const kObservedTopics = [
|
||||||
|
"getUserMedia:response:allow",
|
||||||
|
"getUserMedia:revoke",
|
||||||
|
"getUserMedia:response:deny",
|
||||||
|
"getUserMedia:request",
|
||||||
|
"recording-device-events",
|
||||||
|
"recording-window-ended"
|
||||||
|
];
|
||||||
|
|
||||||
|
const PREF_PERMISSION_FAKE = "media.navigator.permission.fake";
|
||||||
|
|
||||||
|
|
||||||
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
XPCOMUtils.defineLazyServiceGetter(this, "MediaManagerService",
|
||||||
|
"@mozilla.org/mediaManagerService;1",
|
||||||
|
"nsIMediaManagerService");
|
||||||
|
|
||||||
|
var gTab;
|
||||||
|
|
||||||
|
var gObservedTopics = {};
|
||||||
|
function observer(aSubject, aTopic, aData) {
|
||||||
|
if (!(aTopic in gObservedTopics))
|
||||||
|
gObservedTopics[aTopic] = 1;
|
||||||
|
else
|
||||||
|
++gObservedTopics[aTopic];
|
||||||
|
}
|
||||||
|
|
||||||
|
function promiseObserverCalled(aTopic, aAction) {
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
info("Waiting for " + aTopic);
|
||||||
|
|
||||||
|
Services.obs.addObserver(function observer(aSubject, topic, aData) {
|
||||||
|
ok(true, "got " + aTopic + " notification");
|
||||||
|
info("Message: " + aData);
|
||||||
|
Services.obs.removeObserver(observer, aTopic);
|
||||||
|
|
||||||
|
if (kObservedTopics.indexOf(aTopic) != -1) {
|
||||||
|
if (!(aTopic in gObservedTopics))
|
||||||
|
gObservedTopics[aTopic] = -1;
|
||||||
|
else
|
||||||
|
--gObservedTopics[aTopic];
|
||||||
|
}
|
||||||
|
|
||||||
|
deferred.resolve();
|
||||||
|
}, aTopic, false);
|
||||||
|
|
||||||
|
if (aAction)
|
||||||
|
aAction();
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function promisePopupNotification(aName) {
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
|
||||||
|
waitForCondition(() => PopupNotifications.getNotification(aName),
|
||||||
|
() => {
|
||||||
|
ok(!!PopupNotifications.getNotification(aName),
|
||||||
|
aName + " notification appeared");
|
||||||
|
|
||||||
|
deferred.resolve();
|
||||||
|
}, "timeout waiting for popup notification " + aName);
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function promiseNoPopupNotification(aName) {
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
info("Waiting for " + aName + " to be removed");
|
||||||
|
|
||||||
|
waitForCondition(() => !PopupNotifications.getNotification(aName),
|
||||||
|
() => {
|
||||||
|
ok(!PopupNotifications.getNotification(aName),
|
||||||
|
aName + " notification removed");
|
||||||
|
deferred.resolve();
|
||||||
|
}, "timeout waiting for popup notification " + aName + " to disappear");
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function expectObserverCalled(aTopic) {
|
||||||
|
is(gObservedTopics[aTopic], 1, "expected notification " + aTopic);
|
||||||
|
if (aTopic in gObservedTopics)
|
||||||
|
--gObservedTopics[aTopic];
|
||||||
|
}
|
||||||
|
|
||||||
|
function expectNoObserverCalled() {
|
||||||
|
for (let topic in gObservedTopics) {
|
||||||
|
if (gObservedTopics[topic])
|
||||||
|
is(gObservedTopics[topic], 0, topic + " notification unexpected");
|
||||||
|
}
|
||||||
|
gObservedTopics = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMediaCaptureState() {
|
||||||
|
let hasVideo = {};
|
||||||
|
let hasAudio = {};
|
||||||
|
MediaManagerService.mediaCaptureWindowState(content, hasVideo, hasAudio);
|
||||||
|
if (hasVideo.value && hasAudio.value)
|
||||||
|
return "CameraAndMicrophone";
|
||||||
|
if (hasVideo.value)
|
||||||
|
return "Camera";
|
||||||
|
if (hasAudio.value)
|
||||||
|
return "Microphone";
|
||||||
|
return "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeStream(aAlreadyClosed) {
|
||||||
|
expectNoObserverCalled();
|
||||||
|
|
||||||
|
info("closing the stream");
|
||||||
|
content.wrappedJSObject.closeStream();
|
||||||
|
|
||||||
|
if (!aAlreadyClosed)
|
||||||
|
yield promiseObserverCalled("recording-device-events");
|
||||||
|
|
||||||
|
yield promiseNoPopupNotification("webRTC-sharingDevices");
|
||||||
|
if (!aAlreadyClosed)
|
||||||
|
expectObserverCalled("recording-window-ended");
|
||||||
|
|
||||||
|
let statusButton = document.getElementById("webrtc-status-button");
|
||||||
|
ok(statusButton.hidden, "WebRTC status button hidden");
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadPage(aUrl) {
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
|
||||||
|
gTab.linkedBrowser.addEventListener("load", function onload() {
|
||||||
|
gTab.linkedBrowser.removeEventListener("load", onload, true);
|
||||||
|
|
||||||
|
is(PopupNotifications._currentNotifications.length, 0,
|
||||||
|
"should start the test without any prior popup notification");
|
||||||
|
|
||||||
|
deferred.resolve();
|
||||||
|
}, true);
|
||||||
|
content.location = aUrl;
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A fake about module to map get_user_media.html to different about urls.
|
||||||
|
function fakeLoopAboutModule() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fakeLoopAboutModule.prototype = {
|
||||||
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule]),
|
||||||
|
newChannel: function (aURI) {
|
||||||
|
let rootDir = getRootDirectory(gTestPath);
|
||||||
|
let chan = Services.io.newChannel(rootDir + "get_user_media.html", null, null);
|
||||||
|
chan.owner = Services.scriptSecurityManager.getSystemPrincipal();
|
||||||
|
return chan;
|
||||||
|
},
|
||||||
|
getURIFlags: function (aURI) {
|
||||||
|
return Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||||
|
Ci.nsIAboutModule.ALLOW_SCRIPT |
|
||||||
|
Ci.nsIAboutModule.HIDE_FROM_ABOUTABOUT;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let factory = XPCOMUtils._getFactory(fakeLoopAboutModule);
|
||||||
|
let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
|
||||||
|
|
||||||
|
registerCleanupFunction(function() {
|
||||||
|
gBrowser.removeCurrentTab();
|
||||||
|
kObservedTopics.forEach(topic => {
|
||||||
|
Services.obs.removeObserver(observer, topic);
|
||||||
|
});
|
||||||
|
Services.prefs.clearUserPref(PREF_PERMISSION_FAKE);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
let gTests = [
|
||||||
|
|
||||||
|
{
|
||||||
|
desc: "getUserMedia about:loopconversation shouldn't prompt",
|
||||||
|
run: function checkAudioVideoLoop() {
|
||||||
|
let classID = Cc["@mozilla.org/uuid-generator;1"]
|
||||||
|
.getService(Ci.nsIUUIDGenerator).generateUUID();
|
||||||
|
registrar.registerFactory(classID, "",
|
||||||
|
"@mozilla.org/network/protocol/about;1?what=loopconversation",
|
||||||
|
factory);
|
||||||
|
|
||||||
|
yield loadPage("about:loopconversation");
|
||||||
|
|
||||||
|
yield promiseObserverCalled("recording-device-events", () => {
|
||||||
|
info("requesting devices");
|
||||||
|
content.wrappedJSObject.requestDevice(true, true);
|
||||||
|
});
|
||||||
|
// Wait for the devices to actually be captured and running before
|
||||||
|
// proceeding.
|
||||||
|
yield promisePopupNotification("webRTC-sharingDevices");
|
||||||
|
|
||||||
|
is(getMediaCaptureState(), "CameraAndMicrophone",
|
||||||
|
"expected camera and microphone to be shared");
|
||||||
|
|
||||||
|
yield closeStream();
|
||||||
|
|
||||||
|
registrar.unregisterFactory(classID, factory);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
desc: "getUserMedia about:evil should prompt",
|
||||||
|
run: function checkAudioVideoNonLoop() {
|
||||||
|
let classID = Cc["@mozilla.org/uuid-generator;1"]
|
||||||
|
.getService(Ci.nsIUUIDGenerator).generateUUID();
|
||||||
|
registrar.registerFactory(classID, "",
|
||||||
|
"@mozilla.org/network/protocol/about;1?what=evil",
|
||||||
|
factory);
|
||||||
|
|
||||||
|
yield loadPage("about:evil");
|
||||||
|
|
||||||
|
yield promiseObserverCalled("getUserMedia:request", () => {
|
||||||
|
info("requesting devices");
|
||||||
|
content.wrappedJSObject.requestDevice(true, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
isnot(getMediaCaptureState(), "CameraAndMicrophone",
|
||||||
|
"expected camera and microphone not to be shared");
|
||||||
|
|
||||||
|
registrar.unregisterFactory(classID, factory);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
waitForExplicitFinish();
|
||||||
|
|
||||||
|
Services.prefs.setBoolPref(PREF_PERMISSION_FAKE, true);
|
||||||
|
|
||||||
|
gTab = gBrowser.addTab();
|
||||||
|
gBrowser.selectedTab = gTab;
|
||||||
|
|
||||||
|
kObservedTopics.forEach(topic => {
|
||||||
|
Services.obs.addObserver(observer, topic, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
Task.spawn(function () {
|
||||||
|
for (let test of gTests) {
|
||||||
|
info(test.desc);
|
||||||
|
yield test.run();
|
||||||
|
|
||||||
|
// Cleanup before the next test
|
||||||
|
expectNoObserverCalled();
|
||||||
|
}
|
||||||
|
}).then(finish, ex => {
|
||||||
|
ok(false, "Unexpected Exception: " + ex);
|
||||||
|
finish();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function wait(time) {
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
setTimeout(deferred.resolve, time);
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
@ -24,6 +24,7 @@ EXTRA_JS_MODULES += [
|
|||||||
'Social.jsm',
|
'Social.jsm',
|
||||||
'TabCrashReporter.jsm',
|
'TabCrashReporter.jsm',
|
||||||
'WebappManager.jsm',
|
'WebappManager.jsm',
|
||||||
|
'webrtcUI.jsm',
|
||||||
]
|
]
|
||||||
|
|
||||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||||
@ -42,7 +43,6 @@ EXTRA_PP_JS_MODULES += [
|
|||||||
'AboutHome.jsm',
|
'AboutHome.jsm',
|
||||||
'RecentWindow.jsm',
|
'RecentWindow.jsm',
|
||||||
'UITour.jsm',
|
'UITour.jsm',
|
||||||
'webrtcUI.jsm',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
if CONFIG['MOZILLA_OFFICIAL']:
|
if CONFIG['MOZILLA_OFFICIAL']:
|
||||||
|
@ -128,28 +128,8 @@ function prompt(aContentWindow, aCallID, aAudioRequested, aVideoRequested, aDevi
|
|||||||
let chromeDoc = browser.ownerDocument;
|
let chromeDoc = browser.ownerDocument;
|
||||||
let chromeWin = chromeDoc.defaultView;
|
let chromeWin = chromeDoc.defaultView;
|
||||||
let stringBundle = chromeWin.gNavigatorBundle;
|
let stringBundle = chromeWin.gNavigatorBundle;
|
||||||
#ifdef MOZ_LOOP
|
|
||||||
let host;
|
|
||||||
// For Loop protocols that start with about:, use brandShortName instead of the host for now.
|
|
||||||
// Bug 990678 will implement improvements/replacements for the permissions dialog, so this
|
|
||||||
// should become unnecessary.
|
|
||||||
if (uri.spec.startsWith("about:loop")) {
|
|
||||||
let brandBundle = Services.strings.createBundle("chrome://branding/locale/brand.properties");
|
|
||||||
|
|
||||||
host = brandBundle.GetStringFromName("brandShortName");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// uri.host throws for about: protocols, so we have to do this once we know
|
|
||||||
// it isn't about:loop.
|
|
||||||
host = uri.host;
|
|
||||||
}
|
|
||||||
|
|
||||||
let message = stringBundle.getFormattedString("getUserMedia.share" + requestType + ".message",
|
|
||||||
[ host ]);
|
|
||||||
#else
|
|
||||||
let message = stringBundle.getFormattedString("getUserMedia.share" + requestType + ".message",
|
let message = stringBundle.getFormattedString("getUserMedia.share" + requestType + ".message",
|
||||||
[ uri.host ]);
|
[ uri.host ]);
|
||||||
#endif
|
|
||||||
|
|
||||||
let mainAction = {
|
let mainAction = {
|
||||||
label: PluralForm.get(requestType == "CameraAndMicrophone" ? 2 : 1,
|
label: PluralForm.get(requestType == "CameraAndMicrophone" ? 2 : 1,
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "nsIDocument.h"
|
#include "nsIDocument.h"
|
||||||
#include "nsISupportsPrimitives.h"
|
#include "nsISupportsPrimitives.h"
|
||||||
#include "nsIInterfaceRequestorUtils.h"
|
#include "nsIInterfaceRequestorUtils.h"
|
||||||
|
#include "nsNetUtil.h"
|
||||||
#include "mozilla/Types.h"
|
#include "mozilla/Types.h"
|
||||||
#include "mozilla/PeerIdentity.h"
|
#include "mozilla/PeerIdentity.h"
|
||||||
#include "mozilla/dom/ContentChild.h"
|
#include "mozilla/dom/ContentChild.h"
|
||||||
@ -1477,13 +1478,28 @@ MediaManager::GetUserMedia(bool aPrivileged,
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
nsIURI* docURI = aWindow->GetDocumentURI();
|
||||||
|
#ifdef MOZ_LOOP
|
||||||
|
{
|
||||||
|
bool isLoop = false;
|
||||||
|
nsCOMPtr<nsIURI> loopURI;
|
||||||
|
nsresult rv = NS_NewURI(getter_AddRefs(loopURI), "about:loopconversation");
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
rv = docURI->EqualsExceptRef(loopURI, &isLoop);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
if (isLoop) {
|
||||||
|
aPrivileged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// XXX No full support for picture in Desktop yet (needs proper UI)
|
// XXX No full support for picture in Desktop yet (needs proper UI)
|
||||||
if (aPrivileged ||
|
if (aPrivileged ||
|
||||||
(c.mFake && !Preferences::GetBool("media.navigator.permission.fake"))) {
|
(c.mFake && !Preferences::GetBool("media.navigator.permission.fake"))) {
|
||||||
mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
|
mMediaThread->Dispatch(runnable, NS_DISPATCH_NORMAL);
|
||||||
} else {
|
} else {
|
||||||
bool isHTTPS = false;
|
bool isHTTPS = false;
|
||||||
nsIURI* docURI = aWindow->GetDocumentURI();
|
|
||||||
if (docURI) {
|
if (docURI) {
|
||||||
docURI->SchemeIs("https", &isHTTPS);
|
docURI->SchemeIs("https", &isHTTPS);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user