OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "content/child/bluetooth/bluetooth_dispatcher.h" | |
6 | |
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/WebBluetoothDevic
e.h" | |
15 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothError
.h" | |
16 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTC
haracteristic.h" | |
17 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTR
emoteServer.h" | |
18 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTS
ervice.h" | |
19 #include "third_party/WebKit/public/platform/modules/bluetooth/WebRequestDeviceO
ptions.h" | |
20 | |
21 using blink::WebBluetoothConnectGATTCallbacks; | |
22 using blink::WebBluetoothDevice; | |
23 using blink::WebBluetoothError; | |
24 using blink::WebBluetoothGATTCharacteristic; | |
25 using blink::WebBluetoothGATTRemoteServer; | |
26 using blink::WebBluetoothGATTService; | |
27 using blink::WebBluetoothReadValueCallbacks; | |
28 using blink::WebBluetoothRequestDeviceCallbacks; | |
29 using blink::WebBluetoothScanFilter; | |
30 using blink::WebRequestDeviceOptions; | |
31 using blink::WebString; | |
32 using blink::WebVector; | |
33 | |
34 struct BluetoothPrimaryServiceRequest { | |
35 BluetoothPrimaryServiceRequest( | |
36 blink::WebString device_instance_id, | |
37 blink::WebString service_uuid, | |
38 blink::WebBluetoothGetPrimaryServiceCallbacks* callbacks) | |
39 : device_instance_id(device_instance_id), | |
40 service_uuid(service_uuid), | |
41 callbacks(callbacks) {} | |
42 ~BluetoothPrimaryServiceRequest() {} | |
43 | |
44 blink::WebString device_instance_id; | |
45 blink::WebString service_uuid; | |
46 scoped_ptr<blink::WebBluetoothGetPrimaryServiceCallbacks> callbacks; | |
47 }; | |
48 | |
49 struct BluetoothCharacteristicRequest { | |
50 BluetoothCharacteristicRequest( | |
51 blink::WebString service_instance_id, | |
52 blink::WebString characteristic_uuid, | |
53 blink::WebBluetoothGetCharacteristicCallbacks* callbacks) | |
54 : service_instance_id(service_instance_id), | |
55 characteristic_uuid(characteristic_uuid), | |
56 callbacks(callbacks) {} | |
57 ~BluetoothCharacteristicRequest() {} | |
58 | |
59 blink::WebString service_instance_id; | |
60 blink::WebString characteristic_uuid; | |
61 scoped_ptr<blink::WebBluetoothGetCharacteristicCallbacks> callbacks; | |
62 }; | |
63 | |
64 namespace content { | |
65 | |
66 namespace { | |
67 | |
68 base::LazyInstance<base::ThreadLocalPointer<BluetoothDispatcher>>::Leaky | |
69 g_dispatcher_tls = LAZY_INSTANCE_INITIALIZER; | |
70 | |
71 BluetoothDispatcher* const kHasBeenDeleted = | |
72 reinterpret_cast<BluetoothDispatcher*>(0x1); | |
73 | |
74 int CurrentWorkerId() { | |
75 return WorkerTaskRunner::Instance()->CurrentWorkerId(); | |
76 } | |
77 | |
78 WebBluetoothDevice::VendorIDSource GetWebVendorIdSource( | |
79 device::BluetoothDevice::VendorIDSource vendor_id_source) { | |
80 switch (vendor_id_source) { | |
81 case device::BluetoothDevice::VENDOR_ID_UNKNOWN: | |
82 return WebBluetoothDevice::VendorIDSource::Unknown; | |
83 case device::BluetoothDevice::VENDOR_ID_BLUETOOTH: | |
84 return WebBluetoothDevice::VendorIDSource::Bluetooth; | |
85 case device::BluetoothDevice::VENDOR_ID_USB: | |
86 return WebBluetoothDevice::VendorIDSource::USB; | |
87 } | |
88 NOTREACHED(); | |
89 return WebBluetoothDevice::VendorIDSource::Unknown; | |
90 } | |
91 | |
92 } // namespace | |
93 | |
94 BluetoothDispatcher::BluetoothDispatcher(ThreadSafeSender* sender) | |
95 : thread_safe_sender_(sender) { | |
96 g_dispatcher_tls.Pointer()->Set(this); | |
97 } | |
98 | |
99 BluetoothDispatcher::~BluetoothDispatcher() { | |
100 g_dispatcher_tls.Pointer()->Set(kHasBeenDeleted); | |
101 } | |
102 | |
103 BluetoothDispatcher* BluetoothDispatcher::GetOrCreateThreadSpecificInstance( | |
104 ThreadSafeSender* thread_safe_sender) { | |
105 if (g_dispatcher_tls.Pointer()->Get() == kHasBeenDeleted) { | |
106 NOTREACHED() << "Re-instantiating TLS BluetoothDispatcher."; | |
107 g_dispatcher_tls.Pointer()->Set(NULL); | |
108 } | |
109 if (g_dispatcher_tls.Pointer()->Get()) | |
110 return g_dispatcher_tls.Pointer()->Get(); | |
111 | |
112 BluetoothDispatcher* dispatcher = new BluetoothDispatcher(thread_safe_sender); | |
113 if (CurrentWorkerId()) | |
114 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher); | |
115 return dispatcher; | |
116 } | |
117 | |
118 bool BluetoothDispatcher::Send(IPC::Message* msg) { | |
119 return thread_safe_sender_->Send(msg); | |
120 } | |
121 | |
122 void BluetoothDispatcher::OnMessageReceived(const IPC::Message& msg) { | |
123 bool handled = true; | |
124 IPC_BEGIN_MESSAGE_MAP(BluetoothDispatcher, msg) | |
125 IPC_MESSAGE_HANDLER(BluetoothMsg_RequestDeviceSuccess, | |
126 OnRequestDeviceSuccess); | |
127 IPC_MESSAGE_HANDLER(BluetoothMsg_RequestDeviceError, OnRequestDeviceError); | |
128 IPC_MESSAGE_HANDLER(BluetoothMsg_ConnectGATTSuccess, OnConnectGATTSuccess); | |
129 IPC_MESSAGE_HANDLER(BluetoothMsg_ConnectGATTError, OnConnectGATTError); | |
130 IPC_MESSAGE_HANDLER(BluetoothMsg_GetPrimaryServiceSuccess, | |
131 OnGetPrimaryServiceSuccess); | |
132 IPC_MESSAGE_HANDLER(BluetoothMsg_GetPrimaryServiceError, | |
133 OnGetPrimaryServiceError); | |
134 IPC_MESSAGE_HANDLER(BluetoothMsg_GetCharacteristicSuccess, | |
135 OnGetCharacteristicSuccess); | |
136 IPC_MESSAGE_HANDLER(BluetoothMsg_GetCharacteristicError, | |
137 OnGetCharacteristicError); | |
138 IPC_MESSAGE_HANDLER(BluetoothMsg_ReadCharacteristicValueSuccess, | |
139 OnReadValueSuccess); | |
140 IPC_MESSAGE_HANDLER(BluetoothMsg_ReadCharacteristicValueError, | |
141 OnReadValueError); | |
142 IPC_MESSAGE_HANDLER(BluetoothMsg_WriteCharacteristicValueSuccess, | |
143 OnWriteValueSuccess); | |
144 IPC_MESSAGE_HANDLER(BluetoothMsg_WriteCharacteristicValueError, | |
145 OnWriteValueError); | |
146 IPC_MESSAGE_UNHANDLED(handled = false) | |
147 IPC_END_MESSAGE_MAP() | |
148 DCHECK(handled) << "Unhandled message:" << msg.type(); | |
149 } | |
150 | |
151 void BluetoothDispatcher::requestDevice( | |
152 const WebRequestDeviceOptions& options, | |
153 blink::WebBluetoothRequestDeviceCallbacks* callbacks) { | |
154 int request_id = pending_requests_.Add(callbacks); | |
155 | |
156 // Convert |options| to its IPC form. | |
157 std::vector<content::BluetoothScanFilter> filters(options.filters.size()); | |
158 for (size_t i = 0; i < options.filters.size(); ++i) { | |
159 const WebBluetoothScanFilter& web_filter = options.filters[i]; | |
160 BluetoothScanFilter& filter = filters[i]; | |
161 filter.services.reserve(web_filter.services.size()); | |
162 for (const WebString& service : web_filter.services) { | |
163 filter.services.push_back(device::BluetoothUUID(service.utf8())); | |
164 } | |
165 } | |
166 std::vector<device::BluetoothUUID> optional_services; | |
167 optional_services.reserve(options.optionalServices.size()); | |
168 for (const WebString& optional_service : options.optionalServices) { | |
169 optional_services.push_back(device::BluetoothUUID(optional_service.utf8())); | |
170 } | |
171 | |
172 Send(new BluetoothHostMsg_RequestDevice(CurrentWorkerId(), request_id, | |
173 filters, optional_services)); | |
174 } | |
175 | |
176 void BluetoothDispatcher::connectGATT( | |
177 const blink::WebString& device_instance_id, | |
178 blink::WebBluetoothConnectGATTCallbacks* callbacks) { | |
179 int request_id = pending_connect_requests_.Add(callbacks); | |
180 Send(new BluetoothHostMsg_ConnectGATT(CurrentWorkerId(), request_id, | |
181 device_instance_id.utf8())); | |
182 } | |
183 | |
184 void BluetoothDispatcher::getPrimaryService( | |
185 const blink::WebString& device_instance_id, | |
186 const blink::WebString& service_uuid, | |
187 blink::WebBluetoothGetPrimaryServiceCallbacks* callbacks) { | |
188 int request_id = | |
189 pending_primary_service_requests_.Add(new BluetoothPrimaryServiceRequest( | |
190 device_instance_id, service_uuid, callbacks)); | |
191 Send(new BluetoothHostMsg_GetPrimaryService(CurrentWorkerId(), request_id, | |
192 device_instance_id.utf8(), | |
193 service_uuid.utf8())); | |
194 } | |
195 | |
196 void BluetoothDispatcher::getCharacteristic( | |
197 const blink::WebString& service_instance_id, | |
198 const blink::WebString& characteristic_uuid, | |
199 blink::WebBluetoothGetCharacteristicCallbacks* callbacks) { | |
200 int request_id = | |
201 pending_characteristic_requests_.Add(new BluetoothCharacteristicRequest( | |
202 service_instance_id, characteristic_uuid, callbacks)); | |
203 Send(new BluetoothHostMsg_GetCharacteristic(CurrentWorkerId(), request_id, | |
204 service_instance_id.utf8(), | |
205 characteristic_uuid.utf8())); | |
206 } | |
207 | |
208 void BluetoothDispatcher::readValue( | |
209 const blink::WebString& characteristic_instance_id, | |
210 blink::WebBluetoothReadValueCallbacks* callbacks) { | |
211 int request_id = pending_read_value_requests_.Add(callbacks); | |
212 Send(new BluetoothHostMsg_ReadValue(CurrentWorkerId(), request_id, | |
213 characteristic_instance_id.utf8())); | |
214 } | |
215 | |
216 void BluetoothDispatcher::writeValue( | |
217 const blink::WebString& characteristic_instance_id, | |
218 const std::vector<uint8_t>& value, | |
219 blink::WebBluetoothWriteValueCallbacks* callbacks) { | |
220 int request_id = pending_write_value_requests_.Add(callbacks); | |
221 | |
222 Send(new BluetoothHostMsg_WriteValue( | |
223 CurrentWorkerId(), request_id, characteristic_instance_id.utf8(), value)); | |
224 } | |
225 | |
226 void BluetoothDispatcher::OnWorkerRunLoopStopped() { | |
227 delete this; | |
228 } | |
229 | |
230 void BluetoothDispatcher::OnRequestDeviceSuccess( | |
231 int thread_id, | |
232 int request_id, | |
233 const BluetoothDevice& device) { | |
234 DCHECK(pending_requests_.Lookup(request_id)) << request_id; | |
235 | |
236 WebVector<WebString> uuids(device.uuids.size()); | |
237 for (size_t i = 0; i < device.uuids.size(); ++i) | |
238 uuids[i] = WebString::fromUTF8(device.uuids[i].c_str()); | |
239 | |
240 pending_requests_.Lookup(request_id) | |
241 ->onSuccess(new WebBluetoothDevice( | |
242 WebString::fromUTF8(device.instance_id), WebString(device.name), | |
243 device.device_class, GetWebVendorIdSource(device.vendor_id_source), | |
244 device.vendor_id, device.product_id, device.product_version, | |
245 device.paired, uuids)); | |
246 pending_requests_.Remove(request_id); | |
247 } | |
248 | |
249 void BluetoothDispatcher::OnRequestDeviceError(int thread_id, | |
250 int request_id, | |
251 WebBluetoothError error) { | |
252 DCHECK(pending_requests_.Lookup(request_id)) << request_id; | |
253 pending_requests_.Lookup(request_id)->onError(new WebBluetoothError(error)); | |
254 pending_requests_.Remove(request_id); | |
255 } | |
256 | |
257 void BluetoothDispatcher::OnConnectGATTSuccess( | |
258 int thread_id, | |
259 int request_id, | |
260 const std::string& device_instance_id) { | |
261 DCHECK(pending_connect_requests_.Lookup(request_id)) << request_id; | |
262 pending_connect_requests_.Lookup(request_id) | |
263 ->onSuccess(new WebBluetoothGATTRemoteServer( | |
264 WebString::fromUTF8(device_instance_id), true /* connected */)); | |
265 pending_connect_requests_.Remove(request_id); | |
266 } | |
267 | |
268 void BluetoothDispatcher::OnConnectGATTError(int thread_id, | |
269 int request_id, | |
270 WebBluetoothError error) { | |
271 DCHECK(pending_connect_requests_.Lookup(request_id)) << request_id; | |
272 pending_connect_requests_.Lookup(request_id) | |
273 ->onError(new WebBluetoothError(error)); | |
274 pending_connect_requests_.Remove(request_id); | |
275 } | |
276 | |
277 void BluetoothDispatcher::OnGetPrimaryServiceSuccess( | |
278 int thread_id, | |
279 int request_id, | |
280 const std::string& service_instance_id) { | |
281 DCHECK(pending_primary_service_requests_.Lookup(request_id)) << request_id; | |
282 BluetoothPrimaryServiceRequest* request = | |
283 pending_primary_service_requests_.Lookup(request_id); | |
284 request->callbacks->onSuccess(new WebBluetoothGATTService( | |
285 WebString::fromUTF8(service_instance_id), request->service_uuid, | |
286 true /* isPrimary */, request->device_instance_id)); | |
287 pending_primary_service_requests_.Remove(request_id); | |
288 } | |
289 | |
290 void BluetoothDispatcher::OnGetPrimaryServiceError(int thread_id, | |
291 int request_id, | |
292 WebBluetoothError error) { | |
293 DCHECK(pending_primary_service_requests_.Lookup(request_id)) << request_id; | |
294 | |
295 // Since we couldn't find the service return null. See Step 3 of | |
296 // getPrimaryService algorithm: | |
297 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothgattremote
server-getprimaryservice | |
298 if (error == WebBluetoothError::ServiceNotFound) { | |
299 pending_primary_service_requests_.Lookup(request_id) | |
300 ->callbacks->onSuccess(nullptr); | |
301 pending_primary_service_requests_.Remove(request_id); | |
302 return; | |
303 } | |
304 | |
305 pending_primary_service_requests_.Lookup(request_id) | |
306 ->callbacks->onError(new WebBluetoothError(error)); | |
307 pending_primary_service_requests_.Remove(request_id); | |
308 } | |
309 | |
310 void BluetoothDispatcher::OnGetCharacteristicSuccess( | |
311 int thread_id, | |
312 int request_id, | |
313 const std::string& characteristic_instance_id) { | |
314 DCHECK(pending_characteristic_requests_.Lookup(request_id)) << request_id; | |
315 | |
316 BluetoothCharacteristicRequest* request = | |
317 pending_characteristic_requests_.Lookup(request_id); | |
318 request->callbacks->onSuccess(new WebBluetoothGATTCharacteristic( | |
319 WebString::fromUTF8(characteristic_instance_id), | |
320 request->service_instance_id, request->characteristic_uuid)); | |
321 | |
322 pending_characteristic_requests_.Remove(request_id); | |
323 } | |
324 | |
325 void BluetoothDispatcher::OnGetCharacteristicError(int thread_id, | |
326 int request_id, | |
327 WebBluetoothError error) { | |
328 DCHECK(pending_characteristic_requests_.Lookup(request_id)) << request_id; | |
329 | |
330 // Since we couldn't find the characteristic return null. See Step 3 of | |
331 // getCharacteristic algorithm: | |
332 // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothgattservic
e-getcharacteristic | |
333 if (error == WebBluetoothError::CharacteristicNotFound) { | |
334 pending_characteristic_requests_.Lookup(request_id) | |
335 ->callbacks->onSuccess(nullptr); | |
336 } else { | |
337 pending_characteristic_requests_.Lookup(request_id) | |
338 ->callbacks->onError(new WebBluetoothError(error)); | |
339 } | |
340 pending_characteristic_requests_.Remove(request_id); | |
341 } | |
342 | |
343 void BluetoothDispatcher::OnReadValueSuccess( | |
344 int thread_id, | |
345 int request_id, | |
346 const std::vector<uint8_t>& value) { | |
347 DCHECK(pending_read_value_requests_.Lookup(request_id)) << request_id; | |
348 | |
349 // WebArrayBuffer is not accessible from Source/modules so we pass a | |
350 // WebVector instead. | |
351 pending_read_value_requests_.Lookup(request_id) | |
352 ->onSuccess(new WebVector<uint8_t>(value)); | |
353 | |
354 pending_read_value_requests_.Remove(request_id); | |
355 } | |
356 | |
357 void BluetoothDispatcher::OnReadValueError(int thread_id, | |
358 int request_id, | |
359 WebBluetoothError error) { | |
360 DCHECK(pending_read_value_requests_.Lookup(request_id)) << request_id; | |
361 | |
362 pending_read_value_requests_.Lookup(request_id) | |
363 ->onError(new WebBluetoothError(error)); | |
364 | |
365 pending_read_value_requests_.Remove(request_id); | |
366 } | |
367 | |
368 void BluetoothDispatcher::OnWriteValueSuccess(int thread_id, int request_id) { | |
369 DCHECK(pending_write_value_requests_.Lookup(request_id)) << request_id; | |
370 | |
371 pending_write_value_requests_.Lookup(request_id)->onSuccess(); | |
372 | |
373 pending_write_value_requests_.Remove(request_id); | |
374 } | |
375 | |
376 void BluetoothDispatcher::OnWriteValueError(int thread_id, | |
377 int request_id, | |
378 WebBluetoothError error) { | |
379 DCHECK(pending_write_value_requests_.Lookup(request_id)) << request_id; | |
380 | |
381 pending_write_value_requests_.Lookup(request_id) | |
382 ->onError(new WebBluetoothError(error)); | |
383 | |
384 pending_write_value_requests_.Remove(request_id); | |
385 } | |
386 | |
387 } // namespace content | |
OLD | NEW |