Improving webkitGetUserMedia error handling and error messages
authorthiago.lacerda@openbossa.org <thiago.lacerda@openbossa.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Mar 2014 21:06:38 +0000 (21:06 +0000)
committerthiago.lacerda@openbossa.org <thiago.lacerda@openbossa.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Mar 2014 21:06:38 +0000 (21:06 +0000)
https://bugs.webkit.org/show_bug.cgi?id=130452

Reviewed by Eric Carlson.

Checking if first argument of webkitGetUserMedia is a valid Dictionary. If not, throw an exception with a
clearer message of the error.

Source/WebCore:

Test updated.

* Modules/mediastream/NavigatorMediaStream.idl:
* UseJSC.cmake:
* bindings/js/JSNavigatorCustom.cpp: Added.

LayoutTests:

* fast/mediastream/argument-types-expected.txt:
* fast/mediastream/script-tests/argument-types.js:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@165915 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/mediastream/argument-types-expected.txt
LayoutTests/fast/mediastream/script-tests/argument-types.js
Source/WebCore/ChangeLog
Source/WebCore/Modules/mediastream/NavigatorMediaStream.idl
Source/WebCore/UseJSC.cmake
Source/WebCore/bindings/js/JSNavigatorCustom.cpp [new file with mode: 0644]

index b80f4fd..7aeaae0 100644 (file)
@@ -1,3 +1,16 @@
+2014-03-19  Thiago de Barros Lacerda  <thiago.lacerda@openbossa.org>
+
+        Improving webkitGetUserMedia error handling and error messages
+        https://bugs.webkit.org/show_bug.cgi?id=130452
+
+        Reviewed by Eric Carlson.
+
+        Checking if first argument of webkitGetUserMedia is a valid Dictionary. If not, throw an exception with a
+        clearer message of the error.
+
+        * fast/mediastream/argument-types-expected.txt:
+        * fast/mediastream/script-tests/argument-types.js:
+
 2014-03-19  Dirk Schulze  <krit@webkit.org>
 
         Implement method addPath for Path2D
index 88ff9d1..0b94be6 100644 (file)
@@ -14,34 +14,34 @@ PASS navigator.webkitGetUserMedia(Infinity) threw exception TypeError: Not enoug
 PASS navigator.webkitGetUserMedia(-Infinity) threw exception TypeError: Not enough arguments.
 PASS navigator.webkitGetUserMedia(emptyFunction) threw exception TypeError: Not enough arguments.
 PASS navigator.webkitGetUserMedia({video: true}, emptyFunction) did not throw exception.
-PASS navigator.webkitGetUserMedia(undefined, emptyFunction) threw exception Error: NotSupportedError: DOM Exception 9.
-PASS navigator.webkitGetUserMedia(null, emptyFunction) threw exception Error: NotSupportedError: DOM Exception 9.
+PASS navigator.webkitGetUserMedia(undefined, emptyFunction) threw exception TypeError: First argument of webkitGetUserMedia must be a valid Dictionary.
+PASS navigator.webkitGetUserMedia(null, emptyFunction) threw exception TypeError: First argument of webkitGetUserMedia must be a valid Dictionary.
 PASS navigator.webkitGetUserMedia({ }, emptyFunction) threw exception Error: NotSupportedError: DOM Exception 9.
-FAIL navigator.webkitGetUserMedia(true, emptyFunction) should throw TypeError: Not an object.. Threw exception Error: NotSupportedError: DOM Exception 9.
-FAIL navigator.webkitGetUserMedia(42, emptyFunction) should throw TypeError: Not an object.. Threw exception Error: NotSupportedError: DOM Exception 9.
-FAIL navigator.webkitGetUserMedia(Infinity, emptyFunction) should throw TypeError: Not an object.. Threw exception Error: NotSupportedError: DOM Exception 9.
-FAIL navigator.webkitGetUserMedia(-Infinity, emptyFunction) should throw TypeError: Not an object.. Threw exception Error: NotSupportedError: DOM Exception 9.
+PASS navigator.webkitGetUserMedia(true, emptyFunction) threw exception TypeError: First argument of webkitGetUserMedia must be a valid Dictionary.
+PASS navigator.webkitGetUserMedia(42, emptyFunction) threw exception TypeError: First argument of webkitGetUserMedia must be a valid Dictionary.
+PASS navigator.webkitGetUserMedia(Infinity, emptyFunction) threw exception TypeError: First argument of webkitGetUserMedia must be a valid Dictionary.
+PASS navigator.webkitGetUserMedia(-Infinity, emptyFunction) threw exception TypeError: First argument of webkitGetUserMedia must be a valid Dictionary.
 PASS navigator.webkitGetUserMedia(emptyFunction, emptyFunction) threw exception Error: NotSupportedError: DOM Exception 9.
-PASS navigator.webkitGetUserMedia({video: true}, "foobar") threw exception TypeError: Type error.
-PASS navigator.webkitGetUserMedia({video: true}, undefined) threw exception TypeError: Type error.
-PASS navigator.webkitGetUserMedia({video: true}, null) threw exception TypeError: Type error.
-PASS navigator.webkitGetUserMedia({video: true}, {}) threw exception TypeError: Type error.
-PASS navigator.webkitGetUserMedia({video: true}, true) threw exception TypeError: Type error.
-PASS navigator.webkitGetUserMedia({video: true}, 42) threw exception TypeError: Type error.
-PASS navigator.webkitGetUserMedia({video: true}, Infinity) threw exception TypeError: Type error.
-PASS navigator.webkitGetUserMedia({video: true}, -Infinity) threw exception TypeError: Type error.
+PASS navigator.webkitGetUserMedia({video: true}, "foobar") threw exception TypeError: Argument 2 ('successCallback') to Navigator.webkitGetUserMedia must be a function.
+PASS navigator.webkitGetUserMedia({video: true}, undefined) threw exception TypeError: Argument 2 ('successCallback') to Navigator.webkitGetUserMedia must be a function.
+PASS navigator.webkitGetUserMedia({video: true}, null) threw exception TypeError: Argument 2 ('successCallback') to Navigator.webkitGetUserMedia must be a function.
+PASS navigator.webkitGetUserMedia({video: true}, {}) threw exception TypeError: Argument 2 ('successCallback') to Navigator.webkitGetUserMedia must be a function.
+PASS navigator.webkitGetUserMedia({video: true}, true) threw exception TypeError: Argument 2 ('successCallback') to Navigator.webkitGetUserMedia must be a function.
+PASS navigator.webkitGetUserMedia({video: true}, 42) threw exception TypeError: Argument 2 ('successCallback') to Navigator.webkitGetUserMedia must be a function.
+PASS navigator.webkitGetUserMedia({video: true}, Infinity) threw exception TypeError: Argument 2 ('successCallback') to Navigator.webkitGetUserMedia must be a function.
+PASS navigator.webkitGetUserMedia({video: true}, -Infinity) threw exception TypeError: Argument 2 ('successCallback') to Navigator.webkitGetUserMedia must be a function.
 PASS navigator.webkitGetUserMedia({ }, emptyFunction, emptyFunction) threw exception Error: NotSupportedError: DOM Exception 9.
 PASS navigator.webkitGetUserMedia({video: true}, emptyFunction, emptyFunction) did not throw exception.
 PASS navigator.webkitGetUserMedia({video: true}, emptyFunction, undefined) did not throw exception.
 PASS navigator.webkitGetUserMedia({audio:true, video:true}, emptyFunction, undefined) did not throw exception.
 PASS navigator.webkitGetUserMedia({audio:true}, emptyFunction, undefined) did not throw exception.
-PASS navigator.webkitGetUserMedia({video: true}, emptyFunction, "video") threw exception TypeError: Type error.
+PASS navigator.webkitGetUserMedia({video: true}, emptyFunction, "video") threw exception TypeError: Argument 3 ('errorCallback') to Navigator.webkitGetUserMedia must be a function.
 PASS navigator.webkitGetUserMedia({video: true}, emptyFunction, null) did not throw exception.
-PASS navigator.webkitGetUserMedia({video: true}, emptyFunction, {}) threw exception TypeError: Type error.
-PASS navigator.webkitGetUserMedia({video: true}, emptyFunction, true) threw exception TypeError: Type error.
-PASS navigator.webkitGetUserMedia({video: true}, emptyFunction, 42) threw exception TypeError: Type error.
-PASS navigator.webkitGetUserMedia({video: true}, emptyFunction, Infinity) threw exception TypeError: Type error.
-PASS navigator.webkitGetUserMedia({video: true}, emptyFunction, -Infinity) threw exception TypeError: Type error.
+PASS navigator.webkitGetUserMedia({video: true}, emptyFunction, {}) threw exception TypeError: Argument 3 ('errorCallback') to Navigator.webkitGetUserMedia must be a function.
+PASS navigator.webkitGetUserMedia({video: true}, emptyFunction, true) threw exception TypeError: Argument 3 ('errorCallback') to Navigator.webkitGetUserMedia must be a function.
+PASS navigator.webkitGetUserMedia({video: true}, emptyFunction, 42) threw exception TypeError: Argument 3 ('errorCallback') to Navigator.webkitGetUserMedia must be a function.
+PASS navigator.webkitGetUserMedia({video: true}, emptyFunction, Infinity) threw exception TypeError: Argument 3 ('errorCallback') to Navigator.webkitGetUserMedia must be a function.
+PASS navigator.webkitGetUserMedia({video: true}, emptyFunction, -Infinity) threw exception TypeError: Argument 3 ('errorCallback') to Navigator.webkitGetUserMedia must be a function.
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 4a316e8..ac13dd6 100644 (file)
@@ -11,7 +11,10 @@ function test(expression, expressionShouldThrow, expectedException) {
     }
 }
 
+var errorCallbackError = new TypeError("Argument 3 ('errorCallback') to Navigator.webkitGetUserMedia must be a function")
+var invalidDictionaryError = new TypeError('First argument of webkitGetUserMedia must be a valid Dictionary')
 var notSupportedError = new Error('NotSupportedError: DOM Exception 9');
+var successCallbackError = new TypeError("Argument 2 ('successCallback') to Navigator.webkitGetUserMedia must be a function")
 var typeError = new TypeError('Type error');
 var typeNotAnObjectError = new TypeError('Not an object.');
 
@@ -33,22 +36,22 @@ test('navigator.webkitGetUserMedia(emptyFunction)', true);
 
 // 2 Arguments.
 test('navigator.webkitGetUserMedia({video: true}, emptyFunction)', false);
-test('navigator.webkitGetUserMedia(undefined, emptyFunction)', true, notSupportedError);
-test('navigator.webkitGetUserMedia(null, emptyFunction)', true, notSupportedError);
+test('navigator.webkitGetUserMedia(undefined, emptyFunction)', true, invalidDictionaryError);
+test('navigator.webkitGetUserMedia(null, emptyFunction)', true, invalidDictionaryError);
 test('navigator.webkitGetUserMedia({ }, emptyFunction)', true, notSupportedError);
-test('navigator.webkitGetUserMedia(true, emptyFunction)', true, typeNotAnObjectError);
-test('navigator.webkitGetUserMedia(42, emptyFunction)', true, typeNotAnObjectError);
-test('navigator.webkitGetUserMedia(Infinity, emptyFunction)', true, typeNotAnObjectError);
-test('navigator.webkitGetUserMedia(-Infinity, emptyFunction)', true, typeNotAnObjectError);
+test('navigator.webkitGetUserMedia(true, emptyFunction)', true, invalidDictionaryError);
+test('navigator.webkitGetUserMedia(42, emptyFunction)', true, invalidDictionaryError);
+test('navigator.webkitGetUserMedia(Infinity, emptyFunction)', true, invalidDictionaryError);
+test('navigator.webkitGetUserMedia(-Infinity, emptyFunction)', true, invalidDictionaryError);
 test('navigator.webkitGetUserMedia(emptyFunction, emptyFunction)', true, notSupportedError);
-test('navigator.webkitGetUserMedia({video: true}, "foobar")', true, typeError);
-test('navigator.webkitGetUserMedia({video: true}, undefined)', true, typeError);
-test('navigator.webkitGetUserMedia({video: true}, null)', true, typeError);
-test('navigator.webkitGetUserMedia({video: true}, {})', true, typeError);
-test('navigator.webkitGetUserMedia({video: true}, true)', true, typeError);
-test('navigator.webkitGetUserMedia({video: true}, 42)', true, typeError);
-test('navigator.webkitGetUserMedia({video: true}, Infinity)', true, typeError);
-test('navigator.webkitGetUserMedia({video: true}, -Infinity)', true, typeError);
+test('navigator.webkitGetUserMedia({video: true}, "foobar")', true, successCallbackError);
+test('navigator.webkitGetUserMedia({video: true}, undefined)', true, successCallbackError);
+test('navigator.webkitGetUserMedia({video: true}, null)', true, successCallbackError);
+test('navigator.webkitGetUserMedia({video: true}, {})', true, successCallbackError);
+test('navigator.webkitGetUserMedia({video: true}, true)', true, successCallbackError);
+test('navigator.webkitGetUserMedia({video: true}, 42)', true, successCallbackError);
+test('navigator.webkitGetUserMedia({video: true}, Infinity)', true, successCallbackError);
+test('navigator.webkitGetUserMedia({video: true}, -Infinity)', true, successCallbackError);
 
 // 3 Arguments.
 test('navigator.webkitGetUserMedia({ }, emptyFunction, emptyFunction)', true, notSupportedError);
@@ -56,12 +59,12 @@ test('navigator.webkitGetUserMedia({video: true}, emptyFunction, emptyFunction)'
 test('navigator.webkitGetUserMedia({video: true}, emptyFunction, undefined)', false);
 test('navigator.webkitGetUserMedia({audio:true, video:true}, emptyFunction, undefined)', false);
 test('navigator.webkitGetUserMedia({audio:true}, emptyFunction, undefined)', false);
-test('navigator.webkitGetUserMedia({video: true}, emptyFunction, "video")', true, typeError);
+test('navigator.webkitGetUserMedia({video: true}, emptyFunction, "video")', true, errorCallbackError);
 test('navigator.webkitGetUserMedia({video: true}, emptyFunction, null)', false );
-test('navigator.webkitGetUserMedia({video: true}, emptyFunction, {})', true, typeError);
-test('navigator.webkitGetUserMedia({video: true}, emptyFunction, true)', true, typeError);
-test('navigator.webkitGetUserMedia({video: true}, emptyFunction, 42)', true, typeError);
-test('navigator.webkitGetUserMedia({video: true}, emptyFunction, Infinity)', true, typeError);
-test('navigator.webkitGetUserMedia({video: true}, emptyFunction, -Infinity)', true, typeError);
+test('navigator.webkitGetUserMedia({video: true}, emptyFunction, {})', true, errorCallbackError);
+test('navigator.webkitGetUserMedia({video: true}, emptyFunction, true)', true, errorCallbackError);
+test('navigator.webkitGetUserMedia({video: true}, emptyFunction, 42)', true, errorCallbackError);
+test('navigator.webkitGetUserMedia({video: true}, emptyFunction, Infinity)', true, errorCallbackError);
+test('navigator.webkitGetUserMedia({video: true}, emptyFunction, -Infinity)', true, errorCallbackError);
 
 window.jsTestIsAsync = false;
index 77e7760..84ec78b 100644 (file)
@@ -1,3 +1,19 @@
+2014-03-19  Thiago de Barros Lacerda  <thiago.lacerda@openbossa.org>
+
+        Improving webkitGetUserMedia error handling and error messages
+        https://bugs.webkit.org/show_bug.cgi?id=130452
+
+        Reviewed by Eric Carlson.
+
+        Checking if first argument of webkitGetUserMedia is a valid Dictionary. If not, throw an exception with a
+        clearer message of the error.
+
+        Test updated.
+
+        * Modules/mediastream/NavigatorMediaStream.idl:
+        * UseJSC.cmake:
+        * bindings/js/JSNavigatorCustom.cpp: Added.
+
 2014-03-19  Andreas Kling  <akling@apple.com>
 
         JSC bindings should use the passed-in global object for wrapper caching.
index 0cf2307..4c65cb7 100644 (file)
@@ -20,7 +20,7 @@
 [
     Conditional=MEDIA_STREAM,
 ] partial interface Navigator {
-    [RaisesException] void webkitGetUserMedia(Dictionary options,
+    [Custom, RaisesException] void webkitGetUserMedia(Dictionary options,
                                                  NavigatorUserMediaSuccessCallback successCallback,
                                                  optional NavigatorUserMediaErrorCallback errorCallback);
 };
index 28dcae4..922937f 100644 (file)
@@ -108,6 +108,7 @@ list(APPEND WebCore_SOURCES
     bindings/js/JSMutationCallback.cpp
     bindings/js/JSMutationObserverCustom.cpp
     bindings/js/JSNamedNodeMapCustom.cpp
+    bindings/js/JSNavigatorCustom.cpp
     bindings/js/JSNodeCustom.cpp
     bindings/js/JSNodeFilterCondition.cpp
     bindings/js/JSNodeFilterCustom.cpp
diff --git a/Source/WebCore/bindings/js/JSNavigatorCustom.cpp b/Source/WebCore/bindings/js/JSNavigatorCustom.cpp
new file mode 100644 (file)
index 0000000..81cd029
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(MEDIA_STREAM)
+#include "JSNavigator.h"
+
+#include "Dictionary.h"
+#include "ExceptionCode.h"
+#include "JSNavigatorUserMediaErrorCallback.h"
+#include "JSNavigatorUserMediaSuccessCallback.h"
+#include "NavigatorMediaStream.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+JSValue JSNavigator::webkitGetUserMedia(ExecState* exec)
+{
+    if (exec->argumentCount() < 2) {
+        throwVMError(exec, createNotEnoughArgumentsError(exec));
+        return jsUndefined();
+    }
+
+    Dictionary options(exec, exec->argument(0));
+    if (exec->hadException())
+        return jsUndefined();
+
+    if (!options.isObject()) {
+        throwVMError(exec, createTypeError(exec, "First argument of webkitGetUserMedia must be a valid Dictionary"));
+        return jsUndefined();
+    }
+
+    if (!exec->argument(1).isFunction()) {
+        throwVMError(exec, createTypeError(exec, "Argument 2 ('successCallback') to Navigator.webkitGetUserMedia must be a function"));
+        return jsUndefined();
+    }
+
+    JSNavigator* castedThis = jsDynamicCast<JSNavigator*>(exec->hostThisValue());
+    RefPtr<NavigatorUserMediaErrorCallback> errorCallback;
+    if (!exec->argument(2).isUndefinedOrNull()) {
+        if (!exec->uncheckedArgument(2).isFunction()) {
+            throwVMError(exec, createTypeError(exec, "Argument 3 ('errorCallback') to Navigator.webkitGetUserMedia must be a function"));
+            return jsUndefined();
+        }
+        errorCallback = JSNavigatorUserMediaErrorCallback::create(asObject(exec->uncheckedArgument(2)), castedThis->globalObject());
+    }
+
+    RefPtr<NavigatorUserMediaSuccessCallback> successCallback = JSNavigatorUserMediaSuccessCallback::create(asObject(exec->uncheckedArgument(1)), castedThis->globalObject());
+    Navigator& impl = castedThis->impl();
+    ExceptionCode ec = 0;
+    NavigatorMediaStream::webkitGetUserMedia(&impl, options, successCallback, errorCallback, ec);
+    setDOMException(exec, ec);
+    return jsUndefined();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(MEDIA_STREAM)