blob: 8a5eafe8d5a22d1864ac43538898697a115ff75e [file] [log] [blame]
// 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/test/mock_bluetooth_cbperipheral_mac.h"
#include "base/mac/foundation_util.h"
#include "base/mac/scoped_nsobject.h"
#include "device/bluetooth/test/bluetooth_test_mac.h"
#include "device/bluetooth/test/mock_bluetooth_cbcharacteristic_mac.h"
#include "device/bluetooth/test/mock_bluetooth_cbservice_mac.h"
using base::mac::ObjCCast;
using base::scoped_nsobject;
@interface MockCBPeripheral () {
scoped_nsobject<NSUUID> _identifier;
scoped_nsobject<NSString> _name;
id<CBPeripheralDelegate> _delegate;
scoped_nsobject<NSMutableArray> _services;
}
@end
@implementation MockCBPeripheral
@synthesize state = _state;
@synthesize delegate = _delegate;
@synthesize bluetoothTestMac = _bluetoothTestMac;
- (instancetype)init {
[self doesNotRecognizeSelector:_cmd];
return self;
}
- (instancetype)initWithUTF8StringIdentifier:(const char*)utf8Identifier {
return [self initWithUTF8StringIdentifier:utf8Identifier name:nil];
}
- (instancetype)initWithUTF8StringIdentifier:(const char*)utf8Identifier
name:(NSString*)name {
scoped_nsobject<NSUUID> identifier(
[[NSUUID alloc] initWithUUIDString:@(utf8Identifier)]);
return [self initWithIdentifier:identifier name:name];
}
- (instancetype)initWithIdentifier:(NSUUID*)identifier name:(NSString*)name {
self = [super init];
if (self) {
_identifier.reset([identifier retain]);
if (name) {
_name.reset([name retain]);
}
_state = CBPeripheralStateDisconnected;
}
return self;
}
- (BOOL)isKindOfClass:(Class)aClass {
if (aClass == [CBPeripheral class] ||
[aClass isSubclassOfClass:[CBPeripheral class]]) {
return YES;
}
return [super isKindOfClass:aClass];
}
- (BOOL)isMemberOfClass:(Class)aClass {
if (aClass == [CBPeripheral class] ||
[aClass isSubclassOfClass:[CBPeripheral class]]) {
return YES;
}
return [super isKindOfClass:aClass];
}
- (void)setState:(CBPeripheralState)state {
_state = state;
if (_state == CBPeripheralStateDisconnected) {
_services.reset();
}
}
- (void)discoverServices:(NSArray*)serviceUUIDs {
if (_bluetoothTestMac) {
_bluetoothTestMac->OnFakeBluetoothServiceDiscovery();
}
[_delegate peripheral:self.peripheral didDiscoverServices:nil];
}
- (void)discoverCharacteristics:(NSArray*)characteristics
forService:(CBService*)service {
}
- (void)discoverDescriptorsForCharacteristic:(CBCharacteristic*)characteristic {
MockCBCharacteristic* mock_characteristic =
ObjCCast<MockCBCharacteristic>(characteristic);
[mock_characteristic discoverDescriptors];
}
- (void)readValueForCharacteristic:(CBCharacteristic*)characteristic {
DCHECK(_bluetoothTestMac);
_bluetoothTestMac->OnFakeBluetoothCharacteristicReadValue();
}
- (void)writeValue:(NSData*)data
forCharacteristic:(CBCharacteristic*)characteristic
type:(CBCharacteristicWriteType)type {
DCHECK(_bluetoothTestMac);
const uint8_t* buffer = static_cast<const uint8_t*>(data.bytes);
std::vector<uint8_t> value(buffer, buffer + data.length);
_bluetoothTestMac->OnFakeBluetoothCharacteristicWriteValue(value);
}
- (void)removeAllServices {
[_services.get() removeAllObjects];
}
- (void)addServices:(NSArray*)services {
if (!_services.get()) {
_services.reset([[NSMutableArray alloc] init]);
}
for (CBUUID* uuid in services) {
base::scoped_nsobject<MockCBService> service([[MockCBService alloc]
initWithPeripheral:self.peripheral
CBUUID:uuid
primary:YES]);
[_services.get() addObject:service.get().service];
}
}
- (void)didDiscoverServicesWithError:(NSError*)error {
[_delegate peripheral:self.peripheral didDiscoverServices:error];
}
- (void)removeService:(CBService*)service {
base::scoped_nsobject<CBService> serviceToRemove(service,
base::scoped_policy::RETAIN);
DCHECK(serviceToRemove);
[_services.get() removeObject:serviceToRemove];
[self didModifyServices:@[ serviceToRemove ]];
}
- (void)mockDidDiscoverEvents {
[_delegate peripheral:self.peripheral didDiscoverServices:nil];
// BluetoothLowEnergyDeviceMac is expected to call
// -[CBPeripheral discoverCharacteristics:forService:] for each services,
// so -[<CBPeripheralDelegate peripheral:didDiscoverCharacteristicsForService:
// error:] needs to be called for all services.
for (CBService* service in _services.get()) {
[_delegate peripheral:self.peripheral
didDiscoverCharacteristicsForService:service
error:nil];
for (CBCharacteristic* characteristic in service.characteristics) {
// After discovering services, BluetoothLowEnergyDeviceMac is expected to
// discover characteristics for all services.
[_delegate peripheral:self.peripheral
didDiscoverDescriptorsForCharacteristic:characteristic
error:nil];
}
}
}
- (void)didModifyServices:(NSArray*)invalidatedServices {
DCHECK(
[_delegate respondsToSelector:@selector(peripheral:didModifyServices:)]);
[_delegate peripheral:self.peripheral didModifyServices:invalidatedServices];
}
- (void)didDiscoverDescriptorsWithCharacteristic:
(MockCBCharacteristic*)characteristic_mock {
[_delegate peripheral:self.peripheral
didDiscoverDescriptorsForCharacteristic:characteristic_mock.characteristic
error:nil];
}
- (NSUUID*)identifier {
return _identifier.get();
}
- (NSString*)name {
return _name.get();
}
- (NSArray*)services {
return _services.get();
}
- (CBPeripheral*)peripheral {
return ObjCCast<CBPeripheral>(self);
}
- (void)setNotifyValue:(BOOL)notification
forCharacteristic:(CBCharacteristic*)characteristic {
_bluetoothTestMac->OnFakeBluetoothGattSetCharacteristicNotification();
}
@end