| 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 |