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 "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothDevice.h"
14 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothError.h"
15 #include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTRemoteServer.h"
17 using blink::WebBluetoothConnectGATTCallbacks
;
18 using blink::WebBluetoothDevice
;
19 using blink::WebBluetoothError
;
20 using blink::WebBluetoothGATTRemoteServer
;
21 using blink::WebBluetoothRequestDeviceCallbacks
;
22 using blink::WebString
;
23 using blink::WebVector
;
29 base::LazyInstance
<base::ThreadLocalPointer
<BluetoothDispatcher
>>::Leaky
30 g_dispatcher_tls
= LAZY_INSTANCE_INITIALIZER
;
32 BluetoothDispatcher
* const kHasBeenDeleted
=
33 reinterpret_cast<BluetoothDispatcher
*>(0x1);
35 int CurrentWorkerId() {
36 return WorkerTaskRunner::Instance()->CurrentWorkerId();
39 WebBluetoothError::ErrorType
WebBluetoothErrorFromBluetoothError(
40 BluetoothError error_type
) {
42 case BluetoothError::NOT_FOUND
:
43 return WebBluetoothError::NotFoundError
;
44 case BluetoothError::SECURITY
:
45 return WebBluetoothError::SecurityError
;
48 return WebBluetoothError::NotFoundError
;
51 WebBluetoothDevice::VendorIDSource
GetWebVendorIdSource(
52 device::BluetoothDevice::VendorIDSource vendor_id_source
) {
53 switch (vendor_id_source
) {
54 case device::BluetoothDevice::VENDOR_ID_UNKNOWN
:
55 return WebBluetoothDevice::VendorIDSource::Unknown
;
56 case device::BluetoothDevice::VENDOR_ID_BLUETOOTH
:
57 return WebBluetoothDevice::VendorIDSource::Bluetooth
;
58 case device::BluetoothDevice::VENDOR_ID_USB
:
59 return WebBluetoothDevice::VendorIDSource::USB
;
62 return WebBluetoothDevice::VendorIDSource::Unknown
;
67 BluetoothDispatcher::BluetoothDispatcher(ThreadSafeSender
* sender
)
68 : thread_safe_sender_(sender
) {
69 g_dispatcher_tls
.Pointer()->Set(this);
72 BluetoothDispatcher::~BluetoothDispatcher() {
73 g_dispatcher_tls
.Pointer()->Set(kHasBeenDeleted
);
76 BluetoothDispatcher
* BluetoothDispatcher::GetOrCreateThreadSpecificInstance(
77 ThreadSafeSender
* thread_safe_sender
) {
78 if (g_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
) {
79 NOTREACHED() << "Re-instantiating TLS BluetoothDispatcher.";
80 g_dispatcher_tls
.Pointer()->Set(NULL
);
82 if (g_dispatcher_tls
.Pointer()->Get())
83 return g_dispatcher_tls
.Pointer()->Get();
85 BluetoothDispatcher
* dispatcher
= new BluetoothDispatcher(thread_safe_sender
);
86 if (CurrentWorkerId())
87 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher
);
91 bool BluetoothDispatcher::Send(IPC::Message
* msg
) {
92 return thread_safe_sender_
->Send(msg
);
95 void BluetoothDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
97 IPC_BEGIN_MESSAGE_MAP(BluetoothDispatcher
, msg
)
98 IPC_MESSAGE_HANDLER(BluetoothMsg_RequestDeviceSuccess
,
99 OnRequestDeviceSuccess
);
100 IPC_MESSAGE_HANDLER(BluetoothMsg_RequestDeviceError
, OnRequestDeviceError
);
101 IPC_MESSAGE_HANDLER(BluetoothMsg_ConnectGATTSuccess
, OnConnectGATTSuccess
);
102 IPC_MESSAGE_UNHANDLED(handled
= false)
103 IPC_END_MESSAGE_MAP()
104 DCHECK(handled
) << "Unhandled message:" << msg
.type();
107 void BluetoothDispatcher::requestDevice(
108 blink::WebBluetoothRequestDeviceCallbacks
* callbacks
) {
109 int request_id
= pending_requests_
.Add(callbacks
);
110 Send(new BluetoothHostMsg_RequestDevice(CurrentWorkerId(), request_id
));
113 void BluetoothDispatcher::connectGATT(
114 const blink::WebString
& device_instance_id
,
115 blink::WebBluetoothConnectGATTCallbacks
* callbacks
) {
116 int request_id
= pending_connect_requests_
.Add(callbacks
);
117 Send(new BluetoothHostMsg_ConnectGATT(CurrentWorkerId(), request_id
,
118 device_instance_id
.utf8()));
121 void BluetoothDispatcher::SetBluetoothMockDataSetForTesting(
122 const std::string
& name
) {
123 Send(new BluetoothHostMsg_SetBluetoothMockDataSetForTesting(name
));
126 void BluetoothDispatcher::OnWorkerRunLoopStopped() {
130 void BluetoothDispatcher::OnRequestDeviceSuccess(
133 const BluetoothDevice
& device
) {
134 DCHECK(pending_requests_
.Lookup(request_id
)) << request_id
;
136 WebVector
<WebString
> uuids(device
.uuids
.size());
137 for (size_t i
= 0; i
< device
.uuids
.size(); ++i
)
138 uuids
[i
] = WebString::fromUTF8(device
.uuids
[i
].c_str());
140 pending_requests_
.Lookup(request_id
)
141 ->onSuccess(new WebBluetoothDevice(
142 WebString::fromUTF8(device
.instance_id
), WebString(device
.name
),
143 device
.device_class
, GetWebVendorIdSource(device
.vendor_id_source
),
144 device
.vendor_id
, device
.product_id
, device
.product_version
,
145 device
.paired
, uuids
));
146 pending_requests_
.Remove(request_id
);
149 void BluetoothDispatcher::OnConnectGATTSuccess(
152 const std::string
& device_instance_id
) {
153 DCHECK(pending_connect_requests_
.Lookup(request_id
)) << request_id
;
154 pending_connect_requests_
.Lookup(request_id
)
155 ->onSuccess(new WebBluetoothGATTRemoteServer(
156 WebString::fromUTF8(device_instance_id
), true /* connected */));
157 pending_connect_requests_
.Remove(request_id
);
160 void BluetoothDispatcher::OnRequestDeviceError(int thread_id
,
162 BluetoothError error_type
) {
163 DCHECK(pending_requests_
.Lookup(request_id
)) << request_id
;
164 pending_requests_
.Lookup(request_id
)
165 ->onError(new WebBluetoothError(
166 WebBluetoothErrorFromBluetoothError(error_type
), ""));
167 pending_requests_
.Remove(request_id
);
170 } // namespace content