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. 4 5#include "chrome/browser/extensions/api/sockets_udp/sockets_udp_api.h" 6 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_manifest_data.h" 10#include "content/public/common/socket_permission_request.h" 11#include "net/base/net_errors.h" 12 13namespace extensions { 14namespace 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> 26 UDPSocketAsyncApiFunction::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> 39 UDPSocketExtensionWithDnsLookupFunction::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_ = api::sockets_udp::SetPaused::Params::Create(*args_); 141 EXTENSION_FUNCTION_VALIDATE(params_.get()); 142 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; 149} 150 151void SocketsUdpSetPausedFunction::Work() { 152 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id); 153 if (!socket) { 154 error_ = kSocketNotFoundError; 155 return; 156 } 157 158 if (socket->paused() != params_->paused) { 159 socket->set_paused(params_->paused); 160 if (socket->IsBound() && !params_->paused) { 161 socket_event_dispatcher_->OnSocketResume(extension_->id(), 162 params_->socket_id); 163 } 164 } 165 166 results_ = sockets_udp::SetPaused::Results::Create(); 167} 168 169SocketsUdpBindFunction::SocketsUdpBindFunction() 170 : socket_event_dispatcher_(NULL) { 171} 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(GetProfile()); 180 DCHECK(socket_event_dispatcher_) << "There is no socket event dispatcher. " 181 "If this assertion is failing during a test, then it is likely that " 182 "TestExtensionSystem is failing to provide an instance of " 183 "UDPSocketEventDispatcher."; 184 return socket_event_dispatcher_ != NULL; 185} 186 187void SocketsUdpBindFunction::Work() { 188 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id); 189 if (!socket) { 190 error_ = kSocketNotFoundError; 191 return; 192 } 193 194 content::SocketPermissionRequest param( 195 SocketPermissionRequest::UDP_BIND, 196 params_->address, 197 params_->port); 198 if (!SocketsManifestData::CheckRequest(GetExtension(), param)) { 199 error_ = kPermissionError; 200 return; 201 } 202 203 int net_result = socket->Bind(params_->address, params_->port); 204 if (net_result == net::OK) { 205 socket_event_dispatcher_->OnSocketBind(extension_->id(), 206 params_->socket_id); 207 } 208 209 if (net_result != net::OK) 210 error_ = net::ErrorToString(net_result); 211 results_ = sockets_udp::Bind::Results::Create(net_result); 212} 213 214SocketsUdpSendFunction::SocketsUdpSendFunction() 215 : io_buffer_size_(0) {} 216 217SocketsUdpSendFunction::~SocketsUdpSendFunction() {} 218 219bool SocketsUdpSendFunction::Prepare() { 220 params_ = sockets_udp::Send::Params::Create(*args_); 221 EXTENSION_FUNCTION_VALIDATE(params_.get()); 222 io_buffer_size_ = params_->data.size(); 223 io_buffer_ = new net::WrappedIOBuffer(params_->data.data()); 224 225 return true; 226} 227 228void SocketsUdpSendFunction::AsyncWorkStart() { 229 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id); 230 if (!socket) { 231 error_ = kSocketNotFoundError; 232 AsyncWorkCompleted(); 233 return; 234 } 235 236 content::SocketPermissionRequest param( 237 SocketPermissionRequest::UDP_SEND_TO, 238 params_->address, 239 params_->port); 240 if (!SocketsManifestData::CheckRequest(GetExtension(), param)) { 241 error_ = kPermissionError; 242 AsyncWorkCompleted(); 243 return; 244 } 245 246 StartDnsLookup(params_->address); 247} 248 249void SocketsUdpSendFunction::AfterDnsLookup(int lookup_result) { 250 if (lookup_result == net::OK) { 251 StartSendTo(); 252 } else { 253 SetSendResult(lookup_result, -1); 254 } 255} 256 257void SocketsUdpSendFunction::StartSendTo() { 258 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id); 259 if (!socket) { 260 error_ = kSocketNotFoundError; 261 AsyncWorkCompleted(); 262 return; 263 } 264 265 socket->SendTo(io_buffer_, io_buffer_size_, resolved_address_, params_->port, 266 base::Bind(&SocketsUdpSendFunction::OnCompleted, this)); 267} 268 269void SocketsUdpSendFunction::OnCompleted(int net_result) { 270 if (net_result >= net::OK) { 271 SetSendResult(net::OK, net_result); 272 } else { 273 SetSendResult(net_result, -1); 274 } 275} 276 277void SocketsUdpSendFunction::SetSendResult(int net_result, int bytes_sent) { 278 CHECK(net_result <= net::OK) << "Network status code must be < 0"; 279 280 sockets_udp::SendInfo send_info; 281 send_info.result_code = net_result; 282 if (net_result == net::OK) { 283 send_info.bytes_sent.reset(new int(bytes_sent)); 284 } 285 286 if (net_result != net::OK) 287 error_ = net::ErrorToString(net_result); 288 results_ = sockets_udp::Send::Results::Create(send_info); 289 AsyncWorkCompleted(); 290} 291 292SocketsUdpCloseFunction::SocketsUdpCloseFunction() {} 293 294SocketsUdpCloseFunction::~SocketsUdpCloseFunction() {} 295 296bool SocketsUdpCloseFunction::Prepare() { 297 params_ = sockets_udp::Close::Params::Create(*args_); 298 EXTENSION_FUNCTION_VALIDATE(params_.get()); 299 return true; 300} 301 302void SocketsUdpCloseFunction::Work() { 303 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id); 304 if (!socket) { 305 error_ = kSocketNotFoundError; 306 return; 307 } 308 309 socket->Disconnect(); 310 RemoveSocket(params_->socket_id); 311 results_ = sockets_udp::Close::Results::Create(); 312} 313 314SocketsUdpGetInfoFunction::SocketsUdpGetInfoFunction() {} 315 316SocketsUdpGetInfoFunction::~SocketsUdpGetInfoFunction() {} 317 318bool SocketsUdpGetInfoFunction::Prepare() { 319 params_ = sockets_udp::GetInfo::Params::Create(*args_); 320 EXTENSION_FUNCTION_VALIDATE(params_.get()); 321 return true; 322} 323 324void SocketsUdpGetInfoFunction::Work() { 325 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id); 326 if (!socket) { 327 error_ = kSocketNotFoundError; 328 return; 329 } 330 331 linked_ptr<sockets_udp::SocketInfo> socket_info = 332 CreateSocketInfo(params_->socket_id, socket); 333 results_ = sockets_udp::GetInfo::Results::Create(*socket_info); 334} 335 336SocketsUdpGetSocketsFunction::SocketsUdpGetSocketsFunction() {} 337 338SocketsUdpGetSocketsFunction::~SocketsUdpGetSocketsFunction() {} 339 340bool SocketsUdpGetSocketsFunction::Prepare() { 341 return true; 342} 343 344void SocketsUdpGetSocketsFunction::Work() { 345 std::vector<linked_ptr<sockets_udp::SocketInfo> > socket_infos; 346 base::hash_set<int>* resource_ids = GetSocketIds(); 347 if (resource_ids != NULL) { 348 for (base::hash_set<int>::iterator it = resource_ids->begin(); 349 it != resource_ids->end(); ++it) { 350 int socket_id = *it; 351 ResumableUDPSocket* socket = GetUdpSocket(socket_id); 352 if (socket) { 353 socket_infos.push_back(CreateSocketInfo(socket_id, socket)); 354 } 355 } 356 } 357 results_ = sockets_udp::GetSockets::Results::Create(socket_infos); 358} 359 360SocketsUdpJoinGroupFunction::SocketsUdpJoinGroupFunction() {} 361 362SocketsUdpJoinGroupFunction::~SocketsUdpJoinGroupFunction() {} 363 364bool SocketsUdpJoinGroupFunction::Prepare() { 365 params_ = sockets_udp::JoinGroup::Params::Create(*args_); 366 EXTENSION_FUNCTION_VALIDATE(params_.get()); 367 return true; 368} 369 370void SocketsUdpJoinGroupFunction::Work() { 371 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id); 372 if (!socket) { 373 error_ = kSocketNotFoundError; 374 return; 375 } 376 377 content::SocketPermissionRequest param( 378 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP, 379 kWildcardAddress, 380 kWildcardPort); 381 if (!SocketsManifestData::CheckRequest(GetExtension(), param)) { 382 error_ = kPermissionError; 383 return; 384 } 385 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); 390} 391 392SocketsUdpLeaveGroupFunction::SocketsUdpLeaveGroupFunction() {} 393 394SocketsUdpLeaveGroupFunction::~SocketsUdpLeaveGroupFunction() {} 395 396bool SocketsUdpLeaveGroupFunction::Prepare() { 397 params_ = api::sockets_udp::LeaveGroup::Params::Create(*args_); 398 EXTENSION_FUNCTION_VALIDATE(params_.get()); 399 return true; 400} 401 402void SocketsUdpLeaveGroupFunction::Work() { 403 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id); 404 if (!socket) { 405 error_ = kSocketNotFoundError; 406 return; 407 } 408 409 content::SocketPermissionRequest param( 410 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP, 411 kWildcardAddress, 412 kWildcardPort); 413 if (!SocketsManifestData::CheckRequest(GetExtension(), param)) { 414 error_ = kPermissionError; 415 return; 416 } 417 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); 422} 423 424SocketsUdpSetMulticastTimeToLiveFunction:: 425 SocketsUdpSetMulticastTimeToLiveFunction() {} 426 427SocketsUdpSetMulticastTimeToLiveFunction:: 428 ~SocketsUdpSetMulticastTimeToLiveFunction() {} 429 430bool SocketsUdpSetMulticastTimeToLiveFunction::Prepare() { 431 params_ = api::sockets_udp::SetMulticastTimeToLive::Params::Create(*args_); 432 EXTENSION_FUNCTION_VALIDATE(params_.get()); 433 return true; 434} 435 436void SocketsUdpSetMulticastTimeToLiveFunction::Work() { 437 ResumableUDPSocket* socket = GetUdpSocket(params_->socket_id); 438 if (!socket) { 439 error_ = kSocketNotFoundError; 440 return; 441 } 442 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); 447} 448 449SocketsUdpSetMulticastLoopbackModeFunction:: 450 SocketsUdpSetMulticastLoopbackModeFunction() {} 451 452SocketsUdpSetMulticastLoopbackModeFunction:: 453 ~SocketsUdpSetMulticastLoopbackModeFunction() {} 454 455bool SocketsUdpSetMulticastLoopbackModeFunction::Prepare() { 456 params_ = 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_ = 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(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 api 505} // namespace extensions 506