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 23 UDPSocketAsyncApiFunction::~UDPSocketAsyncApiFunction() {} 24 25 scoped_ptr<SocketResourceManagerInterface> 26 UDPSocketAsyncApiFunction::CreateSocketResourceManager() { 27 return scoped_ptr<SocketResourceManagerInterface>( 28 new SocketResourceManager<ResumableUDPSocket>()).Pass(); 29 } 30 31 ResumableUDPSocket* UDPSocketAsyncApiFunction::GetUdpSocket(int socket_id) { 32 return static_cast<ResumableUDPSocket*>(GetSocket(socket_id)); 33 } 34 35 UDPSocketExtensionWithDnsLookupFunction:: 36 ~UDPSocketExtensionWithDnsLookupFunction() {} 37 38 scoped_ptr<SocketResourceManagerInterface> 39 UDPSocketExtensionWithDnsLookupFunction::CreateSocketResourceManager() { 40 return scoped_ptr<SocketResourceManagerInterface>( 41 new SocketResourceManager<ResumableUDPSocket>()).Pass(); 42 } 43 44 ResumableUDPSocket* UDPSocketExtensionWithDnsLookupFunction::GetUdpSocket( 45 int socket_id) { 46 return static_cast<ResumableUDPSocket*>(GetSocket(socket_id)); 47 } 48 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 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 90 SocketsUdpCreateFunction::SocketsUdpCreateFunction() {} 91 92 SocketsUdpCreateFunction::~SocketsUdpCreateFunction() {} 93 94 bool SocketsUdpCreateFunction::Prepare() { 95 params_ = sockets_udp::Create::Params::Create(*args_); 96 EXTENSION_FUNCTION_VALIDATE(params_.get()); 97 return true; 98 } 99 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 113 SocketsUdpUpdateFunction::SocketsUdpUpdateFunction() {} 114 115 SocketsUdpUpdateFunction::~SocketsUdpUpdateFunction() {} 116 117 bool SocketsUdpUpdateFunction::Prepare() { 118 params_ = sockets_udp::Update::Params::Create(*args_); 119 EXTENSION_FUNCTION_VALIDATE(params_.get()); 120 return true; 121 } 122 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 134 SocketsUdpSetPausedFunction::SocketsUdpSetPausedFunction() 135 : socket_event_dispatcher_(NULL) {} 136 137 SocketsUdpSetPausedFunction::~SocketsUdpSetPausedFunction() {} 138 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 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 170 SocketsUdpBindFunction::SocketsUdpBindFunction() 171 : socket_event_dispatcher_(NULL) {} 172 173 SocketsUdpBindFunction::~SocketsUdpBindFunction() {} 174 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 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(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 213 SocketsUdpSendFunction::SocketsUdpSendFunction() : io_buffer_size_(0) {} 214 215 SocketsUdpSendFunction::~SocketsUdpSendFunction() {} 216 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 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(extension(), param)) { 237 error_ = kPermissionError; 238 AsyncWorkCompleted(); 239 return; 240 } 241 242 StartDnsLookup(params_->address); 243 } 244 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 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 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 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 291 SocketsUdpCloseFunction::SocketsUdpCloseFunction() {} 292 293 SocketsUdpCloseFunction::~SocketsUdpCloseFunction() {} 294 295 bool SocketsUdpCloseFunction::Prepare() { 296 params_ = sockets_udp::Close::Params::Create(*args_); 297 EXTENSION_FUNCTION_VALIDATE(params_.get()); 298 return true; 299 } 300 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 313 SocketsUdpGetInfoFunction::SocketsUdpGetInfoFunction() {} 314 315 SocketsUdpGetInfoFunction::~SocketsUdpGetInfoFunction() {} 316 317 bool SocketsUdpGetInfoFunction::Prepare() { 318 params_ = sockets_udp::GetInfo::Params::Create(*args_); 319 EXTENSION_FUNCTION_VALIDATE(params_.get()); 320 return true; 321 } 322 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 335 SocketsUdpGetSocketsFunction::SocketsUdpGetSocketsFunction() {} 336 337 SocketsUdpGetSocketsFunction::~SocketsUdpGetSocketsFunction() {} 338 339 bool SocketsUdpGetSocketsFunction::Prepare() { return true; } 340 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 358 SocketsUdpJoinGroupFunction::SocketsUdpJoinGroupFunction() {} 359 360 SocketsUdpJoinGroupFunction::~SocketsUdpJoinGroupFunction() {} 361 362 bool SocketsUdpJoinGroupFunction::Prepare() { 363 params_ = sockets_udp::JoinGroup::Params::Create(*args_); 364 EXTENSION_FUNCTION_VALIDATE(params_.get()); 365 return true; 366 } 367 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(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 390 SocketsUdpLeaveGroupFunction::SocketsUdpLeaveGroupFunction() {} 391 392 SocketsUdpLeaveGroupFunction::~SocketsUdpLeaveGroupFunction() {} 393 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 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(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 422 SocketsUdpSetMulticastTimeToLiveFunction:: 423 SocketsUdpSetMulticastTimeToLiveFunction() {} 424 425 SocketsUdpSetMulticastTimeToLiveFunction:: 426 ~SocketsUdpSetMulticastTimeToLiveFunction() {} 427 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 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:: 449 SocketsUdpSetMulticastLoopbackModeFunction() {} 450 451 SocketsUdpSetMulticastLoopbackModeFunction:: 452 ~SocketsUdpSetMulticastLoopbackModeFunction() {} 453 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 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 474 SocketsUdpGetJoinedGroupsFunction::SocketsUdpGetJoinedGroupsFunction() {} 475 476 SocketsUdpGetJoinedGroupsFunction::~SocketsUdpGetJoinedGroupsFunction() {} 477 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 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(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