| Index: third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTServer.cpp
|
| diff --git a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTServer.cpp b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTServer.cpp
|
| index a3fccdf812cf473a4df53b47e5038142f049ea44..c20d903f2e9b1cef827ee449484e4cfb5424933a 100644
|
| --- a/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTServer.cpp
|
| +++ b/third_party/WebKit/Source/modules/bluetooth/BluetoothRemoteGATTServer.cpp
|
| @@ -15,14 +15,16 @@
|
| #include "modules/bluetooth/BluetoothError.h"
|
| #include "modules/bluetooth/BluetoothRemoteGATTService.h"
|
| #include "modules/bluetooth/BluetoothUUID.h"
|
| -#include "mojo/public/cpp/bindings/associated_interface_ptr.h"
|
| #include <utility>
|
|
|
| namespace blink {
|
|
|
| BluetoothRemoteGATTServer::BluetoothRemoteGATTServer(ExecutionContext* context,
|
| BluetoothDevice* device)
|
| - : ContextLifecycleObserver(context), m_device(device), m_connected(false) {}
|
| + : ContextLifecycleObserver(context),
|
| + m_clientBinding(this),
|
| + m_device(device),
|
| + m_connected(false) {}
|
|
|
| BluetoothRemoteGATTServer* BluetoothRemoteGATTServer::Create(
|
| ExecutionContext* context,
|
| @@ -35,7 +37,11 @@ void BluetoothRemoteGATTServer::contextDestroyed(ExecutionContext*) {
|
| }
|
|
|
| void BluetoothRemoteGATTServer::GATTServerDisconnected() {
|
| - DispatchDisconnected();
|
| + if (!m_connected) {
|
| + return;
|
| + }
|
| + DCHECK(m_clientBinding.is_bound());
|
| + CleanupDisconnectedDevice(true /* dispatchEvent */);
|
| }
|
|
|
| void BluetoothRemoteGATTServer::AddToActiveAlgorithms(
|
| @@ -53,35 +59,41 @@ bool BluetoothRemoteGATTServer::RemoveFromActiveAlgorithms(
|
| return true;
|
| }
|
|
|
| -void BluetoothRemoteGATTServer::DisconnectIfConnected() {
|
| - if (m_connected) {
|
| - SetConnected(false);
|
| - ClearActiveAlgorithms();
|
| - mojom::blink::WebBluetoothService* service =
|
| - m_device->bluetooth()->Service();
|
| - service->RemoteServerDisconnect(m_device->id());
|
| - }
|
| -}
|
| -
|
| -void BluetoothRemoteGATTServer::CleanupDisconnectedDeviceAndFireEvent() {
|
| +void BluetoothRemoteGATTServer::CleanupDisconnectedDevice(bool dispatchEvent) {
|
| + // This implements the specification "clean up the disconnected device"
|
| + // algorithm:
|
| + // https://webbluetoothcg.github.io/web-bluetooth/#clean-up-the-disconnected-device
|
| DCHECK(m_connected);
|
| SetConnected(false);
|
| ClearActiveAlgorithms();
|
| - m_device->ClearAttributeInstanceMapAndFireEvent();
|
| + m_device->ClearAttributeInstanceMap();
|
| + // Below this line there are steps in the above specification which we are
|
| + // not explicitly handling here: clearing the representedService,
|
| + // representedCharacteristic and representedDescriptors is done by
|
| + // ClearAttributeInstanceMap(). The notification context is implemented in
|
| + // the browser so it cleans up itself.
|
| + if (dispatchEvent) {
|
| + m_device->dispatchEvent(
|
| + Event::createBubble(EventTypeNames::gattserverdisconnected));
|
| + }
|
| }
|
|
|
| -void BluetoothRemoteGATTServer::DispatchDisconnected() {
|
| +void BluetoothRemoteGATTServer::HandleClientConnectionError() {
|
| if (!m_connected) {
|
| return;
|
| }
|
| - CleanupDisconnectedDeviceAndFireEvent();
|
| + CleanupDisconnectedDevice(true /* dispatchEvent */);
|
| }
|
|
|
| void BluetoothRemoteGATTServer::Dispose() {
|
| - DisconnectIfConnected();
|
| - // The pipe to this object must be closed when is marked unreachable to
|
| - // prevent messages from being dispatched before lazy sweeping.
|
| - m_clientBindings.CloseAllBindings();
|
| + if (!m_connected) {
|
| + return;
|
| + }
|
| + // The object is being garbage collected or the context is being destroyed,
|
| + // so no need to dispatch a gattserverdisconnected event.
|
| + CleanupDisconnectedDevice(false /* dispatchEvent */);
|
| + DCHECK(m_clientBinding.is_bound());
|
| + m_clientBinding.Close();
|
| }
|
|
|
| DEFINE_TRACE(BluetoothRemoteGATTServer) {
|
| @@ -109,27 +121,45 @@ ScriptPromise BluetoothRemoteGATTServer::connect(ScriptState* scriptState) {
|
| ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
|
| ScriptPromise promise = resolver->promise();
|
|
|
| - mojom::blink::WebBluetoothService* service = m_device->bluetooth()->Service();
|
| - mojom::blink::WebBluetoothServerClientAssociatedPtrInfo ptrInfo;
|
| - auto request = mojo::MakeRequest(&ptrInfo);
|
| - m_clientBindings.AddBinding(this, std::move(request));
|
| -
|
| - service->RemoteServerConnect(
|
| - m_device->id(), std::move(ptrInfo),
|
| - convertToBaseCallback(
|
| - WTF::bind(&BluetoothRemoteGATTServer::ConnectCallback,
|
| - wrapPersistent(this), wrapPersistent(resolver))));
|
| + if (m_connected) {
|
| + resolver->resolve(this);
|
| + } else {
|
| + mojom::blink::WebBluetoothService* service =
|
| + m_device->bluetooth()->Service();
|
| + mojom::blink::WebBluetoothServerClientAssociatedPtrInfo ptrInfo;
|
| + m_clientBinding.Bind(&ptrInfo);
|
| + m_clientBinding.set_connection_error_handler(convertToBaseCallback(
|
| + WTF::bind(&BluetoothRemoteGATTServer::HandleClientConnectionError,
|
| + wrapWeakPersistent(this))));
|
| +
|
| + service->RemoteServerConnect(
|
| + m_device->id(), std::move(ptrInfo),
|
| + convertToBaseCallback(
|
| + WTF::bind(&BluetoothRemoteGATTServer::ConnectCallback,
|
| + wrapPersistent(this), wrapPersistent(resolver))));
|
| + }
|
|
|
| return promise;
|
| }
|
|
|
| void BluetoothRemoteGATTServer::disconnect(ScriptState* scriptState) {
|
| - if (!m_connected)
|
| + // ClearActiveAlgorithms() implements the specification
|
| + // "1. Clear this.[[activeAlgorithms]] to abort any active connect() calls."
|
| + // at:
|
| + // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-disconnect
|
| + // connect() calls will add a promise to this active algorithms map. When
|
| + // connect's callback is run we check that the promise is still in this
|
| + // map and if not we reject the promise. During this, |m_connected| stays
|
| + // false so if we want to actually cancel the connection we need to do so
|
| + // before the |m_connected| check.
|
| + ClearActiveAlgorithms();
|
| + if (!m_connected) {
|
| return;
|
| - CleanupDisconnectedDeviceAndFireEvent();
|
| - m_clientBindings.CloseAllBindings();
|
| - mojom::blink::WebBluetoothService* service = m_device->bluetooth()->Service();
|
| - service->RemoteServerDisconnect(m_device->id());
|
| + }
|
| + CleanupDisconnectedDevice(true /* dispatchEvent */);
|
| + DCHECK(m_clientBinding.is_bound());
|
| + // Implicitly signals disconnect via the connection_error_handler.
|
| + m_clientBinding.Close();
|
| }
|
|
|
| // Callback that allows us to resolve the promise with a single service or
|
|
|