summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorortuno <ortuno@chromium.org>2015-06-11 14:13:01 -0700
committerCommit bot <commit-bot@chromium.org>2015-06-11 21:14:24 +0000
commita90b6a258b57779ac848cbcef3be13d78a7922b0 (patch)
treeacd3d63b372e1b55e8122cb88aa3f881c1a23fad
parent2e57b39ba44a73b29ae949cd6e6986925be9bbe4 (diff)
downloadchromium_src-a90b6a258b57779ac848cbcef3be13d78a7922b0.zip
chromium_src-a90b6a258b57779ac848cbcef3be13d78a7922b0.tar.gz
chromium_src-a90b6a258b57779ac848cbcef3be13d78a7922b0.tar.bz2
bluetooth: Browser-side implementation of getCharacteristic
This patch also adds the necessary mocks for LayoutTests in the following patch. Updates to the Chrome Implementation Notes corresponding to this patch: https://github.com/WebBluetoothChrome/web-bluetooth/pull/9 This is the second of a set of three patches to implement getCharacteristic: [1] http://crrev.com/1153343002 [2] This patch. [3] http://crrev.com/1146163005 BUG=483344 Review URL: https://codereview.chromium.org/1156573005 Cr-Commit-Position: refs/heads/master@{#334036}
-rw-r--r--content/browser/bad_message.h1
-rw-r--r--content/browser/bluetooth/bluetooth_dispatcher_host.cc69
-rw-r--r--content/browser/bluetooth/bluetooth_dispatcher_host.h8
-rw-r--r--content/child/bluetooth/bluetooth_dispatcher.cc69
-rw-r--r--content/child/bluetooth/bluetooth_dispatcher.h16
-rw-r--r--content/child/bluetooth/web_bluetooth_impl.cc8
-rw-r--r--content/child/bluetooth/web_bluetooth_impl.h6
-rw-r--r--content/common/bluetooth/bluetooth_messages.h19
-rw-r--r--content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc51
-rw-r--r--content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h18
-rw-r--r--device/bluetooth/test/mock_bluetooth_adapter.h2
-rw-r--r--device/bluetooth/test/mock_bluetooth_device.cc9
-rw-r--r--device/bluetooth/test/mock_bluetooth_device.h7
-rw-r--r--device/bluetooth/test/mock_bluetooth_gatt_service.cc14
-rw-r--r--device/bluetooth/test/mock_bluetooth_gatt_service.h18
-rw-r--r--tools/metrics/histograms/histograms.xml1
16 files changed, 298 insertions, 18 deletions
diff --git a/content/browser/bad_message.h b/content/browser/bad_message.h
index 0c72560..566027a 100644
--- a/content/browser/bad_message.h
+++ b/content/browser/bad_message.h
@@ -106,6 +106,7 @@ enum BadMessageReason {
SWDH_GET_REGISTRATIONS_NO_HOST = 80,
SWDH_GET_REGISTRATIONS_INVALID_ORIGIN = 81,
ARH_UNAUTHORIZED_URL = 82,
+ BDH_INVALID_SERVICE_ID = 83,
// Please add new elements here. The naming convention is abbreviated class
// name (e.g. RenderFrameHost becomes RFH) plus a unique description of the
diff --git a/content/browser/bluetooth/bluetooth_dispatcher_host.cc b/content/browser/bluetooth/bluetooth_dispatcher_host.cc
index c11c203..a2c26ec 100644
--- a/content/browser/bluetooth/bluetooth_dispatcher_host.cc
+++ b/content/browser/bluetooth/bluetooth_dispatcher_host.cc
@@ -5,15 +5,18 @@
#include "content/browser/bluetooth/bluetooth_dispatcher_host.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/browser/bad_message.h"
#include "content/common/bluetooth/bluetooth_messages.h"
#include "device/bluetooth/bluetooth_adapter.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/bluetooth_discovery_session.h"
+#include "device/bluetooth/bluetooth_gatt_characteristic.h"
#include "device/bluetooth/bluetooth_gatt_service.h"
using device::BluetoothAdapter;
using device::BluetoothAdapterFactory;
+using device::BluetoothGattCharacteristic;
using device::BluetoothGattService;
namespace content {
@@ -54,6 +57,7 @@ bool BluetoothDispatcherHost::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(BluetoothHostMsg_RequestDevice, OnRequestDevice)
IPC_MESSAGE_HANDLER(BluetoothHostMsg_ConnectGATT, OnConnectGATT)
IPC_MESSAGE_HANDLER(BluetoothHostMsg_GetPrimaryService, OnGetPrimaryService)
+ IPC_MESSAGE_HANDLER(BluetoothHostMsg_GetCharacteristic, OnGetCharacteristic)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -149,6 +153,58 @@ void BluetoothDispatcherHost::OnGetPrimaryService(
base::TimeDelta::FromSeconds(current_delay_time_));
}
+void BluetoothDispatcherHost::OnGetCharacteristic(
+ int thread_id,
+ int request_id,
+ const std::string& service_instance_id,
+ const std::string& characteristic_uuid) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ auto device_iter = service_to_device_.find(service_instance_id);
+ // A service_instance_id not in the map implies a hostile renderer
+ // because a renderer obtains the service id from this class and
+ // it will be added to the map at that time.
+ if (device_iter == service_to_device_.end()) {
+ // Kill the renderer
+ bad_message::ReceivedBadMessage(this, bad_message::BDH_INVALID_SERVICE_ID);
+ return;
+ }
+
+ // TODO(ortuno): Check if domain has access to device.
+ // https://crbug.com/493459
+ device::BluetoothDevice* device =
+ adapter_->GetDevice(device_iter->second /* device_instance_id */);
+
+ if (device == NULL) {
+ Send(new BluetoothMsg_GetCharacteristicError(
+ thread_id, request_id, BluetoothError::NETWORK_ERROR));
+ return;
+ }
+
+ // TODO(ortuno): Check if domain has access to service
+ // http://crbug.com/493460
+ device::BluetoothGattService* service =
+ device->GetGattService(service_instance_id);
+ if (!service) {
+ Send(new BluetoothMsg_GetCharacteristicError(
+ thread_id, request_id, BluetoothError::NETWORK_ERROR));
+ return;
+ }
+
+ for (BluetoothGattCharacteristic* characteristic :
+ service->GetCharacteristics()) {
+ if (characteristic->GetUUID().canonical_value() == characteristic_uuid) {
+ // TODO(ortuno): Use generated instance ID instead.
+ // https://crbug.com/495379
+ Send(new BluetoothMsg_GetCharacteristicSuccess(
+ thread_id, request_id, characteristic->GetIdentifier()));
+ return;
+ }
+ }
+ Send(new BluetoothMsg_GetCharacteristicError(thread_id, request_id,
+ BluetoothError::NOT_FOUND));
+}
+
void BluetoothDispatcherHost::OnDiscoverySessionStarted(
int thread_id,
int request_id,
@@ -253,8 +309,19 @@ void BluetoothDispatcherHost::OnServicesDiscovered(
}
for (BluetoothGattService* service : device->GetGattServices()) {
if (service->GetUUID().canonical_value() == service_uuid) {
+ // TODO(ortuno): Use generated instance ID instead.
+ // https://crbug.com/495379
+ const std::string& service_identifier = service->GetIdentifier();
+ auto insert_result = service_to_device_.insert(
+ make_pair(service_identifier, device_instance_id));
+
+ // If the service existed already check that device_instance_id is the
+ // same.
+ if (!insert_result.second)
+ DCHECK(insert_result.first->second == device_instance_id);
+
Send(new BluetoothMsg_GetPrimaryServiceSuccess(thread_id, request_id,
- service->GetIdentifier()));
+ service_identifier));
return;
}
}
diff --git a/content/browser/bluetooth/bluetooth_dispatcher_host.h b/content/browser/bluetooth/bluetooth_dispatcher_host.h
index bd21686..fff3671 100644
--- a/content/browser/bluetooth/bluetooth_dispatcher_host.h
+++ b/content/browser/bluetooth/bluetooth_dispatcher_host.h
@@ -57,6 +57,10 @@ class CONTENT_EXPORT BluetoothDispatcherHost final
int request_id,
const std::string& device_instance_id,
const std::string& service_uuid);
+ void OnGetCharacteristic(int thread_id,
+ int request_id,
+ const std::string& service_instance_id,
+ const std::string& characteristic_uuid);
// Callbacks for BluetoothAdapter::StartDiscoverySession.
void OnDiscoverySessionStarted(
@@ -95,6 +99,10 @@ class CONTENT_EXPORT BluetoothDispatcherHost final
const std::string& device_instance_id,
const std::string& service_uuid);
+ // Maps to get the object's parent based on it's instanceID
+ // Map of service_instance_id to device_instance_id.
+ std::map<std::string, std::string> service_to_device_;
+
// Defines how long to scan for and how long to discover services for.
int current_delay_time_;
diff --git a/content/child/bluetooth/bluetooth_dispatcher.cc b/content/child/bluetooth/bluetooth_dispatcher.cc
index 40e5bef..7435825 100644
--- a/content/child/bluetooth/bluetooth_dispatcher.cc
+++ b/content/child/bluetooth/bluetooth_dispatcher.cc
@@ -12,12 +12,14 @@
#include "content/common/bluetooth/bluetooth_messages.h"
#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothDevice.h"
#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothError.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTCharacteristic.h"
#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTRemoteServer.h"
#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTService.h"
using blink::WebBluetoothConnectGATTCallbacks;
using blink::WebBluetoothDevice;
using blink::WebBluetoothError;
+using blink::WebBluetoothGATTCharacteristic;
using blink::WebBluetoothGATTRemoteServer;
using blink::WebBluetoothGATTService;
using blink::WebBluetoothRequestDeviceCallbacks;
@@ -39,6 +41,21 @@ struct BluetoothPrimaryServiceRequest {
scoped_ptr<blink::WebBluetoothGetPrimaryServiceCallbacks> callbacks;
};
+struct BluetoothCharacteristicRequest {
+ BluetoothCharacteristicRequest(
+ blink::WebString service_instance_id,
+ blink::WebString characteristic_uuid,
+ blink::WebBluetoothGetCharacteristicCallbacks* callbacks)
+ : service_instance_id(service_instance_id),
+ characteristic_uuid(characteristic_uuid),
+ callbacks(callbacks) {}
+ ~BluetoothCharacteristicRequest() {}
+
+ blink::WebString service_instance_id;
+ blink::WebString characteristic_uuid;
+ scoped_ptr<blink::WebBluetoothGetCharacteristicCallbacks> callbacks;
+};
+
namespace content {
namespace {
@@ -123,6 +140,10 @@ void BluetoothDispatcher::OnMessageReceived(const IPC::Message& msg) {
OnGetPrimaryServiceSuccess);
IPC_MESSAGE_HANDLER(BluetoothMsg_GetPrimaryServiceError,
OnGetPrimaryServiceError);
+ IPC_MESSAGE_HANDLER(BluetoothMsg_GetCharacteristicSuccess,
+ OnGetCharacteristicSuccess);
+ IPC_MESSAGE_HANDLER(BluetoothMsg_GetCharacteristicError,
+ OnGetCharacteristicError);
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
DCHECK(handled) << "Unhandled message:" << msg.type();
@@ -154,6 +175,18 @@ void BluetoothDispatcher::getPrimaryService(
service_uuid.utf8()));
}
+void BluetoothDispatcher::getCharacteristic(
+ const blink::WebString& service_instance_id,
+ const blink::WebString& characteristic_uuid,
+ blink::WebBluetoothGetCharacteristicCallbacks* callbacks) {
+ int request_id =
+ pending_characteristic_requests_.Add(new BluetoothCharacteristicRequest(
+ service_instance_id, characteristic_uuid, callbacks));
+ Send(new BluetoothHostMsg_GetCharacteristic(CurrentWorkerId(), request_id,
+ service_instance_id.utf8(),
+ characteristic_uuid.utf8()));
+}
+
void BluetoothDispatcher::OnWorkerRunLoopStopped() {
delete this;
}
@@ -248,4 +281,40 @@ void BluetoothDispatcher::OnGetPrimaryServiceError(int thread_id,
pending_primary_service_requests_.Remove(request_id);
}
+void BluetoothDispatcher::OnGetCharacteristicSuccess(
+ int thread_id,
+ int request_id,
+ const std::string& characteristic_instance_id) {
+ DCHECK(pending_characteristic_requests_.Lookup(request_id)) << request_id;
+
+ BluetoothCharacteristicRequest* request =
+ pending_characteristic_requests_.Lookup(request_id);
+ request->callbacks->onSuccess(new WebBluetoothGATTCharacteristic(
+ WebString::fromUTF8(characteristic_instance_id),
+ request->service_instance_id, request->characteristic_uuid));
+
+ pending_characteristic_requests_.Remove(request_id);
+}
+
+void BluetoothDispatcher::OnGetCharacteristicError(int thread_id,
+ int request_id,
+ BluetoothError error_type) {
+ DCHECK(pending_characteristic_requests_.Lookup(request_id)) << request_id;
+
+ // Since we couldn't find the characteristic return null. See Step 3 of
+ // getCharacteristic algorithm:
+ // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothgattservice-getcharacteristic
+ if (error_type == BluetoothError::NOT_FOUND) {
+ pending_characteristic_requests_.Lookup(request_id)
+ ->callbacks->onSuccess(nullptr);
+ } else {
+ pending_characteristic_requests_.Lookup(request_id)
+ ->callbacks->onError(new WebBluetoothError(
+ // TODO(ortuno): Return more descriptive error messages.
+ // http://crbug.com/490419
+ WebBluetoothErrorFromBluetoothError(error_type), ""));
+ }
+ pending_characteristic_requests_.Remove(request_id);
+}
+
} // namespace content
diff --git a/content/child/bluetooth/bluetooth_dispatcher.h b/content/child/bluetooth/bluetooth_dispatcher.h
index 94a20af..1e1e9e4 100644
--- a/content/child/bluetooth/bluetooth_dispatcher.h
+++ b/content/child/bluetooth/bluetooth_dispatcher.h
@@ -21,6 +21,7 @@ namespace IPC {
class Message;
}
+struct BluetoothCharacteristicRequest;
struct BluetoothPrimaryServiceRequest;
namespace content {
@@ -57,6 +58,11 @@ class BluetoothDispatcher : public WorkerTaskRunner::Observer {
const blink::WebString& service_uuid,
blink::WebBluetoothGetPrimaryServiceCallbacks* callbacks);
+ void getCharacteristic(
+ const blink::WebString& service_instance_id,
+ const blink::WebString& characteristic_uuid,
+ blink::WebBluetoothGetCharacteristicCallbacks* callbacks);
+
// WorkerTaskRunner::Observer implementation.
void OnWorkerRunLoopStopped() override;
@@ -82,6 +88,13 @@ class BluetoothDispatcher : public WorkerTaskRunner::Observer {
void OnGetPrimaryServiceError(int thread_id,
int request_id,
BluetoothError error_type);
+ void OnGetCharacteristicSuccess(
+ int thread_id,
+ int request_id,
+ const std::string& characteristic_instance_id);
+ void OnGetCharacteristicError(int thread_id,
+ int request_id,
+ BluetoothError error_type);
scoped_refptr<ThreadSafeSender> thread_safe_sender_;
@@ -97,6 +110,9 @@ class BluetoothDispatcher : public WorkerTaskRunner::Observer {
// Owns request objects.
IDMap<BluetoothPrimaryServiceRequest, IDMapOwnPointer>
pending_primary_service_requests_;
+ // Tracks requests to get a characteristic from a service.
+ IDMap<BluetoothCharacteristicRequest, IDMapOwnPointer>
+ pending_characteristic_requests_;
DISALLOW_COPY_AND_ASSIGN(BluetoothDispatcher);
};
diff --git a/content/child/bluetooth/web_bluetooth_impl.cc b/content/child/bluetooth/web_bluetooth_impl.cc
index 4264efd..02de755 100644
--- a/content/child/bluetooth/web_bluetooth_impl.cc
+++ b/content/child/bluetooth/web_bluetooth_impl.cc
@@ -34,6 +34,14 @@ void WebBluetoothImpl::getPrimaryService(
callbacks);
}
+void WebBluetoothImpl::getCharacteristic(
+ const blink::WebString& service_instance_id,
+ const blink::WebString& characteristic_uuid,
+ blink::WebBluetoothGetCharacteristicCallbacks* callbacks) {
+ GetDispatcher()->getCharacteristic(service_instance_id, characteristic_uuid,
+ callbacks);
+}
+
BluetoothDispatcher* WebBluetoothImpl::GetDispatcher() {
return BluetoothDispatcher::GetOrCreateThreadSpecificInstance(
thread_safe_sender_.get());
diff --git a/content/child/bluetooth/web_bluetooth_impl.h b/content/child/bluetooth/web_bluetooth_impl.h
index 3687f47..89628d2 100644
--- a/content/child/bluetooth/web_bluetooth_impl.h
+++ b/content/child/bluetooth/web_bluetooth_impl.h
@@ -28,14 +28,16 @@ class CONTENT_EXPORT WebBluetoothImpl
// blink::WebBluetooth interface:
void requestDevice(
blink::WebBluetoothRequestDeviceCallbacks* callbacks) override;
-
void connectGATT(const blink::WebString& device_instance_id,
blink::WebBluetoothConnectGATTCallbacks* callbacks) override;
-
void getPrimaryService(
const blink::WebString& device_instance_id,
const blink::WebString& service_uuid,
blink::WebBluetoothGetPrimaryServiceCallbacks* callbacks) override;
+ void getCharacteristic(
+ const blink::WebString& service_instance_id,
+ const blink::WebString& characteristic_uuid,
+ blink::WebBluetoothGetCharacteristicCallbacks* callbacks) override;
private:
BluetoothDispatcher* GetDispatcher();
diff --git a/content/common/bluetooth/bluetooth_messages.h b/content/common/bluetooth/bluetooth_messages.h
index 1c9f1d8..935c8b9 100644
--- a/content/common/bluetooth/bluetooth_messages.h
+++ b/content/common/bluetooth/bluetooth_messages.h
@@ -141,6 +141,18 @@ IPC_MESSAGE_CONTROL3(BluetoothMsg_GetPrimaryServiceError,
int /* request_id */,
content::BluetoothError /* result */)
+// Informs the renderer that characteristic request |request_id| succeeded.
+IPC_MESSAGE_CONTROL3(BluetoothMsg_GetCharacteristicSuccess,
+ int /* thread_id */,
+ int /* request_id */,
+ std::string /* characteristic_instance_id */)
+
+// Informs the renderer that the characteristic request |request_id| failed.
+IPC_MESSAGE_CONTROL3(BluetoothMsg_GetCharacteristicError,
+ int /* thread_id */,
+ int /* request_id */,
+ content::BluetoothError /* result */)
+
// Messages sent from the renderer to the browser.
// Requests a bluetooth device from the browser.
@@ -166,3 +178,10 @@ IPC_MESSAGE_CONTROL4(BluetoothHostMsg_GetPrimaryService,
int /* request_id */,
std::string /* device_instance_id */,
std::string /* service_uuid */)
+
+// Gets a GATT Characteristic within a GATT Service.
+IPC_MESSAGE_CONTROL4(BluetoothHostMsg_GetCharacteristic,
+ int /* thread_id */,
+ int /* request_id */,
+ std::string /* service_instance_id */,
+ std::string /* characteristic_uuid */)
diff --git a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc
index 3c3dda0..7f3563f 100644
--- a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc
+++ b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc
@@ -23,6 +23,7 @@ using device::BluetoothUUID;
using device::MockBluetoothAdapter;
using device::MockBluetoothDevice;
using device::MockBluetoothDiscoverySession;
+using device::MockBluetoothGattCharacteristic;
using device::MockBluetoothGattConnection;
using device::MockBluetoothGattService;
using testing::Between;
@@ -64,7 +65,8 @@ ACTION_P(GetMockDevice, adapter) {
}
return NULL;
}
-}
+
+} // namespace
namespace content {
@@ -174,10 +176,18 @@ LayoutTestBluetoothAdapterProvider::GetEmptyDevice(
list.push_back(BluetoothUUID("1801"));
ON_CALL(*empty_device, GetUUIDs()).WillByDefault(Return(list));
- empty_device->AddMockService(
- GetMockService(empty_device.get(), "1800" /* Generic Access */));
- empty_device->AddMockService(
- GetMockService(empty_device.get(), "1801" /* Generic Attribute */));
+ scoped_ptr<NiceMock<MockBluetoothGattService>> generic_access(
+ GetGattService(empty_device.get(), "1800" /* Generic Access */));
+ generic_access->AddMockCharacteristic(
+ GetGattCharacteristic(generic_access.get(), "2A00" /* Device Name */));
+
+ scoped_ptr<NiceMock<MockBluetoothGattService>> generic_attribute(
+ GetGattService(empty_device.get(), "1801" /* Generic Attribute */));
+ generic_attribute->AddMockCharacteristic(GetGattCharacteristic(
+ generic_attribute.get(), "2A05" /* Service Changed */));
+
+ empty_device->AddMockService(generic_access.Pass());
+ empty_device->AddMockService(generic_attribute.Pass());
// Using Invoke allows the device returned from this method to be futher
// modified and have more services added to it. The call to ::GetGattServices
@@ -187,6 +197,13 @@ LayoutTestBluetoothAdapterProvider::GetEmptyDevice(
.WillByDefault(
Invoke(empty_device.get(), &MockBluetoothDevice::GetMockServices));
+ // The call to BluetoothDevice::GetGattService will invoke ::GetMockService
+ // which returns a service matching the identifier provided if the service
+ // was added to the mock.
+ ON_CALL(*empty_device, GetGattService(_))
+ .WillByDefault(
+ Invoke(empty_device.get(), &MockBluetoothDevice::GetMockService));
+
return empty_device.Pass();
}
@@ -223,11 +240,27 @@ LayoutTestBluetoothAdapterProvider::GetUnconnectableDevice(
// static
scoped_ptr<NiceMock<MockBluetoothGattService>>
-LayoutTestBluetoothAdapterProvider::GetMockService(MockBluetoothDevice* device,
+LayoutTestBluetoothAdapterProvider::GetGattService(MockBluetoothDevice* device,
const std::string& uuid) {
- return make_scoped_ptr(new NiceMock<MockBluetoothGattService>(
- device, uuid /* identifier */, BluetoothUUID(uuid), true /* is_primary */,
- false /* is_local */));
+ scoped_ptr<NiceMock<MockBluetoothGattService>> service(
+ new NiceMock<MockBluetoothGattService>(
+ device, uuid /* identifier */, BluetoothUUID(uuid),
+ true /* is_primary */, false /* is_local */));
+
+ ON_CALL(*service, GetCharacteristics())
+ .WillByDefault(Invoke(service.get(),
+ &MockBluetoothGattService::GetMockCharacteristics));
+ return service.Pass();
+}
+
+// static
+scoped_ptr<NiceMock<MockBluetoothGattCharacteristic>>
+LayoutTestBluetoothAdapterProvider::GetGattCharacteristic(
+ MockBluetoothGattService* service,
+ const std::string& uuid) {
+ return make_scoped_ptr(new NiceMock<MockBluetoothGattCharacteristic>(
+ service, uuid /* identifier */, BluetoothUUID(uuid), false /* is_local */,
+ NULL /* properties */, NULL /* permissions */));
}
} // namespace content
diff --git a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h
index fc8efb9..00580e4 100644
--- a/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h
+++ b/content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h
@@ -10,7 +10,9 @@
#include "device/bluetooth/test/mock_bluetooth_adapter.h"
#include "device/bluetooth/test/mock_bluetooth_device.h"
#include "device/bluetooth/test/mock_bluetooth_discovery_session.h"
+#include "device/bluetooth/test/mock_bluetooth_gatt_characteristic.h"
#include "device/bluetooth/test/mock_bluetooth_gatt_service.h"
+
namespace content {
// Implements fake adapters with named mock data set for use in tests as a
@@ -71,7 +73,8 @@ class LayoutTestBluetoothAdapterProvider {
// - |IsPaired| returns true.
// - |GetUUIDs| returns a list with two UUIDs: "1800" and "1801".
// - |GetGattServices| returns a list with two services "Generic Access" and
- // "Generic Attribute".
+ // "Generic Attribute". "Generic Access" has a "Device Name" characteristic
+ // and "Generic Attribute" has a "Service Changed" characteristic.
static scoped_ptr<testing::NiceMock<device::MockBluetoothDevice>>
GetEmptyDevice(device::MockBluetoothAdapter* adapter);
@@ -96,7 +99,18 @@ class LayoutTestBluetoothAdapterProvider {
// - |IsPrimary| returns true.
// - |GetDevice| returns |device|.
static scoped_ptr<testing::NiceMock<device::MockBluetoothGattService>>
- GetMockService(device::MockBluetoothDevice* device, const std::string& uuid);
+ GetGattService(device::MockBluetoothDevice* device, const std::string& uuid);
+
+ // Returns a fake BluetoothGattCharacteristic with the following
+ // characteristics:
+ // - |GetIdentifier| returns |uuid|.
+ // - |GetUUID| returns BluetoothUUID(|uuid|).
+ // - |IsLocal| returns false.
+ // - |GetService| returns |service|.
+ // - |IsNotifying| returns false.
+ static scoped_ptr<testing::NiceMock<device::MockBluetoothGattCharacteristic>>
+ GetGattCharacteristic(device::MockBluetoothGattService* service,
+ const std::string& uuid);
};
} // namespace content
diff --git a/device/bluetooth/test/mock_bluetooth_adapter.h b/device/bluetooth/test/mock_bluetooth_adapter.h
index cd8b8a1..547a9cf 100644
--- a/device/bluetooth/test/mock_bluetooth_adapter.h
+++ b/device/bluetooth/test/mock_bluetooth_adapter.h
@@ -102,7 +102,7 @@ class MockBluetoothAdapter : public BluetoothAdapter {
const ErrorCallback& error_callback);
// BluetoothAdapter is supposed to manage the lifetime of BluetoothDevices.
- // This methods takes ownership of the BluetoothDevices. This is only for
+ // This method takes ownership of the MockBluetoothDevice. This is only for
// convenience as far testing is concerned and it's possible to write test
// cases without using these functions.
void AddMockDevice(scoped_ptr<MockBluetoothDevice> mock_device);
diff --git a/device/bluetooth/test/mock_bluetooth_device.cc b/device/bluetooth/test/mock_bluetooth_device.cc
index 928d98c..19b67a3 100644
--- a/device/bluetooth/test/mock_bluetooth_device.cc
+++ b/device/bluetooth/test/mock_bluetooth_device.cc
@@ -71,4 +71,13 @@ std::vector<BluetoothGattService*> MockBluetoothDevice::GetMockServices()
return services;
}
+BluetoothGattService* MockBluetoothDevice::GetMockService(
+ const std::string& identifier) const {
+ for (BluetoothGattService* service : mock_services_) {
+ if (service->GetIdentifier() == identifier)
+ return service;
+ }
+ return nullptr;
+}
+
} // namespace device
diff --git a/device/bluetooth/test/mock_bluetooth_device.h b/device/bluetooth/test/mock_bluetooth_device.h
index 2d16e46..b5948f6 100644
--- a/device/bluetooth/test/mock_bluetooth_device.h
+++ b/device/bluetooth/test/mock_bluetooth_device.h
@@ -83,15 +83,16 @@ class MockBluetoothDevice : public BluetoothDevice {
MOCK_CONST_METHOD1(GetGattService, BluetoothGattService*(const std::string&));
// BluetoothDevice manages the lifetime of its BluetoothGATTServices.
- // This methods takes ownership of the BluetoothGATTServices. This is only for
- // convenience as far as testing is concerned, and it's possible to write test
- // cases without using these functions.
+ // This method takes ownership of the MockBluetoothGATTServices. This is only
+ // for convenience as far as testing is concerned, and it's possible to write
+ // test cases without using these functions.
// Example:
// ON_CALL(*mock_device, GetGattServices))
// .WillByDefault(Invoke(*mock_device,
// &MockBluetoothDevice::GetMockServices));
void AddMockService(scoped_ptr<MockBluetoothGattService> mock_device);
std::vector<BluetoothGattService*> GetMockServices() const;
+ BluetoothGattService* GetMockService(const std::string& identifier) const;
private:
uint32 bluetooth_class_;
diff --git a/device/bluetooth/test/mock_bluetooth_gatt_service.cc b/device/bluetooth/test/mock_bluetooth_gatt_service.cc
index 37392a6..faba596 100644
--- a/device/bluetooth/test/mock_bluetooth_gatt_service.cc
+++ b/device/bluetooth/test/mock_bluetooth_gatt_service.cc
@@ -33,4 +33,18 @@ MockBluetoothGattService::MockBluetoothGattService(
MockBluetoothGattService::~MockBluetoothGattService() {
}
+void MockBluetoothGattService::AddMockCharacteristic(
+ scoped_ptr<MockBluetoothGattCharacteristic> mock_characteristic) {
+ mock_characteristics_.push_back(mock_characteristic.Pass());
+}
+
+std::vector<BluetoothGattCharacteristic*>
+MockBluetoothGattService::GetMockCharacteristics() const {
+ std::vector<BluetoothGattCharacteristic*> characteristics;
+ for (BluetoothGattCharacteristic* characteristic : mock_characteristics_) {
+ characteristics.push_back(characteristic);
+ }
+ return characteristics;
+}
+
} // namespace device
diff --git a/device/bluetooth/test/mock_bluetooth_gatt_service.h b/device/bluetooth/test/mock_bluetooth_gatt_service.h
index b03adfa..1ba3dea 100644
--- a/device/bluetooth/test/mock_bluetooth_gatt_service.h
+++ b/device/bluetooth/test/mock_bluetooth_gatt_service.h
@@ -8,8 +8,10 @@
#include <string>
#include <vector>
+#include "base/memory/scoped_vector.h"
#include "device/bluetooth/bluetooth_gatt_service.h"
#include "device/bluetooth/bluetooth_uuid.h"
+#include "device/bluetooth/test/mock_bluetooth_gatt_characteristic.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace device {
@@ -41,7 +43,23 @@ class MockBluetoothGattService : public BluetoothGattService {
MOCK_METHOD2(Register, void(const base::Closure&, const ErrorCallback&));
MOCK_METHOD2(Unregister, void(const base::Closure&, const ErrorCallback&));
+ // BluetoothGattService manages the lifetime of its
+ // BluetoothGATTCharacteristics.
+ // This method takes ownership of the MockBluetoothGATTCharacteristics. This
+ // is only for convenience as far as testing is concerned, and it's possible
+ // to write test cases without using these functions.
+ // Example:
+ // ON_CALL(*mock_service, GetCharacteristics))
+ // .WillByDefault(Invoke(
+ // *mock_service,
+ // &MockBluetoothGattService::GetMockCharacteristics));
+ void AddMockCharacteristic(
+ scoped_ptr<MockBluetoothGattCharacteristic> mock_characteristic);
+ std::vector<BluetoothGattCharacteristic*> GetMockCharacteristics() const;
+
private:
+ ScopedVector<MockBluetoothGattCharacteristic> mock_characteristics_;
+
DISALLOW_COPY_AND_ASSIGN(MockBluetoothGattService);
};
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 1cb1984..d75f373 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -49724,6 +49724,7 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries.
<int value="80" label="SWDH_GET_REGISTRATIONS_NO_HOST"/>
<int value="81" label="SWDH_GET_REGISTRATIONS_INVALID_ORIGIN"/>
<int value="82" label="ARH_UNAUTHORIZED_URL"/>
+ <int value="83" label="BDH_INVALID_SERVICE_ID"/>
</enum>
<enum name="BadMessageReasonExtensions" type="int">