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/bluetooth_socket/bluetooth_api_socket.h" 6 7#include "base/lazy_instance.h" 8#include "device/bluetooth/bluetooth_socket.h" 9#include "net/base/io_buffer.h" 10 11namespace { 12 13const char kSocketNotConnectedError[] = "Socket not connected"; 14const char kSocketNotListeningError[] = "Socket not listening"; 15 16} // namespace 17 18namespace extensions { 19 20// static 21static base::LazyInstance< 22 BrowserContextKeyedAPIFactory<ApiResourceManager<BluetoothApiSocket> > > 23 g_server_factory = LAZY_INSTANCE_INITIALIZER; 24 25// static 26template <> 27BrowserContextKeyedAPIFactory<ApiResourceManager<BluetoothApiSocket> >* 28ApiResourceManager<BluetoothApiSocket>::GetFactoryInstance() { 29 return g_server_factory.Pointer(); 30} 31 32BluetoothApiSocket::BluetoothApiSocket(const std::string& owner_extension_id) 33 : ApiResource(owner_extension_id), 34 persistent_(false), 35 buffer_size_(0), 36 paused_(false), 37 connected_(false) { 38 DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); 39} 40 41BluetoothApiSocket::BluetoothApiSocket( 42 const std::string& owner_extension_id, 43 scoped_refptr<device::BluetoothSocket> socket, 44 const std::string& device_address, 45 const device::BluetoothUUID& uuid) 46 : ApiResource(owner_extension_id), 47 socket_(socket), 48 device_address_(device_address), 49 uuid_(uuid), 50 persistent_(false), 51 buffer_size_(0), 52 paused_(true), 53 connected_(true) { 54 DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); 55} 56 57BluetoothApiSocket::~BluetoothApiSocket() { 58 DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); 59 if (socket_.get()) 60 socket_->Close(); 61} 62 63void BluetoothApiSocket::AdoptConnectedSocket( 64 scoped_refptr<device::BluetoothSocket> socket, 65 const std::string& device_address, 66 const device::BluetoothUUID& uuid) { 67 DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); 68 69 if (socket_.get()) 70 socket_->Close(); 71 72 socket_ = socket; 73 device_address_ = device_address; 74 uuid_ = uuid; 75 connected_ = true; 76} 77 78void BluetoothApiSocket::AdoptListeningSocket( 79 scoped_refptr<device::BluetoothSocket> socket, 80 const device::BluetoothUUID& uuid) { 81 DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); 82 83 if (socket_.get()) 84 socket_->Close(); 85 86 socket_ = socket; 87 device_address_ = ""; 88 uuid_ = uuid; 89 connected_ = false; 90} 91 92void BluetoothApiSocket::Disconnect(const base::Closure& callback) { 93 DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); 94 95 if (!socket_.get()) { 96 callback.Run(); 97 return; 98 } 99 100 connected_ = false; 101 socket_->Disconnect(callback); 102} 103 104bool BluetoothApiSocket::IsPersistent() const { 105 DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); 106 return persistent_; 107} 108 109void BluetoothApiSocket::Receive( 110 int count, 111 const ReceiveCompletionCallback& success_callback, 112 const ErrorCompletionCallback& error_callback) { 113 DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); 114 115 if (!socket_.get() || !IsConnected()) { 116 error_callback.Run(BluetoothApiSocket::kNotConnected, 117 kSocketNotConnectedError); 118 return; 119 } 120 121 socket_->Receive(count, 122 success_callback, 123 base::Bind(&OnSocketReceiveError, error_callback)); 124} 125 126// static 127void BluetoothApiSocket::OnSocketReceiveError( 128 const ErrorCompletionCallback& error_callback, 129 device::BluetoothSocket::ErrorReason reason, 130 const std::string& message) { 131 DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); 132 BluetoothApiSocket::ErrorReason error_reason; 133 switch (reason) { 134 case device::BluetoothSocket::kIOPending: 135 error_reason = BluetoothApiSocket::kIOPending; 136 break; 137 case device::BluetoothSocket::kDisconnected: 138 error_reason = BluetoothApiSocket::kDisconnected; 139 break; 140 case device::BluetoothSocket::kSystemError: 141 error_reason = BluetoothApiSocket::kSystemError; 142 break; 143 } 144 error_callback.Run(error_reason, message); 145} 146 147void BluetoothApiSocket::Send(scoped_refptr<net::IOBuffer> buffer, 148 int buffer_size, 149 const SendCompletionCallback& success_callback, 150 const ErrorCompletionCallback& error_callback) { 151 DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); 152 153 if (!socket_.get() || !IsConnected()) { 154 error_callback.Run(BluetoothApiSocket::kNotConnected, 155 kSocketNotConnectedError); 156 return; 157 } 158 159 socket_->Send(buffer, 160 buffer_size, 161 success_callback, 162 base::Bind(&OnSocketSendError, error_callback)); 163} 164 165// static 166void BluetoothApiSocket::OnSocketSendError( 167 const ErrorCompletionCallback& error_callback, 168 const std::string& message) { 169 DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); 170 error_callback.Run(BluetoothApiSocket::kSystemError, message); 171} 172 173void BluetoothApiSocket::Accept( 174 const AcceptCompletionCallback& success_callback, 175 const ErrorCompletionCallback& error_callback) { 176 DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); 177 178 if (!socket_.get() || IsConnected()) { 179 error_callback.Run(BluetoothApiSocket::kNotListening, 180 kSocketNotListeningError); 181 return; 182 } 183 184 socket_->Accept(success_callback, 185 base::Bind(&OnSocketAcceptError, error_callback)); 186} 187 188// static 189void BluetoothApiSocket::OnSocketAcceptError( 190 const ErrorCompletionCallback& error_callback, 191 const std::string& message) { 192 DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); 193 error_callback.Run(BluetoothApiSocket::kSystemError, message); 194} 195 196} // namespace extensions 197