1 // Copyright 2013 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 "chrome/browser/extensions/api/sockets_udp/sockets_udp_api.h"
7 #include "chrome/browser/extensions/api/socket/udp_socket.h"
8 #include "chrome/browser/extensions/api/sockets_udp/udp_socket_event_dispatcher.h"
9 #include "chrome/common/extensions/api/sockets/sockets_handler.h"
10 #include "content/public/common/socket_permission_request.h"
11 #include "net/base/net_errors.h"
13 namespace extensions {
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(
46 return static_cast<ResumableUDPSocket*>(GetSocket(socket_id));
49 linked_ptr<sockets_udp::SocketInfo> CreateSocketInfo(
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
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()));
65 // Grab the local address as known by the OS.
66 net::IPEndPoint localAddress;
67 if (socket->GetLocalAddress(&localAddress)) {
68 socket_info->local_address.reset(
69 new std::string(localAddress.ToStringWithoutPort()));
70 socket_info->local_port.reset(new int(localAddress.port()));
76 void SetSocketProperties(ResumableUDPSocket* socket,
77 sockets_udp::SocketProperties* properties) {
78 if (properties->name.get()) {
79 socket->set_name(*properties->name.get());
81 if (properties->persistent.get()) {
82 socket->set_persistent(*properties->persistent.get());
84 if (properties->buffer_size.get()) {
85 socket->set_buffer_size(*properties->buffer_size.get());
89 SocketsUdpCreateFunction::SocketsUdpCreateFunction() {}
91 SocketsUdpCreateFunction::~SocketsUdpCreateFunction() {}
93 bool SocketsUdpCreateFunction::Prepare() {
94 params_ = sockets_udp::Create::Params::Create(*args_);
95 EXTENSION_FUNCTION_VALIDATE(params_.get());
99 void SocketsUdpCreateFunction::Work() {
100 ResumableUDPSocket* socket = new ResumableUDPSocket(extension_->id());
102 sockets_udp::SocketProperties* properties = params_.get()->properties.get();
104 SetSocketProperties(socket, properties);
107 sockets_udp::CreateInfo create_info;
108 create_info.socket_id = AddSocket(socket);
109 results_ = sockets_udp::Create::Results::Create(create_info);
112 SocketsUdpUpdateFunction::SocketsUdpUpdateFunction() {}
114 SocketsUdpUpdateFunction::~SocketsUdpUpdateFunction() {}
116 bool SocketsUdpUpdateFunction::Prepare() {
117 params_ = sockets_udp::Update::Params::Create(*args_);
118 EXTENSION_FUNCTION_VALIDATE(params_.get());
122 void SocketsUdpUpdateFunction::Work() {
123 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
125 error_ = kSocketNotFoundError;
129 SetSocketProperties(socket, ¶ms_.get()->properties);
130 results_ = sockets_udp::Update::Results::Create();
133 SocketsUdpBindFunction::SocketsUdpBindFunction()
134 : socket_event_dispatcher_(NULL) {
137 SocketsUdpBindFunction::~SocketsUdpBindFunction() {}
139 bool SocketsUdpBindFunction::Prepare() {
140 params_ = sockets_udp::Bind::Params::Create(*args_);
141 EXTENSION_FUNCTION_VALIDATE(params_.get());
143 socket_event_dispatcher_ = UDPSocketEventDispatcher::Get(GetProfile());
144 DCHECK(socket_event_dispatcher_) << "There is no socket event dispatcher. "
145 "If this assertion is failing during a test, then it is likely that "
146 "TestExtensionSystem is failing to provide an instance of "
147 "UDPSocketEventDispatcher.";
148 return socket_event_dispatcher_ != NULL;
151 void SocketsUdpBindFunction::Work() {
152 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
154 error_ = kSocketNotFoundError;
158 content::SocketPermissionRequest param(
159 SocketPermissionRequest::UDP_BIND,
162 if (!SocketsManifestData::CheckRequest(GetExtension(), param)) {
163 error_ = kPermissionError;
167 int net_result = socket->Bind(params_->address, params_->port);
168 if (net_result == net::OK) {
169 socket_event_dispatcher_->OnSocketBind(extension_->id(),
173 if (net_result != net::OK)
174 error_ = net::ErrorToString(net_result);
175 results_ = sockets_udp::Bind::Results::Create(net_result);
178 SocketsUdpSendFunction::SocketsUdpSendFunction()
179 : io_buffer_size_(0) {}
181 SocketsUdpSendFunction::~SocketsUdpSendFunction() {}
183 bool SocketsUdpSendFunction::Prepare() {
184 params_ = sockets_udp::Send::Params::Create(*args_);
185 EXTENSION_FUNCTION_VALIDATE(params_.get());
186 io_buffer_size_ = params_->data.size();
187 io_buffer_ = new net::WrappedIOBuffer(params_->data.data());
191 void SocketsUdpSendFunction::AsyncWorkStart() {
192 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
194 error_ = kSocketNotFoundError;
195 AsyncWorkCompleted();
199 content::SocketPermissionRequest param(
200 SocketPermissionRequest::UDP_SEND_TO,
203 if (!SocketsManifestData::CheckRequest(GetExtension(), param)) {
204 error_ = kPermissionError;
205 AsyncWorkCompleted();
209 StartDnsLookup(params_->address);
212 void SocketsUdpSendFunction::AfterDnsLookup(int lookup_result) {
213 if (lookup_result == net::OK) {
216 SetSendResult(lookup_result, -1);
220 void SocketsUdpSendFunction::StartSendTo() {
221 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
223 error_ = kSocketNotFoundError;
224 AsyncWorkCompleted();
228 socket->SendTo(io_buffer_, io_buffer_size_, resolved_address_, params_->port,
229 base::Bind(&SocketsUdpSendFunction::OnCompleted, this));
232 void SocketsUdpSendFunction::OnCompleted(int net_result) {
233 if (net_result >= net::OK) {
234 SetSendResult(net::OK, net_result);
236 SetSendResult(net_result, -1);
240 void SocketsUdpSendFunction::SetSendResult(int net_result, int bytes_sent) {
241 CHECK(net_result <= net::OK) << "Network status code must be < 0";
243 sockets_udp::SendInfo send_info;
244 send_info.result_code = net_result;
245 if (net_result == net::OK) {
246 send_info.bytes_sent.reset(new int(bytes_sent));
249 if (net_result != net::OK)
250 error_ = net::ErrorToString(net_result);
251 results_ = sockets_udp::Send::Results::Create(send_info);
252 AsyncWorkCompleted();
255 SocketsUdpCloseFunction::SocketsUdpCloseFunction() {}
257 SocketsUdpCloseFunction::~SocketsUdpCloseFunction() {}
259 bool SocketsUdpCloseFunction::Prepare() {
260 params_ = sockets_udp::Close::Params::Create(*args_);
261 EXTENSION_FUNCTION_VALIDATE(params_.get());
265 void SocketsUdpCloseFunction::Work() {
266 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
268 error_ = kSocketNotFoundError;
272 RemoveSocket(params_->socket_id);
273 results_ = sockets_udp::Close::Results::Create();
276 SocketsUdpGetInfoFunction::SocketsUdpGetInfoFunction() {}
278 SocketsUdpGetInfoFunction::~SocketsUdpGetInfoFunction() {}
280 bool SocketsUdpGetInfoFunction::Prepare() {
281 params_ = sockets_udp::GetInfo::Params::Create(*args_);
282 EXTENSION_FUNCTION_VALIDATE(params_.get());
286 void SocketsUdpGetInfoFunction::Work() {
287 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
289 error_ = kSocketNotFoundError;
293 linked_ptr<sockets_udp::SocketInfo> socket_info =
294 CreateSocketInfo(params_->socket_id, socket);
295 results_ = sockets_udp::GetInfo::Results::Create(*socket_info);
298 SocketsUdpGetSocketsFunction::SocketsUdpGetSocketsFunction() {}
300 SocketsUdpGetSocketsFunction::~SocketsUdpGetSocketsFunction() {}
302 bool SocketsUdpGetSocketsFunction::Prepare() {
306 void SocketsUdpGetSocketsFunction::Work() {
307 std::vector<linked_ptr<sockets_udp::SocketInfo> > socket_infos;
308 base::hash_set<int>* resource_ids = GetSocketIds();
309 if (resource_ids != NULL) {
310 for (base::hash_set<int>::iterator it = resource_ids->begin();
311 it != resource_ids->end(); ++it) {
313 ResumableUDPSocket* socket = GetUdpSocket(socket_id);
315 socket_infos.push_back(CreateSocketInfo(socket_id, socket));
319 results_ = sockets_udp::GetSockets::Results::Create(socket_infos);
322 SocketsUdpJoinGroupFunction::SocketsUdpJoinGroupFunction() {}
324 SocketsUdpJoinGroupFunction::~SocketsUdpJoinGroupFunction() {}
326 bool SocketsUdpJoinGroupFunction::Prepare() {
327 params_ = sockets_udp::JoinGroup::Params::Create(*args_);
328 EXTENSION_FUNCTION_VALIDATE(params_.get());
332 void SocketsUdpJoinGroupFunction::Work() {
333 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
335 error_ = kSocketNotFoundError;
339 content::SocketPermissionRequest param(
340 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
343 if (!SocketsManifestData::CheckRequest(GetExtension(), param)) {
344 error_ = kPermissionError;
348 int net_result = socket->JoinGroup(params_->address);
349 if (net_result != net::OK)
350 error_ = net::ErrorToString(net_result);
351 results_ = sockets_udp::JoinGroup::Results::Create(net_result);
354 SocketsUdpLeaveGroupFunction::SocketsUdpLeaveGroupFunction() {}
356 SocketsUdpLeaveGroupFunction::~SocketsUdpLeaveGroupFunction() {}
358 bool SocketsUdpLeaveGroupFunction::Prepare() {
359 params_ = api::sockets_udp::LeaveGroup::Params::Create(*args_);
360 EXTENSION_FUNCTION_VALIDATE(params_.get());
364 void SocketsUdpLeaveGroupFunction::Work() {
365 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
367 error_ = kSocketNotFoundError;
371 content::SocketPermissionRequest param(
372 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
375 if (!SocketsManifestData::CheckRequest(GetExtension(), param)) {
376 error_ = kPermissionError;
380 int net_result = socket->LeaveGroup(params_->address);
381 if (net_result != net::OK)
382 error_ = net::ErrorToString(net_result);
383 results_ = sockets_udp::LeaveGroup::Results::Create(net_result);
386 SocketsUdpSetMulticastTimeToLiveFunction::
387 SocketsUdpSetMulticastTimeToLiveFunction() {}
389 SocketsUdpSetMulticastTimeToLiveFunction::
390 ~SocketsUdpSetMulticastTimeToLiveFunction() {}
392 bool SocketsUdpSetMulticastTimeToLiveFunction::Prepare() {
393 params_ = api::sockets_udp::SetMulticastTimeToLive::Params::Create(*args_);
394 EXTENSION_FUNCTION_VALIDATE(params_.get());
398 void SocketsUdpSetMulticastTimeToLiveFunction::Work() {
399 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
401 error_ = kSocketNotFoundError;
405 int net_result = socket->SetMulticastTimeToLive(params_->ttl);
406 if (net_result != net::OK)
407 error_ = net::ErrorToString(net_result);
408 results_ = sockets_udp::SetMulticastTimeToLive::Results::Create(net_result);
411 SocketsUdpSetMulticastLoopbackModeFunction::
412 SocketsUdpSetMulticastLoopbackModeFunction() {}
414 SocketsUdpSetMulticastLoopbackModeFunction::
415 ~SocketsUdpSetMulticastLoopbackModeFunction() {}
417 bool SocketsUdpSetMulticastLoopbackModeFunction::Prepare() {
418 params_ = api::sockets_udp::SetMulticastLoopbackMode::Params::Create(*args_);
419 EXTENSION_FUNCTION_VALIDATE(params_.get());
423 void SocketsUdpSetMulticastLoopbackModeFunction::Work() {
424 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
426 error_ = kSocketNotFoundError;
430 int net_result = socket->SetMulticastLoopbackMode(params_->enabled);
431 if (net_result != net::OK)
432 error_ = net::ErrorToString(net_result);
433 results_ = sockets_udp::SetMulticastLoopbackMode::Results::Create(net_result);
436 SocketsUdpGetJoinedGroupsFunction::SocketsUdpGetJoinedGroupsFunction() {}
438 SocketsUdpGetJoinedGroupsFunction::~SocketsUdpGetJoinedGroupsFunction() {}
440 bool SocketsUdpGetJoinedGroupsFunction::Prepare() {
441 params_ = api::sockets_udp::GetJoinedGroups::Params::Create(*args_);
442 EXTENSION_FUNCTION_VALIDATE(params_.get());
446 void SocketsUdpGetJoinedGroupsFunction::Work() {
447 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id);
449 error_ = kSocketNotFoundError;
453 content::SocketPermissionRequest param(
454 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP,
457 if (!SocketsManifestData::CheckRequest(GetExtension(), param)) {
458 error_ = kPermissionError;
462 const std::vector<std::string>& groups = socket->GetJoinedGroups();
463 results_ = sockets_udp::GetJoinedGroups::Results::Create(groups);
467 } // namespace extensions