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 13namespace extensions { 14namespace core_api { 15 16using content::SocketPermissionRequest; 17 18const char kSocketNotFoundError[] = "Socket not found"; 19const char kPermissionError[] = "App does not have permission"; 20const char kWildcardAddress[] = "*"; 21const int kWildcardPort = 0; 22 23UDPSocketAsyncApiFunction::~UDPSocketAsyncApiFunction() {} 24 25scoped_ptr<SocketResourceManagerInterface> 26UDPSocketAsyncApiFunction::CreateSocketResourceManager() { 27 return scoped_ptr<SocketResourceManagerInterface>( 28 new SocketResourceManager<ResumableUDPSocket>()).Pass(); 29} 30 31ResumableUDPSocket* UDPSocketAsyncApiFunction::GetUdpSocket(int socket_id) { 32 return static_cast<ResumableUDPSocket*>(GetSocket(socket_id)); 33} 34 35UDPSocketExtensionWithDnsLookupFunction:: 36 ~UDPSocketExtensionWithDnsLookupFunction() {} 37 38scoped_ptr<SocketResourceManagerInterface> 39UDPSocketExtensionWithDnsLookupFunction::CreateSocketResourceManager() { 40 return scoped_ptr<SocketResourceManagerInterface>( 41 new SocketResourceManager<ResumableUDPSocket>()).Pass(); 42} 43 44ResumableUDPSocket* UDPSocketExtensionWithDnsLookupFunction::GetUdpSocket( 45 int socket_id) { 46 return static_cast<ResumableUDPSocket*>(GetSocket(socket_id)); 47} 48 49linked_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 77void 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 90SocketsUdpCreateFunction::SocketsUdpCreateFunction() {} 91 92SocketsUdpCreateFunction::~SocketsUdpCreateFunction() {} 93 94bool SocketsUdpCreateFunction::Prepare() { 95 params_ = sockets_udp::Create::Params::Create(*args_); 96 EXTENSION_FUNCTION_VALIDATE(params_.get()); 97 return true; 98} 99 100void 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 113SocketsUdpUpdateFunction::SocketsUdpUpdateFunction() {} 114 115SocketsUdpUpdateFunction::~SocketsUdpUpdateFunction() {} 116 117bool SocketsUdpUpdateFunction::Prepare() { 118 params_ = sockets_udp::Update::Params::Create(*args_); 119 EXTENSION_FUNCTION_VALIDATE(params_.get()); 120 return true; 121} 122 123void 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 134SocketsUdpSetPausedFunction::SocketsUdpSetPausedFunction() 135 : socket_event_dispatcher_(NULL) {} 136 137SocketsUdpSetPausedFunction::~SocketsUdpSetPausedFunction() {} 138 139bool 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 152void 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 170SocketsUdpBindFunction::SocketsUdpBindFunction() 171 : socket_event_dispatcher_(NULL) {} 172 173SocketsUdpBindFunction::~SocketsUdpBindFunction() {} 174 175bool 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 188void 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(extension(), 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 213SocketsUdpSendFunction::SocketsUdpSendFunction() : io_buffer_size_(0) {} 214 215SocketsUdpSendFunction::~SocketsUdpSendFunction() {} 216 217bool 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 226void 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(extension(), param)) { 237 error_ = kPermissionError; 238 AsyncWorkCompleted(); 239 return; 240 } 241 242 StartDnsLookup(params_->address); 243} 244 245void SocketsUdpSendFunction::AfterDnsLookup(int lookup_result) { 246 if (lookup_result == net::OK) { 247 StartSendTo(); 248 } else { 249 SetSendResult(lookup_result, -1); 250 } 251} 252 253void 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 268void 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 276void 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 291SocketsUdpCloseFunction::SocketsUdpCloseFunction() {} 292 293SocketsUdpCloseFunction::~SocketsUdpCloseFunction() {} 294 295bool SocketsUdpCloseFunction::Prepare() { 296 params_ = sockets_udp::Close::Params::Create(*args_); 297 EXTENSION_FUNCTION_VALIDATE(params_.get()); 298 return true; 299} 300 301void 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 313SocketsUdpGetInfoFunction::SocketsUdpGetInfoFunction() {} 314 315SocketsUdpGetInfoFunction::~SocketsUdpGetInfoFunction() {} 316 317bool SocketsUdpGetInfoFunction::Prepare() { 318 params_ = sockets_udp::GetInfo::Params::Create(*args_); 319 EXTENSION_FUNCTION_VALIDATE(params_.get()); 320 return true; 321} 322 323void 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 335SocketsUdpGetSocketsFunction::SocketsUdpGetSocketsFunction() {} 336 337SocketsUdpGetSocketsFunction::~SocketsUdpGetSocketsFunction() {} 338 339bool SocketsUdpGetSocketsFunction::Prepare() { return true; } 340 341void 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 358SocketsUdpJoinGroupFunction::SocketsUdpJoinGroupFunction() {} 359 360SocketsUdpJoinGroupFunction::~SocketsUdpJoinGroupFunction() {} 361 362bool SocketsUdpJoinGroupFunction::Prepare() { 363 params_ = sockets_udp::JoinGroup::Params::Create(*args_); 364 EXTENSION_FUNCTION_VALIDATE(params_.get()); 365 return true; 366} 367 368void 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(extension(), 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 390SocketsUdpLeaveGroupFunction::SocketsUdpLeaveGroupFunction() {} 391 392SocketsUdpLeaveGroupFunction::~SocketsUdpLeaveGroupFunction() {} 393 394bool SocketsUdpLeaveGroupFunction::Prepare() { 395 params_ = core_api::sockets_udp::LeaveGroup::Params::Create(*args_); 396 EXTENSION_FUNCTION_VALIDATE(params_.get()); 397 return true; 398} 399 400void 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(extension(), 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 422SocketsUdpSetMulticastTimeToLiveFunction:: 423 SocketsUdpSetMulticastTimeToLiveFunction() {} 424 425SocketsUdpSetMulticastTimeToLiveFunction:: 426 ~SocketsUdpSetMulticastTimeToLiveFunction() {} 427 428bool SocketsUdpSetMulticastTimeToLiveFunction::Prepare() { 429 params_ = 430 core_api::sockets_udp::SetMulticastTimeToLive::Params::Create(*args_); 431 EXTENSION_FUNCTION_VALIDATE(params_.get()); 432 return true; 433} 434 435void 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 448SocketsUdpSetMulticastLoopbackModeFunction:: 449 SocketsUdpSetMulticastLoopbackModeFunction() {} 450 451SocketsUdpSetMulticastLoopbackModeFunction:: 452 ~SocketsUdpSetMulticastLoopbackModeFunction() {} 453 454bool SocketsUdpSetMulticastLoopbackModeFunction::Prepare() { 455 params_ = 456 core_api::sockets_udp::SetMulticastLoopbackMode::Params::Create(*args_); 457 EXTENSION_FUNCTION_VALIDATE(params_.get()); 458 return true; 459} 460 461void 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 474SocketsUdpGetJoinedGroupsFunction::SocketsUdpGetJoinedGroupsFunction() {} 475 476SocketsUdpGetJoinedGroupsFunction::~SocketsUdpGetJoinedGroupsFunction() {} 477 478bool SocketsUdpGetJoinedGroupsFunction::Prepare() { 479 params_ = core_api::sockets_udp::GetJoinedGroups::Params::Create(*args_); 480 EXTENSION_FUNCTION_VALIDATE(params_.get()); 481 return true; 482} 483 484void 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(extension(), 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