Update mojo sdk to rev 1dc8a9a5db73d3718d99917fadf31f5fb2ebad4f
[chromium-blink-merge.git] / device / bluetooth / bluetooth_low_energy_discovery_manager_mac.mm
blob11d40caa6261d6a8db61b30986e5b5ab3fcfbe9e
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "device/bluetooth/bluetooth_low_energy_discovery_manager_mac.h"
7 #include "base/mac/mac_util.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/strings/sys_string_conversions.h"
10 #include "device/bluetooth/bluetooth_low_energy_device_mac.h"
12 using device::BluetoothLowEnergyDeviceMac;
13 using device::BluetoothLowEnergyDiscoveryManagerMac;
14 using device::BluetoothLowEnergyDiscoveryManagerMacDelegate;
16 namespace device {
18 // This class is a helper to call some protected methods in
19 // BluetoothLowEnergyDiscoveryManagerMac.
20 class BluetoothLowEnergyDiscoveryManagerMacDelegate {
21  public:
22   BluetoothLowEnergyDiscoveryManagerMacDelegate(
23       BluetoothLowEnergyDiscoveryManagerMac* manager)
24       : manager_(manager) {}
26   virtual ~BluetoothLowEnergyDiscoveryManagerMacDelegate() {}
28   virtual void DiscoveredPeripheral(CBPeripheral* peripheral,
29                                     NSDictionary* advertisementData,
30                                     int rssi) {
31     manager_->DiscoveredPeripheral(peripheral, advertisementData, rssi);
32   }
34   virtual void TryStartDiscovery() { manager_->TryStartDiscovery(); }
36  private:
37   BluetoothLowEnergyDiscoveryManagerMac* manager_;
40 }  // namespace device
42 // This class will serve as the Objective-C delegate of CBCentralManager.
43 @interface BluetoothLowEnergyDiscoveryManagerMacBridge
44     : NSObject<CBCentralManagerDelegate> {
45   BluetoothLowEnergyDiscoveryManagerMac* manager_;
46   scoped_ptr<BluetoothLowEnergyDiscoveryManagerMacDelegate> delegate_;
49 - (id)initWithManager:(BluetoothLowEnergyDiscoveryManagerMac*)manager;
51 @end
53 @implementation BluetoothLowEnergyDiscoveryManagerMacBridge
55 - (id)initWithManager:(BluetoothLowEnergyDiscoveryManagerMac*)manager {
56   if ((self = [super init])) {
57     manager_ = manager;
58     delegate_.reset(
59         new BluetoothLowEnergyDiscoveryManagerMacDelegate(manager_));
60   }
61   return self;
64 - (void)centralManager:(CBCentralManager*)central
65     didDiscoverPeripheral:(CBPeripheral*)peripheral
66         advertisementData:(NSDictionary*)advertisementData
67                      RSSI:(NSNumber*)RSSI {
68   // Notifies the discovery of a device.
69   delegate_->DiscoveredPeripheral(peripheral, advertisementData,
70                                   [RSSI intValue]);
73 - (void)centralManagerDidUpdateState:(CBCentralManager*)central {
74   // Notifies when the powered state of the central manager changed.
75   delegate_->TryStartDiscovery();
78 @end
80 BluetoothLowEnergyDiscoveryManagerMac::
81     ~BluetoothLowEnergyDiscoveryManagerMac() {
82   ClearDevices();
85 bool BluetoothLowEnergyDiscoveryManagerMac::IsDiscovering() const {
86   return discovering_;
89 void BluetoothLowEnergyDiscoveryManagerMac::StartDiscovery(
90     BluetoothDevice::UUIDList services_uuids) {
91   ClearDevices();
92   discovering_ = true;
93   pending_ = true;
94   services_uuids_ = services_uuids;
95   TryStartDiscovery();
98 void BluetoothLowEnergyDiscoveryManagerMac::TryStartDiscovery() {
99   if (!discovering_) {
100     return;
101   }
103   if (!pending_) {
104     return;
105   }
107   // Can only start if the bluetooth power is turned on.
108   if ([manager_ state] != CBCentralManagerStatePoweredOn) {
109     return;
110   }
112   // Converts the services UUIDs to a CoreBluetooth data structure.
113   NSMutableArray* services = nil;
114   if (!services_uuids_.empty()) {
115     services = [NSMutableArray array];
116     for (auto& service_uuid : services_uuids_) {
117       NSString* uuidString =
118           base::SysUTF8ToNSString(service_uuid.canonical_value().c_str());
119       Class aClass = NSClassFromString(@"CBUUID");
120       CBUUID* uuid = [aClass UUIDWithString:uuidString];
121       [services addObject:uuid];
122     }
123   };
125   [manager_ scanForPeripheralsWithServices:services options:nil];
126   pending_ = false;
129 void BluetoothLowEnergyDiscoveryManagerMac::StopDiscovery() {
130   if (discovering_ && !pending_) {
131     [manager_ stopScan];
132   }
133   discovering_ = false;
136 void BluetoothLowEnergyDiscoveryManagerMac::DiscoveredPeripheral(
137     CBPeripheral* peripheral,
138     NSDictionary* advertisementData,
139     int rssi) {
140   // Look for existing device.
141   auto iter = devices_.find(
142       BluetoothLowEnergyDeviceMac::GetPeripheralIdentifier(peripheral));
143   if (iter == devices_.end()) {
144     // A device has been added.
145     BluetoothLowEnergyDeviceMac* device =
146         new BluetoothLowEnergyDeviceMac(peripheral, advertisementData, rssi);
147     devices_.insert(devices_.begin(),
148                     std::make_pair(device->GetIdentifier(), device));
149     observer_->DeviceFound(device);
150     return;
151   }
153   // A device has an update.
154   BluetoothLowEnergyDeviceMac* old_device = iter->second;
155   old_device->Update(peripheral, advertisementData, rssi);
156   observer_->DeviceUpdated(old_device);
159 BluetoothLowEnergyDiscoveryManagerMac*
160 BluetoothLowEnergyDiscoveryManagerMac::Create(Observer* observer) {
161   return new BluetoothLowEnergyDiscoveryManagerMac(observer);
164 BluetoothLowEnergyDiscoveryManagerMac::BluetoothLowEnergyDiscoveryManagerMac(
165     Observer* observer)
166     : observer_(observer) {
167   bridge_.reset([[BluetoothLowEnergyDiscoveryManagerMacBridge alloc]
168       initWithManager:this]);
169   // Since CoreBluetooth is only available on OS X 10.7 or later, we
170   // instantiate CBCentralManager only for OS X >= 10.7.
171   if (base::mac::IsOSLionOrLater()) {
172     Class aClass = NSClassFromString(@"CBCentralManager");
173     manager_.reset(
174         [[aClass alloc] initWithDelegate:bridge_
175                                    queue:dispatch_get_main_queue()]);
176   }
177   discovering_ = false;
180 void BluetoothLowEnergyDiscoveryManagerMac::ClearDevices() {
181   STLDeleteValues(&devices_);