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