Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2356)

Unified Diff: content/renderer/bluetooth/bluetooth_dispatcher.cc

Issue 1334763002: bluetooth: Subscribe to notifications (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@bluetooth-origin
Patch Set: Keep track of objects on the renderer side Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/renderer/bluetooth/bluetooth_dispatcher.cc
diff --git a/content/renderer/bluetooth/bluetooth_dispatcher.cc b/content/renderer/bluetooth/bluetooth_dispatcher.cc
index 1a4679e6d63291c6cb450c564ed1cd8f98f109ac..e9b256f53c63e9fd8c54aaee167f3ea469604386 100644
--- a/content/renderer/bluetooth/bluetooth_dispatcher.cc
+++ b/content/renderer/bluetooth/bluetooth_dispatcher.cc
@@ -15,6 +15,7 @@
#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothDevice.h"
#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothError.h"
#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTCharacteristic.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTCharacteristicDelegate.h"
#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTRemoteServer.h"
#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTService.h"
#include "third_party/WebKit/public/platform/modules/bluetooth/WebRequestDeviceOptions.h"
@@ -62,6 +63,21 @@ struct BluetoothCharacteristicRequest {
scoped_ptr<blink::WebBluetoothGetCharacteristicCallbacks> callbacks;
};
+struct BluetoothNotificationsRequest {
+ BluetoothNotificationsRequest(
+ blink::WebString characteristic_instance_id,
+ blink::WebBluetoothGATTCharacteristicDelegate* delegate,
+ blink::WebBluetoothNotificationsCallbacks* callbacks)
+ : characteristic_instance_id(characteristic_instance_id),
+ delegate(delegate),
+ callbacks(callbacks) {}
+ ~BluetoothNotificationsRequest() {}
+
+ blink::WebString characteristic_instance_id;
+ blink::WebBluetoothGATTCharacteristicDelegate* delegate;
Jeffrey Yasskin 2015/09/15 03:45:37 Can you comment how we know |delegate| will stay a
ortuno 2015/09/15 21:38:19 Well the execution context on the blink side owns
+ scoped_ptr<blink::WebBluetoothNotificationsCallbacks> callbacks;
+};
+
namespace content {
namespace {
@@ -143,6 +159,12 @@ void BluetoothDispatcher::OnMessageReceived(const IPC::Message& msg) {
OnWriteValueSuccess);
IPC_MESSAGE_HANDLER(BluetoothMsg_WriteCharacteristicValueError,
OnWriteValueError);
+ IPC_MESSAGE_HANDLER(BluetoothMsg_StartNotificationsSuccess,
+ OnStartNotificationsSuccess)
+ IPC_MESSAGE_HANDLER(BluetoothMsg_StartNotificationsError,
+ OnStartNotificationsError)
+ IPC_MESSAGE_HANDLER(BluetoothMsg_StopNotificationsSuccess,
+ OnStopNotificationsSuccess)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
DCHECK(handled) << "Unhandled message:" << msg.type();
@@ -225,10 +247,126 @@ void BluetoothDispatcher::writeValue(
CurrentWorkerId(), request_id, characteristic_instance_id.utf8(), value));
}
+void BluetoothDispatcher::startNotifications(
+ const blink::WebString& characteristic_instance_id,
+ blink::WebBluetoothGATTCharacteristicDelegate* delegate,
+ blink::WebBluetoothNotificationsCallbacks* callbacks) {
+ // If an object is already subcribed to notifications from the characteristic,
+ // no need to subscribe to the dispatcher host again.
+ if (IsActiveCharacteristicNotification(characteristic_instance_id)) {
+ AddToActiveNotificationsMap(characteristic_instance_id, delegate);
+ callbacks->onSuccess();
+ return;
+ }
+
+ int request_id = pending_start_notifications_requests_.Add(
+ new BluetoothNotificationsRequest(characteristic_instance_id, delegate,
+ callbacks));
+
+ Send(new BluetoothHostMsg_StartNotifications(
Jeffrey Yasskin 2015/09/15 03:45:37 Since you're creating the active_notifications ent
ortuno 2015/09/15 21:38:19 That seems like an unnecessary optimization. Sendi
+ CurrentWorkerId(), request_id, characteristic_instance_id.utf8()));
+}
+
+void BluetoothDispatcher::stopNotifications(
+ const blink::WebString& characteristic_instance_id,
+ blink::WebBluetoothGATTCharacteristicDelegate* delegate,
+ blink::WebBluetoothNotificationsCallbacks* callbacks) {
+ // If this is not an active characteristic then no need to unsubscribe.
+ if (!IsActiveCharacteristicNotification(characteristic_instance_id)) {
Jeffrey Yasskin 2015/09/15 03:45:37 I think you don't need this check. Removing the el
ortuno 2015/09/15 21:38:19 Reworked this part. Calling stopNotifications twic
+ callbacks->onSuccess();
+ return;
+ }
+
+ RemoveFromActiveNotificationsMap(characteristic_instance_id, delegate);
+
+ // If the characteristic is still active no need to unsubscribe.
+ if (IsActiveCharacteristicNotification(characteristic_instance_id)) {
+ callbacks->onSuccess();
+ return;
+ }
+
+ int request_id = pending_stop_notifications_requests_.Add(
+ new BluetoothNotificationsRequest(characteristic_instance_id, delegate,
+ callbacks));
+
+ Send(new BluetoothHostMsg_StopNotifications(
+ CurrentWorkerId(), request_id, characteristic_instance_id.utf8()));
+}
+
+void BluetoothDispatcher::characteristicDelegateRemoved(
+ const blink::WebString& characteristic_instance_id,
+ blink::WebBluetoothGATTCharacteristicDelegate* delegate) {
+ RemoveFromActiveNotificationsMap(characteristic_instance_id, delegate);
+
+ // If the characteristic is still active no need to unsubscribe.
+ if (IsActiveCharacteristicNotification(characteristic_instance_id)) {
+ return;
+ }
+
+ // There could be a request pending on a delegate so we need to check
+ // the requests map. We ignore the stop request since we don't use
+ // the delegate in those.
+ for (IDMap<BluetoothNotificationsRequest, IDMapOwnPointer>::iterator iter(
+ &pending_start_notifications_requests_);
+ !iter.IsAtEnd(); iter.Advance()) {
+ iter.GetCurrentValue()->delegate = nullptr;
+ }
+}
+
void BluetoothDispatcher::WillStopCurrentWorkerThread() {
delete this;
}
+bool BluetoothDispatcher::IsActiveCharacteristicNotification(
+ const blink::WebString& characteristic_instance_id) {
+ auto char_iter = active_characteristic_notifications.find(
+ characteristic_instance_id.utf8());
+
+ // If this is the first object that is subscribing to notifications then
+ // the characteristic is not active.
+ if (char_iter == active_characteristic_notifications.end()) {
+ return false;
+ }
+
+ // If no object is subscribed to notifications then the characteristic
+ // is not active.
+ if (char_iter->second.size() == 0) {
Jeffrey Yasskin 2015/09/15 03:45:37 We should make sure that we remove elements from t
ortuno 2015/09/15 21:38:20 Done.
+ return false;
+ }
+ return true;
+}
+
+void BluetoothDispatcher::AddToActiveNotificationsMap(
+ const blink::WebString& characteristic_instance_id,
+ blink::WebBluetoothGATTCharacteristicDelegate* delegate) {
+ auto char_iter = active_characteristic_notifications.find(
Jeffrey Yasskin 2015/09/15 03:45:37 This is a good place to use operator[]: std::set<
ortuno 2015/09/15 21:38:20 I don't like adding the delegates to the map befor
+ characteristic_instance_id.utf8());
+
+ // First object that subscribes to notifications for the characteristic.
+ if (char_iter == active_characteristic_notifications.end()) {
+ std::set<blink::WebBluetoothGATTCharacteristicDelegate*> delegates;
+ delegates.insert(delegate);
+ active_characteristic_notifications.insert(
+ std::make_pair(characteristic_instance_id.utf8(), delegates));
+ return;
+ }
+ // Otherwise add to already existing set.
+ char_iter->second.insert(delegate);
+}
+
+void BluetoothDispatcher::RemoveFromActiveNotificationsMap(
+ const blink::WebString& characteristic_instance_id,
+ blink::WebBluetoothGATTCharacteristicDelegate* delegate) {
+ auto char_iter = active_characteristic_notifications.find(
+ characteristic_instance_id.utf8());
+
+ if (char_iter == active_characteristic_notifications.end()) {
+ return;
+ }
+
+ char_iter->second.erase(delegate);
Jeffrey Yasskin 2015/09/15 03:45:37 If the set became empty, remove it from the map he
ortuno 2015/09/15 21:38:20 Done.
+}
+
void BluetoothDispatcher::OnRequestDeviceSuccess(
int thread_id,
int request_id,
@@ -386,4 +524,51 @@ void BluetoothDispatcher::OnWriteValueError(int thread_id,
pending_write_value_requests_.Remove(request_id);
}
+void BluetoothDispatcher::OnStartNotificationsSuccess(int thread_id,
+ int request_id) {
+ DCHECK(pending_start_notifications_requests_.Lookup(request_id))
+ << request_id;
+
+ BluetoothNotificationsRequest* request =
+ pending_start_notifications_requests_.Lookup(request_id);
+
+ // The object requesting the notification could have been destroyed
+ // while waiting for the subscription.
+ if (request->delegate != nullptr) {
Jeffrey Yasskin 2015/09/15 03:45:37 Could you comment that characteristicDelegateRemov
ortuno 2015/09/15 21:38:19 Done.
+ AddToActiveNotificationsMap(request->characteristic_instance_id,
+ request->delegate);
+ }
+ request->callbacks->onSuccess();
+
+ pending_start_notifications_requests_.Remove(request_id);
+}
+
+void BluetoothDispatcher::OnStartNotificationsError(int thread_id,
+ int request_id,
+ WebBluetoothError error) {
+ DCHECK(pending_start_notifications_requests_.Lookup(request_id))
+ << request_id;
+
+ pending_start_notifications_requests_.Lookup(request_id)
+ ->callbacks->onError(error);
+
+ pending_start_notifications_requests_.Remove(request_id);
+}
+
+void BluetoothDispatcher::OnStopNotificationsSuccess(int thread_id,
+ int request_id) {
+ DCHECK(pending_stop_notifications_requests_.Lookup(request_id)) << request_id;
+
+ BluetoothNotificationsRequest* request =
+ pending_stop_notifications_requests_.Lookup(request_id);
+
+ RemoveFromActiveNotificationsMap(request->characteristic_instance_id,
Jeffrey Yasskin 2015/09/15 03:45:37 You already called this before sending the stop IP
ortuno 2015/09/15 21:38:20 No longer calling this from stopNotifications.
+ request->delegate);
+
+ pending_stop_notifications_requests_.Lookup(request_id)
+ ->callbacks->onSuccess();
+
+ pending_stop_notifications_requests_.Remove(request_id);
+}
+
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698