Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(392)

Side by Side Diff: chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_event_dispatcher.cc

Issue 420663003: Extensions: Move bluetooth APIs to extensions/. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix android, gn Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 "chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_event_ dispatcher.h"
6
7 #include "chrome/browser/browser_process.h"
8 #include "chrome/browser/extensions/api/bluetooth_socket/bluetooth_api_socket.h"
9 #include "chrome/common/extensions/api/bluetooth_socket.h"
10 #include "device/bluetooth/bluetooth_device.h"
11 #include "device/bluetooth/bluetooth_socket.h"
12 #include "extensions/browser/event_router.h"
13 #include "net/base/io_buffer.h"
14 #include "net/base/net_errors.h"
15
16 namespace {
17
18 namespace bluetooth_socket = extensions::api::bluetooth_socket;
19 using extensions::BluetoothApiSocket;
20
21 int kDefaultBufferSize = 4096;
22
23 bluetooth_socket::ReceiveError MapReceiveErrorReason(
24 BluetoothApiSocket::ErrorReason value) {
25 switch (value) {
26 case BluetoothApiSocket::kDisconnected:
27 return bluetooth_socket::RECEIVE_ERROR_DISCONNECTED;
28 case BluetoothApiSocket::kNotConnected:
29 // kNotConnected is impossible since a socket has to be connected to be
30 // able to call Receive() on it.
31 // fallthrough
32 case BluetoothApiSocket::kIOPending:
33 // kIOPending is not relevant to apps, as BluetoothSocketEventDispatcher
34 // handles this specific error.
35 // fallthrough
36 default:
37 return bluetooth_socket::RECEIVE_ERROR_SYSTEM_ERROR;
38 }
39 }
40
41 bluetooth_socket::AcceptError MapAcceptErrorReason(
42 BluetoothApiSocket::ErrorReason value) {
43 // TODO(keybuk): All values are system error, we may want to seperate these
44 // out to more discrete reasons.
45 switch (value) {
46 case BluetoothApiSocket::kNotListening:
47 // kNotListening is impossible since a socket has to be listening to be
48 // able to call Accept() on it.
49 // fallthrough
50 default:
51 return bluetooth_socket::ACCEPT_ERROR_SYSTEM_ERROR;
52 }
53 }
54
55 } // namespace
56
57 namespace extensions {
58 namespace api {
59
60 using content::BrowserThread;
61
62 static base::LazyInstance<
63 BrowserContextKeyedAPIFactory<BluetoothSocketEventDispatcher> > g_factory =
64 LAZY_INSTANCE_INITIALIZER;
65
66 // static
67 BrowserContextKeyedAPIFactory<BluetoothSocketEventDispatcher>*
68 BluetoothSocketEventDispatcher::GetFactoryInstance() {
69 return g_factory.Pointer();
70 }
71
72 // static
73 BluetoothSocketEventDispatcher* BluetoothSocketEventDispatcher::Get(
74 content::BrowserContext* context) {
75 DCHECK_CURRENTLY_ON(BrowserThread::UI);
76
77 return BrowserContextKeyedAPIFactory<BluetoothSocketEventDispatcher>::Get(
78 context);
79 }
80
81 BluetoothSocketEventDispatcher::BluetoothSocketEventDispatcher(
82 content::BrowserContext* context)
83 : thread_id_(BluetoothApiSocket::kThreadId),
84 browser_context_(context) {
85 ApiResourceManager<BluetoothApiSocket>* manager =
86 ApiResourceManager<BluetoothApiSocket>::Get(browser_context_);
87 DCHECK(manager)
88 << "There is no socket manager. "
89 "If this assertion is failing during a test, then it is likely that "
90 "TestExtensionSystem is failing to provide an instance of "
91 "ApiResourceManager<BluetoothApiSocket>.";
92 sockets_ = manager->data_;
93 }
94
95 BluetoothSocketEventDispatcher::~BluetoothSocketEventDispatcher() {}
96
97 BluetoothSocketEventDispatcher::SocketParams::SocketParams() {}
98
99 BluetoothSocketEventDispatcher::SocketParams::~SocketParams() {}
100
101 void BluetoothSocketEventDispatcher::OnSocketConnect(
102 const std::string& extension_id,
103 int socket_id) {
104 DCHECK(BrowserThread::CurrentlyOn(thread_id_));
105
106 SocketParams params;
107 params.thread_id = thread_id_;
108 params.browser_context_id = browser_context_;
109 params.extension_id = extension_id;
110 params.sockets = sockets_;
111 params.socket_id = socket_id;
112
113 StartReceive(params);
114 }
115
116 void BluetoothSocketEventDispatcher::OnSocketListen(
117 const std::string& extension_id,
118 int socket_id) {
119 DCHECK(BrowserThread::CurrentlyOn(thread_id_));
120
121 SocketParams params;
122 params.thread_id = thread_id_;
123 params.browser_context_id = browser_context_;
124 params.extension_id = extension_id;
125 params.sockets = sockets_;
126 params.socket_id = socket_id;
127
128 StartAccept(params);
129 }
130
131 void BluetoothSocketEventDispatcher::OnSocketResume(
132 const std::string& extension_id,
133 int socket_id) {
134 DCHECK(BrowserThread::CurrentlyOn(thread_id_));
135
136 SocketParams params;
137 params.thread_id = thread_id_;
138 params.browser_context_id = browser_context_;
139 params.extension_id = extension_id;
140 params.sockets = sockets_;
141 params.socket_id = socket_id;
142
143 BluetoothApiSocket* socket =
144 params.sockets->Get(params.extension_id, params.socket_id);
145 if (!socket) {
146 // This can happen if the socket is closed while our callback is active.
147 return;
148 }
149
150 if (socket->IsConnected()) {
151 StartReceive(params);
152 } else {
153 StartAccept(params);
154 }
155 }
156
157 // static
158 void BluetoothSocketEventDispatcher::StartReceive(const SocketParams& params) {
159 DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
160
161 BluetoothApiSocket* socket =
162 params.sockets->Get(params.extension_id, params.socket_id);
163 if (!socket) {
164 // This can happen if the socket is closed while our callback is active.
165 return;
166 }
167 DCHECK(params.extension_id == socket->owner_extension_id())
168 << "Socket has wrong owner.";
169
170 // Don't start another read if the socket has been paused.
171 if (socket->paused())
172 return;
173
174 int buffer_size = socket->buffer_size();
175 if (buffer_size <= 0)
176 buffer_size = kDefaultBufferSize;
177 socket->Receive(
178 buffer_size,
179 base::Bind(
180 &BluetoothSocketEventDispatcher::ReceiveCallback, params),
181 base::Bind(
182 &BluetoothSocketEventDispatcher::ReceiveErrorCallback, params));
183 }
184
185 // static
186 void BluetoothSocketEventDispatcher::ReceiveCallback(
187 const SocketParams& params,
188 int bytes_read,
189 scoped_refptr<net::IOBuffer> io_buffer) {
190 DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
191
192 // Dispatch "onReceive" event.
193 bluetooth_socket::ReceiveInfo receive_info;
194 receive_info.socket_id = params.socket_id;
195 receive_info.data = std::string(io_buffer->data(), bytes_read);
196 scoped_ptr<base::ListValue> args =
197 bluetooth_socket::OnReceive::Create(receive_info);
198 scoped_ptr<Event> event(
199 new Event(bluetooth_socket::OnReceive::kEventName, args.Pass()));
200 PostEvent(params, event.Pass());
201
202 // Post a task to delay the read until the socket is available, as
203 // calling StartReceive at this point would error with ERR_IO_PENDING.
204 BrowserThread::PostTask(
205 params.thread_id,
206 FROM_HERE,
207 base::Bind(&BluetoothSocketEventDispatcher::StartReceive, params));
208 }
209
210 // static
211 void BluetoothSocketEventDispatcher::ReceiveErrorCallback(
212 const SocketParams& params,
213 BluetoothApiSocket::ErrorReason error_reason,
214 const std::string& error) {
215 DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
216
217 if (error_reason == BluetoothApiSocket::kIOPending) {
218 // This happens when resuming a socket which already had an active "read"
219 // callback. We can safely ignore this error, as the application should not
220 // care.
221 return;
222 }
223
224 // Dispatch "onReceiveError" event but don't start another read to avoid
225 // potential infinite reads if we have a persistent network error.
226 bluetooth_socket::ReceiveErrorInfo receive_error_info;
227 receive_error_info.socket_id = params.socket_id;
228 receive_error_info.error_message = error;
229 receive_error_info.error = MapReceiveErrorReason(error_reason);
230 scoped_ptr<base::ListValue> args =
231 bluetooth_socket::OnReceiveError::Create(receive_error_info);
232 scoped_ptr<Event> event(
233 new Event(bluetooth_socket::OnReceiveError::kEventName, args.Pass()));
234 PostEvent(params, event.Pass());
235
236 // Since we got an error, the socket is now "paused" until the application
237 // "resumes" it.
238 BluetoothApiSocket* socket =
239 params.sockets->Get(params.extension_id, params.socket_id);
240 if (socket) {
241 socket->set_paused(true);
242 }
243 }
244
245 // static
246 void BluetoothSocketEventDispatcher::StartAccept(const SocketParams& params) {
247 DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
248
249 BluetoothApiSocket* socket =
250 params.sockets->Get(params.extension_id, params.socket_id);
251 if (!socket) {
252 // This can happen if the socket is closed while our callback is active.
253 return;
254 }
255 DCHECK(params.extension_id == socket->owner_extension_id())
256 << "Socket has wrong owner.";
257
258 // Don't start another accept if the socket has been paused.
259 if (socket->paused())
260 return;
261
262 socket->Accept(
263 base::Bind(
264 &BluetoothSocketEventDispatcher::AcceptCallback, params),
265 base::Bind(
266 &BluetoothSocketEventDispatcher::AcceptErrorCallback, params));
267 }
268
269 // static
270 void BluetoothSocketEventDispatcher::AcceptCallback(
271 const SocketParams& params,
272 const device::BluetoothDevice* device,
273 scoped_refptr<device::BluetoothSocket> socket) {
274 DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
275
276 BluetoothApiSocket* server_api_socket =
277 params.sockets->Get(params.extension_id, params.socket_id);
278 DCHECK(server_api_socket);
279
280 BluetoothApiSocket* client_api_socket = new BluetoothApiSocket(
281 params.extension_id,
282 socket,
283 device->GetAddress(),
284 server_api_socket->uuid());
285 int client_socket_id = params.sockets->Add(client_api_socket);
286
287 // Dispatch "onAccept" event.
288 bluetooth_socket::AcceptInfo accept_info;
289 accept_info.socket_id = params.socket_id;
290 accept_info.client_socket_id = client_socket_id;
291 scoped_ptr<base::ListValue> args =
292 bluetooth_socket::OnAccept::Create(accept_info);
293 scoped_ptr<Event> event(
294 new Event(bluetooth_socket::OnAccept::kEventName, args.Pass()));
295 PostEvent(params, event.Pass());
296
297 // Post a task to delay the accept until the socket is available, as
298 // calling StartAccept at this point would error with ERR_IO_PENDING.
299 BrowserThread::PostTask(
300 params.thread_id,
301 FROM_HERE,
302 base::Bind(&BluetoothSocketEventDispatcher::StartAccept, params));
303 }
304
305 // static
306 void BluetoothSocketEventDispatcher::AcceptErrorCallback(
307 const SocketParams& params,
308 BluetoothApiSocket::ErrorReason error_reason,
309 const std::string& error) {
310 DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
311
312 if (error_reason == BluetoothApiSocket::kIOPending) {
313 // This happens when resuming a socket which already had an active "accept"
314 // callback. We can safely ignore this error, as the application should not
315 // care.
316 return;
317 }
318
319 // Dispatch "onAcceptError" event but don't start another accept to avoid
320 // potential infinite accepts if we have a persistent network error.
321 bluetooth_socket::AcceptErrorInfo accept_error_info;
322 accept_error_info.socket_id = params.socket_id;
323 accept_error_info.error_message = error;
324 accept_error_info.error = MapAcceptErrorReason(error_reason);
325 scoped_ptr<base::ListValue> args =
326 bluetooth_socket::OnAcceptError::Create(accept_error_info);
327 scoped_ptr<Event> event(
328 new Event(bluetooth_socket::OnAcceptError::kEventName, args.Pass()));
329 PostEvent(params, event.Pass());
330
331 // Since we got an error, the socket is now "paused" until the application
332 // "resumes" it.
333 BluetoothApiSocket* socket =
334 params.sockets->Get(params.extension_id, params.socket_id);
335 if (socket) {
336 socket->set_paused(true);
337 }
338 }
339
340 // static
341 void BluetoothSocketEventDispatcher::PostEvent(const SocketParams& params,
342 scoped_ptr<Event> event) {
343 DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
344
345 BrowserThread::PostTask(
346 BrowserThread::UI,
347 FROM_HERE,
348 base::Bind(&DispatchEvent,
349 params.browser_context_id,
350 params.extension_id,
351 base::Passed(event.Pass())));
352 }
353
354 // static
355 void BluetoothSocketEventDispatcher::DispatchEvent(
356 void* browser_context_id,
357 const std::string& extension_id,
358 scoped_ptr<Event> event) {
359 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
360
361 content::BrowserContext* context =
362 reinterpret_cast<content::BrowserContext*>(browser_context_id);
363 if (!extensions::ExtensionsBrowserClient::Get()->IsValidContext(context))
364 return;
365
366 EventRouter* router = EventRouter::Get(context);
367 if (router)
368 router->DispatchEventToExtension(extension_id, event.Pass());
369 }
370
371 } // namespace api
372 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698