Commit 03b3c884 authored by Jeremy Roman's avatar Jeremy Roman Committed by Commit Bot

Use [RaisesException] for immediate promise rejections in...

Use [RaisesException] for immediate promise rejections in /third_party/blink/renderer/modules/serial.

The bindings layer implicitly converts thrown exceptions in promise-returning
functions to promise rejections, and using ExceptionState makes this more
similar to ordinarily throwing exceptions, notably by including the auto-
generated exception context that makes it easier to see what IDL operation
caused an exception to be thrown.

This CL was uploaded by git cl split.

R=reillyg@chromium.org

Bug: 1001114
Change-Id: I705359178d1e7c429d48f24f37ca11c28f750d2c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1786934Reviewed-by: default avatarReilly Grant <reillyg@chromium.org>
Commit-Queue: Jeremy Roman <jbroman@chromium.org>
Auto-Submit: Jeremy Roman <jbroman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#694276}
parent 34691aae
...@@ -23,6 +23,7 @@ namespace blink { ...@@ -23,6 +23,7 @@ namespace blink {
namespace { namespace {
const char kContextGone[] = "Script context has shut down.";
const char kFeaturePolicyBlocked[] = const char kFeaturePolicyBlocked[] =
"Access to the feature \"serial\" is disallowed by feature policy."; "Access to the feature \"serial\" is disallowed by feature policy.";
const char kNoPortSelected[] = "No port selected by the user."; const char kNoPortSelected[] = "No port selected by the user.";
...@@ -52,21 +53,20 @@ void Serial::ContextDestroyed(ExecutionContext*) { ...@@ -52,21 +53,20 @@ void Serial::ContextDestroyed(ExecutionContext*) {
entry.value->ContextDestroyed(); entry.value->ContextDestroyed();
} }
ScriptPromise Serial::getPorts(ScriptState* script_state) { ScriptPromise Serial::getPorts(ScriptState* script_state,
ExceptionState& exception_state) {
auto* context = GetExecutionContext(); auto* context = GetExecutionContext();
if (!context) { if (!context) {
return ScriptPromise::RejectWithDOMException( exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
script_state, MakeGarbageCollected<DOMException>( kContextGone);
DOMExceptionCode::kNotSupportedError)); return ScriptPromise();
} }
if (!context->GetSecurityContext().IsFeatureEnabled( if (!context->GetSecurityContext().IsFeatureEnabled(
mojom::FeaturePolicyFeature::kSerial, mojom::FeaturePolicyFeature::kSerial,
ReportOptions::kReportOnFailure)) { ReportOptions::kReportOnFailure)) {
return ScriptPromise::RejectWithDOMException( exception_state.ThrowSecurityError(kFeaturePolicyBlocked);
script_state, return ScriptPromise();
MakeGarbageCollected<DOMException>(DOMExceptionCode::kSecurityError,
kFeaturePolicyBlocked));
} }
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
...@@ -80,29 +80,26 @@ ScriptPromise Serial::getPorts(ScriptState* script_state) { ...@@ -80,29 +80,26 @@ ScriptPromise Serial::getPorts(ScriptState* script_state) {
} }
ScriptPromise Serial::requestPort(ScriptState* script_state, ScriptPromise Serial::requestPort(ScriptState* script_state,
const SerialPortRequestOptions* options) { const SerialPortRequestOptions* options,
ExceptionState& exception_state) {
auto* frame = GetFrame(); auto* frame = GetFrame();
if (!frame || !frame->GetDocument()) { if (!frame || !frame->GetDocument()) {
return ScriptPromise::RejectWithDOMException( exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
script_state, MakeGarbageCollected<DOMException>( kContextGone);
DOMExceptionCode::kNotSupportedError)); return ScriptPromise();
} }
if (!frame->GetDocument()->IsFeatureEnabled( if (!frame->GetDocument()->IsFeatureEnabled(
mojom::FeaturePolicyFeature::kSerial, mojom::FeaturePolicyFeature::kSerial,
ReportOptions::kReportOnFailure)) { ReportOptions::kReportOnFailure)) {
return ScriptPromise::RejectWithDOMException( exception_state.ThrowSecurityError(kFeaturePolicyBlocked);
script_state, return ScriptPromise();
MakeGarbageCollected<DOMException>(DOMExceptionCode::kSecurityError,
kFeaturePolicyBlocked));
} }
if (!LocalFrame::HasTransientUserActivation(frame)) { if (!LocalFrame::HasTransientUserActivation(frame)) {
return ScriptPromise::RejectWithDOMException( exception_state.ThrowSecurityError(
script_state, "Must be handling a user gesture to show a permission request.");
MakeGarbageCollected<DOMException>( return ScriptPromise();
DOMExceptionCode::kSecurityError,
"Must be handling a user gesture to show a permission request."));
} }
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
......
...@@ -41,8 +41,10 @@ class Serial final : public EventTargetWithInlineData, ...@@ -41,8 +41,10 @@ class Serial final : public EventTargetWithInlineData,
// Web-exposed interfaces // Web-exposed interfaces
DEFINE_ATTRIBUTE_EVENT_LISTENER(connect, kConnect) DEFINE_ATTRIBUTE_EVENT_LISTENER(connect, kConnect)
DEFINE_ATTRIBUTE_EVENT_LISTENER(disconnect, kDisconnect) DEFINE_ATTRIBUTE_EVENT_LISTENER(disconnect, kDisconnect)
ScriptPromise getPorts(ScriptState*); ScriptPromise getPorts(ScriptState*, ExceptionState&);
ScriptPromise requestPort(ScriptState*, const SerialPortRequestOptions*); ScriptPromise requestPort(ScriptState*,
const SerialPortRequestOptions*,
ExceptionState&);
void GetPort( void GetPort(
const base::UnguessableToken& token, const base::UnguessableToken& token,
......
...@@ -11,9 +11,9 @@ ...@@ -11,9 +11,9 @@
attribute EventHandler onconnect; attribute EventHandler onconnect;
attribute EventHandler ondisconnect; attribute EventHandler ondisconnect;
[CallWith=ScriptState, MeasureAs=SerialGetPorts] [CallWith=ScriptState, RaisesException, MeasureAs=SerialGetPorts]
Promise<sequence<SerialPort>> getPorts(); Promise<sequence<SerialPort>> getPorts();
[CallWith=ScriptState, MeasureAs=SerialRequestPort, Exposed=Window] [CallWith=ScriptState, RaisesException, MeasureAs=SerialRequestPort, Exposed=Window]
Promise<SerialPort> requestPort(optional SerialPortRequestOptions options); Promise<SerialPort> requestPort(optional SerialPortRequestOptions options);
}; };
...@@ -81,28 +81,27 @@ SerialPort::SerialPort(Serial* parent, mojom::blink::SerialPortInfoPtr info) ...@@ -81,28 +81,27 @@ SerialPort::SerialPort(Serial* parent, mojom::blink::SerialPortInfoPtr info)
SerialPort::~SerialPort() = default; SerialPort::~SerialPort() = default;
ScriptPromise SerialPort::open(ScriptState* script_state, ScriptPromise SerialPort::open(ScriptState* script_state,
const SerialOptions* options) { const SerialOptions* options,
ExceptionState& exception_state) {
if (open_resolver_) { if (open_resolver_) {
return ScriptPromise::RejectWithDOMException( exception_state.ThrowDOMException(
script_state, MakeGarbageCollected<DOMException>( DOMExceptionCode::kInvalidStateError,
DOMExceptionCode::kInvalidStateError, "A call to open() is already in progress.");
"A call to open() is already in progress.")); return ScriptPromise();
} }
if (port_) { if (port_) {
return ScriptPromise::RejectWithDOMException( exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
script_state, "The port is already open.");
MakeGarbageCollected<DOMException>(DOMExceptionCode::kInvalidStateError, return ScriptPromise();
"The port is already open."));
} }
auto mojo_options = device::mojom::blink::SerialConnectionOptions::New(); auto mojo_options = device::mojom::blink::SerialConnectionOptions::New();
if (options->baudrate() == 0) { if (options->baudrate() == 0) {
return ScriptPromise::Reject( exception_state.ThrowTypeError(
script_state, V8ThrowException::CreateTypeError( "Requested baud rate must be greater than zero.");
script_state->GetIsolate(), return ScriptPromise();
"Requested baud rate must be greater than zero."));
} }
mojo_options->bitrate = options->baudrate(); mojo_options->bitrate = options->baudrate();
...@@ -114,10 +113,9 @@ ScriptPromise SerialPort::open(ScriptState* script_state, ...@@ -114,10 +113,9 @@ ScriptPromise SerialPort::open(ScriptState* script_state,
mojo_options->data_bits = device::mojom::blink::SerialDataBits::EIGHT; mojo_options->data_bits = device::mojom::blink::SerialDataBits::EIGHT;
break; break;
default: default:
return ScriptPromise::Reject( exception_state.ThrowTypeError(
script_state, V8ThrowException::CreateTypeError( "Requested number of data bits must be 7 or 8.");
script_state->GetIsolate(), return ScriptPromise();
"Requested number of data bits must be 7 or 8."));
} }
if (options->parity() == "none") { if (options->parity() == "none") {
...@@ -138,30 +136,24 @@ ScriptPromise SerialPort::open(ScriptState* script_state, ...@@ -138,30 +136,24 @@ ScriptPromise SerialPort::open(ScriptState* script_state,
mojo_options->stop_bits = device::mojom::blink::SerialStopBits::TWO; mojo_options->stop_bits = device::mojom::blink::SerialStopBits::TWO;
break; break;
default: default:
return ScriptPromise::Reject( exception_state.ThrowTypeError(
script_state, V8ThrowException::CreateTypeError( "Requested number of stop bits must be 1 or 2.");
script_state->GetIsolate(), return ScriptPromise();
"Requested number of stop bits must be 1 or 2."));
} }
if (options->buffersize() == 0) { if (options->buffersize() == 0) {
return ScriptPromise::Reject( exception_state.ThrowTypeError(String::Format(
script_state, "Requested buffer size (%d bytes) must be greater than zero.",
V8ThrowException::CreateTypeError( options->buffersize()));
script_state->GetIsolate(), return ScriptPromise();
String::Format(
"Requested buffer size (%d bytes) must be greater than zero.",
options->buffersize())));
} }
if (options->buffersize() > kMaxBufferSize) { if (options->buffersize() > kMaxBufferSize) {
return ScriptPromise::Reject( exception_state.ThrowTypeError(
script_state, String::Format("Requested buffer size (%d bytes) is greater than "
V8ThrowException::CreateTypeError( "the maximum allowed (%d bytes).",
script_state->GetIsolate(), options->buffersize(), kMaxBufferSize));
String::Format("Requested buffer size (%d bytes) is greater than " return ScriptPromise();
"the maximum allowed (%d bytes).",
options->buffersize(), kMaxBufferSize)));
} }
buffer_size_ = options->buffersize(); buffer_size_ = options->buffersize();
...@@ -172,20 +164,18 @@ ScriptPromise SerialPort::open(ScriptState* script_state, ...@@ -172,20 +164,18 @@ ScriptPromise SerialPort::open(ScriptState* script_state,
mojo::ScopedDataPipeConsumerHandle readable_pipe; mojo::ScopedDataPipeConsumerHandle readable_pipe;
mojo::ScopedDataPipeProducerHandle readable_pipe_producer; mojo::ScopedDataPipeProducerHandle readable_pipe_producer;
if (!CreateDataPipe(&readable_pipe_producer, &readable_pipe)) { if (!CreateDataPipe(&readable_pipe_producer, &readable_pipe)) {
return ScriptPromise::RejectWithDOMException( exception_state.ThrowDOMException(DOMExceptionCode::kQuotaExceededError,
script_state, MakeGarbageCollected<DOMException>( kResourcesExhaustedReadBuffer);
DOMExceptionCode::kQuotaExceededError, return ScriptPromise();
kResourcesExhaustedReadBuffer));
} }
// Pipe handle pair for the WritableStream. // Pipe handle pair for the WritableStream.
mojo::ScopedDataPipeProducerHandle writable_pipe; mojo::ScopedDataPipeProducerHandle writable_pipe;
mojo::ScopedDataPipeConsumerHandle writable_pipe_consumer; mojo::ScopedDataPipeConsumerHandle writable_pipe_consumer;
if (!CreateDataPipe(&writable_pipe, &writable_pipe_consumer)) { if (!CreateDataPipe(&writable_pipe, &writable_pipe_consumer)) {
return ScriptPromise::RejectWithDOMException( exception_state.ThrowDOMException(DOMExceptionCode::kQuotaExceededError,
script_state, MakeGarbageCollected<DOMException>( kResourcesExhaustedWriteBuffer);
DOMExceptionCode::kQuotaExceededError, return ScriptPromise();
kResourcesExhaustedWriteBuffer));
} }
device::mojom::blink::SerialPortClientPtr client_ptr; device::mojom::blink::SerialPortClientPtr client_ptr;
...@@ -248,11 +238,12 @@ WritableStream* SerialPort::writable(ScriptState* script_state, ...@@ -248,11 +238,12 @@ WritableStream* SerialPort::writable(ScriptState* script_state,
return writable_; return writable_;
} }
ScriptPromise SerialPort::getSignals(ScriptState* script_state) { ScriptPromise SerialPort::getSignals(ScriptState* script_state,
ExceptionState& exception_state) {
if (!port_) { if (!port_) {
return ScriptPromise::RejectWithDOMException( exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
script_state, MakeGarbageCollected<DOMException>( kPortClosed);
DOMExceptionCode::kInvalidStateError, kPortClosed)); return ScriptPromise();
} }
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
...@@ -264,11 +255,12 @@ ScriptPromise SerialPort::getSignals(ScriptState* script_state) { ...@@ -264,11 +255,12 @@ ScriptPromise SerialPort::getSignals(ScriptState* script_state) {
} }
ScriptPromise SerialPort::setSignals(ScriptState* script_state, ScriptPromise SerialPort::setSignals(ScriptState* script_state,
const SerialOutputSignals* signals) { const SerialOutputSignals* signals,
ExceptionState& exception_state) {
if (!port_) { if (!port_) {
return ScriptPromise::RejectWithDOMException( exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
script_state, MakeGarbageCollected<DOMException>( kPortClosed);
DOMExceptionCode::kInvalidStateError, kPortClosed)); return ScriptPromise();
} }
auto mojo_signals = device::mojom::blink::SerialHostControlSignals::New(); auto mojo_signals = device::mojom::blink::SerialHostControlSignals::New();
......
...@@ -40,11 +40,15 @@ class SerialPort final : public ScriptWrappable, ...@@ -40,11 +40,15 @@ class SerialPort final : public ScriptWrappable,
~SerialPort() override; ~SerialPort() override;
// Web-exposed functions // Web-exposed functions
ScriptPromise open(ScriptState*, const SerialOptions* options); ScriptPromise open(ScriptState*,
const SerialOptions* options,
ExceptionState&);
ReadableStream* readable(ScriptState*, ExceptionState&); ReadableStream* readable(ScriptState*, ExceptionState&);
WritableStream* writable(ScriptState*, ExceptionState&); WritableStream* writable(ScriptState*, ExceptionState&);
ScriptPromise getSignals(ScriptState*); ScriptPromise getSignals(ScriptState*, ExceptionState&);
ScriptPromise setSignals(ScriptState*, const SerialOutputSignals*); ScriptPromise setSignals(ScriptState*,
const SerialOutputSignals*,
ExceptionState&);
void close(); void close();
const base::UnguessableToken& token() const { return info_->token; } const base::UnguessableToken& token() const { return info_->token; }
......
...@@ -13,11 +13,11 @@ ...@@ -13,11 +13,11 @@
[CallWith=ScriptState, RaisesException] [CallWith=ScriptState, RaisesException]
readonly attribute WritableStream writable; readonly attribute WritableStream writable;
[CallWith=ScriptState, MeasureAs=SerialPortOpen] [CallWith=ScriptState, RaisesException, MeasureAs=SerialPortOpen]
Promise<void> open(SerialOptions options); Promise<void> open(SerialOptions options);
[CallWith=ScriptState] [CallWith=ScriptState, RaisesException]
Promise<SerialInputSignals> getSignals(); Promise<SerialInputSignals> getSignals();
[CallWith=ScriptState] [CallWith=ScriptState, RaisesException]
Promise<void> setSignals(SerialOutputSignals signals); Promise<void> setSignals(SerialOutputSignals signals);
[MeasureAs=SerialPortClose] [MeasureAs=SerialPortClose]
void close(); void close();
......
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