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::NETWORK_ERROR
:
43 return WebBluetoothError::NetworkError
;
44 case BluetoothError::NOT_FOUND
:
45 return WebBluetoothError::NotFoundError
;
46 case BluetoothError::SECURITY
:
47 return WebBluetoothError::SecurityError
;
50 return WebBluetoothError::NotFoundError
;
53 WebBluetoothDevice::VendorIDSource
GetWebVendorIdSource(
54 device::BluetoothDevice::VendorIDSource vendor_id_source
) {
55 switch (vendor_id_source
) {
56 case device::BluetoothDevice::VENDOR_ID_UNKNOWN
:
57 return WebBluetoothDevice::VendorIDSource::Unknown
;
58 case device::BluetoothDevice::VENDOR_ID_BLUETOOTH
:
59 return WebBluetoothDevice::VendorIDSource::Bluetooth
;
60 case device::BluetoothDevice::VENDOR_ID_USB
:
61 return WebBluetoothDevice::VendorIDSource::USB
;
64 return WebBluetoothDevice::VendorIDSource::Unknown
;
69 BluetoothDispatcher::BluetoothDispatcher(ThreadSafeSender
* sender
)
70 : thread_safe_sender_(sender
) {
71 g_dispatcher_tls
.Pointer()->Set(this);
74 BluetoothDispatcher::~BluetoothDispatcher() {
75 g_dispatcher_tls
.Pointer()->Set(kHasBeenDeleted
);
78 BluetoothDispatcher
* BluetoothDispatcher::GetOrCreateThreadSpecificInstance(
79 ThreadSafeSender
* thread_safe_sender
) {
80 if (g_dispatcher_tls
.Pointer()->Get() == kHasBeenDeleted
) {
81 NOTREACHED() << "Re-instantiating TLS BluetoothDispatcher.";
82 g_dispatcher_tls
.Pointer()->Set(NULL
);
84 if (g_dispatcher_tls
.Pointer()->Get())
85 return g_dispatcher_tls
.Pointer()->Get();
87 BluetoothDispatcher
* dispatcher
= new BluetoothDispatcher(thread_safe_sender
);
88 if (CurrentWorkerId())
89 WorkerTaskRunner::Instance()->AddStopObserver(dispatcher
);
93 bool BluetoothDispatcher::Send(IPC::Message
* msg
) {
94 return thread_safe_sender_
->Send(msg
);
97 void BluetoothDispatcher::OnMessageReceived(const IPC::Message
& msg
) {
99 IPC_BEGIN_MESSAGE_MAP(BluetoothDispatcher
, msg
)
100 IPC_MESSAGE_HANDLER(BluetoothMsg_RequestDeviceSuccess
,
101 OnRequestDeviceSuccess
);
102 IPC_MESSAGE_HANDLER(BluetoothMsg_RequestDeviceError
, OnRequestDeviceError
);
103 IPC_MESSAGE_HANDLER(BluetoothMsg_ConnectGATTSuccess
, OnConnectGATTSuccess
);
104 IPC_MESSAGE_HANDLER(BluetoothMsg_ConnectGATTError
, OnConnectGATTError
);
105 IPC_MESSAGE_UNHANDLED(handled
= false)
106 IPC_END_MESSAGE_MAP()
107 DCHECK(handled
) << "Unhandled message:" << msg
.type();
110 void BluetoothDispatcher::requestDevice(
111 blink::WebBluetoothRequestDeviceCallbacks
* callbacks
) {
112 int request_id
= pending_requests_
.Add(callbacks
);
113 Send(new BluetoothHostMsg_RequestDevice(CurrentWorkerId(), request_id
));
116 void BluetoothDispatcher::connectGATT(
117 const blink::WebString
& device_instance_id
,
118 blink::WebBluetoothConnectGATTCallbacks
* callbacks
) {
119 int request_id
= pending_connect_requests_
.Add(callbacks
);
120 Send(new BluetoothHostMsg_ConnectGATT(CurrentWorkerId(), request_id
,
121 device_instance_id
.utf8()));
124 void BluetoothDispatcher::OnWorkerRunLoopStopped() {
128 void BluetoothDispatcher::OnRequestDeviceSuccess(
131 const BluetoothDevice
& device
) {
132 DCHECK(pending_requests_
.Lookup(request_id
)) << request_id
;
134 WebVector
<WebString
> uuids(device
.uuids
.size());
135 for (size_t i
= 0; i
< device
.uuids
.size(); ++i
)
136 uuids
[i
] = WebString::fromUTF8(device
.uuids
[i
].c_str());
138 pending_requests_
.Lookup(request_id
)
139 ->onSuccess(new WebBluetoothDevice(
140 WebString::fromUTF8(device
.instance_id
), WebString(device
.name
),
141 device
.device_class
, GetWebVendorIdSource(device
.vendor_id_source
),
142 device
.vendor_id
, device
.product_id
, device
.product_version
,
143 device
.paired
, uuids
));
144 pending_requests_
.Remove(request_id
);
147 void BluetoothDispatcher::OnRequestDeviceError(int thread_id
,
149 BluetoothError error_type
) {
150 DCHECK(pending_requests_
.Lookup(request_id
)) << request_id
;
151 pending_requests_
.Lookup(request_id
)
152 ->onError(new WebBluetoothError(
153 // TODO(ortuno): Return more descriptive error messages.
154 // http://crbug.com/490419
155 WebBluetoothErrorFromBluetoothError(error_type
), ""));
156 pending_requests_
.Remove(request_id
);
159 void BluetoothDispatcher::OnConnectGATTSuccess(
162 const std::string
& device_instance_id
) {
163 DCHECK(pending_connect_requests_
.Lookup(request_id
)) << request_id
;
164 pending_connect_requests_
.Lookup(request_id
)
165 ->onSuccess(new WebBluetoothGATTRemoteServer(
166 WebString::fromUTF8(device_instance_id
), true /* connected */));
167 pending_connect_requests_
.Remove(request_id
);
170 void BluetoothDispatcher::OnConnectGATTError(int thread_id
,
172 BluetoothError error_type
) {
173 DCHECK(pending_connect_requests_
.Lookup(request_id
)) << request_id
;
174 pending_connect_requests_
.Lookup(request_id
)
175 ->onError(new WebBluetoothError(
176 // TODO(ortuno): Return more descriptive error messages.
177 // http://crbug.com/490419
178 WebBluetoothErrorFromBluetoothError(error_type
), ""));
179 pending_connect_requests_
.Remove(request_id
);
182 } // namespace content