diff options
author | scottmg@chromium.org <scottmg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-07 19:58:52 +0000 |
---|---|---|
committer | scottmg@chromium.org <scottmg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-07 19:58:52 +0000 |
commit | dc85cefeac3ce32fe326af854676f4d0ca3bd90a (patch) | |
tree | 73fc7ff21bc50d1c36c8c082397f7f6651d23c76 | |
parent | 4b22d0aac0b8300ea268a92ae071235902efad83 (diff) | |
download | chromium_src-dc85cefeac3ce32fe326af854676f4d0ca3bd90a.zip chromium_src-dc85cefeac3ce32fe326af854676f4d0ca3bd90a.tar.gz chromium_src-dc85cefeac3ce32fe326af854676f4d0ca3bd90a.tar.bz2 |
Revert 262175 "* Replace "read" method with onReceiveXxx events."
Failed compile on Linux CrOS Full: http://build.chromium.org/p/chromium.chromiumos/builders/Linux%20ChromiumOS%20Full/builds/2043/steps/compile/logs/stdio
> * Replace "read" method with onReceiveXxx events.
> * Few minor changes to idl file.
> * Socket implementation on Windows fully implemented and with (hopefully) correct threading usage.
> * ChromeOS and MacOS socket implementation empty for now (they will come in later CLs).
>
> BUG=336824,340363, 340413, 343651, 344081
>
> Review URL: https://codereview.chromium.org/180163009
TBR=rpaquay@chromium.org
Review URL: https://codereview.chromium.org/227493006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@262180 0039d316-1c4b-4281-b951-d872f2087c98
51 files changed, 786 insertions, 2544 deletions
diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_api.cc b/chrome/browser/extensions/api/bluetooth/bluetooth_api.cc index ce04129..d520f3d 100644 --- a/chrome/browser/extensions/api/bluetooth/bluetooth_api.cc +++ b/chrome/browser/extensions/api/bluetooth/bluetooth_api.cc @@ -10,8 +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" #include "content/public/browser/browser_thread.h" @@ -27,26 +25,19 @@ #include "net/base/io_buffer.h" using content::BrowserContext; -using content::BrowserThread; - using device::BluetoothAdapter; using device::BluetoothDevice; using device::BluetoothProfile; using device::BluetoothServiceRecord; using device::BluetoothSocket; -using extensions::BluetoothApiSocket; +namespace { -namespace AddProfile = extensions::api::bluetooth::AddProfile; -namespace bluetooth = extensions::api::bluetooth; -namespace Connect = extensions::api::bluetooth::Connect; -namespace Disconnect = extensions::api::bluetooth::Disconnect; -namespace GetDevice = extensions::api::bluetooth::GetDevice; -namespace GetDevices = extensions::api::bluetooth::GetDevices; -namespace RemoveProfile = extensions::api::bluetooth::RemoveProfile; -namespace SetOutOfBandPairingData = - extensions::api::bluetooth::SetOutOfBandPairingData; -namespace Send = extensions::api::bluetooth::Send; +extensions::BluetoothEventRouter* GetEventRouter(BrowserContext* context) { + return extensions::BluetoothAPI::Get(context)->bluetooth_event_router(); +} + +} // namespace namespace { @@ -54,6 +45,7 @@ const char kCouldNotGetLocalOutOfBandPairingData[] = "Could not get local Out Of Band Pairing Data"; const char kCouldNotSetOutOfBandPairingData[] = "Could not set Out Of Band Pairing Data"; +const char kFailedToConnect[] = "Connection failed"; const char kInvalidDevice[] = "Invalid device"; const char kInvalidUuid[] = "Invalid UUID"; const char kPermissionDenied[] = "Permission to add profile denied."; @@ -65,72 +57,20 @@ const char kSocketNotFoundError[] = "Socket not found: invalid socket id"; const char kStartDiscoveryFailed[] = "Starting discovery failed"; const char kStopDiscoveryFailed[] = "Failed to stop discovery"; -extensions::BluetoothEventRouter* GetEventRouter(BrowserContext* context) { - // Note: |context| is valid on UI thread only. - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - 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, - const device::BluetoothUUID& profile_uuid, - const device::BluetoothDevice* device, - scoped_refptr<device::BluetoothSocket> socket) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - content::BrowserContext* context = - reinterpret_cast<content::BrowserContext*>(browser_context_id); - if (!extensions::ExtensionsBrowserClient::Get()->IsValidContext(context)) - return; - - extensions::BluetoothAPI* bluetooth_api = - extensions::BluetoothAPI::Get(context); - if (!bluetooth_api) - return; - - bluetooth_api->DispatchConnectionEvent( - extension_id, profile_uuid, device, socket); -} - } // namespace +namespace AddProfile = extensions::api::bluetooth::AddProfile; +namespace bluetooth = extensions::api::bluetooth; +namespace Connect = extensions::api::bluetooth::Connect; +namespace Disconnect = extensions::api::bluetooth::Disconnect; +namespace GetDevice = extensions::api::bluetooth::GetDevice; +namespace GetDevices = extensions::api::bluetooth::GetDevices; +namespace Read = extensions::api::bluetooth::Read; +namespace RemoveProfile = extensions::api::bluetooth::RemoveProfile; +namespace SetOutOfBandPairingData = + extensions::api::bluetooth::SetOutOfBandPairingData; +namespace Write = extensions::api::bluetooth::Write; + namespace extensions { static base::LazyInstance<BrowserContextKeyedAPIFactory<BluetoothAPI> > @@ -144,17 +84,11 @@ BluetoothAPI::GetFactoryInstance() { // static BluetoothAPI* BluetoothAPI::Get(BrowserContext* context) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); return GetFactoryInstance()->Get(context); } -BluetoothAPI::ConnectionParams::ConnectionParams() {} - -BluetoothAPI::ConnectionParams::~ConnectionParams() {} - -BluetoothAPI::BluetoothAPI(content::BrowserContext* context) +BluetoothAPI::BluetoothAPI(BrowserContext* context) : browser_context_(context) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); ExtensionSystem::Get(browser_context_)->event_router()->RegisterObserver( this, bluetooth::OnAdapterStateChanged::kEventName); ExtensionSystem::Get(browser_context_)->event_router()->RegisterObserver( @@ -165,241 +99,37 @@ BluetoothAPI::BluetoothAPI(content::BrowserContext* context) this, bluetooth::OnDeviceRemoved::kEventName); } -BluetoothAPI::~BluetoothAPI() {} - -BluetoothEventRouter* BluetoothAPI::event_router() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (!event_router_) { - event_router_.reset(new BluetoothEventRouter(browser_context_)); - } - return event_router_.get(); +BluetoothAPI::~BluetoothAPI() { } -scoped_refptr<BluetoothAPI::SocketData> BluetoothAPI::socket_data() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (!socket_data_) { - ApiResourceManager<BluetoothApiSocket>* socket_manager = - ApiResourceManager<BluetoothApiSocket>::Get(browser_context_); - DCHECK(socket_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>."; - - socket_data_ = socket_manager->data_; - } - return socket_data_; -} +BluetoothEventRouter* BluetoothAPI::bluetooth_event_router() { + if (!bluetooth_event_router_) + bluetooth_event_router_.reset(new BluetoothEventRouter(browser_context_)); -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_; + return bluetooth_event_router_.get(); } void BluetoothAPI::Shutdown() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); ExtensionSystem::Get(browser_context_)->event_router()->UnregisterObserver( this); } void BluetoothAPI::OnListenerAdded(const EventListenerInfo& details) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (event_router()->IsBluetoothSupported()) - event_router()->OnListenerAdded(); + if (bluetooth_event_router()->IsBluetoothSupported()) + bluetooth_event_router()->OnListenerAdded(); } void BluetoothAPI::OnListenerRemoved(const EventListenerInfo& details) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (event_router()->IsBluetoothSupported()) - event_router()->OnListenerRemoved(); -} - -void BluetoothAPI::DispatchConnectionEvent( - const std::string& extension_id, - const device::BluetoothUUID& uuid, - const device::BluetoothDevice* device, - scoped_refptr<device::BluetoothSocket> socket) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - if (!event_router()->HasProfile(uuid)) - return; - - extensions::BluetoothAPI::ConnectionParams params; - params.browser_context_id = browser_context_; - params.thread_id = BluetoothApiSocket::kThreadId; - params.extension_id = extension_id; - params.uuid = uuid; - params.device_address = device->GetAddress(); - params.socket = socket; - params.socket_data = socket_data(); - BrowserThread::PostTask( - params.thread_id, FROM_HERE, base::Bind(&RegisterSocket, params)); -} - -// static -void BluetoothAPI::RegisterSocket( - const BluetoothAPI::ConnectionParams& params) { - DCHECK(BrowserThread::CurrentlyOn(params.thread_id)); - - BluetoothApiSocket* api_socket = new BluetoothApiSocket( - params.extension_id, params.socket, params.device_address, params.uuid); - int socket_id = params.socket_data->Add(api_socket); - - BrowserThread::PostTask(BrowserThread::UI, - FROM_HERE, - base::Bind(&RegisterSocketUI, params, socket_id)); -} - -// static -void BluetoothAPI::RegisterSocketUI(const ConnectionParams& params, - int socket_id) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - content::BrowserContext* context = - reinterpret_cast<content::BrowserContext*>(params.browser_context_id); - if (!extensions::ExtensionsBrowserClient::Get()->IsValidContext(context)) - return; - - BluetoothAPI::Get(context)->event_router()->GetAdapter( - base::Bind(&RegisterSocketWithAdapterUI, params, socket_id)); -} - -void BluetoothAPI::RegisterSocketWithAdapterUI( - const ConnectionParams& params, - int socket_id, - scoped_refptr<device::BluetoothAdapter> adapter) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - content::BrowserContext* context = - reinterpret_cast<content::BrowserContext*>(params.browser_context_id); - if (!extensions::ExtensionsBrowserClient::Get()->IsValidContext(context)) - return; - - BluetoothDevice* device = adapter->GetDevice(params.device_address); - if (!device) - return; - - api::bluetooth::Socket result_socket; - bluetooth::BluetoothDeviceToApiDevice(*device, &result_socket.device); - result_socket.uuid = params.uuid.canonical_value(); - result_socket.id = socket_id; - - scoped_ptr<base::ListValue> args = - bluetooth::OnConnection::Create(result_socket); - scoped_ptr<Event> event( - new Event(bluetooth::OnConnection::kEventName, args.Pass())); - - EventRouter* router = ExtensionSystem::Get(context)->event_router(); - if (router) - router->DispatchEventToExtension(params.extension_id, event.Pass()); + if (bluetooth_event_router()->IsBluetoothSupported()) + bluetooth_event_router()->OnListenerRemoved(); } 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( - scoped_refptr<BluetoothAdapter> adapter) { - bluetooth::AdapterState state; - PopulateAdapterState(*adapter.get(), &state); - results_ = bluetooth::GetAdapterState::Results::Create(state); - SendResponse(true); - return true; -} - -BluetoothGetDevicesFunction::~BluetoothGetDevicesFunction() {} - -bool BluetoothGetDevicesFunction::DoWork( - scoped_refptr<BluetoothAdapter> adapter) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - - base::ListValue* device_list = new base::ListValue; - SetResult(device_list); - - BluetoothAdapter::DeviceList devices = adapter->GetDevices(); - for (BluetoothAdapter::DeviceList::const_iterator iter = devices.begin(); - iter != devices.end(); - ++iter) { - const BluetoothDevice* device = *iter; - DCHECK(device); - - bluetooth::Device extension_device; - bluetooth::BluetoothDeviceToApiDevice(*device, &extension_device); - - device_list->Append(extension_device.ToValue().release()); - } - - SendResponse(true); - - return true; -} - -BluetoothGetDeviceFunction::~BluetoothGetDeviceFunction() {} - -bool BluetoothGetDeviceFunction::DoWork( - scoped_refptr<BluetoothAdapter> adapter) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - - scoped_ptr<GetDevice::Params> params(GetDevice::Params::Create(*args_)); - EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); - const std::string& device_address = params->device_address; - - BluetoothDevice* device = adapter->GetDevice(device_address); - if (device) { - bluetooth::Device extension_device; - bluetooth::BluetoothDeviceToApiDevice(*device, &extension_device); - SetResult(extension_device.ToValue().release()); - SendResponse(true); - } else { - SetError(kInvalidDevice); - SendResponse(false); - } - - return false; +BluetoothAddProfileFunction::BluetoothAddProfileFunction() { } -BluetoothAddProfileFunction::BluetoothAddProfileFunction() {} - -BluetoothAddProfileFunction::~BluetoothAddProfileFunction() {} - bool BluetoothAddProfileFunction::RunImpl() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); scoped_ptr<AddProfile::Params> params(AddProfile::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); @@ -455,13 +185,11 @@ bool BluetoothAddProfileFunction::RunImpl() { void BluetoothAddProfileFunction::RegisterProfile( const BluetoothProfile::Options& options, const BluetoothProfile::ProfileCallback& callback) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); BluetoothProfile::Register(uuid_, options, callback); } void BluetoothAddProfileFunction::OnProfileRegistered( BluetoothProfile* bluetooth_profile) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); if (!bluetooth_profile) { SetError(kProfileRegistrationFailed); SendResponse(false); @@ -476,8 +204,8 @@ void BluetoothAddProfileFunction::OnProfileRegistered( } bluetooth_profile->SetConnectionCallback( - base::Bind(&DispatchConnectionEventWorker, - browser_context(), + base::Bind(&BluetoothEventRouter::DispatchConnectionEvent, + base::Unretained(GetEventRouter(browser_context())), extension_id(), uuid_)); GetEventRouter(browser_context()) @@ -485,10 +213,7 @@ void BluetoothAddProfileFunction::OnProfileRegistered( SendResponse(true); } -BluetoothRemoveProfileFunction::~BluetoothRemoveProfileFunction() {} - bool BluetoothRemoveProfileFunction::RunImpl() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); scoped_ptr<RemoveProfile::Params> params( RemoveProfile::Params::Create(*args_)); @@ -508,7 +233,70 @@ bool BluetoothRemoveProfileFunction::RunImpl() { return true; } -BluetoothConnectFunction::~BluetoothConnectFunction() {} +bool BluetoothGetAdapterStateFunction::DoWork( + scoped_refptr<BluetoothAdapter> adapter) { + bluetooth::AdapterState state; + PopulateAdapterState(*adapter.get(), &state); + SetResult(state.ToValue().release()); + SendResponse(true); + return true; +} + +bool BluetoothGetDevicesFunction::DoWork( + scoped_refptr<BluetoothAdapter> adapter) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + base::ListValue* device_list = new base::ListValue; + SetResult(device_list); + + BluetoothAdapter::DeviceList devices = adapter->GetDevices(); + for (BluetoothAdapter::DeviceList::const_iterator iter = devices.begin(); + iter != devices.end(); + ++iter) { + const BluetoothDevice* device = *iter; + DCHECK(device); + + bluetooth::Device extension_device; + bluetooth::BluetoothDeviceToApiDevice(*device, &extension_device); + + device_list->Append(extension_device.ToValue().release()); + } + + SendResponse(true); + + return true; +} + +bool BluetoothGetDeviceFunction::DoWork( + scoped_refptr<BluetoothAdapter> adapter) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + scoped_ptr<GetDevice::Params> params(GetDevice::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); + const std::string& device_address = params->device_address; + + BluetoothDevice* device = adapter->GetDevice(device_address); + if (device) { + bluetooth::Device extension_device; + bluetooth::BluetoothDeviceToApiDevice(*device, &extension_device); + SetResult(extension_device.ToValue().release()); + SendResponse(true); + } else { + SetError(kInvalidDevice); + SendResponse(false); + } + + return false; +} + +void BluetoothConnectFunction::OnSuccessCallback() { + SendResponse(true); +} + +void BluetoothConnectFunction::OnErrorCallback() { + SetError(kFailedToConnect); + SendResponse(false); +} bool BluetoothConnectFunction::DoWork(scoped_refptr<BluetoothAdapter> adapter) { scoped_ptr<Connect::Params> params(Connect::Params::Create(*args_)); @@ -546,181 +334,108 @@ bool BluetoothConnectFunction::DoWork(scoped_refptr<BluetoothAdapter> adapter) { return true; } -void BluetoothConnectFunction::OnSuccessCallback() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - SendResponse(true); -} - -void BluetoothConnectFunction::OnErrorCallback(const std::string& error) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - SetError(error); - SendResponse(false); +bool BluetoothDisconnectFunction::RunImpl() { + scoped_ptr<Disconnect::Params> params(Disconnect::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); + const bluetooth::DisconnectOptions& options = params->options; + return GetEventRouter(browser_context())->ReleaseSocket(options.socket.id); } -BluetoothDisconnectFunction::BluetoothDisconnectFunction() {} +BluetoothReadFunction::BluetoothReadFunction() : success_(false) {} +BluetoothReadFunction::~BluetoothReadFunction() {} -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; -} +bool BluetoothReadFunction::Prepare() { + scoped_ptr<Read::Params> params(Read::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); + const bluetooth::ReadOptions& options = params->options; -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_ = GetEventRouter(browser_context())->GetSocket(options.socket.id); + if (socket_.get() == NULL) { + SetError(kSocketNotFoundError); + return false; } - 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()); + success_ = false; 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; +void BluetoothReadFunction::Work() { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + if (!socket_.get()) 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(); + scoped_refptr<net::GrowableIOBuffer> buffer(new net::GrowableIOBuffer); + success_ = socket_->Receive(buffer.get()); + if (success_) + SetResult(base::BinaryValue::CreateWithCopiedBuffer(buffer->StartOfBuffer(), + buffer->offset())); + else + SetError(socket_->GetLastErrorMessage()); } -void BluetoothSendFunction::OnSendError(const std::string& message) { - DCHECK(BrowserThread::CurrentlyOn(work_thread_id())); - error_ = message; - AsyncWorkCompleted(); +bool BluetoothReadFunction::Respond() { + return success_; } -BluetoothUpdateSocketFunction::BluetoothUpdateSocketFunction() {} - -BluetoothUpdateSocketFunction::~BluetoothUpdateSocketFunction() {} - -bool BluetoothUpdateSocketFunction::Prepare() { - params_ = bluetooth::UpdateSocket::Params::Create(*args_); - EXTENSION_FUNCTION_VALIDATE(params_.get()); - return true; +BluetoothWriteFunction::BluetoothWriteFunction() + : success_(false), + data_to_write_(NULL) { } -void BluetoothUpdateSocketFunction::Work() { - BluetoothApiSocket* socket = - socket_data_->Get(extension_id(), params_->socket_id); - if (!socket) { - error_ = kSocketNotFoundError; - return; - } +BluetoothWriteFunction::~BluetoothWriteFunction() {} - SetSocketProperties(socket, ¶ms_.get()->properties); - results_ = bluetooth::UpdateSocket::Results::Create(); -} +bool BluetoothWriteFunction::Prepare() { + // TODO(bryeung): update to new-style parameter passing when ArrayBuffer + // support is added + base::DictionaryValue* options; + EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options)); -BluetoothSetSocketPausedFunction::BluetoothSetSocketPausedFunction() {} + base::DictionaryValue* socket; + EXTENSION_FUNCTION_VALIDATE(options->GetDictionary("socket", &socket)); -BluetoothSetSocketPausedFunction::~BluetoothSetSocketPausedFunction() {} + int socket_id; + EXTENSION_FUNCTION_VALIDATE(socket->GetInteger("id", &socket_id)); -bool BluetoothSetSocketPausedFunction::Prepare() { - params_ = bluetooth::SetSocketPaused::Params::Create(*args_); - EXTENSION_FUNCTION_VALIDATE(params_.get()); - return true; -} - -void BluetoothSetSocketPausedFunction::Work() { - BluetoothApiSocket* socket = - socket_data_->Get(extension_id(), params_->socket_id); - if (!socket) { - error_ = kSocketNotFoundError; - return; + socket_ = GetEventRouter(browser_context())->GetSocket(socket_id); + if (socket_.get() == NULL) { + SetError(kSocketNotFoundError); + return false; } - if (socket->paused() != params_->paused) { - socket->set_paused(params_->paused); - if (!params_->paused) { - socket_event_dispatcher_->OnSocketResume(extension_->id(), - params_->socket_id); - } - } + base::BinaryValue* tmp_data; + EXTENSION_FUNCTION_VALIDATE(options->GetBinary("data", &tmp_data)); + data_to_write_ = tmp_data; - results_ = bluetooth::SetSocketPaused::Results::Create(); + success_ = false; + return socket_.get() != NULL; } -BluetoothGetSocketFunction::BluetoothGetSocketFunction() {} - -BluetoothGetSocketFunction::~BluetoothGetSocketFunction() {} - -bool BluetoothGetSocketFunction::Prepare() { - params_ = bluetooth::GetSocket::Params::Create(*args_); - EXTENSION_FUNCTION_VALIDATE(params_.get()); - return true; -} +void BluetoothWriteFunction::Work() { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); -void BluetoothGetSocketFunction::Work() { - BluetoothApiSocket* socket = - socket_data_->Get(extension_id(), params_->socket_id); - if (!socket) { - error_ = kSocketNotFoundError; + if (socket_.get() == NULL) return; - } - linked_ptr<bluetooth::Socket> socket_info = - CreateSocketInfo(params_->socket_id, socket); - results_ = bluetooth::GetSocket::Results::Create(*socket_info); + scoped_refptr<net::WrappedIOBuffer> wrapped_io_buffer( + new net::WrappedIOBuffer(data_to_write_->GetBuffer())); + scoped_refptr<net::DrainableIOBuffer> drainable_io_buffer( + new net::DrainableIOBuffer(wrapped_io_buffer.get(), + data_to_write_->GetSize())); + success_ = socket_->Send(drainable_io_buffer.get()); + if (success_) { + if (drainable_io_buffer->BytesConsumed() > 0) + SetResult(new base::FundamentalValue( + drainable_io_buffer->BytesConsumed())); + else + results_.reset(); + } else { + SetError(socket_->GetLastErrorMessage()); + } } -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 BluetoothWriteFunction::Respond() { + return success_; } void BluetoothSetOutOfBandPairingDataFunction::OnSuccessCallback() { diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_api.h b/chrome/browser/extensions/api/bluetooth/bluetooth_api.h index 38dce60..21e164c 100644 --- a/chrome/browser/extensions/api/bluetooth/bluetooth_api.h +++ b/chrome/browser/extensions/api/bluetooth/bluetooth_api.h @@ -9,14 +9,10 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" -#include "chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.h" #include "chrome/browser/extensions/api/bluetooth/bluetooth_extension_function.h" -#include "chrome/common/extensions/api/bluetooth.h" #include "device/bluetooth/bluetooth_device.h" #include "device/bluetooth/bluetooth_profile.h" -#include "device/bluetooth/bluetooth_socket.h" #include "device/bluetooth/bluetooth_uuid.h" -#include "extensions/browser/api/api_resource_manager.h" #include "extensions/browser/api/async_api_function.h" #include "extensions/browser/browser_context_keyed_api_factory.h" #include "extensions/browser/event_router.h" @@ -27,40 +23,23 @@ class BrowserContext; } namespace device { + class BluetoothAdapter; +class BluetoothDevice; +class BluetoothSocket; struct BluetoothOutOfBandPairingData; -} -namespace net { -class IOBuffer; -} +} // namespace device namespace extensions { class BluetoothEventRouter; // The profile-keyed service that manages the bluetooth extension API. -// All methods of this class must be called on the UI thread. -// TODO(rpaquay): Rename this and move to separate file. class BluetoothAPI : public BrowserContextKeyedAPI, public EventRouter::Observer { public: - typedef ApiResourceManager<BluetoothApiSocket>::ApiResourceData SocketData; - - struct ConnectionParams { - ConnectionParams(); - ~ConnectionParams(); - - content::BrowserThread::ID thread_id; - void* browser_context_id; - std::string extension_id; - std::string device_address; - device::BluetoothUUID uuid; - scoped_refptr<device::BluetoothSocket> socket; - scoped_refptr<SocketData> socket_data; - }; - - // Convenience method to get the BluetoothAPI for a browser context. + // Convenience method to get the BluetoothAPI for a profile. static BluetoothAPI* Get(content::BrowserContext* context); static BrowserContextKeyedAPIFactory<BluetoothAPI>* GetFactoryInstance(); @@ -68,9 +47,7 @@ class BluetoothAPI : public BrowserContextKeyedAPI, explicit BluetoothAPI(content::BrowserContext* context); virtual ~BluetoothAPI(); - BluetoothEventRouter* event_router(); - scoped_refptr<SocketData> socket_data(); - scoped_refptr<api::BluetoothSocketEventDispatcher> socket_event_dispatcher(); + BluetoothEventRouter* bluetooth_event_router(); // KeyedService implementation. virtual void Shutdown() OVERRIDE; @@ -79,23 +56,10 @@ class BluetoothAPI : public BrowserContextKeyedAPI, virtual void OnListenerAdded(const EventListenerInfo& details) OVERRIDE; virtual void OnListenerRemoved(const EventListenerInfo& details) OVERRIDE; - // Dispatch an event that takes a connection socket as a parameter to the - // extension that registered the profile that the socket has connected to. - void DispatchConnectionEvent(const std::string& extension_id, - const device::BluetoothUUID& profile_uuid, - const device::BluetoothDevice* device, - scoped_refptr<device::BluetoothSocket> socket); - private: - static void RegisterSocket(const ConnectionParams& params); - static void RegisterSocketUI(const ConnectionParams& params, int socket_id); - static void RegisterSocketWithAdapterUI( - const ConnectionParams& params, - int socket_id, - scoped_refptr<device::BluetoothAdapter> adapter); + friend class BrowserContextKeyedAPIFactory<BluetoothAPI>; // BrowserContextKeyedAPI implementation. - friend class BrowserContextKeyedAPIFactory<BluetoothAPI>; static const char* service_name() { return "BluetoothAPI"; } static const bool kServiceRedirectedInIncognito = true; static const bool kServiceIsNULLWhileTesting = true; @@ -103,77 +67,11 @@ class BluetoothAPI : public BrowserContextKeyedAPI, content::BrowserContext* browser_context_; // Created lazily on first access. - scoped_ptr<BluetoothEventRouter> event_router_; - scoped_refptr<SocketData> socket_data_; - scoped_refptr<api::BluetoothSocketEventDispatcher> socket_event_dispatcher_; + scoped_ptr<BluetoothEventRouter> bluetooth_event_router_; }; 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", - BLUETOOTH_GETADAPTERSTATE) - - protected: - virtual ~BluetoothGetAdapterStateFunction(); - - // BluetoothExtensionFunction: - virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) OVERRIDE; -}; - -class BluetoothGetDevicesFunction : public BluetoothExtensionFunction { - public: - DECLARE_EXTENSION_FUNCTION("bluetooth.getDevices", BLUETOOTH_GETDEVICES) - - protected: - virtual ~BluetoothGetDevicesFunction(); - - // BluetoothExtensionFunction: - virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) OVERRIDE; -}; - -class BluetoothGetDeviceFunction : public BluetoothExtensionFunction { - public: - DECLARE_EXTENSION_FUNCTION("bluetooth.getDevice", BLUETOOTH_GETDEVICE) - - // BluetoothExtensionFunction: - virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) OVERRIDE; - - protected: - virtual ~BluetoothGetDeviceFunction(); -}; - class BluetoothAddProfileFunction : public UIThreadExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("bluetooth.addProfile", BLUETOOTH_ADDPROFILE) @@ -181,7 +79,7 @@ class BluetoothAddProfileFunction : public UIThreadExtensionFunction { BluetoothAddProfileFunction(); protected: - virtual ~BluetoothAddProfileFunction(); + virtual ~BluetoothAddProfileFunction() {} virtual bool RunImpl() OVERRIDE; virtual void RegisterProfile( @@ -200,137 +98,121 @@ class BluetoothRemoveProfileFunction : public SyncExtensionFunction { BLUETOOTH_REMOVEPROFILE) protected: - virtual ~BluetoothRemoveProfileFunction(); + virtual ~BluetoothRemoveProfileFunction() {} virtual bool RunImpl() OVERRIDE; }; -class BluetoothGetProfilesFunction : public BluetoothExtensionFunction { +class BluetoothGetAdapterStateFunction : public BluetoothExtensionFunction { public: - DECLARE_EXTENSION_FUNCTION("bluetooth.getProfiles", BLUETOOTH_GETPROFILES) + DECLARE_EXTENSION_FUNCTION("bluetooth.getAdapterState", + BLUETOOTH_GETADAPTERSTATE) protected: - virtual ~BluetoothGetProfilesFunction() {} + virtual ~BluetoothGetAdapterStateFunction() {} // BluetoothExtensionFunction: virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) OVERRIDE; }; -class BluetoothConnectFunction : public BluetoothExtensionFunction { +class BluetoothGetDevicesFunction : public BluetoothExtensionFunction { public: - DECLARE_EXTENSION_FUNCTION("bluetooth.connect", BLUETOOTH_CONNECT) + DECLARE_EXTENSION_FUNCTION("bluetooth.getDevices", BLUETOOTH_GETDEVICES) protected: - virtual ~BluetoothConnectFunction(); + virtual ~BluetoothGetDevicesFunction() {} // BluetoothExtensionFunction: virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) OVERRIDE; - - private: - void OnSuccessCallback(); - void OnErrorCallback(const std::string& error); }; -class BluetoothDisconnectFunction : public BluetoothSocketApiFunction { +class BluetoothGetDeviceFunction : public BluetoothExtensionFunction { public: - DECLARE_EXTENSION_FUNCTION("bluetooth.disconnect", BLUETOOTH_DISCONNECT) - BluetoothDisconnectFunction(); + DECLARE_EXTENSION_FUNCTION("bluetooth.getDevice", BLUETOOTH_GETDEVICE) protected: - virtual ~BluetoothDisconnectFunction(); + virtual ~BluetoothGetDeviceFunction() {} - // AsyncApiFunction: - virtual bool Prepare() OVERRIDE; - virtual void AsyncWorkStart() OVERRIDE; - - private: - void OnSuccess(); - - scoped_ptr<bluetooth::Disconnect::Params> params_; + // BluetoothExtensionFunction: + virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) OVERRIDE; }; -class BluetoothSendFunction : public BluetoothSocketApiFunction { +class BluetoothConnectFunction : public BluetoothExtensionFunction { public: - DECLARE_EXTENSION_FUNCTION("bluetooth.send", BLUETOOTH_WRITE) - BluetoothSendFunction(); + DECLARE_EXTENSION_FUNCTION("bluetooth.connect", BLUETOOTH_CONNECT) protected: - virtual ~BluetoothSendFunction(); + virtual ~BluetoothConnectFunction() {} - // AsyncApiFunction: - virtual bool Prepare() OVERRIDE; - virtual void AsyncWorkStart() OVERRIDE; + // BluetoothExtensionFunction: + virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) 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_; + void OnSuccessCallback(); + void OnErrorCallback(); }; -class BluetoothUpdateSocketFunction : public BluetoothSocketApiFunction { +class BluetoothDisconnectFunction : public SyncExtensionFunction { public: - DECLARE_EXTENSION_FUNCTION("bluetooth.updateSocket", BLUETOOTH_UPDATE_SOCKET) - BluetoothUpdateSocketFunction(); + DECLARE_EXTENSION_FUNCTION("bluetooth.disconnect", BLUETOOTH_DISCONNECT) protected: - virtual ~BluetoothUpdateSocketFunction(); - - // AsyncApiFunction: - virtual bool Prepare() OVERRIDE; - virtual void Work() OVERRIDE; + virtual ~BluetoothDisconnectFunction() {} - private: - scoped_ptr<bluetooth::UpdateSocket::Params> params_; + // ExtensionFunction: + virtual bool RunImpl() OVERRIDE; }; -class BluetoothSetSocketPausedFunction : public BluetoothSocketApiFunction { +class BluetoothReadFunction : public AsyncApiFunction { public: - DECLARE_EXTENSION_FUNCTION("bluetooth.setSocketPaused", - BLUETOOTH_SET_SOCKET_PAUSED) - BluetoothSetSocketPausedFunction(); + DECLARE_EXTENSION_FUNCTION("bluetooth.read", BLUETOOTH_READ) + BluetoothReadFunction(); protected: - virtual ~BluetoothSetSocketPausedFunction(); + virtual ~BluetoothReadFunction(); // AsyncApiFunction: virtual bool Prepare() OVERRIDE; + virtual bool Respond() OVERRIDE; virtual void Work() OVERRIDE; private: - scoped_ptr<bluetooth::SetSocketPaused::Params> params_; + bool success_; + scoped_refptr<device::BluetoothSocket> socket_; }; -class BluetoothGetSocketFunction : public BluetoothSocketApiFunction { +class BluetoothWriteFunction : public AsyncApiFunction { public: - DECLARE_EXTENSION_FUNCTION("bluetooth.getSocket", BLUETOOTH_GET_SOCKET) - - BluetoothGetSocketFunction(); + DECLARE_EXTENSION_FUNCTION("bluetooth.write", BLUETOOTH_WRITE) + BluetoothWriteFunction(); protected: - virtual ~BluetoothGetSocketFunction(); + virtual ~BluetoothWriteFunction(); // AsyncApiFunction: virtual bool Prepare() OVERRIDE; + virtual bool Respond() OVERRIDE; virtual void Work() OVERRIDE; private: - scoped_ptr<bluetooth::GetSocket::Params> params_; + bool success_; + const base::BinaryValue* data_to_write_; // memory is owned by args_ + scoped_refptr<device::BluetoothSocket> socket_; }; -class BluetoothGetSocketsFunction : public BluetoothSocketApiFunction { +class BluetoothSetOutOfBandPairingDataFunction + : public BluetoothExtensionFunction { public: - DECLARE_EXTENSION_FUNCTION("bluetooth.getSockets", BLUETOOTH_GET_SOCKETS) - - BluetoothGetSocketsFunction(); + DECLARE_EXTENSION_FUNCTION("bluetooth.setOutOfBandPairingData", + BLUETOOTH_SETOUTOFBANDPAIRINGDATA) protected: - virtual ~BluetoothGetSocketsFunction(); + virtual ~BluetoothSetOutOfBandPairingDataFunction() {} - // AsyncApiFunction: - virtual bool Prepare() OVERRIDE; - virtual void Work() OVERRIDE; + void OnSuccessCallback(); + void OnErrorCallback(); + + // BluetoothExtensionFunction: + virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) OVERRIDE; }; class BluetoothGetLocalOutOfBandPairingDataFunction @@ -342,29 +224,14 @@ class BluetoothGetLocalOutOfBandPairingDataFunction protected: virtual ~BluetoothGetLocalOutOfBandPairingDataFunction() {} - void ReadCallback(const device::BluetoothOutOfBandPairingData& data); + void ReadCallback( + const device::BluetoothOutOfBandPairingData& data); void ErrorCallback(); // BluetoothExtensionFunction: virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) OVERRIDE; }; -class BluetoothSetOutOfBandPairingDataFunction - : public BluetoothExtensionFunction { - public: - DECLARE_EXTENSION_FUNCTION("bluetooth.setOutOfBandPairingData", - BLUETOOTH_SETOUTOFBANDPAIRINGDATA) - - protected: - virtual ~BluetoothSetOutOfBandPairingDataFunction() {} - - void OnSuccessCallback(); - void OnErrorCallback(); - - // BluetoothExtensionFunction: - virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) OVERRIDE; -}; - class BluetoothStartDiscoveryFunction : public BluetoothExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("bluetooth.startDiscovery", diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.cc b/chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.cc deleted file mode 100644 index e818152..0000000 --- a/chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.cc +++ /dev/null @@ -1,95 +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. - -#include "chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.h" - -#include "device/bluetooth/bluetooth_socket.h" -#include "net/base/io_buffer.h" - -namespace extensions { - -// static -static base::LazyInstance< - BrowserContextKeyedAPIFactory<ApiResourceManager<BluetoothApiSocket> > > - g_server_factory = LAZY_INSTANCE_INITIALIZER; - -// static -template <> -BrowserContextKeyedAPIFactory<ApiResourceManager<BluetoothApiSocket> >* -ApiResourceManager<BluetoothApiSocket>::GetFactoryInstance() { - return g_server_factory.Pointer(); -} - -BluetoothApiSocket::BluetoothApiSocket( - const std::string& owner_extension_id, - scoped_refptr<device::BluetoothSocket> 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) { - DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); -} - -BluetoothApiSocket::~BluetoothApiSocket() { - DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); - socket_->Close(); -} - -void BluetoothApiSocket::Disconnect(const base::Closure& success_callback) { - DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); - socket_->Disconnect(success_callback); -} - -bool BluetoothApiSocket::IsPersistent() const { - DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); - return persistent_; -} - -void BluetoothApiSocket::Receive( - int count, - const ReceiveCompletionCallback& success_callback, - const ReceiveErrorCompletionCallback& error_callback) { - DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); - socket_->Receive(count, - success_callback, - base::Bind(&OnSocketReceiveError, error_callback)); -} - -// static -void BluetoothApiSocket::OnSocketReceiveError( - const ReceiveErrorCompletionCallback& 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<net::IOBuffer> buffer, - int buffer_size, - const SendCompletionCallback& success_callback, - const ErrorCompletionCallback& error_callback) { - DCHECK(content::BrowserThread::CurrentlyOn(kThreadId)); - socket_->Send(buffer, buffer_size, success_callback, error_callback); -} - -} // namespace extensions diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.h b/chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.h deleted file mode 100644 index 02b0bbd..0000000 --- a/chrome/browser/extensions/api/bluetooth/bluetooth_api_socket.h +++ /dev/null @@ -1,125 +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_API_SOCKET_H_ -#define CHROME_BROWSER_EXTENSIONS_API_BLUETOOTH_BLUETOOTH_API_SOCKET_H_ - -#include <string> - -#include "device/bluetooth/bluetooth_socket.h" -#include "device/bluetooth/bluetooth_uuid.h" -#include "extensions/browser/api/api_resource.h" -#include "extensions/browser/api/api_resource_manager.h" - -namespace net { -class IOBuffer; -} // namespace net - -namespace extensions { - -// Representation of socket instances from the "bluetooth" namespace, -// abstracting away platform differences from the underlying BluetoothSocketXxx -// class. All methods must be called on the |kThreadId| thread. -class BluetoothApiSocket : public ApiResource { - public: - enum ErrorReason { kSystemError, 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; - - BluetoothApiSocket(const std::string& owner_extension_id, - scoped_refptr<device::BluetoothSocket> socket, - const std::string& device_address, - const device::BluetoothUUID& uuid); - virtual ~BluetoothApiSocket(); - - // Closes the underlying connection. This is a best effort, and never fails. - virtual void Disconnect(const base::Closure& success_callback); - - // Receives data from the socket and calls |success_callback| when data is - // available. |count| is maximum amount of bytes received. If an error occurs, - // calls |error_callback| with a reason and a message. In particular, if a - // |Receive| operation is still pending, |error_callback| will be called with - // |kIOPending| error. - virtual void Receive(int count, - const ReceiveCompletionCallback& success_callback, - const ReceiveErrorCompletionCallback& 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 - // |buffer|. If an error occurs, calls |error_callback| with a reason and a - // message. Calling |Send| multiple times without waiting for the callbacks to - // be called is a valid usage, as |buffer| instances are buffered until the - // underlying communication channel is available for sending data. - virtual void Send(scoped_refptr<net::IOBuffer> buffer, - int buffer_size, - const SendCompletionCallback& success_callback, - const ErrorCompletionCallback& error_callback); - - const std::string& device_address() const { return device_address_; } - const device::BluetoothUUID& uuid() const { return uuid_; } - - // Overriden from extensions::ApiResource. - virtual bool IsPersistent() const OVERRIDE; - - const std::string& name() const { return name_; } - void set_name(const std::string& name) { name_ = name; } - - bool persistent() const { return persistent_; } - void set_persistent(bool persistent) { persistent_ = persistent; } - - int buffer_size() const { return buffer_size_; } - void set_buffer_size(int buffer_size) { buffer_size_ = buffer_size; } - - bool paused() const { return paused_; } - void set_paused(bool paused) { paused_ = paused; } - - // Platform specific implementations of |BluetoothSocket| require being called - // on the UI thread. - static const content::BrowserThread::ID kThreadId = - content::BrowserThread::UI; - - private: - friend class ApiResourceManager<BluetoothApiSocket>; - static const char* service_name() { return "BluetoothApiSocketManager"; } - - static void OnSocketReceiveError( - const ReceiveErrorCompletionCallback& error_callback, - device::BluetoothSocket::ErrorReason reason, - const std::string& message); - - // The underlying device socket instance. - scoped_refptr<device::BluetoothSocket> socket_; - - // The address of the device this socket is connected to. - std::string device_address_; - - // The uuid of the service this socket is connected to. - device::BluetoothUUID uuid_; - - // Application-defined string - see bluetooth.idl. - std::string name_; - - // Flag indicating whether the socket is left open when the application is - // suspended - see bluetooth.idl. - bool persistent_; - - // The size of the buffer used to receive data - see bluetooth.idl. - int buffer_size_; - - // Flag indicating whether a connected socket blocks its peer from sending - // more data - see bluetooth.idl. - bool paused_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothApiSocket); -}; - -} // namespace extensions - -#endif // CHROME_BROWSER_EXTENSIONS_API_BLUETOOTH_BLUETOOTH_API_SOCKET_H_ diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_api_unittest.cc b/chrome/browser/extensions/api/bluetooth/bluetooth_api_unittest.cc deleted file mode 100644 index b13909f..0000000 --- a/chrome/browser/extensions/api/bluetooth/bluetooth_api_unittest.cc +++ /dev/null @@ -1,207 +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. - -#include <string> - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/extensions/api/bluetooth/bluetooth_api.h" -#include "chrome/browser/extensions/api/bluetooth/bluetooth_event_router.h" -#include "chrome/browser/extensions/extension_system_factory.h" -#include "chrome/browser/extensions/test_extension_system.h" -#include "chrome/common/extensions/api/bluetooth.h" -#include "chrome/test/base/testing_browser_process.h" -#include "chrome/test/base/testing_profile.h" -#include "chrome/test/base/testing_profile_manager.h" -#include "content/public/browser/notification_service.h" -#include "content/public/test/test_browser_thread_bundle.h" -#include "device/bluetooth/test/mock_bluetooth_adapter.h" -#include "device/bluetooth/test/mock_bluetooth_device.h" -#include "device/bluetooth/test/mock_bluetooth_profile.h" -#include "device/bluetooth/test/mock_bluetooth_socket.h" -#include "extensions/browser/event_router.h" -#include "extensions/common/extension_builder.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace { - -const char kTestExtensionId[] = "test extension id"; -const device::BluetoothUUID kAudioProfileUuid("1234"); - -static KeyedService* ApiResourceManagerTestFactory( - content::BrowserContext* context) { - content::BrowserThread::ID id; - CHECK(content::BrowserThread::GetCurrentThreadIdentifier(&id)); - return extensions::ApiResourceManager< - extensions::BluetoothApiSocket>::CreateApiResourceManagerForTest(context, - id); -} - -static KeyedService* BluetoothAPITestFactory(content::BrowserContext* context) { - content::BrowserThread::ID id; - CHECK(content::BrowserThread::GetCurrentThreadIdentifier(&id)); - return new extensions::BluetoothAPI(context); -} - -class FakeEventRouter : public extensions::EventRouter { - public: - explicit FakeEventRouter(Profile* profile) : EventRouter(profile, NULL) {} - - virtual void DispatchEventToExtension(const std::string& extension_id, - scoped_ptr<extensions::Event> event) - OVERRIDE { - extension_id_ = extension_id; - event_ = event.Pass(); - } - - std::string extension_id() const { return extension_id_; } - - const extensions::Event* event() const { return event_.get(); } - - private: - std::string extension_id_; - scoped_ptr<extensions::Event> event_; - - DISALLOW_COPY_AND_ASSIGN(FakeEventRouter); -}; - -class FakeExtensionSystem : public extensions::TestExtensionSystem { - public: - explicit FakeExtensionSystem(Profile* profile) - : extensions::TestExtensionSystem(profile) {} - - virtual extensions::EventRouter* event_router() OVERRIDE { - if (!fake_event_router_) - fake_event_router_.reset(new FakeEventRouter(profile_)); - return fake_event_router_.get(); - } - - private: - scoped_ptr<FakeEventRouter> fake_event_router_; - - DISALLOW_COPY_AND_ASSIGN(FakeExtensionSystem); -}; - -KeyedService* BuildFakeExtensionSystem(content::BrowserContext* profile) { - return new FakeExtensionSystem(static_cast<Profile*>(profile)); -} - -} // namespace - -namespace extensions { - -namespace bluetooth = api::bluetooth; - -class ExtensionBluetoothApiTest : public testing::Test { - public: - ExtensionBluetoothApiTest() - : profile_manager_(TestingBrowserProcess::GetGlobal()), - mock_adapter_(new testing::StrictMock<device::MockBluetoothAdapter>()), - test_profile_(NULL) {} - - virtual void SetUp() OVERRIDE { - testing::Test::SetUp(); - ASSERT_TRUE(profile_manager_.SetUp()); - test_profile_ = profile_manager_.CreateTestingProfile("test"); - ExtensionSystemFactory::GetInstance()->SetTestingFactoryAndUse( - test_profile_, &BuildFakeExtensionSystem); - ApiResourceManager<BluetoothApiSocket>::GetFactoryInstance() - ->SetTestingFactoryAndUse(test_profile_, ApiResourceManagerTestFactory); - BluetoothAPI::GetFactoryInstance()->SetTestingFactoryAndUse( - test_profile_, BluetoothAPITestFactory); - BluetoothAPI::Get(test_profile_)->event_router()->SetAdapterForTest( - mock_adapter_); - } - - virtual void TearDown() OVERRIDE { - // Some profile-dependent services rely on UI thread to clean up. We make - // sure they are properly cleaned up by running the UI message loop until - // idle. - test_profile_ = NULL; - profile_manager_.DeleteTestingProfile("test"); - base::RunLoop run_loop; - run_loop.RunUntilIdle(); - } - - protected: - content::TestBrowserThreadBundle thread_bundle_; - TestingProfileManager profile_manager_; - scoped_refptr<testing::StrictMock<device::MockBluetoothAdapter> > - mock_adapter_; - testing::NiceMock<device::MockBluetoothProfile> mock_audio_profile_; - testing::NiceMock<device::MockBluetoothProfile> mock_health_profile_; - // Profiles are weak pointers, owned by |profile_manager_|. - TestingProfile* test_profile_; -}; - -TEST_F(ExtensionBluetoothApiTest, DispatchConnectionEvent) { - testing::NiceMock<device::MockBluetoothDevice> mock_device( - mock_adapter_.get(), 0, "device name", "device address", true, false); - EXPECT_CALL(*mock_adapter_, GetDevice(mock_device.GetAddress())) - .WillOnce(testing::Return(&mock_device)); - scoped_refptr<testing::NiceMock<device::MockBluetoothSocket> > mock_socket( - new testing::NiceMock<device::MockBluetoothSocket>()); - - BluetoothAPI::Get(test_profile_)->event_router()->AddProfile( - kAudioProfileUuid, kTestExtensionId, &mock_audio_profile_); - - BluetoothAPI::Get(test_profile_)->DispatchConnectionEvent( - kTestExtensionId, kAudioProfileUuid, &mock_device, mock_socket); - // Connection events are dispatched using a couple of PostTask to the UI - // thread. Waiting until idle ensures the event is dispatched to the - // receiver(s). - base::RunLoop().RunUntilIdle(); - - FakeEventRouter* fake_event_router = static_cast<FakeEventRouter*>( - ExtensionSystem::Get(test_profile_)->event_router()); - - ASSERT_TRUE(fake_event_router->event()); - EXPECT_STREQ(kTestExtensionId, fake_event_router->extension_id().c_str()); - EXPECT_STREQ(bluetooth::OnConnection::kEventName, - fake_event_router->event()->event_name.c_str()); - - base::ListValue* event_args = fake_event_router->event()->event_args.get(); - base::DictionaryValue* socket_value = NULL; - ASSERT_TRUE(event_args->GetDictionary(0, &socket_value)); - int socket_id; - ASSERT_TRUE(socket_value->GetInteger("id", &socket_id)); - - ASSERT_TRUE(BluetoothAPI::Get(test_profile_)->socket_data()->Get( - kTestExtensionId, socket_id)); - - std::string uuid; - ASSERT_TRUE(socket_value->GetString("uuid", &uuid)); - EXPECT_STREQ(kAudioProfileUuid.canonical_value().c_str(), uuid.c_str()); - - EXPECT_CALL(*mock_adapter_, RemoveObserver(testing::_)).Times(1); - BluetoothAPI::Get(test_profile_)->socket_data()->Remove(kTestExtensionId, - socket_id); -} - -TEST_F(ExtensionBluetoothApiTest, DoNotDispatchConnectionEvent) { - testing::NiceMock<device::MockBluetoothDevice> mock_device( - mock_adapter_.get(), 0, "device name", "device address", true, false); - scoped_refptr<testing::NiceMock<device::MockBluetoothSocket> > mock_socket( - new testing::NiceMock<device::MockBluetoothSocket>()); - - // Connection event won't be dispatched for non-registered profiles. - BluetoothAPI::Get(test_profile_)->DispatchConnectionEvent( - kTestExtensionId, kAudioProfileUuid, &mock_device, mock_socket); - // Connection events are dispatched using a couple of PostTask to the UI - // thread. Waiting until idle ensures the event is dispatched to the - // receiver(s). - base::RunLoop().RunUntilIdle(); - - FakeEventRouter* fake_event_router = static_cast<FakeEventRouter*>( - ExtensionSystem::Get(test_profile_)->event_router()); - EXPECT_TRUE(fake_event_router->event() == NULL); - - EXPECT_CALL(*mock_adapter_, RemoveObserver(testing::_)).Times(1); -} - -} // namespace extensions diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_apitest.cc b/chrome/browser/extensions/api/bluetooth/bluetooth_apitest.cc index 4c1e85f..f1113b8 100644 --- a/chrome/browser/extensions/api/bluetooth/bluetooth_apitest.cc +++ b/chrome/browser/extensions/api/bluetooth/bluetooth_apitest.cc @@ -74,6 +74,7 @@ class BluetoothApiTest : public ExtensionApiTest { device3_.reset(new testing::NiceMock<MockBluetoothDevice>( mock_adapter_, 0, "d3", "31:32:33:34:35:36", false /* paired */, false /* connected */)); + } void DiscoverySessionCallback( @@ -104,11 +105,8 @@ class BluetoothApiTest : public ExtensionApiTest { scoped_ptr<testing::NiceMock<MockBluetoothProfile> > profile2_; extensions::BluetoothEventRouter* event_router() { - return bluetooth_api()->event_router(); - } - - extensions::BluetoothAPI* bluetooth_api() { - return extensions::BluetoothAPI::Get(browser()->profile()); + return extensions::BluetoothAPI::Get(browser()->profile()) + ->bluetooth_event_router(); } private: @@ -156,11 +154,6 @@ static bool CallClosure(const base::Closure& callback) { return true; } -static bool CallErrorClosure(const BluetoothDevice::ErrorCallback& callback) { - callback.Run(); - return true; -} - static void StopDiscoverySessionCallback(const base::Closure& callback, const base::Closure& error_callback) { callback.Run(); @@ -325,9 +318,9 @@ IN_PROC_BROWSER_TEST_F(BluetoothApiTest, SetOutOfBandPairingData) { testing::Mock::VerifyAndClearExpectations(device1_.get()); EXPECT_CALL(*mock_adapter_, GetDevice(device1_->GetAddress())) .WillOnce(testing::Return(device1_.get())); - EXPECT_CALL( - *device1_, - ClearOutOfBandPairingData(testing::_, testing::Truly(CallErrorClosure))); + EXPECT_CALL(*device1_, + ClearOutOfBandPairingData(testing::_, + testing::Truly(CallClosure))); set_oob_function = setupFunction( new api::BluetoothSetOutOfBandPairingDataFunction); @@ -569,17 +562,11 @@ IN_PROC_BROWSER_TEST_F(BluetoothApiTest, OnConnection) { scoped_refptr<device::MockBluetoothSocket> socket = new device::MockBluetoothSocket(); - EXPECT_CALL(*mock_adapter_, GetDevice(device1_->GetAddress())) - .WillOnce(testing::Return(device1_.get())); - event_router()->AddProfile( - BluetoothUUID("1234"), extension->id(), profile1_.get()); - bluetooth_api()->DispatchConnectionEvent( + BluetoothUUID("1234"), + extension->id(), profile1_.get()); + event_router()->DispatchConnectionEvent( extension->id(), BluetoothUUID("1234"), device1_.get(), socket); - // Connection events are dispatched using a couple of PostTask to the UI - // thread. Waiting until idle ensures the event is dispatched to the - // receiver(s). - base::RunLoop().RunUntilIdle(); listener.Reply("go"); EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_event_router.cc b/chrome/browser/extensions/api/bluetooth/bluetooth_event_router.cc index a440c49..41bba4c 100644 --- a/chrome/browser/extensions/api/bluetooth/bluetooth_event_router.cc +++ b/chrome/browser/extensions/api/bluetooth/bluetooth_event_router.cc @@ -30,7 +30,6 @@ #include "device/bluetooth/bluetooth_profile.h" #include "device/bluetooth/bluetooth_socket.h" #include "extensions/browser/event_router.h" -#include "extensions/browser/extension_host.h" #include "extensions/browser/extension_system.h" namespace extensions { @@ -38,6 +37,12 @@ namespace extensions { namespace bluetooth = api::bluetooth; namespace bt_private = api::bluetooth_private; +// A struct storing a Bluetooth socket and the extension that added it. +struct BluetoothEventRouter::ExtensionBluetoothSocketRecord { + std::string extension_id; + scoped_refptr<device::BluetoothSocket> socket; +}; + // A struct storing a Bluetooth profile and the extension that added it. struct BluetoothEventRouter::ExtensionBluetoothProfileRecord { std::string extension_id; @@ -48,23 +53,21 @@ BluetoothEventRouter::BluetoothEventRouter(content::BrowserContext* context) : browser_context_(context), adapter_(NULL), num_event_listeners_(0), + next_socket_id_(1), weak_ptr_factory_(this) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); DCHECK(browser_context_); registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED, content::Source<content::BrowserContext>(browser_context_)); - registrar_.Add(this, - chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED, - content::Source<content::BrowserContext>(browser_context_)); } BluetoothEventRouter::~BluetoothEventRouter() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); if (adapter_.get()) { adapter_->RemoveObserver(this); adapter_ = NULL; } + DLOG_IF(WARNING, socket_map_.size() != 0) + << "Bluetooth sockets are still open."; CleanUpAllExtensions(); } @@ -83,18 +86,39 @@ void BluetoothEventRouter::GetAdapter( device::BluetoothAdapterFactory::GetAdapter(callback); } +int BluetoothEventRouter::RegisterSocket( + const std::string& extension_id, + scoped_refptr<device::BluetoothSocket> socket) { + // If there is a socket registered with the same fd, just return it's id + for (SocketMap::const_iterator i = socket_map_.begin(); + i != socket_map_.end(); ++i) { + if (i->second.socket.get() == socket.get()) + return i->first; + } + int return_id = next_socket_id_++; + ExtensionBluetoothSocketRecord record = { extension_id, socket }; + socket_map_[return_id] = record; + return return_id; +} + +bool BluetoothEventRouter::ReleaseSocket(int id) { + SocketMap::iterator socket_entry = socket_map_.find(id); + if (socket_entry == socket_map_.end()) + return false; + socket_map_.erase(socket_entry); + return true; +} + void BluetoothEventRouter::AddProfile( const device::BluetoothUUID& uuid, const std::string& extension_id, device::BluetoothProfile* bluetooth_profile) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); DCHECK(!HasProfile(uuid)); ExtensionBluetoothProfileRecord record = { extension_id, bluetooth_profile }; bluetooth_profile_map_[uuid] = record; } void BluetoothEventRouter::RemoveProfile(const device::BluetoothUUID& uuid) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); BluetoothProfileMap::iterator iter = bluetooth_profile_map_.find(uuid); if (iter != bluetooth_profile_map_.end()) { device::BluetoothProfile* bluetooth_profile = iter->second.profile; @@ -104,7 +128,6 @@ void BluetoothEventRouter::RemoveProfile(const device::BluetoothUUID& uuid) { } bool BluetoothEventRouter::HasProfile(const device::BluetoothUUID& uuid) const { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); return bluetooth_profile_map_.find(uuid) != bluetooth_profile_map_.end(); } @@ -154,7 +177,6 @@ void BluetoothEventRouter::StopDiscoverySession( device::BluetoothProfile* BluetoothEventRouter::GetProfile( const device::BluetoothUUID& uuid) const { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); BluetoothProfileMap::const_iterator iter = bluetooth_profile_map_.find(uuid); if (iter != bluetooth_profile_map_.end()) return iter->second.profile; @@ -162,6 +184,36 @@ device::BluetoothProfile* BluetoothEventRouter::GetProfile( return NULL; } +scoped_refptr<device::BluetoothSocket> BluetoothEventRouter::GetSocket(int id) { + SocketMap::iterator socket_entry = socket_map_.find(id); + if (socket_entry == socket_map_.end()) + return NULL; + return socket_entry->second.socket; +} + +void BluetoothEventRouter::DispatchConnectionEvent( + const std::string& extension_id, + const device::BluetoothUUID& uuid, + const device::BluetoothDevice* device, + scoped_refptr<device::BluetoothSocket> socket) { + if (!HasProfile(uuid)) + return; + + int socket_id = RegisterSocket(extension_id, socket); + bluetooth::Socket result_socket; + bluetooth::BluetoothDeviceToApiDevice(*device, &result_socket.device); + result_socket.profile.uuid = uuid.canonical_value(); + result_socket.id = socket_id; + + scoped_ptr<base::ListValue> args = + bluetooth::OnConnection::Create(result_socket); + scoped_ptr<Event> event(new Event( + bluetooth::OnConnection::kEventName, args.Pass())); + ExtensionSystem::Get(browser_context_) + ->event_router() + ->DispatchEventToExtension(extension_id, event.Pass()); +} + BluetoothApiPairingDelegate* BluetoothEventRouter::GetPairingDelegate( const std::string& extension_id) { return ContainsKey(pairing_delegate_map_, extension_id) @@ -229,7 +281,6 @@ void BluetoothEventRouter::RemovePairingDelegate( void BluetoothEventRouter::AdapterPresentChanged( device::BluetoothAdapter* adapter, bool present) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); if (adapter != adapter_.get()) { DVLOG(1) << "Ignoring event for adapter " << adapter->GetAddress(); return; @@ -240,7 +291,6 @@ void BluetoothEventRouter::AdapterPresentChanged( void BluetoothEventRouter::AdapterPoweredChanged( device::BluetoothAdapter* adapter, bool has_power) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); if (adapter != adapter_.get()) { DVLOG(1) << "Ignoring event for adapter " << adapter->GetAddress(); return; @@ -251,7 +301,6 @@ void BluetoothEventRouter::AdapterPoweredChanged( void BluetoothEventRouter::AdapterDiscoveringChanged( device::BluetoothAdapter* adapter, bool discovering) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); if (adapter != adapter_.get()) { DVLOG(1) << "Ignoring event for adapter " << adapter->GetAddress(); return; @@ -279,7 +328,6 @@ void BluetoothEventRouter::AdapterDiscoveringChanged( void BluetoothEventRouter::DeviceAdded(device::BluetoothAdapter* adapter, device::BluetoothDevice* device) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); if (adapter != adapter_.get()) { DVLOG(1) << "Ignoring event for adapter " << adapter->GetAddress(); return; @@ -290,7 +338,6 @@ void BluetoothEventRouter::DeviceAdded(device::BluetoothAdapter* adapter, void BluetoothEventRouter::DeviceChanged(device::BluetoothAdapter* adapter, device::BluetoothDevice* device) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); if (adapter != adapter_.get()) { DVLOG(1) << "Ignoring event for adapter " << adapter->GetAddress(); return; @@ -301,7 +348,6 @@ void BluetoothEventRouter::DeviceChanged(device::BluetoothAdapter* adapter, void BluetoothEventRouter::DeviceRemoved(device::BluetoothAdapter* adapter, device::BluetoothDevice* device) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); if (adapter != adapter_.get()) { DVLOG(1) << "Ignoring event for adapter " << adapter->GetAddress(); return; @@ -312,7 +358,6 @@ void BluetoothEventRouter::DeviceRemoved(device::BluetoothAdapter* adapter, void BluetoothEventRouter::OnListenerAdded() { num_event_listeners_++; - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); if (!adapter_.get()) { GetAdapter(base::Bind(&BluetoothEventRouter::OnAdapterInitialized, weak_ptr_factory_.GetWeakPtr(), @@ -327,8 +372,7 @@ void BluetoothEventRouter::OnListenerRemoved() { } void BluetoothEventRouter::DispatchAdapterStateEvent() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - api::bluetooth::AdapterState state; + bluetooth::AdapterState state; PopulateAdapterState(*adapter_.get(), &state); scoped_ptr<base::ListValue> args = @@ -355,7 +399,6 @@ void BluetoothEventRouter::DispatchDeviceEvent( void BluetoothEventRouter::CleanUpForExtension( const std::string& extension_id) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); RemovePairingDelegate(extension_id); // Remove all profiles added by the extension. @@ -370,6 +413,17 @@ void BluetoothEventRouter::CleanUpForExtension( } } + // Remove all sockets opened by the extension. + SocketMap::iterator socket_iter = socket_map_.begin(); + while (socket_iter != socket_map_.end()) { + int socket_id = socket_iter->first; + ExtensionBluetoothSocketRecord record = socket_iter->second; + socket_iter++; + if (record.extension_id == extension_id) { + ReleaseSocket(socket_id); + } + } + // Remove any discovery session initiated by the extension. DiscoverySessionMap::iterator session_iter = discovery_session_map_.find(extension_id); @@ -394,6 +448,10 @@ void BluetoothEventRouter::CleanUpAllExtensions() { } discovery_session_map_.clear(); + SocketMap::iterator socket_iter = socket_map_.begin(); + while (socket_iter != socket_map_.end()) + ReleaseSocket(socket_iter++->first); + PairingDelegateMap::iterator pairing_iter = pairing_delegate_map_.begin(); while (pairing_iter != pairing_delegate_map_.end()) RemovePairingDelegate(pairing_iter++->first); @@ -416,7 +474,6 @@ void BluetoothEventRouter::Observe( int type, const content::NotificationSource& source, const content::NotificationDetails& details) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); switch (type) { case chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED: { extensions::UnloadedExtensionInfo* info = @@ -424,11 +481,6 @@ void BluetoothEventRouter::Observe( CleanUpForExtension(info->extension->id()); break; } - case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: { - ExtensionHost* host = content::Details<ExtensionHost>(details).ptr(); - CleanUpForExtension(host->extension_id()); - break; - } } } diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_event_router.h b/chrome/browser/extensions/api/bluetooth/bluetooth_event_router.h index d3c3a9a..4d86b4f 100644 --- a/chrome/browser/extensions/api/bluetooth/bluetooth_event_router.h +++ b/chrome/browser/extensions/api/bluetooth/bluetooth_event_router.h @@ -49,6 +49,17 @@ class BluetoothEventRouter : public device::BluetoothAdapter::Observer, void GetAdapter( const device::BluetoothAdapterFactory::AdapterCallback& callback); + // Register the BluetoothSocket |socket| for use by the extensions system. + // This class will hold onto the socket for its lifetime until + // ReleaseSocket is called for the socket, or until the extension associated + // with the socket is disabled/ reloaded. Returns an id for the socket. + int RegisterSocket(const std::string& extension_id, + scoped_refptr<device::BluetoothSocket> socket); + + // Release the BluetoothSocket corresponding to |id|. Returns true if + // the socket was found and released, false otherwise. + bool ReleaseSocket(int id); + // Add the BluetoothProfile |bluetooth_profile| for use by the extension // system. This class will hold onto the profile until RemoveProfile is // called for the profile, or until the extension that added the profile @@ -88,6 +99,16 @@ class BluetoothEventRouter : public device::BluetoothAdapter::Observer, // if the BluetoothProfile with |uuid| does not exist. device::BluetoothProfile* GetProfile(const device::BluetoothUUID& uuid) const; + // Get the BluetoothSocket corresponding to |id|. + scoped_refptr<device::BluetoothSocket> GetSocket(int id); + + // Dispatch an event that takes a connection socket as a parameter to the + // extension that registered the profile that the socket has connected to. + void DispatchConnectionEvent(const std::string& extension_id, + const device::BluetoothUUID& uuid, + const device::BluetoothDevice* device, + scoped_refptr<device::BluetoothSocket> socket); + // Called when a bluetooth event listener is added. void OnListenerAdded(); @@ -157,6 +178,14 @@ class BluetoothEventRouter : public device::BluetoothAdapter::Observer, int num_event_listeners_; + // The next id to use for referring to a BluetoothSocket. We avoid using + // the fd of the socket because we don't want to leak that information to + // the extension javascript. + int next_socket_id_; + + typedef std::map<int, ExtensionBluetoothSocketRecord> SocketMap; + SocketMap socket_map_; + // Maps uuids to a struct containing a Bluetooth profile and its // associated extension id. typedef std::map<device::BluetoothUUID, ExtensionBluetoothProfileRecord> diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_event_router_unittest.cc b/chrome/browser/extensions/api/bluetooth/bluetooth_event_router_unittest.cc index 06ec55e..98bf071 100644 --- a/chrome/browser/extensions/api/bluetooth/bluetooth_event_router_unittest.cc +++ b/chrome/browser/extensions/api/bluetooth/bluetooth_event_router_unittest.cc @@ -16,7 +16,6 @@ #include "chrome/test/base/testing_profile.h" #include "content/public/browser/notification_service.h" #include "content/public/test/test_browser_thread.h" -#include "content/public/test/test_browser_thread_bundle.h" #include "device/bluetooth/bluetooth_uuid.h" #include "device/bluetooth/test/mock_bluetooth_adapter.h" #include "device/bluetooth/test/mock_bluetooth_device.h" @@ -33,6 +32,53 @@ const char kTestExtensionId[] = "test extension id"; const device::BluetoothUUID kAudioProfileUuid("1234"); const device::BluetoothUUID kHealthProfileUuid("4321"); +class FakeEventRouter : public extensions::EventRouter { + public: + explicit FakeEventRouter(Profile* profile) : EventRouter(profile, NULL) {} + + virtual void DispatchEventToExtension( + const std::string& extension_id, + scoped_ptr<extensions::Event> event) OVERRIDE { + extension_id_ = extension_id; + event_ = event.Pass(); + } + + std::string extension_id() const { + return extension_id_; + } + + const extensions::Event* event() const { + return event_.get(); + } + + private: + std::string extension_id_; + scoped_ptr<extensions::Event> event_; + + DISALLOW_COPY_AND_ASSIGN(FakeEventRouter); +}; + +class FakeExtensionSystem : public extensions::TestExtensionSystem { + public: + explicit FakeExtensionSystem(Profile* profile) + : extensions::TestExtensionSystem(profile) {} + + virtual extensions::EventRouter* event_router() OVERRIDE { + if (!fake_event_router_) + fake_event_router_.reset(new FakeEventRouter(profile_)); + return fake_event_router_.get(); + } + + private: + scoped_ptr<FakeEventRouter> fake_event_router_; + + DISALLOW_COPY_AND_ASSIGN(FakeExtensionSystem); +}; + +KeyedService* BuildFakeExtensionSystem(content::BrowserContext* profile) { + return new FakeExtensionSystem(static_cast<Profile*>(profile)); +} + } // namespace namespace extensions { @@ -42,10 +88,10 @@ namespace bluetooth = api::bluetooth; class BluetoothEventRouterTest : public testing::Test { public: BluetoothEventRouterTest() - : ui_thread_(content::BrowserThread::UI, &message_loop_), - mock_adapter_(new testing::StrictMock<device::MockBluetoothAdapter>()), + : mock_adapter_(new testing::StrictMock<device::MockBluetoothAdapter>()), test_profile_(new TestingProfile()), - router_(test_profile_.get()) { + router_(test_profile_.get()), + ui_thread_(content::BrowserThread::UI, &message_loop_) { router_.SetAdapterForTest(mock_adapter_); } @@ -59,14 +105,13 @@ class BluetoothEventRouterTest : public testing::Test { } protected: - base::MessageLoopForUI message_loop_; - // Note: |ui_thread_| must be declared before |router_|. - content::TestBrowserThread ui_thread_; testing::StrictMock<device::MockBluetoothAdapter>* mock_adapter_; testing::NiceMock<device::MockBluetoothProfile> mock_audio_profile_; testing::NiceMock<device::MockBluetoothProfile> mock_health_profile_; scoped_ptr<TestingProfile> test_profile_; BluetoothEventRouter router_; + base::MessageLoopForUI message_loop_; + content::TestBrowserThread ui_thread_; }; TEST_F(BluetoothEventRouterTest, BluetoothEventListener) { @@ -140,4 +185,69 @@ TEST_F(BluetoothEventRouterTest, UnloadExtension) { EXPECT_CALL(*mock_adapter_, RemoveObserver(testing::_)).Times(1); } +TEST_F(BluetoothEventRouterTest, DispatchConnectionEvent) { + router_.AddProfile( + kAudioProfileUuid, kTestExtensionId, &mock_audio_profile_); + + FakeExtensionSystem* fake_extension_system = + static_cast<FakeExtensionSystem*>(ExtensionSystemFactory::GetInstance()-> + SetTestingFactoryAndUse(test_profile_.get(), + &BuildFakeExtensionSystem)); + + testing::NiceMock<device::MockBluetoothDevice> mock_device( + mock_adapter_, 0, "device name", "device address", true, false); + scoped_refptr<testing::NiceMock<device::MockBluetoothSocket> > mock_socket( + new testing::NiceMock<device::MockBluetoothSocket>()); + + router_.DispatchConnectionEvent(kTestExtensionId, + kAudioProfileUuid, + &mock_device, + mock_socket); + + FakeEventRouter* fake_event_router = + static_cast<FakeEventRouter*>(fake_extension_system->event_router()); + + EXPECT_STREQ(kTestExtensionId, fake_event_router->extension_id().c_str()); + EXPECT_STREQ(bluetooth::OnConnection::kEventName, + fake_event_router->event()->event_name.c_str()); + + base::ListValue* event_args = fake_event_router->event()->event_args.get(); + base::DictionaryValue* socket_value = NULL; + ASSERT_TRUE(event_args->GetDictionary(0, &socket_value)); + int socket_id; + ASSERT_TRUE(socket_value->GetInteger("id", &socket_id)); + EXPECT_EQ(mock_socket.get(), router_.GetSocket(socket_id).get()); + + base::DictionaryValue* profile_value = NULL; + ASSERT_TRUE(socket_value->GetDictionary("profile", &profile_value)); + std::string uuid; + ASSERT_TRUE(profile_value->GetString("uuid", &uuid)); + EXPECT_STREQ(kAudioProfileUuid.canonical_value().c_str(), uuid.c_str()); + + EXPECT_CALL(*mock_adapter_, RemoveObserver(testing::_)).Times(1); + router_.ReleaseSocket(socket_id); +} + +TEST_F(BluetoothEventRouterTest, DoNotDispatchConnectionEvent) { + FakeExtensionSystem* fake_extension_system = + static_cast<FakeExtensionSystem*>(ExtensionSystemFactory::GetInstance()-> + SetTestingFactoryAndUse(test_profile_.get(), + &BuildFakeExtensionSystem)); + testing::NiceMock<device::MockBluetoothDevice> mock_device( + mock_adapter_, 0, "device name", "device address", true, false); + scoped_refptr<testing::NiceMock<device::MockBluetoothSocket> > mock_socket( + new testing::NiceMock<device::MockBluetoothSocket>()); + + // Connection event won't be dispatched for non-registered profiles. + router_.DispatchConnectionEvent("test extension id", + kAudioProfileUuid, + &mock_device, + mock_socket); + FakeEventRouter* fake_event_router = + static_cast<FakeEventRouter*>(fake_extension_system->event_router()); + EXPECT_TRUE(fake_event_router->event() == NULL); + + EXPECT_CALL(*mock_adapter_, RemoveObserver(testing::_)).Times(1); +} + } // namespace extensions diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_extension_function.cc b/chrome/browser/extensions/api/bluetooth/bluetooth_extension_function.cc index 2732bea..6c6c23c 100644 --- a/chrome/browser/extensions/api/bluetooth/bluetooth_extension_function.cc +++ b/chrome/browser/extensions/api/bluetooth/bluetooth_extension_function.cc @@ -7,12 +7,9 @@ #include "base/memory/ref_counted.h" #include "chrome/browser/extensions/api/bluetooth/bluetooth_api.h" #include "chrome/browser/extensions/api/bluetooth/bluetooth_event_router.h" -#include "content/public/browser/browser_thread.h" #include "device/bluetooth/bluetooth_adapter.h" #include "device/bluetooth/bluetooth_adapter_factory.h" -using content::BrowserThread; - namespace { const char kPlatformNotSupported[] = @@ -20,24 +17,22 @@ const char kPlatformNotSupported[] = extensions::BluetoothEventRouter* GetEventRouter( content::BrowserContext* context) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - return extensions::BluetoothAPI::Get(context)->event_router(); + return extensions::BluetoothAPI::Get(context)->bluetooth_event_router(); } bool IsBluetoothSupported(content::BrowserContext* context) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); return GetEventRouter(context)->IsBluetoothSupported(); } void GetAdapter(const device::BluetoothAdapterFactory::AdapterCallback callback, content::BrowserContext* context) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); GetEventRouter(context)->GetAdapter(callback); } } // namespace namespace extensions { + namespace api { BluetoothExtensionFunction::BluetoothExtensionFunction() { @@ -47,8 +42,6 @@ BluetoothExtensionFunction::~BluetoothExtensionFunction() { } bool BluetoothExtensionFunction::RunImpl() { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (!IsBluetoothSupported(browser_context())) { SetError(kPlatformNotSupported); return false; @@ -61,9 +54,9 @@ bool BluetoothExtensionFunction::RunImpl() { void BluetoothExtensionFunction::RunOnAdapterReady( scoped_refptr<device::BluetoothAdapter> adapter) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DoWork(adapter); } } // namespace api + } // namespace extensions diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_extension_function.h b/chrome/browser/extensions/api/bluetooth/bluetooth_extension_function.h index 0e77d7a..fd2f3cc 100644 --- a/chrome/browser/extensions/api/bluetooth/bluetooth_extension_function.h +++ b/chrome/browser/extensions/api/bluetooth/bluetooth_extension_function.h @@ -16,11 +16,12 @@ class BluetoothAdapter; } // namespace device namespace extensions { + namespace api { // Base class for bluetooth extension functions. This class initializes -// bluetooth adapter and calls (on the UI thread) DoWork() implemented by -// individual bluetooth extension functions. +// bluetooth adapter and calls DoWork() implemented by individual bluetooth +// extension functions. class BluetoothExtensionFunction : public UIThreadExtensionFunction { public: BluetoothExtensionFunction(); @@ -35,13 +36,14 @@ class BluetoothExtensionFunction : public UIThreadExtensionFunction { void RunOnAdapterReady(scoped_refptr<device::BluetoothAdapter> adapter); // Implemented by individual bluetooth extension functions, called - // automatically on the UI thread once |adapter| has been initialized. + // automatically once |adapter| has been initialized. virtual bool DoWork(scoped_refptr<device::BluetoothAdapter> adapter) = 0; DISALLOW_COPY_AND_ASSIGN(BluetoothExtensionFunction); }; } // namespace api + } // namespace extensions #endif // CHROME_BROWSER_EXTENSIONS_API_BLUETOOTH_BLUETOOTH_EXTENSION_FUNCTION_H_ diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_private_api.cc b/chrome/browser/extensions/api/bluetooth/bluetooth_private_api.cc index da1711e..482f7bf 100644 --- a/chrome/browser/extensions/api/bluetooth/bluetooth_private_api.cc +++ b/chrome/browser/extensions/api/bluetooth/bluetooth_private_api.cc @@ -41,13 +41,15 @@ void BluetoothPrivateAPI::Shutdown() { } void BluetoothPrivateAPI::OnListenerAdded(const EventListenerInfo& details) { - BluetoothAPI::Get(browser_context_)->event_router()->AddPairingDelegate( - details.extension_id); + BluetoothAPI::Get(browser_context_) + ->bluetooth_event_router() + ->AddPairingDelegate(details.extension_id); } void BluetoothPrivateAPI::OnListenerRemoved(const EventListenerInfo& details) { - BluetoothAPI::Get(browser_context_)->event_router()->RemovePairingDelegate( - details.extension_id); + BluetoothAPI::Get(browser_context_) + ->bluetooth_event_router() + ->RemovePairingDelegate(details.extension_id); } namespace api { @@ -220,7 +222,7 @@ bool BluetoothPrivateSetPairingResponseFunction::DoWork( const bt_private::SetPairingResponseOptions& options = params->options; BluetoothEventRouter* router = - BluetoothAPI::Get(browser_context())->event_router(); + BluetoothAPI::Get(browser_context())->bluetooth_event_router(); if (!router->GetPairingDelegate(extension_id())) { SetError(kPairingNotEnabled); SendResponse(false); diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_socket_event_dispatcher.cc b/chrome/browser/extensions/api/bluetooth/bluetooth_socket_event_dispatcher.cc deleted file mode 100644 index ddd413c..0000000 --- a/chrome/browser/extensions/api/bluetooth/bluetooth_socket_event_dispatcher.cc +++ /dev/null @@ -1,179 +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. - -#include "chrome/browser/extensions/api/bluetooth/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 "extensions/browser/event_router.h" -#include "extensions/browser/extension_system.h" -#include "net/base/io_buffer.h" -#include "net/base/net_errors.h" - -namespace { - -namespace bluetooth = extensions::api::bluetooth; -using extensions::BluetoothApiSocket; - -int kDefaultBufferSize = 4096; - -bluetooth::ReceiveError MapErrorReason(BluetoothApiSocket::ErrorReason value) { - switch (value) { - case BluetoothApiSocket::kDisconnected: - return bluetooth::RECEIVE_ERROR_DISCONNECTED; - case BluetoothApiSocket::kIOPending: - // kIOPending is not relevant to apps, as BluetoothSocketEventDispatcher - // handles this specific error. - // fallthrough - default: - return bluetooth::RECEIVE_ERROR_SYSTEM_ERROR; - } -} - -} // namespace - -namespace extensions { -namespace api { - -using content::BrowserThread; - -BluetoothSocketEventDispatcher::BluetoothSocketEventDispatcher( - content::BrowserContext* context, - scoped_refptr<SocketData> socket_data) - : thread_id_(BluetoothApiSocket::kThreadId), - browser_context_id_(context), - socket_data_(socket_data) {} - -BluetoothSocketEventDispatcher::~BluetoothSocketEventDispatcher() {} - -BluetoothSocketEventDispatcher::ReceiveParams::ReceiveParams() {} - -BluetoothSocketEventDispatcher::ReceiveParams::~ReceiveParams() {} - -void BluetoothSocketEventDispatcher::OnSocketResume( - const std::string& extension_id, - int socket_id) { - DCHECK(BrowserThread::CurrentlyOn(thread_id_)); - - ReceiveParams params; - params.extension_id = extension_id; - params.socket_id = socket_id; - StartReceive(params); -} - -void BluetoothSocketEventDispatcher::StartReceive(const ReceiveParams& params) { - DCHECK(BrowserThread::CurrentlyOn(thread_id_)); - - BluetoothApiSocket* socket = - socket_data_->Get(params.extension_id, params.socket_id); - if (!socket) { - // This can happen if the socket is closed while our callback is active. - return; - } - DCHECK(params.extension_id == socket->owner_extension_id()) - << "Socket has wrong owner."; - - // Don't start another read if the socket has been paused. - if (socket->paused()) - return; - - int buffer_size = socket->buffer_size(); - if (buffer_size <= 0) - buffer_size = kDefaultBufferSize; - socket->Receive( - buffer_size, - base::Bind( - &BluetoothSocketEventDispatcher::ReceiveCallback, this, params), - base::Bind( - &BluetoothSocketEventDispatcher::ReceiveErrorCallback, this, params)); -} - -void BluetoothSocketEventDispatcher::ReceiveCallback( - const ReceiveParams& params, - int bytes_read, - scoped_refptr<net::IOBuffer> io_buffer) { - DCHECK(BrowserThread::CurrentlyOn(thread_id_)); - - // Dispatch "onReceive" event. - bluetooth::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<Event> event( - new Event(bluetooth::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_, - FROM_HERE, - base::Bind(&BluetoothSocketEventDispatcher::StartReceive, this, params)); -} - -void BluetoothSocketEventDispatcher::ReceiveErrorCallback( - const ReceiveParams& params, - BluetoothApiSocket::ErrorReason error_reason, - const std::string& error) { - DCHECK(BrowserThread::CurrentlyOn(thread_id_)); - - if (error_reason == BluetoothApiSocket::kIOPending) { - // This happens when resuming a socket which already had an active "read" - // callback. We can safely ignore this error, as the application should not - // care. - return; - } - - // 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; - 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); - scoped_ptr<Event> event( - new Event(bluetooth::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); - if (socket) { - socket->set_paused(true); - } -} - -void BluetoothSocketEventDispatcher::PostEvent(const ReceiveParams& params, - scoped_ptr<Event> event) { - DCHECK(BrowserThread::CurrentlyOn(thread_id_)); - - BrowserThread::PostTask( - BrowserThread::UI, - FROM_HERE, - base::Bind(&BluetoothSocketEventDispatcher::DispatchEvent, - this, - params.extension_id, - base::Passed(event.Pass()))); -} - -void BluetoothSocketEventDispatcher::DispatchEvent( - const std::string& extension_id, - scoped_ptr<Event> event) { - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - - content::BrowserContext* context = - reinterpret_cast<content::BrowserContext*>(browser_context_id_); - if (!extensions::ExtensionsBrowserClient::Get()->IsValidContext(context)) - return; - - EventRouter* router = ExtensionSystem::Get(context)->event_router(); - if (router) - router->DispatchEventToExtension(extension_id, event.Pass()); -} - -} // namespace api -} // namespace extensions 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/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi index e724734..798b0c4 100644 --- a/chrome/chrome_browser_extensions.gypi +++ b/chrome/chrome_browser_extensions.gypi @@ -142,8 +142,6 @@ 'browser/extensions/api/bluetooth/bluetooth_api.h', 'browser/extensions/api/bluetooth/bluetooth_api_pairing_delegate.cc', 'browser/extensions/api/bluetooth/bluetooth_api_pairing_delegate.h', - 'browser/extensions/api/bluetooth/bluetooth_api_socket.h', - 'browser/extensions/api/bluetooth/bluetooth_api_socket.cc', 'browser/extensions/api/bluetooth/bluetooth_api_utils.cc', 'browser/extensions/api/bluetooth/bluetooth_api_utils.h', 'browser/extensions/api/bluetooth/bluetooth_event_router.cc', @@ -152,8 +150,6 @@ 'browser/extensions/api/bluetooth/bluetooth_extension_function.h', 'browser/extensions/api/bluetooth/bluetooth_private_api.cc', 'browser/extensions/api/bluetooth/bluetooth_private_api.h', - 'browser/extensions/api/bluetooth/bluetooth_socket_event_dispatcher.h', - 'browser/extensions/api/bluetooth/bluetooth_socket_event_dispatcher.cc', 'browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc', 'browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.h', 'browser/extensions/api/bookmarks/bookmark_api_constants.cc', diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index d0aa86b..4d2b718 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi @@ -847,7 +847,6 @@ 'browser/extensions/api/activity_log_private/activity_log_private_api_unittest.cc', 'browser/extensions/api/alarms/alarms_api_unittest.cc', 'browser/extensions/api/api_resource_manager_unittest.cc', - 'browser/extensions/api/bluetooth/bluetooth_api_unittest.cc', 'browser/extensions/api/bluetooth/bluetooth_event_router_unittest.cc', 'browser/extensions/api/bookmarks/bookmark_api_helpers_unittest.cc', 'browser/extensions/api/cast_channel/cast_socket_unittest.cc', diff --git a/chrome/common/extensions/api/bluetooth.idl b/chrome/common/extensions/api/bluetooth.idl index b42fce4..e66cda1 100644 --- a/chrome/common/extensions/api/bluetooth.idl +++ b/chrome/common/extensions/api/bluetooth.idl @@ -13,7 +13,6 @@ namespace bluetooth { joystick, gamepad, keyboard, mouse, tablet, keyboardMouseCombo}; - // Information about the state of the Bluetooth adapter. dictionary AdapterState { // The address of the adapter, in the format 'XX:XX:XX:XX:XX:XX'. DOMString address; @@ -31,7 +30,6 @@ namespace bluetooth { boolean discovering; }; - // Information about the state of a known Bluetooth device. dictionary Device { // The address of the device, in the format 'XX:XX:XX:XX:XX:XX'. DOMString address; @@ -69,7 +67,6 @@ namespace bluetooth { DOMString[]? uuids; }; - // Information about a Bluetooth profile. dictionary Profile { // Unique profile identifier, e.g. 00001401-0000-1000-8000-00805F9B23FB DOMString uuid; @@ -82,7 +79,7 @@ namespace bluetooth { long? channel; // The LS2CAP PSM number, used when the profile is to be exported to remote - // devices. + // deviecs. long? psm; // Specifies whether pairing (and encryption) is required to be able to @@ -104,49 +101,24 @@ namespace bluetooth { long? features; }; - // The socket properties specified in the $ref:update function. Each property - // is optional. If a property value is not specified, the existing value if - // preserved when calling $ref:update. - dictionary SocketProperties { - // Flag indicating whether the socket is left open when the event page of - // the application is unloaded (see <a - // href="http://developer.chrome.com/apps/app_lifecycle.html">Manage App - // Lifecycle</a>). The default value is <code>false.</code> When the - // application is loaded, any sockets previously opened with persistent=true - // can be fetched with $ref:getSockets. - boolean? persistent; - - // An application-defined string associated with the socket. - DOMString? name; + dictionary ServiceRecord { + // The name of the service. + DOMString name; - // The size of the buffer used to receive data. The default value is 4096. - long? bufferSize; + // The UUID of the service. + DOMString? uuid; }; dictionary Socket { - // The socket identifier. - long id; - // The remote Bluetooth device associated with this socket. Device device; - // The remote Bluetooth uuid associated with this socket. - DOMString uuid; - - // Flag indicating whether the socket is left open when the application is - // suspended (see <code>SocketProperties.persistent</code>). - boolean persistent; - - // Application-defined string associated with the socket. - DOMString? name; - - // The size of the buffer used to receive data. If no buffer size has been - // specified explictly, the field is not provided. - long? bufferSize; + // The remote Bluetooth profile associated with this socket. + Profile profile; - // Flag indicating whether a connected socket blocks its peer from sending - // more data (see <code>setPaused</code>). - boolean paused; + // An identifier for this socket that should be used with the + // read/write/disconnect methods. + long id; }; dictionary OutOfBandPairingData { @@ -182,8 +154,23 @@ namespace bluetooth { // Options for the disconnect function. dictionary DisconnectOptions { - // The socket identifier. - long socketId; + // The socket to disconnect. + Socket socket; + }; + + // Options for the read function. + dictionary ReadOptions { + // The socket to read from. + Socket socket; + }; + + // Options for the write function. + dictionary WriteOptions { + // The socket to write to. + Socket socket; + + // The data to write. + ArrayBuffer data; }; // Options for the setOutOfBandPairingData function. @@ -197,45 +184,17 @@ namespace bluetooth { OutOfBandPairingData? data; }; - // Callback from the <code>getSocket</code> method. - // |socket| : Object containing the socket information. - callback GetSocketCallback = void (Socket socket); - - // Callback from the <code>getSockets</code> method. - // |sockets| : Array of object containing socket information. - callback GetSocketsCallback = void (Socket[] sockets); - - // Data from an <code>onReceive</code> event. - dictionary ReceiveInfo { - // The socket identifier. - long socketId; - - // The data received, with a maximum size of <code>bufferSize</code>. - ArrayBuffer data; - }; - - enum ReceiveError { - // The connection was disconnected. - disconnected, - - // A system error occurred and the connection may be unrecoverable. - system_error - }; - - // Data from an <code>onReceiveError</code> event. - dictionary ReceiveErrorInfo { - // The socket identifier. - long socketId; - - // The error message. - DOMString errorMessage; - - // An error code indicating what went wrong. - ReceiveError error; - }; - // These functions all report failures via chrome.runtime.lastError. interface Functions { + // Registers the JavaScript application as an implementation for the given + // Profile; if a channel or PSM is specified, the profile will be exported + // in the host's SDP and GATT tables and advertised to other devices. + static void addProfile(Profile profile, ResultCallback callback); + + // Unregisters the JavaScript application as an implementation for the given + // Profile; only the uuid field of the Profile object is used. + static void removeProfile(Profile profile, ResultCallback callback); + // Get information about the Bluetooth adapter. // |callback| : Called with an AdapterState object describing the adapter // state. @@ -251,62 +210,31 @@ namespace bluetooth { // |callback| : Called with the Device object describing the device. static void getDevice(DOMString deviceAddress, DeviceCallback callback); - // Registers the JavaScript application as an implementation for the given - // Profile; if a channel or PSM is specified, the profile will be exported - // in the host's SDP and GATT tables and advertised to other devices. - static void addProfile(Profile profile, ResultCallback callback); - - // Unregisters the JavaScript application as an implementation for the given - // Profile; only the uuid field of the Profile object is used. - static void removeProfile(Profile profile, ResultCallback callback); - // Connect to a service on a device. // |options| : The options for the connection. // |callback| : Called to indicate success or failure. static void connect(ConnectOptions options, ResultCallback callback); - // Closes a Bluetooth connection. + // Close a Bluetooth connection. // |options| : The options for this function. // |callback| : Called to indicate success or failure. static void disconnect(DisconnectOptions options, optional ResultCallback callback); - // Sends data to a Bluetooth connection. - // |socketId| : The socket identifier. - // |data| : The data to send. - // |callback| : Called with the number of bytes sent. - static void send(long socketId, - ArrayBuffer data, - optional SizeCallback callback); - - // Updates the socket properties. - // |socketId| : The socket identifier. - // |properties| : The properties to update. - // |callback| : Called when the properties are updated. - static void updateSocket(long socketId, - SocketProperties properties, - optional ResultCallback callback); - - // Enables or disables the application from receiving messages from its - // peer. The default value is <code>false</code>. Pausing a socket is - // typically used by an application to throttle data sent by its peer. When - // a socket is paused, no $ref:onReceive event is raised. When a socket is - // connected and un-paused, $ref:onReceive events are raised again when - // messages are received. - static void setSocketPaused(long socketId, - boolean paused, - optional ResultCallback callback); - - // Retrieves the state of the given socket. - // |socketId| : The socket identifier. - // |callback| : Called when the socket state is available. - static void getSocket(long socketId, - GetSocketCallback callback); - - // Retrieves the list of currently opened sockets owned by the application. - // |callback| : Called when the list of sockets is available. - static void getSockets(GetSocketsCallback callback); + // Read data from a Bluetooth connection. The |callback| will be called + // with the current data in the buffer even if it is empty. This function + // should be polled to read incoming data. + // |options| : The options for this function. + // |callback| : Called with the data read from the socket buffer. + static void read(ReadOptions options, + DataCallback callback); + + // Write data to a Bluetooth connection. + // |options| : The options for this function. + // |callback| : Called with the number of bytes written. + static void write(WriteOptions options, + optional SizeCallback callback); // Get the local Out of Band Pairing data. // |callback| : Called with the data. @@ -357,16 +285,5 @@ namespace bluetooth { // Fired when a connection has been made for a registered profile. // |socket| : The socket for the connection. static void onConnection(Socket socket); - - // Event raised when data has been received for a given socket. - // |info| : The event data. - static void onReceive(ReceiveInfo info); - - // Event raised when a network error occured while the runtime was waiting - // for data on the socket. Once this event is raised, the socket is set to - // <code>paused</code> and no more <code>onReceive</code> events are raised - // for this socket. - // |info| : The event data. - static void onReceiveError(ReceiveErrorInfo info); }; }; diff --git a/chrome/test/data/extensions/api_test/bluetooth/on_connection/runtest.js b/chrome/test/data/extensions/api_test/bluetooth/on_connection/runtest.js index d532544..1a05349 100644 --- a/chrome/test/data/extensions/api_test/bluetooth/on_connection/runtest.js +++ b/chrome/test/data/extensions/api_test/bluetooth/on_connection/runtest.js @@ -18,8 +18,8 @@ chrome.bluetooth.onConnection.addListener( function(socket) { deviceName = socket.device.name; deviceAddress = socket.device.address; - profileUuid = socket.uuid; - chrome.bluetooth.disconnect({'socketId': socket.id}); + profileUuid = socket.profile.uuid; + chrome.bluetooth.disconnect({'socket': socket}); }); chrome.test.sendMessage('ready', diff --git a/device/bluetooth/DEPS b/device/bluetooth/DEPS index 93c11ef..7f93e42 100644 --- a/device/bluetooth/DEPS +++ b/device/bluetooth/DEPS @@ -3,7 +3,6 @@ include_rules = [ "+dbus", "+grit", "+net/base", - "+net/socket", "+ui/base/l10n", "+third_party/cros_system_api/dbus", "+third_party/libxml/chromium", diff --git a/device/bluetooth/OWNERS b/device/bluetooth/OWNERS index 8b0555a..7bf8537 100644 --- a/device/bluetooth/OWNERS +++ b/device/bluetooth/OWNERS @@ -1,5 +1,2 @@ keybuk@chromium.org armansito@chromium.org - -per-file *_mac*=rpaquay@chromium.org -per-file *_win*=rpaquay@chromium.org diff --git a/device/bluetooth/bluetooth.gyp b/device/bluetooth/bluetooth.gyp index f819f91..c3f8475 100644 --- a/device/bluetooth/bluetooth.gyp +++ b/device/bluetooth/bluetooth.gyp @@ -66,14 +66,11 @@ 'bluetooth_service_record_mac.mm', 'bluetooth_service_record_win.cc', 'bluetooth_service_record_win.h', - 'bluetooth_socket.cc', 'bluetooth_socket.h', 'bluetooth_socket_chromeos.cc', 'bluetooth_socket_chromeos.h', 'bluetooth_socket_mac.h', 'bluetooth_socket_mac.mm', - 'bluetooth_socket_thread_win.cc', - 'bluetooth_socket_thread_win.h', 'bluetooth_socket_win.cc', 'bluetooth_socket_win.h', 'bluetooth_task_manager_win.cc', diff --git a/device/bluetooth/bluetooth_adapter.h b/device/bluetooth/bluetooth_adapter.h index f46a477..e713ff4 100644 --- a/device/bluetooth/bluetooth_adapter.h +++ b/device/bluetooth/bluetooth_adapter.h @@ -35,15 +35,15 @@ class BluetoothAdapter : public base::RefCounted<BluetoothAdapter> { public: virtual ~Observer() {} - // Called when the presence of the adapter |adapter| changes, when |present| - // is true the adapter is now present, false means the adapter has been - // removed from the system. + // Called when the presence of the adapter |adapter| changes, when + // |present| is true the adapter is now present, false means the adapter + // has been removed from the system. virtual void AdapterPresentChanged(BluetoothAdapter* adapter, bool present) {} - // Called when the radio power state of the adapter |adapter| changes, when - // |powered| is true the adapter radio is powered, false means the adapter - // radio is off. + // Called when the radio power state of the adapter |adapter| changes, + // when |powered| is true the adapter radio is powered, false means the + // adapter radio is off. virtual void AdapterPoweredChanged(BluetoothAdapter* adapter, bool powered) {} @@ -53,9 +53,9 @@ class BluetoothAdapter : public base::RefCounted<BluetoothAdapter> { virtual void AdapterDiscoverableChanged(BluetoothAdapter* adapter, bool discoverable) {} - // Called when the discovering state of the adapter |adapter| changes, when - // |discovering| is true the adapter is seeking new devices, false means it - // is not. + // Called when the discovering state of the adapter |adapter| changes, + // when |discovering| is true the adapter is seeking new devices, false + // means it is not. virtual void AdapterDiscoveringChanged(BluetoothAdapter* adapter, bool discovering) {} @@ -78,8 +78,8 @@ class BluetoothAdapter : public base::RefCounted<BluetoothAdapter> { BluetoothDevice* device) {} }; - // The ErrorCallback is used for methods that can fail in which case it is - // called, in the success case the callback is simply not called. + // The ErrorCallback is used for methods that can fail in which case it + // is called, in the success case the callback is simply not called. typedef base::Closure ErrorCallback; // The BluetoothOutOfBandPairingDataCallback is used to return @@ -87,9 +87,9 @@ class BluetoothAdapter : public base::RefCounted<BluetoothAdapter> { typedef base::Callback<void(const BluetoothOutOfBandPairingData& data)> BluetoothOutOfBandPairingDataCallback; - // Adds and removes observers for events on this bluetooth adapter, if - // monitoring multiple adapters check the |adapter| parameter of observer - // methods to determine which adapter is issuing the event. + // Adds and removes observers for events on this bluetooth adapter, + // if monitoring multiple adapters check the |adapter| parameter of + // observer methods to determine which adapter is issuing the event. virtual void AddObserver(BluetoothAdapter::Observer* observer) = 0; virtual void RemoveObserver( BluetoothAdapter::Observer* observer) = 0; @@ -110,9 +110,9 @@ class BluetoothAdapter : public base::RefCounted<BluetoothAdapter> { // Indicates whether the adapter is initialized and ready to use. virtual bool IsInitialized() const = 0; - // Indicates whether the adapter is actually present on the system, for the - // default adapter this indicates whether any adapter is present. An adapter - // is only considered present if the address has been obtained. + // Indicates whether the adapter is actually present on the system, for + // the default adapter this indicates whether any adapter is present. An + // adapter is only considered present if the address has been obtained. virtual bool IsPresent() const = 0; // Indicates whether the adapter radio is powered. @@ -161,16 +161,16 @@ class BluetoothAdapter : public base::RefCounted<BluetoothAdapter> { virtual void StartDiscoverySession(const DiscoverySessionCallback& callback, const ErrorCallback& error_callback); - // Requests the list of devices from the adapter, all are returned including - // those currently connected and those paired. Use the returned device - // pointers to determine which they are. + // Requests the list of devices from the adapter, all are returned + // including those currently connected and those paired. Use the + // returned device pointers to determine which they are. typedef std::vector<BluetoothDevice*> DeviceList; virtual DeviceList GetDevices(); typedef std::vector<const BluetoothDevice*> ConstDeviceList; virtual ConstDeviceList GetDevices() const; - // Returns a pointer to the device with the given address |address| or NULL if - // no such device is known. + // Returns a pointer to the device with the given address |address| or + // NULL if no such device is known. virtual BluetoothDevice* GetDevice(const std::string& address); virtual const BluetoothDevice* GetDevice( const std::string& address) const; @@ -269,9 +269,9 @@ class BluetoothAdapter : public base::RefCounted<BluetoothAdapter> { BluetoothDiscoverySession* discovery_session); // Devices paired with, connected to, discovered by, or visible to the - // adapter. The key is the Bluetooth address of the device and the value is - // the BluetoothDevice object whose lifetime is managed by the adapter - // instance. + // adapter. The key is the Bluetooth address of the device and the value + // is the BluetoothDevice object whose lifetime is managed by the + // adapter instance. typedef std::map<const std::string, BluetoothDevice*> DevicesMap; DevicesMap devices_; diff --git a/device/bluetooth/bluetooth_adapter_win.cc b/device/bluetooth/bluetooth_adapter_win.cc index 8f92be8..bf0a9b7 100644 --- a/device/bluetooth/bluetooth_adapter_win.cc +++ b/device/bluetooth/bluetooth_adapter_win.cc @@ -14,7 +14,6 @@ #include "base/stl_util.h" #include "base/thread_task_runner_handle.h" #include "device/bluetooth/bluetooth_device_win.h" -#include "device/bluetooth/bluetooth_socket_thread_win.h" #include "device/bluetooth/bluetooth_task_manager_win.h" namespace device { @@ -186,8 +185,7 @@ void BluetoothAdapterWin::DevicesDiscovered( ++iter) { if (discovered_devices_.find((*iter)->address) == discovered_devices_.end()) { - BluetoothDeviceWin device_win( - **iter, ui_task_runner_, socket_thread_, NULL, net::NetLog::Source()); + BluetoothDeviceWin device_win(**iter); FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, DeviceAdded(this, &device_win)); discovered_devices_.insert((*iter)->address); @@ -202,8 +200,7 @@ void BluetoothAdapterWin::DevicesUpdated( devices.begin(); iter != devices.end(); ++iter) { - devices_[(*iter)->address] = new BluetoothDeviceWin( - **iter, ui_task_runner_, socket_thread_, NULL, net::NetLog::Source()); + devices_[(*iter)->address] = new BluetoothDeviceWin(**iter); } } @@ -235,7 +232,6 @@ void BluetoothAdapterWin::RemoveDiscoverySession( void BluetoothAdapterWin::Init() { ui_task_runner_ = base::ThreadTaskRunnerHandle::Get(); - socket_thread_ = BluetoothSocketThreadWin::Get(); task_manager_ = new BluetoothTaskManagerWin(ui_task_runner_); task_manager_->AddObserver(this); diff --git a/device/bluetooth/bluetooth_adapter_win.h b/device/bluetooth/bluetooth_adapter_win.h index 2c12fda..6e7382f 100644 --- a/device/bluetooth/bluetooth_adapter_win.h +++ b/device/bluetooth/bluetooth_adapter_win.h @@ -18,8 +18,9 @@ #include "device/bluetooth/bluetooth_task_manager_win.h" namespace base { + class SequencedTaskRunner; -class Thread; + } // namespace base namespace device { @@ -27,7 +28,6 @@ namespace device { class BluetoothAdapterFactory; class BluetoothAdapterWinTest; class BluetoothDevice; -class BluetoothSocketThreadWin; class BluetoothAdapterWin : public BluetoothAdapter, public BluetoothTaskManagerWin::Observer { @@ -121,7 +121,6 @@ class BluetoothAdapterWin : public BluetoothAdapter, size_t num_discovery_listeners_; scoped_refptr<base::SequencedTaskRunner> ui_task_runner_; - scoped_refptr<BluetoothSocketThreadWin> socket_thread_; scoped_refptr<BluetoothTaskManagerWin> task_manager_; base::ThreadChecker thread_checker_; diff --git a/device/bluetooth/bluetooth_device.h b/device/bluetooth/bluetooth_device.h index bfe7987..cfe8d9a 100644 --- a/device/bluetooth/bluetooth_device.h +++ b/device/bluetooth/bluetooth_device.h @@ -12,7 +12,6 @@ #include "base/memory/scoped_vector.h" #include "base/strings/string16.h" #include "device/bluetooth/bluetooth_uuid.h" -#include "net/base/net_log.h" namespace device { @@ -336,12 +335,9 @@ class BluetoothDevice { // identified by |profile|, on success the profile's connection callback // will be called as well as |callback|; on failure |error_callback| will be // called. - typedef base::Callback<void(const std::string&)> - ConnectToProfileErrorCallback; - virtual void ConnectToProfile( - BluetoothProfile* profile, - const base::Closure& callback, - const ConnectToProfileErrorCallback& error_callback) = 0; + virtual void ConnectToProfile(BluetoothProfile* profile, + const base::Closure& callback, + const ErrorCallback& error_callback) = 0; // Sets the Out Of Band pairing data for this device to |data|. Exactly one // of |callback| or |error_callback| will be run. diff --git a/device/bluetooth/bluetooth_device_chromeos.cc b/device/bluetooth/bluetooth_device_chromeos.cc index 7d37d93..f42f3ee 100644 --- a/device/bluetooth/bluetooth_device_chromeos.cc +++ b/device/bluetooth/bluetooth_device_chromeos.cc @@ -361,7 +361,7 @@ void BluetoothDeviceChromeOS::ConnectToService( void BluetoothDeviceChromeOS::ConnectToProfile( device::BluetoothProfile* profile, const base::Closure& callback, - const ConnectToProfileErrorCallback& error_callback) { + const ErrorCallback& error_callback) { BluetoothProfileChromeOS* profile_chromeos = static_cast<BluetoothProfileChromeOS*>(profile); VLOG(1) << object_path_.value() << ": Connecting profile: " @@ -581,7 +581,7 @@ void BluetoothDeviceChromeOS::OnConnectProfile( void BluetoothDeviceChromeOS::OnConnectProfileError( device::BluetoothProfile* profile, - const ConnectToProfileErrorCallback& error_callback, + const ErrorCallback& error_callback, const std::string& error_name, const std::string& error_message) { BluetoothProfileChromeOS* profile_chromeos = @@ -589,7 +589,7 @@ void BluetoothDeviceChromeOS::OnConnectProfileError( VLOG(1) << object_path_.value() << ": Profile connection failed: " << profile_chromeos->uuid().canonical_value() << ": " << error_name << ": " << error_message; - error_callback.Run(error_message); + error_callback.Run(); } } // namespace chromeos diff --git a/device/bluetooth/bluetooth_device_chromeos.h b/device/bluetooth/bluetooth_device_chromeos.h index 0dc5133..98475f2 100644 --- a/device/bluetooth/bluetooth_device_chromeos.h +++ b/device/bluetooth/bluetooth_device_chromeos.h @@ -57,7 +57,7 @@ class BluetoothDeviceChromeOS virtual void ConnectToProfile( device::BluetoothProfile* profile, const base::Closure& callback, - const ConnectToProfileErrorCallback& error_callback) OVERRIDE; + const ErrorCallback& error_callback) OVERRIDE; virtual void SetOutOfBandPairingData( const device::BluetoothOutOfBandPairingData& data, const base::Closure& callback, @@ -140,11 +140,10 @@ class BluetoothDeviceChromeOS // connect a peofile. void OnConnectProfile(device::BluetoothProfile* profile, const base::Closure& callback); - void OnConnectProfileError( - device::BluetoothProfile* profile, - const ConnectToProfileErrorCallback& error_callback, - const std::string& error_name, - const std::string& error_message); + void OnConnectProfileError(device::BluetoothProfile* profile, + const ErrorCallback& error_callback, + const std::string& error_name, + const std::string& error_message); // Returns the object path of the device; used by BluetoothAdapterChromeOS const dbus::ObjectPath& object_path() const { return object_path_; } diff --git a/device/bluetooth/bluetooth_device_mac.h b/device/bluetooth/bluetooth_device_mac.h index 26b1b8f..f610f24 100644 --- a/device/bluetooth/bluetooth_device_mac.h +++ b/device/bluetooth/bluetooth_device_mac.h @@ -55,9 +55,9 @@ class BluetoothDeviceMac : public BluetoothDevice { const device::BluetoothUUID& service_uuid, const SocketCallback& callback) OVERRIDE; virtual void ConnectToProfile( - BluetoothProfile* profile, + device::BluetoothProfile* profile, const base::Closure& callback, - const ConnectToProfileErrorCallback& error_callback) OVERRIDE; + const ErrorCallback& error_callback) OVERRIDE; virtual void SetOutOfBandPairingData( const BluetoothOutOfBandPairingData& data, const base::Closure& callback, diff --git a/device/bluetooth/bluetooth_device_mac.mm b/device/bluetooth/bluetooth_device_mac.mm index 00ce0cf..6fbad23 100644 --- a/device/bluetooth/bluetooth_device_mac.mm +++ b/device/bluetooth/bluetooth_device_mac.mm @@ -36,8 +36,6 @@ namespace { -const char kFailedToConnect[] = "Connection failed"; - // Converts |uuid| to a IOBluetoothSDPUUID instance. // // |uuid| must be in the format of XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX. @@ -196,13 +194,13 @@ void BluetoothDeviceMac::ConnectToService( } void BluetoothDeviceMac::ConnectToProfile( - BluetoothProfile* profile, + device::BluetoothProfile* profile, const base::Closure& callback, - const ConnectToProfileErrorCallback& error_callback) { + const ErrorCallback& error_callback) { if (static_cast<BluetoothProfileMac*>(profile)->Connect(device_)) callback.Run(); else - error_callback.Run(kFailedToConnect); + error_callback.Run(); } void BluetoothDeviceMac::SetOutOfBandPairingData( diff --git a/device/bluetooth/bluetooth_device_win.cc b/device/bluetooth/bluetooth_device_win.cc index 1834096..312f0e5 100644 --- a/device/bluetooth/bluetooth_device_win.cc +++ b/device/bluetooth/bluetooth_device_win.cc @@ -9,12 +9,10 @@ #include "base/basictypes.h" #include "base/logging.h" #include "base/memory/scoped_vector.h" -#include "base/sequenced_task_runner.h" #include "base/strings/stringprintf.h" #include "device/bluetooth/bluetooth_out_of_band_pairing_data.h" #include "device/bluetooth/bluetooth_profile_win.h" #include "device/bluetooth/bluetooth_service_record_win.h" -#include "device/bluetooth/bluetooth_socket_thread_win.h" #include "device/bluetooth/bluetooth_socket_win.h" #include "device/bluetooth/bluetooth_task_manager_win.h" @@ -27,16 +25,8 @@ const int kSdpBytesBufferSize = 1024; namespace device { BluetoothDeviceWin::BluetoothDeviceWin( - const BluetoothTaskManagerWin::DeviceState& state, - scoped_refptr<base::SequencedTaskRunner> ui_task_runner, - scoped_refptr<BluetoothSocketThreadWin> socket_thread, - net::NetLog* net_log, - const net::NetLog::Source& net_log_source) - : BluetoothDevice(), - ui_task_runner_(ui_task_runner), - socket_thread_(socket_thread), - net_log_(net_log), - net_log_source_(net_log_source) { + const BluetoothTaskManagerWin::DeviceState& state) + : BluetoothDevice() { name_ = state.name; address_ = state.address; bluetooth_class_ = state.bluetooth_class; @@ -173,21 +163,29 @@ void BluetoothDeviceWin::Forget(const ErrorCallback& error_callback) { void BluetoothDeviceWin::ConnectToService( const device::BluetoothUUID& service_uuid, const SocketCallback& callback) { - NOTIMPLEMENTED(); + for (ServiceRecordList::const_iterator iter = service_record_list_.begin(); + iter != service_record_list_.end(); + ++iter) { + if ((*iter)->uuid() == service_uuid) { + // If multiple service records are found, use the first one that works. + scoped_refptr<BluetoothSocket> socket( + BluetoothSocketWin::CreateBluetoothSocket(**iter)); + if (socket.get() != NULL) { + callback.Run(socket); + return; + } + } + } } void BluetoothDeviceWin::ConnectToProfile( device::BluetoothProfile* profile, const base::Closure& callback, - const ConnectToProfileErrorCallback& error_callback) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); - static_cast<BluetoothProfileWin*>(profile)->Connect(this, - ui_task_runner_, - socket_thread_, - net_log_, - net_log_source_, - callback, - error_callback); + const ErrorCallback& error_callback) { + if (static_cast<BluetoothProfileWin*>(profile)->Connect(this)) + callback.Run(); + else + error_callback.Run(); } void BluetoothDeviceWin::SetOutOfBandPairingData( diff --git a/device/bluetooth/bluetooth_device_win.h b/device/bluetooth/bluetooth_device_win.h index acbb350..0ba0796 100644 --- a/device/bluetooth/bluetooth_device_win.h +++ b/device/bluetooth/bluetooth_device_win.h @@ -16,16 +16,11 @@ namespace device { class BluetoothAdapterWin; class BluetoothServiceRecord; -class BluetoothSocketThreadWin; class BluetoothDeviceWin : public BluetoothDevice { public: explicit BluetoothDeviceWin( - const BluetoothTaskManagerWin::DeviceState& state, - scoped_refptr<base::SequencedTaskRunner> ui_task_runner, - scoped_refptr<BluetoothSocketThreadWin> socket_thread, - net::NetLog* net_log, - const net::NetLog::Source& net_log_source); + const BluetoothTaskManagerWin::DeviceState& state); virtual ~BluetoothDeviceWin(); // BluetoothDevice override @@ -62,7 +57,7 @@ class BluetoothDeviceWin : public BluetoothDevice { virtual void ConnectToProfile( device::BluetoothProfile* profile, const base::Closure& callback, - const ConnectToProfileErrorCallback& error_callback) OVERRIDE; + const ErrorCallback& error_callback) OVERRIDE; virtual void SetOutOfBandPairingData( const BluetoothOutOfBandPairingData& data, const base::Closure& callback, @@ -87,11 +82,6 @@ class BluetoothDeviceWin : public BluetoothDevice { // discovery. void SetVisible(bool visible); - scoped_refptr<base::SequencedTaskRunner> ui_task_runner_; - scoped_refptr<BluetoothSocketThreadWin> socket_thread_; - net::NetLog* net_log_; - net::NetLog::Source net_log_source_; - // The Bluetooth class of the device, a bitmask that may be decoded using // https://www.bluetooth.org/Technical/AssignedNumbers/baseband.htm uint32 bluetooth_class_; diff --git a/device/bluetooth/bluetooth_device_win_unittest.cc b/device/bluetooth/bluetooth_device_win_unittest.cc index e784863..45a4a81 100644 --- a/device/bluetooth/bluetooth_device_win_unittest.cc +++ b/device/bluetooth/bluetooth_device_win_unittest.cc @@ -6,12 +6,9 @@ #include "base/bind.h" #include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" -#include "base/sequenced_task_runner.h" #include "base/strings/string_number_conversions.h" -#include "base/test/test_simple_task_runner.h" #include "device/bluetooth/bluetooth_device_win.h" #include "device/bluetooth/bluetooth_service_record.h" -#include "device/bluetooth/bluetooth_socket_thread_win.h" #include "device/bluetooth/bluetooth_task_manager_win.h" #include "device/bluetooth/bluetooth_uuid.h" #include "testing/gtest/include/gtest/gtest.h" @@ -63,23 +60,11 @@ class BluetoothDeviceWinTest : public testing::Test { base::HexStringToBytes(kTestVideoSdpBytes, &video_state->sdp_bytes); device_state.service_record_states.push_back(video_state); - scoped_refptr<base::SequencedTaskRunner> ui_task_runner( - new base::TestSimpleTaskRunner()); - scoped_refptr<BluetoothSocketThreadWin> socket_thread( - BluetoothSocketThreadWin::Get()); - device_.reset(new BluetoothDeviceWin(device_state, - ui_task_runner, - socket_thread, - NULL, - net::NetLog::Source())); + device_.reset(new BluetoothDeviceWin(device_state)); // Add empty device. device_state.service_record_states.clear(); - empty_device_.reset(new BluetoothDeviceWin(device_state, - ui_task_runner, - socket_thread, - NULL, - net::NetLog::Source())); + empty_device_.reset(new BluetoothDeviceWin(device_state)); } protected: diff --git a/device/bluetooth/bluetooth_profile_chromeos_unittest.cc b/device/bluetooth/bluetooth_profile_chromeos_unittest.cc index 277e8b3..24061b7 100644 --- a/device/bluetooth/bluetooth_profile_chromeos_unittest.cc +++ b/device/bluetooth/bluetooth_profile_chromeos_unittest.cc @@ -92,10 +92,6 @@ class BluetoothProfileChromeOSTest : public testing::Test { message_loop_.Quit(); } - void ConnectToProfileErrorCallback(const std::string error) { - ErrorCallback(); - } - void ProfileCallback(BluetoothProfile* profile) { ++profile_callback_count_; last_profile_ = profile; @@ -161,7 +157,7 @@ TEST_F(BluetoothProfileChromeOSTest, L2capEndToEnd) { profile, base::Bind(&BluetoothProfileChromeOSTest::Callback, base::Unretained(this)), - base::Bind(&BluetoothProfileChromeOSTest::ConnectToProfileErrorCallback, + base::Bind(&BluetoothProfileChromeOSTest::ErrorCallback, base::Unretained(this))); message_loop_.Run(); @@ -287,7 +283,7 @@ TEST_F(BluetoothProfileChromeOSTest, RfcommEndToEnd) { profile, base::Bind(&BluetoothProfileChromeOSTest::Callback, base::Unretained(this)), - base::Bind(&BluetoothProfileChromeOSTest::ConnectToProfileErrorCallback, + base::Bind(&BluetoothProfileChromeOSTest::ErrorCallback, base::Unretained(this))); message_loop_.Run(); diff --git a/device/bluetooth/bluetooth_profile_win.cc b/device/bluetooth/bluetooth_profile_win.cc index 79848ca..707afeb 100644 --- a/device/bluetooth/bluetooth_profile_win.cc +++ b/device/bluetooth/bluetooth_profile_win.cc @@ -4,66 +4,11 @@ #include "device/bluetooth/bluetooth_profile_win.h" -#include "base/bind.h" #include "base/memory/ref_counted.h" -#include "base/sequenced_task_runner.h" -#include "device/bluetooth/bluetooth_adapter_factory.h" #include "device/bluetooth/bluetooth_device_win.h" #include "device/bluetooth/bluetooth_service_record.h" -#include "device/bluetooth/bluetooth_socket_thread_win.h" #include "device/bluetooth/bluetooth_socket_win.h" -namespace { - -using device::BluetoothAdapter; -using device::BluetoothDevice; -using device::BluetoothProfileWin; -using device::BluetoothSocket; -using device::BluetoothSocketWin; - -const char kNoConnectionCallback[] = "Connection callback not set"; -const char kProfileNotFound[] = "Profile not found"; - -void OnConnectSuccessUIWithAdapter( - scoped_refptr<base::SequencedTaskRunner> ui_task_runner, - const base::Closure& callback, - const BluetoothProfileWin::ConnectionCallback& connection_callback, - const std::string& device_address, - scoped_refptr<BluetoothSocketWin> socket, - scoped_refptr<BluetoothAdapter> adapter) { - DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); - const BluetoothDevice* device = adapter->GetDevice(device_address); - if (device) { - connection_callback.Run(device, socket); - callback.Run(); - } -} - -void OnConnectSuccessUI( - scoped_refptr<base::SequencedTaskRunner> ui_task_runner, - const base::Closure& callback, - const BluetoothProfileWin::ConnectionCallback& connection_callback, - const std::string& device_address, - scoped_refptr<BluetoothSocketWin> socket) { - DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); - device::BluetoothAdapterFactory::GetAdapter( - base::Bind(&OnConnectSuccessUIWithAdapter, - ui_task_runner, - callback, - connection_callback, - device_address, - socket)); -} - -void OnConnectErrorUI(scoped_refptr<base::SequencedTaskRunner> ui_task_runner, - const BluetoothProfileWin::ErrorCallback& error_callback, - const std::string& error) { - DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); - error_callback.Run(error); -} - -} // namespace - namespace device { BluetoothProfileWin::BluetoothProfileWin(const BluetoothUUID& uuid, @@ -83,37 +28,20 @@ void BluetoothProfileWin::SetConnectionCallback( connection_callback_ = callback; } -void BluetoothProfileWin::Connect( - const BluetoothDeviceWin* device, - scoped_refptr<base::SequencedTaskRunner> ui_task_runner, - scoped_refptr<BluetoothSocketThreadWin> socket_thread, - net::NetLog* net_log, - const net::NetLog::Source& source, - const base::Closure& success_callback, - const ErrorCallback& error_callback) { - DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); - if (connection_callback_.is_null()) { - error_callback.Run(kNoConnectionCallback); - return; - } +bool BluetoothProfileWin::Connect(const BluetoothDeviceWin* device) { + if (connection_callback_.is_null()) + return false; const BluetoothServiceRecord* record = device->GetServiceRecord(uuid_); - if (!record) { - error_callback.Run(kProfileNotFound); - return; + if (record) { + scoped_refptr<BluetoothSocket> socket( + BluetoothSocketWin::CreateBluetoothSocket(*record)); + if (socket.get() != NULL) { + connection_callback_.Run(device, socket); + return true; + } } - - scoped_refptr<BluetoothSocketWin> socket( - BluetoothSocketWin::CreateBluetoothSocket( - *record, ui_task_runner, socket_thread, net_log, source)); - - socket->Connect(base::Bind(&OnConnectSuccessUI, - ui_task_runner, - success_callback, - connection_callback_, - device->GetAddress(), - socket), - error_callback); + return false; } } // namespace device diff --git a/device/bluetooth/bluetooth_profile_win.h b/device/bluetooth/bluetooth_profile_win.h index e235bd2..b7b5333 100644 --- a/device/bluetooth/bluetooth_profile_win.h +++ b/device/bluetooth/bluetooth_profile_win.h @@ -9,12 +9,10 @@ #include "device/bluetooth/bluetooth_profile.h" #include "device/bluetooth/bluetooth_uuid.h" -#include "net/base/net_log.h" namespace device { class BluetoothDeviceWin; -class BluetoothSocketThreadWin; class BluetoothProfileWin : public BluetoothProfile { public: @@ -23,15 +21,7 @@ class BluetoothProfileWin : public BluetoothProfile { virtual void SetConnectionCallback( const ConnectionCallback& callback) OVERRIDE; - typedef base::Callback<void(const std::string&)> ErrorCallback; - - void Connect(const BluetoothDeviceWin* device, - scoped_refptr<base::SequencedTaskRunner> ui_task_runner, - scoped_refptr<BluetoothSocketThreadWin> socket_thread, - net::NetLog* net_log, - const net::NetLog::Source& source, - const base::Closure& callback, - const ErrorCallback& error_callback); + bool Connect(const BluetoothDeviceWin* device); private: friend BluetoothProfile; @@ -42,8 +32,6 @@ class BluetoothProfileWin : public BluetoothProfile { const BluetoothUUID uuid_; const std::string name_; ConnectionCallback connection_callback_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothProfileWin); }; } // namespace device diff --git a/device/bluetooth/bluetooth_socket.cc b/device/bluetooth/bluetooth_socket.cc deleted file mode 100644 index 26981ab..0000000 --- a/device/bluetooth/bluetooth_socket.cc +++ /dev/null @@ -1,11 +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. - -#include "device/bluetooth/bluetooth_socket.h" - -namespace device { - -BluetoothSocket::~BluetoothSocket() {} - -} // namespace device diff --git a/device/bluetooth/bluetooth_socket.h b/device/bluetooth/bluetooth_socket.h index 8aaa086..6ae349e 100644 --- a/device/bluetooth/bluetooth_socket.h +++ b/device/bluetooth/bluetooth_socket.h @@ -7,11 +7,13 @@ #include <string> -#include "base/callback.h" #include "base/memory/ref_counted.h" namespace net { -class IOBuffer; + +class DrainableIOBuffer; +class GrowableIOBuffer; + } // namespace net namespace device { @@ -19,51 +21,24 @@ namespace device { // BluetoothSocket represents a socket to a specific service on a // BluetoothDevice. BluetoothSocket objects are ref counted and may outlive // both the BluetoothDevice and BluetoothAdapter that were involved in their -// creation. In terms of threading, platform specific implementations may -// differ slightly, but platform independent consumers must guarantee calling -// various instances methods on the same thread as the thread used at -// construction time -- platform specific implementation are resonsible for -// marshalling calls to a different thread if required. -class BluetoothSocket : public base::RefCountedThreadSafe<BluetoothSocket> { +// creation. +class BluetoothSocket : public base::RefCounted<BluetoothSocket> { public: - enum ErrorReason { kSystemError, 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; - - // Destroys resources associated with the socket. After calling this method, - // it is illegal to call any method on this socket instance (except for the - // desctrutor via Release). - virtual void Close() = 0; - - // Gracefully disconnects the socket and calls |callback| upon completion. - // There is no failure case, as this is a best effort operation. - virtual void Disconnect(const base::Closure& callback) = 0; + // Receives data from the socket and stores it in |buffer|. It returns whether + // the reception has been successful. If it fails, the caller can get the + // error message through |GetLastErrorMessage()|. + virtual bool Receive(net::GrowableIOBuffer* buffer) = 0; - // Receives data from the socket and calls |success_callback| when data is - // available. |count| is maximum amount of bytes received. If an error occurs, - // calls |error_callback| with a reason and an error message. - virtual void Receive( - int count, - const ReceiveCompletionCallback& success_callback, - const ReceiveErrorCompletionCallback& error_callback) = 0; + // Sends |buffer| to the socket. It returns whether the sending has been + // successful. If it fails, the caller can get the error message through + // |GetLastErrorMessage()|. + virtual bool Send(net::DrainableIOBuffer* buffer) = 0; - // Sends |buffer| to the socket and calls |success_callback| when data has - // been successfully sent. |buffer_size| is the number of bytes contained in - // |buffer|. If an error occurs, calls |error_callback| with an error message. - virtual void Send(scoped_refptr<net::IOBuffer> buffer, - int buffer_size, - const SendCompletionCallback& success_callback, - const ErrorCompletionCallback& error_callback) = 0; + virtual std::string GetLastErrorMessage() const = 0; protected: - friend class base::RefCountedThreadSafe<BluetoothSocket>; - virtual ~BluetoothSocket(); + friend class base::RefCounted<BluetoothSocket>; + virtual ~BluetoothSocket() {} }; } // namespace device diff --git a/device/bluetooth/bluetooth_socket_chromeos.cc b/device/bluetooth/bluetooth_socket_chromeos.cc index 7725b6d..85544d2 100644 --- a/device/bluetooth/bluetooth_socket_chromeos.cc +++ b/device/bluetooth/bluetooth_socket_chromeos.cc @@ -47,28 +47,6 @@ BluetoothSocketChromeOS::~BluetoothSocketChromeOS() { close(fd_); } -void BluetoothSocketChromeOS::Close() { NOTIMPLEMENTED(); } - -void BluetoothSocketChromeOS::Disconnect(const base::Closure& callback) { - NOTIMPLEMENTED(); -} - -void BluetoothSocketChromeOS::Receive( - int count, - const ReceiveCompletionCallback& success_callback, - const ReceiveErrorCompletionCallback& error_callback) { - NOTIMPLEMENTED(); -} - -void BluetoothSocketChromeOS::Send( - scoped_refptr<net::IOBuffer> buffer, - int buffer_size, - const SendCompletionCallback& success_callback, - const ErrorCompletionCallback& error_callback) { - NOTIMPLEMENTED(); -} - -#if 0 bool BluetoothSocketChromeOS::Receive(net::GrowableIOBuffer *buffer) { base::ThreadRestrictions::AssertIOAllowed(); @@ -175,7 +153,6 @@ bool BluetoothSocketChromeOS::Send(net::DrainableIOBuffer *buffer) { std::string BluetoothSocketChromeOS::GetLastErrorMessage() const { return error_message_; } -#endif // static scoped_refptr<device::BluetoothSocket> BluetoothSocketChromeOS::Create( diff --git a/device/bluetooth/bluetooth_socket_chromeos.h b/device/bluetooth/bluetooth_socket_chromeos.h index 5cfefba..1c52c67 100644 --- a/device/bluetooth/bluetooth_socket_chromeos.h +++ b/device/bluetooth/bluetooth_socket_chromeos.h @@ -13,11 +13,16 @@ #include "device/bluetooth/bluetooth_socket.h" namespace dbus { + class FileDescriptor; + } // namespace dbus namespace net { -class IOBuffer; + +class DrainableIOBuffer; +class GrowableIOBuffer; + } // namespace net namespace chromeos { @@ -27,17 +32,10 @@ namespace chromeos { class CHROMEOS_EXPORT BluetoothSocketChromeOS : public device::BluetoothSocket { public: - // Overriden from BluetoothSocket: - virtual void Close() OVERRIDE; - virtual void Disconnect(const base::Closure& callback) OVERRIDE; - virtual void Receive(int count, - const ReceiveCompletionCallback& success_callback, - const ReceiveErrorCompletionCallback& error_callback) - OVERRIDE; - virtual void Send(scoped_refptr<net::IOBuffer> buffer, - int buffer_size, - const SendCompletionCallback& success_callback, - const ErrorCompletionCallback& error_callback) OVERRIDE; + // BluetoothSocket override. + virtual bool Receive(net::GrowableIOBuffer* buffer) OVERRIDE; + virtual bool Send(net::DrainableIOBuffer* buffer) OVERRIDE; + virtual std::string GetLastErrorMessage() const OVERRIDE; // Create an instance of a BluetoothSocket from the passed file descriptor // received over D-Bus in |fd|, the descriptor will be taken from that object diff --git a/device/bluetooth/bluetooth_socket_mac.h b/device/bluetooth/bluetooth_socket_mac.h index 806eceb..4d7bfb7 100644 --- a/device/bluetooth/bluetooth_socket_mac.h +++ b/device/bluetooth/bluetooth_socket_mac.h @@ -21,8 +21,10 @@ class IOBluetoothSDPServiceRecord; #endif namespace net { + +class DrainableIOBuffer; class GrowableIOBuffer; -class IOBuffer; + } // namespace net namespace device { @@ -40,17 +42,10 @@ class BluetoothSocketMac : public BluetoothSocket { static scoped_refptr<BluetoothSocket> CreateBluetoothSocket( IOBluetoothSDPServiceRecord* record); - // Overriden from BluetoothSocket: - virtual void Close() OVERRIDE; - virtual void Disconnect(const base::Closure& callback) OVERRIDE; - virtual void Receive(int count, - const ReceiveCompletionCallback& success_callback, - const ReceiveErrorCompletionCallback& error_callback) - OVERRIDE; - virtual void Send(scoped_refptr<net::IOBuffer> buffer, - int buffer_size, - const SendCompletionCallback& success_callback, - const ErrorCompletionCallback& error_callback) OVERRIDE; + // BluetoothSocket override + virtual bool Receive(net::GrowableIOBuffer* buffer) OVERRIDE; + virtual bool Send(net::DrainableIOBuffer* buffer) OVERRIDE; + virtual std::string GetLastErrorMessage() const OVERRIDE; // called by BluetoothRFCOMMChannelDelegate. void OnDataReceived(IOBluetoothRFCOMMChannel* rfcomm_channel, diff --git a/device/bluetooth/bluetooth_socket_mac.mm b/device/bluetooth/bluetooth_socket_mac.mm index b4a88c0..3751441 100644 --- a/device/bluetooth/bluetooth_socket_mac.mm +++ b/device/bluetooth/bluetooth_socket_mac.mm @@ -123,27 +123,6 @@ scoped_refptr<BluetoothSocket> BluetoothSocketMac::CreateBluetoothSocket( return scoped_refptr<BluetoothSocketMac>(bluetooth_socket); } -void BluetoothSocketMac::Close() { NOTIMPLEMENTED(); } - -void BluetoothSocketMac::Disconnect(const base::Closure& callback) { - NOTIMPLEMENTED(); -} - -void BluetoothSocketMac::Receive( - int count, - const ReceiveCompletionCallback& success_callback, - const ReceiveErrorCompletionCallback& error_callback) { - NOTIMPLEMENTED(); -} - -void BluetoothSocketMac::Send(scoped_refptr<net::IOBuffer> buffer, - int buffer_size, - const SendCompletionCallback& success_callback, - const ErrorCompletionCallback& error_callback) { - NOTIMPLEMENTED(); -} - -#if 0 bool BluetoothSocketMac::Receive(net::GrowableIOBuffer* buffer) { CHECK(buffer->offset() == 0); int length = incoming_data_buffer_->offset(); @@ -175,7 +154,7 @@ bool BluetoothSocketMac::Send(net::DrainableIOBuffer* buffer) { std::string BluetoothSocketMac::GetLastErrorMessage() const { return error_message_; } -#endif + void BluetoothSocketMac::OnDataReceived( IOBluetoothRFCOMMChannel* rfcomm_channel, void* data, size_t length) { DCHECK(rfcomm_channel_ == rfcomm_channel); diff --git a/device/bluetooth/bluetooth_socket_thread_win.cc b/device/bluetooth/bluetooth_socket_thread_win.cc deleted file mode 100644 index 04ce799..0000000 --- a/device/bluetooth/bluetooth_socket_thread_win.cc +++ /dev/null @@ -1,66 +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. - -#include "device/bluetooth/bluetooth_socket_thread_win.h" - -#include "base/lazy_instance.h" -#include "base/sequenced_task_runner.h" -#include "base/threading/thread.h" - -namespace device { - -base::LazyInstance<scoped_refptr<BluetoothSocketThreadWin> > g_instance = - LAZY_INSTANCE_INITIALIZER; - -// static -scoped_refptr<BluetoothSocketThreadWin> BluetoothSocketThreadWin::Get() { - if (!g_instance.Get().get()) { - g_instance.Get() = new BluetoothSocketThreadWin(); - } - return g_instance.Get(); -} - -BluetoothSocketThreadWin::BluetoothSocketThreadWin() - : active_socket_count_(0) {} - -BluetoothSocketThreadWin::~BluetoothSocketThreadWin() {} - -void BluetoothSocketThreadWin::OnSocketActivate() { - DCHECK(thread_checker_.CalledOnValidThread()); - active_socket_count_++; - EnsureStarted(); -} - -void BluetoothSocketThreadWin::OnSocketDeactivate() { - DCHECK(thread_checker_.CalledOnValidThread()); - active_socket_count_--; - if (active_socket_count_ == 0 && thread_) { - thread_->Stop(); - thread_.reset(NULL); - task_runner_ = NULL; - } -} - -void BluetoothSocketThreadWin::EnsureStarted() { - DCHECK(thread_checker_.CalledOnValidThread()); - if (thread_) - return; - - base::Thread::Options thread_options; - thread_options.message_loop_type = base::MessageLoop::TYPE_IO; - thread_.reset(new base::Thread("BluetoothSocketThreadWin")); - thread_->StartWithOptions(thread_options); - task_runner_ = thread_->message_loop_proxy(); -} - -scoped_refptr<base::SequencedTaskRunner> BluetoothSocketThreadWin::task_runner() - const { - DCHECK(active_socket_count_ > 0); - DCHECK(thread_); - DCHECK(task_runner_); - - return task_runner_; -} - -} // namespace device diff --git a/device/bluetooth/bluetooth_socket_thread_win.h b/device/bluetooth/bluetooth_socket_thread_win.h deleted file mode 100644 index 063ebbb..0000000 --- a/device/bluetooth/bluetooth_socket_thread_win.h +++ /dev/null @@ -1,48 +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 DEVICE_BLUETOOTH_BLUETOOTH_SOCKET_THREAD_WIN_H_ -#define DEVICE_BLUETOOTH_BLUETOOTH_SOCKET_THREAD_WIN_H_ - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/threading/thread_checker.h" - -namespace base { -class SequencedTaskRunner; -class Thread; -} // namespace base - -namespace device { - -// Thread abstraction used by |BluetoothSocketWWin| to perform IO operations on -// the underlying platform sockets. An instance of this class can be shared by -// many active sockets. -class BluetoothSocketThreadWin - : public base::RefCountedThreadSafe<BluetoothSocketThreadWin> { - public: - static scoped_refptr<BluetoothSocketThreadWin> Get(); - void OnSocketActivate(); - void OnSocketDeactivate(); - - scoped_refptr<base::SequencedTaskRunner> task_runner() const; - - private: - friend class base::RefCountedThreadSafe<BluetoothSocketThreadWin>; - BluetoothSocketThreadWin(); - virtual ~BluetoothSocketThreadWin(); - - void EnsureStarted(); - - base::ThreadChecker thread_checker_; - int active_socket_count_; - scoped_ptr<base::Thread> thread_; - scoped_refptr<base::SequencedTaskRunner> task_runner_; - - DISALLOW_COPY_AND_ASSIGN(BluetoothSocketThreadWin); -}; - -} // namespace device - -#endif // DEVICE_BLUETOOTH_BLUETOOTH_SOCKET_THREAD_WIN_H_ diff --git a/device/bluetooth/bluetooth_socket_win.cc b/device/bluetooth/bluetooth_socket_win.cc index 9b1e953..a684d14 100644 --- a/device/bluetooth/bluetooth_socket_win.cc +++ b/device/bluetooth/bluetooth_socket_win.cc @@ -8,25 +8,14 @@ #include "base/logging.h" #include "base/memory/ref_counted.h" -#include "base/sequenced_task_runner.h" #include "base/strings/sys_string_conversions.h" -#include "base/threading/thread_restrictions.h" #include "device/bluetooth/bluetooth_init_win.h" #include "device/bluetooth/bluetooth_service_record_win.h" -#include "device/bluetooth/bluetooth_socket_thread_win.h" #include "net/base/io_buffer.h" -#include "net/base/ip_endpoint.h" -#include "net/base/net_errors.h" #include "net/base/winsock_init.h" namespace { -const char kL2CAPNotSupported[] = "Bluetooth L2CAP protocal is not supported"; -const char kSocketAlreadyConnected[] = "Socket is already connected."; -const char kSocketNotConnected[] = "Socket is not connected."; - -using device::BluetoothSocketWin; - std::string FormatErrorMessage(DWORD error_code) { TCHAR error_msg[1024]; FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, @@ -39,364 +28,88 @@ std::string FormatErrorMessage(DWORD error_code) { return base::SysWideToUTF8(error_msg); } -static void DeactivateSocket( - const scoped_refptr<device::BluetoothSocketThreadWin>& socket_thread) { - socket_thread->OnSocketDeactivate(); -} - } // namespace namespace device { -// static -scoped_refptr<BluetoothSocketWin> BluetoothSocketWin::CreateBluetoothSocket( - const BluetoothServiceRecord& service_record, - scoped_refptr<base::SequencedTaskRunner> ui_task_runner, - scoped_refptr<BluetoothSocketThreadWin> socket_thread, - net::NetLog* net_log, - const net::NetLog::Source& source) { - DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); - const BluetoothServiceRecordWin* service_record_win = - static_cast<const BluetoothServiceRecordWin*>(&service_record); - - scoped_refptr<BluetoothSocketWin> result( - new BluetoothSocketWin(ui_task_runner, socket_thread, net_log, source)); - result->device_address_ = service_record_win->address(); - if (service_record.SupportsRfcomm()) { - result->supports_rfcomm_ = true; - result->rfcomm_channel_ = service_record_win->rfcomm_channel(); - result->bth_addr_ = service_record_win->bth_addr(); - } - - return result; -} - -BluetoothSocketWin::BluetoothSocketWin( - scoped_refptr<base::SequencedTaskRunner> ui_task_runner, - scoped_refptr<BluetoothSocketThreadWin> socket_thread, - net::NetLog* net_log, - const net::NetLog::Source& source) - : ui_task_runner_(ui_task_runner), - socket_thread_(socket_thread), - net_log_(net_log), - source_(source), - supports_rfcomm_(false), - rfcomm_channel_(-1), - bth_addr_(BTH_ADDR_NULL) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); - socket_thread->OnSocketActivate(); +BluetoothSocketWin::BluetoothSocketWin(SOCKET fd) : fd_(fd) { } BluetoothSocketWin::~BluetoothSocketWin() { - ui_task_runner_->PostTask(FROM_HERE, - base::Bind(&DeactivateSocket, socket_thread_)); -} - -void BluetoothSocketWin::Close() { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); - socket_thread_->task_runner()->PostTask( - FROM_HERE, base::Bind(&BluetoothSocketWin::DoClose, this)); -} - -void BluetoothSocketWin::Connect( - const base::Closure& success_callback, - const ErrorCompletionCallback& error_callback) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); - socket_thread_->task_runner()->PostTask( - FROM_HERE, - base::Bind( - &BluetoothSocketWin::DoConnect, - this, - base::Bind(&BluetoothSocketWin::PostSuccess, this, success_callback), - base::Bind( - &BluetoothSocketWin::PostErrorCompletion, this, error_callback))); -} - -void BluetoothSocketWin::Disconnect(const base::Closure& success_callback) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); - socket_thread_->task_runner()->PostTask( - FROM_HERE, - base::Bind( - &BluetoothSocketWin::DoDisconnect, - this, - base::Bind( - &BluetoothSocketWin::PostSuccess, this, success_callback))); -} - -void BluetoothSocketWin::Receive( - int count, - const ReceiveCompletionCallback& success_callback, - const ReceiveErrorCompletionCallback& error_callback) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); - socket_thread_->task_runner()->PostTask( - FROM_HERE, - base::Bind(&BluetoothSocketWin::DoReceive, - this, - count, - base::Bind(&BluetoothSocketWin::PostReceiveCompletion, - this, - success_callback), - base::Bind(&BluetoothSocketWin::PostReceiveErrorCompletion, - this, - error_callback))); -} - -void BluetoothSocketWin::Send(scoped_refptr<net::IOBuffer> buffer, - int buffer_size, - const SendCompletionCallback& success_callback, - const ErrorCompletionCallback& error_callback) { - DCHECK(ui_task_runner_->RunsTasksOnCurrentThread()); - socket_thread_->task_runner()->PostTask( - FROM_HERE, - base::Bind( - &BluetoothSocketWin::DoSend, - this, - buffer, - buffer_size, - base::Bind( - &BluetoothSocketWin::PostSendCompletion, this, success_callback), - base::Bind( - &BluetoothSocketWin::PostErrorCompletion, this, error_callback))); + closesocket(fd_); } -void BluetoothSocketWin::DoClose() { - DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); - base::ThreadRestrictions::AssertIOAllowed(); - - if (tcp_socket_) { - tcp_socket_->Close(); - tcp_socket_.reset(NULL); +// static +scoped_refptr<BluetoothSocket> BluetoothSocketWin::CreateBluetoothSocket( + const BluetoothServiceRecord& service_record) { + BluetoothSocketWin* bluetooth_socket = NULL; + if (service_record.SupportsRfcomm()) { + net::EnsureWinsockInit(); + SOCKET socket_fd = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); + SOCKADDR_BTH sa; + ZeroMemory(&sa, sizeof(sa)); + sa.addressFamily = AF_BTH; + sa.port = service_record.rfcomm_channel(); + const BluetoothServiceRecordWin* service_record_win = + static_cast<const BluetoothServiceRecordWin*>(&service_record); + sa.btAddr = service_record_win->bth_addr(); + + int status = connect(socket_fd, + reinterpret_cast<SOCKADDR *>(&sa), + sizeof(sa)); + DWORD error_code = WSAGetLastError(); + if (status == 0 || error_code == WSAEINPROGRESS) { + bluetooth_socket = + new BluetoothSocketWin(socket_fd); + } else { + LOG(ERROR) << "Failed to connect bluetooth socket " + << "(" << service_record.address() << "): " + << "(" << error_code << ")" << FormatErrorMessage(error_code); + closesocket(socket_fd); + } } + // TODO(youngki) add support for L2CAP sockets as well. - // Note: Closing |tcp_socket_| above released all potential pending - // Send/Receive operations, so we can no safely release the state associated - // to those pending operations. - read_buffer_ = NULL; - std::queue<linked_ptr<WriteRequest> > empty; - write_queue_.swap(empty); + return scoped_refptr<BluetoothSocketWin>(bluetooth_socket); } -void BluetoothSocketWin::DoConnect( - const base::Closure& success_callback, - const ErrorCompletionCallback& error_callback) { - DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); - base::ThreadRestrictions::AssertIOAllowed(); - - if (tcp_socket_) { - error_callback.Run(kSocketAlreadyConnected); - return; - } - - if (!supports_rfcomm_) { - // TODO(youngki) add support for L2CAP sockets as well. - error_callback.Run(kL2CAPNotSupported); - return; - } - - tcp_socket_.reset(new net::TCPSocket(net_log_, source_)); - net::EnsureWinsockInit(); - SOCKET socket_fd = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM); - SOCKADDR_BTH sa; - ZeroMemory(&sa, sizeof(sa)); - sa.addressFamily = AF_BTH; - sa.port = rfcomm_channel_; - sa.btAddr = bth_addr_; +bool BluetoothSocketWin::Receive(net::GrowableIOBuffer* buffer) { + buffer->SetCapacity(1024); + int bytes_read; + do { + if (buffer->RemainingCapacity() == 0) + buffer->SetCapacity(buffer->capacity() * 2); + bytes_read = recv(fd_, buffer->data(), buffer->RemainingCapacity(), 0); + if (bytes_read > 0) + buffer->set_offset(buffer->offset() + bytes_read); + } while (bytes_read > 0); - // TODO(rpaquay): Condider making this call non-blocking. - int status = connect(socket_fd, reinterpret_cast<SOCKADDR*>(&sa), sizeof(sa)); DWORD error_code = WSAGetLastError(); - if (!(status == 0 || error_code == WSAEINPROGRESS)) { - LOG(ERROR) << "Failed to connect bluetooth socket " - << "(" << device_address_ << "): " - << "(" << error_code << ")" << FormatErrorMessage(error_code); - error_callback.Run("Error connecting to socket: " + - FormatErrorMessage(error_code)); - closesocket(socket_fd); - return; - } - - // Note: We don't have a meaningful |IPEndPoint|, but that is ok since the - // TCPSocket implementation does not actually require one. - int net_result = - tcp_socket_->AdoptConnectedSocket(socket_fd, net::IPEndPoint()); - if (net_result != net::OK) { - error_callback.Run("Error connecting to socket: " + - std::string(net::ErrorToString(net_result))); - closesocket(socket_fd); - return; - } - - success_callback.Run(); -} - -void BluetoothSocketWin::DoDisconnect(const base::Closure& success_callback) { - DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); - base::ThreadRestrictions::AssertIOAllowed(); - - DoClose(); - success_callback.Run(); -} - -void BluetoothSocketWin::DoReceive( - int count, - const ReceiveCompletionCallback& success_callback, - const ReceiveErrorCompletionCallback& error_callback) { - DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); - base::ThreadRestrictions::AssertIOAllowed(); - - if (!tcp_socket_) { - error_callback.Run(BluetoothSocketWin::kDisconnected, kSocketNotConnected); - return; - } - - // Only one pending read at a time - if (read_buffer_.get()) { - error_callback.Run(BluetoothSocketWin::kIOPending, - net::ErrorToString(net::ERR_IO_PENDING)); - return; - } - - scoped_refptr<net::IOBufferWithSize> buffer(new net::IOBufferWithSize(count)); - int read_result = - tcp_socket_->Read(buffer.get(), - buffer->size(), - base::Bind(&BluetoothSocketWin::OnSocketReadComplete, - this, - success_callback, - error_callback)); - - if (read_result > 0) { - success_callback.Run(read_result, buffer); - } else if (read_result == net::OK || - read_result == net::ERR_CONNECTION_CLOSED) { - error_callback.Run(BluetoothSocketWin::kDisconnected, - net::ErrorToString(net::ERR_CONNECTION_CLOSED)); - } else if (read_result == net::ERR_IO_PENDING) { - read_buffer_ = buffer; - } else { - error_callback.Run(BluetoothSocketWin::kSystemError, - net::ErrorToString(read_result)); - } -} - -void BluetoothSocketWin::OnSocketReadComplete( - const ReceiveCompletionCallback& success_callback, - const ReceiveErrorCompletionCallback& error_callback, - int read_result) { - DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); - base::ThreadRestrictions::AssertIOAllowed(); - - scoped_refptr<net::IOBufferWithSize> buffer; - buffer.swap(read_buffer_); - if (read_result > 0) { - success_callback.Run(read_result, buffer); - } else if (read_result == net::OK || - read_result == net::ERR_CONNECTION_CLOSED) { - error_callback.Run(BluetoothSocketWin::kDisconnected, - net::ErrorToString(net::ERR_CONNECTION_CLOSED)); - } else { - error_callback.Run(BluetoothSocketWin::kSystemError, - net::ErrorToString(read_result)); - } -} - -void BluetoothSocketWin::DoSend(scoped_refptr<net::IOBuffer> buffer, - int buffer_size, - const SendCompletionCallback& success_callback, - const ErrorCompletionCallback& error_callback) { - DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); - base::ThreadRestrictions::AssertIOAllowed(); - - if (!tcp_socket_) { - error_callback.Run(kSocketNotConnected); - return; - } - - linked_ptr<WriteRequest> request(new WriteRequest()); - request->buffer = buffer; - request->buffer_size = buffer_size; - request->success_callback = success_callback; - request->error_callback = error_callback; - - write_queue_.push(request); - if (write_queue_.size() == 1) { - SendFrontWriteRequest(); + if (bytes_read < 0 && error_code != WSAEWOULDBLOCK) { + error_message_ = FormatErrorMessage(error_code); + return false; } + return true; } -void BluetoothSocketWin::SendFrontWriteRequest() { - DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); - base::ThreadRestrictions::AssertIOAllowed(); - - if (!tcp_socket_) - return; - - if (write_queue_.size() == 0) - return; +bool BluetoothSocketWin::Send(net::DrainableIOBuffer* buffer) { + int bytes_written; + do { + bytes_written = send(fd_, buffer->data(), buffer->BytesRemaining(), 0); + if (bytes_written > 0) + buffer->DidConsume(bytes_written); + } while (buffer->BytesRemaining() > 0 && bytes_written > 0); - linked_ptr<WriteRequest> request = write_queue_.front(); - net::CompletionCallback callback = - base::Bind(&BluetoothSocketWin::OnSocketWriteComplete, - this, - request->success_callback, - request->error_callback); - int send_result = - tcp_socket_->Write(request->buffer, request->buffer_size, callback); - if (send_result != net::ERR_IO_PENDING) { - callback.Run(send_result); - } -} - -void BluetoothSocketWin::OnSocketWriteComplete( - const SendCompletionCallback& success_callback, - const ErrorCompletionCallback& error_callback, - int send_result) { - DCHECK(socket_thread_->task_runner()->RunsTasksOnCurrentThread()); - base::ThreadRestrictions::AssertIOAllowed(); - - write_queue_.pop(); - - if (send_result >= net::OK) { - success_callback.Run(send_result); - } else { - error_callback.Run(net::ErrorToString(send_result)); + DWORD error_code = WSAGetLastError(); + if (bytes_written < 0 && error_code != WSAEWOULDBLOCK) { + error_message_ = FormatErrorMessage(error_code); + return false; } - - // Don't call directly to avoid potentail large recursion. - socket_thread_->task_runner()->PostNonNestableTask( - FROM_HERE, base::Bind(&BluetoothSocketWin::SendFrontWriteRequest, this)); -} - -void BluetoothSocketWin::PostSuccess(const base::Closure& callback) { - ui_task_runner_->PostTask(FROM_HERE, callback); -} - -void BluetoothSocketWin::PostErrorCompletion( - const ErrorCompletionCallback& callback, - const std::string& error) { - ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, error)); -} - -void BluetoothSocketWin::PostReceiveCompletion( - const ReceiveCompletionCallback& callback, - int io_buffer_size, - scoped_refptr<net::IOBuffer> io_buffer) { - ui_task_runner_->PostTask(FROM_HERE, - base::Bind(callback, io_buffer_size, io_buffer)); -} - -void BluetoothSocketWin::PostReceiveErrorCompletion( - const ReceiveErrorCompletionCallback& callback, - ErrorReason reason, - const std::string& error_message) { - ui_task_runner_->PostTask(FROM_HERE, - base::Bind(callback, reason, error_message)); + return true; } -void BluetoothSocketWin::PostSendCompletion( - const SendCompletionCallback& callback, - int bytes_written) { - ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, bytes_written)); +std::string BluetoothSocketWin::GetLastErrorMessage() const { + return error_message_; } } // namespace device diff --git a/device/bluetooth/bluetooth_socket_win.h b/device/bluetooth/bluetooth_socket_win.h index 94f3df2..41713e7 100644 --- a/device/bluetooth/bluetooth_socket_win.h +++ b/device/bluetooth/bluetooth_socket_win.h @@ -7,123 +7,42 @@ #include <WinSock2.h> -#include <queue> #include <string> -#include "base/memory/linked_ptr.h" #include "base/memory/ref_counted.h" -#include "base/threading/thread_checker.h" -#include "device/bluetooth/bluetooth_service_record_win.h" #include "device/bluetooth/bluetooth_socket.h" -#include "net/base/net_log.h" -#include "net/socket/tcp_socket.h" namespace net { -class IOBuffer; -class IOBufferWithSize; + +class DrainableIOBuffer; +class GrowableIOBuffer; + } // namespace net namespace device { class BluetoothServiceRecord; -class BluetoothSocketThreadWin; -// This class is an implementation of BluetoothSocket class for the Windows -// platform. All public methods (including the factory method) must be called -// on the UI thread, while underlying socket operations are performed on a -// separated thread. +// This class is an implementation of BluetoothSocket class for Windows +// platform. class BluetoothSocketWin : public BluetoothSocket { public: - static scoped_refptr<BluetoothSocketWin> CreateBluetoothSocket( - const BluetoothServiceRecord& service_record, - scoped_refptr<base::SequencedTaskRunner> ui_task_runner, - scoped_refptr<BluetoothSocketThreadWin> socket_thread, - net::NetLog* net_log, - const net::NetLog::Source& source); - - // Connect to the peer device and calls |success_callback| when the - // connection has been established successfully. If an error occurs, calls - // |error_callback| with a system error message. - void Connect(const base::Closure& success_callback, - const ErrorCompletionCallback& error_callback); - - // Overriden from BluetoothSocket: - virtual void Close() OVERRIDE; - - virtual void Disconnect(const base::Closure& callback) OVERRIDE; - - virtual void Receive(int count, - const ReceiveCompletionCallback& success_callback, - const ReceiveErrorCompletionCallback& error_callback) - OVERRIDE; - virtual void Send(scoped_refptr<net::IOBuffer> buffer, - int buffer_size, - const SendCompletionCallback& success_callback, - const ErrorCompletionCallback& error_callback) OVERRIDE; + static scoped_refptr<BluetoothSocket> CreateBluetoothSocket( + const BluetoothServiceRecord& service_record); + + // BluetoothSocket override + virtual bool Receive(net::GrowableIOBuffer* buffer) OVERRIDE; + virtual bool Send(net::DrainableIOBuffer* buffer) OVERRIDE; + virtual std::string GetLastErrorMessage() const OVERRIDE; protected: virtual ~BluetoothSocketWin(); private: - struct WriteRequest { - scoped_refptr<net::IOBuffer> buffer; - int buffer_size; - SendCompletionCallback success_callback; - ErrorCompletionCallback error_callback; - }; - - BluetoothSocketWin(scoped_refptr<base::SequencedTaskRunner> ui_task_runner, - scoped_refptr<BluetoothSocketThreadWin> socket_thread, - net::NetLog* net_log, - const net::NetLog::Source& source); - - void DoClose(); - void DoConnect(const base::Closure& success_callback, - const ErrorCompletionCallback& error_callback); - void DoDisconnect(const base::Closure& callback); - void DoReceive(int count, - const ReceiveCompletionCallback& success_callback, - const ReceiveErrorCompletionCallback& error_callback); - void DoSend(scoped_refptr<net::IOBuffer> buffer, - int buffer_size, - const SendCompletionCallback& success_callback, - const ErrorCompletionCallback& error_callback); - - void PostSuccess(const base::Closure& callback); - void PostErrorCompletion(const ErrorCompletionCallback& callback, - const std::string& error); - void PostReceiveCompletion(const ReceiveCompletionCallback& callback, - int io_buffer_size, - scoped_refptr<net::IOBuffer> io_buffer); - void PostReceiveErrorCompletion( - const ReceiveErrorCompletionCallback& callback, - ErrorReason reason, - const std::string& error_message); - void PostSendCompletion(const SendCompletionCallback& callback, - int bytes_written); - - void SendFrontWriteRequest(); - void OnSocketWriteComplete(const SendCompletionCallback& success_callback, - const ErrorCompletionCallback& error_callback, - int net_status); - void OnSocketReadComplete( - const ReceiveCompletionCallback& success_callback, - const ReceiveErrorCompletionCallback& error_callback, - int send_result); - - scoped_refptr<base::SequencedTaskRunner> ui_task_runner_; - scoped_refptr<BluetoothSocketThreadWin> socket_thread_; - net::NetLog* net_log_; - const net::NetLog::Source source_; - std::string device_address_; - bool supports_rfcomm_; - uint8 rfcomm_channel_; - BTH_ADDR bth_addr_; - scoped_ptr<net::TCPSocket> tcp_socket_; - // Queue of pending writes. The buffer at the front of the queue is the one - // being written. - std::queue<linked_ptr<WriteRequest> > write_queue_; - scoped_refptr<net::IOBufferWithSize> read_buffer_; + explicit BluetoothSocketWin(SOCKET fd); + + const SOCKET fd_; + std::string error_message_; DISALLOW_COPY_AND_ASSIGN(BluetoothSocketWin); }; diff --git a/device/bluetooth/bluetooth_task_manager_win.cc b/device/bluetooth/bluetooth_task_manager_win.cc index 95b580a..3347f0f 100644 --- a/device/bluetooth/bluetooth_task_manager_win.cc +++ b/device/bluetooth/bluetooth_task_manager_win.cc @@ -30,8 +30,6 @@ const int kMaxNumDeviceAddressChar = 127; const int kServiceDiscoveryResultBufferSize = 5000; const int kMaxDeviceDiscoveryTimeout = 48; -typedef device::BluetoothTaskManagerWin::ServiceRecordState ServiceRecordState; - // Populates bluetooth adapter state using adapter_handle. void GetAdapterState(HANDLE adapter_handle, device::BluetoothTaskManagerWin::AdapterState* state) { @@ -73,49 +71,6 @@ void GetDeviceState(const BLUETOOTH_DEVICE_INFO& device_info, state->authenticated = !!device_info.fAuthenticated; } -void DiscoverDeviceServices( - const std::string& device_address, - const GUID& protocol_uuid, - ScopedVector<ServiceRecordState>* service_record_states) { - // Bluetooth and WSAQUERYSET for Service Inquiry. See http://goo.gl/2v9pyt. - WSAQUERYSET sdp_query; - ZeroMemory(&sdp_query, sizeof(sdp_query)); - sdp_query.dwSize = sizeof(sdp_query); - GUID protocol = protocol_uuid; - sdp_query.lpServiceClassId = &protocol; - sdp_query.dwNameSpace = NS_BTH; - wchar_t device_address_context[kMaxNumDeviceAddressChar]; - std::size_t length = base::SysUTF8ToWide("(" + device_address + ")").copy( - device_address_context, kMaxNumDeviceAddressChar); - device_address_context[length] = NULL; - sdp_query.lpszContext = device_address_context; - HANDLE sdp_handle; - if (ERROR_SUCCESS != - WSALookupServiceBegin(&sdp_query, LUP_RETURN_ALL, &sdp_handle)) { - return; - } - char sdp_buffer[kServiceDiscoveryResultBufferSize]; - LPWSAQUERYSET sdp_result_data = reinterpret_cast<LPWSAQUERYSET>(sdp_buffer); - while (true) { - DWORD sdp_buffer_size = sizeof(sdp_buffer); - if (ERROR_SUCCESS != - WSALookupServiceNext( - sdp_handle, LUP_RETURN_ALL, &sdp_buffer_size, sdp_result_data)) { - break; - } - ServiceRecordState* service_record_state = new ServiceRecordState(); - service_record_state->name = - base::SysWideToUTF8(sdp_result_data->lpszServiceInstanceName); - service_record_state->address = device_address; - for (uint64 i = 0; i < sdp_result_data->lpBlob->cbSize; i++) { - service_record_state->sdp_bytes.push_back( - sdp_result_data->lpBlob->pBlobData[i]); - } - service_record_states->push_back(service_record_state); - } - WSALookupServiceEnd(sdp_handle); -} - } // namespace namespace device { @@ -420,9 +375,41 @@ void BluetoothTaskManagerWin::DiscoverServices( const std::string device_address = (*iter)->address; ScopedVector<ServiceRecordState>* service_record_states = &(*iter)->service_record_states; - - DiscoverDeviceServices( - device_address, L2CAP_PROTOCOL_UUID, service_record_states); + WSAQUERYSET sdp_query; + ZeroMemory(&sdp_query, sizeof(sdp_query)); + sdp_query.dwSize = sizeof(sdp_query); + GUID protocol = L2CAP_PROTOCOL_UUID; + sdp_query.lpServiceClassId = &protocol; + sdp_query.dwNameSpace = NS_BTH; + wchar_t device_address_context[kMaxNumDeviceAddressChar]; + std::size_t length = + base::SysUTF8ToWide("(" + device_address + ")").copy( + device_address_context, kMaxNumDeviceAddressChar); + device_address_context[length] = NULL; + sdp_query.lpszContext = device_address_context; + HANDLE sdp_handle; + if (ERROR_SUCCESS != + WSALookupServiceBegin(&sdp_query, LUP_RETURN_ALL, &sdp_handle)) { + return; + } + char sdp_buffer[kServiceDiscoveryResultBufferSize]; + LPWSAQUERYSET sdp_result_data = reinterpret_cast<LPWSAQUERYSET>(sdp_buffer); + DWORD sdp_buffer_size = sizeof(sdp_buffer); + while (ERROR_SUCCESS == WSALookupServiceNext(sdp_handle, + LUP_RETURN_ALL, + &sdp_buffer_size, + sdp_result_data)) { + ServiceRecordState* service_record_state = new ServiceRecordState(); + service_record_state->name = + base::SysWideToUTF8(sdp_result_data->lpszServiceInstanceName); + service_record_state->address = device_address; + for (uint64 i = 0; i < sdp_result_data->lpBlob->cbSize; i++) { + service_record_state->sdp_bytes.push_back( + sdp_result_data->lpBlob->pBlobData[i]); + } + service_record_states->push_back(service_record_state); + } + WSALookupServiceEnd(sdp_handle); } } diff --git a/device/bluetooth/test/mock_bluetooth_device.h b/device/bluetooth/test/mock_bluetooth_device.h index 675610a..6bd5707 100644 --- a/device/bluetooth/test/mock_bluetooth_device.h +++ b/device/bluetooth/test/mock_bluetooth_device.h @@ -62,9 +62,9 @@ class MockBluetoothDevice : public BluetoothDevice { void(const BluetoothUUID&, const BluetoothDevice::SocketCallback&)); MOCK_METHOD3(ConnectToProfile, - void(BluetoothProfile* profile, - const base::Closure& callback, - const ConnectToProfileErrorCallback& error_callback)); + void(BluetoothProfile*, + const base::Closure&, + const BluetoothDevice::ErrorCallback&)); MOCK_METHOD3(SetOutOfBandPairingData, void(const BluetoothOutOfBandPairingData& data, diff --git a/device/bluetooth/test/mock_bluetooth_socket.h b/device/bluetooth/test/mock_bluetooth_socket.h index 09e7e26..8b5e142 100644 --- a/device/bluetooth/test/mock_bluetooth_socket.h +++ b/device/bluetooth/test/mock_bluetooth_socket.h @@ -8,25 +8,23 @@ #include <string> #include "device/bluetooth/bluetooth_socket.h" -#include "net/base/io_buffer.h" #include "testing/gmock/include/gmock/gmock.h" +namespace net { + +class DrainableIOBuffer; +class GrowableIOBuffer; + +} // namespace net + namespace device { class MockBluetoothSocket : public BluetoothSocket { public: MockBluetoothSocket(); - MOCK_METHOD0(Close, void()); - MOCK_METHOD1(Disconnect, void(const base::Closure& callback)); - MOCK_METHOD3(Receive, - void(int count, - const ReceiveCompletionCallback& success_callback, - const ReceiveErrorCompletionCallback& error_callback)); - MOCK_METHOD4(Send, - void(scoped_refptr<net::IOBuffer> buffer, - int buffer_size, - const SendCompletionCallback& success_callback, - const ErrorCompletionCallback& error_callback)); + MOCK_METHOD1(Receive, bool(net::GrowableIOBuffer*)); + MOCK_METHOD1(Send, bool(net::DrainableIOBuffer*)); + MOCK_CONST_METHOD0(GetLastErrorMessage, std::string()); protected: virtual ~MockBluetoothSocket(); diff --git a/extensions/browser/api/api_resource_manager.h b/extensions/browser/api/api_resource_manager.h index e0c9b81..6374abe 100644 --- a/extensions/browser/api/api_resource_manager.h +++ b/extensions/browser/api/api_resource_manager.h @@ -25,8 +25,6 @@ namespace extensions { namespace api { -class BluetoothSocketApiFunction; -class BluetoothSocketEventDispatcher; class SerialEventDispatcher; } @@ -154,9 +152,6 @@ class ApiResourceManager : public BrowserContextKeyedAPI, private: // TODO(rockot): ApiResourceData could be moved out of ApiResourceManager and // we could avoid maintaining a friends list here. - friend class BluetoothAPI; - friend class api::BluetoothSocketApiFunction; - friend class api::BluetoothSocketEventDispatcher; friend class api::SerialEventDispatcher; friend class core_api::TCPServerSocketEventDispatcher; friend class core_api::TCPSocketEventDispatcher; @@ -220,38 +215,26 @@ class ApiResourceManager : public BrowserContextKeyedAPI, } void InitiateExtensionUnloadedCleanup(const std::string& extension_id) { - if (content::BrowserThread::CurrentlyOn(thread_id_)) { - CleanupResourcesFromUnloadedExtension(extension_id); - } else { - content::BrowserThread::PostTask( - thread_id_, - FROM_HERE, - base::Bind(&ApiResourceData::CleanupResourcesFromUnloadedExtension, - this, - extension_id)); - } + content::BrowserThread::PostTask( + thread_id_, + FROM_HERE, + base::Bind(&ApiResourceData::CleanupResourcesFromUnloadedExtension, + this, + extension_id)); } void InitiateExtensionSuspendedCleanup(const std::string& extension_id) { - if (content::BrowserThread::CurrentlyOn(thread_id_)) { - CleanupResourcesFromSuspendedExtension(extension_id); - } else { - content::BrowserThread::PostTask( - thread_id_, - FROM_HERE, - base::Bind(&ApiResourceData::CleanupResourcesFromSuspendedExtension, - this, - extension_id)); - } + content::BrowserThread::PostTask( + thread_id_, + FROM_HERE, + base::Bind(&ApiResourceData::CleanupResourcesFromSuspendedExtension, + this, + extension_id)); } void InititateCleanup() { - if (content::BrowserThread::CurrentlyOn(thread_id_)) { - Cleanup(); - } else { - content::BrowserThread::PostTask( - thread_id_, FROM_HERE, base::Bind(&ApiResourceData::Cleanup, this)); - } + content::BrowserThread::PostTask( + thread_id_, FROM_HERE, base::Bind(&ApiResourceData::Cleanup, this)); } private: diff --git a/extensions/browser/api/async_api_function.h b/extensions/browser/api/async_api_function.h index b18ec4d..dd4b500 100644 --- a/extensions/browser/api/async_api_function.h +++ b/extensions/browser/api/async_api_function.h @@ -42,7 +42,6 @@ class AsyncApiFunction : public UIThreadExtensionFunction { virtual bool RunImpl() OVERRIDE; protected: - content::BrowserThread::ID work_thread_id() const { return work_thread_id_; } void set_work_thread_id(content::BrowserThread::ID work_thread_id) { work_thread_id_ = work_thread_id; } diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index ec2a0ca..17eee77 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h @@ -770,10 +770,6 @@ enum HistogramValue { BLUETOOTHPRIVATE_SETPAIRINGRESPONSE, NETWORKINGPRIVATE_GETCAPTIVEPORTALSTATUS, AUTOMATIONINTERNAL_PERFORMACTION, - BLUETOOTH_UPDATE_SOCKET, - BLUETOOTH_SET_SOCKET_PAUSED, - BLUETOOTH_GET_SOCKET, - BLUETOOTH_GET_SOCKETS, // Last entry: Add new entries above and ensure to update // tools/metrics/histograms/histograms/histograms.xml. ENUM_BOUNDARY |