Roll src/third_party/WebKit a3b4a2e:7441784 (svn 202551:202552)
[chromium-blink-merge.git] / extensions / browser / api / sockets_udp / sockets_udp_api.cc
blob68329144dc627c5a58e1831322956c5ecabec33a
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 "extensions/browser/api/sockets_udp/sockets_udp_api.h"
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"
13 namespace extensions {
14 namespace api {
16 using content::SocketPermissionRequest;
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;
23 UDPSocketAsyncApiFunction::~UDPSocketAsyncApiFunction() {}
25 scoped_ptr<SocketResourceManagerInterface>
26 UDPSocketAsyncApiFunction::CreateSocketResourceManager() {
27 return scoped_ptr<SocketResourceManagerInterface>(
28 new SocketResourceManager<ResumableUDPSocket>()).Pass();
31 ResumableUDPSocket* UDPSocketAsyncApiFunction::GetUdpSocket(int socket_id) {
32 return static_cast<ResumableUDPSocket*>(GetSocket(socket_id));
35 UDPSocketExtensionWithDnsLookupFunction::
36 ~UDPSocketExtensionWithDnsLookupFunction() {}
38 scoped_ptr<SocketResourceManagerInterface>
39 UDPSocketExtensionWithDnsLookupFunction::CreateSocketResourceManager() {
40 return scoped_ptr<SocketResourceManagerInterface>(
41 new SocketResourceManager<ResumableUDPSocket>()).Pass();
44 ResumableUDPSocket* UDPSocketExtensionWithDnsLookupFunction::GetUdpSocket(
45 int socket_id) {
46 return static_cast<ResumableUDPSocket*>(GetSocket(socket_id));
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()));
60 socket_info->persistent = socket->persistent();
61 if (socket->buffer_size() > 0) {
62 socket_info->buffer_size.reset(new int(socket->buffer_size()));
64 socket_info->paused = socket->paused();
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()));
74 return socket_info;
77 void SetSocketProperties(ResumableUDPSocket* socket,
78 sockets_udp::SocketProperties* properties) {
79 if (properties->name.get()) {
80 socket->set_name(*properties->name.get());
82 if (properties->persistent.get()) {
83 socket->set_persistent(*properties->persistent.get());
85 if (properties->buffer_size.get()) {
86 socket->set_buffer_size(*properties->buffer_size.get());
90 SocketsUdpCreateFunction::SocketsUdpCreateFunction() {}
92 SocketsUdpCreateFunction::~SocketsUdpCreateFunction() {}
94 bool SocketsUdpCreateFunction::Prepare() {
95 params_ = sockets_udp::Create::Params::Create(*args_);
96 EXTENSION_FUNCTION_VALIDATE(params_.get());
97 return true;
100 void SocketsUdpCreateFunction::Work() {
101 ResumableUDPSocket* socket = new ResumableUDPSocket(extension_->id());
103 sockets_udp::SocketProperties* properties = params_.get()->properties.get();
104 if (properties) {
105 SetSocketProperties(socket, properties);
108 sockets_udp::CreateInfo create_info;
109 create_info.socket_id = AddSocket(socket);
110 results_ = sockets_udp::Create::Results::Create(create_info);
113 SocketsUdpUpdateFunction::SocketsUdpUpdateFunction() {}
115 SocketsUdpUpdateFunction::~SocketsUdpUpdateFunction() {}
117 bool SocketsUdpUpdateFunction::Prepare() {
118 params_ = sockets_udp::Update::Params::Create(*args_);
119 EXTENSION_FUNCTION_VALIDATE(params_.get());
120 return true;
123 void SocketsUdpUpdateFunction::Work() {
124 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
125 if (!socket) {
126 error_ = kSocketNotFoundError;
127 return;
130 SetSocketProperties(socket, &params_.get()->properties);
131 results_ = sockets_udp::Update::Results::Create();
134 SocketsUdpSetPausedFunction::SocketsUdpSetPausedFunction()
135 : socket_event_dispatcher_(NULL) {}
137 SocketsUdpSetPausedFunction::~SocketsUdpSetPausedFunction() {}
139 bool SocketsUdpSetPausedFunction::Prepare() {
140 params_ = api::sockets_udp::SetPaused::Params::Create(*args_);
141 EXTENSION_FUNCTION_VALIDATE(params_.get());
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;
152 void SocketsUdpSetPausedFunction::Work() {
153 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
154 if (!socket) {
155 error_ = kSocketNotFoundError;
156 return;
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);
167 results_ = sockets_udp::SetPaused::Results::Create();
170 SocketsUdpBindFunction::SocketsUdpBindFunction()
171 : socket_event_dispatcher_(NULL) {}
173 SocketsUdpBindFunction::~SocketsUdpBindFunction() {}
175 bool SocketsUdpBindFunction::Prepare() {
176 params_ = sockets_udp::Bind::Params::Create(*args_);
177 EXTENSION_FUNCTION_VALIDATE(params_.get());
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;
188 void SocketsUdpBindFunction::AsyncWorkStart() {
189 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
190 if (!socket) {
191 error_ = kSocketNotFoundError;
192 AsyncWorkCompleted();
193 return;
196 content::SocketPermissionRequest param(
197 SocketPermissionRequest::UDP_BIND, params_->address, params_->port);
198 if (!SocketsManifestData::CheckRequest(extension(), param)) {
199 error_ = kPermissionError;
200 AsyncWorkCompleted();
201 return;
204 int net_result = socket->Bind(params_->address, params_->port);
205 results_ = sockets_udp::Bind::Results::Create(net_result);
206 if (net_result == net::OK) {
207 socket_event_dispatcher_->OnSocketBind(extension_->id(),
208 params_->socket_id);
209 } else {
210 error_ = net::ErrorToString(net_result);
211 AsyncWorkCompleted();
212 return;
215 OpenFirewallHole(params_->address, params_->socket_id, socket);
218 SocketsUdpSendFunction::SocketsUdpSendFunction() : io_buffer_size_(0) {}
220 SocketsUdpSendFunction::~SocketsUdpSendFunction() {}
222 bool SocketsUdpSendFunction::Prepare() {
223 params_ = sockets_udp::Send::Params::Create(*args_);
224 EXTENSION_FUNCTION_VALIDATE(params_.get());
225 io_buffer_size_ = params_->data.size();
226 io_buffer_ = new net::WrappedIOBuffer(params_->data.data());
228 return true;
231 void SocketsUdpSendFunction::AsyncWorkStart() {
232 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
233 if (!socket) {
234 error_ = kSocketNotFoundError;
235 AsyncWorkCompleted();
236 return;
239 content::SocketPermissionRequest param(
240 SocketPermissionRequest::UDP_SEND_TO, params_->address, params_->port);
241 if (!SocketsManifestData::CheckRequest(extension(), param)) {
242 error_ = kPermissionError;
243 AsyncWorkCompleted();
244 return;
247 StartDnsLookup(net::HostPortPair(params_->address, params_->port));
250 void SocketsUdpSendFunction::AfterDnsLookup(int lookup_result) {
251 if (lookup_result == net::OK) {
252 StartSendTo();
253 } else {
254 SetSendResult(lookup_result, -1);
258 void SocketsUdpSendFunction::StartSendTo() {
259 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
260 if (!socket) {
261 error_ = kSocketNotFoundError;
262 AsyncWorkCompleted();
263 return;
266 socket->SendTo(io_buffer_, io_buffer_size_, addresses_.front(),
267 base::Bind(&SocketsUdpSendFunction::OnCompleted, this));
270 void SocketsUdpSendFunction::OnCompleted(int net_result) {
271 if (net_result >= net::OK) {
272 SetSendResult(net::OK, net_result);
273 } else {
274 SetSendResult(net_result, -1);
278 void SocketsUdpSendFunction::SetSendResult(int net_result, int bytes_sent) {
279 CHECK(net_result <= net::OK) << "Network status code must be < 0";
281 sockets_udp::SendInfo send_info;
282 send_info.result_code = net_result;
283 if (net_result == net::OK) {
284 send_info.bytes_sent.reset(new int(bytes_sent));
287 if (net_result != net::OK)
288 error_ = net::ErrorToString(net_result);
289 results_ = sockets_udp::Send::Results::Create(send_info);
290 AsyncWorkCompleted();
293 SocketsUdpCloseFunction::SocketsUdpCloseFunction() {}
295 SocketsUdpCloseFunction::~SocketsUdpCloseFunction() {}
297 bool SocketsUdpCloseFunction::Prepare() {
298 params_ = sockets_udp::Close::Params::Create(*args_);
299 EXTENSION_FUNCTION_VALIDATE(params_.get());
300 return true;
303 void SocketsUdpCloseFunction::Work() {
304 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
305 if (!socket) {
306 error_ = kSocketNotFoundError;
307 return;
310 socket->Disconnect();
311 RemoveSocket(params_->socket_id);
312 results_ = sockets_udp::Close::Results::Create();
315 SocketsUdpGetInfoFunction::SocketsUdpGetInfoFunction() {}
317 SocketsUdpGetInfoFunction::~SocketsUdpGetInfoFunction() {}
319 bool SocketsUdpGetInfoFunction::Prepare() {
320 params_ = sockets_udp::GetInfo::Params::Create(*args_);
321 EXTENSION_FUNCTION_VALIDATE(params_.get());
322 return true;
325 void SocketsUdpGetInfoFunction::Work() {
326 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
327 if (!socket) {
328 error_ = kSocketNotFoundError;
329 return;
332 linked_ptr<sockets_udp::SocketInfo> socket_info =
333 CreateSocketInfo(params_->socket_id, socket);
334 results_ = sockets_udp::GetInfo::Results::Create(*socket_info);
337 SocketsUdpGetSocketsFunction::SocketsUdpGetSocketsFunction() {}
339 SocketsUdpGetSocketsFunction::~SocketsUdpGetSocketsFunction() {}
341 bool SocketsUdpGetSocketsFunction::Prepare() { return true; }
343 void SocketsUdpGetSocketsFunction::Work() {
344 std::vector<linked_ptr<sockets_udp::SocketInfo> > socket_infos;
345 base::hash_set<int>* resource_ids = GetSocketIds();
346 if (resource_ids != NULL) {
347 for (base::hash_set<int>::iterator it = resource_ids->begin();
348 it != resource_ids->end();
349 ++it) {
350 int socket_id = *it;
351 ResumableUDPSocket* socket = GetUdpSocket(socket_id);
352 if (socket) {
353 socket_infos.push_back(CreateSocketInfo(socket_id, socket));
357 results_ = sockets_udp::GetSockets::Results::Create(socket_infos);
360 SocketsUdpJoinGroupFunction::SocketsUdpJoinGroupFunction() {}
362 SocketsUdpJoinGroupFunction::~SocketsUdpJoinGroupFunction() {}
364 bool SocketsUdpJoinGroupFunction::Prepare() {
365 params_ = sockets_udp::JoinGroup::Params::Create(*args_);
366 EXTENSION_FUNCTION_VALIDATE(params_.get());
367 return true;
370 void SocketsUdpJoinGroupFunction::Work() {
371 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
372 if (!socket) {
373 error_ = kSocketNotFoundError;
374 return;
377 content::SocketPermissionRequest param(
378 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
379 kWildcardAddress,
380 kWildcardPort);
381 if (!SocketsManifestData::CheckRequest(extension(), param)) {
382 error_ = kPermissionError;
383 return;
386 int net_result = socket->JoinGroup(params_->address);
387 if (net_result != net::OK)
388 error_ = net::ErrorToString(net_result);
389 results_ = sockets_udp::JoinGroup::Results::Create(net_result);
392 SocketsUdpLeaveGroupFunction::SocketsUdpLeaveGroupFunction() {}
394 SocketsUdpLeaveGroupFunction::~SocketsUdpLeaveGroupFunction() {}
396 bool SocketsUdpLeaveGroupFunction::Prepare() {
397 params_ = api::sockets_udp::LeaveGroup::Params::Create(*args_);
398 EXTENSION_FUNCTION_VALIDATE(params_.get());
399 return true;
402 void SocketsUdpLeaveGroupFunction::Work() {
403 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
404 if (!socket) {
405 error_ = kSocketNotFoundError;
406 return;
409 content::SocketPermissionRequest param(
410 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
411 kWildcardAddress,
412 kWildcardPort);
413 if (!SocketsManifestData::CheckRequest(extension(), param)) {
414 error_ = kPermissionError;
415 return;
418 int net_result = socket->LeaveGroup(params_->address);
419 if (net_result != net::OK)
420 error_ = net::ErrorToString(net_result);
421 results_ = sockets_udp::LeaveGroup::Results::Create(net_result);
424 SocketsUdpSetMulticastTimeToLiveFunction::
425 SocketsUdpSetMulticastTimeToLiveFunction() {}
427 SocketsUdpSetMulticastTimeToLiveFunction::
428 ~SocketsUdpSetMulticastTimeToLiveFunction() {}
430 bool SocketsUdpSetMulticastTimeToLiveFunction::Prepare() {
431 params_ = api::sockets_udp::SetMulticastTimeToLive::Params::Create(*args_);
432 EXTENSION_FUNCTION_VALIDATE(params_.get());
433 return true;
436 void SocketsUdpSetMulticastTimeToLiveFunction::Work() {
437 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
438 if (!socket) {
439 error_ = kSocketNotFoundError;
440 return;
443 int net_result = socket->SetMulticastTimeToLive(params_->ttl);
444 if (net_result != net::OK)
445 error_ = net::ErrorToString(net_result);
446 results_ = sockets_udp::SetMulticastTimeToLive::Results::Create(net_result);
449 SocketsUdpSetMulticastLoopbackModeFunction::
450 SocketsUdpSetMulticastLoopbackModeFunction() {}
452 SocketsUdpSetMulticastLoopbackModeFunction::
453 ~SocketsUdpSetMulticastLoopbackModeFunction() {}
455 bool SocketsUdpSetMulticastLoopbackModeFunction::Prepare() {
456 params_ = api::sockets_udp::SetMulticastLoopbackMode::Params::Create(*args_);
457 EXTENSION_FUNCTION_VALIDATE(params_.get());
458 return true;
461 void SocketsUdpSetMulticastLoopbackModeFunction::Work() {
462 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
463 if (!socket) {
464 error_ = kSocketNotFoundError;
465 return;
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);
474 SocketsUdpGetJoinedGroupsFunction::SocketsUdpGetJoinedGroupsFunction() {}
476 SocketsUdpGetJoinedGroupsFunction::~SocketsUdpGetJoinedGroupsFunction() {}
478 bool SocketsUdpGetJoinedGroupsFunction::Prepare() {
479 params_ = api::sockets_udp::GetJoinedGroups::Params::Create(*args_);
480 EXTENSION_FUNCTION_VALIDATE(params_.get());
481 return true;
484 void SocketsUdpGetJoinedGroupsFunction::Work() {
485 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
486 if (!socket) {
487 error_ = kSocketNotFoundError;
488 return;
491 content::SocketPermissionRequest param(
492 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
493 kWildcardAddress,
494 kWildcardPort);
495 if (!SocketsManifestData::CheckRequest(extension(), param)) {
496 error_ = kPermissionError;
497 return;
500 const std::vector<std::string>& groups = socket->GetJoinedGroups();
501 results_ = sockets_udp::GetJoinedGroups::Results::Create(groups);
504 SocketsUdpSetBroadcastFunction::SocketsUdpSetBroadcastFunction() {
507 SocketsUdpSetBroadcastFunction::~SocketsUdpSetBroadcastFunction() {
510 bool SocketsUdpSetBroadcastFunction::Prepare() {
511 params_ = api::sockets_udp::SetBroadcast::Params::Create(*args_);
512 EXTENSION_FUNCTION_VALIDATE(params_.get());
513 return true;
516 void SocketsUdpSetBroadcastFunction::Work() {
517 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
518 if (!socket) {
519 error_ = kSocketNotFoundError;
520 return;
523 int net_result = socket->SetBroadcast(params_->enabled);
524 if (net_result != net::OK) {
525 error_ = net::ErrorToString(net_result);
527 results_ = sockets_udp::SetBroadcast::Results::Create(net_result);
530 } // namespace api
531 } // namespace extensions