Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4160)

Unified Diff: chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc

Issue 349433002: chrome.bluetoothLowEnergy: Introduce connect and disconnect methods. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased & marked occurrences isLocal as nodoc Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc
diff --git a/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc b/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc
index 9e2761ece155b53db7bb6a730aaf1cd018b60865..bfd3eb57d1f0c48ba0fb5a13ee3d451e338722dd 100644
--- a/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc
+++ b/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc
@@ -7,11 +7,13 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/values.h"
+#include "chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_connection.h"
#include "chrome/browser/extensions/api/bluetooth_low_energy/utils.h"
#include "chrome/common/extensions/api/bluetooth/bluetooth_manifest_data.h"
#include "content/public/browser/browser_thread.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/bluetooth/bluetooth_gatt_characteristic.h"
+#include "device/bluetooth/bluetooth_gatt_connection.h"
#include "device/bluetooth/bluetooth_gatt_descriptor.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_registry.h"
@@ -22,6 +24,7 @@ using device::BluetoothAdapter;
using device::BluetoothAdapterFactory;
using device::BluetoothDevice;
using device::BluetoothGattCharacteristic;
+using device::BluetoothGattConnection;
using device::BluetoothGattDescriptor;
using device::BluetoothGattService;
@@ -120,6 +123,19 @@ void PopulateDescriptor(const BluetoothGattDescriptor* descriptor,
out->value.reset(new std::string(value.begin(), value.end()));
}
+typedef extensions::ApiResourceManager<extensions::BluetoothLowEnergyConnection>
+ ConnectionResourceManager;
+ConnectionResourceManager* GetConnectionResourceManager(
+ content::BrowserContext* context) {
+ ConnectionResourceManager* manager = ConnectionResourceManager::Get(context);
+ DCHECK(manager)
+ << "There is no Bluetooth low energy connection manager. "
+ "If this assertion is failing during a test, then it is likely that "
+ "TestExtensionSystem is failing to provide an instance of "
+ "ApiResourceManager<BluetoothLowEnergyConnection>.";
+ return manager;
+}
+
} // namespace
namespace extensions {
@@ -193,6 +209,94 @@ bool BluetoothLowEnergyEventRouter::HasAdapter() const {
return (adapter_.get() != NULL);
}
+void BluetoothLowEnergyEventRouter::Connect(
+ bool persistent,
+ const Extension* extension,
+ const std::string& device_address,
+ const base::Closure& callback,
+ const ErrorCallback& error_callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (!adapter_) {
+ VLOG(1) << "BluetoothAdapter not ready.";
+ error_callback.Run(kStatusErrorFailed);
+ return;
+ }
+
+ if (connecting_devices_.count(device_address) != 0) {
+ error_callback.Run(kStatusErrorInProgress);
+ return;
+ }
+
+ const std::string extension_id = extension->id();
+ BluetoothLowEnergyConnection* conn =
+ FindConnection(extension_id, device_address);
+ if (conn) {
+ if (conn->GetConnection()->IsConnected()) {
+ VLOG(1) << "Application already connected to device: " << device_address;
+ error_callback.Run(kStatusErrorAlreadyConnected);
+ return;
+ }
+
+ // There is a connection object but it's no longer active. Simply remove it.
+ RemoveConnection(extension_id, device_address);
+ }
+
+ BluetoothDevice* device = adapter_->GetDevice(device_address);
+ if (!device) {
+ VLOG(1) << "Bluetooth device not found: " << device_address;
+ error_callback.Run(kStatusErrorNotFound);
+ return;
+ }
+
+ connecting_devices_.insert(device_address);
+ device->CreateGattConnection(
+ base::Bind(&BluetoothLowEnergyEventRouter::OnCreateGattConnection,
+ weak_ptr_factory_.GetWeakPtr(),
+ persistent,
+ extension_id,
+ device_address,
+ callback),
+ base::Bind(&BluetoothLowEnergyEventRouter::OnConnectError,
+ weak_ptr_factory_.GetWeakPtr(),
+ device_address,
+ error_callback));
+}
+
+void BluetoothLowEnergyEventRouter::Disconnect(
+ const Extension* extension,
+ const std::string& device_address,
+ const base::Closure& callback,
+ const ErrorCallback& error_callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (!adapter_) {
+ VLOG(1) << "BluetoothAdapter not ready.";
+ error_callback.Run(kStatusErrorFailed);
+ return;
+ }
+
+ if (disconnecting_devices_.count(device_address) != 0) {
+ error_callback.Run(kStatusErrorInProgress);
+ return;
+ }
+
+ const std::string& extension_id = extension->id();
+ BluetoothLowEnergyConnection* conn =
+ FindConnection(extension_id, device_address);
+ if (!conn || !conn->GetConnection()->IsConnected()) {
+ VLOG(1) << "Application not connected to device: " << device_address;
+ error_callback.Run(kStatusErrorNotConnected);
+ return;
+ }
+
+ disconnecting_devices_.insert(device_address);
+ conn->GetConnection()->Disconnect(
+ base::Bind(&BluetoothLowEnergyEventRouter::OnDisconnect,
+ weak_ptr_factory_.GetWeakPtr(),
+ extension_id,
+ device_address,
+ callback));
+}
+
bool BluetoothLowEnergyEventRouter::GetServices(
const std::string& device_address,
ServiceList* out_services) const {
@@ -440,8 +544,7 @@ BluetoothLowEnergyEventRouter::GetDescriptor(
return kStatusSuccess;
}
-BluetoothLowEnergyEventRouter::Status
-BluetoothLowEnergyEventRouter::ReadCharacteristicValue(
+void BluetoothLowEnergyEventRouter::ReadCharacteristicValue(
const Extension* extension,
const std::string& instance_id,
const base::Closure& callback,
@@ -450,14 +553,16 @@ BluetoothLowEnergyEventRouter::ReadCharacteristicValue(
DCHECK(extension);
if (!adapter_) {
VLOG(1) << "BluetoothAdapter not ready.";
- return kStatusErrorFailed;
+ error_callback.Run(kStatusErrorFailed);
+ return;
}
BluetoothGattCharacteristic* characteristic =
FindCharacteristicById(instance_id);
if (!characteristic) {
VLOG(1) << "Characteristic not found: " << instance_id;
- return kStatusErrorNotFound;
+ error_callback.Run(kStatusErrorNotFound);
+ return;
}
BluetoothPermissionRequest request(
@@ -465,7 +570,8 @@ BluetoothLowEnergyEventRouter::ReadCharacteristicValue(
if (!BluetoothManifestData::CheckRequest(extension, request)) {
VLOG(1) << "App has no permission to access this characteristic: "
<< instance_id;
- return kStatusErrorPermissionDenied;
+ error_callback.Run(kStatusErrorPermissionDenied);
+ return;
}
characteristic->ReadRemoteCharacteristic(
@@ -475,12 +581,9 @@ BluetoothLowEnergyEventRouter::ReadCharacteristicValue(
base::Bind(&BluetoothLowEnergyEventRouter::OnError,
weak_ptr_factory_.GetWeakPtr(),
error_callback));
-
- return kStatusSuccess;
}
-BluetoothLowEnergyEventRouter::Status
-BluetoothLowEnergyEventRouter::WriteCharacteristicValue(
+void BluetoothLowEnergyEventRouter::WriteCharacteristicValue(
const Extension* extension,
const std::string& instance_id,
const std::vector<uint8>& value,
@@ -490,14 +593,16 @@ BluetoothLowEnergyEventRouter::WriteCharacteristicValue(
DCHECK(extension);
if (!adapter_) {
VLOG(1) << "BluetoothAdapter not ready.";
- return kStatusErrorFailed;
+ error_callback.Run(kStatusErrorFailed);
+ return;
}
BluetoothGattCharacteristic* characteristic =
FindCharacteristicById(instance_id);
if (!characteristic) {
VLOG(1) << "Characteristic not found: " << instance_id;
- return kStatusErrorNotFound;
+ error_callback.Run(kStatusErrorNotFound);
+ return;
}
BluetoothPermissionRequest request(
@@ -505,7 +610,8 @@ BluetoothLowEnergyEventRouter::WriteCharacteristicValue(
if (!BluetoothManifestData::CheckRequest(extension, request)) {
VLOG(1) << "App has no permission to access this characteristic: "
<< instance_id;
- return kStatusErrorPermissionDenied;
+ error_callback.Run(kStatusErrorPermissionDenied);
+ return;
}
characteristic->WriteRemoteCharacteristic(
@@ -514,11 +620,9 @@ BluetoothLowEnergyEventRouter::WriteCharacteristicValue(
base::Bind(&BluetoothLowEnergyEventRouter::OnError,
weak_ptr_factory_.GetWeakPtr(),
error_callback));
- return kStatusSuccess;
}
-BluetoothLowEnergyEventRouter::Status
-BluetoothLowEnergyEventRouter::ReadDescriptorValue(
+void BluetoothLowEnergyEventRouter::ReadDescriptorValue(
const Extension* extension,
const std::string& instance_id,
const base::Closure& callback,
@@ -527,13 +631,15 @@ BluetoothLowEnergyEventRouter::ReadDescriptorValue(
DCHECK(extension);
if (!adapter_) {
VLOG(1) << "BluetoothAdapter not ready.";
- return kStatusErrorFailed;
+ error_callback.Run(kStatusErrorFailed);
+ return;
}
BluetoothGattDescriptor* descriptor = FindDescriptorById(instance_id);
if (!descriptor) {
VLOG(1) << "Descriptor not found: " << instance_id;
- return kStatusErrorNotFound;
+ error_callback.Run(kStatusErrorNotFound);
+ return;
}
BluetoothPermissionRequest request(
@@ -541,7 +647,8 @@ BluetoothLowEnergyEventRouter::ReadDescriptorValue(
if (!BluetoothManifestData::CheckRequest(extension, request)) {
VLOG(1) << "App has no permission to access this descriptor: "
<< instance_id;
- return kStatusErrorPermissionDenied;
+ error_callback.Run(kStatusErrorPermissionDenied);
+ return;
}
descriptor->ReadRemoteDescriptor(
@@ -551,11 +658,9 @@ BluetoothLowEnergyEventRouter::ReadDescriptorValue(
base::Bind(&BluetoothLowEnergyEventRouter::OnError,
weak_ptr_factory_.GetWeakPtr(),
error_callback));
- return kStatusSuccess;
}
-BluetoothLowEnergyEventRouter::Status
-BluetoothLowEnergyEventRouter::WriteDescriptorValue(
+void BluetoothLowEnergyEventRouter::WriteDescriptorValue(
const Extension* extension,
const std::string& instance_id,
const std::vector<uint8>& value,
@@ -565,13 +670,15 @@ BluetoothLowEnergyEventRouter::WriteDescriptorValue(
DCHECK(extension);
if (!adapter_) {
VLOG(1) << "BluetoothAdapter not ready.";
- return kStatusErrorFailed;
+ error_callback.Run(kStatusErrorFailed);
+ return;
}
BluetoothGattDescriptor* descriptor = FindDescriptorById(instance_id);
if (!descriptor) {
VLOG(1) << "Descriptor not found: " << instance_id;
- return kStatusErrorNotFound;
+ error_callback.Run(kStatusErrorNotFound);
+ return;
}
BluetoothPermissionRequest request(
@@ -579,7 +686,8 @@ BluetoothLowEnergyEventRouter::WriteDescriptorValue(
if (!BluetoothManifestData::CheckRequest(extension, request)) {
VLOG(1) << "App has no permission to access this descriptor: "
<< instance_id;
- return kStatusErrorPermissionDenied;
+ error_callback.Run(kStatusErrorPermissionDenied);
+ return;
}
descriptor->WriteRemoteDescriptor(
@@ -588,7 +696,6 @@ BluetoothLowEnergyEventRouter::WriteDescriptorValue(
base::Bind(&BluetoothLowEnergyEventRouter::OnError,
weak_ptr_factory_.GetWeakPtr(),
error_callback));
- return kStatusSuccess;
}
void BluetoothLowEnergyEventRouter::SetAdapterForTesting(
@@ -1007,10 +1114,108 @@ void BluetoothLowEnergyEventRouter::OnValueSuccess(
callback.Run();
}
+void BluetoothLowEnergyEventRouter::OnCreateGattConnection(
+ bool persistent,
+ const std::string& extension_id,
+ const std::string& device_address,
+ const base::Closure& callback,
+ scoped_ptr<BluetoothGattConnection> connection) {
+ VLOG(2) << "GATT connection created.";
+ DCHECK(connection.get());
+ DCHECK(!FindConnection(extension_id, device_address));
+ DCHECK_EQ(device_address, connection->GetDeviceAddress());
+ DCHECK_NE(0U, connecting_devices_.count(device_address));
+
+ BluetoothLowEnergyConnection* conn = new BluetoothLowEnergyConnection(
+ persistent, extension_id, connection.Pass());
+ ConnectionResourceManager* manager =
+ GetConnectionResourceManager(browser_context_);
+ manager->Add(conn);
+
+ connecting_devices_.erase(device_address);
+ callback.Run();
+}
+
+void BluetoothLowEnergyEventRouter::OnDisconnect(
+ const std::string& extension_id,
+ const std::string& device_address,
+ const base::Closure& callback) {
+ VLOG(2) << "GATT connection terminated.";
+ DCHECK_NE(0U, disconnecting_devices_.count(device_address));
+ if (!RemoveConnection(extension_id, device_address)) {
+ VLOG(1) << "The connection was removed before disconnect completed, id: "
+ << extension_id << ", device: " << device_address;
+ }
+
+ disconnecting_devices_.erase(device_address);
+ callback.Run();
+}
+
void BluetoothLowEnergyEventRouter::OnError(
const ErrorCallback& error_callback) {
VLOG(2) << "Remote characteristic/descriptor value read/write failed.";
error_callback.Run(kStatusErrorFailed);
}
+void BluetoothLowEnergyEventRouter::OnConnectError(
+ const std::string& device_address,
+ const ErrorCallback& error_callback,
+ BluetoothDevice::ConnectErrorCode error_code) {
+ VLOG(2) << "Failed to create GATT connection: " << error_code;
+ DCHECK_NE(0U, connecting_devices_.count(device_address));
+
+ connecting_devices_.erase(device_address);
+ error_callback.Run(kStatusErrorFailed);
+}
+
+BluetoothLowEnergyConnection* BluetoothLowEnergyEventRouter::FindConnection(
+ const std::string& extension_id,
+ const std::string& device_address) {
+ ConnectionResourceManager* manager =
+ GetConnectionResourceManager(browser_context_);
+
+ base::hash_set<int>* connection_ids = manager->GetResourceIds(extension_id);
+ if (!connection_ids)
+ return NULL;
+
+ for (base::hash_set<int>::const_iterator iter = connection_ids->begin();
+ iter != connection_ids->end();
+ ++iter) {
+ extensions::BluetoothLowEnergyConnection* conn =
+ manager->Get(extension_id, *iter);
+ if (!conn)
+ continue;
+
+ if (conn->GetConnection()->GetDeviceAddress() == device_address)
+ return conn;
+ }
+
+ return NULL;
+}
+
+bool BluetoothLowEnergyEventRouter::RemoveConnection(
+ const std::string& extension_id,
+ const std::string& device_address) {
+ ConnectionResourceManager* manager =
+ GetConnectionResourceManager(browser_context_);
+
+ base::hash_set<int>* connection_ids = manager->GetResourceIds(extension_id);
+ if (!connection_ids)
+ return false;
+
+ for (base::hash_set<int>::const_iterator iter = connection_ids->begin();
+ iter != connection_ids->end();
+ ++iter) {
+ extensions::BluetoothLowEnergyConnection* conn =
+ manager->Get(extension_id, *iter);
+ if (!conn || conn->GetConnection()->GetDeviceAddress() != device_address)
+ continue;
+
+ manager->Remove(extension_id, *iter);
+ return true;
+ }
+
+ return false;
+}
+
} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698