123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- // Copyright 2018 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_device_watcher_mac.h"
- #include <utility>
- #include "base/bind.h"
- #include "base/files/file_util.h"
- #include "base/logging.h"
- #include "base/strings/sys_string_conversions.h"
- #include "base/task/task_traits.h"
- #include "device/bluetooth/bluetooth_adapter_mac.h"
- namespace device {
- namespace {
- constexpr char kBluetoothPlistFilePath[] =
- "/Library/Preferences/com.apple.Bluetooth.plist";
- } // namespace
- // static
- scoped_refptr<BluetoothLowEnergyDeviceWatcherMac>
- BluetoothLowEnergyDeviceWatcherMac::CreateAndStartWatching(
- scoped_refptr<base::SequencedTaskRunner> ui_thread_task_runner,
- LowEnergyDeviceListUpdatedCallback
- low_energy_device_list_updated_callback) {
- auto watcher = base::MakeRefCounted<BluetoothLowEnergyDeviceWatcherMac>(
- std::move(ui_thread_task_runner),
- std::move(low_energy_device_list_updated_callback));
- watcher->Init();
- return watcher;
- }
- BluetoothLowEnergyDeviceWatcherMac::BluetoothLowEnergyDeviceWatcherMac(
- scoped_refptr<base::SequencedTaskRunner> ui_thread_task_runner,
- LowEnergyDeviceListUpdatedCallback low_energy_device_list_updated_callback)
- : ui_thread_task_runner_(std::move(ui_thread_task_runner)),
- low_energy_device_list_updated_callback_(
- std::move(low_energy_device_list_updated_callback)) {
- DETACH_FROM_SEQUENCE(sequence_checker_);
- }
- BluetoothLowEnergyDeviceWatcherMac::~BluetoothLowEnergyDeviceWatcherMac() {
- file_thread_task_runner_->DeleteSoon(FROM_HERE,
- property_list_watcher_.release());
- }
- void BluetoothLowEnergyDeviceWatcherMac::OnPropertyListFileChangedOnFileThread(
- const base::FilePath& path,
- bool error) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (error) {
- LOG(WARNING) << "Failed to read com.apple.Bluetooth.plist.";
- return;
- }
- // Bluetooth property list file is expected to have the following format:
- //
- // "CoreBluetoothCache" => {
- // "E7F8589A-A7D9-4B94-9A08-D89076A159F4" => {
- // "DeviceAddress" => "11-11-11-11-11-11"
- // "DeviceAddressType" => 1
- // "ServiceChangedHandle" => 3
- // "ServiceChangedSubscribed" => 0
- // "ServiceDiscoveryComplete" => 0
- // }
- // "D3CAC59E-C501-4599-97DA-2DF491544EEE" => {
- // "DeviceAddress" => "22-22-22-22-22-22"
- // "DeviceAddressType" => 1
- // "ServiceChangedHandle" => 3
- // "ServiceChangedSubscribed" => 0
- // "ServiceDiscoveryComplete" => 0
- // }
- // }
- NSString* plist_file_path = base::SysUTF8ToNSString(path.value());
- NSDictionary* bluetooth_info_dictionary =
- [NSDictionary dictionaryWithContentsOfFile:plist_file_path];
- // |bluetooth_info_dictionary| is nil if there was an error reading the file
- // or if the content of the read file cannot be represented by a dictionary.
- if (!bluetooth_info_dictionary)
- return;
- auto parsed_data =
- ParseBluetoothDevicePropertyListData(bluetooth_info_dictionary);
- ui_thread_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(low_energy_device_list_updated_callback_,
- std::move(parsed_data)));
- }
- void BluetoothLowEnergyDeviceWatcherMac::Init() {
- file_thread_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&BluetoothLowEnergyDeviceWatcherMac::
- AddBluetoothPropertyListFileWatcher,
- this));
- }
- void BluetoothLowEnergyDeviceWatcherMac::ReadBluetoothPropertyListFile() {
- file_thread_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&BluetoothLowEnergyDeviceWatcherMac::
- OnPropertyListFileChangedOnFileThread,
- this, BluetoothPlistFilePath(), false /* error */));
- }
- std::map<std::string, std::string>
- BluetoothLowEnergyDeviceWatcherMac::ParseBluetoothDevicePropertyListData(
- NSDictionary* data) {
- std::map<std::string, std::string> updated_low_energy_devices_info;
- NSDictionary* low_energy_devices_info = data[@"CoreBluetoothCache"];
- if (!low_energy_devices_info)
- return updated_low_energy_devices_info;
- for (NSString* identifier in low_energy_devices_info) {
- NSDictionary* device_info = low_energy_devices_info[identifier];
- if (!device_info)
- continue;
- NSString* raw_device_address = device_info[@"DeviceAddress"];
- if (!raw_device_address)
- continue;
- NSString* formatted_device_address =
- [raw_device_address stringByReplacingOccurrencesOfString:@"-"
- withString:@":"];
- updated_low_energy_devices_info[base::SysNSStringToUTF8(identifier)] =
- base::SysNSStringToUTF8(formatted_device_address);
- }
- return updated_low_energy_devices_info;
- }
- // static
- const base::FilePath&
- BluetoothLowEnergyDeviceWatcherMac::BluetoothPlistFilePath() {
- static const base::FilePath file_path(kBluetoothPlistFilePath);
- return file_path;
- }
- void BluetoothLowEnergyDeviceWatcherMac::AddBluetoothPropertyListFileWatcher() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- property_list_watcher_->Watch(
- BluetoothPlistFilePath(), base::FilePathWatcher::Type::kNonRecursive,
- base::BindRepeating(&BluetoothLowEnergyDeviceWatcherMac::
- OnPropertyListFileChangedOnFileThread,
- this));
- }
- } // namespace device
|