Record MTU discovery packets in net-internals log.
[chromium-blink-merge.git] / content / child / bluetooth / bluetooth_dispatcher.cc
blobbf425a7cbe31b66253c81b2c8eadb2b1a019018e
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/child/bluetooth/bluetooth_dispatcher.h"
7 #include "base/lazy_instance.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "content/child/thread_safe_sender.h"
12 #include "content/common/bluetooth/bluetooth_messages.h"
13 #include "device/bluetooth/bluetooth_uuid.h"
14 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothDevice.h"
15 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothError.h"
16 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothErrorMessage.h"
17 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTCharacteristic.h"
18 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTRemoteServer.h"
19 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTService.h"
20 #include "third_party/WebKit/public/platform/modules/bluetooth/WebRequestDeviceOptions.h"
22 using blink::WebBluetoothConnectGATTCallbacks;
23 using blink::WebBluetoothDevice;
24 using blink::WebBluetoothError;
25 using blink::WebBluetoothErrorMessage;
26 using blink::WebBluetoothGATTCharacteristic;
27 using blink::WebBluetoothGATTRemoteServer;
28 using blink::WebBluetoothGATTService;
29 using blink::WebBluetoothReadValueCallbacks;
30 using blink::WebBluetoothRequestDeviceCallbacks;
31 using blink::WebBluetoothScanFilter;
32 using blink::WebRequestDeviceOptions;
33 using blink::WebString;
34 using blink::WebVector;
36 struct BluetoothPrimaryServiceRequest {
37 BluetoothPrimaryServiceRequest(
38 blink::WebString device_instance_id,
39 blink::WebString service_uuid,
40 blink::WebBluetoothGetPrimaryServiceCallbacks* callbacks)
41 : device_instance_id(device_instance_id),
42 service_uuid(service_uuid),
43 callbacks(callbacks) {}
44 ~BluetoothPrimaryServiceRequest() {}
46 blink::WebString device_instance_id;
47 blink::WebString service_uuid;
48 scoped_ptr<blink::WebBluetoothGetPrimaryServiceCallbacks> callbacks;
51 struct BluetoothCharacteristicRequest {
52 BluetoothCharacteristicRequest(
53 blink::WebString service_instance_id,
54 blink::WebString characteristic_uuid,
55 blink::WebBluetoothGetCharacteristicCallbacks* callbacks)
56 : service_instance_id(service_instance_id),
57 characteristic_uuid(characteristic_uuid),
58 callbacks(callbacks) {}
59 ~BluetoothCharacteristicRequest() {}
61 blink::WebString service_instance_id;
62 blink::WebString characteristic_uuid;
63 scoped_ptr<blink::WebBluetoothGetCharacteristicCallbacks> callbacks;
66 namespace content {
68 namespace {
70 base::LazyInstance<base::ThreadLocalPointer<BluetoothDispatcher>>::Leaky
71 g_dispatcher_tls = LAZY_INSTANCE_INITIALIZER;
73 BluetoothDispatcher* const kHasBeenDeleted =
74 reinterpret_cast<BluetoothDispatcher*>(0x1);
76 int CurrentWorkerId() {
77 return WorkerTaskRunner::Instance()->CurrentWorkerId();
80 WebBluetoothDevice::VendorIDSource GetWebVendorIdSource(
81 device::BluetoothDevice::VendorIDSource vendor_id_source) {
82 switch (vendor_id_source) {
83 case device::BluetoothDevice::VENDOR_ID_UNKNOWN:
84 return WebBluetoothDevice::VendorIDSource::Unknown;
85 case device::BluetoothDevice::VENDOR_ID_BLUETOOTH:
86 return WebBluetoothDevice::VendorIDSource::Bluetooth;
87 case device::BluetoothDevice::VENDOR_ID_USB:
88 return WebBluetoothDevice::VendorIDSource::USB;
90 NOTREACHED();
91 return WebBluetoothDevice::VendorIDSource::Unknown;
94 } // namespace
96 BluetoothDispatcher::BluetoothDispatcher(ThreadSafeSender* sender)
97 : thread_safe_sender_(sender) {
98 g_dispatcher_tls.Pointer()->Set(this);
101 BluetoothDispatcher::~BluetoothDispatcher() {
102 g_dispatcher_tls.Pointer()->Set(kHasBeenDeleted);
105 BluetoothDispatcher* BluetoothDispatcher::GetOrCreateThreadSpecificInstance(
106 ThreadSafeSender* thread_safe_sender) {
107 if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) {
108 NOTREACHED() << "Re-instantiating TLS BluetoothDispatcher.";
109 g_dispatcher_tls.Pointer()->Set(NULL);
111 if (g_dispatcher_tls.Pointer()->Get())
112 return g_dispatcher_tls.Pointer()->Get();
114 BluetoothDispatcher* dispatcher = new BluetoothDispatcher(thread_safe_sender);
115 if (CurrentWorkerId())
116 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher);
117 return dispatcher;
120 bool BluetoothDispatcher::Send(IPC::Message* msg) {
121 return thread_safe_sender_->Send(msg);
124 void BluetoothDispatcher::OnMessageReceived(const IPC::Message& msg) {
125 bool handled = true;
126 IPC_BEGIN_MESSAGE_MAP(BluetoothDispatcher, msg)
127 IPC_MESSAGE_HANDLER(BluetoothMsg_RequestDeviceSuccess,
128 OnRequestDeviceSuccess);
129 IPC_MESSAGE_HANDLER(BluetoothMsg_RequestDeviceError, OnRequestDeviceError);
130 IPC_MESSAGE_HANDLER(BluetoothMsg_ConnectGATTSuccess, OnConnectGATTSuccess);
131 IPC_MESSAGE_HANDLER(BluetoothMsg_ConnectGATTError, OnConnectGATTError);
132 IPC_MESSAGE_HANDLER(BluetoothMsg_GetPrimaryServiceSuccess,
133 OnGetPrimaryServiceSuccess);
134 IPC_MESSAGE_HANDLER(BluetoothMsg_GetPrimaryServiceError,
135 OnGetPrimaryServiceError);
136 IPC_MESSAGE_HANDLER(BluetoothMsg_GetCharacteristicSuccess,
137 OnGetCharacteristicSuccess);
138 IPC_MESSAGE_HANDLER(BluetoothMsg_GetCharacteristicError,
139 OnGetCharacteristicError);
140 IPC_MESSAGE_HANDLER(BluetoothMsg_ReadCharacteristicValueSuccess,
141 OnReadValueSuccess);
142 IPC_MESSAGE_HANDLER(BluetoothMsg_ReadCharacteristicValueError,
143 OnReadValueError);
144 IPC_MESSAGE_HANDLER(BluetoothMsg_WriteCharacteristicValueSuccess,
145 OnWriteValueSuccess);
146 IPC_MESSAGE_HANDLER(BluetoothMsg_WriteCharacteristicValueError,
147 OnWriteValueError);
148 IPC_MESSAGE_UNHANDLED(handled = false)
149 IPC_END_MESSAGE_MAP()
150 DCHECK(handled) << "Unhandled message:" << msg.type();
153 void BluetoothDispatcher::requestDevice(
154 const WebRequestDeviceOptions& options,
155 blink::WebBluetoothRequestDeviceCallbacks* callbacks) {
156 int request_id = pending_requests_.Add(callbacks);
158 // Convert |options| to its IPC form.
159 std::vector<content::BluetoothScanFilter> filters(options.filters.size());
160 for (size_t i = 0; i < options.filters.size(); ++i) {
161 const WebBluetoothScanFilter& web_filter = options.filters[i];
162 BluetoothScanFilter& filter = filters[i];
163 filter.services.reserve(web_filter.services.size());
164 for (const WebString& service : web_filter.services) {
165 filter.services.push_back(device::BluetoothUUID(service.utf8()));
168 std::vector<device::BluetoothUUID> optional_services;
169 optional_services.reserve(options.optionalServices.size());
170 for (const WebString& optional_service : options.optionalServices) {
171 optional_services.push_back(device::BluetoothUUID(optional_service.utf8()));
174 Send(new BluetoothHostMsg_RequestDevice(CurrentWorkerId(), request_id,
175 filters, optional_services));
178 void BluetoothDispatcher::connectGATT(
179 const blink::WebString& device_instance_id,
180 blink::WebBluetoothConnectGATTCallbacks* callbacks) {
181 int request_id = pending_connect_requests_.Add(callbacks);
182 Send(new BluetoothHostMsg_ConnectGATT(CurrentWorkerId(), request_id,
183 device_instance_id.utf8()));
186 void BluetoothDispatcher::getPrimaryService(
187 const blink::WebString& device_instance_id,
188 const blink::WebString& service_uuid,
189 blink::WebBluetoothGetPrimaryServiceCallbacks* callbacks) {
190 int request_id =
191 pending_primary_service_requests_.Add(new BluetoothPrimaryServiceRequest(
192 device_instance_id, service_uuid, callbacks));
193 Send(new BluetoothHostMsg_GetPrimaryService(CurrentWorkerId(), request_id,
194 device_instance_id.utf8(),
195 service_uuid.utf8()));
198 void BluetoothDispatcher::getCharacteristic(
199 const blink::WebString& service_instance_id,
200 const blink::WebString& characteristic_uuid,
201 blink::WebBluetoothGetCharacteristicCallbacks* callbacks) {
202 int request_id =
203 pending_characteristic_requests_.Add(new BluetoothCharacteristicRequest(
204 service_instance_id, characteristic_uuid, callbacks));
205 Send(new BluetoothHostMsg_GetCharacteristic(CurrentWorkerId(), request_id,
206 service_instance_id.utf8(),
207 characteristic_uuid.utf8()));
210 void BluetoothDispatcher::readValue(
211 const blink::WebString& characteristic_instance_id,
212 blink::WebBluetoothReadValueCallbacks* callbacks) {
213 int request_id = pending_read_value_requests_.Add(callbacks);
214 Send(new BluetoothHostMsg_ReadValue(CurrentWorkerId(), request_id,
215 characteristic_instance_id.utf8()));
218 void BluetoothDispatcher::writeValue(
219 const blink::WebString& characteristic_instance_id,
220 const std::vector<uint8_t>& value,
221 blink::WebBluetoothWriteValueCallbacks* callbacks) {
222 int request_id = pending_write_value_requests_.Add(callbacks);
224 Send(new BluetoothHostMsg_WriteValue(
225 CurrentWorkerId(), request_id, characteristic_instance_id.utf8(), value));
228 void BluetoothDispatcher::OnWorkerRunLoopStopped() {
229 delete this;
232 void BluetoothDispatcher::OnRequestDeviceSuccess(
233 int thread_id,
234 int request_id,
235 const BluetoothDevice& device) {
236 DCHECK(pending_requests_.Lookup(request_id)) << request_id;
238 WebVector<WebString> uuids(device.uuids.size());
239 for (size_t i = 0; i < device.uuids.size(); ++i)
240 uuids[i] = WebString::fromUTF8(device.uuids[i].c_str());
242 pending_requests_.Lookup(request_id)
243 ->onSuccess(new WebBluetoothDevice(
244 WebString::fromUTF8(device.instance_id), WebString(device.name),
245 device.device_class, GetWebVendorIdSource(device.vendor_id_source),
246 device.vendor_id, device.product_id, device.product_version,
247 device.paired, uuids));
248 pending_requests_.Remove(request_id);
251 void BluetoothDispatcher::OnRequestDeviceError(int thread_id,
252 int request_id,
253 WebBluetoothErrorMessage error) {
254 DCHECK(pending_requests_.Lookup(request_id)) << request_id;
255 pending_requests_.Lookup(request_id)->onError(new WebBluetoothError(error));
256 pending_requests_.Remove(request_id);
259 void BluetoothDispatcher::OnConnectGATTSuccess(
260 int thread_id,
261 int request_id,
262 const std::string& device_instance_id) {
263 DCHECK(pending_connect_requests_.Lookup(request_id)) << request_id;
264 pending_connect_requests_.Lookup(request_id)
265 ->onSuccess(new WebBluetoothGATTRemoteServer(
266 WebString::fromUTF8(device_instance_id), true /* connected */));
267 pending_connect_requests_.Remove(request_id);
270 void BluetoothDispatcher::OnConnectGATTError(int thread_id,
271 int request_id,
272 WebBluetoothErrorMessage error) {
273 DCHECK(pending_connect_requests_.Lookup(request_id)) << request_id;
274 pending_connect_requests_.Lookup(request_id)
275 ->onError(new WebBluetoothError(error));
276 pending_connect_requests_.Remove(request_id);
279 void BluetoothDispatcher::OnGetPrimaryServiceSuccess(
280 int thread_id,
281 int request_id,
282 const std::string& service_instance_id) {
283 DCHECK(pending_primary_service_requests_.Lookup(request_id)) << request_id;
284 BluetoothPrimaryServiceRequest* request =
285 pending_primary_service_requests_.Lookup(request_id);
286 request->callbacks->onSuccess(new WebBluetoothGATTService(
287 WebString::fromUTF8(service_instance_id), request->service_uuid,
288 true /* isPrimary */, request->device_instance_id));
289 pending_primary_service_requests_.Remove(request_id);
292 void BluetoothDispatcher::OnGetPrimaryServiceError(
293 int thread_id,
294 int request_id,
295 WebBluetoothErrorMessage error) {
296 DCHECK(pending_primary_service_requests_.Lookup(request_id)) << request_id;
298 // Since we couldn't find the service return null. See Step 3 of
299 // getPrimaryService algorithm:
300 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothgattremoteserver-getprimaryservice
301 if (error == WebBluetoothErrorMessage::ServiceNotFound) {
302 pending_primary_service_requests_.Lookup(request_id)
303 ->callbacks->onSuccess(nullptr);
304 pending_primary_service_requests_.Remove(request_id);
305 return;
308 pending_primary_service_requests_.Lookup(request_id)
309 ->callbacks->onError(new WebBluetoothError(error));
310 pending_primary_service_requests_.Remove(request_id);
313 void BluetoothDispatcher::OnGetCharacteristicSuccess(
314 int thread_id,
315 int request_id,
316 const std::string& characteristic_instance_id) {
317 DCHECK(pending_characteristic_requests_.Lookup(request_id)) << request_id;
319 BluetoothCharacteristicRequest* request =
320 pending_characteristic_requests_.Lookup(request_id);
321 request->callbacks->onSuccess(new WebBluetoothGATTCharacteristic(
322 WebString::fromUTF8(characteristic_instance_id),
323 request->service_instance_id, request->characteristic_uuid));
325 pending_characteristic_requests_.Remove(request_id);
328 void BluetoothDispatcher::OnGetCharacteristicError(
329 int thread_id,
330 int request_id,
331 WebBluetoothErrorMessage error) {
332 DCHECK(pending_characteristic_requests_.Lookup(request_id)) << request_id;
334 // Since we couldn't find the characteristic return null. See Step 3 of
335 // getCharacteristic algorithm:
336 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothgattservice-getcharacteristic
337 if (error == WebBluetoothErrorMessage::CharacteristicNotFound) {
338 pending_characteristic_requests_.Lookup(request_id)
339 ->callbacks->onSuccess(nullptr);
340 } else {
341 pending_characteristic_requests_.Lookup(request_id)
342 ->callbacks->onError(new WebBluetoothError(error));
344 pending_characteristic_requests_.Remove(request_id);
347 void BluetoothDispatcher::OnReadValueSuccess(
348 int thread_id,
349 int request_id,
350 const std::vector<uint8_t>& value) {
351 DCHECK(pending_read_value_requests_.Lookup(request_id)) << request_id;
353 // WebArrayBuffer is not accessible from Source/modules so we pass a
354 // WebVector instead.
355 pending_read_value_requests_.Lookup(request_id)
356 ->onSuccess(new WebVector<uint8_t>(value));
358 pending_read_value_requests_.Remove(request_id);
361 void BluetoothDispatcher::OnReadValueError(int thread_id,
362 int request_id,
363 WebBluetoothErrorMessage error) {
364 DCHECK(pending_read_value_requests_.Lookup(request_id)) << request_id;
366 pending_read_value_requests_.Lookup(request_id)
367 ->onError(new WebBluetoothError(error));
369 pending_read_value_requests_.Remove(request_id);
372 void BluetoothDispatcher::OnWriteValueSuccess(int thread_id, int request_id) {
373 DCHECK(pending_write_value_requests_.Lookup(request_id)) << request_id;
375 pending_write_value_requests_.Lookup(request_id)->onSuccess();
377 pending_write_value_requests_.Remove(request_id);
380 void BluetoothDispatcher::OnWriteValueError(int thread_id,
381 int request_id,
382 WebBluetoothErrorMessage error) {
383 DCHECK(pending_write_value_requests_.Lookup(request_id)) << request_id;
385 pending_write_value_requests_.Lookup(request_id)
386 ->onError(new WebBluetoothError(error));
388 pending_write_value_requests_.Remove(request_id);
391 } // namespace content