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 // NETWORK_ERROR Note: | 5 // NETWORK_ERROR Note: |
6 // When a device can't be found in the BluetoothAdapter, that generally | 6 // When a device can't be found in the BluetoothAdapter, that generally |
7 // indicates that it's gone out of range. We reject with a NetworkError in that | 7 // indicates that it's gone out of range. We reject with a NetworkError in that |
8 // case. | 8 // case. |
9 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothdevice-conne
ctgatt | 9 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothdevice-conne
ctgatt |
10 | 10 |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
244 } | 244 } |
245 | 245 |
246 const int thread_id; | 246 const int thread_id; |
247 const int request_id; | 247 const int request_id; |
248 const std::vector<BluetoothScanFilter> filters; | 248 const std::vector<BluetoothScanFilter> filters; |
249 const std::vector<BluetoothUUID> optional_services; | 249 const std::vector<BluetoothUUID> optional_services; |
250 scoped_ptr<BluetoothChooser> chooser; | 250 scoped_ptr<BluetoothChooser> chooser; |
251 scoped_ptr<device::BluetoothDiscoverySession> discovery_session; | 251 scoped_ptr<device::BluetoothDiscoverySession> discovery_session; |
252 }; | 252 }; |
253 | 253 |
| 254 blink::WebBluetoothError |
| 255 BluetoothDispatcherHost::CacheQueryOutcomeToWebBluetoothError( |
| 256 BluetoothDispatcherHost::CacheQueryOutcome outcome) { |
| 257 switch (outcome) { |
| 258 case CacheQueryOutcome::SUCCESS: |
| 259 case CacheQueryOutcome::BAD_RENDERER: |
| 260 CHECK(false) << "Not errors"; |
| 261 case CacheQueryOutcome::NO_DEVICE: |
| 262 return WebBluetoothError::DeviceNoLongerInRange; |
| 263 case CacheQueryOutcome::NO_SERVICE: |
| 264 return WebBluetoothError::ServiceNoLongerExists; |
| 265 case CacheQueryOutcome::NO_CHARACTERISTIC: |
| 266 return WebBluetoothError::CharacteristicNoLongerExists; |
| 267 } |
| 268 NOTIMPLEMENTED(); |
| 269 return WebBluetoothError::ENUM_MAX_VALUE; |
| 270 } |
| 271 |
| 272 // TODO(ortuno): There shouldn't be a need for each user of these functions |
| 273 // to histogram the outcome on their own. We should refactor bluetooth_metrics |
| 274 // to use RecordOperationOutcome(WebBluetooth::Operation, Outcome), that way |
| 275 // histogramming can be done inside these functions directly. |
| 276 std::pair<BluetoothDispatcherHost::CacheQueryOutcome, device::BluetoothDevice*> |
| 277 BluetoothDispatcherHost::QueryForDevice(const std::string& device_instance_id) { |
| 278 device::BluetoothDevice* device = adapter_->GetDevice(device_instance_id); |
| 279 CacheQueryOutcome device_outcome = CacheQueryOutcome::SUCCESS; |
| 280 if (device == nullptr) { // See "NETWORK_ERROR Note" above. |
| 281 device_outcome = CacheQueryOutcome::NO_DEVICE; |
| 282 } |
| 283 return std::make_pair(device_outcome, device); |
| 284 } |
| 285 |
| 286 std::pair<BluetoothDispatcherHost::CacheQueryOutcome, |
| 287 device::BluetoothGattService*> |
| 288 BluetoothDispatcherHost::QueryForService( |
| 289 const std::string& service_instance_id) { |
| 290 auto device_iter = service_to_device_.find(service_instance_id); |
| 291 // A service_instance_id not in the map implies a hostile renderer |
| 292 // because a renderer obtains the service id from this class and |
| 293 // it will be added to the map at that time. |
| 294 if (device_iter == service_to_device_.end()) { |
| 295 // Kill the renderer |
| 296 bad_message::ReceivedBadMessage(this, bad_message::BDH_INVALID_SERVICE_ID); |
| 297 return std::make_pair(CacheQueryOutcome::BAD_RENDERER, nullptr); |
| 298 } |
| 299 |
| 300 // TODO(ortuno): Check if domain has access to device. |
| 301 // https://crbug.com/493459 |
| 302 auto device_query_outcome = QueryForDevice(device_iter->second); |
| 303 if (device_query_outcome.first != CacheQueryOutcome::SUCCESS) { |
| 304 return std::make_pair(device_query_outcome.first, nullptr); |
| 305 } |
| 306 |
| 307 CacheQueryOutcome service_outcome = CacheQueryOutcome::SUCCESS; |
| 308 // TODO(ortuno): Check if domain has access to service |
| 309 // http://crbug.com/493460 |
| 310 device::BluetoothGattService* service = |
| 311 device_query_outcome.second->GetGattService(service_instance_id); |
| 312 if (!service) { |
| 313 service_outcome = CacheQueryOutcome::NO_SERVICE; |
| 314 } |
| 315 return std::make_pair(service_outcome, service); |
| 316 } |
| 317 |
| 318 std::pair<BluetoothDispatcherHost::CacheQueryOutcome, |
| 319 device::BluetoothGattCharacteristic*> |
| 320 BluetoothDispatcherHost::QueryForCharacteristic( |
| 321 const std::string& characteristic_instance_id) { |
| 322 auto characteristic_iter = |
| 323 characteristic_to_service_.find(characteristic_instance_id); |
| 324 // A characteristic_instance_id not in the map implies a hostile renderer |
| 325 // because a renderer obtains the characteristic id from this class and |
| 326 // it will be added to the map at that time. |
| 327 if (characteristic_iter == characteristic_to_service_.end()) { |
| 328 // Kill the renderer |
| 329 bad_message::ReceivedBadMessage(this, |
| 330 bad_message::BDH_INVALID_CHARACTERISTIC_ID); |
| 331 return std::make_pair(CacheQueryOutcome::BAD_RENDERER, nullptr); |
| 332 } |
| 333 |
| 334 auto service_query_outcome = QueryForService(characteristic_iter->second); |
| 335 if (service_query_outcome.first != CacheQueryOutcome::SUCCESS) { |
| 336 return std::make_pair(service_query_outcome.first, nullptr); |
| 337 } |
| 338 |
| 339 CacheQueryOutcome characteristic_outcome = CacheQueryOutcome::SUCCESS; |
| 340 BluetoothGattCharacteristic* characteristic = |
| 341 service_query_outcome.second->GetCharacteristic( |
| 342 characteristic_instance_id); |
| 343 if (!characteristic) { |
| 344 characteristic_outcome = CacheQueryOutcome::NO_CHARACTERISTIC; |
| 345 } |
| 346 return std::make_pair(characteristic_outcome, characteristic); |
| 347 } |
| 348 |
254 void BluetoothDispatcherHost::set_adapter( | 349 void BluetoothDispatcherHost::set_adapter( |
255 scoped_refptr<device::BluetoothAdapter> adapter) { | 350 scoped_refptr<device::BluetoothAdapter> adapter) { |
256 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 351 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
257 if (adapter_.get()) | 352 if (adapter_.get()) |
258 adapter_->RemoveObserver(this); | 353 adapter_->RemoveObserver(this); |
259 adapter_ = adapter; | 354 adapter_ = adapter; |
260 if (adapter_.get()) | 355 if (adapter_.get()) |
261 adapter_->AddObserver(this); | 356 adapter_->AddObserver(this); |
262 } | 357 } |
263 | 358 |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
441 int request_id, | 536 int request_id, |
442 const std::string& device_instance_id) { | 537 const std::string& device_instance_id) { |
443 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 538 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
444 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::CONNECT_GATT); | 539 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::CONNECT_GATT); |
445 const base::TimeTicks start_time = base::TimeTicks::Now(); | 540 const base::TimeTicks start_time = base::TimeTicks::Now(); |
446 | 541 |
447 // TODO(ortuno): Right now it's pointless to check if the domain has access to | 542 // TODO(ortuno): Right now it's pointless to check if the domain has access to |
448 // the device, because any domain can connect to any device. But once | 543 // the device, because any domain can connect to any device. But once |
449 // permissions are implemented we should check that the domain has access to | 544 // permissions are implemented we should check that the domain has access to |
450 // the device. https://crbug.com/484745 | 545 // the device. https://crbug.com/484745 |
451 device::BluetoothDevice* device = adapter_->GetDevice(device_instance_id); | 546 auto device_query_result = QueryForDevice(device_instance_id); |
452 if (device == nullptr) { // See "NETWORK_ERROR Note" above. | 547 if (device_query_result.first != CacheQueryOutcome::SUCCESS) { |
453 RecordConnectGATTOutcome(UMAConnectGATTOutcome::NO_DEVICE); | 548 if (device_query_result.first == CacheQueryOutcome::NO_DEVICE) { |
| 549 RecordConnectGATTOutcome(UMAConnectGATTOutcome::NO_DEVICE); |
| 550 } |
454 Send(new BluetoothMsg_ConnectGATTError( | 551 Send(new BluetoothMsg_ConnectGATTError( |
455 thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); | 552 thread_id, request_id, |
| 553 CacheQueryOutcomeToWebBluetoothError(device_query_result.first))); |
456 return; | 554 return; |
457 } | 555 } |
458 device->CreateGattConnection( | 556 device_query_result.second->CreateGattConnection( |
459 base::Bind(&BluetoothDispatcherHost::OnGATTConnectionCreated, | 557 base::Bind(&BluetoothDispatcherHost::OnGATTConnectionCreated, |
460 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, | 558 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, |
461 device_instance_id, start_time), | 559 device_instance_id, start_time), |
462 base::Bind(&BluetoothDispatcherHost::OnCreateGATTConnectionError, | 560 base::Bind(&BluetoothDispatcherHost::OnCreateGATTConnectionError, |
463 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, | 561 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id, |
464 device_instance_id, start_time)); | 562 device_instance_id, start_time)); |
465 } | 563 } |
466 | 564 |
467 void BluetoothDispatcherHost::OnGetPrimaryService( | 565 void BluetoothDispatcherHost::OnGetPrimaryService( |
468 int thread_id, | 566 int thread_id, |
(...skipping 20 matching lines...) Expand all Loading... |
489 | 587 |
490 void BluetoothDispatcherHost::OnGetCharacteristic( | 588 void BluetoothDispatcherHost::OnGetCharacteristic( |
491 int thread_id, | 589 int thread_id, |
492 int request_id, | 590 int request_id, |
493 const std::string& service_instance_id, | 591 const std::string& service_instance_id, |
494 const std::string& characteristic_uuid) { | 592 const std::string& characteristic_uuid) { |
495 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 593 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
496 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::GET_CHARACTERISTIC); | 594 RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::GET_CHARACTERISTIC); |
497 RecordGetCharacteristicCharacteristic(characteristic_uuid); | 595 RecordGetCharacteristicCharacteristic(characteristic_uuid); |
498 | 596 |
499 auto device_iter = service_to_device_.find(service_instance_id); | 597 auto service_query_outcome = QueryForService(service_instance_id); |
500 // A service_instance_id not in the map implies a hostile renderer | |
501 // because a renderer obtains the service id from this class and | |
502 // it will be added to the map at that time. | |
503 if (device_iter == service_to_device_.end()) { | |
504 // Kill the renderer | |
505 bad_message::ReceivedBadMessage(this, bad_message::BDH_INVALID_SERVICE_ID); | |
506 return; | |
507 } | |
508 | 598 |
509 // TODO(ortuno): Check if domain has access to device. | 599 if (service_query_outcome.first != CacheQueryOutcome::SUCCESS) { |
510 // https://crbug.com/493459 | 600 CacheQueryOutcome error_outcome = service_query_outcome.first; |
511 device::BluetoothDevice* device = | 601 if (error_outcome == CacheQueryOutcome::BAD_RENDERER) { |
512 adapter_->GetDevice(device_iter->second /* device_instance_id */); | 602 // QueryForService already took care of sending the message |
513 | 603 return; |
514 if (device == nullptr) { // See "NETWORK_ERROR Note" above. | 604 } |
515 RecordGetCharacteristicOutcome(UMAGetCharacteristicOutcome::NO_DEVICE); | 605 if (error_outcome == CacheQueryOutcome::NO_DEVICE) { |
| 606 RecordGetCharacteristicOutcome(UMAGetCharacteristicOutcome::NO_DEVICE); |
| 607 } else if (error_outcome == CacheQueryOutcome::NO_SERVICE) { |
| 608 RecordGetCharacteristicOutcome(UMAGetCharacteristicOutcome::NO_SERVICE); |
| 609 } |
516 Send(new BluetoothMsg_GetCharacteristicError( | 610 Send(new BluetoothMsg_GetCharacteristicError( |
517 thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); | 611 thread_id, request_id, |
518 return; | 612 CacheQueryOutcomeToWebBluetoothError(error_outcome))); |
519 } | |
520 | |
521 // TODO(ortuno): Check if domain has access to service | |
522 // http://crbug.com/493460 | |
523 device::BluetoothGattService* service = | |
524 device->GetGattService(service_instance_id); | |
525 if (!service) { | |
526 RecordGetCharacteristicOutcome(UMAGetCharacteristicOutcome::NO_SERVICE); | |
527 Send(new BluetoothMsg_GetCharacteristicError( | |
528 thread_id, request_id, WebBluetoothError::ServiceNoLongerExists)); | |
529 return; | 613 return; |
530 } | 614 } |
531 | 615 |
532 for (BluetoothGattCharacteristic* characteristic : | 616 for (BluetoothGattCharacteristic* characteristic : |
533 service->GetCharacteristics()) { | 617 service_query_outcome.second->GetCharacteristics()) { |
534 if (characteristic->GetUUID().canonical_value() == characteristic_uuid) { | 618 if (characteristic->GetUUID().canonical_value() == characteristic_uuid) { |
535 const std::string& characteristic_instance_id = | 619 const std::string& characteristic_instance_id = |
536 characteristic->GetIdentifier(); | 620 characteristic->GetIdentifier(); |
537 | 621 |
538 auto insert_result = characteristic_to_service_.insert( | 622 auto insert_result = characteristic_to_service_.insert( |
539 make_pair(characteristic_instance_id, service_instance_id)); | 623 make_pair(characteristic_instance_id, service_instance_id)); |
540 | 624 |
541 // If value is already in map, DCHECK it's valid. | 625 // If value is already in map, DCHECK it's valid. |
542 if (!insert_result.second) | 626 if (!insert_result.second) |
543 DCHECK(insert_result.first->second == service_instance_id); | 627 DCHECK(insert_result.first->second == service_instance_id); |
(...skipping 12 matching lines...) Expand all Loading... |
556 } | 640 } |
557 | 641 |
558 void BluetoothDispatcherHost::OnReadValue( | 642 void BluetoothDispatcherHost::OnReadValue( |
559 int thread_id, | 643 int thread_id, |
560 int request_id, | 644 int request_id, |
561 const std::string& characteristic_instance_id) { | 645 const std::string& characteristic_instance_id) { |
562 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 646 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
563 RecordWebBluetoothFunctionCall( | 647 RecordWebBluetoothFunctionCall( |
564 UMAWebBluetoothFunction::CHARACTERISTIC_READ_VALUE); | 648 UMAWebBluetoothFunction::CHARACTERISTIC_READ_VALUE); |
565 | 649 |
566 auto characteristic_iter = | 650 auto characteristic_query_outcome = |
567 characteristic_to_service_.find(characteristic_instance_id); | 651 QueryForCharacteristic(characteristic_instance_id); |
568 // A characteristic_instance_id not in the map implies a hostile renderer | |
569 // because a renderer obtains the characteristic id from this class and | |
570 // it will be added to the map at that time. | |
571 if (characteristic_iter == characteristic_to_service_.end()) { | |
572 // Kill the renderer | |
573 bad_message::ReceivedBadMessage(this, | |
574 bad_message::BDH_INVALID_CHARACTERISTIC_ID); | |
575 return; | |
576 } | |
577 const std::string& service_instance_id = characteristic_iter->second; | |
578 | 652 |
579 auto device_iter = service_to_device_.find(service_instance_id); | 653 if (characteristic_query_outcome.first != CacheQueryOutcome::SUCCESS) { |
580 | 654 CacheQueryOutcome error_outcome = characteristic_query_outcome.first; |
581 CHECK(device_iter != service_to_device_.end()); | 655 if (error_outcome == CacheQueryOutcome::BAD_RENDERER) { |
582 | 656 // The query handles the message. |
583 device::BluetoothDevice* device = | 657 return; |
584 adapter_->GetDevice(device_iter->second /* device_instance_id */); | 658 } |
585 if (device == nullptr) { // See "NETWORK_ERROR Note" above. | 659 if (error_outcome == CacheQueryOutcome::NO_DEVICE) { |
586 RecordCharacteristicReadValueOutcome(UMAGATTOperationOutcome::NO_DEVICE); | 660 RecordCharacteristicReadValueOutcome(UMAGATTOperationOutcome::NO_DEVICE); |
| 661 } else if (error_outcome == CacheQueryOutcome::NO_SERVICE) { |
| 662 RecordCharacteristicReadValueOutcome(UMAGATTOperationOutcome::NO_SERVICE); |
| 663 } else if (error_outcome == CacheQueryOutcome::NO_CHARACTERISTIC) { |
| 664 RecordCharacteristicReadValueOutcome( |
| 665 UMAGATTOperationOutcome::NO_CHARACTERISTIC); |
| 666 } |
587 Send(new BluetoothMsg_ReadCharacteristicValueError( | 667 Send(new BluetoothMsg_ReadCharacteristicValueError( |
588 thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); | 668 thread_id, request_id, |
| 669 CacheQueryOutcomeToWebBluetoothError(error_outcome))); |
589 return; | 670 return; |
590 } | 671 } |
591 | 672 |
592 BluetoothGattService* service = device->GetGattService(service_instance_id); | 673 characteristic_query_outcome.second->ReadRemoteCharacteristic( |
593 if (service == nullptr) { | |
594 RecordCharacteristicReadValueOutcome(UMAGATTOperationOutcome::NO_SERVICE); | |
595 Send(new BluetoothMsg_ReadCharacteristicValueError( | |
596 thread_id, request_id, WebBluetoothError::ServiceNoLongerExists)); | |
597 return; | |
598 } | |
599 | |
600 BluetoothGattCharacteristic* characteristic = | |
601 service->GetCharacteristic(characteristic_instance_id); | |
602 if (characteristic == nullptr) { | |
603 RecordCharacteristicReadValueOutcome( | |
604 UMAGATTOperationOutcome::NO_CHARACTERISTIC); | |
605 Send(new BluetoothMsg_ReadCharacteristicValueError( | |
606 thread_id, request_id, | |
607 WebBluetoothError::CharacteristicNoLongerExists)); | |
608 return; | |
609 } | |
610 | |
611 characteristic->ReadRemoteCharacteristic( | |
612 base::Bind(&BluetoothDispatcherHost::OnCharacteristicValueRead, | 674 base::Bind(&BluetoothDispatcherHost::OnCharacteristicValueRead, |
613 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), | 675 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), |
614 base::Bind(&BluetoothDispatcherHost::OnCharacteristicReadValueError, | 676 base::Bind(&BluetoothDispatcherHost::OnCharacteristicReadValueError, |
615 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); | 677 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); |
616 } | 678 } |
617 | 679 |
618 void BluetoothDispatcherHost::OnWriteValue( | 680 void BluetoothDispatcherHost::OnWriteValue( |
619 int thread_id, | 681 int thread_id, |
620 int request_id, | 682 int request_id, |
621 const std::string& characteristic_instance_id, | 683 const std::string& characteristic_instance_id, |
622 const std::vector<uint8_t>& value) { | 684 const std::vector<uint8_t>& value) { |
623 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 685 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
624 RecordWebBluetoothFunctionCall( | 686 RecordWebBluetoothFunctionCall( |
625 UMAWebBluetoothFunction::CHARACTERISTIC_WRITE_VALUE); | 687 UMAWebBluetoothFunction::CHARACTERISTIC_WRITE_VALUE); |
626 | 688 |
627 // Length check per step 3 of writeValue algorithm: | 689 // Length check per step 3 of writeValue algorithm: |
628 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothgattcharac
teristic-writevalue | 690 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothgattcharac
teristic-writevalue |
629 // We perform the length check on the renderer side. So if we | 691 // We perform the length check on the renderer side. So if we |
630 // get a value with length > 512, we can assume it's a hostile | 692 // get a value with length > 512, we can assume it's a hostile |
631 // renderer and kill it. | 693 // renderer and kill it. |
632 if (value.size() > 512) { | 694 if (value.size() > 512) { |
633 bad_message::ReceivedBadMessage( | 695 bad_message::ReceivedBadMessage( |
634 this, bad_message::BDH_INVALID_WRITE_VALUE_LENGTH); | 696 this, bad_message::BDH_INVALID_WRITE_VALUE_LENGTH); |
635 return; | 697 return; |
636 } | 698 } |
637 | 699 |
638 auto characteristic_iter = | 700 auto characteristic_query_outcome = |
639 characteristic_to_service_.find(characteristic_instance_id); | 701 QueryForCharacteristic(characteristic_instance_id); |
640 // A characteristic_instance_id not in the map implies a hostile renderer | |
641 // because a renderer obtains the characteristic id from this class and | |
642 // it will be added to the map at that time. | |
643 if (characteristic_iter == characteristic_to_service_.end()) { | |
644 bad_message::ReceivedBadMessage(this, | |
645 bad_message::BDH_INVALID_CHARACTERISTIC_ID); | |
646 return; | |
647 } | |
648 const std::string& service_instance_id = characteristic_iter->second; | |
649 | 702 |
650 auto device_iter = service_to_device_.find(service_instance_id); | 703 if (characteristic_query_outcome.first != CacheQueryOutcome::SUCCESS) { |
651 | 704 CacheQueryOutcome error_outcome = characteristic_query_outcome.first; |
652 CHECK(device_iter != service_to_device_.end()); | 705 if (error_outcome == CacheQueryOutcome::BAD_RENDERER) { |
653 | 706 // The query handles the message. |
654 device::BluetoothDevice* device = | 707 return; |
655 adapter_->GetDevice(device_iter->second /* device_instance_id */); | 708 } |
656 if (device == nullptr) { // See "NETWORK_ERROR Note" above. | 709 if (error_outcome == CacheQueryOutcome::NO_DEVICE) { |
657 RecordCharacteristicWriteValueOutcome(UMAGATTOperationOutcome::NO_DEVICE); | 710 RecordCharacteristicWriteValueOutcome(UMAGATTOperationOutcome::NO_DEVICE); |
| 711 } else if (error_outcome == CacheQueryOutcome::NO_SERVICE) { |
| 712 RecordCharacteristicWriteValueOutcome( |
| 713 UMAGATTOperationOutcome::NO_SERVICE); |
| 714 } else if (error_outcome == CacheQueryOutcome::NO_CHARACTERISTIC) { |
| 715 RecordCharacteristicWriteValueOutcome( |
| 716 UMAGATTOperationOutcome::NO_CHARACTERISTIC); |
| 717 } |
658 Send(new BluetoothMsg_WriteCharacteristicValueError( | 718 Send(new BluetoothMsg_WriteCharacteristicValueError( |
659 thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); | 719 thread_id, request_id, |
| 720 CacheQueryOutcomeToWebBluetoothError(error_outcome))); |
660 return; | 721 return; |
661 } | 722 } |
662 | 723 |
663 BluetoothGattService* service = device->GetGattService(service_instance_id); | 724 characteristic_query_outcome.second->WriteRemoteCharacteristic( |
664 if (service == nullptr) { | |
665 RecordCharacteristicWriteValueOutcome(UMAGATTOperationOutcome::NO_SERVICE); | |
666 Send(new BluetoothMsg_WriteCharacteristicValueError( | |
667 thread_id, request_id, WebBluetoothError::ServiceNoLongerExists)); | |
668 return; | |
669 } | |
670 | |
671 BluetoothGattCharacteristic* characteristic = | |
672 service->GetCharacteristic(characteristic_instance_id); | |
673 if (characteristic == nullptr) { | |
674 RecordCharacteristicWriteValueOutcome( | |
675 UMAGATTOperationOutcome::NO_CHARACTERISTIC); | |
676 Send(new BluetoothMsg_WriteCharacteristicValueError( | |
677 thread_id, request_id, | |
678 WebBluetoothError::CharacteristicNoLongerExists)); | |
679 return; | |
680 } | |
681 characteristic->WriteRemoteCharacteristic( | |
682 value, base::Bind(&BluetoothDispatcherHost::OnWriteValueSuccess, | 725 value, base::Bind(&BluetoothDispatcherHost::OnWriteValueSuccess, |
683 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), | 726 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id), |
684 base::Bind(&BluetoothDispatcherHost::OnWriteValueFailed, | 727 base::Bind(&BluetoothDispatcherHost::OnWriteValueFailed, |
685 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); | 728 weak_ptr_factory_.GetWeakPtr(), thread_id, request_id)); |
686 } | 729 } |
687 | 730 |
688 void BluetoothDispatcherHost::OnDiscoverySessionStarted( | 731 void BluetoothDispatcherHost::OnDiscoverySessionStarted( |
689 int chooser_id, | 732 int chooser_id, |
690 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { | 733 scoped_ptr<device::BluetoothDiscoverySession> discovery_session) { |
691 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 734 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
842 TranslateConnectError(error_code))); | 885 TranslateConnectError(error_code))); |
843 } | 886 } |
844 | 887 |
845 void BluetoothDispatcherHost::OnServicesDiscovered( | 888 void BluetoothDispatcherHost::OnServicesDiscovered( |
846 int thread_id, | 889 int thread_id, |
847 int request_id, | 890 int request_id, |
848 const std::string& device_instance_id, | 891 const std::string& device_instance_id, |
849 const std::string& service_uuid) { | 892 const std::string& service_uuid) { |
850 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 893 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
851 | 894 |
852 device::BluetoothDevice* device = adapter_->GetDevice(device_instance_id); | 895 auto device_query_result = QueryForDevice(device_instance_id); |
853 if (device == nullptr) { // See "NETWORK_ERROR Note" above. | 896 if (device_query_result.first != CacheQueryOutcome::SUCCESS) { |
854 RecordGetPrimaryServiceOutcome(UMAGetPrimaryServiceOutcome::NO_DEVICE); | 897 if (device_query_result.first == CacheQueryOutcome::NO_DEVICE) { |
| 898 RecordGetPrimaryServiceOutcome(UMAGetPrimaryServiceOutcome::NO_DEVICE); |
| 899 } |
855 Send(new BluetoothMsg_GetPrimaryServiceError( | 900 Send(new BluetoothMsg_GetPrimaryServiceError( |
856 thread_id, request_id, WebBluetoothError::DeviceNoLongerInRange)); | 901 thread_id, request_id, |
| 902 CacheQueryOutcomeToWebBluetoothError(device_query_result.first))); |
857 return; | 903 return; |
858 } | 904 } |
859 for (BluetoothGattService* service : device->GetGattServices()) { | 905 |
| 906 for (BluetoothGattService* service : |
| 907 device_query_result.second->GetGattServices()) { |
860 if (service->GetUUID().canonical_value() == service_uuid) { | 908 if (service->GetUUID().canonical_value() == service_uuid) { |
861 // TODO(ortuno): Use generated instance ID instead. | 909 // TODO(ortuno): Use generated instance ID instead. |
862 // https://crbug.com/495379 | 910 // https://crbug.com/495379 |
863 const std::string& service_identifier = service->GetIdentifier(); | 911 const std::string& service_identifier = service->GetIdentifier(); |
864 auto insert_result = service_to_device_.insert( | 912 auto insert_result = service_to_device_.insert( |
865 make_pair(service_identifier, device_instance_id)); | 913 make_pair(service_identifier, device_instance_id)); |
866 | 914 |
867 // If a value is already in map, DCHECK it's valid. | 915 // If a value is already in map, DCHECK it's valid. |
868 if (!insert_result.second) | 916 if (!insert_result.second) |
869 DCHECK(insert_result.first->second == device_instance_id); | 917 DCHECK(insert_result.first->second == device_instance_id); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
920 | 968 |
921 void BluetoothDispatcherHost::ShowBluetoothPairingLink() { | 969 void BluetoothDispatcherHost::ShowBluetoothPairingLink() { |
922 NOTIMPLEMENTED(); | 970 NOTIMPLEMENTED(); |
923 } | 971 } |
924 | 972 |
925 void BluetoothDispatcherHost::ShowBluetoothAdapterOffLink() { | 973 void BluetoothDispatcherHost::ShowBluetoothAdapterOffLink() { |
926 NOTIMPLEMENTED(); | 974 NOTIMPLEMENTED(); |
927 } | 975 } |
928 | 976 |
929 } // namespace content | 977 } // namespace content |
OLD | NEW |