| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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/socket/socket_api.h" | |
| 6 | |
| 7 #include <vector> | |
| 8 | |
| 9 #include "base/bind.h" | |
| 10 #include "base/containers/hash_tables.h" | |
| 11 #include "chrome/browser/extensions/api/dns/host_resolver_wrapper.h" | |
| 12 #include "chrome/browser/extensions/api/socket/socket.h" | |
| 13 #include "chrome/browser/extensions/api/socket/tcp_socket.h" | |
| 14 #include "chrome/browser/extensions/api/socket/udp_socket.h" | |
| 15 #include "chrome/common/extensions/permissions/socket_permission.h" | |
| 16 #include "content/public/browser/browser_context.h" | |
| 17 #include "content/public/browser/resource_context.h" | |
| 18 #include "extensions/browser/extension_system.h" | |
| 19 #include "extensions/common/extension.h" | |
| 20 #include "extensions/common/permissions/permissions_data.h" | |
| 21 #include "net/base/host_port_pair.h" | |
| 22 #include "net/base/io_buffer.h" | |
| 23 #include "net/base/ip_endpoint.h" | |
| 24 #include "net/base/net_errors.h" | |
| 25 #include "net/base/net_log.h" | |
| 26 #include "net/base/net_util.h" | |
| 27 | |
| 28 namespace extensions { | |
| 29 | |
| 30 using content::SocketPermissionRequest; | |
| 31 | |
| 32 const char kAddressKey[] = "address"; | |
| 33 const char kPortKey[] = "port"; | |
| 34 const char kBytesWrittenKey[] = "bytesWritten"; | |
| 35 const char kDataKey[] = "data"; | |
| 36 const char kResultCodeKey[] = "resultCode"; | |
| 37 const char kSocketIdKey[] = "socketId"; | |
| 38 | |
| 39 const char kSocketNotFoundError[] = "Socket not found"; | |
| 40 const char kDnsLookupFailedError[] = "DNS resolution failed"; | |
| 41 const char kPermissionError[] = "App does not have permission"; | |
| 42 const char kNetworkListError[] = "Network lookup failed or unsupported"; | |
| 43 const char kTCPSocketBindError[] = | |
| 44 "TCP socket does not support bind. For TCP server please use listen."; | |
| 45 const char kMulticastSocketTypeError[] = | |
| 46 "Only UDP socket supports multicast."; | |
| 47 const char kWildcardAddress[] = "*"; | |
| 48 const int kWildcardPort = 0; | |
| 49 | |
| 50 SocketAsyncApiFunction::SocketAsyncApiFunction() { | |
| 51 } | |
| 52 | |
| 53 SocketAsyncApiFunction::~SocketAsyncApiFunction() { | |
| 54 } | |
| 55 | |
| 56 bool SocketAsyncApiFunction::PrePrepare() { | |
| 57 manager_ = CreateSocketResourceManager(); | |
| 58 return manager_->SetBrowserContext(browser_context()); | |
| 59 } | |
| 60 | |
| 61 bool SocketAsyncApiFunction::Respond() { | |
| 62 return error_.empty(); | |
| 63 } | |
| 64 | |
| 65 scoped_ptr<SocketResourceManagerInterface> | |
| 66 SocketAsyncApiFunction::CreateSocketResourceManager() { | |
| 67 return scoped_ptr<SocketResourceManagerInterface>( | |
| 68 new SocketResourceManager<Socket>()).Pass(); | |
| 69 } | |
| 70 | |
| 71 int SocketAsyncApiFunction::AddSocket(Socket* socket) { | |
| 72 return manager_->Add(socket); | |
| 73 } | |
| 74 | |
| 75 Socket* SocketAsyncApiFunction::GetSocket(int api_resource_id) { | |
| 76 return manager_->Get(extension_->id(), api_resource_id); | |
| 77 } | |
| 78 | |
| 79 base::hash_set<int>* SocketAsyncApiFunction::GetSocketIds() { | |
| 80 return manager_->GetResourceIds(extension_->id()); | |
| 81 } | |
| 82 | |
| 83 void SocketAsyncApiFunction::RemoveSocket(int api_resource_id) { | |
| 84 manager_->Remove(extension_->id(), api_resource_id); | |
| 85 } | |
| 86 | |
| 87 SocketExtensionWithDnsLookupFunction::SocketExtensionWithDnsLookupFunction() | |
| 88 : resource_context_(NULL), | |
| 89 request_handle_(new net::HostResolver::RequestHandle), | |
| 90 addresses_(new net::AddressList) {} | |
| 91 | |
| 92 SocketExtensionWithDnsLookupFunction::~SocketExtensionWithDnsLookupFunction() { | |
| 93 } | |
| 94 | |
| 95 bool SocketExtensionWithDnsLookupFunction::PrePrepare() { | |
| 96 if (!SocketAsyncApiFunction::PrePrepare()) | |
| 97 return false; | |
| 98 resource_context_ = browser_context()->GetResourceContext(); | |
| 99 return resource_context_ != NULL; | |
| 100 } | |
| 101 | |
| 102 void SocketExtensionWithDnsLookupFunction::StartDnsLookup( | |
| 103 const std::string& hostname) { | |
| 104 net::HostResolver* host_resolver = | |
| 105 extensions::HostResolverWrapper::GetInstance()->GetHostResolver( | |
| 106 resource_context_->GetHostResolver()); | |
| 107 DCHECK(host_resolver); | |
| 108 | |
| 109 // Yes, we are passing zero as the port. There are some interesting but not | |
| 110 // presently relevant reasons why HostResolver asks for the port of the | |
| 111 // hostname you'd like to resolve, even though it doesn't use that value in | |
| 112 // determining its answer. | |
| 113 net::HostPortPair host_port_pair(hostname, 0); | |
| 114 | |
| 115 net::HostResolver::RequestInfo request_info(host_port_pair); | |
| 116 int resolve_result = host_resolver->Resolve( | |
| 117 request_info, | |
| 118 net::DEFAULT_PRIORITY, | |
| 119 addresses_.get(), | |
| 120 base::Bind(&SocketExtensionWithDnsLookupFunction::OnDnsLookup, this), | |
| 121 request_handle_.get(), | |
| 122 net::BoundNetLog()); | |
| 123 | |
| 124 if (resolve_result != net::ERR_IO_PENDING) | |
| 125 OnDnsLookup(resolve_result); | |
| 126 } | |
| 127 | |
| 128 void SocketExtensionWithDnsLookupFunction::OnDnsLookup(int resolve_result) { | |
| 129 if (resolve_result == net::OK) { | |
| 130 DCHECK(!addresses_->empty()); | |
| 131 resolved_address_ = addresses_->front().ToStringWithoutPort(); | |
| 132 } else { | |
| 133 error_ = kDnsLookupFailedError; | |
| 134 } | |
| 135 AfterDnsLookup(resolve_result); | |
| 136 } | |
| 137 | |
| 138 SocketCreateFunction::SocketCreateFunction() | |
| 139 : socket_type_(kSocketTypeInvalid) { | |
| 140 } | |
| 141 | |
| 142 SocketCreateFunction::~SocketCreateFunction() {} | |
| 143 | |
| 144 bool SocketCreateFunction::Prepare() { | |
| 145 params_ = api::socket::Create::Params::Create(*args_); | |
| 146 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
| 147 | |
| 148 switch (params_->type) { | |
| 149 case extensions::api::socket::SOCKET_TYPE_TCP: | |
| 150 socket_type_ = kSocketTypeTCP; | |
| 151 break; | |
| 152 case extensions::api::socket::SOCKET_TYPE_UDP: | |
| 153 socket_type_ = kSocketTypeUDP; | |
| 154 break; | |
| 155 case extensions::api::socket::SOCKET_TYPE_NONE: | |
| 156 NOTREACHED(); | |
| 157 break; | |
| 158 } | |
| 159 | |
| 160 return true; | |
| 161 } | |
| 162 | |
| 163 void SocketCreateFunction::Work() { | |
| 164 Socket* socket = NULL; | |
| 165 if (socket_type_ == kSocketTypeTCP) { | |
| 166 socket = new TCPSocket(extension_->id()); | |
| 167 } else if (socket_type_== kSocketTypeUDP) { | |
| 168 socket = new UDPSocket(extension_->id()); | |
| 169 } | |
| 170 DCHECK(socket); | |
| 171 | |
| 172 base::DictionaryValue* result = new base::DictionaryValue(); | |
| 173 result->SetInteger(kSocketIdKey, AddSocket(socket)); | |
| 174 SetResult(result); | |
| 175 } | |
| 176 | |
| 177 bool SocketDestroyFunction::Prepare() { | |
| 178 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_)); | |
| 179 return true; | |
| 180 } | |
| 181 | |
| 182 void SocketDestroyFunction::Work() { | |
| 183 RemoveSocket(socket_id_); | |
| 184 } | |
| 185 | |
| 186 SocketConnectFunction::SocketConnectFunction() | |
| 187 : socket_id_(0), | |
| 188 hostname_(), | |
| 189 port_(0), | |
| 190 socket_(NULL) { | |
| 191 } | |
| 192 | |
| 193 SocketConnectFunction::~SocketConnectFunction() { | |
| 194 } | |
| 195 | |
| 196 bool SocketConnectFunction::Prepare() { | |
| 197 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_)); | |
| 198 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &hostname_)); | |
| 199 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(2, &port_)); | |
| 200 return true; | |
| 201 } | |
| 202 | |
| 203 void SocketConnectFunction::AsyncWorkStart() { | |
| 204 socket_ = GetSocket(socket_id_); | |
| 205 if (!socket_) { | |
| 206 error_ = kSocketNotFoundError; | |
| 207 SetResult(new base::FundamentalValue(-1)); | |
| 208 AsyncWorkCompleted(); | |
| 209 return; | |
| 210 } | |
| 211 | |
| 212 SocketPermissionRequest::OperationType operation_type; | |
| 213 switch (socket_->GetSocketType()) { | |
| 214 case Socket::TYPE_TCP: | |
| 215 operation_type = SocketPermissionRequest::TCP_CONNECT; | |
| 216 break; | |
| 217 case Socket::TYPE_UDP: | |
| 218 operation_type = SocketPermissionRequest::UDP_SEND_TO; | |
| 219 break; | |
| 220 default: | |
| 221 NOTREACHED() << "Unknown socket type."; | |
| 222 operation_type = SocketPermissionRequest::NONE; | |
| 223 break; | |
| 224 } | |
| 225 | |
| 226 SocketPermission::CheckParam param(operation_type, hostname_, port_); | |
| 227 if (!PermissionsData::CheckAPIPermissionWithParam( | |
| 228 GetExtension(), APIPermission::kSocket, ¶m)) { | |
| 229 error_ = kPermissionError; | |
| 230 SetResult(new base::FundamentalValue(-1)); | |
| 231 AsyncWorkCompleted(); | |
| 232 return; | |
| 233 } | |
| 234 | |
| 235 StartDnsLookup(hostname_); | |
| 236 } | |
| 237 | |
| 238 void SocketConnectFunction::AfterDnsLookup(int lookup_result) { | |
| 239 if (lookup_result == net::OK) { | |
| 240 StartConnect(); | |
| 241 } else { | |
| 242 SetResult(new base::FundamentalValue(lookup_result)); | |
| 243 AsyncWorkCompleted(); | |
| 244 } | |
| 245 } | |
| 246 | |
| 247 void SocketConnectFunction::StartConnect() { | |
| 248 socket_->Connect(resolved_address_, port_, | |
| 249 base::Bind(&SocketConnectFunction::OnConnect, this)); | |
| 250 } | |
| 251 | |
| 252 void SocketConnectFunction::OnConnect(int result) { | |
| 253 SetResult(new base::FundamentalValue(result)); | |
| 254 AsyncWorkCompleted(); | |
| 255 } | |
| 256 | |
| 257 bool SocketDisconnectFunction::Prepare() { | |
| 258 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_)); | |
| 259 return true; | |
| 260 } | |
| 261 | |
| 262 void SocketDisconnectFunction::Work() { | |
| 263 Socket* socket = GetSocket(socket_id_); | |
| 264 if (socket) | |
| 265 socket->Disconnect(); | |
| 266 else | |
| 267 error_ = kSocketNotFoundError; | |
| 268 SetResult(base::Value::CreateNullValue()); | |
| 269 } | |
| 270 | |
| 271 bool SocketBindFunction::Prepare() { | |
| 272 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_)); | |
| 273 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &address_)); | |
| 274 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(2, &port_)); | |
| 275 return true; | |
| 276 } | |
| 277 | |
| 278 void SocketBindFunction::Work() { | |
| 279 int result = -1; | |
| 280 Socket* socket = GetSocket(socket_id_); | |
| 281 | |
| 282 if (!socket) { | |
| 283 error_ = kSocketNotFoundError; | |
| 284 SetResult(new base::FundamentalValue(result)); | |
| 285 return; | |
| 286 } | |
| 287 | |
| 288 if (socket->GetSocketType() == Socket::TYPE_UDP) { | |
| 289 SocketPermission::CheckParam param( | |
| 290 SocketPermissionRequest::UDP_BIND, address_, port_); | |
| 291 if (!PermissionsData::CheckAPIPermissionWithParam( | |
| 292 GetExtension(), | |
| 293 APIPermission::kSocket, | |
| 294 ¶m)) { | |
| 295 error_ = kPermissionError; | |
| 296 SetResult(new base::FundamentalValue(result)); | |
| 297 return; | |
| 298 } | |
| 299 } else if (socket->GetSocketType() == Socket::TYPE_TCP) { | |
| 300 error_ = kTCPSocketBindError; | |
| 301 SetResult(new base::FundamentalValue(result)); | |
| 302 return; | |
| 303 } | |
| 304 | |
| 305 result = socket->Bind(address_, port_); | |
| 306 SetResult(new base::FundamentalValue(result)); | |
| 307 } | |
| 308 | |
| 309 SocketListenFunction::SocketListenFunction() {} | |
| 310 | |
| 311 SocketListenFunction::~SocketListenFunction() {} | |
| 312 | |
| 313 bool SocketListenFunction::Prepare() { | |
| 314 params_ = api::socket::Listen::Params::Create(*args_); | |
| 315 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
| 316 return true; | |
| 317 } | |
| 318 | |
| 319 void SocketListenFunction::Work() { | |
| 320 int result = -1; | |
| 321 | |
| 322 Socket* socket = GetSocket(params_->socket_id); | |
| 323 if (socket) { | |
| 324 SocketPermission::CheckParam param( | |
| 325 SocketPermissionRequest::TCP_LISTEN, params_->address, params_->port); | |
| 326 if (!PermissionsData::CheckAPIPermissionWithParam( | |
| 327 GetExtension(), | |
| 328 APIPermission::kSocket, | |
| 329 ¶m)) { | |
| 330 error_ = kPermissionError; | |
| 331 SetResult(new base::FundamentalValue(result)); | |
| 332 return; | |
| 333 } | |
| 334 | |
| 335 result = socket->Listen( | |
| 336 params_->address, | |
| 337 params_->port, | |
| 338 params_->backlog.get() ? *params_->backlog.get() : 5, | |
| 339 &error_); | |
| 340 } else { | |
| 341 error_ = kSocketNotFoundError; | |
| 342 } | |
| 343 | |
| 344 SetResult(new base::FundamentalValue(result)); | |
| 345 } | |
| 346 | |
| 347 SocketAcceptFunction::SocketAcceptFunction() {} | |
| 348 | |
| 349 SocketAcceptFunction::~SocketAcceptFunction() {} | |
| 350 | |
| 351 bool SocketAcceptFunction::Prepare() { | |
| 352 params_ = api::socket::Accept::Params::Create(*args_); | |
| 353 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
| 354 return true; | |
| 355 } | |
| 356 | |
| 357 void SocketAcceptFunction::AsyncWorkStart() { | |
| 358 Socket* socket = GetSocket(params_->socket_id); | |
| 359 if (socket) { | |
| 360 socket->Accept(base::Bind(&SocketAcceptFunction::OnAccept, this)); | |
| 361 } else { | |
| 362 error_ = kSocketNotFoundError; | |
| 363 OnAccept(-1, NULL); | |
| 364 } | |
| 365 } | |
| 366 | |
| 367 void SocketAcceptFunction::OnAccept(int result_code, | |
| 368 net::TCPClientSocket *socket) { | |
| 369 base::DictionaryValue* result = new base::DictionaryValue(); | |
| 370 result->SetInteger(kResultCodeKey, result_code); | |
| 371 if (socket) { | |
| 372 Socket *client_socket = new TCPSocket(socket, extension_id(), true); | |
| 373 result->SetInteger(kSocketIdKey, AddSocket(client_socket)); | |
| 374 } | |
| 375 SetResult(result); | |
| 376 | |
| 377 AsyncWorkCompleted(); | |
| 378 } | |
| 379 | |
| 380 SocketReadFunction::SocketReadFunction() {} | |
| 381 | |
| 382 SocketReadFunction::~SocketReadFunction() {} | |
| 383 | |
| 384 bool SocketReadFunction::Prepare() { | |
| 385 params_ = api::socket::Read::Params::Create(*args_); | |
| 386 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
| 387 return true; | |
| 388 } | |
| 389 | |
| 390 void SocketReadFunction::AsyncWorkStart() { | |
| 391 Socket* socket = GetSocket(params_->socket_id); | |
| 392 if (!socket) { | |
| 393 error_ = kSocketNotFoundError; | |
| 394 OnCompleted(-1, NULL); | |
| 395 return; | |
| 396 } | |
| 397 | |
| 398 socket->Read(params_->buffer_size.get() ? *params_->buffer_size.get() : 4096, | |
| 399 base::Bind(&SocketReadFunction::OnCompleted, this)); | |
| 400 } | |
| 401 | |
| 402 void SocketReadFunction::OnCompleted(int bytes_read, | |
| 403 scoped_refptr<net::IOBuffer> io_buffer) { | |
| 404 base::DictionaryValue* result = new base::DictionaryValue(); | |
| 405 result->SetInteger(kResultCodeKey, bytes_read); | |
| 406 if (bytes_read > 0) { | |
| 407 result->Set(kDataKey, | |
| 408 base::BinaryValue::CreateWithCopiedBuffer(io_buffer->data(), | |
| 409 bytes_read)); | |
| 410 } else { | |
| 411 result->Set(kDataKey, new base::BinaryValue()); | |
| 412 } | |
| 413 SetResult(result); | |
| 414 | |
| 415 AsyncWorkCompleted(); | |
| 416 } | |
| 417 | |
| 418 SocketWriteFunction::SocketWriteFunction() | |
| 419 : socket_id_(0), | |
| 420 io_buffer_(NULL), | |
| 421 io_buffer_size_(0) { | |
| 422 } | |
| 423 | |
| 424 SocketWriteFunction::~SocketWriteFunction() {} | |
| 425 | |
| 426 bool SocketWriteFunction::Prepare() { | |
| 427 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_)); | |
| 428 base::BinaryValue *data = NULL; | |
| 429 EXTENSION_FUNCTION_VALIDATE(args_->GetBinary(1, &data)); | |
| 430 | |
| 431 io_buffer_size_ = data->GetSize(); | |
| 432 io_buffer_ = new net::WrappedIOBuffer(data->GetBuffer()); | |
| 433 return true; | |
| 434 } | |
| 435 | |
| 436 void SocketWriteFunction::AsyncWorkStart() { | |
| 437 Socket* socket = GetSocket(socket_id_); | |
| 438 | |
| 439 if (!socket) { | |
| 440 error_ = kSocketNotFoundError; | |
| 441 OnCompleted(-1); | |
| 442 return; | |
| 443 } | |
| 444 | |
| 445 socket->Write(io_buffer_, io_buffer_size_, | |
| 446 base::Bind(&SocketWriteFunction::OnCompleted, this)); | |
| 447 } | |
| 448 | |
| 449 void SocketWriteFunction::OnCompleted(int bytes_written) { | |
| 450 base::DictionaryValue* result = new base::DictionaryValue(); | |
| 451 result->SetInteger(kBytesWrittenKey, bytes_written); | |
| 452 SetResult(result); | |
| 453 | |
| 454 AsyncWorkCompleted(); | |
| 455 } | |
| 456 | |
| 457 SocketRecvFromFunction::SocketRecvFromFunction() {} | |
| 458 | |
| 459 SocketRecvFromFunction::~SocketRecvFromFunction() {} | |
| 460 | |
| 461 bool SocketRecvFromFunction::Prepare() { | |
| 462 params_ = api::socket::RecvFrom::Params::Create(*args_); | |
| 463 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
| 464 return true; | |
| 465 } | |
| 466 | |
| 467 void SocketRecvFromFunction::AsyncWorkStart() { | |
| 468 Socket* socket = GetSocket(params_->socket_id); | |
| 469 if (!socket) { | |
| 470 error_ = kSocketNotFoundError; | |
| 471 OnCompleted(-1, NULL, std::string(), 0); | |
| 472 return; | |
| 473 } | |
| 474 | |
| 475 socket->RecvFrom(params_->buffer_size.get() ? *params_->buffer_size : 4096, | |
| 476 base::Bind(&SocketRecvFromFunction::OnCompleted, this)); | |
| 477 } | |
| 478 | |
| 479 void SocketRecvFromFunction::OnCompleted(int bytes_read, | |
| 480 scoped_refptr<net::IOBuffer> io_buffer, | |
| 481 const std::string& address, | |
| 482 int port) { | |
| 483 base::DictionaryValue* result = new base::DictionaryValue(); | |
| 484 result->SetInteger(kResultCodeKey, bytes_read); | |
| 485 if (bytes_read > 0) { | |
| 486 result->Set(kDataKey, | |
| 487 base::BinaryValue::CreateWithCopiedBuffer(io_buffer->data(), | |
| 488 bytes_read)); | |
| 489 } else { | |
| 490 result->Set(kDataKey, new base::BinaryValue()); | |
| 491 } | |
| 492 result->SetString(kAddressKey, address); | |
| 493 result->SetInteger(kPortKey, port); | |
| 494 SetResult(result); | |
| 495 | |
| 496 AsyncWorkCompleted(); | |
| 497 } | |
| 498 | |
| 499 SocketSendToFunction::SocketSendToFunction() | |
| 500 : socket_id_(0), | |
| 501 io_buffer_(NULL), | |
| 502 io_buffer_size_(0), | |
| 503 port_(0), | |
| 504 socket_(NULL) { | |
| 505 } | |
| 506 | |
| 507 SocketSendToFunction::~SocketSendToFunction() {} | |
| 508 | |
| 509 bool SocketSendToFunction::Prepare() { | |
| 510 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_)); | |
| 511 base::BinaryValue *data = NULL; | |
| 512 EXTENSION_FUNCTION_VALIDATE(args_->GetBinary(1, &data)); | |
| 513 EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &hostname_)); | |
| 514 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(3, &port_)); | |
| 515 | |
| 516 io_buffer_size_ = data->GetSize(); | |
| 517 io_buffer_ = new net::WrappedIOBuffer(data->GetBuffer()); | |
| 518 return true; | |
| 519 } | |
| 520 | |
| 521 void SocketSendToFunction::AsyncWorkStart() { | |
| 522 socket_ = GetSocket(socket_id_); | |
| 523 if (!socket_) { | |
| 524 error_ = kSocketNotFoundError; | |
| 525 SetResult(new base::FundamentalValue(-1)); | |
| 526 AsyncWorkCompleted(); | |
| 527 return; | |
| 528 } | |
| 529 | |
| 530 if (socket_->GetSocketType() == Socket::TYPE_UDP) { | |
| 531 SocketPermission::CheckParam param(SocketPermissionRequest::UDP_SEND_TO, | |
| 532 hostname_, port_); | |
| 533 if (!PermissionsData::CheckAPIPermissionWithParam( | |
| 534 GetExtension(), | |
| 535 APIPermission::kSocket, | |
| 536 ¶m)) { | |
| 537 error_ = kPermissionError; | |
| 538 SetResult(new base::FundamentalValue(-1)); | |
| 539 AsyncWorkCompleted(); | |
| 540 return; | |
| 541 } | |
| 542 } | |
| 543 | |
| 544 StartDnsLookup(hostname_); | |
| 545 } | |
| 546 | |
| 547 void SocketSendToFunction::AfterDnsLookup(int lookup_result) { | |
| 548 if (lookup_result == net::OK) { | |
| 549 StartSendTo(); | |
| 550 } else { | |
| 551 SetResult(new base::FundamentalValue(lookup_result)); | |
| 552 AsyncWorkCompleted(); | |
| 553 } | |
| 554 } | |
| 555 | |
| 556 void SocketSendToFunction::StartSendTo() { | |
| 557 socket_->SendTo(io_buffer_, io_buffer_size_, resolved_address_, port_, | |
| 558 base::Bind(&SocketSendToFunction::OnCompleted, this)); | |
| 559 } | |
| 560 | |
| 561 void SocketSendToFunction::OnCompleted(int bytes_written) { | |
| 562 base::DictionaryValue* result = new base::DictionaryValue(); | |
| 563 result->SetInteger(kBytesWrittenKey, bytes_written); | |
| 564 SetResult(result); | |
| 565 | |
| 566 AsyncWorkCompleted(); | |
| 567 } | |
| 568 | |
| 569 SocketSetKeepAliveFunction::SocketSetKeepAliveFunction() {} | |
| 570 | |
| 571 SocketSetKeepAliveFunction::~SocketSetKeepAliveFunction() {} | |
| 572 | |
| 573 bool SocketSetKeepAliveFunction::Prepare() { | |
| 574 params_ = api::socket::SetKeepAlive::Params::Create(*args_); | |
| 575 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
| 576 return true; | |
| 577 } | |
| 578 | |
| 579 void SocketSetKeepAliveFunction::Work() { | |
| 580 bool result = false; | |
| 581 Socket* socket = GetSocket(params_->socket_id); | |
| 582 if (socket) { | |
| 583 int delay = 0; | |
| 584 if (params_->delay.get()) | |
| 585 delay = *params_->delay; | |
| 586 result = socket->SetKeepAlive(params_->enable, delay); | |
| 587 } else { | |
| 588 error_ = kSocketNotFoundError; | |
| 589 } | |
| 590 SetResult(new base::FundamentalValue(result)); | |
| 591 } | |
| 592 | |
| 593 SocketSetNoDelayFunction::SocketSetNoDelayFunction() {} | |
| 594 | |
| 595 SocketSetNoDelayFunction::~SocketSetNoDelayFunction() {} | |
| 596 | |
| 597 bool SocketSetNoDelayFunction::Prepare() { | |
| 598 params_ = api::socket::SetNoDelay::Params::Create(*args_); | |
| 599 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
| 600 return true; | |
| 601 } | |
| 602 | |
| 603 void SocketSetNoDelayFunction::Work() { | |
| 604 bool result = false; | |
| 605 Socket* socket = GetSocket(params_->socket_id); | |
| 606 if (socket) | |
| 607 result = socket->SetNoDelay(params_->no_delay); | |
| 608 else | |
| 609 error_ = kSocketNotFoundError; | |
| 610 SetResult(new base::FundamentalValue(result)); | |
| 611 } | |
| 612 | |
| 613 SocketGetInfoFunction::SocketGetInfoFunction() {} | |
| 614 | |
| 615 SocketGetInfoFunction::~SocketGetInfoFunction() {} | |
| 616 | |
| 617 bool SocketGetInfoFunction::Prepare() { | |
| 618 params_ = api::socket::GetInfo::Params::Create(*args_); | |
| 619 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
| 620 return true; | |
| 621 } | |
| 622 | |
| 623 void SocketGetInfoFunction::Work() { | |
| 624 Socket* socket = GetSocket(params_->socket_id); | |
| 625 if (!socket) { | |
| 626 error_ = kSocketNotFoundError; | |
| 627 return; | |
| 628 } | |
| 629 | |
| 630 api::socket::SocketInfo info; | |
| 631 // This represents what we know about the socket, and does not call through | |
| 632 // to the system. | |
| 633 if (socket->GetSocketType() == Socket::TYPE_TCP) | |
| 634 info.socket_type = extensions::api::socket::SOCKET_TYPE_TCP; | |
| 635 else | |
| 636 info.socket_type = extensions::api::socket::SOCKET_TYPE_UDP; | |
| 637 info.connected = socket->IsConnected(); | |
| 638 | |
| 639 // Grab the peer address as known by the OS. This and the call below will | |
| 640 // always succeed while the socket is connected, even if the socket has | |
| 641 // been remotely closed by the peer; only reading the socket will reveal | |
| 642 // that it should be closed locally. | |
| 643 net::IPEndPoint peerAddress; | |
| 644 if (socket->GetPeerAddress(&peerAddress)) { | |
| 645 info.peer_address.reset( | |
| 646 new std::string(peerAddress.ToStringWithoutPort())); | |
| 647 info.peer_port.reset(new int(peerAddress.port())); | |
| 648 } | |
| 649 | |
| 650 // Grab the local address as known by the OS. | |
| 651 net::IPEndPoint localAddress; | |
| 652 if (socket->GetLocalAddress(&localAddress)) { | |
| 653 info.local_address.reset( | |
| 654 new std::string(localAddress.ToStringWithoutPort())); | |
| 655 info.local_port.reset(new int(localAddress.port())); | |
| 656 } | |
| 657 | |
| 658 SetResult(info.ToValue().release()); | |
| 659 } | |
| 660 | |
| 661 bool SocketGetNetworkListFunction::RunImpl() { | |
| 662 content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE, | |
| 663 base::Bind(&SocketGetNetworkListFunction::GetNetworkListOnFileThread, | |
| 664 this)); | |
| 665 return true; | |
| 666 } | |
| 667 | |
| 668 void SocketGetNetworkListFunction::GetNetworkListOnFileThread() { | |
| 669 net::NetworkInterfaceList interface_list; | |
| 670 if (GetNetworkList(&interface_list, | |
| 671 net::INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES)) { | |
| 672 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | |
| 673 base::Bind(&SocketGetNetworkListFunction::SendResponseOnUIThread, | |
| 674 this, interface_list)); | |
| 675 return; | |
| 676 } | |
| 677 | |
| 678 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | |
| 679 base::Bind(&SocketGetNetworkListFunction::HandleGetNetworkListError, | |
| 680 this)); | |
| 681 } | |
| 682 | |
| 683 void SocketGetNetworkListFunction::HandleGetNetworkListError() { | |
| 684 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
| 685 error_ = kNetworkListError; | |
| 686 SendResponse(false); | |
| 687 } | |
| 688 | |
| 689 void SocketGetNetworkListFunction::SendResponseOnUIThread( | |
| 690 const net::NetworkInterfaceList& interface_list) { | |
| 691 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | |
| 692 | |
| 693 std::vector<linked_ptr<api::socket::NetworkInterface> > create_arg; | |
| 694 create_arg.reserve(interface_list.size()); | |
| 695 for (net::NetworkInterfaceList::const_iterator i = interface_list.begin(); | |
| 696 i != interface_list.end(); ++i) { | |
| 697 linked_ptr<api::socket::NetworkInterface> info = | |
| 698 make_linked_ptr(new api::socket::NetworkInterface); | |
| 699 info->name = i->name; | |
| 700 info->address = net::IPAddressToString(i->address); | |
| 701 info->prefix_length = i->network_prefix; | |
| 702 create_arg.push_back(info); | |
| 703 } | |
| 704 | |
| 705 results_ = api::socket::GetNetworkList::Results::Create(create_arg); | |
| 706 SendResponse(true); | |
| 707 } | |
| 708 | |
| 709 SocketJoinGroupFunction::SocketJoinGroupFunction() {} | |
| 710 | |
| 711 SocketJoinGroupFunction::~SocketJoinGroupFunction() {} | |
| 712 | |
| 713 bool SocketJoinGroupFunction::Prepare() { | |
| 714 params_ = api::socket::JoinGroup::Params::Create(*args_); | |
| 715 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
| 716 return true; | |
| 717 } | |
| 718 | |
| 719 void SocketJoinGroupFunction::Work() { | |
| 720 int result = -1; | |
| 721 Socket* socket = GetSocket(params_->socket_id); | |
| 722 if (!socket) { | |
| 723 error_ = kSocketNotFoundError; | |
| 724 SetResult(new base::FundamentalValue(result)); | |
| 725 return; | |
| 726 } | |
| 727 | |
| 728 if (socket->GetSocketType() != Socket::TYPE_UDP) { | |
| 729 error_ = kMulticastSocketTypeError; | |
| 730 SetResult(new base::FundamentalValue(result)); | |
| 731 return; | |
| 732 } | |
| 733 | |
| 734 SocketPermission::CheckParam param( | |
| 735 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP, | |
| 736 kWildcardAddress, | |
| 737 kWildcardPort); | |
| 738 | |
| 739 if (!PermissionsData::CheckAPIPermissionWithParam( | |
| 740 GetExtension(), APIPermission::kSocket, ¶m)) { | |
| 741 error_ = kPermissionError; | |
| 742 SetResult(new base::FundamentalValue(result)); | |
| 743 return; | |
| 744 } | |
| 745 | |
| 746 result = static_cast<UDPSocket*>(socket)->JoinGroup(params_->address); | |
| 747 if (result != 0) { | |
| 748 error_ = net::ErrorToString(result); | |
| 749 } | |
| 750 SetResult(new base::FundamentalValue(result)); | |
| 751 } | |
| 752 | |
| 753 SocketLeaveGroupFunction::SocketLeaveGroupFunction() {} | |
| 754 | |
| 755 SocketLeaveGroupFunction::~SocketLeaveGroupFunction() {} | |
| 756 | |
| 757 bool SocketLeaveGroupFunction::Prepare() { | |
| 758 params_ = api::socket::LeaveGroup::Params::Create(*args_); | |
| 759 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
| 760 return true; | |
| 761 } | |
| 762 | |
| 763 void SocketLeaveGroupFunction::Work() { | |
| 764 int result = -1; | |
| 765 Socket* socket = GetSocket(params_->socket_id); | |
| 766 | |
| 767 if (!socket) { | |
| 768 error_ = kSocketNotFoundError; | |
| 769 SetResult(new base::FundamentalValue(result)); | |
| 770 return; | |
| 771 } | |
| 772 | |
| 773 if (socket->GetSocketType() != Socket::TYPE_UDP) { | |
| 774 error_ = kMulticastSocketTypeError; | |
| 775 SetResult(new base::FundamentalValue(result)); | |
| 776 return; | |
| 777 } | |
| 778 | |
| 779 SocketPermission::CheckParam param( | |
| 780 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP, | |
| 781 kWildcardAddress, | |
| 782 kWildcardPort); | |
| 783 if (!PermissionsData::CheckAPIPermissionWithParam(GetExtension(), | |
| 784 APIPermission::kSocket, | |
| 785 ¶m)) { | |
| 786 error_ = kPermissionError; | |
| 787 SetResult(new base::FundamentalValue(result)); | |
| 788 return; | |
| 789 } | |
| 790 | |
| 791 result = static_cast<UDPSocket*>(socket)->LeaveGroup(params_->address); | |
| 792 if (result != 0) | |
| 793 error_ = net::ErrorToString(result); | |
| 794 SetResult(new base::FundamentalValue(result)); | |
| 795 } | |
| 796 | |
| 797 SocketSetMulticastTimeToLiveFunction::SocketSetMulticastTimeToLiveFunction() {} | |
| 798 | |
| 799 SocketSetMulticastTimeToLiveFunction::~SocketSetMulticastTimeToLiveFunction() {} | |
| 800 | |
| 801 bool SocketSetMulticastTimeToLiveFunction::Prepare() { | |
| 802 params_ = api::socket::SetMulticastTimeToLive::Params::Create(*args_); | |
| 803 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
| 804 return true; | |
| 805 } | |
| 806 void SocketSetMulticastTimeToLiveFunction::Work() { | |
| 807 int result = -1; | |
| 808 Socket* socket = GetSocket(params_->socket_id); | |
| 809 if (!socket) { | |
| 810 error_ = kSocketNotFoundError; | |
| 811 SetResult(new base::FundamentalValue(result)); | |
| 812 return; | |
| 813 } | |
| 814 | |
| 815 if (socket->GetSocketType() != Socket::TYPE_UDP) { | |
| 816 error_ = kMulticastSocketTypeError; | |
| 817 SetResult(new base::FundamentalValue(result)); | |
| 818 return; | |
| 819 } | |
| 820 | |
| 821 result = static_cast<UDPSocket*>(socket)->SetMulticastTimeToLive( | |
| 822 params_->ttl); | |
| 823 if (result != 0) | |
| 824 error_ = net::ErrorToString(result); | |
| 825 SetResult(new base::FundamentalValue(result)); | |
| 826 } | |
| 827 | |
| 828 SocketSetMulticastLoopbackModeFunction:: | |
| 829 SocketSetMulticastLoopbackModeFunction() {} | |
| 830 | |
| 831 SocketSetMulticastLoopbackModeFunction:: | |
| 832 ~SocketSetMulticastLoopbackModeFunction() {} | |
| 833 | |
| 834 bool SocketSetMulticastLoopbackModeFunction::Prepare() { | |
| 835 params_ = api::socket::SetMulticastLoopbackMode::Params::Create(*args_); | |
| 836 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
| 837 return true; | |
| 838 } | |
| 839 | |
| 840 void SocketSetMulticastLoopbackModeFunction::Work() { | |
| 841 int result = -1; | |
| 842 Socket* socket = GetSocket(params_->socket_id); | |
| 843 if (!socket) { | |
| 844 error_ = kSocketNotFoundError; | |
| 845 SetResult(new base::FundamentalValue(result)); | |
| 846 return; | |
| 847 } | |
| 848 | |
| 849 if (socket->GetSocketType() != Socket::TYPE_UDP) { | |
| 850 error_ = kMulticastSocketTypeError; | |
| 851 SetResult(new base::FundamentalValue(result)); | |
| 852 return; | |
| 853 } | |
| 854 | |
| 855 result = static_cast<UDPSocket*>(socket)-> | |
| 856 SetMulticastLoopbackMode(params_->enabled); | |
| 857 if (result != 0) | |
| 858 error_ = net::ErrorToString(result); | |
| 859 SetResult(new base::FundamentalValue(result)); | |
| 860 } | |
| 861 | |
| 862 SocketGetJoinedGroupsFunction::SocketGetJoinedGroupsFunction() {} | |
| 863 | |
| 864 SocketGetJoinedGroupsFunction::~SocketGetJoinedGroupsFunction() {} | |
| 865 | |
| 866 bool SocketGetJoinedGroupsFunction::Prepare() { | |
| 867 params_ = api::socket::GetJoinedGroups::Params::Create(*args_); | |
| 868 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
| 869 return true; | |
| 870 } | |
| 871 | |
| 872 void SocketGetJoinedGroupsFunction::Work() { | |
| 873 int result = -1; | |
| 874 Socket* socket = GetSocket(params_->socket_id); | |
| 875 if (!socket) { | |
| 876 error_ = kSocketNotFoundError; | |
| 877 SetResult(new base::FundamentalValue(result)); | |
| 878 return; | |
| 879 } | |
| 880 | |
| 881 if (socket->GetSocketType() != Socket::TYPE_UDP) { | |
| 882 error_ = kMulticastSocketTypeError; | |
| 883 SetResult(new base::FundamentalValue(result)); | |
| 884 return; | |
| 885 } | |
| 886 | |
| 887 SocketPermission::CheckParam param( | |
| 888 SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP, | |
| 889 kWildcardAddress, | |
| 890 kWildcardPort); | |
| 891 if (!PermissionsData::CheckAPIPermissionWithParam( | |
| 892 GetExtension(), | |
| 893 APIPermission::kSocket, | |
| 894 ¶m)) { | |
| 895 error_ = kPermissionError; | |
| 896 SetResult(new base::FundamentalValue(result)); | |
| 897 return; | |
| 898 } | |
| 899 | |
| 900 base::ListValue* values = new base::ListValue(); | |
| 901 values->AppendStrings((std::vector<std::string>&) | |
| 902 static_cast<UDPSocket*>(socket)->GetJoinedGroups()); | |
| 903 SetResult(values); | |
| 904 } | |
| 905 | |
| 906 } // namespace extensions | |
| OLD | NEW |