chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h

// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_CHARACTERISTIC_MAC_H_
#define DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_CHARACTERISTIC_MAC_H_

#include "device/bluetooth/bluetooth_remote_gatt_characteristic.h"

#import <CoreBluetooth/CoreBluetooth.h>

#include <string>
#include <utility>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"

namespace device {

class BluetoothLowEnergyAdapterApple;
class BluetoothRemoteGattDescriptorMac;
class BluetoothRemoteGattServiceMac;

// The BluetoothRemoteGattCharacteristicMac class implements
// BluetoothRemoteGattCharacteristic for remote GATT services on OS X.
class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattCharacteristicMac
    : public BluetoothRemoteGattCharacteristic {
 public:
  BluetoothRemoteGattCharacteristicMac(
      BluetoothRemoteGattServiceMac* gatt_service,
      CBCharacteristic* cb_characteristic);

  BluetoothRemoteGattCharacteristicMac(
      const BluetoothRemoteGattCharacteristicMac&) = delete;
  BluetoothRemoteGattCharacteristicMac& operator=(
      const BluetoothRemoteGattCharacteristicMac&) = delete;

  ~BluetoothRemoteGattCharacteristicMac() override;

  // Override BluetoothGattCharacteristic methods.
  std::string GetIdentifier() const override;
  BluetoothUUID GetUUID() const override;
  Properties GetProperties() const override;
  Permissions GetPermissions() const override;

  // Override BluetoothRemoteGattCharacteristic methods.
  const std::vector<uint8_t>& GetValue() const override;
  BluetoothRemoteGattService* GetService() const override;
  bool IsNotifying() const override;
  void ReadRemoteCharacteristic(ValueCallback callback) override;
  void WriteRemoteCharacteristic(const std::vector<uint8_t>& value,
                                 WriteType write_type,
                                 base::OnceClosure callback,
                                 ErrorCallback error_callback) override;
  void DeprecatedWriteRemoteCharacteristic(
      const std::vector<uint8_t>& value,
      base::OnceClosure callback,
      ErrorCallback error_callback) override;

 protected:
  void SubscribeToNotifications(BluetoothRemoteGattDescriptor* ccc_descriptor,
                                base::OnceClosure callback,
                                ErrorCallback error_callback) override;
  void UnsubscribeFromNotifications(
      BluetoothRemoteGattDescriptor* ccc_descriptor,
      base::OnceClosure callback,
      ErrorCallback error_callback) override;

 private:
  friend class BluetoothLowEnergyDeviceMac;
  friend class BluetoothRemoteGattDescriptorMac;
  friend class BluetoothRemoteGattServiceMac;
  friend class BluetoothTestMac;

  void DiscoverDescriptors();
  // Called by the BluetoothRemoteGattServiceMac instance when the
  // characteristics value has been read.
  void DidUpdateValue(NSError* error);
  // Updates value_.
  void UpdateValue();
  // Called by the BluetoothRemoteGattServiceMac instance when the
  // characteristics value has been written.
  void DidWriteValue(NSError* error);
  // Called by the BluetoothRemoteGattServiceMac instance when the notify
  // session has been started or failed to be started.
  void DidUpdateNotificationState(NSError* error);
  // Called by the BluetoothRemoteGattServiceMac instance when the descriptors
  // has been discovered.
  void DidDiscoverDescriptors();
  // Returns true if the characteristic is readable.
  bool IsReadable() const;
  // Returns true if the characteristic is writable.
  bool IsWritable() const;
  // Returns true if the characteristic supports notifications or indications.
  bool SupportsNotificationsOrIndications() const;
  // Returns the write type (with or without responses).
  CBCharacteristicWriteType GetCBWriteType() const;
  // Returns CoreBluetooth characteristic.
  CBCharacteristic* GetCBCharacteristic() const;
  // Returns the LowEnergyBluetooth adapter.
  BluetoothLowEnergyAdapterApple* GetLowEnergyAdapter() const;
  // Returns CoreBluetooth peripheral.
  CBPeripheral* GetCBPeripheral() const;
  // Returns true if this characteristic has been fully discovered.
  bool IsDiscoveryComplete() const;
  // Returns BluetoothRemoteGattDescriptorMac from CBDescriptor.
  BluetoothRemoteGattDescriptorMac* GetBluetoothRemoteGattDescriptorMac(
      CBDescriptor* cb_descriptor) const;
  bool HasPendingRead() const {
    return !read_characteristic_value_callback_.is_null();
  }
  bool HasPendingWrite() const {
    return !write_characteristic_value_callbacks_.first.is_null();
  }
  // Is true if the characteristic has been discovered with all its descriptors
  // and discovery_pending_count_ is 0.
  bool is_discovery_complete_;
  // Increased each time DiscoverDescriptors() is called. And decreased when
  // DidDiscoverDescriptors() is called.
  int discovery_pending_count_;
  // gatt_service_ owns instances of this class.
  raw_ptr<BluetoothRemoteGattServiceMac> gatt_service_;
  // A characteristic from CBPeripheral.services.characteristics.
  CBCharacteristic* __strong cb_characteristic_;
  // Characteristic identifier.
  std::string identifier_;
  // Service UUID.
  BluetoothUUID uuid_;
  // Characteristic value.
  std::vector<uint8_t> value_;
  // The destructor runs callbacks. Methods can use |destructor_called_| to
  // protect against reentrant calls to a partially deleted instance.
  bool destructor_called_ = false;
  // ReadRemoteCharacteristic request callback.
  ValueCallback read_characteristic_value_callback_;
  // WriteRemoteCharacteristic request callbacks.
  std::pair<base::OnceClosure, ErrorCallback>
      write_characteristic_value_callbacks_;
  // Stores callbacks for SubscribeToNotifications and
  // UnsubscribeFromNotifications requests.
  typedef std::pair<base::OnceClosure, ErrorCallback> PendingNotifyCallbacks;
  // Stores SubscribeToNotifications request callbacks.
  PendingNotifyCallbacks subscribe_to_notification_callbacks_;
  // Stores UnsubscribeFromNotifications request callbacks.
  PendingNotifyCallbacks unsubscribe_from_notification_callbacks_;

  base::WeakPtrFactory<BluetoothRemoteGattCharacteristicMac> weak_ptr_factory_;
};

// Stream operator for logging.
DEVICE_BLUETOOTH_EXPORT std::ostream& operator<<(
    std::ostream& out,
    const BluetoothRemoteGattCharacteristicMac& characteristic);

}  // namespace device

#endif  // DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_CHARACTERISTIC_MAC_H_