chrome.bluetoothLowEnergy: Implement readDescriptorValue.

This CL implements the readDescriptorValue function of the
bluetoothLowEnergy API.

BUG=265663
TEST=browser_tests --gtest_filter=BluetoothLowEnergyApiTest.*

Review URL: https://codereview.chromium.org/297003004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@272445 0039d316-1c4b-4281-b951-d872f2087c98
parent 4e4b23eb
...@@ -30,6 +30,8 @@ const char kErrorDeviceNotFoundFormat[] = ...@@ -30,6 +30,8 @@ const char kErrorDeviceNotFoundFormat[] =
"Device with address \"%s\" not found."; "Device with address \"%s\" not found.";
const char kErrorReadCharacteristicValueFailedFormat[] = const char kErrorReadCharacteristicValueFailedFormat[] =
"Failed to read value of characteristic with ID \"%s\"."; "Failed to read value of characteristic with ID \"%s\".";
const char kErrorReadDescriptorValueFailedFormat[] =
"Failed to read value of descriptor with ID \"%s\".";
const char kErrorServiceNotFoundFormat[] = "Service with ID \"%s\" not found."; const char kErrorServiceNotFoundFormat[] = "Service with ID \"%s\" not found.";
const char kErrorPlatformNotSupported[] = const char kErrorPlatformNotSupported[] =
"This operation is not supported on the current platform"; "This operation is not supported on the current platform";
...@@ -486,10 +488,65 @@ void BluetoothLowEnergyWriteCharacteristicValueFunction::ErrorCallback() { ...@@ -486,10 +488,65 @@ void BluetoothLowEnergyWriteCharacteristicValueFunction::ErrorCallback() {
} }
bool BluetoothLowEnergyReadDescriptorValueFunction::DoWork() { bool BluetoothLowEnergyReadDescriptorValueFunction::DoWork() {
// TODO(armansito): Implement. DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
SetError("Call not supported.");
BluetoothLowEnergyEventRouter* event_router =
GetEventRouter(browser_context());
// The adapter must be initialized at this point, but return an error instead
// of asserting.
if (!event_router->HasAdapter()) {
SetError(kErrorAdapterNotInitialized);
SendResponse(false);
return false;
}
scoped_ptr<apibtle::ReadDescriptorValue::Params> params(
apibtle::ReadDescriptorValue::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
instance_id_ = params->descriptor_id;
if (!event_router->ReadDescriptorValue(
instance_id_,
base::Bind(
&BluetoothLowEnergyReadDescriptorValueFunction::SuccessCallback,
this),
base::Bind(
&BluetoothLowEnergyReadDescriptorValueFunction::ErrorCallback,
this))) {
SetError(base::StringPrintf(kErrorDescriptorNotFoundFormat,
instance_id_.c_str()));
SendResponse(false);
return false;
}
return true;
}
void BluetoothLowEnergyReadDescriptorValueFunction::SuccessCallback() {
// Obtain info on the descriptor and see whether or not the descriptor is
// still around.
apibtle::Descriptor descriptor;
if (!GetEventRouter(browser_context())
->GetDescriptor(instance_id_, &descriptor)) {
SetError(base::StringPrintf(kErrorDescriptorNotFoundFormat,
instance_id_.c_str()));
SendResponse(false);
return;
}
// Manually construct the result instead of using
// apibtle::GetDescriptor::Results::Create as it doesn't convert lists of
// enums correctly.
SetResult(apibtle::DescriptorToValue(&descriptor).release());
SendResponse(true);
}
void BluetoothLowEnergyReadDescriptorValueFunction::ErrorCallback() {
SetError(base::StringPrintf(kErrorReadDescriptorValueFailedFormat,
instance_id_.c_str()));
SendResponse(false); SendResponse(false);
return false;
} }
bool BluetoothLowEnergyWriteDescriptorValueFunction::DoWork() { bool BluetoothLowEnergyWriteDescriptorValueFunction::DoWork() {
......
...@@ -219,6 +219,15 @@ class BluetoothLowEnergyReadDescriptorValueFunction ...@@ -219,6 +219,15 @@ class BluetoothLowEnergyReadDescriptorValueFunction
// BluetoothLowEnergyExtensionFunction override. // BluetoothLowEnergyExtensionFunction override.
virtual bool DoWork() OVERRIDE; virtual bool DoWork() OVERRIDE;
private:
// Success and error callbacks, called by
// BluetoothLowEnergyEventRouter::ReadDescriptorValue.
void SuccessCallback();
void ErrorCallback();
// The instance ID of the requested descriptor.
std::string instance_id_;
}; };
class BluetoothLowEnergyWriteDescriptorValueFunction class BluetoothLowEnergyWriteDescriptorValueFunction
......
...@@ -858,4 +858,49 @@ IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, DescriptorValueChanged) { ...@@ -858,4 +858,49 @@ IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, DescriptorValueChanged) {
event_router()->DeviceRemoved(mock_adapter_, device_.get()); event_router()->DeviceRemoved(mock_adapter_, device_.get());
} }
IN_PROC_BROWSER_TEST_F(BluetoothLowEnergyApiTest, ReadDescriptorValue) {
ResultCatcher catcher;
catcher.RestrictToProfile(browser()->profile());
event_router()->DeviceAdded(mock_adapter_, device_.get());
event_router()->GattServiceAdded(device_.get(), service0_.get());
event_router()->GattCharacteristicAdded(service0_.get(), chrc0_.get());
event_router()->GattDescriptorAdded(chrc0_.get(), desc0_.get());
EXPECT_CALL(*mock_adapter_, GetDevice(_))
.Times(3)
.WillRepeatedly(Return(device_.get()));
EXPECT_CALL(*device_, GetGattService(kTestServiceId0))
.Times(3)
.WillRepeatedly(Return(service0_.get()));
EXPECT_CALL(*service0_, GetCharacteristic(kTestCharacteristicId0))
.Times(3)
.WillRepeatedly(Return(chrc0_.get()));
EXPECT_CALL(*chrc0_, GetDescriptor(kTestDescriptorId0))
.Times(3)
.WillRepeatedly(Return(desc0_.get()));
EXPECT_CALL(*desc0_, ReadRemoteDescriptor(_, _))
.Times(2)
.WillOnce(Invoke(&ReadValueErrorCallback))
.WillOnce(Invoke(&ReadValueSuccessCallback));
ExtensionTestMessageListener listener("ready", true);
ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII(
"bluetooth_low_energy/read_descriptor_value")));
EXPECT_TRUE(listener.WaitUntilSatisfied());
listener.Reply("go");
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
event_router()->GattDescriptorRemoved(chrc0_.get(), desc0_.get());
event_router()->GattCharacteristicRemoved(service0_.get(), chrc0_.get());
event_router()->GattServiceRemoved(device_.get(), service0_.get());
event_router()->DeviceRemoved(mock_adapter_, device_.get());
}
} // namespace } // namespace
...@@ -441,6 +441,30 @@ bool BluetoothLowEnergyEventRouter::WriteCharacteristicValue( ...@@ -441,6 +441,30 @@ bool BluetoothLowEnergyEventRouter::WriteCharacteristicValue(
return true; return true;
} }
bool BluetoothLowEnergyEventRouter::ReadDescriptorValue(
const std::string& instance_id,
const base::Closure& callback,
const base::Closure& error_callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
if (!adapter_) {
VLOG(1) << "BluetoothAdapter not ready.";
return false;
}
BluetoothGattDescriptor* descriptor = FindDescriptorById(instance_id);
if (!descriptor) {
VLOG(1) << "Descriptor not found: " << instance_id;
return false;
}
descriptor->ReadRemoteDescriptor(
base::Bind(&BluetoothLowEnergyEventRouter::ValueCallback,
weak_ptr_factory_.GetWeakPtr(),
callback),
error_callback);
return true;
}
void BluetoothLowEnergyEventRouter::SetAdapterForTesting( void BluetoothLowEnergyEventRouter::SetAdapterForTesting(
device::BluetoothAdapter* adapter) { device::BluetoothAdapter* adapter) {
adapter_ = adapter; adapter_ = adapter;
...@@ -812,7 +836,7 @@ BluetoothGattDescriptor* BluetoothLowEnergyEventRouter::FindDescriptorById( ...@@ -812,7 +836,7 @@ BluetoothGattDescriptor* BluetoothLowEnergyEventRouter::FindDescriptorById(
void BluetoothLowEnergyEventRouter::ValueCallback( void BluetoothLowEnergyEventRouter::ValueCallback(
const base::Closure& callback, const base::Closure& callback,
const std::vector<uint8>& value) { const std::vector<uint8>& value) {
VLOG(2) << "Remote characteristic value read successful."; VLOG(2) << "Remote characteristic/descriptor value read successful.";
callback.Run(); callback.Run();
} }
......
...@@ -140,6 +140,14 @@ class BluetoothLowEnergyEventRouter ...@@ -140,6 +140,14 @@ class BluetoothLowEnergyEventRouter
const base::Closure& callback, const base::Closure& callback,
const base::Closure& error_callback); const base::Closure& error_callback);
// Sends a request to read the value of the descriptor with instance ID
// |instance_id|. Returns false, if no such descriptor is known. Otherwise,
// returns true and invokes |callback| on success, and |error_callback| on
// failure.
bool ReadDescriptorValue(const std::string& instance_id,
const base::Closure& callback,
const base::Closure& error_callback);
// Initializes the adapter for testing. Used by unit tests only. // Initializes the adapter for testing. Used by unit tests only.
void SetAdapterForTesting(device::BluetoothAdapter* adapter); void SetAdapterForTesting(device::BluetoothAdapter* adapter);
...@@ -204,8 +212,8 @@ class BluetoothLowEnergyEventRouter ...@@ -204,8 +212,8 @@ class BluetoothLowEnergyEventRouter
device::BluetoothGattDescriptor* FindDescriptorById( device::BluetoothGattDescriptor* FindDescriptorById(
const std::string& instance_id) const; const std::string& instance_id) const;
// Called by BluetoothGattCharacteristic in response to // Called by BluetoothGattCharacteristic and BluetoothGattDescriptor in
// ReadRemoteCharacteristic. // response to ReadRemoteCharacteristic and ReadRemoteDescriptor.
void ValueCallback(const base::Closure& callback, void ValueCallback(const base::Closure& callback,
const std::vector<uint8>& value); const std::vector<uint8>& value);
......
{
"manifest_version": 2,
"name": "Test the Bluetooth Low Energy readDescriptorValue API",
"version": "1.0",
"app": {
"background": {
"scripts": ["runtest.js"]
}
},
"bluetooth": {}
}
// Copyright 2014 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.
function testReadDescriptorValue() {
chrome.test.assertTrue(descriptor != null, '\'descriptor\' is null');
chrome.test.assertEq(descId, descriptor.instanceId);
chrome.test.succeed();
}
var readDescriptorValue = chrome.bluetoothLowEnergy.readDescriptorValue;
var descId = 'desc_id0';
var badDescId = 'desc_id1';
var descriptor = null;
// 1. Unknown descriptor instanceId.
readDescriptorValue(badDescId, function (result) {
if (result || !chrome.runtime.lastError) {
chrome.test.fail('\'badDescId\' did not cause failure');
}
// 2. Known descriptor instanceId, but call failure.
readDescriptorValue(descId, function (result) {
if (result || !chrome.runtime.lastError) {
chrome.test.fail('readDescriptorValue should have failed');
}
// 3. Call should succeed.
readDescriptorValue(descId, function (result) {
if (chrome.runtime.lastError) {
chrome.test.fail(chrome.runtime.lastError.message);
}
descriptor = result;
chrome.test.sendMessage('ready', function (message) {
chrome.test.runTests([testReadDescriptorValue]);
});
});
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment