Commit 5882ee35 authored by Harald Alvestrand's avatar Harald Alvestrand Committed by Commit Bot

Implement datachannel.onclosing event

Bug: chromium:1040584
Change-Id: Ic78ea01897ee3f8dd120ed6d638a1f70a288c26c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1991571
Auto-Submit: Harald Alvestrand <hta@chromium.org>
Reviewed-by: default avatarPhilip Jägenstedt <foolip@chromium.org>
Reviewed-by: default avatarHenrik Boström <hbos@chromium.org>
Reviewed-by: default avatarSteve Anton <steveanton@chromium.org>
Commit-Queue: Harald Alvestrand <hta@chromium.org>
Cr-Commit-Position: refs/heads/master@{#732632}
parent be9ead6f
...@@ -69,6 +69,7 @@ ...@@ -69,6 +69,7 @@
"checking", "checking",
"click", "click",
"close", "close",
"closing",
"complete", "complete",
"compositionend", "compositionend",
"compositionstart", "compositionstart",
......
...@@ -222,6 +222,7 @@ RTCDataChannel::RTCDataChannel( ...@@ -222,6 +222,7 @@ RTCDataChannel::RTCDataChannel(
buffered_amount_low_threshold_(0U), buffered_amount_low_threshold_(0U),
buffered_amount_(0U), buffered_amount_(0U),
stopped_(false), stopped_(false),
closed_from_owner_(false),
observer_(base::MakeRefCounted<Observer>( observer_(base::MakeRefCounted<Observer>(
context->GetTaskRunner(TaskType::kNetworking), context->GetTaskRunner(TaskType::kNetworking),
this, this,
...@@ -427,6 +428,7 @@ void RTCDataChannel::send(Blob* data, ExceptionState& exception_state) { ...@@ -427,6 +428,7 @@ void RTCDataChannel::send(Blob* data, ExceptionState& exception_state) {
void RTCDataChannel::close() { void RTCDataChannel::close() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
closed_from_owner_ = true;
if (observer_) if (observer_)
channel()->Close(); channel()->Close();
// Note that even though Close() will run synchronously, the readyState has // Note that even though Close() will run synchronously, the readyState has
...@@ -459,9 +461,10 @@ bool RTCDataChannel::HasPendingActivity() const { ...@@ -459,9 +461,10 @@ bool RTCDataChannel::HasPendingActivity() const {
// A RTCDataChannel object must not be garbage collected if its // A RTCDataChannel object must not be garbage collected if its
// * readyState is connecting and at least one event listener is registered // * readyState is connecting and at least one event listener is registered
// for open events, message events, error events, or close events. // for open events, message events, error events, closing events
// or close events.
// * readyState is open and at least one event listener is registered for // * readyState is open and at least one event listener is registered for
// message events, error events, or close events. // message events, error events, closing events, or close events.
// * readyState is closing and at least one event listener is registered for // * readyState is closing and at least one event listener is registered for
// error events, or close events. // error events, or close events.
// * underlying data transport is established and data is queued to be // * underlying data transport is established and data is queued to be
...@@ -472,7 +475,8 @@ bool RTCDataChannel::HasPendingActivity() const { ...@@ -472,7 +475,8 @@ bool RTCDataChannel::HasPendingActivity() const {
has_valid_listeners |= HasEventListeners(event_type_names::kOpen); has_valid_listeners |= HasEventListeners(event_type_names::kOpen);
FALLTHROUGH; FALLTHROUGH;
case webrtc::DataChannelInterface::kOpen: case webrtc::DataChannelInterface::kOpen:
has_valid_listeners |= HasEventListeners(event_type_names::kMessage); has_valid_listeners |= HasEventListeners(event_type_names::kMessage) ||
HasEventListeners(event_type_names::kClosing);
FALLTHROUGH; FALLTHROUGH;
case webrtc::DataChannelInterface::kClosing: case webrtc::DataChannelInterface::kClosing:
has_valid_listeners |= HasEventListeners(event_type_names::kError) || has_valid_listeners |= HasEventListeners(event_type_names::kError) ||
...@@ -509,6 +513,11 @@ void RTCDataChannel::OnStateChange( ...@@ -509,6 +513,11 @@ void RTCDataChannel::OnStateChange(
IncrementCounter(DataChannelCounters::kOpened); IncrementCounter(DataChannelCounters::kOpened);
ScheduleDispatchEvent(Event::Create(event_type_names::kOpen)); ScheduleDispatchEvent(Event::Create(event_type_names::kOpen));
break; break;
case webrtc::DataChannelInterface::kClosing:
if (!closed_from_owner_) {
ScheduleDispatchEvent(Event::Create(event_type_names::kClosing));
}
break;
case webrtc::DataChannelInterface::kClosed: case webrtc::DataChannelInterface::kClosed:
if (!channel()->error().ok()) { if (!channel()->error().ok()) {
ScheduleDispatchEvent(MakeGarbageCollected<RTCErrorEvent>( ScheduleDispatchEvent(MakeGarbageCollected<RTCErrorEvent>(
......
...@@ -91,6 +91,7 @@ class MODULES_EXPORT RTCDataChannel final ...@@ -91,6 +91,7 @@ class MODULES_EXPORT RTCDataChannel final
DEFINE_ATTRIBUTE_EVENT_LISTENER(bufferedamountlow, kBufferedamountlow) DEFINE_ATTRIBUTE_EVENT_LISTENER(bufferedamountlow, kBufferedamountlow)
DEFINE_ATTRIBUTE_EVENT_LISTENER(error, kError) DEFINE_ATTRIBUTE_EVENT_LISTENER(error, kError)
DEFINE_ATTRIBUTE_EVENT_LISTENER(close, kClose) DEFINE_ATTRIBUTE_EVENT_LISTENER(close, kClose)
DEFINE_ATTRIBUTE_EVENT_LISTENER(closing, kClosing)
DEFINE_ATTRIBUTE_EVENT_LISTENER(message, kMessage) DEFINE_ATTRIBUTE_EVENT_LISTENER(message, kMessage)
// EventTarget // EventTarget
...@@ -174,6 +175,7 @@ class MODULES_EXPORT RTCDataChannel final ...@@ -174,6 +175,7 @@ class MODULES_EXPORT RTCDataChannel final
unsigned buffered_amount_low_threshold_; unsigned buffered_amount_low_threshold_;
unsigned buffered_amount_; unsigned buffered_amount_;
bool stopped_; bool stopped_;
bool closed_from_owner_;
scoped_refptr<Observer> observer_; scoped_refptr<Observer> observer_;
THREAD_CHECKER(thread_checker_); THREAD_CHECKER(thread_checker_);
}; };
......
...@@ -51,6 +51,7 @@ enum RTCDataChannelState { ...@@ -51,6 +51,7 @@ enum RTCDataChannelState {
attribute EventHandler onopen; attribute EventHandler onopen;
attribute EventHandler onbufferedamountlow; attribute EventHandler onbufferedamountlow;
attribute EventHandler onerror; attribute EventHandler onerror;
attribute EventHandler onclosing;
attribute EventHandler onclose; attribute EventHandler onclose;
void close(); void close();
attribute EventHandler onmessage; attribute EventHandler onmessage;
......
...@@ -12,15 +12,23 @@ promise_test(async t => { ...@@ -12,15 +12,23 @@ promise_test(async t => {
let pc1 = new RTCPeerConnection(); let pc1 = new RTCPeerConnection();
t.add_cleanup(() => pc1.close()); t.add_cleanup(() => pc1.close());
let [channel1, channel2] = await createDataChannelPair(pc1); let [channel1, channel2] = await createDataChannelPair(pc1);
let close_handler = new Promise(resolve => { let closeHandler = new Promise(resolve => {
channel2.onclose = event => { channel2.onclose = event => {
resolve(); resolve();
}; };
}); });
let closingSeen = false;
channel1.onclosing = t.unreached_func();
channel2.onclosing = event => {
assert_equals(channel2.readyState, 'closing');
closingSeen = true;
}
channel2.addEventListener('error', t.unreached_func()); channel2.addEventListener('error', t.unreached_func());
channel1.close(); channel1.close();
await close_handler; await closeHandler;
}, 'Close datachannel causes onclose to be called'); assert_equals(channel2.readyState, 'closed');
assert_true(closingSeen, 'Closing event was seen');
}, 'Close datachannel causes onclosing and onclose to be called');
promise_test(async t => { promise_test(async t => {
// This is the same test as above, but using addEventListener // This is the same test as above, but using addEventListener
...@@ -28,15 +36,23 @@ promise_test(async t => { ...@@ -28,15 +36,23 @@ promise_test(async t => {
let pc1 = new RTCPeerConnection(); let pc1 = new RTCPeerConnection();
t.add_cleanup(() => pc1.close()); t.add_cleanup(() => pc1.close());
let [channel1, channel2] = await createDataChannelPair(pc1); let [channel1, channel2] = await createDataChannelPair(pc1);
let close_handler = new Promise(resolve => { let closeHandler = new Promise(resolve => {
channel2.addEventListener('close', event => { channel2.addEventListener('close', event => {
resolve(); resolve();
}); });
}); });
let closingSeen = false;
channel1.addEventListener('closing', t.unreached_func());
channel2.addEventListener('closing', event => {
assert_equals(channel2.readyState, 'closing');
closingSeen = true;
});
channel2.addEventListener('error', t.unreached_func()); channel2.addEventListener('error', t.unreached_func());
channel1.close(); channel1.close();
await close_handler; await closeHandler;
}, 'Close datachannel causes close event to be called'); assert_equals(channel2.readyState, 'closed');
assert_true(closingSeen, 'Closing event was seen');
}, 'Close datachannel causes closing and close event to be called');
promise_test(async t => { promise_test(async t => {
let pc1 = new RTCPeerConnection(); let pc1 = new RTCPeerConnection();
...@@ -44,13 +60,13 @@ promise_test(async t => { ...@@ -44,13 +60,13 @@ promise_test(async t => {
let [channel1, channel2] = await createDataChannelPair(pc1); let [channel1, channel2] = await createDataChannelPair(pc1);
let events = []; let events = [];
let error = null; let error = null;
let close_handler = new Promise(resolve => { let closeHandler = new Promise(resolve => {
channel2.addEventListener('close', event => { channel2.addEventListener('close', event => {
events.push('close'); events.push('close');
resolve(); resolve();
}); });
}); });
let error_handler = new Promise((resolve, reject) => { let errorHandler = new Promise((resolve, reject) => {
channel2.addEventListener('error', event => { channel2.addEventListener('error', event => {
events.push('error'); events.push('error');
try { try {
...@@ -64,8 +80,8 @@ promise_test(async t => { ...@@ -64,8 +80,8 @@ promise_test(async t => {
}); });
}); });
pc1.close(); pc1.close();
await error_handler; await errorHandler;
await close_handler; await closeHandler;
// Error should fire before close. // Error should fire before close.
assert_array_equals(['error', 'close'], events); assert_array_equals(['error', 'close'], events);
assert_true(error instanceof RTCError); assert_true(error instanceof RTCError);
......
This is a testharness.js-based test. This is a testharness.js-based test.
Found 496 tests; 466 PASS, 30 FAIL, 0 TIMEOUT, 0 NOTRUN. Found 496 tests; 468 PASS, 28 FAIL, 0 TIMEOUT, 0 NOTRUN.
PASS idl_test setup PASS idl_test setup
PASS idl_test validation PASS idl_test validation
PASS Test driver for asyncInitCertificate PASS Test driver for asyncInitCertificate
...@@ -407,7 +407,7 @@ PASS RTCDataChannel interface: attribute bufferedAmountLowThreshold ...@@ -407,7 +407,7 @@ PASS RTCDataChannel interface: attribute bufferedAmountLowThreshold
PASS RTCDataChannel interface: attribute onopen PASS RTCDataChannel interface: attribute onopen
PASS RTCDataChannel interface: attribute onbufferedamountlow PASS RTCDataChannel interface: attribute onbufferedamountlow
PASS RTCDataChannel interface: attribute onerror PASS RTCDataChannel interface: attribute onerror
FAIL RTCDataChannel interface: attribute onclosing assert_true: The prototype object must have a property "onclosing" expected true got false PASS RTCDataChannel interface: attribute onclosing
PASS RTCDataChannel interface: attribute onclose PASS RTCDataChannel interface: attribute onclose
PASS RTCDataChannel interface: operation close() PASS RTCDataChannel interface: operation close()
PASS RTCDataChannel interface: attribute onmessage PASS RTCDataChannel interface: attribute onmessage
...@@ -431,7 +431,7 @@ PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') mus ...@@ -431,7 +431,7 @@ PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') mus
PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onopen" with the proper type PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onopen" with the proper type
PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onbufferedamountlow" with the proper type PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onbufferedamountlow" with the proper type
PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onerror" with the proper type PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onerror" with the proper type
FAIL RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onclosing" with the proper type assert_inherits: property "onclosing" not found in prototype chain PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onclosing" with the proper type
PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onclose" with the proper type PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onclose" with the proper type
PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "close()" with the proper type PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "close()" with the proper type
PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onmessage" with the proper type PASS RTCDataChannel interface: new RTCPeerConnection().createDataChannel('') must inherit property "onmessage" with the proper type
......
...@@ -5106,6 +5106,7 @@ interface RTCDataChannel : EventTarget ...@@ -5106,6 +5106,7 @@ interface RTCDataChannel : EventTarget
getter negotiated getter negotiated
getter onbufferedamountlow getter onbufferedamountlow
getter onclose getter onclose
getter onclosing
getter onerror getter onerror
getter onmessage getter onmessage
getter onopen getter onopen
...@@ -5120,6 +5121,7 @@ interface RTCDataChannel : EventTarget ...@@ -5120,6 +5121,7 @@ interface RTCDataChannel : EventTarget
setter bufferedAmountLowThreshold setter bufferedAmountLowThreshold
setter onbufferedamountlow setter onbufferedamountlow
setter onclose setter onclose
setter onclosing
setter onerror setter onerror
setter onmessage setter onmessage
setter onopen setter onopen
......
...@@ -6234,6 +6234,7 @@ interface RTCDataChannel : EventTarget ...@@ -6234,6 +6234,7 @@ interface RTCDataChannel : EventTarget
getter negotiated getter negotiated
getter onbufferedamountlow getter onbufferedamountlow
getter onclose getter onclose
getter onclosing
getter onerror getter onerror
getter onmessage getter onmessage
getter onopen getter onopen
...@@ -6248,6 +6249,7 @@ interface RTCDataChannel : EventTarget ...@@ -6248,6 +6249,7 @@ interface RTCDataChannel : EventTarget
setter bufferedAmountLowThreshold setter bufferedAmountLowThreshold
setter onbufferedamountlow setter onbufferedamountlow
setter onclose setter onclose
setter onclosing
setter onerror setter onerror
setter onmessage setter onmessage
setter onopen setter onopen
......
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