OLD | NEW |
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
haracteristicInit.h" | 18 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTC
haracteristicInit.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::WebBluetoothGATTCharacteristicInit; | 26 using blink::WebBluetoothGATTCharacteristicInit; |
26 using blink::WebBluetoothGATTRemoteServer; | 27 using blink::WebBluetoothGATTRemoteServer; |
27 using blink::WebBluetoothGATTService; | 28 using blink::WebBluetoothGATTService; |
28 using blink::WebBluetoothReadValueCallbacks; | 29 using blink::WebBluetoothReadValueCallbacks; |
29 using blink::WebBluetoothRequestDeviceCallbacks; | 30 using blink::WebBluetoothRequestDeviceCallbacks; |
30 using blink::WebBluetoothScanFilter; | 31 using blink::WebBluetoothScanFilter; |
31 using blink::WebRequestDeviceOptions; | 32 using blink::WebRequestDeviceOptions; |
32 using blink::WebString; | 33 using blink::WebString; |
33 using blink::WebVector; | 34 using blink::WebVector; |
| 35 using NotificationsRequestType = |
| 36 content::BluetoothDispatcher::NotificationsRequestType; |
34 | 37 |
35 struct BluetoothPrimaryServiceRequest { | 38 struct BluetoothPrimaryServiceRequest { |
36 BluetoothPrimaryServiceRequest( | 39 BluetoothPrimaryServiceRequest( |
37 blink::WebString device_instance_id, | 40 blink::WebString device_instance_id, |
38 blink::WebString service_uuid, | 41 blink::WebString service_uuid, |
39 blink::WebBluetoothGetPrimaryServiceCallbacks* callbacks) | 42 blink::WebBluetoothGetPrimaryServiceCallbacks* callbacks) |
40 : device_instance_id(device_instance_id), | 43 : device_instance_id(device_instance_id), |
41 service_uuid(service_uuid), | 44 service_uuid(service_uuid), |
42 callbacks(callbacks) {} | 45 callbacks(callbacks) {} |
43 ~BluetoothPrimaryServiceRequest() {} | 46 ~BluetoothPrimaryServiceRequest() {} |
(...skipping 11 matching lines...) Expand all Loading... |
55 : service_instance_id(service_instance_id), | 58 : service_instance_id(service_instance_id), |
56 characteristic_uuid(characteristic_uuid), | 59 characteristic_uuid(characteristic_uuid), |
57 callbacks(callbacks) {} | 60 callbacks(callbacks) {} |
58 ~BluetoothCharacteristicRequest() {} | 61 ~BluetoothCharacteristicRequest() {} |
59 | 62 |
60 blink::WebString service_instance_id; | 63 blink::WebString service_instance_id; |
61 blink::WebString characteristic_uuid; | 64 blink::WebString characteristic_uuid; |
62 scoped_ptr<blink::WebBluetoothGetCharacteristicCallbacks> callbacks; | 65 scoped_ptr<blink::WebBluetoothGetCharacteristicCallbacks> callbacks; |
63 }; | 66 }; |
64 | 67 |
| 68 // Struct that holds a pending Start/StopNotifications request. |
| 69 struct BluetoothNotificationsRequest { |
| 70 BluetoothNotificationsRequest( |
| 71 const std::string characteristic_instance_id, |
| 72 blink::WebBluetoothGATTCharacteristic* characteristic, |
| 73 blink::WebBluetoothNotificationsCallbacks* callbacks, |
| 74 NotificationsRequestType type) |
| 75 : characteristic_instance_id(characteristic_instance_id), |
| 76 characteristic(characteristic), |
| 77 callbacks(callbacks), |
| 78 type(type) {} |
| 79 ~BluetoothNotificationsRequest() {} |
| 80 |
| 81 const std::string characteristic_instance_id; |
| 82 // The characteristic object is owned by the execution context on |
| 83 // the blink side which can destroy the object at any point. Since the |
| 84 // object implements ActiveDOMObject, the object calls Stop when is getting |
| 85 // destroyed, which in turn calls characteristicObjectRemoved. |
| 86 // characteristicObjectRemoved will null any pointers to the object |
| 87 // and queue a stop notifications request if necessary. |
| 88 blink::WebBluetoothGATTCharacteristic* characteristic; |
| 89 scoped_ptr<blink::WebBluetoothNotificationsCallbacks> callbacks; |
| 90 NotificationsRequestType type; |
| 91 }; |
| 92 |
65 namespace content { | 93 namespace content { |
66 | 94 |
67 namespace { | 95 namespace { |
68 | 96 |
69 base::LazyInstance<base::ThreadLocalPointer<void>>::Leaky g_dispatcher_tls = | 97 base::LazyInstance<base::ThreadLocalPointer<void>>::Leaky g_dispatcher_tls = |
70 LAZY_INSTANCE_INITIALIZER; | 98 LAZY_INSTANCE_INITIALIZER; |
71 | 99 |
72 void* const kHasBeenDeleted = reinterpret_cast<void*>(0x1); | 100 void* const kHasBeenDeleted = reinterpret_cast<void*>(0x1); |
73 | 101 |
74 int CurrentWorkerId() { | 102 int CurrentWorkerId() { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 IPC_MESSAGE_HANDLER(BluetoothMsg_GetCharacteristicError, | 164 IPC_MESSAGE_HANDLER(BluetoothMsg_GetCharacteristicError, |
137 OnGetCharacteristicError); | 165 OnGetCharacteristicError); |
138 IPC_MESSAGE_HANDLER(BluetoothMsg_ReadCharacteristicValueSuccess, | 166 IPC_MESSAGE_HANDLER(BluetoothMsg_ReadCharacteristicValueSuccess, |
139 OnReadValueSuccess); | 167 OnReadValueSuccess); |
140 IPC_MESSAGE_HANDLER(BluetoothMsg_ReadCharacteristicValueError, | 168 IPC_MESSAGE_HANDLER(BluetoothMsg_ReadCharacteristicValueError, |
141 OnReadValueError); | 169 OnReadValueError); |
142 IPC_MESSAGE_HANDLER(BluetoothMsg_WriteCharacteristicValueSuccess, | 170 IPC_MESSAGE_HANDLER(BluetoothMsg_WriteCharacteristicValueSuccess, |
143 OnWriteValueSuccess); | 171 OnWriteValueSuccess); |
144 IPC_MESSAGE_HANDLER(BluetoothMsg_WriteCharacteristicValueError, | 172 IPC_MESSAGE_HANDLER(BluetoothMsg_WriteCharacteristicValueError, |
145 OnWriteValueError); | 173 OnWriteValueError); |
| 174 IPC_MESSAGE_HANDLER(BluetoothMsg_StartNotificationsSuccess, |
| 175 OnStartNotificationsSuccess) |
| 176 IPC_MESSAGE_HANDLER(BluetoothMsg_StartNotificationsError, |
| 177 OnStartNotificationsError) |
| 178 IPC_MESSAGE_HANDLER(BluetoothMsg_StopNotificationsSuccess, |
| 179 OnStopNotificationsSuccess) |
146 IPC_MESSAGE_UNHANDLED(handled = false) | 180 IPC_MESSAGE_UNHANDLED(handled = false) |
147 IPC_END_MESSAGE_MAP() | 181 IPC_END_MESSAGE_MAP() |
148 DCHECK(handled) << "Unhandled message:" << msg.type(); | 182 DCHECK(handled) << "Unhandled message:" << msg.type(); |
149 } | 183 } |
150 | 184 |
151 void BluetoothDispatcher::requestDevice( | 185 void BluetoothDispatcher::requestDevice( |
152 int frame_routing_id, | 186 int frame_routing_id, |
153 const WebRequestDeviceOptions& options, | 187 const WebRequestDeviceOptions& options, |
154 blink::WebBluetoothRequestDeviceCallbacks* callbacks) { | 188 blink::WebBluetoothRequestDeviceCallbacks* callbacks) { |
155 int request_id = pending_requests_.Add(callbacks); | 189 int request_id = pending_requests_.Add(callbacks); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 void BluetoothDispatcher::writeValue( | 252 void BluetoothDispatcher::writeValue( |
219 const blink::WebString& characteristic_instance_id, | 253 const blink::WebString& characteristic_instance_id, |
220 const std::vector<uint8_t>& value, | 254 const std::vector<uint8_t>& value, |
221 blink::WebBluetoothWriteValueCallbacks* callbacks) { | 255 blink::WebBluetoothWriteValueCallbacks* callbacks) { |
222 int request_id = pending_write_value_requests_.Add(callbacks); | 256 int request_id = pending_write_value_requests_.Add(callbacks); |
223 | 257 |
224 Send(new BluetoothHostMsg_WriteValue( | 258 Send(new BluetoothHostMsg_WriteValue( |
225 CurrentWorkerId(), request_id, characteristic_instance_id.utf8(), value)); | 259 CurrentWorkerId(), request_id, characteristic_instance_id.utf8(), value)); |
226 } | 260 } |
227 | 261 |
| 262 void BluetoothDispatcher::startNotifications( |
| 263 const blink::WebString& characteristic_instance_id, |
| 264 blink::WebBluetoothGATTCharacteristic* characteristic, |
| 265 blink::WebBluetoothNotificationsCallbacks* callbacks) { |
| 266 int request_id = QueueNotificationRequest(characteristic_instance_id.utf8(), |
| 267 characteristic, callbacks, |
| 268 NotificationsRequestType::START); |
| 269 // The Notification subscription's state can change after a request |
| 270 // finishes. To avoid resolving with a soon-to-be-invalid state we queue |
| 271 // requests. |
| 272 if (HasNotificationRequestResponsePending( |
| 273 characteristic_instance_id.utf8())) { |
| 274 return; |
| 275 } |
| 276 |
| 277 ResolveOrSendStartNotificationRequest(request_id); |
| 278 } |
| 279 |
| 280 void BluetoothDispatcher::stopNotifications( |
| 281 const blink::WebString& characteristic_instance_id, |
| 282 blink::WebBluetoothGATTCharacteristic* characteristic, |
| 283 blink::WebBluetoothNotificationsCallbacks* callbacks) { |
| 284 int request_id = QueueNotificationRequest(characteristic_instance_id.utf8(), |
| 285 characteristic, callbacks, |
| 286 NotificationsRequestType::STOP); |
| 287 if (HasNotificationRequestResponsePending( |
| 288 characteristic_instance_id.utf8())) { |
| 289 return; |
| 290 } |
| 291 |
| 292 ResolveOrSendStopNotificationsRequest(request_id); |
| 293 } |
| 294 |
| 295 void BluetoothDispatcher::characteristicObjectRemoved( |
| 296 const blink::WebString& characteristic_instance_id, |
| 297 blink::WebBluetoothGATTCharacteristic* characteristic) { |
| 298 // A characteristic object is in the queue waiting for a response |
| 299 // or in the set of active notifications. |
| 300 |
| 301 // If the object is in the queue we null the characteristic. If this is the |
| 302 // first object waiting for a response OnStartNotificationsSuccess will make |
| 303 // sure not to add the characteristic to the map and it will queue a Stop |
| 304 // request. Otherwise ResolveOrSendStartNotificationRequest will make sure not |
| 305 // to add it to active notification subscriptions. |
| 306 bool found = false; |
| 307 for (IDMap<BluetoothNotificationsRequest, IDMapOwnPointer>::iterator iter( |
| 308 &pending_notifications_requests_); |
| 309 !iter.IsAtEnd(); iter.Advance()) { |
| 310 if (iter.GetCurrentValue()->characteristic == characteristic) { |
| 311 found = true; |
| 312 iter.GetCurrentValue()->characteristic = nullptr; |
| 313 } |
| 314 } |
| 315 |
| 316 if (found) { |
| 317 // A characteristic will never be in the set of active notifications |
| 318 // and in the queue at the same time. |
| 319 auto subscriptions_iter = active_notification_subscriptions_.find( |
| 320 characteristic_instance_id.utf8()); |
| 321 if (subscriptions_iter != active_notification_subscriptions_.end()) { |
| 322 DCHECK(!ContainsKey(subscriptions_iter->second, characteristic)); |
| 323 } |
| 324 return; |
| 325 } |
| 326 |
| 327 // If the object is not in the queue then: |
| 328 // 1. The subscription was inactive already: this characteristic |
| 329 // object didn't subscribe to notifications. |
| 330 // 2. The subscription will become inactive: the characteristic |
| 331 // object that subscribed to notifications is getting destroyed. |
| 332 // 3. The subscription will still be active: there are other |
| 333 // characteristic objects subscribed to notifications. |
| 334 |
| 335 if (!HasActiveNotificationSubscription(characteristic_instance_id.utf8())) { |
| 336 return; |
| 337 } |
| 338 |
| 339 // For 2 and 3 calling ResolveOrSendStopNotificationsRequest ensures the |
| 340 // notification subscription is released. |
| 341 // We pass in the characteristic so that ResolveOrSendStopNotificationsRequest |
| 342 // can remove the characteristic from ActiveNotificationSubscriptions. |
| 343 ResolveOrSendStopNotificationsRequest(QueueNotificationRequest( |
| 344 characteristic_instance_id.utf8(), characteristic, |
| 345 nullptr /* callbacks */, NotificationsRequestType::STOP)); |
| 346 } |
| 347 |
228 void BluetoothDispatcher::WillStopCurrentWorkerThread() { | 348 void BluetoothDispatcher::WillStopCurrentWorkerThread() { |
229 delete this; | 349 delete this; |
230 } | 350 } |
231 | 351 |
| 352 int BluetoothDispatcher::QueueNotificationRequest( |
| 353 const std::string& characteristic_instance_id, |
| 354 blink::WebBluetoothGATTCharacteristic* characteristic, |
| 355 blink::WebBluetoothNotificationsCallbacks* callbacks, |
| 356 NotificationsRequestType type) { |
| 357 int request_id = |
| 358 pending_notifications_requests_.Add(new BluetoothNotificationsRequest( |
| 359 characteristic_instance_id, characteristic, callbacks, type)); |
| 360 notification_requests_queues_[characteristic_instance_id].push(request_id); |
| 361 |
| 362 return request_id; |
| 363 } |
| 364 |
| 365 void BluetoothDispatcher::PopNotificationRequestQueueAndProcessNext( |
| 366 int request_id) { |
| 367 BluetoothNotificationsRequest* old_request = |
| 368 pending_notifications_requests_.Lookup(request_id); |
| 369 |
| 370 auto queue_iter = notification_requests_queues_.find( |
| 371 old_request->characteristic_instance_id); |
| 372 |
| 373 CHECK(queue_iter != notification_requests_queues_.end()); |
| 374 |
| 375 std::queue<int>& request_queue = queue_iter->second; |
| 376 |
| 377 DCHECK(request_queue.front() == request_id); |
| 378 |
| 379 // Remove old request and clean map if necessary. |
| 380 request_queue.pop(); |
| 381 pending_notifications_requests_.Remove(request_id); |
| 382 if (request_queue.empty()) { |
| 383 notification_requests_queues_.erase(queue_iter); |
| 384 return; |
| 385 } |
| 386 |
| 387 int next_request_id = request_queue.front(); |
| 388 BluetoothNotificationsRequest* next_request = |
| 389 pending_notifications_requests_.Lookup(next_request_id); |
| 390 |
| 391 switch (next_request->type) { |
| 392 case NotificationsRequestType::START: |
| 393 ResolveOrSendStartNotificationRequest(next_request_id); |
| 394 return; |
| 395 case NotificationsRequestType::STOP: |
| 396 ResolveOrSendStopNotificationsRequest(next_request_id); |
| 397 return; |
| 398 } |
| 399 } |
| 400 |
| 401 bool BluetoothDispatcher::HasNotificationRequestResponsePending( |
| 402 const std::string& characteristic_instance_id) { |
| 403 return ContainsKey(notification_requests_queues_, |
| 404 characteristic_instance_id) && |
| 405 (notification_requests_queues_[characteristic_instance_id].size() > 1); |
| 406 } |
| 407 |
| 408 bool BluetoothDispatcher::HasActiveNotificationSubscription( |
| 409 const std::string& characteristic_instance_id) { |
| 410 return ContainsKey(active_notification_subscriptions_, |
| 411 characteristic_instance_id); |
| 412 } |
| 413 |
| 414 void BluetoothDispatcher::AddToActiveNotificationSubscriptions( |
| 415 const std::string& characteristic_instance_id, |
| 416 blink::WebBluetoothGATTCharacteristic* characteristic) { |
| 417 active_notification_subscriptions_[characteristic_instance_id].insert( |
| 418 characteristic); |
| 419 } |
| 420 |
| 421 bool BluetoothDispatcher::RemoveFromActiveNotificationSubscriptions( |
| 422 const std::string& characteristic_instance_id, |
| 423 blink::WebBluetoothGATTCharacteristic* characteristic) { |
| 424 auto active_map = |
| 425 active_notification_subscriptions_.find(characteristic_instance_id); |
| 426 |
| 427 if (active_map == active_notification_subscriptions_.end()) { |
| 428 return false; |
| 429 } |
| 430 |
| 431 active_map->second.erase(characteristic); |
| 432 |
| 433 if (active_map->second.empty()) { |
| 434 active_notification_subscriptions_.erase(active_map); |
| 435 DCHECK(!HasActiveNotificationSubscription(characteristic_instance_id)); |
| 436 return true; |
| 437 } |
| 438 return false; |
| 439 } |
| 440 |
| 441 void BluetoothDispatcher::ResolveOrSendStartNotificationRequest( |
| 442 int request_id) { |
| 443 BluetoothNotificationsRequest* request = |
| 444 pending_notifications_requests_.Lookup(request_id); |
| 445 const std::string& characteristic_instance_id = |
| 446 request->characteristic_instance_id; |
| 447 blink::WebBluetoothGATTCharacteristic* characteristic = |
| 448 request->characteristic; |
| 449 blink::WebBluetoothNotificationsCallbacks* callbacks = |
| 450 request->callbacks.get(); |
| 451 |
| 452 // If an object is already subscribed to notifications from the characteristic |
| 453 // no need to send an IPC again. |
| 454 if (HasActiveNotificationSubscription(characteristic_instance_id)) { |
| 455 // The object could have been destroyed while we waited. |
| 456 if (characteristic != nullptr) { |
| 457 AddToActiveNotificationSubscriptions(characteristic_instance_id, |
| 458 characteristic); |
| 459 } |
| 460 callbacks->onSuccess(); |
| 461 |
| 462 PopNotificationRequestQueueAndProcessNext(request_id); |
| 463 return; |
| 464 } |
| 465 |
| 466 Send(new BluetoothHostMsg_StartNotifications(CurrentWorkerId(), request_id, |
| 467 characteristic_instance_id)); |
| 468 } |
| 469 |
| 470 void BluetoothDispatcher::ResolveOrSendStopNotificationsRequest( |
| 471 int request_id) { |
| 472 // The Notification subscription's state can change after a request |
| 473 // finishes. To avoid resolving with a soon-to-be-invalid state we queue |
| 474 // requests. |
| 475 BluetoothNotificationsRequest* request = |
| 476 pending_notifications_requests_.Lookup(request_id); |
| 477 const std::string& characteristic_instance_id = |
| 478 request->characteristic_instance_id; |
| 479 blink::WebBluetoothGATTCharacteristic* characteristic = |
| 480 request->characteristic; |
| 481 blink::WebBluetoothNotificationsCallbacks* callbacks = |
| 482 request->callbacks.get(); |
| 483 |
| 484 // If removing turns the subscription inactive then stop. |
| 485 if (RemoveFromActiveNotificationSubscriptions(characteristic_instance_id, |
| 486 characteristic)) { |
| 487 Send(new BluetoothHostMsg_StopNotifications(CurrentWorkerId(), request_id, |
| 488 characteristic_instance_id)); |
| 489 return; |
| 490 } |
| 491 |
| 492 // We could be processing a request with nullptr callbacks due to: |
| 493 // 1) OnStartNotificationSuccess queues a Stop request because the object |
| 494 // got destroyed in characteristicObjectRemoved. |
| 495 // 2) The last characteristic object that held this subscription got |
| 496 // destroyed in characteristicObjectRemoved. |
| 497 if (callbacks != nullptr) { |
| 498 callbacks->onSuccess(); |
| 499 } |
| 500 PopNotificationRequestQueueAndProcessNext(request_id); |
| 501 } |
| 502 |
232 void BluetoothDispatcher::OnRequestDeviceSuccess( | 503 void BluetoothDispatcher::OnRequestDeviceSuccess( |
233 int thread_id, | 504 int thread_id, |
234 int request_id, | 505 int request_id, |
235 const BluetoothDevice& device) { | 506 const BluetoothDevice& device) { |
236 DCHECK(pending_requests_.Lookup(request_id)) << request_id; | 507 DCHECK(pending_requests_.Lookup(request_id)) << request_id; |
237 | 508 |
238 WebVector<WebString> uuids(device.uuids.size()); | 509 WebVector<WebString> uuids(device.uuids.size()); |
239 for (size_t i = 0; i < device.uuids.size(); ++i) | 510 for (size_t i = 0; i < device.uuids.size(); ++i) |
240 uuids[i] = WebString::fromUTF8(device.uuids[i].c_str()); | 511 uuids[i] = WebString::fromUTF8(device.uuids[i].c_str()); |
241 | 512 |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 int request_id, | 633 int request_id, |
363 WebBluetoothError error) { | 634 WebBluetoothError error) { |
364 DCHECK(pending_write_value_requests_.Lookup(request_id)) << request_id; | 635 DCHECK(pending_write_value_requests_.Lookup(request_id)) << request_id; |
365 | 636 |
366 pending_write_value_requests_.Lookup(request_id) | 637 pending_write_value_requests_.Lookup(request_id) |
367 ->onError(WebBluetoothError(error)); | 638 ->onError(WebBluetoothError(error)); |
368 | 639 |
369 pending_write_value_requests_.Remove(request_id); | 640 pending_write_value_requests_.Remove(request_id); |
370 } | 641 } |
371 | 642 |
| 643 void BluetoothDispatcher::OnStartNotificationsSuccess(int thread_id, |
| 644 int request_id) { |
| 645 DCHECK(pending_notifications_requests_.Lookup(request_id)) << request_id; |
| 646 |
| 647 BluetoothNotificationsRequest* request = |
| 648 pending_notifications_requests_.Lookup(request_id); |
| 649 |
| 650 DCHECK(notification_requests_queues_[request->characteristic_instance_id] |
| 651 .front() == request_id); |
| 652 |
| 653 // We only send an IPC for inactive notifications. |
| 654 DCHECK( |
| 655 !HasActiveNotificationSubscription(request->characteristic_instance_id)); |
| 656 |
| 657 AddToActiveNotificationSubscriptions(request->characteristic_instance_id, |
| 658 request->characteristic); |
| 659 |
| 660 // The object requesting the notification could have been destroyed |
| 661 // while waiting for the subscription. characteristicRemoved |
| 662 // nulls the characteristic when the corresponding js object gets destroyed. |
| 663 // A Stop request must be issued as the subscription is no longer needed. |
| 664 // The Stop requets is added to the end of the queue in case another |
| 665 // Start request exists in the queue from another characteristic object, |
| 666 // which would result in the subscription continuing. |
| 667 if (request->characteristic == nullptr) { |
| 668 QueueNotificationRequest( |
| 669 request->characteristic_instance_id, nullptr /* characteristic */, |
| 670 nullptr /* callbacks */, NotificationsRequestType::STOP); |
| 671 } |
| 672 |
| 673 request->callbacks->onSuccess(); |
| 674 |
| 675 PopNotificationRequestQueueAndProcessNext(request_id); |
| 676 } |
| 677 |
| 678 void BluetoothDispatcher::OnStartNotificationsError(int thread_id, |
| 679 int request_id, |
| 680 WebBluetoothError error) { |
| 681 DCHECK(pending_notifications_requests_.Lookup(request_id)) << request_id; |
| 682 |
| 683 BluetoothNotificationsRequest* request = |
| 684 pending_notifications_requests_.Lookup(request_id); |
| 685 |
| 686 DCHECK(notification_requests_queues_[request->characteristic_instance_id] |
| 687 .front() == request_id); |
| 688 |
| 689 // We only send an IPC for inactive notifications. |
| 690 DCHECK( |
| 691 !HasActiveNotificationSubscription(request->characteristic_instance_id)); |
| 692 |
| 693 request->callbacks->onError(error); |
| 694 |
| 695 PopNotificationRequestQueueAndProcessNext(request_id); |
| 696 } |
| 697 |
| 698 void BluetoothDispatcher::OnStopNotificationsSuccess(int thread_id, |
| 699 int request_id) { |
| 700 DCHECK(pending_notifications_requests_.Lookup(request_id)) << request_id; |
| 701 |
| 702 BluetoothNotificationsRequest* request = |
| 703 pending_notifications_requests_.Lookup(request_id); |
| 704 |
| 705 DCHECK(notification_requests_queues_[request->characteristic_instance_id] |
| 706 .front() == request_id); |
| 707 |
| 708 // We only send an IPC for inactive notifications. |
| 709 DCHECK( |
| 710 !HasActiveNotificationSubscription(request->characteristic_instance_id)); |
| 711 |
| 712 if (request->callbacks != nullptr) { |
| 713 request->callbacks->onSuccess(); |
| 714 } |
| 715 |
| 716 PopNotificationRequestQueueAndProcessNext(request_id); |
| 717 } |
| 718 |
372 } // namespace content | 719 } // namespace content |
OLD | NEW |