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