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 |