summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/extensions/api/bluetooth/bluetooth_api.cc257
-rw-r--r--chrome/browser/extensions/api/bluetooth/bluetooth_api.h116
-rw-r--r--chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.cc59
-rw-r--r--chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.h20
-rw-r--r--chrome/browser/extensions/api/bluetooth/bluetooth_socket_event_dispatcher.h81
-rw-r--r--chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_api.cc355
-rw-r--r--chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_api.h170
-rw-r--r--chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_event_dispatcher.cc (renamed from chrome/browser/extensions/api/bluetooth/bluetooth_socket_event_dispatcher.cc)100
-rw-r--r--chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_event_dispatcher.h94
-rw-r--r--chrome/browser/extensions/browser_context_keyed_service_factories.cc2
10 files changed, 744 insertions, 510 deletions
diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_api.cc b/chrome/browser/extensions/api/bluetooth/bluetooth_api.cc
index 52c631e..77128f8 100644
--- a/chrome/browser/extensions/api/bluetooth/bluetooth_api.cc
+++ b/chrome/browser/extensions/api/bluetooth/bluetooth_api.cc
@@ -10,7 +10,6 @@
#include "base/memory/ref_counted.h"
#include "chrome/browser/extensions/api/bluetooth/bluetooth_api_utils.h"
#include "chrome/browser/extensions/api/bluetooth/bluetooth_event_router.h"
-#include "chrome/browser/extensions/api/bluetooth/bluetooth_socket_event_dispatcher.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/extensions/api/bluetooth.h"
#include "chrome/common/extensions/api/bluetooth/bluetooth_manifest_data.h"
@@ -60,7 +59,6 @@ const char kProfileAlreadyRegistered[] =
"This profile has already been registered";
const char kProfileNotFound[] = "Profile not found: invalid uuid";
const char kProfileRegistrationFailed[] = "Profile registration failed";
-const char kSocketNotFoundError[] = "Socket not found: invalid socket id";
const char kStartDiscoveryFailed[] = "Starting discovery failed";
const char kStopDiscoveryFailed[] = "Failed to stop discovery";
@@ -70,42 +68,6 @@ extensions::BluetoothEventRouter* GetEventRouter(BrowserContext* context) {
return extensions::BluetoothAPI::Get(context)->event_router();
}
-linked_ptr<bluetooth::Socket> CreateSocketInfo(int socket_id,
- BluetoothApiSocket* socket) {
- DCHECK(BrowserThread::CurrentlyOn(BluetoothApiSocket::kThreadId));
- linked_ptr<bluetooth::Socket> socket_info(new bluetooth::Socket());
- // This represents what we know about the socket, and does not call through
- // to the system.
- socket_info->id = socket_id;
- if (!socket->name().empty()) {
- socket_info->name.reset(new std::string(socket->name()));
- }
- socket_info->persistent = socket->persistent();
- if (socket->buffer_size() > 0) {
- socket_info->buffer_size.reset(new int(socket->buffer_size()));
- }
- socket_info->paused = socket->paused();
- socket_info->device.address = socket->device_address();
- socket_info->uuid = socket->uuid().canonical_value();
-
- return socket_info;
-}
-
-void SetSocketProperties(extensions::BluetoothApiSocket* socket,
- bluetooth::SocketProperties* properties) {
- if (properties->name.get()) {
- socket->set_name(*properties->name.get());
- }
- if (properties->persistent.get()) {
- socket->set_persistent(*properties->persistent.get());
- }
- if (properties->buffer_size.get()) {
- // buffer size is validated when issuing the actual Recv operation
- // on the socket.
- socket->set_buffer_size(*properties->buffer_size.get());
- }
-}
-
static void DispatchConnectionEventWorker(
void* browser_context_id,
const std::string& extension_id,
@@ -188,15 +150,6 @@ scoped_refptr<BluetoothAPI::SocketData> BluetoothAPI::socket_data() {
return socket_data_;
}
-scoped_refptr<api::BluetoothSocketEventDispatcher>
-BluetoothAPI::socket_event_dispatcher() {
- if (!socket_event_dispatcher_) {
- socket_event_dispatcher_ = new api::BluetoothSocketEventDispatcher(
- browser_context_, socket_data());
- }
- return socket_event_dispatcher_;
-}
-
void BluetoothAPI::Shutdown() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
EventRouter::Get(browser_context_)->UnregisterObserver(this);
@@ -296,38 +249,6 @@ void BluetoothAPI::RegisterSocketWithAdapterUI(
namespace api {
-BluetoothSocketApiFunction::BluetoothSocketApiFunction() {}
-
-BluetoothSocketApiFunction::~BluetoothSocketApiFunction() {}
-
-bool BluetoothSocketApiFunction::RunImpl() {
- if (!PrePrepare() || !Prepare()) {
- return false;
- }
- AsyncWorkStart();
- return true;
-}
-
-bool BluetoothSocketApiFunction::PrePrepare() {
- socket_data_ = BluetoothAPI::Get(browser_context())->socket_data();
- socket_event_dispatcher_ =
- BluetoothAPI::Get(browser_context())->socket_event_dispatcher();
- return socket_data_ && socket_event_dispatcher_;
-}
-
-void BluetoothSocketApiFunction::AsyncWorkStart() {
- Work();
- AsyncWorkCompleted();
-}
-
-void BluetoothSocketApiFunction::Work() {}
-
-void BluetoothSocketApiFunction::AsyncWorkCompleted() {
- SendResponse(Respond());
-}
-
-bool BluetoothSocketApiFunction::Respond() { return error_.empty(); }
-
BluetoothGetAdapterStateFunction::~BluetoothGetAdapterStateFunction() {}
bool BluetoothGetAdapterStateFunction::DoWork(
@@ -553,170 +474,40 @@ void BluetoothConnectFunction::OnErrorCallback(const std::string& error) {
SendResponse(false);
}
-BluetoothDisconnectFunction::BluetoothDisconnectFunction() {}
-
-BluetoothDisconnectFunction::~BluetoothDisconnectFunction() {}
-
-bool BluetoothDisconnectFunction::Prepare() {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- params_ = Disconnect::Params::Create(*args_);
- EXTENSION_FUNCTION_VALIDATE(params_.get() != NULL);
- return true;
-}
-
-void BluetoothDisconnectFunction::AsyncWorkStart() {
- DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
- BluetoothApiSocket* socket =
- socket_data_->Get(extension_id(), params_->options.socket_id);
- if (!socket) {
- error_ = kSocketNotFoundError;
- return;
- }
- socket->Disconnect(base::Bind(&BluetoothDisconnectFunction::OnSuccess, this));
-}
-
-void BluetoothDisconnectFunction::OnSuccess() {
- DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
- socket_data_->Remove(extension_id(), params_->options.socket_id);
- results_ = bluetooth::Disconnect::Results::Create();
- AsyncWorkCompleted();
-}
-
-BluetoothSendFunction::BluetoothSendFunction() : io_buffer_size_(0) {}
-
-BluetoothSendFunction::~BluetoothSendFunction() {}
-
-bool BluetoothSendFunction::Prepare() {
- DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
- params_ = Send::Params::Create(*args_);
- EXTENSION_FUNCTION_VALIDATE(params_.get() != NULL);
- io_buffer_size_ = params_->data.size();
- io_buffer_ = new net::WrappedIOBuffer(params_->data.data());
- return true;
-}
-
-void BluetoothSendFunction::AsyncWorkStart() {
- DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
- BluetoothApiSocket* socket =
- socket_data_->Get(extension_id(), params_->socket_id);
- if (!socket) {
- error_ = kSocketNotFoundError;
- return;
- }
- socket->Send(io_buffer_,
- io_buffer_size_,
- base::Bind(&BluetoothSendFunction::OnSendSuccess, this),
- base::Bind(&BluetoothSendFunction::OnSendError, this));
-}
-
-void BluetoothSendFunction::OnSendSuccess(int bytes_sent) {
- DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
- results_ = Send::Results::Create(bytes_sent);
- AsyncWorkCompleted();
-}
-
-void BluetoothSendFunction::OnSendError(const std::string& message) {
- DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
- error_ = message;
- AsyncWorkCompleted();
-}
-
-BluetoothUpdateSocketFunction::BluetoothUpdateSocketFunction() {}
-
-BluetoothUpdateSocketFunction::~BluetoothUpdateSocketFunction() {}
-
-bool BluetoothUpdateSocketFunction::Prepare() {
- params_ = bluetooth::UpdateSocket::Params::Create(*args_);
- EXTENSION_FUNCTION_VALIDATE(params_.get());
- return true;
-}
-
-void BluetoothUpdateSocketFunction::Work() {
- BluetoothApiSocket* socket =
- socket_data_->Get(extension_id(), params_->socket_id);
- if (!socket) {
- error_ = kSocketNotFoundError;
- return;
- }
-
- SetSocketProperties(socket, &params_.get()->properties);
- results_ = bluetooth::UpdateSocket::Results::Create();
+bool BluetoothDisconnectFunction::RunImpl() {
+ // TODO(keybuk): Remove.
+ SetError("Removed. Use chrome.bluetoothSocket.disconnect() instead.");
+ return false;
}
-BluetoothSetSocketPausedFunction::BluetoothSetSocketPausedFunction() {}
-
-BluetoothSetSocketPausedFunction::~BluetoothSetSocketPausedFunction() {}
-
-bool BluetoothSetSocketPausedFunction::Prepare() {
- params_ = bluetooth::SetSocketPaused::Params::Create(*args_);
- EXTENSION_FUNCTION_VALIDATE(params_.get());
- return true;
+bool BluetoothSendFunction::RunImpl() {
+ // TODO(keybuk): Remove.
+ SetError("Removed. Use chrome.bluetoothSocket.send() instead.");
+ return false;
}
-void BluetoothSetSocketPausedFunction::Work() {
- BluetoothApiSocket* socket =
- socket_data_->Get(extension_id(), params_->socket_id);
- if (!socket) {
- error_ = kSocketNotFoundError;
- return;
- }
-
- if (socket->paused() != params_->paused) {
- socket->set_paused(params_->paused);
- if (!params_->paused) {
- socket_event_dispatcher_->OnSocketResume(extension_->id(),
- params_->socket_id);
- }
- }
-
- results_ = bluetooth::SetSocketPaused::Results::Create();
+bool BluetoothUpdateSocketFunction::RunImpl() {
+ // TODO(keybuk): Remove.
+ SetError("Removed. Use chrome.bluetoothSocket.update() instead.");
+ return false;
}
-BluetoothGetSocketFunction::BluetoothGetSocketFunction() {}
-
-BluetoothGetSocketFunction::~BluetoothGetSocketFunction() {}
-
-bool BluetoothGetSocketFunction::Prepare() {
- params_ = bluetooth::GetSocket::Params::Create(*args_);
- EXTENSION_FUNCTION_VALIDATE(params_.get());
- return true;
+bool BluetoothSetSocketPausedFunction::RunImpl() {
+ // TODO(keybuk): Remove.
+ SetError("Removed. Use chrome.bluetoothSocket.setPaused() instead.");
+ return false;
}
-void BluetoothGetSocketFunction::Work() {
- BluetoothApiSocket* socket =
- socket_data_->Get(extension_id(), params_->socket_id);
- if (!socket) {
- error_ = kSocketNotFoundError;
- return;
- }
-
- linked_ptr<bluetooth::Socket> socket_info =
- CreateSocketInfo(params_->socket_id, socket);
- results_ = bluetooth::GetSocket::Results::Create(*socket_info);
+bool BluetoothGetSocketFunction::RunImpl() {
+ // TODO(keybuk): Remove.
+ SetError("Removed. Use chrome.bluetoothSocket.getInfo() instead.");
+ return false;
}
-BluetoothGetSocketsFunction::BluetoothGetSocketsFunction() {}
-
-BluetoothGetSocketsFunction::~BluetoothGetSocketsFunction() {}
-
-bool BluetoothGetSocketsFunction::Prepare() { return true; }
-
-void BluetoothGetSocketsFunction::Work() {
- std::vector<linked_ptr<bluetooth::Socket> > socket_infos;
- base::hash_set<int>* resource_ids =
- socket_data_->GetResourceIds(extension_id());
- if (resource_ids != NULL) {
- for (base::hash_set<int>::iterator it = resource_ids->begin();
- it != resource_ids->end();
- ++it) {
- int socket_id = *it;
- BluetoothApiSocket* socket = socket_data_->Get(extension_id(), socket_id);
- if (socket) {
- socket_infos.push_back(CreateSocketInfo(socket_id, socket));
- }
- }
- }
- results_ = bluetooth::GetSockets::Results::Create(socket_infos);
+bool BluetoothGetSocketsFunction::RunImpl() {
+ // TODO(keybuk): Remove.
+ SetError("Removed. Use chrome.bluetoothSocket.getSockets() instead.");
+ return false;
}
void BluetoothSetOutOfBandPairingDataFunction::OnSuccessCallback() {
diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_api.h b/chrome/browser/extensions/api/bluetooth/bluetooth_api.h
index 8cfa295..9ce771e 100644
--- a/chrome/browser/extensions/api/bluetooth/bluetooth_api.h
+++ b/chrome/browser/extensions/api/bluetooth/bluetooth_api.h
@@ -70,7 +70,6 @@ class BluetoothAPI : public BrowserContextKeyedAPI,
BluetoothEventRouter* event_router();
scoped_refptr<SocketData> socket_data();
- scoped_refptr<api::BluetoothSocketEventDispatcher> socket_event_dispatcher();
// KeyedService implementation.
virtual void Shutdown() OVERRIDE;
@@ -105,41 +104,10 @@ class BluetoothAPI : public BrowserContextKeyedAPI,
// Created lazily on first access.
scoped_ptr<BluetoothEventRouter> event_router_;
scoped_refptr<SocketData> socket_data_;
- scoped_refptr<api::BluetoothSocketEventDispatcher> socket_event_dispatcher_;
};
namespace api {
-class BluetoothSocketEventDispatcher;
-
-// Base class for methods dealing with BluetoothSocketApi and
-// ApiResourceManager<BluetoothSocketApi>.
-class BluetoothSocketApiFunction : public UIThreadExtensionFunction {
- public:
- BluetoothSocketApiFunction();
-
- protected:
- virtual ~BluetoothSocketApiFunction();
-
- // ExtensionFunction::RunImpl()
- virtual bool RunImpl() OVERRIDE;
-
- bool PrePrepare();
- bool Respond();
- void AsyncWorkCompleted();
-
- virtual bool Prepare() = 0;
- virtual void Work();
- virtual void AsyncWorkStart();
-
- content::BrowserThread::ID work_thread_id() const {
- return BluetoothApiSocket::kThreadId;
- }
-
- scoped_refptr<BluetoothAPI::SocketData> socket_data_;
- scoped_refptr<api::BluetoothSocketEventDispatcher> socket_event_dispatcher_;
-};
-
class BluetoothGetAdapterStateFunction : public BluetoothExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("bluetooth.getAdapterState",
@@ -219,107 +187,71 @@ class BluetoothConnectFunction : public BluetoothExtensionFunction {
void OnErrorCallback(const std::string& error);
};
-class BluetoothDisconnectFunction : public BluetoothSocketApiFunction {
+class BluetoothDisconnectFunction : public UIThreadExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("bluetooth.disconnect", BLUETOOTH_DISCONNECT)
- BluetoothDisconnectFunction();
protected:
- virtual ~BluetoothDisconnectFunction();
+ virtual ~BluetoothDisconnectFunction() {}
- // AsyncApiFunction:
- virtual bool Prepare() OVERRIDE;
- virtual void AsyncWorkStart() OVERRIDE;
-
- private:
- void OnSuccess();
-
- scoped_ptr<bluetooth::Disconnect::Params> params_;
+ // UIThreadExtensionFunction:
+ virtual bool RunImpl() OVERRIDE;
};
-class BluetoothSendFunction : public BluetoothSocketApiFunction {
+class BluetoothSendFunction : public UIThreadExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("bluetooth.send", BLUETOOTH_WRITE)
- BluetoothSendFunction();
protected:
- virtual ~BluetoothSendFunction();
+ virtual ~BluetoothSendFunction() {}
- // AsyncApiFunction:
- virtual bool Prepare() OVERRIDE;
- virtual void AsyncWorkStart() OVERRIDE;
-
- private:
- void OnSendSuccess(int bytes_sent);
- void OnSendError(const std::string& message);
-
- scoped_ptr<bluetooth::Send::Params> params_;
- scoped_refptr<net::IOBuffer> io_buffer_;
- size_t io_buffer_size_;
+ // UIThreadExtensionFunction:
+ virtual bool RunImpl() OVERRIDE;
};
-class BluetoothUpdateSocketFunction : public BluetoothSocketApiFunction {
+class BluetoothUpdateSocketFunction : public UIThreadExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("bluetooth.updateSocket", BLUETOOTH_UPDATE_SOCKET)
- BluetoothUpdateSocketFunction();
protected:
- virtual ~BluetoothUpdateSocketFunction();
+ virtual ~BluetoothUpdateSocketFunction() {}
- // AsyncApiFunction:
- virtual bool Prepare() OVERRIDE;
- virtual void Work() OVERRIDE;
-
- private:
- scoped_ptr<bluetooth::UpdateSocket::Params> params_;
+ // UIThreadExtensionFunction:
+ virtual bool RunImpl() OVERRIDE;
};
-class BluetoothSetSocketPausedFunction : public BluetoothSocketApiFunction {
+class BluetoothSetSocketPausedFunction : public UIThreadExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("bluetooth.setSocketPaused",
BLUETOOTH_SET_SOCKET_PAUSED)
- BluetoothSetSocketPausedFunction();
protected:
- virtual ~BluetoothSetSocketPausedFunction();
-
- // AsyncApiFunction:
- virtual bool Prepare() OVERRIDE;
- virtual void Work() OVERRIDE;
+ virtual ~BluetoothSetSocketPausedFunction() {}
- private:
- scoped_ptr<bluetooth::SetSocketPaused::Params> params_;
+ // UIThreadExtensionFunction:
+ virtual bool RunImpl() OVERRIDE;
};
-class BluetoothGetSocketFunction : public BluetoothSocketApiFunction {
+class BluetoothGetSocketFunction : public UIThreadExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("bluetooth.getSocket", BLUETOOTH_GET_SOCKET)
- BluetoothGetSocketFunction();
-
protected:
- virtual ~BluetoothGetSocketFunction();
-
- // AsyncApiFunction:
- virtual bool Prepare() OVERRIDE;
- virtual void Work() OVERRIDE;
+ virtual ~BluetoothGetSocketFunction() {}
- private:
- scoped_ptr<bluetooth::GetSocket::Params> params_;
+ // UIThreadExtensionFunction:
+ virtual bool RunImpl() OVERRIDE;
};
-class BluetoothGetSocketsFunction : public BluetoothSocketApiFunction {
+class BluetoothGetSocketsFunction : public UIThreadExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("bluetooth.getSockets", BLUETOOTH_GET_SOCKETS)
- BluetoothGetSocketsFunction();
-
protected:
- virtual ~BluetoothGetSocketsFunction();
+ virtual ~BluetoothGetSocketsFunction() {}
- // AsyncApiFunction:
- virtual bool Prepare() OVERRIDE;
- virtual void Work() OVERRIDE;
+ // UIThreadExtensionFunction:
+ virtual bool RunImpl() OVERRIDE;
};
class BluetoothGetLocalOutOfBandPairingDataFunction
diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.cc b/chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.cc
index e818152..2be7f3e 100644
--- a/chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.cc
+++ b/chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.cc
@@ -7,6 +7,12 @@
#include "device/bluetooth/bluetooth_socket.h"
#include "net/base/io_buffer.h"
+namespace {
+
+const char kSocketNotConnectedError[] = "Socket not connected";
+
+} // namespace
+
namespace extensions {
// static
@@ -21,6 +27,15 @@ ApiResourceManager<BluetoothApiSocket>::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<device::BluetoothSocket> socket,
@@ -32,17 +47,25 @@ BluetoothApiSocket::BluetoothApiSocket(
uuid_(uuid),
persistent_(false),
buffer_size_(0),
- paused_(true) {
+ paused_(true),
+ connected_(true) {
DCHECK(content::BrowserThread::CurrentlyOn(kThreadId));
}
BluetoothApiSocket::~BluetoothApiSocket() {
DCHECK(content::BrowserThread::CurrentlyOn(kThreadId));
- socket_->Close();
+ if (socket_.get())
+ socket_->Close();
}
void BluetoothApiSocket::Disconnect(const base::Closure& success_callback) {
DCHECK(content::BrowserThread::CurrentlyOn(kThreadId));
+
+ if (!socket_.get() || !IsConnected()) {
+ success_callback.Run();
+ return;
+ }
+
socket_->Disconnect(success_callback);
}
@@ -54,8 +77,15 @@ bool BluetoothApiSocket::IsPersistent() const {
void BluetoothApiSocket::Receive(
int count,
const ReceiveCompletionCallback& success_callback,
- const ReceiveErrorCompletionCallback& error_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));
@@ -63,7 +93,7 @@ void BluetoothApiSocket::Receive(
// static
void BluetoothApiSocket::OnSocketReceiveError(
- const ReceiveErrorCompletionCallback& error_callback,
+ const ErrorCompletionCallback& error_callback,
device::BluetoothSocket::ErrorReason reason,
const std::string& message) {
DCHECK(content::BrowserThread::CurrentlyOn(kThreadId));
@@ -89,7 +119,26 @@ void BluetoothApiSocket::Send(scoped_refptr<net::IOBuffer> buffer,
const SendCompletionCallback& success_callback,
const ErrorCompletionCallback& error_callback) {
DCHECK(content::BrowserThread::CurrentlyOn(kThreadId));
- socket_->Send(buffer, buffer_size, success_callback, error_callback);
+
+ 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);
+
}
} // namespace extensions
diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.h b/chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.h
index 02b0bbd..965cc51 100644
--- a/chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.h
+++ b/chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.h
@@ -23,16 +23,15 @@ namespace extensions {
// class. All methods must be called on the |kThreadId| thread.
class BluetoothApiSocket : public ApiResource {
public:
- enum ErrorReason { kSystemError, kIOPending, kDisconnected };
+ enum ErrorReason { kSystemError, kNotConnected, kIOPending, kDisconnected };
typedef base::Callback<void(int)> SendCompletionCallback;
typedef base::Callback<void(int, scoped_refptr<net::IOBuffer> io_buffer)>
ReceiveCompletionCallback;
- typedef base::Callback<void(const std::string& error_message)>
- ErrorCompletionCallback;
typedef base::Callback<void(ErrorReason, const std::string& error_message)>
- ReceiveErrorCompletionCallback;
+ ErrorCompletionCallback;
+ explicit BluetoothApiSocket(const std::string& owner_extension_id);
BluetoothApiSocket(const std::string& owner_extension_id,
scoped_refptr<device::BluetoothSocket> socket,
const std::string& device_address,
@@ -49,7 +48,7 @@ class BluetoothApiSocket : public ApiResource {
// |kIOPending| error.
virtual void Receive(int count,
const ReceiveCompletionCallback& success_callback,
- const ReceiveErrorCompletionCallback& error_callback);
+ const ErrorCompletionCallback& error_callback);
// Sends |buffer| to the socket and calls |success_callback| when data has
// been successfully sent. |buffer_size| is the numberof bytes contained in
@@ -80,6 +79,8 @@ class BluetoothApiSocket : public ApiResource {
bool paused() const { return paused_; }
void set_paused(bool paused) { paused_ = paused; }
+ bool IsConnected() const { return connected_; }
+
// Platform specific implementations of |BluetoothSocket| require being called
// on the UI thread.
static const content::BrowserThread::ID kThreadId =
@@ -90,10 +91,14 @@ class BluetoothApiSocket : public ApiResource {
static const char* service_name() { return "BluetoothApiSocketManager"; }
static void OnSocketReceiveError(
- const ReceiveErrorCompletionCallback& error_callback,
+ const ErrorCompletionCallback& error_callback,
device::BluetoothSocket::ErrorReason reason,
const std::string& message);
+ static void OnSocketSendError(
+ const ErrorCompletionCallback& error_callback,
+ const std::string& message);
+
// The underlying device socket instance.
scoped_refptr<device::BluetoothSocket> socket_;
@@ -117,6 +122,9 @@ class BluetoothApiSocket : public ApiResource {
// more data - see bluetooth.idl.
bool paused_;
+ // Flag indicating whether a socket is connected.
+ bool connected_;
+
DISALLOW_COPY_AND_ASSIGN(BluetoothApiSocket);
};
diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_socket_event_dispatcher.h b/chrome/browser/extensions/api/bluetooth/bluetooth_socket_event_dispatcher.h
deleted file mode 100644
index 9f0c2a5..0000000
--- a/chrome/browser/extensions/api/bluetooth/bluetooth_socket_event_dispatcher.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// 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.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_API_BLUETOOTH_BLUETOOTH_SOCKET_EVENT_DISPATCHER_H_
-#define CHROME_BROWSER_EXTENSIONS_API_BLUETOOTH_BLUETOOTH_SOCKET_EVENT_DISPATCHER_H_
-
-#include "chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.h"
-#include "extensions/browser/api/api_resource_manager.h"
-#include "extensions/browser/browser_context_keyed_api_factory.h"
-
-namespace content {
-class BrowserContext;
-}
-
-namespace extensions {
-struct Event;
-class BluetoothApiSocket;
-}
-
-namespace extensions {
-namespace api {
-
-// Dispatch events related to "bluetooth" sockets from callback on native socket
-// instances. There is one instance per browser context.
-class BluetoothSocketEventDispatcher
- : public base::RefCountedThreadSafe<BluetoothSocketEventDispatcher> {
- public:
- typedef ApiResourceManager<BluetoothApiSocket>::ApiResourceData SocketData;
- explicit BluetoothSocketEventDispatcher(
- content::BrowserContext* context,
- scoped_refptr<SocketData> socket_data);
-
- // Socket is active again, start receiving data from it.
- void OnSocketResume(const std::string& extension_id, int socket_id);
-
- private:
- friend class base::RefCountedThreadSafe<BluetoothSocketEventDispatcher>;
- virtual ~BluetoothSocketEventDispatcher();
-
- // base::Bind supports methods with up to 6 parameters. ReceiveParams is used
- // as a workaround that limitation for invoking StartReceive.
- struct ReceiveParams {
- ReceiveParams();
- ~ReceiveParams();
-
- std::string extension_id;
- int socket_id;
- };
-
- // Start a receive and register a callback.
- void StartReceive(const ReceiveParams& params);
-
- // Called when socket receive data.
- void ReceiveCallback(const ReceiveParams& params,
- int bytes_read,
- scoped_refptr<net::IOBuffer> io_buffer);
-
- // Called when socket receive data.
- void ReceiveErrorCallback(const ReceiveParams& params,
- BluetoothApiSocket::ErrorReason error_reason,
- const std::string& error);
-
- // Post an extension event from IO to UI thread
- void PostEvent(const ReceiveParams& params, scoped_ptr<Event> event);
-
- // Dispatch an extension event on to EventRouter instance on UI thread.
- void DispatchEvent(const std::string& extension_id, scoped_ptr<Event> event);
-
- // Usually FILE thread (except for unit testing).
- content::BrowserThread::ID thread_id_;
- void* browser_context_id_;
- scoped_refptr<SocketData> socket_data_;
-
- DISALLOW_COPY_AND_ASSIGN(BluetoothSocketEventDispatcher);
-};
-
-} // namespace api
-} // namespace extensions
-
-#endif // CHROME_BROWSER_EXTENSIONS_API_BLUETOOTH_BLUETOOTH_SOCKET_EVENT_DISPATCHER_H_
diff --git a/chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_api.cc b/chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_api.cc
index 9ecdca5..0fd43f5 100644
--- a/chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_api.cc
+++ b/chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_api.cc
@@ -4,25 +4,208 @@
#include "chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_api.h"
+#include "chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.h"
+#include "chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_event_dispatcher.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
+#include "net/base/io_buffer.h"
+
+using content::BrowserThread;
+using extensions::BluetoothApiSocket;
+using extensions::api::bluetooth_socket::SocketInfo;
+using extensions::api::bluetooth_socket::SocketProperties;
+
+namespace {
+
+const char kSocketNotFoundError[] = "Socket not found";
+
+linked_ptr<SocketInfo> CreateSocketInfo(int socket_id,
+ BluetoothApiSocket* socket) {
+ DCHECK(BrowserThread::CurrentlyOn(BluetoothApiSocket::kThreadId));
+ linked_ptr<SocketInfo> socket_info(new SocketInfo());
+ // This represents what we know about the socket, and does not call through
+ // to the system.
+ socket_info->socket_id = socket_id;
+ if (!socket->name().empty()) {
+ socket_info->name.reset(new std::string(socket->name()));
+ }
+ socket_info->persistent = socket->persistent();
+ if (socket->buffer_size() > 0) {
+ socket_info->buffer_size.reset(new int(socket->buffer_size()));
+ }
+ socket_info->paused = socket->paused();
+ socket_info->connected = socket->IsConnected();
+
+ // TODO(keybuk): These should not be present if socket isn't connected or
+ // listening.
+ socket_info->address.reset(new std::string(socket->device_address()));
+ socket_info->uuid.reset(new std::string(socket->uuid().canonical_value()));
+
+ return socket_info;
+}
+
+void SetSocketProperties(BluetoothApiSocket* socket,
+ SocketProperties* properties) {
+ if (properties->name.get()) {
+ socket->set_name(*properties->name.get());
+ }
+ if (properties->persistent.get()) {
+ socket->set_persistent(*properties->persistent.get());
+ }
+ if (properties->buffer_size.get()) {
+ // buffer size is validated when issuing the actual Recv operation
+ // on the socket.
+ socket->set_buffer_size(*properties->buffer_size.get());
+ }
+}
+
+} // namespace
+
namespace extensions {
namespace api {
-bool BluetoothSocketCreateFunction::RunImpl() {
- // TODO(keybuk): Implement.
- SetError("Not yet implemented.");
- return false;
+BluetoothSocketAsyncApiFunction::BluetoothSocketAsyncApiFunction() {}
+
+BluetoothSocketAsyncApiFunction::~BluetoothSocketAsyncApiFunction() {}
+
+bool BluetoothSocketAsyncApiFunction::RunImpl() {
+ if (!PrePrepare() || !Prepare()) {
+ return false;
+ }
+ AsyncWorkStart();
+ return true;
}
-bool BluetoothSocketUpdateFunction::RunImpl() {
- // TODO(keybuk): Implement.
- SetError("Not yet implemented.");
- return false;
+bool BluetoothSocketAsyncApiFunction::PrePrepare() {
+ manager_ = ApiResourceManager<BluetoothApiSocket>::Get(browser_context());
+ DCHECK(manager_)
+ << "There is no socket manager. "
+ "If this assertion is failing during a test, then it is likely that "
+ "TestExtensionSystem is failing to provide an instance of "
+ "ApiResourceManager<BluetoothApiSocket>.";
+ return manager_ != NULL;
}
-bool BluetoothSocketSetPausedFunction::RunImpl() {
- // TODO(keybuk): Implement.
- SetError("Not yet implemented.");
- return false;
+bool BluetoothSocketAsyncApiFunction::Respond() { return error_.empty(); }
+
+void BluetoothSocketAsyncApiFunction::AsyncWorkCompleted() {
+ SendResponse(Respond());
+}
+
+void BluetoothSocketAsyncApiFunction::Work() {}
+
+void BluetoothSocketAsyncApiFunction::AsyncWorkStart() {
+ Work();
+ AsyncWorkCompleted();
+}
+
+int BluetoothSocketAsyncApiFunction::AddSocket(BluetoothApiSocket* socket) {
+ return manager_->Add(socket);
+}
+
+content::BrowserThread::ID
+BluetoothSocketAsyncApiFunction::work_thread_id() const {
+ return BluetoothApiSocket::kThreadId;
+}
+
+BluetoothApiSocket* BluetoothSocketAsyncApiFunction::GetSocket(
+ int api_resource_id) {
+ return manager_->Get(extension_id(), api_resource_id);
+}
+
+void BluetoothSocketAsyncApiFunction::RemoveSocket(int api_resource_id) {
+ manager_->Remove(extension_id(), api_resource_id);
+}
+
+base::hash_set<int>* BluetoothSocketAsyncApiFunction::GetSocketIds() {
+ return manager_->GetResourceIds(extension_id());
+}
+
+BluetoothSocketCreateFunction::BluetoothSocketCreateFunction() {}
+
+BluetoothSocketCreateFunction::~BluetoothSocketCreateFunction() {}
+
+bool BluetoothSocketCreateFunction::Prepare() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ params_ = bluetooth_socket::Create::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(params_.get());
+ return true;
+}
+
+void BluetoothSocketCreateFunction::Work() {
+ DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
+
+ BluetoothApiSocket* socket = new BluetoothApiSocket(extension_id());
+
+ bluetooth_socket::SocketProperties* properties =
+ params_.get()->properties.get();
+ if (properties) {
+ SetSocketProperties(socket, properties);
+ }
+
+ bluetooth_socket::CreateInfo create_info;
+ create_info.socket_id = AddSocket(socket);
+ results_ = bluetooth_socket::Create::Results::Create(create_info);
+ AsyncWorkCompleted();
+}
+
+BluetoothSocketUpdateFunction::BluetoothSocketUpdateFunction() {}
+
+BluetoothSocketUpdateFunction::~BluetoothSocketUpdateFunction() {}
+
+bool BluetoothSocketUpdateFunction::Prepare() {
+ params_ = bluetooth_socket::Update::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(params_.get());
+ return true;
+}
+
+void BluetoothSocketUpdateFunction::Work() {
+ BluetoothApiSocket* socket = GetSocket(params_->socket_id);
+ if (!socket) {
+ error_ = kSocketNotFoundError;
+ return;
+ }
+
+ SetSocketProperties(socket, &params_.get()->properties);
+ results_ = bluetooth_socket::Update::Results::Create();
+}
+
+BluetoothSocketSetPausedFunction::BluetoothSocketSetPausedFunction()
+ : socket_event_dispatcher_(NULL) {}
+
+BluetoothSocketSetPausedFunction::~BluetoothSocketSetPausedFunction() {}
+
+bool BluetoothSocketSetPausedFunction::Prepare() {
+ params_ = bluetooth_socket::SetPaused::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(params_.get());
+
+ socket_event_dispatcher_ =
+ BluetoothSocketEventDispatcher::Get(browser_context());
+ DCHECK(socket_event_dispatcher_)
+ << "There is no socket event dispatcher. "
+ "If this assertion is failing during a test, then it is likely that "
+ "TestExtensionSystem is failing to provide an instance of "
+ "BluetoothSocketEventDispatcher.";
+ return socket_event_dispatcher_ != NULL;
+}
+
+void BluetoothSocketSetPausedFunction::Work() {
+ BluetoothApiSocket* socket = GetSocket(params_->socket_id);
+ if (!socket) {
+ error_ = kSocketNotFoundError;
+ return;
+ }
+
+ if (socket->paused() != params_->paused) {
+ socket->set_paused(params_->paused);
+ if (!params_->paused) {
+ socket_event_dispatcher_->OnSocketResume(extension_id(),
+ params_->socket_id);
+ }
+ }
+
+ results_ = bluetooth_socket::SetPaused::Results::Create();
}
bool BluetoothSocketListenUsingRfcommFunction::RunImpl() {
@@ -49,34 +232,142 @@ bool BluetoothSocketConnectFunction::RunImpl() {
return false;
}
-bool BluetoothSocketDisconnectFunction::RunImpl() {
- // TODO(keybuk): Implement.
- SetError("Not yet implemented.");
- return false;
+BluetoothSocketDisconnectFunction::BluetoothSocketDisconnectFunction() {}
+
+BluetoothSocketDisconnectFunction::~BluetoothSocketDisconnectFunction() {}
+
+bool BluetoothSocketDisconnectFunction::Prepare() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ params_ = bluetooth_socket::Disconnect::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(params_.get());
+ return true;
}
-bool BluetoothSocketCloseFunction::RunImpl() {
- // TODO(keybuk): Implement.
- SetError("Not yet implemented.");
- return false;
+void BluetoothSocketDisconnectFunction::AsyncWorkStart() {
+ DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
+ BluetoothApiSocket* socket = GetSocket(params_->socket_id);
+ if (!socket) {
+ error_ = kSocketNotFoundError;
+ return;
+ }
+
+ socket->Disconnect(base::Bind(&BluetoothSocketDisconnectFunction::OnSuccess,
+ this));
}
-bool BluetoothSocketSendFunction::RunImpl() {
- // TODO(keybuk): Implement.
- SetError("Not yet implemented.");
- return false;
+void BluetoothSocketDisconnectFunction::OnSuccess() {
+ DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
+ results_ = bluetooth_socket::Disconnect::Results::Create();
+ AsyncWorkCompleted();
}
-bool BluetoothSocketGetInfoFunction::RunImpl() {
- // TODO(keybuk): Implement.
- SetError("Not yet implemented.");
- return false;
+BluetoothSocketCloseFunction::BluetoothSocketCloseFunction() {}
+
+BluetoothSocketCloseFunction::~BluetoothSocketCloseFunction() {}
+
+bool BluetoothSocketCloseFunction::Prepare() {
+ params_ = bluetooth_socket::Close::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(params_.get());
+ return true;
}
-bool BluetoothSocketGetSocketsFunction::RunImpl() {
- // TODO(keybuk): Implement.
- SetError("Not yet implemented.");
- return false;
+void BluetoothSocketCloseFunction::Work() {
+ BluetoothApiSocket* socket = GetSocket(params_->socket_id);
+ if (!socket) {
+ error_ = kSocketNotFoundError;
+ return;
+ }
+
+ RemoveSocket(params_->socket_id);
+ results_ = bluetooth_socket::Close::Results::Create();
+}
+
+BluetoothSocketSendFunction::BluetoothSocketSendFunction()
+ : io_buffer_size_(0) {}
+
+BluetoothSocketSendFunction::~BluetoothSocketSendFunction() {}
+
+bool BluetoothSocketSendFunction::Prepare() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ params_ = bluetooth_socket::Send::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(params_.get());
+
+ io_buffer_size_ = params_->data.size();
+ io_buffer_ = new net::WrappedIOBuffer(params_->data.data());
+ return true;
+}
+
+void BluetoothSocketSendFunction::AsyncWorkStart() {
+ DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
+ BluetoothApiSocket* socket = GetSocket(params_->socket_id);
+ if (!socket) {
+ error_ = kSocketNotFoundError;
+ return;
+ }
+
+ socket->Send(io_buffer_,
+ io_buffer_size_,
+ base::Bind(&BluetoothSocketSendFunction::OnSuccess, this),
+ base::Bind(&BluetoothSocketSendFunction::OnError, this));
+}
+
+void BluetoothSocketSendFunction::OnSuccess(int bytes_sent) {
+ DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
+ results_ = bluetooth_socket::Send::Results::Create(bytes_sent);
+ AsyncWorkCompleted();
+}
+
+void BluetoothSocketSendFunction::OnError(
+ BluetoothApiSocket::ErrorReason reason,
+ const std::string& message) {
+ DCHECK(BrowserThread::CurrentlyOn(work_thread_id()));
+ error_ = message;
+ AsyncWorkCompleted();
+}
+
+BluetoothSocketGetInfoFunction::BluetoothSocketGetInfoFunction() {}
+
+BluetoothSocketGetInfoFunction::~BluetoothSocketGetInfoFunction() {}
+
+bool BluetoothSocketGetInfoFunction::Prepare() {
+ params_ = bluetooth_socket::GetInfo::Params::Create(*args_);
+ EXTENSION_FUNCTION_VALIDATE(params_.get());
+ return true;
+}
+
+void BluetoothSocketGetInfoFunction::Work() {
+ BluetoothApiSocket* socket = GetSocket(params_->socket_id);
+ if (!socket) {
+ error_ = kSocketNotFoundError;
+ return;
+ }
+
+ linked_ptr<bluetooth_socket::SocketInfo> socket_info =
+ CreateSocketInfo(params_->socket_id, socket);
+ results_ = bluetooth_socket::GetInfo::Results::Create(*socket_info);
+}
+
+BluetoothSocketGetSocketsFunction::BluetoothSocketGetSocketsFunction() {}
+
+BluetoothSocketGetSocketsFunction::~BluetoothSocketGetSocketsFunction() {}
+
+bool BluetoothSocketGetSocketsFunction::Prepare() { return true; }
+
+void BluetoothSocketGetSocketsFunction::Work() {
+ std::vector<linked_ptr<bluetooth_socket::SocketInfo> > socket_infos;
+ base::hash_set<int>* resource_ids = GetSocketIds();
+ if (resource_ids != NULL) {
+ for (base::hash_set<int>::iterator it = resource_ids->begin();
+ it != resource_ids->end();
+ ++it) {
+ int socket_id = *it;
+ BluetoothApiSocket* socket = GetSocket(socket_id);
+ if (socket) {
+ socket_infos.push_back(CreateSocketInfo(socket_id, socket));
+ }
+ }
+ }
+ results_ = bluetooth_socket::GetSockets::Results::Create(socket_infos);
}
} // namespace api
diff --git a/chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_api.h b/chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_api.h
index 02f7937..c7cd376 100644
--- a/chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_api.h
+++ b/chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_api.h
@@ -5,44 +5,113 @@
#ifndef CHROME_BROWSER_EXTENSIONS_API_BLUETOOTH_SOCKET_BLUETOOTH_SOCKET_API_H_
#define CHROME_BROWSER_EXTENSIONS_API_BLUETOOTH_SOCKET_BLUETOOTH_SOCKET_API_H_
+#include <string>
+
+#include "base/containers/hash_tables.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.h"
+#include "chrome/common/extensions/api/bluetooth_socket.h"
+#include "extensions/browser/api/api_resource_manager.h"
+#include "extensions/browser/api/async_api_function.h"
#include "extensions/browser/extension_function.h"
#include "extensions/browser/extension_function_histogram_value.h"
+namespace net {
+class IOBuffer;
+}
+
namespace extensions {
+
namespace api {
-class BluetoothSocketCreateFunction : public UIThreadExtensionFunction {
+class BluetoothSocketEventDispatcher;
+
+// Asynchronous API function that performs its work on the BluetoothApiSocket
+// thread while providing methods to manage resources of that class. This
+// follows the pattern of AsyncApiFunction, but does not derive from it,
+// because BluetoothApiSocket methods must be called on the UI Thread.
+class BluetoothSocketAsyncApiFunction : public UIThreadExtensionFunction {
public:
- DECLARE_EXTENSION_FUNCTION("bluetoothSocket.create", BLUETOOTHSOCKET_CREATE);
+ BluetoothSocketAsyncApiFunction();
protected:
- virtual ~BluetoothSocketCreateFunction() {}
+ virtual ~BluetoothSocketAsyncApiFunction();
- // UIThreadExtensionFunction override:
+ // UIThreadExtensionFunction:
virtual bool RunImpl() OVERRIDE;
+
+ bool PrePrepare();
+ bool Respond();
+ void AsyncWorkCompleted();
+
+ virtual bool Prepare() = 0;
+ virtual void Work();
+ virtual void AsyncWorkStart();
+
+ content::BrowserThread::ID work_thread_id() const;
+
+ int AddSocket(BluetoothApiSocket* socket);
+ BluetoothApiSocket* GetSocket(int api_resource_id);
+ void RemoveSocket(int api_resource_id);
+ base::hash_set<int>* GetSocketIds();
+
+ private:
+ ApiResourceManager<BluetoothApiSocket>* manager_;
+};
+
+class BluetoothSocketCreateFunction : public BluetoothSocketAsyncApiFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("bluetoothSocket.create", BLUETOOTHSOCKET_CREATE);
+
+ BluetoothSocketCreateFunction();
+
+ protected:
+ virtual ~BluetoothSocketCreateFunction();
+
+ // BluetoothSocketAsyncApiFunction:
+ virtual bool Prepare() OVERRIDE;
+ virtual void Work() OVERRIDE;
+
+ private:
+ scoped_ptr<bluetooth_socket::Create::Params> params_;
};
-class BluetoothSocketUpdateFunction : public UIThreadExtensionFunction {
+class BluetoothSocketUpdateFunction : public BluetoothSocketAsyncApiFunction {
public:
DECLARE_EXTENSION_FUNCTION("bluetoothSocket.update", BLUETOOTHSOCKET_UPDATE);
+ BluetoothSocketUpdateFunction();
+
protected:
- virtual ~BluetoothSocketUpdateFunction() {}
+ virtual ~BluetoothSocketUpdateFunction();
- // UIThreadExtensionFunction override:
- virtual bool RunImpl() OVERRIDE;
+ // BluetoothSocketAsyncApiFunction:
+ virtual bool Prepare() OVERRIDE;
+ virtual void Work() OVERRIDE;
+
+ private:
+ scoped_ptr<bluetooth_socket::Update::Params> params_;
};
-class BluetoothSocketSetPausedFunction : public UIThreadExtensionFunction {
+class BluetoothSocketSetPausedFunction
+ : public BluetoothSocketAsyncApiFunction {
public:
DECLARE_EXTENSION_FUNCTION("bluetoothSocket.setPaused",
BLUETOOTHSOCKET_SETPAUSED);
+ BluetoothSocketSetPausedFunction();
+
protected:
- virtual ~BluetoothSocketSetPausedFunction() {}
+ virtual ~BluetoothSocketSetPausedFunction();
- // UIThreadExtensionFunction override:
- virtual bool RunImpl() OVERRIDE;
+ // BluetoothSocketAsyncApiFunction:
+ virtual bool Prepare() OVERRIDE;
+ virtual void Work() OVERRIDE;
+
+ private:
+ scoped_ptr<bluetooth_socket::SetPaused::Params> params_;
+ BluetoothSocketEventDispatcher* socket_event_dispatcher_;
};
class BluetoothSocketListenUsingRfcommFunction
@@ -96,62 +165,99 @@ class BluetoothSocketConnectFunction : public UIThreadExtensionFunction {
virtual bool RunImpl() OVERRIDE;
};
-class BluetoothSocketDisconnectFunction : public UIThreadExtensionFunction {
+class BluetoothSocketDisconnectFunction
+ : public BluetoothSocketAsyncApiFunction {
public:
DECLARE_EXTENSION_FUNCTION("bluetoothSocket.disconnect",
BLUETOOTHSOCKET_DISCONNECT);
+ BluetoothSocketDisconnectFunction();
+
protected:
- virtual ~BluetoothSocketDisconnectFunction() {}
+ virtual ~BluetoothSocketDisconnectFunction();
- // UIThreadExtensionFunction override:
- virtual bool RunImpl() OVERRIDE;
+ // BluetoothSocketAsyncApiFunction:
+ virtual bool Prepare() OVERRIDE;
+ virtual void AsyncWorkStart() OVERRIDE;
+
+ private:
+ virtual void OnSuccess();
+
+ scoped_ptr<bluetooth_socket::Disconnect::Params> params_;
};
-class BluetoothSocketCloseFunction : public UIThreadExtensionFunction {
+class BluetoothSocketCloseFunction : public BluetoothSocketAsyncApiFunction {
public:
DECLARE_EXTENSION_FUNCTION("bluetoothSocket.close", BLUETOOTHSOCKET_CLOSE);
+ BluetoothSocketCloseFunction();
+
protected:
- virtual ~BluetoothSocketCloseFunction() {}
+ virtual ~BluetoothSocketCloseFunction();
- // UIThreadExtensionFunction override:
- virtual bool RunImpl() OVERRIDE;
+ // BluetoothSocketAsyncApiFunction:
+ virtual bool Prepare() OVERRIDE;
+ virtual void Work() OVERRIDE;
+
+ private:
+ scoped_ptr<bluetooth_socket::Close::Params> params_;
};
-class BluetoothSocketSendFunction : public UIThreadExtensionFunction {
+class BluetoothSocketSendFunction : public BluetoothSocketAsyncApiFunction {
public:
DECLARE_EXTENSION_FUNCTION("bluetoothSocket.send", BLUETOOTHSOCKET_SEND);
+ BluetoothSocketSendFunction();
+
protected:
- virtual ~BluetoothSocketSendFunction() {}
+ virtual ~BluetoothSocketSendFunction();
- // UIThreadExtensionFunction override:
- virtual bool RunImpl() OVERRIDE;
+ // BluetoothSocketAsyncApiFunction:
+ virtual bool Prepare() OVERRIDE;
+ virtual void AsyncWorkStart() OVERRIDE;
+
+ private:
+ void OnSuccess(int bytes_sent);
+ void OnError(BluetoothApiSocket::ErrorReason reason,
+ const std::string& message);
+
+ scoped_ptr<bluetooth_socket::Send::Params> params_;
+ scoped_refptr<net::IOBuffer> io_buffer_;
+ size_t io_buffer_size_;
};
-class BluetoothSocketGetInfoFunction : public UIThreadExtensionFunction {
+class BluetoothSocketGetInfoFunction : public BluetoothSocketAsyncApiFunction {
public:
DECLARE_EXTENSION_FUNCTION("bluetoothSocket.getInfo",
BLUETOOTHSOCKET_GETINFO);
+ BluetoothSocketGetInfoFunction();
+
protected:
- virtual ~BluetoothSocketGetInfoFunction() {}
+ virtual ~BluetoothSocketGetInfoFunction();
- // UIThreadExtensionFunction override:
- virtual bool RunImpl() OVERRIDE;
+ // BluetoothSocketAsyncApiFunction:
+ virtual bool Prepare() OVERRIDE;
+ virtual void Work() OVERRIDE;
+
+ private:
+ scoped_ptr<bluetooth_socket::GetInfo::Params> params_;
};
-class BluetoothSocketGetSocketsFunction : public UIThreadExtensionFunction {
+class BluetoothSocketGetSocketsFunction
+ : public BluetoothSocketAsyncApiFunction {
public:
DECLARE_EXTENSION_FUNCTION("bluetoothSocket.getSockets",
BLUETOOTHSOCKET_GETSOCKETS);
+ BluetoothSocketGetSocketsFunction();
+
protected:
- virtual ~BluetoothSocketGetSocketsFunction() {}
+ virtual ~BluetoothSocketGetSocketsFunction();
- // UIThreadExtensionFunction override:
- virtual bool RunImpl() OVERRIDE;
+ // BluetoothSocketAsyncApiFunction:
+ virtual bool Prepare() OVERRIDE;
+ virtual void Work() OVERRIDE;
};
} // namespace api
diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_socket_event_dispatcher.cc b/chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_event_dispatcher.cc
index 6429ed474..2d7f539 100644
--- a/chrome/browser/extensions/api/bluetooth/bluetooth_socket_event_dispatcher.cc
+++ b/chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_event_dispatcher.cc
@@ -2,32 +2,37 @@
// 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/bluetooth_socket_event_dispatcher.h"
+#include "chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_event_dispatcher.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.h"
-#include "chrome/common/extensions/api/bluetooth.h"
+#include "chrome/common/extensions/api/bluetooth_socket.h"
#include "extensions/browser/event_router.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
namespace {
-namespace bluetooth = extensions::api::bluetooth;
+namespace bluetooth_socket = extensions::api::bluetooth_socket;
using extensions::BluetoothApiSocket;
int kDefaultBufferSize = 4096;
-bluetooth::ReceiveError MapErrorReason(BluetoothApiSocket::ErrorReason value) {
+bluetooth_socket::ReceiveError MapErrorReason(
+ BluetoothApiSocket::ErrorReason value) {
switch (value) {
case BluetoothApiSocket::kDisconnected:
- return bluetooth::RECEIVE_ERROR_DISCONNECTED;
+ return bluetooth_socket::RECEIVE_ERROR_DISCONNECTED;
+ case BluetoothApiSocket::kNotConnected:
+ // kNotConnected is impossible since a socket has to be connected to be
+ // able to call Receive() on it.
+ // fallthrough
case BluetoothApiSocket::kIOPending:
// kIOPending is not relevant to apps, as BluetoothSocketEventDispatcher
// handles this specific error.
// fallthrough
default:
- return bluetooth::RECEIVE_ERROR_SYSTEM_ERROR;
+ return bluetooth_socket::RECEIVE_ERROR_SYSTEM_ERROR;
}
}
@@ -38,12 +43,38 @@ namespace api {
using content::BrowserThread;
+static base::LazyInstance<
+ BrowserContextKeyedAPIFactory<BluetoothSocketEventDispatcher> > g_factory =
+ LAZY_INSTANCE_INITIALIZER;
+
+// static
+BrowserContextKeyedAPIFactory<BluetoothSocketEventDispatcher>*
+BluetoothSocketEventDispatcher::GetFactoryInstance() {
+ return g_factory.Pointer();
+}
+
+// static
+BluetoothSocketEventDispatcher* BluetoothSocketEventDispatcher::Get(
+ content::BrowserContext* context) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ return BrowserContextKeyedAPIFactory<BluetoothSocketEventDispatcher>::Get(
+ context);
+}
+
BluetoothSocketEventDispatcher::BluetoothSocketEventDispatcher(
- content::BrowserContext* context,
- scoped_refptr<SocketData> socket_data)
+ content::BrowserContext* context)
: thread_id_(BluetoothApiSocket::kThreadId),
- browser_context_id_(context),
- socket_data_(socket_data) {}
+ browser_context_(context) {
+ ApiResourceManager<BluetoothApiSocket>* manager =
+ ApiResourceManager<BluetoothApiSocket>::Get(browser_context_);
+ DCHECK(manager)
+ << "There is no socket manager. "
+ "If this assertion is failing during a test, then it is likely that "
+ "TestExtensionSystem is failing to provide an instance of "
+ "ApiResourceManager<BluetoothApiSocket>.";
+ sockets_ = manager->data_;
+}
BluetoothSocketEventDispatcher::~BluetoothSocketEventDispatcher() {}
@@ -57,16 +88,21 @@ void BluetoothSocketEventDispatcher::OnSocketResume(
DCHECK(BrowserThread::CurrentlyOn(thread_id_));
ReceiveParams params;
+ params.thread_id = thread_id_;
+ params.browser_context_id = browser_context_;
params.extension_id = extension_id;
+ params.sockets = sockets_;
params.socket_id = socket_id;
+
StartReceive(params);
}
+// static
void BluetoothSocketEventDispatcher::StartReceive(const ReceiveParams& params) {
- DCHECK(BrowserThread::CurrentlyOn(thread_id_));
+ DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
BluetoothApiSocket* socket =
- socket_data_->Get(params.extension_id, params.socket_id);
+ params.sockets->Get(params.extension_id, params.socket_id);
if (!socket) {
// This can happen if the socket is closed while our callback is active.
return;
@@ -84,39 +120,42 @@ void BluetoothSocketEventDispatcher::StartReceive(const ReceiveParams& params) {
socket->Receive(
buffer_size,
base::Bind(
- &BluetoothSocketEventDispatcher::ReceiveCallback, this, params),
+ &BluetoothSocketEventDispatcher::ReceiveCallback, params),
base::Bind(
- &BluetoothSocketEventDispatcher::ReceiveErrorCallback, this, params));
+ &BluetoothSocketEventDispatcher::ReceiveErrorCallback, params));
}
+// static
void BluetoothSocketEventDispatcher::ReceiveCallback(
const ReceiveParams& params,
int bytes_read,
scoped_refptr<net::IOBuffer> io_buffer) {
- DCHECK(BrowserThread::CurrentlyOn(thread_id_));
+ DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
// Dispatch "onReceive" event.
- bluetooth::ReceiveInfo receive_info;
+ bluetooth_socket::ReceiveInfo receive_info;
receive_info.socket_id = params.socket_id;
receive_info.data = std::string(io_buffer->data(), bytes_read);
- scoped_ptr<base::ListValue> args = bluetooth::OnReceive::Create(receive_info);
+ scoped_ptr<base::ListValue> args =
+ bluetooth_socket::OnReceive::Create(receive_info);
scoped_ptr<Event> event(
- new Event(bluetooth::OnReceive::kEventName, args.Pass()));
+ new Event(bluetooth_socket::OnReceive::kEventName, args.Pass()));
PostEvent(params, event.Pass());
// Post a task to delay the read until the socket is available, as
// calling StartReceive at this point would error with ERR_IO_PENDING.
BrowserThread::PostTask(
- thread_id_,
+ params.thread_id,
FROM_HERE,
- base::Bind(&BluetoothSocketEventDispatcher::StartReceive, this, params));
+ base::Bind(&BluetoothSocketEventDispatcher::StartReceive, params));
}
+// static
void BluetoothSocketEventDispatcher::ReceiveErrorCallback(
const ReceiveParams& params,
BluetoothApiSocket::ErrorReason error_reason,
const std::string& error) {
- DCHECK(BrowserThread::CurrentlyOn(thread_id_));
+ DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
if (error_reason == BluetoothApiSocket::kIOPending) {
// This happens when resuming a socket which already had an active "read"
@@ -127,45 +166,48 @@ void BluetoothSocketEventDispatcher::ReceiveErrorCallback(
// Dispatch "onReceiveError" event but don't start another read to avoid
// potential infinite reads if we have a persistent network error.
- bluetooth::ReceiveErrorInfo receive_error_info;
+ bluetooth_socket::ReceiveErrorInfo receive_error_info;
receive_error_info.socket_id = params.socket_id;
receive_error_info.error_message = error;
receive_error_info.error = MapErrorReason(error_reason);
scoped_ptr<base::ListValue> args =
- bluetooth::OnReceiveError::Create(receive_error_info);
+ bluetooth_socket::OnReceiveError::Create(receive_error_info);
scoped_ptr<Event> event(
- new Event(bluetooth::OnReceiveError::kEventName, args.Pass()));
+ new Event(bluetooth_socket::OnReceiveError::kEventName, args.Pass()));
PostEvent(params, event.Pass());
// Since we got an error, the socket is now "paused" until the application
// "resumes" it.
BluetoothApiSocket* socket =
- socket_data_->Get(params.extension_id, params.socket_id);
+ params.sockets->Get(params.extension_id, params.socket_id);
if (socket) {
socket->set_paused(true);
}
}
+// static
void BluetoothSocketEventDispatcher::PostEvent(const ReceiveParams& params,
scoped_ptr<Event> event) {
- DCHECK(BrowserThread::CurrentlyOn(thread_id_));
+ DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
BrowserThread::PostTask(
BrowserThread::UI,
FROM_HERE,
- base::Bind(&BluetoothSocketEventDispatcher::DispatchEvent,
- this,
+ base::Bind(&DispatchEvent,
+ params.browser_context_id,
params.extension_id,
base::Passed(event.Pass())));
}
+// static
void BluetoothSocketEventDispatcher::DispatchEvent(
+ void* browser_context_id,
const std::string& extension_id,
scoped_ptr<Event> event) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
content::BrowserContext* context =
- reinterpret_cast<content::BrowserContext*>(browser_context_id_);
+ reinterpret_cast<content::BrowserContext*>(browser_context_id);
if (!extensions::ExtensionsBrowserClient::Get()->IsValidContext(context))
return;
diff --git a/chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_event_dispatcher.h b/chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_event_dispatcher.h
new file mode 100644
index 0000000..81fdfca
--- /dev/null
+++ b/chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_event_dispatcher.h
@@ -0,0 +1,94 @@
+// 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.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_BLUETOOTH_SOCKET_BLUETOOTH_SOCKET_EVENT_DISPATCHER_H_
+#define CHROME_BROWSER_EXTENSIONS_API_BLUETOOTH_SOCKET_BLUETOOTH_SOCKET_EVENT_DISPATCHER_H_
+
+#include "chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.h"
+#include "extensions/browser/api/api_resource_manager.h"
+#include "extensions/browser/browser_context_keyed_api_factory.h"
+
+namespace content {
+class BrowserContext;
+}
+
+namespace extensions {
+struct Event;
+class BluetoothApiSocket;
+}
+
+namespace extensions {
+namespace api {
+
+// Dispatch events related to "bluetooth" sockets from callback on native socket
+// instances. There is one instance per browser context.
+class BluetoothSocketEventDispatcher
+ : public BrowserContextKeyedAPI,
+ public base::SupportsWeakPtr<BluetoothSocketEventDispatcher> {
+ public:
+ explicit BluetoothSocketEventDispatcher(content::BrowserContext* context);
+ virtual ~BluetoothSocketEventDispatcher();
+
+ // Socket is active again, start receiving data from it.
+ void OnSocketResume(const std::string& extension_id, int socket_id);
+
+ // BrowserContextKeyedAPI implementation.
+ static BrowserContextKeyedAPIFactory<BluetoothSocketEventDispatcher>*
+ GetFactoryInstance();
+
+ // Convenience method to get the SocketEventDispatcher for a profile.
+ static BluetoothSocketEventDispatcher* Get(content::BrowserContext* context);
+
+ private:
+ typedef ApiResourceManager<BluetoothApiSocket>::ApiResourceData SocketData;
+ friend class BrowserContextKeyedAPIFactory<BluetoothSocketEventDispatcher>;
+ // BrowserContextKeyedAPI implementation.
+ static const char* service_name() { return "BluetoothSocketEventDispatcher"; }
+ static const bool kServiceHasOwnInstanceInIncognito = true;
+ static const bool kServiceIsNULLWhileTesting = true;
+
+ // base::Bind supports methods with up to 6 parameters. ReceiveParams is used
+ // as a workaround that limitation for invoking StartReceive.
+ struct ReceiveParams {
+ ReceiveParams();
+ ~ReceiveParams();
+
+ content::BrowserThread::ID thread_id;
+ void* browser_context_id;
+ std::string extension_id;
+ scoped_refptr<SocketData> sockets;
+ int socket_id;
+ };
+
+ // Start a receive and register a callback.
+ static void StartReceive(const ReceiveParams& params);
+
+ // Called when socket receive data.
+ static void ReceiveCallback(const ReceiveParams& params,
+ int bytes_read,
+ scoped_refptr<net::IOBuffer> io_buffer);
+
+ // Called when socket receive data.
+ static void ReceiveErrorCallback(const ReceiveParams& params,
+ BluetoothApiSocket::ErrorReason error_reason,
+ const std::string& error);
+
+ // Post an extension event from IO to UI thread
+ static void PostEvent(const ReceiveParams& params, scoped_ptr<Event> event);
+
+ // Dispatch an extension event on to EventRouter instance on UI thread.
+ static void DispatchEvent(void* browser_context_id,
+ const std::string& extension_id,
+ scoped_ptr<Event> event);
+
+ // Usually FILE thread (except for unit testing).
+ content::BrowserThread::ID thread_id_;
+ content::BrowserContext* const browser_context_;
+ scoped_refptr<SocketData> sockets_;
+};
+
+} // namespace api
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_BLUETOOTH_SOCKET_BLUETOOTH_SOCKET_EVENT_DISPATCHER_H_
diff --git a/chrome/browser/extensions/browser_context_keyed_service_factories.cc b/chrome/browser/extensions/browser_context_keyed_service_factories.cc
index 8a79b26..c9f3c43 100644
--- a/chrome/browser/extensions/browser_context_keyed_service_factories.cc
+++ b/chrome/browser/extensions/browser_context_keyed_service_factories.cc
@@ -11,6 +11,7 @@
#include "chrome/browser/extensions/api/bluetooth/bluetooth_api.h"
#include "chrome/browser/extensions/api/bluetooth/bluetooth_private_api.h"
#include "chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_api.h"
+#include "chrome/browser/extensions/api/bluetooth_socket/bluetooth_socket_event_dispatcher.h"
#include "chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.h"
#include "chrome/browser/extensions/api/bookmarks/bookmarks_api.h"
#include "chrome/browser/extensions/api/braille_display_private/braille_display_private_api.h"
@@ -163,6 +164,7 @@ void EnsureBrowserContextKeyedServiceFactoriesBuilt() {
#endif
TokenCacheServiceFactory::GetInstance();
extensions::ExtensionGCMAppHandler::GetFactoryInstance();
+ extensions::api::BluetoothSocketEventDispatcher::GetFactoryInstance();
}
} // namespace chrome_extensions