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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/bluetooth/bluetooth_dispatcher.h" 5 #include "content/renderer/bluetooth/bluetooth_dispatcher.h"
6 6
7 #include "base/lazy_instance.h" 7 #include "base/lazy_instance.h"
8 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h" 9 #include "base/message_loop/message_loop.h"
10 #include "base/thread_task_runner_handle.h" 10 #include "base/thread_task_runner_handle.h"
11 #include "content/child/thread_safe_sender.h" 11 #include "content/child/thread_safe_sender.h"
12 #include "content/common/bluetooth/bluetooth_messages.h" 12 #include "content/common/bluetooth/bluetooth_messages.h"
13 #include "device/bluetooth/bluetooth_uuid.h" 13 #include "device/bluetooth/bluetooth_uuid.h"
14 #include "third_party/WebKit/public/platform/WebPassOwnPtr.h" 14 #include "third_party/WebKit/public/platform/WebPassOwnPtr.h"
15 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothDevic e.h" 15 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothDevic e.h"
16 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothError .h" 16 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothError .h"
17 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTC haracteristic.h" 17 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTC haracteristic.h"
18 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTC haracteristicDelegate.h"
18 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTR emoteServer.h" 19 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTR emoteServer.h"
19 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTS ervice.h" 20 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTS ervice.h"
20 #include "third_party/WebKit/public/platform/modules/bluetooth/WebRequestDeviceO ptions.h" 21 #include "third_party/WebKit/public/platform/modules/bluetooth/WebRequestDeviceO ptions.h"
21 22
22 using blink::WebBluetoothConnectGATTCallbacks; 23 using blink::WebBluetoothConnectGATTCallbacks;
23 using blink::WebBluetoothDevice; 24 using blink::WebBluetoothDevice;
24 using blink::WebBluetoothError; 25 using blink::WebBluetoothError;
25 using blink::WebBluetoothGATTCharacteristic; 26 using blink::WebBluetoothGATTCharacteristic;
26 using blink::WebBluetoothGATTRemoteServer; 27 using blink::WebBluetoothGATTRemoteServer;
27 using blink::WebBluetoothGATTService; 28 using blink::WebBluetoothGATTService;
(...skipping 27 matching lines...) Expand all
55 : service_instance_id(service_instance_id), 56 : service_instance_id(service_instance_id),
56 characteristic_uuid(characteristic_uuid), 57 characteristic_uuid(characteristic_uuid),
57 callbacks(callbacks) {} 58 callbacks(callbacks) {}
58 ~BluetoothCharacteristicRequest() {} 59 ~BluetoothCharacteristicRequest() {}
59 60
60 blink::WebString service_instance_id; 61 blink::WebString service_instance_id;
61 blink::WebString characteristic_uuid; 62 blink::WebString characteristic_uuid;
62 scoped_ptr<blink::WebBluetoothGetCharacteristicCallbacks> callbacks; 63 scoped_ptr<blink::WebBluetoothGetCharacteristicCallbacks> callbacks;
63 }; 64 };
64 65
66 struct BluetoothNotificationsRequest {
67 BluetoothNotificationsRequest(
68 blink::WebString characteristic_instance_id,
69 blink::WebBluetoothGATTCharacteristicDelegate* delegate,
70 blink::WebBluetoothNotificationsCallbacks* callbacks)
71 : characteristic_instance_id(characteristic_instance_id),
72 delegate(delegate),
73 callbacks(callbacks) {}
74 ~BluetoothNotificationsRequest() {}
75
76 blink::WebString characteristic_instance_id;
77 // Note that the delegate is owned by the execution context on the blink
78 // side which can destroy the delegate at any point. Since the delegate
79 // implements ActiveDOMObject we do get notify when it's being destroyed,
80 // so we can remove any references to it.
81 blink::WebBluetoothGATTCharacteristicDelegate* delegate;
82 scoped_ptr<blink::WebBluetoothNotificationsCallbacks> callbacks;
83 };
84
65 namespace content { 85 namespace content {
66 86
67 namespace { 87 namespace {
68 88
69 base::LazyInstance<base::ThreadLocalPointer<void>>::Leaky g_dispatcher_tls = 89 base::LazyInstance<base::ThreadLocalPointer<void>>::Leaky g_dispatcher_tls =
70 LAZY_INSTANCE_INITIALIZER; 90 LAZY_INSTANCE_INITIALIZER;
71 91
72 void* const kHasBeenDeleted = reinterpret_cast<void*>(0x1); 92 void* const kHasBeenDeleted = reinterpret_cast<void*>(0x1);
73 93
74 int CurrentWorkerId() { 94 int CurrentWorkerId() {
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 IPC_MESSAGE_HANDLER(BluetoothMsg_GetCharacteristicError, 156 IPC_MESSAGE_HANDLER(BluetoothMsg_GetCharacteristicError,
137 OnGetCharacteristicError); 157 OnGetCharacteristicError);
138 IPC_MESSAGE_HANDLER(BluetoothMsg_ReadCharacteristicValueSuccess, 158 IPC_MESSAGE_HANDLER(BluetoothMsg_ReadCharacteristicValueSuccess,
139 OnReadValueSuccess); 159 OnReadValueSuccess);
140 IPC_MESSAGE_HANDLER(BluetoothMsg_ReadCharacteristicValueError, 160 IPC_MESSAGE_HANDLER(BluetoothMsg_ReadCharacteristicValueError,
141 OnReadValueError); 161 OnReadValueError);
142 IPC_MESSAGE_HANDLER(BluetoothMsg_WriteCharacteristicValueSuccess, 162 IPC_MESSAGE_HANDLER(BluetoothMsg_WriteCharacteristicValueSuccess,
143 OnWriteValueSuccess); 163 OnWriteValueSuccess);
144 IPC_MESSAGE_HANDLER(BluetoothMsg_WriteCharacteristicValueError, 164 IPC_MESSAGE_HANDLER(BluetoothMsg_WriteCharacteristicValueError,
145 OnWriteValueError); 165 OnWriteValueError);
166 IPC_MESSAGE_HANDLER(BluetoothMsg_StartNotificationsSuccess,
167 OnStartNotificationsSuccess)
168 IPC_MESSAGE_HANDLER(BluetoothMsg_StartNotificationsError,
169 OnStartNotificationsError)
170 IPC_MESSAGE_HANDLER(BluetoothMsg_StopNotificationsSuccess,
171 OnStopNotificationsSuccess)
146 IPC_MESSAGE_UNHANDLED(handled = false) 172 IPC_MESSAGE_UNHANDLED(handled = false)
147 IPC_END_MESSAGE_MAP() 173 IPC_END_MESSAGE_MAP()
148 DCHECK(handled) << "Unhandled message:" << msg.type(); 174 DCHECK(handled) << "Unhandled message:" << msg.type();
149 } 175 }
150 176
151 void BluetoothDispatcher::requestDevice( 177 void BluetoothDispatcher::requestDevice(
152 int frame_routing_id, 178 int frame_routing_id,
153 const WebRequestDeviceOptions& options, 179 const WebRequestDeviceOptions& options,
154 blink::WebBluetoothRequestDeviceCallbacks* callbacks) { 180 blink::WebBluetoothRequestDeviceCallbacks* callbacks) {
155 int request_id = pending_requests_.Add(callbacks); 181 int request_id = pending_requests_.Add(callbacks);
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 void BluetoothDispatcher::writeValue( 244 void BluetoothDispatcher::writeValue(
219 const blink::WebString& characteristic_instance_id, 245 const blink::WebString& characteristic_instance_id,
220 const std::vector<uint8_t>& value, 246 const std::vector<uint8_t>& value,
221 blink::WebBluetoothWriteValueCallbacks* callbacks) { 247 blink::WebBluetoothWriteValueCallbacks* callbacks) {
222 int request_id = pending_write_value_requests_.Add(callbacks); 248 int request_id = pending_write_value_requests_.Add(callbacks);
223 249
224 Send(new BluetoothHostMsg_WriteValue( 250 Send(new BluetoothHostMsg_WriteValue(
225 CurrentWorkerId(), request_id, characteristic_instance_id.utf8(), value)); 251 CurrentWorkerId(), request_id, characteristic_instance_id.utf8(), value));
226 } 252 }
227 253
254 void BluetoothDispatcher::startNotifications(
255 const blink::WebString& characteristic_instance_id,
256 blink::WebBluetoothGATTCharacteristicDelegate* delegate,
257 blink::WebBluetoothNotificationsCallbacks* callbacks) {
258 // If an object is already subcribed to notifications from the characteristic,
259 // no need to subscribe to the dispatcher host again.
260 if (HasActiveCharacteristicNotification(characteristic_instance_id)) {
261 AddToActiveNotificationsMap(characteristic_instance_id, delegate);
262 callbacks->onSuccess();
263 return;
264 }
265
266 int request_id = pending_start_notifications_requests_.Add(
267 new BluetoothNotificationsRequest(characteristic_instance_id, delegate,
268 callbacks));
269
270 Send(new BluetoothHostMsg_StartNotifications(
271 CurrentWorkerId(), request_id, characteristic_instance_id.utf8()));
272 }
273
274 void BluetoothDispatcher::stopNotifications(
275 const blink::WebString& characteristic_instance_id,
276 blink::WebBluetoothGATTCharacteristicDelegate* delegate,
277 blink::WebBluetoothNotificationsCallbacks* callbacks) {
278 // If this is not an active characteristic then no need to unsubscribe.
279 if (!HasActiveCharacteristicNotification(characteristic_instance_id)) {
280 callbacks->onSuccess();
281 return;
282 }
283
284 if (WillBeActiveNotificationWhenRemoved(characteristic_instance_id,
285 delegate)) {
286 RemoveFromActiveNotificationsMap(characteristic_instance_id, delegate);
287 callbacks->onSuccess();
288 return;
289 }
290
291 int request_id = pending_stop_notifications_requests_.Add(
292 new BluetoothNotificationsRequest(characteristic_instance_id, delegate,
293 callbacks));
294
295 Send(new BluetoothHostMsg_StopNotifications(
296 CurrentWorkerId(), request_id, characteristic_instance_id.utf8()));
297 }
298
299 void BluetoothDispatcher::characteristicDelegateRemoved(
300 const blink::WebString& characteristic_instance_id,
301 blink::WebBluetoothGATTCharacteristicDelegate* delegate) {
302 RemoveFromActiveNotificationsMap(characteristic_instance_id, delegate);
303
304 // If the characteristic is still active no need to unsubscribe.
305 if (HasActiveCharacteristicNotification(characteristic_instance_id)) {
306 return;
307 }
308
309 // There could be a request pending on a delegate so we need to check
310 // the requests map. We ignore the stop request since we don't use
311 // the delegate in those.
312 for (IDMap<BluetoothNotificationsRequest, IDMapOwnPointer>::iterator iter(
313 &pending_start_notifications_requests_);
314 !iter.IsAtEnd(); iter.Advance()) {
315 iter.GetCurrentValue()->delegate = nullptr;
316 }
317 }
318
228 void BluetoothDispatcher::WillStopCurrentWorkerThread() { 319 void BluetoothDispatcher::WillStopCurrentWorkerThread() {
229 delete this; 320 delete this;
230 } 321 }
231 322
323 bool BluetoothDispatcher::HasActiveCharacteristicNotification(
324 const blink::WebString& characteristic_instance_id) {
325 auto char_iter = active_characteristic_notifications.find(
326 characteristic_instance_id.utf8());
327
328 // An active characteristic will point to a set of delegates.
329 if (char_iter == active_characteristic_notifications.end()) {
330 return false;
331 }
332
333 return true;
334 }
335
336 void BluetoothDispatcher::AddToActiveNotificationsMap(
337 const blink::WebString& characteristic_instance_id,
338 blink::WebBluetoothGATTCharacteristicDelegate* delegate) {
339 auto char_iter = active_characteristic_notifications.find(
340 characteristic_instance_id.utf8());
341
342 // First object that subscribes to notifications for the characteristic.
343 if (char_iter == active_characteristic_notifications.end()) {
344 std::set<blink::WebBluetoothGATTCharacteristicDelegate*> delegates;
345 delegates.insert(delegate);
346 active_characteristic_notifications.insert(
347 std::make_pair(characteristic_instance_id.utf8(), delegates));
348 return;
349 }
350 // Otherwise add to already existing set.
351 char_iter->second.insert(delegate);
352 }
353
354 bool BluetoothDispatcher::WillBeActiveNotificationWhenRemoved(
355 const blink::WebString& characteristic_instance_id,
356 blink::WebBluetoothGATTCharacteristicDelegate* delegate) {
357 auto char_iter = active_characteristic_notifications.find(
358 characteristic_instance_id.utf8());
359
360 // The characteristic will point to a set as long as there is at least
361 // one delegate subscribed to notifications.
362 if (char_iter == active_characteristic_notifications.end()) {
363 return false;
364 }
365 const std::set<blink::WebBluetoothGATTCharacteristicDelegate*>& delegate_set =
366 char_iter->second;
367 // If we find the delegate and the size of the set is one then removing
368 // the delegate will make the notification inactive.
369 if (delegate_set.find(delegate) != delegate_set.end() &&
370 delegate_set.size() == 1) {
371 return false;
372 }
373 return true;
374 }
375
376 void BluetoothDispatcher::RemoveFromActiveNotificationsMap(
377 const blink::WebString& characteristic_instance_id,
378 blink::WebBluetoothGATTCharacteristicDelegate* delegate) {
379 auto char_iter = active_characteristic_notifications.find(
380 characteristic_instance_id.utf8());
381
382 if (char_iter == active_characteristic_notifications.end()) {
383 return;
384 }
385
386 char_iter->second.erase(delegate);
387
388 if (char_iter->second.size() == 0) {
389 active_characteristic_notifications.erase(char_iter);
390 }
391 }
392
232 void BluetoothDispatcher::OnRequestDeviceSuccess( 393 void BluetoothDispatcher::OnRequestDeviceSuccess(
233 int thread_id, 394 int thread_id,
234 int request_id, 395 int request_id,
235 const BluetoothDevice& device) { 396 const BluetoothDevice& device) {
236 DCHECK(pending_requests_.Lookup(request_id)) << request_id; 397 DCHECK(pending_requests_.Lookup(request_id)) << request_id;
237 398
238 WebVector<WebString> uuids(device.uuids.size()); 399 WebVector<WebString> uuids(device.uuids.size());
239 for (size_t i = 0; i < device.uuids.size(); ++i) 400 for (size_t i = 0; i < device.uuids.size(); ++i)
240 uuids[i] = WebString::fromUTF8(device.uuids[i].c_str()); 401 uuids[i] = WebString::fromUTF8(device.uuids[i].c_str());
241 402
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 int request_id, 540 int request_id,
380 WebBluetoothError error) { 541 WebBluetoothError error) {
381 DCHECK(pending_write_value_requests_.Lookup(request_id)) << request_id; 542 DCHECK(pending_write_value_requests_.Lookup(request_id)) << request_id;
382 543
383 pending_write_value_requests_.Lookup(request_id) 544 pending_write_value_requests_.Lookup(request_id)
384 ->onError(WebBluetoothError(error)); 545 ->onError(WebBluetoothError(error));
385 546
386 pending_write_value_requests_.Remove(request_id); 547 pending_write_value_requests_.Remove(request_id);
387 } 548 }
388 549
550 void BluetoothDispatcher::OnStartNotificationsSuccess(int thread_id,
551 int request_id) {
552 DCHECK(pending_start_notifications_requests_.Lookup(request_id))
553 << request_id;
554
555 BluetoothNotificationsRequest* request =
556 pending_start_notifications_requests_.Lookup(request_id);
557
558 // The object requesting the notification could have been destroyed
559 // while waiting for the subscription. characteristicDelegateRemoved
560 // nulls the delegate when the delegate gets destroyed.
561 if (request->delegate != nullptr) {
ortuno 2015/09/16 16:30:08 Argh. This doesn't work. If the delegate gets dest
562 AddToActiveNotificationsMap(request->characteristic_instance_id,
563 request->delegate);
564 }
565 request->callbacks->onSuccess();
566
567 pending_start_notifications_requests_.Remove(request_id);
568 }
569
570 void BluetoothDispatcher::OnStartNotificationsError(int thread_id,
571 int request_id,
572 WebBluetoothError error) {
573 DCHECK(pending_start_notifications_requests_.Lookup(request_id))
574 << request_id;
575
576 pending_start_notifications_requests_.Lookup(request_id)
577 ->callbacks->onError(error);
578
579 pending_start_notifications_requests_.Remove(request_id);
580 }
581
582 void BluetoothDispatcher::OnStopNotificationsSuccess(int thread_id,
583 int request_id) {
584 DCHECK(pending_stop_notifications_requests_.Lookup(request_id)) << request_id;
585
586 BluetoothNotificationsRequest* request =
587 pending_stop_notifications_requests_.Lookup(request_id);
588
589 RemoveFromActiveNotificationsMap(request->characteristic_instance_id,
590 request->delegate);
591
592 pending_stop_notifications_requests_.Lookup(request_id)
593 ->callbacks->onSuccess();
594
595 pending_stop_notifications_requests_.Remove(request_id);
596 }
597
389 } // namespace content 598 } // namespace content
OLDNEW
« 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