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

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: Address jyasskin's comments 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
« no previous file with comments | « content/renderer/bluetooth/bluetooth_dispatcher.h ('k') | content/renderer/bluetooth/web_bluetooth_impl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..2e83e4fd3e49219fdf56ffdc9e82a63438554c0c 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,25 @@ 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;
+ // Note that the delegate is owned by the execution context on the blink
+ // side which can destroy the delegate at any point. Since the delegate
+ // implements ActiveDOMObject we do get notify when it's being destroyed,
+ // so we can remove any references to it.
+ blink::WebBluetoothGATTCharacteristicDelegate* delegate;
+ scoped_ptr<blink::WebBluetoothNotificationsCallbacks> callbacks;
+};
+
namespace content {
namespace {
@@ -143,6 +163,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 +251,145 @@ 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 (HasActiveCharacteristicNotification(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(
+ 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 (!HasActiveCharacteristicNotification(characteristic_instance_id)) {
+ callbacks->onSuccess();
+ return;
+ }
+
+ if (WillBeActiveNotificationWhenRemoved(characteristic_instance_id,
+ delegate)) {
+ RemoveFromActiveNotificationsMap(characteristic_instance_id, delegate);
+ 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 (HasActiveCharacteristicNotification(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::HasActiveCharacteristicNotification(
+ const blink::WebString& characteristic_instance_id) {
+ auto char_iter = active_characteristic_notifications.find(
+ characteristic_instance_id.utf8());
+
+ // An active characteristic will point to a set of delegates.
+ if (char_iter == active_characteristic_notifications.end()) {
+ return false;
+ }
+
+ return true;
+}
+
+void BluetoothDispatcher::AddToActiveNotificationsMap(
+ const blink::WebString& characteristic_instance_id,
+ blink::WebBluetoothGATTCharacteristicDelegate* delegate) {
+ auto char_iter = active_characteristic_notifications.find(
+ 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);
+}
+
+bool BluetoothDispatcher::WillBeActiveNotificationWhenRemoved(
+ const blink::WebString& characteristic_instance_id,
+ blink::WebBluetoothGATTCharacteristicDelegate* delegate) {
+ auto char_iter = active_characteristic_notifications.find(
+ characteristic_instance_id.utf8());
+
+ // The characteristic will point to a set as long as there is at least
+ // one delegate subscribed to notifications.
+ if (char_iter == active_characteristic_notifications.end()) {
+ return false;
+ }
+ const std::set<blink::WebBluetoothGATTCharacteristicDelegate*>& delegate_set =
+ char_iter->second;
+ // If we find the delegate and the size of the set is one then removing
+ // the delegate will make the notification inactive.
+ if (delegate_set.find(delegate) != delegate_set.end() &&
+ delegate_set.size() == 1) {
+ return false;
+ }
+ return true;
+}
+
+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);
+
+ if (char_iter->second.size() == 0) {
+ active_characteristic_notifications.erase(char_iter);
+ }
+}
+
void BluetoothDispatcher::OnRequestDeviceSuccess(
int thread_id,
int request_id,
@@ -386,4 +547,52 @@ 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. characteristicDelegateRemoved
+ // nulls the delegate when the delegate gets destroyed.
+ if (request->delegate != nullptr) {
ortuno 2015/09/16 16:30:08 Argh. This doesn't work. If the delegate gets dest
+ 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,
+ request->delegate);
+
+ pending_stop_notifications_requests_.Lookup(request_id)
+ ->callbacks->onSuccess();
+
+ pending_stop_notifications_requests_.Remove(request_id);
+}
+
} // namespace content
« no previous file with comments | « content/renderer/bluetooth/bluetooth_dispatcher.h ('k') | content/renderer/bluetooth/web_bluetooth_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698