Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/api/socket/socket_api.h" | 5 #include "chrome/browser/extensions/api/socket/socket_api.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "chrome/common/extensions/permissions/socket_permission.h" | |
| 8 #include "chrome/browser/browser_process.h" | 9 #include "chrome/browser/browser_process.h" |
| 9 #include "chrome/browser/extensions/api/dns/host_resolver_wrapper.h" | 10 #include "chrome/browser/extensions/api/dns/host_resolver_wrapper.h" |
| 10 #include "chrome/browser/extensions/api/socket/socket.h" | 11 #include "chrome/browser/extensions/api/socket/socket.h" |
| 11 #include "chrome/browser/extensions/api/socket/tcp_socket.h" | 12 #include "chrome/browser/extensions/api/socket/tcp_socket.h" |
| 12 #include "chrome/browser/extensions/api/socket/udp_socket.h" | 13 #include "chrome/browser/extensions/api/socket/udp_socket.h" |
| 13 #include "chrome/browser/extensions/extension_system.h" | 14 #include "chrome/browser/extensions/extension_system.h" |
| 14 #include "chrome/browser/io_thread.h" | 15 #include "chrome/browser/io_thread.h" |
| 15 #include "net/base/host_port_pair.h" | 16 #include "net/base/host_port_pair.h" |
| 16 #include "net/base/io_buffer.h" | 17 #include "net/base/io_buffer.h" |
| 17 #include "net/base/ip_endpoint.h" | 18 #include "net/base/ip_endpoint.h" |
| 18 #include "net/base/net_errors.h" | 19 #include "net/base/net_errors.h" |
| 19 #include "net/base/net_log.h" | 20 #include "net/base/net_log.h" |
| 20 | 21 |
| 21 namespace extensions { | 22 namespace extensions { |
| 22 | 23 |
| 23 const char kAddressKey[] = "address"; | 24 const char kAddressKey[] = "address"; |
| 24 const char kPortKey[] = "port"; | 25 const char kPortKey[] = "port"; |
| 25 const char kBytesWrittenKey[] = "bytesWritten"; | 26 const char kBytesWrittenKey[] = "bytesWritten"; |
| 26 const char kDataKey[] = "data"; | 27 const char kDataKey[] = "data"; |
| 27 const char kResultCodeKey[] = "resultCode"; | 28 const char kResultCodeKey[] = "resultCode"; |
| 28 const char kSocketIdKey[] = "socketId"; | 29 const char kSocketIdKey[] = "socketId"; |
| 29 const char kTCPOption[] = "tcp"; | 30 const char kTCPOption[] = "tcp"; |
| 30 const char kUDPOption[] = "udp"; | 31 const char kUDPOption[] = "udp"; |
| 32 const char kUnknown[] = "unknown"; | |
| 31 | 33 |
| 32 const char kSocketNotFoundError[] = "Socket not found"; | 34 const char kSocketNotFoundError[] = "Socket not found"; |
| 33 const char kSocketTypeInvalidError[] = "Socket type is not supported"; | 35 const char kSocketTypeInvalidError[] = "Socket type is not supported"; |
| 34 const char kDnsLookupFailedError[] = "DNS resolution failed"; | 36 const char kDnsLookupFailedError[] = "DNS resolution failed"; |
| 37 const char kPermissionError[] = "Caller does not have permission"; | |
| 35 | 38 |
| 36 SocketAsyncApiFunction::SocketAsyncApiFunction() | 39 SocketAsyncApiFunction::SocketAsyncApiFunction() |
| 37 : manager_(NULL) { | 40 : manager_(NULL) { |
| 38 } | 41 } |
| 39 | 42 |
| 40 SocketAsyncApiFunction::~SocketAsyncApiFunction() { | 43 SocketAsyncApiFunction::~SocketAsyncApiFunction() { |
| 41 } | 44 } |
| 42 | 45 |
| 43 bool SocketAsyncApiFunction::PrePrepare() { | 46 bool SocketAsyncApiFunction::PrePrepare() { |
| 44 manager_ = ExtensionSystem::Get(profile())->socket_manager(); | 47 manager_ = ExtensionSystem::Get(profile())->socket_manager(); |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 156 } | 159 } |
| 157 | 160 |
| 158 bool SocketConnectFunction::Prepare() { | 161 bool SocketConnectFunction::Prepare() { |
| 159 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_)); | 162 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_)); |
| 160 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &hostname_)); | 163 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &hostname_)); |
| 161 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(2, &port_)); | 164 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(2, &port_)); |
| 162 return true; | 165 return true; |
| 163 } | 166 } |
| 164 | 167 |
| 165 void SocketConnectFunction::AsyncWorkStart() { | 168 void SocketConnectFunction::AsyncWorkStart() { |
| 169 socket_ = manager_->Get(socket_id_); | |
| 170 if (!socket_) { | |
| 171 error_ = kSocketNotFoundError; | |
| 172 SetResult(Value::CreateIntegerValue(-1)); | |
| 173 AsyncWorkCompleted(); | |
| 174 return; | |
| 175 } | |
| 176 | |
| 177 SocketPermissionData::OperationType type; | |
|
Mihai Parparita -not on Chrome
2012/08/10 00:16:16
Can you call this variable operation_type? Otherwi
Peng
2012/08/13 16:26:10
Done.
| |
| 178 switch (socket_->socket_type()) { | |
| 179 case Socket::TYPE_TCP: | |
| 180 type = SocketPermissionData::TCP_CONNECT; | |
| 181 break; | |
| 182 case Socket::TYPE_UDP: | |
| 183 type = SocketPermissionData::UDP_SEND_TO; | |
| 184 break; | |
| 185 default: | |
| 186 type = SocketPermissionData::NONE; | |
|
Mihai Parparita -not on Chrome
2012/08/10 00:16:16
NOTREACHED() may be more appropriate here (I think
Peng
2012/08/13 16:26:10
Done.
| |
| 187 break; | |
| 188 } | |
| 189 | |
| 190 SocketPermission::CheckParam param(type, hostname_, port_); | |
| 191 if (!GetExtension()->CheckAPIPermissionWithDetail(APIPermission::kSocket, | |
| 192 ¶m)) { | |
| 193 error_ = kPermissionError; | |
| 194 SetResult(Value::CreateIntegerValue(-1)); | |
| 195 AsyncWorkCompleted(); | |
| 196 return; | |
| 197 } | |
| 198 | |
| 166 StartDnsLookup(hostname_); | 199 StartDnsLookup(hostname_); |
| 167 } | 200 } |
| 168 | 201 |
| 169 void SocketConnectFunction::AfterDnsLookup(int lookup_result) { | 202 void SocketConnectFunction::AfterDnsLookup(int lookup_result) { |
| 170 if (lookup_result == net::OK) { | 203 if (lookup_result == net::OK) { |
| 171 StartConnect(); | 204 StartConnect(); |
| 172 } else { | 205 } else { |
| 173 SetResult(Value::CreateIntegerValue(lookup_result)); | 206 SetResult(Value::CreateIntegerValue(lookup_result)); |
| 174 AsyncWorkCompleted(); | 207 AsyncWorkCompleted(); |
| 175 } | 208 } |
| 176 } | 209 } |
| 177 | 210 |
| 178 void SocketConnectFunction::StartConnect() { | 211 void SocketConnectFunction::StartConnect() { |
| 179 Socket* socket = manager_->Get(socket_id_); | 212 socket_->Connect(resolved_address_, port_, |
| 180 if (!socket) { | 213 base::Bind(&SocketConnectFunction::OnConnect, this)); |
| 181 error_ = kSocketNotFoundError; | |
| 182 OnConnect(-1); | |
| 183 return; | |
| 184 } | |
| 185 | |
| 186 socket->Connect(resolved_address_, port_, | |
| 187 base::Bind(&SocketConnectFunction::OnConnect, this)); | |
| 188 } | 214 } |
| 189 | 215 |
| 190 void SocketConnectFunction::OnConnect(int result) { | 216 void SocketConnectFunction::OnConnect(int result) { |
| 191 SetResult(Value::CreateIntegerValue(result)); | 217 SetResult(Value::CreateIntegerValue(result)); |
| 192 AsyncWorkCompleted(); | 218 AsyncWorkCompleted(); |
| 193 } | 219 } |
| 194 | 220 |
| 195 bool SocketDisconnectFunction::Prepare() { | 221 bool SocketDisconnectFunction::Prepare() { |
| 196 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_)); | 222 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_)); |
| 197 return true; | 223 return true; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 209 bool SocketBindFunction::Prepare() { | 235 bool SocketBindFunction::Prepare() { |
| 210 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_)); | 236 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &socket_id_)); |
| 211 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &address_)); | 237 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &address_)); |
| 212 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(2, &port_)); | 238 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(2, &port_)); |
| 213 return true; | 239 return true; |
| 214 } | 240 } |
| 215 | 241 |
| 216 void SocketBindFunction::Work() { | 242 void SocketBindFunction::Work() { |
| 217 int result = -1; | 243 int result = -1; |
| 218 Socket* socket = manager_->Get(socket_id_); | 244 Socket* socket = manager_->Get(socket_id_); |
| 219 if (socket) | 245 SocketPermission::CheckParam param( |
| 220 result = socket->Bind(address_, port_); | 246 SocketPermissionData::UDP_BIND, address_, port_); |
|
Mihai Parparita -not on Chrome
2012/08/10 00:16:16
TCP sockets also implement the Bind method. Can yo
Peng
2012/08/13 16:26:10
Done.
| |
| 221 else | 247 if (socket) { |
| 248 if (GetExtension()->CheckAPIPermissionWithDetail(APIPermission::kSocket, | |
| 249 ¶m)) | |
| 250 result = socket->Bind(address_, port_); | |
| 251 else | |
| 252 error_ = kPermissionError; | |
| 253 } else { | |
| 222 error_ = kSocketNotFoundError; | 254 error_ = kSocketNotFoundError; |
| 255 } | |
| 223 | 256 |
| 224 SetResult(Value::CreateIntegerValue(result)); | 257 SetResult(Value::CreateIntegerValue(result)); |
| 225 } | 258 } |
| 226 | 259 |
| 227 SocketReadFunction::SocketReadFunction() | 260 SocketReadFunction::SocketReadFunction() |
| 228 : params_(NULL) { | 261 : params_(NULL) { |
| 229 } | 262 } |
| 230 | 263 |
| 231 SocketReadFunction::~SocketReadFunction() {} | 264 SocketReadFunction::~SocketReadFunction() {} |
| 232 | 265 |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 366 EXTENSION_FUNCTION_VALIDATE(args_->GetBinary(1, &data)); | 399 EXTENSION_FUNCTION_VALIDATE(args_->GetBinary(1, &data)); |
| 367 EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &hostname_)); | 400 EXTENSION_FUNCTION_VALIDATE(args_->GetString(2, &hostname_)); |
| 368 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(3, &port_)); | 401 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(3, &port_)); |
| 369 | 402 |
| 370 io_buffer_size_ = data->GetSize(); | 403 io_buffer_size_ = data->GetSize(); |
| 371 io_buffer_ = new net::WrappedIOBuffer(data->GetBuffer()); | 404 io_buffer_ = new net::WrappedIOBuffer(data->GetBuffer()); |
| 372 return true; | 405 return true; |
| 373 } | 406 } |
| 374 | 407 |
| 375 void SocketSendToFunction::AsyncWorkStart() { | 408 void SocketSendToFunction::AsyncWorkStart() { |
| 376 StartDnsLookup(hostname_); | 409 do { |
| 410 socket_ = manager_->Get(socket_id_); | |
| 411 if (!socket_) { | |
| 412 error_ = kSocketNotFoundError; | |
| 413 break; | |
| 414 } | |
| 415 | |
| 416 SocketPermission::CheckParam param(SocketPermissionData::UDP_SEND_TO, | |
|
Mihai Parparita -not on Chrome
2012/08/10 00:16:16
Same thing here.
Peng
2012/08/13 16:26:10
Done.
| |
| 417 hostname_, port_); | |
| 418 if (!GetExtension()->CheckAPIPermissionWithDetail(APIPermission::kSocket, | |
| 419 ¶m)) { | |
| 420 error_ = kPermissionError; | |
| 421 break; | |
| 422 } | |
| 423 | |
| 424 StartDnsLookup(hostname_); | |
| 425 return; | |
| 426 } while (false); | |
|
Mihai Parparita -not on Chrome
2012/08/10 00:16:16
I found the break/while(false) pattern hard to rea
Peng
2012/08/13 16:26:10
Done.
Peng
2012/08/13 16:26:10
Done.
| |
| 427 SetResult(Value::CreateIntegerValue(-1)); | |
| 428 AsyncWorkCompleted(); | |
| 377 } | 429 } |
| 378 | 430 |
| 379 void SocketSendToFunction::AfterDnsLookup(int lookup_result) { | 431 void SocketSendToFunction::AfterDnsLookup(int lookup_result) { |
| 380 if (lookup_result == net::OK) { | 432 if (lookup_result == net::OK) { |
| 381 StartSendTo(); | 433 StartSendTo(); |
| 382 } else { | 434 } else { |
| 383 SetResult(Value::CreateIntegerValue(lookup_result)); | 435 SetResult(Value::CreateIntegerValue(lookup_result)); |
| 384 AsyncWorkCompleted(); | 436 AsyncWorkCompleted(); |
| 385 } | 437 } |
| 386 } | 438 } |
| 387 | 439 |
| 388 void SocketSendToFunction::StartSendTo() { | 440 void SocketSendToFunction::StartSendTo() { |
| 389 Socket* socket = manager_->Get(socket_id_); | 441 socket_->SendTo(io_buffer_, io_buffer_size_, resolved_address_, port_, |
| 390 if (!socket) { | 442 base::Bind(&SocketSendToFunction::OnCompleted, this)); |
| 391 error_ = kSocketNotFoundError; | |
| 392 OnCompleted(-1); | |
| 393 return; | |
| 394 } | |
| 395 | |
| 396 socket->SendTo(io_buffer_, io_buffer_size_, resolved_address_, port_, | |
| 397 base::Bind(&SocketSendToFunction::OnCompleted, this)); | |
| 398 } | 443 } |
| 399 | 444 |
| 400 void SocketSendToFunction::OnCompleted(int bytes_written) { | 445 void SocketSendToFunction::OnCompleted(int bytes_written) { |
| 401 DictionaryValue* result = new DictionaryValue(); | 446 DictionaryValue* result = new DictionaryValue(); |
| 402 result->SetInteger(kBytesWrittenKey, bytes_written); | 447 result->SetInteger(kBytesWrittenKey, bytes_written); |
| 403 SetResult(result); | 448 SetResult(result); |
| 404 | 449 |
| 405 AsyncWorkCompleted(); | 450 AsyncWorkCompleted(); |
| 406 } | 451 } |
| 407 | 452 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 463 EXTENSION_FUNCTION_VALIDATE(params_.get()); | 508 EXTENSION_FUNCTION_VALIDATE(params_.get()); |
| 464 return true; | 509 return true; |
| 465 } | 510 } |
| 466 | 511 |
| 467 void SocketGetInfoFunction::Work() { | 512 void SocketGetInfoFunction::Work() { |
| 468 api::socket::SocketInfo info; | 513 api::socket::SocketInfo info; |
| 469 Socket* socket = manager_->Get(params_->socket_id); | 514 Socket* socket = manager_->Get(params_->socket_id); |
| 470 if (socket) { | 515 if (socket) { |
| 471 // This represents what we know about the socket, and does not call through | 516 // This represents what we know about the socket, and does not call through |
| 472 // to the system. | 517 // to the system. |
| 473 info.socket_type = (socket->IsTCPSocket() ? kTCPOption : kUDPOption); | 518 switch (socket->socket_type()) { |
| 519 case Socket::TYPE_TCP: | |
| 520 info.socket_type = kTCPOption; | |
| 521 break; | |
| 522 case Socket::TYPE_UDP: | |
| 523 info.socket_type = kUDPOption; | |
| 524 break; | |
| 525 default: | |
| 526 info.socket_type = kUnknown; | |
|
Mihai Parparita -not on Chrome
2012/08/10 00:16:16
Also use NOTREACHED here.
Peng
2012/08/13 16:26:10
Done.
| |
| 527 break; | |
| 528 } | |
| 474 info.connected = socket->IsConnected(); | 529 info.connected = socket->IsConnected(); |
| 475 | 530 |
| 476 // Grab the peer address as known by the OS. This and the call below will | 531 // Grab the peer address as known by the OS. This and the call below will |
| 477 // always succeed while the socket is connected, even if the socket has | 532 // always succeed while the socket is connected, even if the socket has |
| 478 // been remotely closed by the peer; only reading the socket will reveal | 533 // been remotely closed by the peer; only reading the socket will reveal |
| 479 // that it should be closed locally. | 534 // that it should be closed locally. |
| 480 net::IPEndPoint peerAddress; | 535 net::IPEndPoint peerAddress; |
| 481 if (socket->GetPeerAddress(&peerAddress)) { | 536 if (socket->GetPeerAddress(&peerAddress)) { |
| 482 info.peer_address.reset( | 537 info.peer_address.reset( |
| 483 new std::string(peerAddress.ToStringWithoutPort())); | 538 new std::string(peerAddress.ToStringWithoutPort())); |
| 484 info.peer_port.reset(new int(peerAddress.port())); | 539 info.peer_port.reset(new int(peerAddress.port())); |
| 485 } | 540 } |
| 486 | 541 |
| 487 // Grab the local address as known by the OS. | 542 // Grab the local address as known by the OS. |
| 488 net::IPEndPoint localAddress; | 543 net::IPEndPoint localAddress; |
| 489 if (socket->GetLocalAddress(&localAddress)) { | 544 if (socket->GetLocalAddress(&localAddress)) { |
| 490 info.local_address.reset( | 545 info.local_address.reset( |
| 491 new std::string(localAddress.ToStringWithoutPort())); | 546 new std::string(localAddress.ToStringWithoutPort())); |
| 492 info.local_port.reset(new int(localAddress.port())); | 547 info.local_port.reset(new int(localAddress.port())); |
| 493 } | 548 } |
| 494 } else { | 549 } else { |
| 495 error_ = kSocketNotFoundError; | 550 error_ = kSocketNotFoundError; |
| 496 } | 551 } |
| 497 SetResult(info.ToValue().release()); | 552 SetResult(info.ToValue().release()); |
| 498 } | 553 } |
| 499 | 554 |
| 500 } // namespace extensions | 555 } // namespace extensions |
| OLD | NEW |