Index: device/bluetooth/bluetooth_low_energy_discovery_manager_mac.mm |
diff --git a/device/bluetooth/bluetooth_low_energy_discovery_manager_mac.mm b/device/bluetooth/bluetooth_low_energy_discovery_manager_mac.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..1d7e409c81cd864d7935326d8b8f4583cd312587 |
--- /dev/null |
+++ b/device/bluetooth/bluetooth_low_energy_discovery_manager_mac.mm |
@@ -0,0 +1,180 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "device/bluetooth/bluetooth_low_energy_discovery_manager_mac.h" |
+ |
+#include "base/mac/mac_util.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/strings/sys_string_conversions.h" |
+#include "device/bluetooth/bluetooth_low_energy_device_mac.h" |
+ |
+using device::BluetoothLowEnergyDeviceMac; |
+using device::BluetoothLowEnergyDiscoveryManagerMac; |
+using device::BluetoothLowEnergyDiscoveryManagerMacDelegate; |
+ |
+namespace device { |
+ |
+// This class is a helper to call some protected methods in |
+// BluetoothLowEnergyDiscoveryManagerMac. |
+class BluetoothLowEnergyDiscoveryManagerMacDelegate { |
+ public: |
+ BluetoothLowEnergyDiscoveryManagerMacDelegate( |
+ BluetoothLowEnergyDiscoveryManagerMac* manager) |
+ : manager_(manager) {} |
+ |
+ virtual ~BluetoothLowEnergyDiscoveryManagerMacDelegate() {} |
+ |
+ virtual void DiscoveredPeripheral(CBPeripheral* peripheral, |
+ NSDictionary* advertisementData, |
+ int rssi) { |
+ manager_->DiscoveredPeripheral(peripheral, advertisementData, rssi); |
+ } |
+ |
+ virtual void TryStartDiscovery() { manager_->TryStartDiscovery(); } |
+ |
+ private: |
+ BluetoothLowEnergyDiscoveryManagerMac* manager_; |
+}; |
+ |
+} // namespace device |
+ |
+// This class will serve as the Objective-C delegate of CBCentralManager. |
+@interface BluetoothLowEnergyDiscoveryManagerMacBridge |
+ : NSObject<CBCentralManagerDelegate> |
+ |
+- (id)initWithManager:(BluetoothLowEnergyDiscoveryManagerMac*)manager; |
+ |
+@end |
+ |
+@implementation BluetoothLowEnergyDiscoveryManagerMacBridge { |
+ BluetoothLowEnergyDiscoveryManagerMac* manager_; |
+ scoped_ptr<BluetoothLowEnergyDiscoveryManagerMacDelegate> delegate_; |
+} |
+ |
+- (id)initWithManager:(BluetoothLowEnergyDiscoveryManagerMac*)manager { |
+ if ((self = [super init])) { |
+ manager_ = manager; |
+ delegate_.reset( |
+ new BluetoothLowEnergyDiscoveryManagerMacDelegate(manager_)); |
+ } |
+ return self; |
+} |
+ |
+- (void)centralManager:(CBCentralManager*)central |
+ didDiscoverPeripheral:(CBPeripheral*)peripheral |
+ advertisementData:(NSDictionary*)advertisementData |
+ RSSI:(NSNumber*)RSSI { |
+ // Notifies the discovery of a device. |
+ delegate_->DiscoveredPeripheral(peripheral, advertisementData, |
+ [RSSI intValue]); |
+} |
+ |
+- (void)centralManagerDidUpdateState:(CBCentralManager*)central { |
+ // Notifies when the powered state of the central manager changed. |
+ delegate_->TryStartDiscovery(); |
+} |
+ |
+@end |
+ |
+BluetoothLowEnergyDiscoveryManagerMac:: |
+ ~BluetoothLowEnergyDiscoveryManagerMac() { |
+ ClearDevices(); |
+} |
+ |
+bool BluetoothLowEnergyDiscoveryManagerMac::IsDiscovering() const { |
+ return discovering_; |
+} |
+ |
+void BluetoothLowEnergyDiscoveryManagerMac::StartDiscovery( |
+ BluetoothDevice::UUIDList services_uuids) { |
+ ClearDevices(); |
+ discovering_ = true; |
+ pending_ = true; |
+ services_uuids_ = services_uuids; |
+ TryStartDiscovery(); |
+} |
+ |
+void BluetoothLowEnergyDiscoveryManagerMac::TryStartDiscovery() { |
+ if (!discovering_) { |
+ return; |
+ } |
+ |
+ if (!pending_) { |
+ return; |
+ } |
+ |
+ // Can only start if the bluetooth power is turned on. |
+ if ([manager_ state] != CBCentralManagerStatePoweredOn) { |
+ return; |
+ } |
+ |
+ // Converts the services UUIDs to a CoreBluetooth data structure. |
+ NSMutableArray* services = nil; |
+ if (!services_uuids_.empty()) { |
+ services = [NSMutableArray array]; |
+ for (auto& service_uuid : services_uuids_) { |
+ NSString* uuidString = |
+ base::SysUTF8ToNSString(service_uuid.canonical_value().c_str()); |
+ CBUUID* uuid = [CBUUID UUIDWithString:uuidString]; |
+ [services addObject:uuid]; |
+ } |
+ } |
+ |
+ [manager_ scanForPeripheralsWithServices:services options:nil]; |
+ pending_ = false; |
+} |
+ |
+void BluetoothLowEnergyDiscoveryManagerMac::StopDiscovery() { |
+ if (discovering_ && !pending_) { |
+ [manager_ stopScan]; |
+ } |
+ discovering_ = false; |
+} |
+ |
+void BluetoothLowEnergyDiscoveryManagerMac::DiscoveredPeripheral( |
+ CBPeripheral* peripheral, |
+ NSDictionary* advertisementData, |
+ int rssi) { |
+ // Look for existing device. |
+ auto iter = devices_.find( |
+ BluetoothLowEnergyDeviceMac::GetPeripheralIdentifier(peripheral)); |
+ if (iter == devices_.end()) { |
+ // A device has been added. |
+ BluetoothLowEnergyDeviceMac* device = |
+ new BluetoothLowEnergyDeviceMac(peripheral, advertisementData, rssi); |
+ devices_.insert(devices_.begin(), |
+ std::make_pair(device->GetIdentifier(), device)); |
+ observer_->DeviceFound(device); |
+ return; |
+ } |
+ |
+ // A device has an update. |
+ BluetoothLowEnergyDeviceMac* old_device = iter->second; |
+ old_device->Update(peripheral, advertisementData, rssi); |
+ observer_->DeviceUpdated(old_device); |
+} |
+ |
+BluetoothLowEnergyDiscoveryManagerMac* |
+BluetoothLowEnergyDiscoveryManagerMac::Create(Observer* observer) { |
+ return new BluetoothLowEnergyDiscoveryManagerMac(observer); |
+} |
+ |
+BluetoothLowEnergyDiscoveryManagerMac::BluetoothLowEnergyDiscoveryManagerMac( |
+ Observer* observer) |
+ : observer_(observer) { |
+ bridge_.reset([[BluetoothLowEnergyDiscoveryManagerMacBridge alloc] |
+ initWithManager:this]); |
+ // Since CoreBluetooth is only available on OS X 10.7 or later, we |
+ // instantiate CBCentralManager only for OS X >= 10.7. |
+ if (base::mac::IsOSLionOrLater()) { |
+ manager_.reset( |
+ [[CBCentralManager alloc] initWithDelegate:bridge_ |
+ queue:dispatch_get_main_queue()]); |
+ } |
+ discovering_ = false; |
+} |
+ |
+void BluetoothLowEnergyDiscoveryManagerMac::ClearDevices() { |
+ STLDeleteValues(&devices_); |
+} |