Commit fa5c5890 authored by Julie Jeongeun Kim's avatar Julie Jeongeun Kim Committed by Commit Bot

Use [RaisesException] for immediate promise rejections in mediastream

This is a part of effort for using [RaisesException] when synchronously
rejecting a promise.

It uses [RaisesException] for
//third_party/blink/renderer/modules/mediastream.

Bug: 1001114
Change-Id: I3fde5022c2a992e5f04e4419fd9e960c5a42dbb6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1988126Reviewed-by: default avatarTommi <tommi@chromium.org>
Commit-Queue: Julie Kim <jkim@igalia.com>
Cr-Commit-Position: refs/heads/master@{#728760}
parent 1d8aa4c1
......@@ -23,6 +23,7 @@
#include "third_party/blink/renderer/modules/mediastream/media_track_supported_constraints.h"
#include "third_party/blink/renderer/modules/mediastream/navigator_media_stream.h"
#include "third_party/blink/renderer/modules/mediastream/user_media_controller.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/mediastream/webrtc_uma_histograms.h"
......@@ -63,15 +64,15 @@ MediaDevices::MediaDevices(ExecutionContext* context)
MediaDevices::~MediaDevices() = default;
ScriptPromise MediaDevices::enumerateDevices(ScriptState* script_state) {
ScriptPromise MediaDevices::enumerateDevices(ScriptState* script_state,
ExceptionState& exception_state) {
UpdateWebRTCMethodCount(RTCAPIName::kEnumerateDevices);
LocalFrame* frame =
To<Document>(ExecutionContext::From(script_state))->GetFrame();
if (!frame) {
return ScriptPromise::RejectWithDOMException(
script_state,
MakeGarbageCollected<DOMException>(DOMExceptionCode::kNotSupportedError,
"Current frame is detached."));
exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"Current frame is detached.");
return ScriptPromise();
}
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
......@@ -111,11 +112,10 @@ ScriptPromise MediaDevices::SendUserMediaRequest(
UserMediaController* user_media =
UserMediaController::From(document->GetFrame());
if (!user_media) {
return ScriptPromise::RejectWithDOMException(
script_state, MakeGarbageCollected<DOMException>(
DOMExceptionCode::kNotSupportedError,
"No media device controller available; is this a "
"detached window?"));
exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
"No media device controller available; "
"is this a detached window?");
return ScriptPromise();
}
MediaErrorState error_state;
......@@ -134,9 +134,9 @@ ScriptPromise MediaDevices::SendUserMediaRequest(
String error_message;
if (!request->IsSecureContextUse(error_message)) {
return ScriptPromise::RejectWithDOMException(
script_state, MakeGarbageCollected<DOMException>(
DOMExceptionCode::kNotSupportedError, error_message));
exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
error_message);
return ScriptPromise();
}
auto promise = resolver->Promise();
request->Start();
......
......@@ -21,6 +21,7 @@
namespace blink {
class ExceptionState;
class LocalFrame;
class MediaStreamConstraints;
class MediaTrackSupportedConstraints;
......@@ -41,7 +42,7 @@ class MODULES_EXPORT MediaDevices final
explicit MediaDevices(ExecutionContext*);
~MediaDevices() override;
ScriptPromise enumerateDevices(ScriptState*);
ScriptPromise enumerateDevices(ScriptState*, ExceptionState&);
MediaTrackSupportedConstraints* getSupportedConstraints() const;
ScriptPromise getUserMedia(ScriptState*,
const MediaStreamConstraints*,
......
......@@ -13,7 +13,7 @@
] interface MediaDevices : EventTarget {
[RuntimeEnabled=OnDeviceChange] attribute EventHandler ondevicechange;
[
CallWith = ScriptState, HighEntropy, MeasureAs = MediaDevicesEnumerateDevices
CallWith = ScriptState, RaisesException, HighEntropy, MeasureAs = MediaDevicesEnumerateDevices
] Promise<sequence<MediaDeviceInfo>>
enumerateDevices();
MediaTrackSupportedConstraints getSupportedConstraints();
......
......@@ -163,57 +163,6 @@ class MockMediaDevicesDispatcherHost
mojo::Receiver<mojom::blink::MediaDevicesDispatcherHost> receiver_{this};
};
class PromiseObserver {
public:
PromiseObserver(ScriptState* script_state, ScriptPromise promise)
: is_rejected_(false), is_fulfilled_(false) {
v8::Local<v8::Function> on_fulfilled = MyScriptFunction::CreateFunction(
script_state, &is_fulfilled_, &saved_arg_);
v8::Local<v8::Function> on_rejected = MyScriptFunction::CreateFunction(
script_state, &is_rejected_, &saved_arg_);
promise.Then(on_fulfilled, on_rejected);
}
bool isDecided() { return is_rejected_ || is_fulfilled_; }
bool isFulfilled() { return is_fulfilled_; }
bool isRejected() { return is_rejected_; }
ScriptValue argument() { return saved_arg_; }
void Trace(blink::Visitor* visitor) { visitor->Trace(saved_arg_); }
private:
class MyScriptFunction : public ScriptFunction {
public:
static v8::Local<v8::Function> CreateFunction(ScriptState* script_state,
bool* flag_to_set,
ScriptValue* arg_to_set) {
MyScriptFunction* self = MakeGarbageCollected<MyScriptFunction>(
script_state, flag_to_set, arg_to_set);
return self->BindToV8Function();
}
MyScriptFunction(ScriptState* script_state,
bool* flag_to_set,
ScriptValue* arg_to_set)
: ScriptFunction(script_state),
flag_to_set_(flag_to_set),
arg_to_set_(arg_to_set) {}
ScriptValue Call(ScriptValue arg) override {
*flag_to_set_ = true;
*arg_to_set_ = arg;
return arg;
}
private:
bool* flag_to_set_;
ScriptValue* arg_to_set_;
};
bool is_rejected_;
bool is_fulfilled_;
ScriptValue saved_arg_;
};
class MediaDevicesTest : public testing::Test {
public:
using MediaDeviceInfos = HeapVector<Member<MediaDeviceInfo>>;
......@@ -298,24 +247,13 @@ TEST_F(MediaDevicesTest, GetUserMediaCanBeCalled) {
GetMediaDevices(scope.GetExecutionContext())
->getUserMedia(scope.GetScriptState(), constraints,
scope.GetExceptionState());
ASSERT_FALSE(promise.IsEmpty());
PromiseObserver promise_observer(scope.GetScriptState(), promise);
EXPECT_FALSE(promise_observer.isDecided());
v8::MicrotasksScope::PerformCheckpoint(scope.GetIsolate());
EXPECT_TRUE(promise_observer.isDecided());
ASSERT_TRUE(promise.IsEmpty());
// In the default test environment, we expect a DOM rejection because
// the script state's execution context's document's frame doesn't
// have an UserMediaController.
EXPECT_TRUE(promise_observer.isRejected());
// TODO(hta): Check that the correct error ("not supported") is returned.
EXPECT_FALSE(promise_observer.argument().IsNull());
// This log statement is included as a demonstration of how to get the string
// value of the argument.
VLOG(1) << "Argument is"
<< ToCoreString(promise_observer.argument()
.V8Value()
->ToString(scope.GetContext())
.ToLocalChecked());
DCHECK_EQ(scope.GetExceptionState().Code(),
ToExceptionCode(DOMExceptionCode::kNotSupportedError));
VLOG(1) << "Exception message is" << scope.GetExceptionState().Message();
}
TEST_F(MediaDevicesTest, EnumerateDevices) {
......@@ -323,8 +261,8 @@ TEST_F(MediaDevicesTest, EnumerateDevices) {
auto* media_devices = GetMediaDevices(scope.GetExecutionContext());
media_devices->SetEnumerateDevicesCallbackForTesting(
WTF::Bind(&MediaDevicesTest::DevicesEnumerated, WTF::Unretained(this)));
ScriptPromise promise =
media_devices->enumerateDevices(scope.GetScriptState());
ScriptPromise promise = media_devices->enumerateDevices(
scope.GetScriptState(), scope.GetExceptionState());
platform()->RunUntilIdle();
ASSERT_FALSE(promise.IsEmpty());
......@@ -385,8 +323,8 @@ TEST_F(MediaDevicesTest, EnumerateDevicesAfterConnectionError) {
CloseBinding();
platform()->RunUntilIdle();
ScriptPromise promise =
media_devices->enumerateDevices(scope.GetScriptState());
ScriptPromise promise = media_devices->enumerateDevices(
scope.GetScriptState(), scope.GetExceptionState());
platform()->RunUntilIdle();
ASSERT_FALSE(promise.IsEmpty());
EXPECT_TRUE(dispatcher_host_connection_error());
......@@ -403,8 +341,8 @@ TEST_F(MediaDevicesTest, EnumerateDevicesBeforeConnectionError) {
WTF::Unretained(this)));
EXPECT_FALSE(dispatcher_host_connection_error());
ScriptPromise promise =
media_devices->enumerateDevices(scope.GetScriptState());
ScriptPromise promise = media_devices->enumerateDevices(
scope.GetScriptState(), scope.GetExceptionState());
platform()->RunUntilIdle();
ASSERT_FALSE(promise.IsEmpty());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment