mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-22 18:32:00 +00:00
Bug 1033885 - return MediaStreamError instead of error strings, to spec. r=bz, r=jesup
This commit is contained in:
parent
d7d2397713
commit
54d43d8dad
@ -43,7 +43,7 @@ function runNext() {
|
||||
ok(false, 'unexpected success, permission request should be denied');
|
||||
runNext();
|
||||
}, function failure(err) {
|
||||
is(err.toLowerCase(), 'permission denied', 'expected permission denied');
|
||||
is(err.name, 'PermissionDeniedError', 'expected permission denied');
|
||||
runNext();
|
||||
});
|
||||
} else {
|
||||
|
@ -223,6 +223,8 @@ function checkNotSharing() {
|
||||
assertWebRTCIndicatorStatus(null);
|
||||
}
|
||||
|
||||
const permissionError = "error: PermissionDeniedError: The user did not grant permission for the operation.";
|
||||
|
||||
let gTests = [
|
||||
|
||||
{
|
||||
@ -381,7 +383,7 @@ let gTests = [
|
||||
enableDevice("Camera", false);
|
||||
enableDevice("Microphone", false);
|
||||
|
||||
yield promiseMessage("error: PERMISSION_DENIED", () => {
|
||||
yield promiseMessage(permissionError, () => {
|
||||
PopupNotifications.panel.firstChild.button.click();
|
||||
});
|
||||
|
||||
@ -405,7 +407,7 @@ let gTests = [
|
||||
expectObserverCalled("getUserMedia:request");
|
||||
checkDeviceSelectors(true, true);
|
||||
|
||||
yield promiseMessage("error: PERMISSION_DENIED", () => {
|
||||
yield promiseMessage(permissionError, () => {
|
||||
activateSecondaryAction(kActionDeny);
|
||||
});
|
||||
|
||||
@ -482,7 +484,7 @@ let gTests = [
|
||||
enableDevice("Camera", aAllowVideo || aNever);
|
||||
|
||||
let expectedMessage =
|
||||
(aAllowVideo || aAllowAudio) ? "ok" : "error: PERMISSION_DENIED";
|
||||
(aAllowVideo || aAllowAudio) ? "ok" : permissionError;
|
||||
yield promiseMessage(expectedMessage, () => {
|
||||
activateSecondaryAction(aNever ? kActionNever : kActionAlways);
|
||||
});
|
||||
@ -587,14 +589,14 @@ let gTests = [
|
||||
expectObserverCalled("getUserMedia:request");
|
||||
|
||||
// Deny the request to cleanup...
|
||||
yield promiseMessage("error: PERMISSION_DENIED", () => {
|
||||
yield promiseMessage(permissionError, () => {
|
||||
activateSecondaryAction(kActionDeny);
|
||||
});
|
||||
expectObserverCalled("getUserMedia:response:deny");
|
||||
expectObserverCalled("recording-window-ended");
|
||||
}
|
||||
else {
|
||||
let expectedMessage = aExpectStream ? "ok" : "error: PERMISSION_DENIED";
|
||||
let expectedMessage = aExpectStream ? "ok" : permissionError;
|
||||
yield promiseMessage(expectedMessage, gum);
|
||||
|
||||
if (expectedMessage == "ok") {
|
||||
|
@ -64,7 +64,7 @@ function handleRequest(aSubject, aTopic, aData) {
|
||||
constraints, devices, secure);
|
||||
},
|
||||
function (error) {
|
||||
// bug 827146 -- In the future, the UI should catch NO_DEVICES_FOUND
|
||||
// bug 827146 -- In the future, the UI should catch NotFoundError
|
||||
// and allow the user to plug in a device, instead of immediately failing.
|
||||
denyRequest({callID: aSubject.callID}, error);
|
||||
},
|
||||
@ -108,7 +108,7 @@ function prompt(aContentWindow, aWindowID, aCallID, aConstraints, aDevices, aSec
|
||||
requestTypes.push("Microphone");
|
||||
|
||||
if (!requestTypes.length) {
|
||||
denyRequest({callID: aCallID}, "NO_DEVICES_FOUND");
|
||||
denyRequest({callID: aCallID}, "NotFoundError");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -102,6 +102,7 @@ GetMediaManagerLog()
|
||||
using dom::MediaStreamConstraints; // Outside API (contains JSObject)
|
||||
using dom::MediaTrackConstraintSet; // Mandatory or optional constraints
|
||||
using dom::MediaTrackConstraints; // Raw mMandatory (as JSObject)
|
||||
using dom::MediaStreamError;
|
||||
using dom::GetUserMediaRequest;
|
||||
using dom::Sequence;
|
||||
using dom::OwningBooleanOrMediaTrackConstraints;
|
||||
@ -196,8 +197,9 @@ HostHasPermission(nsIURI &docURI)
|
||||
ErrorCallbackRunnable::ErrorCallbackRunnable(
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aOnSuccess,
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
|
||||
const nsAString& aErrorMsg, uint64_t aWindowID)
|
||||
: mErrorMsg(aErrorMsg)
|
||||
MediaMgrError& aError,
|
||||
uint64_t aWindowID)
|
||||
: mError(&aError)
|
||||
, mWindowID(aWindowID)
|
||||
, mManager(MediaManager::GetInstance())
|
||||
{
|
||||
@ -224,7 +226,11 @@ ErrorCallbackRunnable::Run()
|
||||
}
|
||||
// This is safe since we're on main-thread, and the windowlist can only
|
||||
// be invalidated from the main-thread (see OnNavigation)
|
||||
onFailure->OnError(mErrorMsg);
|
||||
nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(mWindowID);
|
||||
if (window) {
|
||||
nsRefPtr<MediaStreamError> error = new MediaStreamError(window, *mError);
|
||||
onFailure->OnError(error);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -315,7 +321,12 @@ public:
|
||||
// We should in the future return an empty array, and dynamically add
|
||||
// devices to the dropdowns if things are hotplugged while the
|
||||
// requester is up.
|
||||
mOnFailure->OnError(NS_LITERAL_STRING("NO_DEVICES_FOUND"));
|
||||
nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(mWindowID);
|
||||
if (window) {
|
||||
nsRefPtr<MediaStreamError> error = new MediaStreamError(window,
|
||||
NS_LITERAL_STRING("NotFoundError"));
|
||||
mOnFailure->OnError(error);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -830,9 +841,16 @@ public:
|
||||
nsDOMUserMediaStream::CreateTrackUnionStream(window, mListener,
|
||||
mAudioSource, mVideoSource);
|
||||
if (!trackunion) {
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error = mOnFailure.forget();
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure = mOnFailure.forget();
|
||||
LOG(("Returning error for getUserMedia() - no stream"));
|
||||
error->OnError(NS_LITERAL_STRING("NO_STREAM"));
|
||||
|
||||
nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(mWindowID);
|
||||
if (window) {
|
||||
nsRefPtr<MediaStreamError> error = new MediaStreamError(window,
|
||||
NS_LITERAL_STRING("InternalError"),
|
||||
NS_LITERAL_STRING("No stream."));
|
||||
onFailure->OnError(error);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
trackunion->AudioConfig(aec_on, (uint32_t) aec,
|
||||
@ -1097,9 +1115,11 @@ public:
|
||||
}
|
||||
|
||||
void
|
||||
Fail(const nsAString& aMessage) {
|
||||
Fail(const nsAString& aName,
|
||||
const nsAString& aMessage = EmptyString()) {
|
||||
nsRefPtr<MediaMgrError> error = new MediaMgrError(aName, aMessage);
|
||||
nsRefPtr<ErrorCallbackRunnable> runnable =
|
||||
new ErrorCallbackRunnable(mOnSuccess, mOnFailure, aMessage, mWindowID);
|
||||
new ErrorCallbackRunnable(mOnSuccess, mOnFailure, *error, mWindowID);
|
||||
// These should be empty now
|
||||
MOZ_ASSERT(!mOnSuccess);
|
||||
MOZ_ASSERT(!mOnFailure);
|
||||
@ -1136,7 +1156,8 @@ public:
|
||||
}
|
||||
|
||||
nsresult
|
||||
Denied(const nsAString& aErrorMsg)
|
||||
Denied(const nsAString& aName,
|
||||
const nsAString& aMessage = EmptyString())
|
||||
{
|
||||
MOZ_ASSERT(mOnSuccess);
|
||||
MOZ_ASSERT(mOnFailure);
|
||||
@ -1148,15 +1169,20 @@ public:
|
||||
// be invalidated from the main-thread (see OnNavigation)
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onSuccess = mOnSuccess.forget();
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onFailure = mOnFailure.forget();
|
||||
onFailure->OnError(aErrorMsg);
|
||||
|
||||
nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(mWindowID);
|
||||
if (window) {
|
||||
nsRefPtr<MediaStreamError> error = new MediaStreamError(window,
|
||||
aName, aMessage);
|
||||
onFailure->OnError(error);
|
||||
}
|
||||
// Should happen *after* error runs for consistency, but may not matter
|
||||
nsRefPtr<MediaManager> manager(MediaManager::GetInstance());
|
||||
manager->RemoveFromWindowList(mWindowID, mListener);
|
||||
} else {
|
||||
// This will re-check the window being alive on main-thread
|
||||
// Note: we must remove the listener on MainThread as well
|
||||
Fail(aErrorMsg);
|
||||
Fail(aName, aMessage);
|
||||
|
||||
// MUST happen after ErrorCallbackRunnable Run()s, as it checks the active window list
|
||||
NS_DispatchToMainThread(new GetUserMediaListenerRemove(mWindowID, mListener));
|
||||
@ -1202,7 +1228,7 @@ public:
|
||||
GetSources(backend, constraints, &MediaEngine::EnumerateVideoDevices, sources);
|
||||
|
||||
if (!sources.Length()) {
|
||||
Fail(NS_LITERAL_STRING("NO_DEVICES_FOUND"));
|
||||
Fail(NS_LITERAL_STRING("NotFoundError"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// Pick the first available device.
|
||||
@ -1215,7 +1241,7 @@ public:
|
||||
GetSources(backend, constraints, &MediaEngine::EnumerateAudioDevices, sources);
|
||||
|
||||
if (!sources.Length()) {
|
||||
Fail(NS_LITERAL_STRING("NO_DEVICES_FOUND"));
|
||||
Fail(NS_LITERAL_STRING("NotFoundError"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// Pick the first available device.
|
||||
@ -1241,7 +1267,8 @@ public:
|
||||
rv = aAudioSource->Allocate(GetInvariant(mConstraints.mAudio), mPrefs);
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("Failed to allocate audiosource %d",rv));
|
||||
Fail(NS_LITERAL_STRING("HARDWARE_UNAVAILABLE"));
|
||||
Fail(NS_LITERAL_STRING("SourceUnavailableError"),
|
||||
NS_LITERAL_STRING("Failed to allocate audiosource"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1252,7 +1279,8 @@ public:
|
||||
if (aAudioSource) {
|
||||
aAudioSource->Deallocate();
|
||||
}
|
||||
Fail(NS_LITERAL_STRING("HARDWARE_UNAVAILABLE"));
|
||||
Fail(NS_LITERAL_STRING("SourceUnavailableError"),
|
||||
NS_LITERAL_STRING("Failed to allocate videosource"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1655,10 +1683,10 @@ MediaManager::GetUserMedia(
|
||||
if (tc.mMediaSource != dom::MediaSourceEnum::Camera) {
|
||||
if (tc.mMediaSource == dom::MediaSourceEnum::Browser) {
|
||||
if (!Preferences::GetBool("media.getusermedia.browser.enabled", false)) {
|
||||
return task->Denied(NS_LITERAL_STRING("PERMISSION_DENIED"));
|
||||
return task->Denied(NS_LITERAL_STRING("PermissionDeniedError"));
|
||||
}
|
||||
} else if (!Preferences::GetBool("media.getusermedia.screensharing.enabled", false)) {
|
||||
return task->Denied(NS_LITERAL_STRING("PERMISSION_DENIED"));
|
||||
return task->Denied(NS_LITERAL_STRING("PermissionDeniedError"));
|
||||
}
|
||||
/* Deny screensharing if the requesting document is not from a host
|
||||
on the whitelist. */
|
||||
@ -1676,7 +1704,7 @@ MediaManager::GetUserMedia(
|
||||
) ||
|
||||
#endif
|
||||
(!privileged && !HostHasPermission(*docURI))) {
|
||||
return task->Denied(NS_LITERAL_STRING("PERMISSION_DENIED"));
|
||||
return task->Denied(NS_LITERAL_STRING("PermissionDeniedError"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1730,7 +1758,7 @@ MediaManager::GetUserMedia(
|
||||
|
||||
if ((!IsOn(c.mAudio) || audioPerm == nsIPermissionManager::DENY_ACTION) &&
|
||||
(!IsOn(c.mVideo) || videoPerm == nsIPermissionManager::DENY_ACTION)) {
|
||||
return task->Denied(NS_LITERAL_STRING("PERMISSION_DENIED"));
|
||||
return task->Denied(NS_LITERAL_STRING("PermissionDeniedError"));
|
||||
}
|
||||
|
||||
// Ask for user permission, and dispatch task (or not) when a response
|
||||
@ -2020,7 +2048,7 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
MOZ_ASSERT(len);
|
||||
if (!len) {
|
||||
// neither audio nor video were selected
|
||||
task->Denied(NS_LITERAL_STRING("PERMISSION_DENIED"));
|
||||
task->Denied(NS_LITERAL_STRING("PermissionDeniedError"));
|
||||
return NS_OK;
|
||||
}
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
@ -2047,14 +2075,14 @@ MediaManager::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
return NS_OK;
|
||||
|
||||
} else if (!strcmp(aTopic, "getUserMedia:response:deny")) {
|
||||
nsString errorMessage(NS_LITERAL_STRING("PERMISSION_DENIED"));
|
||||
nsString errorMessage(NS_LITERAL_STRING("PermissionDeniedError"));
|
||||
|
||||
if (aSubject) {
|
||||
nsCOMPtr<nsISupportsString> msg(do_QueryInterface(aSubject));
|
||||
MOZ_ASSERT(msg);
|
||||
msg->GetData(errorMessage);
|
||||
if (errorMessage.IsEmpty())
|
||||
errorMessage.AssignLiteral(MOZ_UTF16("UNKNOWN_ERROR"));
|
||||
errorMessage.AssignLiteral(MOZ_UTF16("InternalError"));
|
||||
}
|
||||
|
||||
nsString key(aData);
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/dom/MediaStreamBinding.h"
|
||||
#include "mozilla/dom/MediaStreamTrackBinding.h"
|
||||
#include "mozilla/dom/MediaStreamError.h"
|
||||
#include "prlog.h"
|
||||
#include "DOMMediaStream.h"
|
||||
|
||||
@ -298,7 +299,7 @@ class MediaManager;
|
||||
class GetUserMediaTask;
|
||||
|
||||
/**
|
||||
* Send an error back to content. The error is the form a string.
|
||||
* Send an error back to content.
|
||||
* Do this only on the main thread. The onSuccess callback is also passed here
|
||||
* so it can be released correctly.
|
||||
*/
|
||||
@ -306,16 +307,16 @@ class ErrorCallbackRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
ErrorCallbackRunnable(
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aSuccess,
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aError,
|
||||
const nsAString& aErrorMsg, uint64_t aWindowID);
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback>& aOnSuccess,
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback>& aOnFailure,
|
||||
MediaMgrError& aError, uint64_t aWindowID);
|
||||
NS_IMETHOD Run();
|
||||
private:
|
||||
~ErrorCallbackRunnable();
|
||||
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> mOnSuccess;
|
||||
nsCOMPtr<nsIDOMGetUserMediaErrorCallback> mOnFailure;
|
||||
const nsString mErrorMsg;
|
||||
nsRefPtr<MediaMgrError> mError;
|
||||
uint64_t mWindowID;
|
||||
nsRefPtr<MediaManager> mManager; // get ref to this when creating the runnable
|
||||
};
|
||||
@ -373,10 +374,12 @@ public:
|
||||
mOnTracksAvailableCallback.forget()));
|
||||
nsString log;
|
||||
|
||||
log.AssignASCII(errorLog, strlen(errorLog));
|
||||
log.AssignASCII(errorLog);
|
||||
nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> onSuccess;
|
||||
nsRefPtr<MediaMgrError> error = new MediaMgrError(
|
||||
NS_LITERAL_STRING("InternalError"), log);
|
||||
NS_DispatchToMainThread(new ErrorCallbackRunnable(onSuccess, mOnFailure,
|
||||
log, mWindowID));
|
||||
*error, mWindowID));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "GetUserMediaRequest.h"
|
||||
#include "mozilla/dom/PBrowserChild.h"
|
||||
#include "mozilla/dom/MediaStreamTrackBinding.h"
|
||||
#include "mozilla/dom/MediaStreamError.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsArrayUtils.h"
|
||||
@ -224,7 +225,7 @@ MediaPermissionRequest::Cancel()
|
||||
{
|
||||
nsString callID;
|
||||
mRequest->GetCallID(callID);
|
||||
NotifyPermissionDeny(callID, NS_LITERAL_STRING("Permission Denied"));
|
||||
NotifyPermissionDeny(callID, NS_LITERAL_STRING("PermissionDeniedError"));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -393,9 +394,17 @@ NS_IMPL_ISUPPORTS(MediaDeviceErrorCallback, nsIDOMGetUserMediaErrorCallback)
|
||||
|
||||
// nsIDOMGetUserMediaErrorCallback method
|
||||
NS_IMETHODIMP
|
||||
MediaDeviceErrorCallback::OnError(const nsAString &aError)
|
||||
MediaDeviceErrorCallback::OnError(nsISupports* aError)
|
||||
{
|
||||
return NotifyPermissionDeny(mCallID, aError);
|
||||
MediaStreamError *error = nullptr;
|
||||
nsresult rv = CallQueryInterface(aError, &error);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsString name;
|
||||
error->GetName(name);
|
||||
return NotifyPermissionDeny(mCallID, name);
|
||||
}
|
||||
|
||||
} // namespace anonymous
|
||||
|
@ -9,6 +9,31 @@
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
BaseMediaMgrError::BaseMediaMgrError(const nsAString& aName,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aConstraintName)
|
||||
: mName(aName)
|
||||
, mMessage(aMessage)
|
||||
, mConstraintName(aConstraintName)
|
||||
{
|
||||
if (mMessage.IsEmpty()) {
|
||||
if (mName.EqualsLiteral("NotFoundError")) {
|
||||
mMessage.AssignLiteral("The object can not be found here.");
|
||||
} else if (mName.EqualsLiteral("PermissionDeniedError")) {
|
||||
mMessage.AssignLiteral("The user did not grant permission for the operation.");
|
||||
} else if (mName.EqualsLiteral("SourceUnavailableError")) {
|
||||
mMessage.AssignLiteral("The source of the MediaStream could not be "
|
||||
"accessed due to a hardware error (e.g. lock from another process).");
|
||||
} else if (mName.EqualsLiteral("InternalError")) {
|
||||
mMessage.AssignLiteral("Internal error.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS0(MediaMgrError)
|
||||
|
||||
namespace dom {
|
||||
|
||||
MediaStreamError::MediaStreamError(
|
||||
@ -16,10 +41,8 @@ MediaStreamError::MediaStreamError(
|
||||
const nsAString& aName,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aConstraintName)
|
||||
: mParent(aParent)
|
||||
, mName(aName)
|
||||
, mMessage(aMessage)
|
||||
, mConstraintName(aConstraintName) {}
|
||||
: BaseMediaMgrError(aName, aMessage, aConstraintName)
|
||||
, mParent(aParent) {}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MediaStreamError, mParent)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaStreamError)
|
||||
|
@ -21,16 +21,59 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class MediaStreamError : public nsISupports, public nsWrapperCache
|
||||
#define MOZILLA_DOM_MEDIASTREAMERROR_IMPLEMENTATION_IID \
|
||||
{ 0x95fa29aa, 0x0cc2, 0x4698, \
|
||||
{ 0x9d, 0xa9, 0xf2, 0xeb, 0x03, 0x91, 0x0b, 0xd1 } }
|
||||
|
||||
class MediaStreamError;
|
||||
}
|
||||
|
||||
class BaseMediaMgrError
|
||||
{
|
||||
friend class dom::MediaStreamError;
|
||||
protected:
|
||||
BaseMediaMgrError(const nsAString& aName,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aConstraintName);
|
||||
const nsString mName;
|
||||
nsString mMessage;
|
||||
const nsString mConstraintName;
|
||||
};
|
||||
|
||||
class MediaMgrError MOZ_FINAL : public nsISupports,
|
||||
public BaseMediaMgrError
|
||||
{
|
||||
public:
|
||||
MediaMgrError(const nsAString& aName,
|
||||
const nsAString& aMessage = EmptyString(),
|
||||
const nsAString& aConstraintName = EmptyString())
|
||||
: BaseMediaMgrError(aName, aMessage, aConstraintName) {}
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
private:
|
||||
~MediaMgrError() {}
|
||||
};
|
||||
|
||||
namespace dom {
|
||||
class MediaStreamError MOZ_FINAL : public nsISupports,
|
||||
public BaseMediaMgrError,
|
||||
public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
MediaStreamError(nsPIDOMWindow* aParent,
|
||||
const nsAString& aName,
|
||||
const nsAString& aMessage,
|
||||
const nsAString& aConstraintName);
|
||||
const nsAString& aMessage = EmptyString(),
|
||||
const nsAString& aConstraintName = EmptyString());
|
||||
|
||||
MediaStreamError(nsPIDOMWindow* aParent,
|
||||
const BaseMediaMgrError& aOther)
|
||||
: BaseMediaMgrError(aOther.mName, aOther.mMessage, aOther.mConstraintName)
|
||||
, mParent(aParent) {}
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MediaStreamError)
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(MOZILLA_DOM_MEDIASTREAMERROR_IMPLEMENTATION_IID)
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
@ -46,11 +89,10 @@ private:
|
||||
virtual ~MediaStreamError() {}
|
||||
|
||||
nsRefPtr<nsPIDOMWindow> mParent;
|
||||
const nsString mName;
|
||||
const nsString mMessage;
|
||||
const nsString mConstraintName;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(MediaStreamError,
|
||||
MOZILLA_DOM_MEDIASTREAMERROR_IMPLEMENTATION_IID)
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -34,5 +34,5 @@ interface nsIDOMGetUserMediaSuccessCallback : nsISupports
|
||||
[scriptable, function, uuid(2614bbcf-85cc-43e5-8740-964f52bdc7ca)]
|
||||
interface nsIDOMGetUserMediaErrorCallback : nsISupports
|
||||
{
|
||||
void onError(in DOMString error);
|
||||
void onError(in nsISupports error);
|
||||
};
|
||||
|
@ -14,19 +14,19 @@ var common_tests = [
|
||||
{ message: "unknown required constraint on video fails",
|
||||
constraints: { video: { somethingUnknown:0, require:["somethingUnknown"] },
|
||||
fake: true },
|
||||
error: "NO_DEVICES_FOUND" },
|
||||
error: "NotFoundError" },
|
||||
{ message: "unknown required constraint on audio fails",
|
||||
constraints: { audio: { somethingUnknown:0, require:["somethingUnknown"] },
|
||||
fake: true },
|
||||
error: "NO_DEVICES_FOUND" },
|
||||
error: "NotFoundError" },
|
||||
{ message: "video overconstrained by facingMode fails",
|
||||
constraints: { video: { facingMode:'left', require:["facingMode"] },
|
||||
fake: true },
|
||||
error: "NO_DEVICES_FOUND" },
|
||||
error: "NotFoundError" },
|
||||
{ message: "audio overconstrained by facingMode fails",
|
||||
constraints: { audio: { facingMode:'left', require:["facingMode"] },
|
||||
fake: true },
|
||||
error: "NO_DEVICES_FOUND" },
|
||||
error: "NotFoundError" },
|
||||
{ message: "Success-path: optional video facingMode + audio ignoring facingMode",
|
||||
constraints: { fake: true,
|
||||
audio: { facingMode:'left',
|
||||
@ -61,8 +61,8 @@ function testConstraints(tests) {
|
||||
next();
|
||||
}
|
||||
function Failure(err) {
|
||||
ok(tests[i].error? (err === tests[i].error) : false,
|
||||
tests[i].message + " (err=" + err + ")");
|
||||
ok(tests[i].error? (err.name == tests[i].error) : false,
|
||||
tests[i].message + " (err=" + err.name + ")");
|
||||
i++;
|
||||
next();
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=882145
|
||||
var mobile_tests = [
|
||||
{ message: "legacy facingMode overconstrains video (mobile)",
|
||||
constraints: { video: { mandatory: { facingMode:'left' } }, fake: true },
|
||||
error: "NO_DEVICES_FOUND" },
|
||||
error: "NotFoundError" },
|
||||
];
|
||||
|
||||
runTest(function () {
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "mozilla/dom/SpeechRecognitionBinding.h"
|
||||
#include "mozilla/dom/MediaStreamTrackBinding.h"
|
||||
#include "mozilla/dom/MediaStreamError.h"
|
||||
#include "mozilla/MediaManager.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
@ -950,19 +951,26 @@ SpeechRecognition::GetUserMediaSuccessCallback::OnSuccess(nsISupports* aStream)
|
||||
NS_IMPL_ISUPPORTS(SpeechRecognition::GetUserMediaErrorCallback, nsIDOMGetUserMediaErrorCallback)
|
||||
|
||||
NS_IMETHODIMP
|
||||
SpeechRecognition::GetUserMediaErrorCallback::OnError(const nsAString& aError)
|
||||
SpeechRecognition::GetUserMediaErrorCallback::OnError(nsISupports* aError)
|
||||
{
|
||||
nsRefPtr<MediaStreamError> error = do_QueryObject(aError);
|
||||
if (!error) {
|
||||
return NS_OK;
|
||||
}
|
||||
SpeechRecognitionErrorCode errorCode;
|
||||
|
||||
if (aError.EqualsLiteral("PERMISSION_DENIED")) {
|
||||
nsString name;
|
||||
error->GetName(name);
|
||||
if (name.EqualsLiteral("PERMISSION_DENIED")) {
|
||||
errorCode = SpeechRecognitionErrorCode::Not_allowed;
|
||||
} else {
|
||||
errorCode = SpeechRecognitionErrorCode::Audio_capture;
|
||||
}
|
||||
|
||||
nsString message;
|
||||
error->GetMessage(message);
|
||||
mRecognition->DispatchError(SpeechRecognition::EVENT_AUDIO_ERROR, errorCode,
|
||||
aError);
|
||||
|
||||
message);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -354,7 +354,7 @@ partial interface Navigator {
|
||||
|
||||
#ifdef MOZ_MEDIA_NAVIGATOR
|
||||
callback NavigatorUserMediaSuccessCallback = void (MediaStream stream);
|
||||
callback NavigatorUserMediaErrorCallback = void (DOMString error);
|
||||
callback NavigatorUserMediaErrorCallback = void (MediaStreamError error);
|
||||
|
||||
partial interface Navigator {
|
||||
[Throws, Func="Navigator::HasUserMediaSupport"]
|
||||
|
@ -27,7 +27,8 @@ function test() {
|
||||
loadWebapp("getUserMedia.webapp", undefined, function onLoad() {
|
||||
let msg = gAppBrowser.contentDocument.getElementById("msg");
|
||||
mutObserver = new MutationObserver(function(mutations) {
|
||||
is(msg.textContent, "PERMISSION_DENIED", "getUserMedia permission denied.");
|
||||
is(msg.textContent, "PermissionDeniedError",
|
||||
"getUserMedia permission denied.");
|
||||
ok(getUserMediaDialogOpened, "Prompt shown.");
|
||||
finish();
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user