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_tcp/sockets_tcp_api.h" 6 7 #include "content/public/common/socket_permission_request.h" 8 #include "extensions/browser/api/socket/tcp_socket.h" 9 #include "extensions/browser/api/sockets_tcp/tcp_socket_event_dispatcher.h" 10 #include "extensions/common/api/sockets/sockets_manifest_data.h" 11 #include "net/base/net_errors.h" 12 13 using extensions::ResumableTCPSocket; 14 using extensions::core_api::sockets_tcp::SocketInfo; 15 using extensions::core_api::sockets_tcp::SocketProperties; 16 17 namespace { 18 19 const char kSocketNotFoundError[] = "Socket not found"; 20 const char kPermissionError[] = "Does not have permission"; 21 22 linked_ptr<SocketInfo> CreateSocketInfo(int socket_id, 23 ResumableTCPSocket* socket) { 24 linked_ptr<SocketInfo> socket_info(new SocketInfo()); 25 // This represents what we know about the socket, and does not call through 26 // to the system. 27 socket_info->socket_id = socket_id; 28 if (!socket->name().empty()) { 29 socket_info->name.reset(new std::string(socket->name())); 30 } 31 socket_info->persistent = socket->persistent(); 32 if (socket->buffer_size() > 0) { 33 socket_info->buffer_size.reset(new int(socket->buffer_size())); 34 } 35 socket_info->paused = socket->paused(); 36 socket_info->connected = socket->IsConnected(); 37 38 // Grab the local address as known by the OS. 39 net::IPEndPoint localAddress; 40 if (socket->GetLocalAddress(&localAddress)) { 41 socket_info->local_address.reset( 42 new std::string(localAddress.ToStringWithoutPort())); 43 socket_info->local_port.reset(new int(localAddress.port())); 44 } 45 46 // Grab the peer address as known by the OS. This and the call below will 47 // always succeed while the socket is connected, even if the socket has 48 // been remotely closed by the peer; only reading the socket will reveal 49 // that it should be closed locally. 50 net::IPEndPoint peerAddress; 51 if (socket->GetPeerAddress(&peerAddress)) { 52 socket_info->peer_address.reset( 53 new std::string(peerAddress.ToStringWithoutPort())); 54 socket_info->peer_port.reset(new int(peerAddress.port())); 55 } 56 57 return socket_info; 58 } 59 60 void SetSocketProperties(ResumableTCPSocket* socket, 61 SocketProperties* properties) { 62 if (properties->name.get()) { 63 socket->set_name(*properties->name.get()); 64 } 65 if (properties->persistent.get()) { 66 socket->set_persistent(*properties->persistent.get()); 67 } 68 if (properties->buffer_size.get()) { 69 // buffer size is validated when issuing the actual Recv operation 70 // on the socket. 71 socket->set_buffer_size(*properties->buffer_size.get()); 72 } 73 } 74 75 } // namespace 76 77 namespace extensions { 78 namespace core_api { 79 80 using content::SocketPermissionRequest; 81 82 TCPSocketAsyncApiFunction::~TCPSocketAsyncApiFunction() {} 83 84 scoped_ptr<SocketResourceManagerInterface> 85 TCPSocketAsyncApiFunction::CreateSocketResourceManager() { 86 return scoped_ptr<SocketResourceManagerInterface>( 87 new SocketResourceManager<ResumableTCPSocket>()).Pass(); 88 } 89 90 ResumableTCPSocket* TCPSocketAsyncApiFunction::GetTcpSocket(int socket_id) { 91 return static_cast<ResumableTCPSocket*>(GetSocket(socket_id)); 92 } 93 94 TCPSocketExtensionWithDnsLookupFunction:: 95 ~TCPSocketExtensionWithDnsLookupFunction() {} 96 97 scoped_ptr<SocketResourceManagerInterface> 98 TCPSocketExtensionWithDnsLookupFunction::CreateSocketResourceManager() { 99 return scoped_ptr<SocketResourceManagerInterface>( 100 new SocketResourceManager<ResumableTCPSocket>()).Pass(); 101 } 102 103 ResumableTCPSocket* TCPSocketExtensionWithDnsLookupFunction::GetTcpSocket( 104 int socket_id) { 105 return static_cast<ResumableTCPSocket*>(GetSocket(socket_id)); 106 } 107 108 SocketsTcpCreateFunction::SocketsTcpCreateFunction() {} 109 110 SocketsTcpCreateFunction::~SocketsTcpCreateFunction() {} 111 112 bool SocketsTcpCreateFunction::Prepare() { 113 params_ = sockets_tcp::Create::Params::Create(*args_); 114 EXTENSION_FUNCTION_VALIDATE(params_.get()); 115 return true; 116 } 117 118 void SocketsTcpCreateFunction::Work() { 119 ResumableTCPSocket* socket = new ResumableTCPSocket(extension_->id()); 120 121 sockets_tcp::SocketProperties* properties = params_.get()->properties.get(); 122 if (properties) { 123 SetSocketProperties(socket, properties); 124 } 125 126 sockets_tcp::CreateInfo create_info; 127 create_info.socket_id = AddSocket(socket); 128 results_ = sockets_tcp::Create::Results::Create(create_info); 129 } 130 131 SocketsTcpUpdateFunction::SocketsTcpUpdateFunction() {} 132 133 SocketsTcpUpdateFunction::~SocketsTcpUpdateFunction() {} 134 135 bool SocketsTcpUpdateFunction::Prepare() { 136 params_ = sockets_tcp::Update::Params::Create(*args_); 137 EXTENSION_FUNCTION_VALIDATE(params_.get()); 138 return true; 139 } 140 141 void SocketsTcpUpdateFunction::Work() { 142 ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id); 143 if (!socket) { 144 error_ = kSocketNotFoundError; 145 return; 146 } 147 148 SetSocketProperties(socket, ¶ms_.get()->properties); 149 results_ = sockets_tcp::Update::Results::Create(); 150 } 151 152 SocketsTcpSetPausedFunction::SocketsTcpSetPausedFunction() 153 : socket_event_dispatcher_(NULL) {} 154 155 SocketsTcpSetPausedFunction::~SocketsTcpSetPausedFunction() {} 156 157 bool SocketsTcpSetPausedFunction::Prepare() { 158 params_ = core_api::sockets_tcp::SetPaused::Params::Create(*args_); 159 EXTENSION_FUNCTION_VALIDATE(params_.get()); 160 161 socket_event_dispatcher_ = TCPSocketEventDispatcher::Get(browser_context()); 162 DCHECK(socket_event_dispatcher_) 163 << "There is no socket event dispatcher. " 164 "If this assertion is failing during a test, then it is likely that " 165 "TestExtensionSystem is failing to provide an instance of " 166 "TCPSocketEventDispatcher."; 167 return socket_event_dispatcher_ != NULL; 168 } 169 170 void SocketsTcpSetPausedFunction::Work() { 171 ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id); 172 if (!socket) { 173 error_ = kSocketNotFoundError; 174 return; 175 } 176 177 if (socket->paused() != params_->paused) { 178 socket->set_paused(params_->paused); 179 if (socket->IsConnected() && !params_->paused) { 180 socket_event_dispatcher_->OnSocketResume(extension_->id(), 181 params_->socket_id); 182 } 183 } 184 185 results_ = sockets_tcp::SetPaused::Results::Create(); 186 } 187 188 SocketsTcpSetKeepAliveFunction::SocketsTcpSetKeepAliveFunction() {} 189 190 SocketsTcpSetKeepAliveFunction::~SocketsTcpSetKeepAliveFunction() {} 191 192 bool SocketsTcpSetKeepAliveFunction::Prepare() { 193 params_ = core_api::sockets_tcp::SetKeepAlive::Params::Create(*args_); 194 EXTENSION_FUNCTION_VALIDATE(params_.get()); 195 return true; 196 } 197 198 void SocketsTcpSetKeepAliveFunction::Work() { 199 ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id); 200 if (!socket) { 201 error_ = kSocketNotFoundError; 202 return; 203 } 204 205 int delay = params_->delay ? *params_->delay.get() : 0; 206 207 bool success = socket->SetKeepAlive(params_->enable, delay); 208 int net_result = (success ? net::OK : net::ERR_FAILED); 209 if (net_result != net::OK) 210 error_ = net::ErrorToString(net_result); 211 results_ = sockets_tcp::SetKeepAlive::Results::Create(net_result); 212 } 213 214 SocketsTcpSetNoDelayFunction::SocketsTcpSetNoDelayFunction() {} 215 216 SocketsTcpSetNoDelayFunction::~SocketsTcpSetNoDelayFunction() {} 217 218 bool SocketsTcpSetNoDelayFunction::Prepare() { 219 params_ = core_api::sockets_tcp::SetNoDelay::Params::Create(*args_); 220 EXTENSION_FUNCTION_VALIDATE(params_.get()); 221 return true; 222 } 223 224 void SocketsTcpSetNoDelayFunction::Work() { 225 ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id); 226 if (!socket) { 227 error_ = kSocketNotFoundError; 228 return; 229 } 230 231 bool success = socket->SetNoDelay(params_->no_delay); 232 int net_result = (success ? net::OK : net::ERR_FAILED); 233 if (net_result != net::OK) 234 error_ = net::ErrorToString(net_result); 235 results_ = sockets_tcp::SetNoDelay::Results::Create(net_result); 236 } 237 238 SocketsTcpConnectFunction::SocketsTcpConnectFunction() 239 : socket_event_dispatcher_(NULL) {} 240 241 SocketsTcpConnectFunction::~SocketsTcpConnectFunction() {} 242 243 bool SocketsTcpConnectFunction::Prepare() { 244 params_ = sockets_tcp::Connect::Params::Create(*args_); 245 EXTENSION_FUNCTION_VALIDATE(params_.get()); 246 247 socket_event_dispatcher_ = TCPSocketEventDispatcher::Get(browser_context()); 248 DCHECK(socket_event_dispatcher_) 249 << "There is no socket event dispatcher. " 250 "If this assertion is failing during a test, then it is likely that " 251 "TestExtensionSystem is failing to provide an instance of " 252 "TCPSocketEventDispatcher."; 253 return socket_event_dispatcher_ != NULL; 254 } 255 256 void SocketsTcpConnectFunction::AsyncWorkStart() { 257 ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id); 258 if (!socket) { 259 error_ = kSocketNotFoundError; 260 AsyncWorkCompleted(); 261 return; 262 } 263 264 content::SocketPermissionRequest param(SocketPermissionRequest::TCP_CONNECT, 265 params_->peer_address, 266 params_->peer_port); 267 if (!SocketsManifestData::CheckRequest(GetExtension(), param)) { 268 error_ = kPermissionError; 269 AsyncWorkCompleted(); 270 return; 271 } 272 273 StartDnsLookup(params_->peer_address); 274 } 275 276 void SocketsTcpConnectFunction::AfterDnsLookup(int lookup_result) { 277 if (lookup_result == net::OK) { 278 StartConnect(); 279 } else { 280 OnCompleted(lookup_result); 281 } 282 } 283 284 void SocketsTcpConnectFunction::StartConnect() { 285 ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id); 286 if (!socket) { 287 error_ = kSocketNotFoundError; 288 AsyncWorkCompleted(); 289 return; 290 } 291 292 socket->Connect(resolved_address_, 293 params_->peer_port, 294 base::Bind(&SocketsTcpConnectFunction::OnCompleted, this)); 295 } 296 297 void SocketsTcpConnectFunction::OnCompleted(int net_result) { 298 if (net_result == net::OK) { 299 socket_event_dispatcher_->OnSocketConnect(extension_->id(), 300 params_->socket_id); 301 } 302 303 if (net_result != net::OK) 304 error_ = net::ErrorToString(net_result); 305 results_ = sockets_tcp::Connect::Results::Create(net_result); 306 AsyncWorkCompleted(); 307 } 308 309 SocketsTcpDisconnectFunction::SocketsTcpDisconnectFunction() {} 310 311 SocketsTcpDisconnectFunction::~SocketsTcpDisconnectFunction() {} 312 313 bool SocketsTcpDisconnectFunction::Prepare() { 314 params_ = sockets_tcp::Disconnect::Params::Create(*args_); 315 EXTENSION_FUNCTION_VALIDATE(params_.get()); 316 return true; 317 } 318 319 void SocketsTcpDisconnectFunction::Work() { 320 ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id); 321 if (!socket) { 322 error_ = kSocketNotFoundError; 323 return; 324 } 325 326 socket->Disconnect(); 327 results_ = sockets_tcp::Disconnect::Results::Create(); 328 } 329 330 SocketsTcpSendFunction::SocketsTcpSendFunction() : io_buffer_size_(0) {} 331 332 SocketsTcpSendFunction::~SocketsTcpSendFunction() {} 333 334 bool SocketsTcpSendFunction::Prepare() { 335 params_ = sockets_tcp::Send::Params::Create(*args_); 336 EXTENSION_FUNCTION_VALIDATE(params_.get()); 337 io_buffer_size_ = params_->data.size(); 338 io_buffer_ = new net::WrappedIOBuffer(params_->data.data()); 339 return true; 340 } 341 342 void SocketsTcpSendFunction::AsyncWorkStart() { 343 ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id); 344 if (!socket) { 345 error_ = kSocketNotFoundError; 346 AsyncWorkCompleted(); 347 return; 348 } 349 350 socket->Write(io_buffer_, 351 io_buffer_size_, 352 base::Bind(&SocketsTcpSendFunction::OnCompleted, this)); 353 } 354 355 void SocketsTcpSendFunction::OnCompleted(int net_result) { 356 if (net_result >= net::OK) { 357 SetSendResult(net::OK, net_result); 358 } else { 359 SetSendResult(net_result, -1); 360 } 361 } 362 363 void SocketsTcpSendFunction::SetSendResult(int net_result, int bytes_sent) { 364 CHECK(net_result <= net::OK) << "Network status code must be <= net::OK"; 365 366 sockets_tcp::SendInfo send_info; 367 send_info.result_code = net_result; 368 if (net_result == net::OK) { 369 send_info.bytes_sent.reset(new int(bytes_sent)); 370 } 371 372 if (net_result != net::OK) 373 error_ = net::ErrorToString(net_result); 374 results_ = sockets_tcp::Send::Results::Create(send_info); 375 AsyncWorkCompleted(); 376 } 377 378 SocketsTcpCloseFunction::SocketsTcpCloseFunction() {} 379 380 SocketsTcpCloseFunction::~SocketsTcpCloseFunction() {} 381 382 bool SocketsTcpCloseFunction::Prepare() { 383 params_ = sockets_tcp::Close::Params::Create(*args_); 384 EXTENSION_FUNCTION_VALIDATE(params_.get()); 385 return true; 386 } 387 388 void SocketsTcpCloseFunction::Work() { 389 ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id); 390 if (!socket) { 391 error_ = kSocketNotFoundError; 392 return; 393 } 394 395 RemoveSocket(params_->socket_id); 396 results_ = sockets_tcp::Close::Results::Create(); 397 } 398 399 SocketsTcpGetInfoFunction::SocketsTcpGetInfoFunction() {} 400 401 SocketsTcpGetInfoFunction::~SocketsTcpGetInfoFunction() {} 402 403 bool SocketsTcpGetInfoFunction::Prepare() { 404 params_ = sockets_tcp::GetInfo::Params::Create(*args_); 405 EXTENSION_FUNCTION_VALIDATE(params_.get()); 406 return true; 407 } 408 409 void SocketsTcpGetInfoFunction::Work() { 410 ResumableTCPSocket* socket = GetTcpSocket(params_->socket_id); 411 if (!socket) { 412 error_ = kSocketNotFoundError; 413 return; 414 } 415 416 linked_ptr<sockets_tcp::SocketInfo> socket_info = 417 CreateSocketInfo(params_->socket_id, socket); 418 results_ = sockets_tcp::GetInfo::Results::Create(*socket_info); 419 } 420 421 SocketsTcpGetSocketsFunction::SocketsTcpGetSocketsFunction() {} 422 423 SocketsTcpGetSocketsFunction::~SocketsTcpGetSocketsFunction() {} 424 425 bool SocketsTcpGetSocketsFunction::Prepare() { return true; } 426 427 void SocketsTcpGetSocketsFunction::Work() { 428 std::vector<linked_ptr<sockets_tcp::SocketInfo> > socket_infos; 429 base::hash_set<int>* resource_ids = GetSocketIds(); 430 if (resource_ids != NULL) { 431 for (base::hash_set<int>::iterator it = resource_ids->begin(); 432 it != resource_ids->end(); 433 ++it) { 434 int socket_id = *it; 435 ResumableTCPSocket* socket = GetTcpSocket(socket_id); 436 if (socket) { 437 socket_infos.push_back(CreateSocketInfo(socket_id, socket)); 438 } 439 } 440 } 441 results_ = sockets_tcp::GetSockets::Results::Create(socket_infos); 442 } 443 444 } // namespace core_api 445 } // namespace extensions 446