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 "extensions/browser/api/sockets_udp/sockets_udp_api.h"
6
7 #include "content/public/common/socket_permission_request.h"
8 #include "extensions/browser/api/socket/udp_socket.h"
9 #include "extensions/browser/api/sockets_udp/udp_socket_event_dispatcher.h"
10 #include "extensions/common/api/sockets/sockets_manifest_data.h"
11 #include "net/base/net_errors.h"
12
13 namespace extensions {
14 namespace core_api {
15
16 using content::SocketPermissionRequest;
17
18 const char kSocketNotFoundError[] = "Socket not found";
19 const char kPermissionError[] = "App does not have permission";
20 const char kWildcardAddress[] = "*";
21 const int kWildcardPort = 0;
22
~UDPSocketAsyncApiFunction()23 UDPSocketAsyncApiFunction::~UDPSocketAsyncApiFunction() {}
24
25 scoped_ptr<SocketResourceManagerInterface>
CreateSocketResourceManager()26 UDPSocketAsyncApiFunction::CreateSocketResourceManager() {
27 return scoped_ptr<SocketResourceManagerInterface>(
28 new SocketResourceManager<ResumableUDPSocket>()).Pass();
29 }
30
GetUdpSocket(int socket_id)31 ResumableUDPSocket* UDPSocketAsyncApiFunction::GetUdpSocket(int socket_id) {
32 return static_cast<ResumableUDPSocket*>(GetSocket(socket_id));
33 }
34
35 UDPSocketExtensionWithDnsLookupFunction::
~UDPSocketExtensionWithDnsLookupFunction()36 ~UDPSocketExtensionWithDnsLookupFunction() {}
37
38 scoped_ptr<SocketResourceManagerInterface>
CreateSocketResourceManager()39 UDPSocketExtensionWithDnsLookupFunction::CreateSocketResourceManager() {
40 return scoped_ptr<SocketResourceManagerInterface>(
41 new SocketResourceManager<ResumableUDPSocket>()).Pass();
42 }
43
GetUdpSocket(int socket_id)44 ResumableUDPSocket* UDPSocketExtensionWithDnsLookupFunction::GetUdpSocket(
45 int socket_id) {
46 return static_cast<ResumableUDPSocket*>(GetSocket(socket_id));
47 }
48
CreateSocketInfo(int socket_id,ResumableUDPSocket * socket)49 linked_ptr<sockets_udp::SocketInfo> CreateSocketInfo(
50 int socket_id,
51 ResumableUDPSocket* socket) {
52 linked_ptr<sockets_udp::SocketInfo> socket_info(
53 new sockets_udp::SocketInfo());
54 // This represents what we know about the socket, and does not call through
55 // to the system.
56 socket_info->socket_id = socket_id;
57 if (!socket->name().empty()) {
58 socket_info->name.reset(new std::string(socket->name()));
59 }
60 socket_info->persistent = socket->persistent();
61 if (socket->buffer_size() > 0) {
62 socket_info->buffer_size.reset(new int(socket->buffer_size()));
63 }
64 socket_info->paused = socket->paused();
65
66 // Grab the local address as known by the OS.
67 net::IPEndPoint localAddress;
68 if (socket->GetLocalAddress(&localAddress)) {
69 socket_info->local_address.reset(
70 new std::string(localAddress.ToStringWithoutPort()));
71 socket_info->local_port.reset(new int(localAddress.port()));
72 }
73
74 return socket_info;
75 }
76
SetSocketProperties(ResumableUDPSocket * socket,sockets_udp::SocketProperties * properties)77 void SetSocketProperties(ResumableUDPSocket* socket,
78 sockets_udp::SocketProperties* properties) {
79 if (properties->name.get()) {
80 socket->set_name(*properties->name.get());
81 }
82 if (properties->persistent.get()) {
83 socket->set_persistent(*properties->persistent.get());
84 }
85 if (properties->buffer_size.get()) {
86 socket->set_buffer_size(*properties->buffer_size.get());
87 }
88 }
89
SocketsUdpCreateFunction()90 SocketsUdpCreateFunction::SocketsUdpCreateFunction() {}
91
~SocketsUdpCreateFunction()92 SocketsUdpCreateFunction::~SocketsUdpCreateFunction() {}
93
Prepare()94 bool SocketsUdpCreateFunction::Prepare() {
95 params_ = sockets_udp::Create::Params::Create(*args_);
96 EXTENSION_FUNCTION_VALIDATE(params_.get());
97 return true;
98 }
99
Work()100 void SocketsUdpCreateFunction::Work() {
101 ResumableUDPSocket* socket = new ResumableUDPSocket(extension_->id());
102
103 sockets_udp::SocketProperties* properties = params_.get()->properties.get();
104 if (properties) {
105 SetSocketProperties(socket, properties);
106 }
107
108 sockets_udp::CreateInfo create_info;
109 create_info.socket_id = AddSocket(socket);
110 results_ = sockets_udp::Create::Results::Create(create_info);
111 }
112
SocketsUdpUpdateFunction()113 SocketsUdpUpdateFunction::SocketsUdpUpdateFunction() {}
114
~SocketsUdpUpdateFunction()115 SocketsUdpUpdateFunction::~SocketsUdpUpdateFunction() {}
116
Prepare()117 bool SocketsUdpUpdateFunction::Prepare() {
118 params_ = sockets_udp::Update::Params::Create(*args_);
119 EXTENSION_FUNCTION_VALIDATE(params_.get());
120 return true;
121 }
122
Work()123 void SocketsUdpUpdateFunction::Work() {
124 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
125 if (!socket) {
126 error_ = kSocketNotFoundError;
127 return;
128 }
129
130 SetSocketProperties(socket, ¶ms_.get()->properties);
131 results_ = sockets_udp::Update::Results::Create();
132 }
133
SocketsUdpSetPausedFunction()134 SocketsUdpSetPausedFunction::SocketsUdpSetPausedFunction()
135 : socket_event_dispatcher_(NULL) {}
136
~SocketsUdpSetPausedFunction()137 SocketsUdpSetPausedFunction::~SocketsUdpSetPausedFunction() {}
138
Prepare()139 bool SocketsUdpSetPausedFunction::Prepare() {
140 params_ = core_api::sockets_udp::SetPaused::Params::Create(*args_);
141 EXTENSION_FUNCTION_VALIDATE(params_.get());
142
143 socket_event_dispatcher_ = UDPSocketEventDispatcher::Get(browser_context());
144 DCHECK(socket_event_dispatcher_)
145 << "There is no socket event dispatcher. "
146 "If this assertion is failing during a test, then it is likely that "
147 "TestExtensionSystem is failing to provide an instance of "
148 "UDPSocketEventDispatcher.";
149 return socket_event_dispatcher_ != NULL;
150 }
151
Work()152 void SocketsUdpSetPausedFunction::Work() {
153 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
154 if (!socket) {
155 error_ = kSocketNotFoundError;
156 return;
157 }
158
159 if (socket->paused() != params_->paused) {
160 socket->set_paused(params_->paused);
161 if (socket->IsBound() && !params_->paused) {
162 socket_event_dispatcher_->OnSocketResume(extension_->id(),
163 params_->socket_id);
164 }
165 }
166
167 results_ = sockets_udp::SetPaused::Results::Create();
168 }
169
SocketsUdpBindFunction()170 SocketsUdpBindFunction::SocketsUdpBindFunction()
171 : socket_event_dispatcher_(NULL) {}
172
~SocketsUdpBindFunction()173 SocketsUdpBindFunction::~SocketsUdpBindFunction() {}
174
Prepare()175 bool SocketsUdpBindFunction::Prepare() {
176 params_ = sockets_udp::Bind::Params::Create(*args_);
177 EXTENSION_FUNCTION_VALIDATE(params_.get());
178
179 socket_event_dispatcher_ = UDPSocketEventDispatcher::Get(browser_context());
180 DCHECK(socket_event_dispatcher_)
181 << "There is no socket event dispatcher. "
182 "If this assertion is failing during a test, then it is likely that "
183 "TestExtensionSystem is failing to provide an instance of "
184 "UDPSocketEventDispatcher.";
185 return socket_event_dispatcher_ != NULL;
186 }
187
Work()188 void SocketsUdpBindFunction::Work() {
189 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
190 if (!socket) {
191 error_ = kSocketNotFoundError;
192 return;
193 }
194
195 content::SocketPermissionRequest param(
196 SocketPermissionRequest::UDP_BIND, params_->address, params_->port);
197 if (!SocketsManifestData::CheckRequest(GetExtension(), param)) {
198 error_ = kPermissionError;
199 return;
200 }
201
202 int net_result = socket->Bind(params_->address, params_->port);
203 if (net_result == net::OK) {
204 socket_event_dispatcher_->OnSocketBind(extension_->id(),
205 params_->socket_id);
206 }
207
208 if (net_result != net::OK)
209 error_ = net::ErrorToString(net_result);
210 results_ = sockets_udp::Bind::Results::Create(net_result);
211 }
212
SocketsUdpSendFunction()213 SocketsUdpSendFunction::SocketsUdpSendFunction() : io_buffer_size_(0) {}
214
~SocketsUdpSendFunction()215 SocketsUdpSendFunction::~SocketsUdpSendFunction() {}
216
Prepare()217 bool SocketsUdpSendFunction::Prepare() {
218 params_ = sockets_udp::Send::Params::Create(*args_);
219 EXTENSION_FUNCTION_VALIDATE(params_.get());
220 io_buffer_size_ = params_->data.size();
221 io_buffer_ = new net::WrappedIOBuffer(params_->data.data());
222
223 return true;
224 }
225
AsyncWorkStart()226 void SocketsUdpSendFunction::AsyncWorkStart() {
227 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
228 if (!socket) {
229 error_ = kSocketNotFoundError;
230 AsyncWorkCompleted();
231 return;
232 }
233
234 content::SocketPermissionRequest param(
235 SocketPermissionRequest::UDP_SEND_TO, params_->address, params_->port);
236 if (!SocketsManifestData::CheckRequest(GetExtension(), param)) {
237 error_ = kPermissionError;
238 AsyncWorkCompleted();
239 return;
240 }
241
242 StartDnsLookup(params_->address);
243 }
244
AfterDnsLookup(int lookup_result)245 void SocketsUdpSendFunction::AfterDnsLookup(int lookup_result) {
246 if (lookup_result == net::OK) {
247 StartSendTo();
248 } else {
249 SetSendResult(lookup_result, -1);
250 }
251 }
252
StartSendTo()253 void SocketsUdpSendFunction::StartSendTo() {
254 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
255 if (!socket) {
256 error_ = kSocketNotFoundError;
257 AsyncWorkCompleted();
258 return;
259 }
260
261 socket->SendTo(io_buffer_,
262 io_buffer_size_,
263 resolved_address_,
264 params_->port,
265 base::Bind(&SocketsUdpSendFunction::OnCompleted, this));
266 }
267
OnCompleted(int net_result)268 void SocketsUdpSendFunction::OnCompleted(int net_result) {
269 if (net_result >= net::OK) {
270 SetSendResult(net::OK, net_result);
271 } else {
272 SetSendResult(net_result, -1);
273 }
274 }
275
SetSendResult(int net_result,int bytes_sent)276 void SocketsUdpSendFunction::SetSendResult(int net_result, int bytes_sent) {
277 CHECK(net_result <= net::OK) << "Network status code must be < 0";
278
279 sockets_udp::SendInfo send_info;
280 send_info.result_code = net_result;
281 if (net_result == net::OK) {
282 send_info.bytes_sent.reset(new int(bytes_sent));
283 }
284
285 if (net_result != net::OK)
286 error_ = net::ErrorToString(net_result);
287 results_ = sockets_udp::Send::Results::Create(send_info);
288 AsyncWorkCompleted();
289 }
290
SocketsUdpCloseFunction()291 SocketsUdpCloseFunction::SocketsUdpCloseFunction() {}
292
~SocketsUdpCloseFunction()293 SocketsUdpCloseFunction::~SocketsUdpCloseFunction() {}
294
Prepare()295 bool SocketsUdpCloseFunction::Prepare() {
296 params_ = sockets_udp::Close::Params::Create(*args_);
297 EXTENSION_FUNCTION_VALIDATE(params_.get());
298 return true;
299 }
300
Work()301 void SocketsUdpCloseFunction::Work() {
302 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
303 if (!socket) {
304 error_ = kSocketNotFoundError;
305 return;
306 }
307
308 socket->Disconnect();
309 RemoveSocket(params_->socket_id);
310 results_ = sockets_udp::Close::Results::Create();
311 }
312
SocketsUdpGetInfoFunction()313 SocketsUdpGetInfoFunction::SocketsUdpGetInfoFunction() {}
314
~SocketsUdpGetInfoFunction()315 SocketsUdpGetInfoFunction::~SocketsUdpGetInfoFunction() {}
316
Prepare()317 bool SocketsUdpGetInfoFunction::Prepare() {
318 params_ = sockets_udp::GetInfo::Params::Create(*args_);
319 EXTENSION_FUNCTION_VALIDATE(params_.get());
320 return true;
321 }
322
Work()323 void SocketsUdpGetInfoFunction::Work() {
324 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
325 if (!socket) {
326 error_ = kSocketNotFoundError;
327 return;
328 }
329
330 linked_ptr<sockets_udp::SocketInfo> socket_info =
331 CreateSocketInfo(params_->socket_id, socket);
332 results_ = sockets_udp::GetInfo::Results::Create(*socket_info);
333 }
334
SocketsUdpGetSocketsFunction()335 SocketsUdpGetSocketsFunction::SocketsUdpGetSocketsFunction() {}
336
~SocketsUdpGetSocketsFunction()337 SocketsUdpGetSocketsFunction::~SocketsUdpGetSocketsFunction() {}
338
Prepare()339 bool SocketsUdpGetSocketsFunction::Prepare() { return true; }
340
Work()341 void SocketsUdpGetSocketsFunction::Work() {
342 std::vector<linked_ptr<sockets_udp::SocketInfo> > socket_infos;
343 base::hash_set<int>* resource_ids = GetSocketIds();
344 if (resource_ids != NULL) {
345 for (base::hash_set<int>::iterator it = resource_ids->begin();
346 it != resource_ids->end();
347 ++it) {
348 int socket_id = *it;
349 ResumableUDPSocket* socket = GetUdpSocket(socket_id);
350 if (socket) {
351 socket_infos.push_back(CreateSocketInfo(socket_id, socket));
352 }
353 }
354 }
355 results_ = sockets_udp::GetSockets::Results::Create(socket_infos);
356 }
357
SocketsUdpJoinGroupFunction()358 SocketsUdpJoinGroupFunction::SocketsUdpJoinGroupFunction() {}
359
~SocketsUdpJoinGroupFunction()360 SocketsUdpJoinGroupFunction::~SocketsUdpJoinGroupFunction() {}
361
Prepare()362 bool SocketsUdpJoinGroupFunction::Prepare() {
363 params_ = sockets_udp::JoinGroup::Params::Create(*args_);
364 EXTENSION_FUNCTION_VALIDATE(params_.get());
365 return true;
366 }
367
Work()368 void SocketsUdpJoinGroupFunction::Work() {
369 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
370 if (!socket) {
371 error_ = kSocketNotFoundError;
372 return;
373 }
374
375 content::SocketPermissionRequest param(
376 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
377 kWildcardAddress,
378 kWildcardPort);
379 if (!SocketsManifestData::CheckRequest(GetExtension(), param)) {
380 error_ = kPermissionError;
381 return;
382 }
383
384 int net_result = socket->JoinGroup(params_->address);
385 if (net_result != net::OK)
386 error_ = net::ErrorToString(net_result);
387 results_ = sockets_udp::JoinGroup::Results::Create(net_result);
388 }
389
SocketsUdpLeaveGroupFunction()390 SocketsUdpLeaveGroupFunction::SocketsUdpLeaveGroupFunction() {}
391
~SocketsUdpLeaveGroupFunction()392 SocketsUdpLeaveGroupFunction::~SocketsUdpLeaveGroupFunction() {}
393
Prepare()394 bool SocketsUdpLeaveGroupFunction::Prepare() {
395 params_ = core_api::sockets_udp::LeaveGroup::Params::Create(*args_);
396 EXTENSION_FUNCTION_VALIDATE(params_.get());
397 return true;
398 }
399
Work()400 void SocketsUdpLeaveGroupFunction::Work() {
401 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
402 if (!socket) {
403 error_ = kSocketNotFoundError;
404 return;
405 }
406
407 content::SocketPermissionRequest param(
408 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
409 kWildcardAddress,
410 kWildcardPort);
411 if (!SocketsManifestData::CheckRequest(GetExtension(), param)) {
412 error_ = kPermissionError;
413 return;
414 }
415
416 int net_result = socket->LeaveGroup(params_->address);
417 if (net_result != net::OK)
418 error_ = net::ErrorToString(net_result);
419 results_ = sockets_udp::LeaveGroup::Results::Create(net_result);
420 }
421
422 SocketsUdpSetMulticastTimeToLiveFunction::
SocketsUdpSetMulticastTimeToLiveFunction()423 SocketsUdpSetMulticastTimeToLiveFunction() {}
424
425 SocketsUdpSetMulticastTimeToLiveFunction::
~SocketsUdpSetMulticastTimeToLiveFunction()426 ~SocketsUdpSetMulticastTimeToLiveFunction() {}
427
Prepare()428 bool SocketsUdpSetMulticastTimeToLiveFunction::Prepare() {
429 params_ =
430 core_api::sockets_udp::SetMulticastTimeToLive::Params::Create(*args_);
431 EXTENSION_FUNCTION_VALIDATE(params_.get());
432 return true;
433 }
434
Work()435 void SocketsUdpSetMulticastTimeToLiveFunction::Work() {
436 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
437 if (!socket) {
438 error_ = kSocketNotFoundError;
439 return;
440 }
441
442 int net_result = socket->SetMulticastTimeToLive(params_->ttl);
443 if (net_result != net::OK)
444 error_ = net::ErrorToString(net_result);
445 results_ = sockets_udp::SetMulticastTimeToLive::Results::Create(net_result);
446 }
447
448 SocketsUdpSetMulticastLoopbackModeFunction::
SocketsUdpSetMulticastLoopbackModeFunction()449 SocketsUdpSetMulticastLoopbackModeFunction() {}
450
451 SocketsUdpSetMulticastLoopbackModeFunction::
~SocketsUdpSetMulticastLoopbackModeFunction()452 ~SocketsUdpSetMulticastLoopbackModeFunction() {}
453
Prepare()454 bool SocketsUdpSetMulticastLoopbackModeFunction::Prepare() {
455 params_ =
456 core_api::sockets_udp::SetMulticastLoopbackMode::Params::Create(*args_);
457 EXTENSION_FUNCTION_VALIDATE(params_.get());
458 return true;
459 }
460
Work()461 void SocketsUdpSetMulticastLoopbackModeFunction::Work() {
462 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
463 if (!socket) {
464 error_ = kSocketNotFoundError;
465 return;
466 }
467
468 int net_result = socket->SetMulticastLoopbackMode(params_->enabled);
469 if (net_result != net::OK)
470 error_ = net::ErrorToString(net_result);
471 results_ = sockets_udp::SetMulticastLoopbackMode::Results::Create(net_result);
472 }
473
SocketsUdpGetJoinedGroupsFunction()474 SocketsUdpGetJoinedGroupsFunction::SocketsUdpGetJoinedGroupsFunction() {}
475
~SocketsUdpGetJoinedGroupsFunction()476 SocketsUdpGetJoinedGroupsFunction::~SocketsUdpGetJoinedGroupsFunction() {}
477
Prepare()478 bool SocketsUdpGetJoinedGroupsFunction::Prepare() {
479 params_ = core_api::sockets_udp::GetJoinedGroups::Params::Create(*args_);
480 EXTENSION_FUNCTION_VALIDATE(params_.get());
481 return true;
482 }
483
Work()484 void SocketsUdpGetJoinedGroupsFunction::Work() {
485 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
486 if (!socket) {
487 error_ = kSocketNotFoundError;
488 return;
489 }
490
491 content::SocketPermissionRequest param(
492 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
493 kWildcardAddress,
494 kWildcardPort);
495 if (!SocketsManifestData::CheckRequest(GetExtension(), param)) {
496 error_ = kPermissionError;
497 return;
498 }
499
500 const std::vector<std::string>& groups = socket->GetJoinedGroups();
501 results_ = sockets_udp::GetJoinedGroups::Results::Create(groups);
502 }
503
504 } // namespace core_api
505 } // namespace extensions
506