// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/extensions/api/bluetooth_socket/bluetooth_api_socket.h" #include "device/bluetooth/bluetooth_socket.h" #include "net/base/io_buffer.h" namespace { const char kSocketNotConnectedError[] = "Socket not connected"; const char kSocketNotListeningError[] = "Socket not listening"; } // namespace namespace extensions { // static static base::LazyInstance< BrowserContextKeyedAPIFactory > > g_server_factory = LAZY_INSTANCE_INITIALIZER; // static template <> BrowserContextKeyedAPIFactory >* ApiResourceManager::GetFactoryInstance() { return g_server_factory.Pointer(); } BluetoothApiSocket::BluetoothApiSocket(const std::string& owner_extension_id) : ApiResource(owner_extension_id), persistent_(false), buffer_size_(0), paused_(false), connected_(false) { DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); } BluetoothApiSocket::BluetoothApiSocket( const std::string& owner_extension_id, scoped_refptr socket, const std::string& device_address, const device::BluetoothUUID& uuid) : ApiResource(owner_extension_id), socket_(socket), device_address_(device_address), uuid_(uuid), persistent_(false), buffer_size_(0), paused_(true), connected_(true) { DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); } BluetoothApiSocket::~BluetoothApiSocket() { DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); if (socket_.get()) socket_->Close(); } void BluetoothApiSocket::AdoptConnectedSocket( scoped_refptr socket, const std::string& device_address, const device::BluetoothUUID& uuid) { DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); if (socket_.get()) socket_->Close(); socket_ = socket; device_address_ = device_address; uuid_ = uuid; connected_ = true; } void BluetoothApiSocket::AdoptListeningSocket( scoped_refptr socket, const device::BluetoothUUID& uuid) { DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); if (socket_.get()) socket_->Close(); socket_ = socket; device_address_ = ""; uuid_ = uuid; connected_ = false; } void BluetoothApiSocket::Disconnect(const base::Closure& callback) { DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); if (!socket_.get()) { callback.Run(); return; } connected_ = false; socket_->Disconnect(callback); } bool BluetoothApiSocket::IsPersistent() const { DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); return persistent_; } void BluetoothApiSocket::Receive( int count, const ReceiveCompletionCallback& success_callback, const ErrorCompletionCallback& error_callback) { DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); if (!socket_.get() || !IsConnected()) { error_callback.Run(BluetoothApiSocket::kNotConnected, kSocketNotConnectedError); return; } socket_->Receive(count, success_callback, base::Bind(&OnSocketReceiveError, error_callback)); } // static void BluetoothApiSocket::OnSocketReceiveError( const ErrorCompletionCallback& error_callback, device::BluetoothSocket::ErrorReason reason, const std::string& message) { DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); BluetoothApiSocket::ErrorReason error_reason; switch (reason) { case device::BluetoothSocket::kIOPending: error_reason = BluetoothApiSocket::kIOPending; break; case device::BluetoothSocket::kDisconnected: error_reason = BluetoothApiSocket::kDisconnected; break; case device::BluetoothSocket::kSystemError: error_reason = BluetoothApiSocket::kSystemError; break; default: NOTREACHED(); } error_callback.Run(error_reason, message); } void BluetoothApiSocket::Send(scoped_refptr buffer, int buffer_size, const SendCompletionCallback& success_callback, const ErrorCompletionCallback& error_callback) { DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); if (!socket_.get() || !IsConnected()) { error_callback.Run(BluetoothApiSocket::kNotConnected, kSocketNotConnectedError); return; } socket_->Send(buffer, buffer_size, success_callback, base::Bind(&OnSocketSendError, error_callback)); } // static void BluetoothApiSocket::OnSocketSendError( const ErrorCompletionCallback& error_callback, const std::string& message) { DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); error_callback.Run(BluetoothApiSocket::kSystemError, message); } void BluetoothApiSocket::Accept( const AcceptCompletionCallback& success_callback, const ErrorCompletionCallback& error_callback) { DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); if (!socket_.get() || IsConnected()) { error_callback.Run(BluetoothApiSocket::kNotListening, kSocketNotListeningError); return; } socket_->Accept(success_callback, base::Bind(&OnSocketAcceptError, error_callback)); } // static void BluetoothApiSocket::OnSocketAcceptError( const ErrorCompletionCallback& error_callback, const std::string& message) { DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); error_callback.Run(BluetoothApiSocket::kSystemError, message); } } // namespace extensions