Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / bluetooth / bluetooth_event_router.cc
index bb84336..31a26c1 100644 (file)
@@ -8,14 +8,19 @@
 #include <string>
 
 #include "base/bind.h"
-#include "base/json/json_writer.h"
+#include "base/bind_helpers.h"
+#include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_vector.h"
+#include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/extensions/api/bluetooth/bluetooth_api_pairing_delegate.h"
 #include "chrome/browser/extensions/api/bluetooth/bluetooth_api_utils.h"
+#include "chrome/browser/extensions/api/bluetooth/bluetooth_private_api.h"
 #include "chrome/common/extensions/api/bluetooth.h"
+#include "chrome/common/extensions/api/bluetooth_private.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_source.h"
 #include "device/bluetooth/bluetooth_adapter.h"
 #include "device/bluetooth/bluetooth_profile.h"
 #include "device/bluetooth/bluetooth_socket.h"
 #include "extensions/browser/event_router.h"
-#include "extensions/browser/extension_system.h"
+#include "extensions/browser/extension_host.h"
 
 namespace extensions {
 
 namespace bluetooth = api::bluetooth;
-
-// A struct storing a Bluetooth socket and the extension that added it.
-struct ExtensionBluetoothSocketRecord {
-  std::string extension_id;
-  scoped_refptr<device::BluetoothSocket> socket;
-};
+namespace bt_private = api::bluetooth_private;
 
 // A struct storing a Bluetooth profile and the extension that added it.
-struct ExtensionBluetoothProfileRecord {
+struct BluetoothEventRouter::ExtensionBluetoothProfileRecord {
   std::string extension_id;
   device::BluetoothProfile* profile;
 };
 
-ExtensionBluetoothEventRouter::ExtensionBluetoothEventRouter(
-    content::BrowserContext* context)
+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_));
 }
 
-ExtensionBluetoothEventRouter::~ExtensionBluetoothEventRouter() {
+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.";
-  socket_map_.clear();
-
-  for (BluetoothProfileMap::iterator iter = bluetooth_profile_map_.begin();
-       iter != bluetooth_profile_map_.end();
-       ++iter) {
-    iter->second.profile->Unregister();
-  }
-  for (DiscoverySessionMap::iterator iter = discovery_session_map_.begin();
-       iter != discovery_session_map_.end();
-       ++iter) {
-    delete iter->second;
-  }
+  CleanUpAllExtensions();
 }
 
-bool ExtensionBluetoothEventRouter::IsBluetoothSupported() const {
+bool BluetoothEventRouter::IsBluetoothSupported() const {
   return adapter_.get() ||
          device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable();
 }
 
-void ExtensionBluetoothEventRouter::GetAdapter(
+void BluetoothEventRouter::GetAdapter(
     const device::BluetoothAdapterFactory::AdapterCallback& callback) {
   if (adapter_.get()) {
     callback.Run(scoped_refptr<device::BluetoothAdapter>(adapter_));
@@ -92,50 +82,18 @@ void ExtensionBluetoothEventRouter::GetAdapter(
   device::BluetoothAdapterFactory::GetAdapter(callback);
 }
 
-void ExtensionBluetoothEventRouter::OnListenerAdded() {
-  num_event_listeners_++;
-  InitializeAdapterIfNeeded();
-}
-
-void ExtensionBluetoothEventRouter::OnListenerRemoved() {
-  if (num_event_listeners_ > 0)
-    num_event_listeners_--;
-  MaybeReleaseAdapter();
-}
-
-int ExtensionBluetoothEventRouter::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 ExtensionBluetoothEventRouter::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 ExtensionBluetoothEventRouter::AddProfile(
-    const std::string& uuid,
+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 ExtensionBluetoothEventRouter::RemoveProfile(const std::string& uuid) {
+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;
@@ -144,11 +102,12 @@ void ExtensionBluetoothEventRouter::RemoveProfile(const std::string& uuid) {
   }
 }
 
-bool ExtensionBluetoothEventRouter::HasProfile(const std::string& uuid) const {
+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();
 }
 
-void ExtensionBluetoothEventRouter::StartDiscoverySession(
+void BluetoothEventRouter::StartDiscoverySession(
     device::BluetoothAdapter* adapter,
     const std::string& extension_id,
     const base::Closure& callback,
@@ -165,14 +124,14 @@ void ExtensionBluetoothEventRouter::StartDiscoverySession(
     return;
   }
   adapter->StartDiscoverySession(
-      base::Bind(&ExtensionBluetoothEventRouter::OnStartDiscoverySession,
+      base::Bind(&BluetoothEventRouter::OnStartDiscoverySession,
                  weak_ptr_factory_.GetWeakPtr(),
                  extension_id,
                  callback),
       error_callback);
 }
 
-void ExtensionBluetoothEventRouter::StopDiscoverySession(
+void BluetoothEventRouter::StopDiscoverySession(
     device::BluetoothAdapter* adapter,
     const std::string& extension_id,
     const base::Closure& callback,
@@ -192,8 +151,9 @@ void ExtensionBluetoothEventRouter::StopDiscoverySession(
   session->Stop(callback, error_callback);
 }
 
-device::BluetoothProfile* ExtensionBluetoothEventRouter::GetProfile(
-    const std::string& uuid) const {
+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;
@@ -201,39 +161,74 @@ device::BluetoothProfile* ExtensionBluetoothEventRouter::GetProfile(
   return NULL;
 }
 
-scoped_refptr<device::BluetoothSocket>
-ExtensionBluetoothEventRouter::GetSocket(int id) {
-  SocketMap::iterator socket_entry = socket_map_.find(id);
-  if (socket_entry == socket_map_.end())
-    return NULL;
-  return socket_entry->second.socket;
+BluetoothApiPairingDelegate* BluetoothEventRouter::GetPairingDelegate(
+    const std::string& extension_id) {
+  return ContainsKey(pairing_delegate_map_, extension_id)
+             ? pairing_delegate_map_[extension_id]
+             : NULL;
 }
 
-void ExtensionBluetoothEventRouter::DispatchConnectionEvent(
-    const std::string& extension_id,
-    const std::string& uuid,
-    const device::BluetoothDevice* device,
-    scoped_refptr<device::BluetoothSocket> socket) {
-  if (!HasProfile(uuid))
+void BluetoothEventRouter::OnAdapterInitialized(
+    const base::Closure& callback,
+    scoped_refptr<device::BluetoothAdapter> adapter) {
+  if (!adapter_.get()) {
+    adapter_ = adapter;
+    adapter_->AddObserver(this);
+  }
+
+  callback.Run();
+}
+
+void BluetoothEventRouter::MaybeReleaseAdapter() {
+  if (adapter_.get() && num_event_listeners_ == 0 &&
+      pairing_delegate_map_.empty()) {
+    adapter_->RemoveObserver(this);
+    adapter_ = NULL;
+  }
+}
+
+void BluetoothEventRouter::AddPairingDelegate(const std::string& extension_id) {
+  if (!adapter_.get()) {
+    base::Closure self_callback =
+        base::Bind(&BluetoothEventRouter::AddPairingDelegate,
+                   weak_ptr_factory_.GetWeakPtr(),
+                   extension_id);
+    GetAdapter(base::Bind(&BluetoothEventRouter::OnAdapterInitialized,
+                          weak_ptr_factory_.GetWeakPtr(),
+                          self_callback));
     return;
+  }
 
-  int socket_id = RegisterSocket(extension_id, socket);
-  bluetooth::Socket result_socket;
-  bluetooth::BluetoothDeviceToApiDevice(*device, &result_socket.device);
-  result_socket.profile.uuid = uuid;
-  result_socket.id = socket_id;
+  if (!ContainsKey(pairing_delegate_map_, extension_id)) {
+    BluetoothApiPairingDelegate* delegate =
+        new BluetoothApiPairingDelegate(extension_id, browser_context_);
+    DCHECK(adapter_.get());
+    adapter_->AddPairingDelegate(
+        delegate, device::BluetoothAdapter::PAIRING_DELEGATE_PRIORITY_HIGH);
+    pairing_delegate_map_[extension_id] = delegate;
+  } else {
+    LOG(ERROR) << "Pairing delegate already exists for extension. "
+               << "There should be at most one onPairing listener.";
+    NOTREACHED();
+  }
+}
 
-  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());
+void BluetoothEventRouter::RemovePairingDelegate(
+    const std::string& extension_id) {
+  if (ContainsKey(pairing_delegate_map_, extension_id)) {
+    BluetoothApiPairingDelegate* delegate = pairing_delegate_map_[extension_id];
+    if (adapter_.get())
+      adapter_->RemovePairingDelegate(delegate);
+    pairing_delegate_map_.erase(extension_id);
+    delete delegate;
+    MaybeReleaseAdapter();
+  }
 }
 
-void ExtensionBluetoothEventRouter::AdapterPresentChanged(
-    device::BluetoothAdapter* adapter, bool present) {
+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;
@@ -241,8 +236,10 @@ void ExtensionBluetoothEventRouter::AdapterPresentChanged(
   DispatchAdapterStateEvent();
 }
 
-void ExtensionBluetoothEventRouter::AdapterPoweredChanged(
-    device::BluetoothAdapter* adapter, bool has_power) {
+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;
@@ -250,8 +247,10 @@ void ExtensionBluetoothEventRouter::AdapterPoweredChanged(
   DispatchAdapterStateEvent();
 }
 
-void ExtensionBluetoothEventRouter::AdapterDiscoveringChanged(
-    device::BluetoothAdapter* adapter, bool discovering) {
+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;
@@ -271,14 +270,15 @@ void ExtensionBluetoothEventRouter::AdapterDiscoveringChanged(
       delete session;
     }
     discovery_session_map_.swap(active_session_map);
+    MaybeReleaseAdapter();
   }
 
   DispatchAdapterStateEvent();
 }
 
-void ExtensionBluetoothEventRouter::DeviceAdded(
-    device::BluetoothAdapter* adapter,
-    device::BluetoothDevice* device) {
+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;
@@ -287,9 +287,9 @@ void ExtensionBluetoothEventRouter::DeviceAdded(
   DispatchDeviceEvent(bluetooth::OnDeviceAdded::kEventName, device);
 }
 
-void ExtensionBluetoothEventRouter::DeviceChanged(
-    device::BluetoothAdapter* adapter,
-    device::BluetoothDevice* device) {
+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;
@@ -298,9 +298,9 @@ void ExtensionBluetoothEventRouter::DeviceChanged(
   DispatchDeviceEvent(bluetooth::OnDeviceChanged::kEventName, device);
 }
 
-void ExtensionBluetoothEventRouter::DeviceRemoved(
-    device::BluetoothAdapter* adapter,
-    device::BluetoothDevice* device) {
+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;
@@ -309,30 +309,25 @@ void ExtensionBluetoothEventRouter::DeviceRemoved(
   DispatchDeviceEvent(bluetooth::OnDeviceRemoved::kEventName, device);
 }
 
-void ExtensionBluetoothEventRouter::InitializeAdapterIfNeeded() {
+void BluetoothEventRouter::OnListenerAdded() {
+  num_event_listeners_++;
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   if (!adapter_.get()) {
-    GetAdapter(base::Bind(&ExtensionBluetoothEventRouter::InitializeAdapter,
-                          weak_ptr_factory_.GetWeakPtr()));
+    GetAdapter(base::Bind(&BluetoothEventRouter::OnAdapterInitialized,
+                          weak_ptr_factory_.GetWeakPtr(),
+                          base::Bind(&base::DoNothing)));
   }
 }
 
-void ExtensionBluetoothEventRouter::InitializeAdapter(
-    scoped_refptr<device::BluetoothAdapter> adapter) {
-  if (!adapter_.get()) {
-    adapter_ = adapter;
-    adapter_->AddObserver(this);
-  }
-}
-
-void ExtensionBluetoothEventRouter::MaybeReleaseAdapter() {
-  if (adapter_.get() && num_event_listeners_ == 0) {
-    adapter_->RemoveObserver(this);
-    adapter_ = NULL;
-  }
+void BluetoothEventRouter::OnListenerRemoved() {
+  if (num_event_listeners_ > 0)
+    num_event_listeners_--;
+  MaybeReleaseAdapter();
 }
 
-void ExtensionBluetoothEventRouter::DispatchAdapterStateEvent() {
-  bluetooth::AdapterState state;
+void BluetoothEventRouter::DispatchAdapterStateEvent() {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  api::bluetooth::AdapterState state;
   PopulateAdapterState(*adapter_.get(), &state);
 
   scoped_ptr<base::ListValue> args =
@@ -340,11 +335,10 @@ void ExtensionBluetoothEventRouter::DispatchAdapterStateEvent() {
   scoped_ptr<Event> event(new Event(
       bluetooth::OnAdapterStateChanged::kEventName,
       args.Pass()));
-  ExtensionSystem::Get(browser_context_)->event_router()->BroadcastEvent(
-      event.Pass());
+  EventRouter::Get(browser_context_)->BroadcastEvent(event.Pass());
 }
 
-void ExtensionBluetoothEventRouter::DispatchDeviceEvent(
+void BluetoothEventRouter::DispatchDeviceEvent(
     const std::string& event_name,
     device::BluetoothDevice* device) {
   bluetooth::Device extension_device;
@@ -353,12 +347,14 @@ void ExtensionBluetoothEventRouter::DispatchDeviceEvent(
   scoped_ptr<base::ListValue> args =
       bluetooth::OnDeviceAdded::Create(extension_device);
   scoped_ptr<Event> event(new Event(event_name, args.Pass()));
-  ExtensionSystem::Get(browser_context_)->event_router()->BroadcastEvent(
-      event.Pass());
+  EventRouter::Get(browser_context_)->BroadcastEvent(event.Pass());
 }
 
-void ExtensionBluetoothEventRouter::CleanUpForExtension(
+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.
   BluetoothProfileMap::iterator profile_iter = bluetooth_profile_map_.begin();
   while (profile_iter != bluetooth_profile_map_.end()) {
@@ -371,17 +367,6 @@ void ExtensionBluetoothEventRouter::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);
@@ -391,7 +376,27 @@ void ExtensionBluetoothEventRouter::CleanUpForExtension(
   discovery_session_map_.erase(session_iter);
 }
 
-void ExtensionBluetoothEventRouter::OnStartDiscoverySession(
+void BluetoothEventRouter::CleanUpAllExtensions() {
+  for (BluetoothProfileMap::iterator it = bluetooth_profile_map_.begin();
+       it != bluetooth_profile_map_.end();
+       ++it) {
+    it->second.profile->Unregister();
+  }
+  bluetooth_profile_map_.clear();
+
+  for (DiscoverySessionMap::iterator it = discovery_session_map_.begin();
+       it != discovery_session_map_.end();
+       ++it) {
+    delete it->second;
+  }
+  discovery_session_map_.clear();
+
+  PairingDelegateMap::iterator pairing_iter = pairing_delegate_map_.begin();
+  while (pairing_iter != pairing_delegate_map_.end())
+    RemovePairingDelegate(pairing_iter++->first);
+}
+
+void BluetoothEventRouter::OnStartDiscoverySession(
     const std::string& extension_id,
     const base::Closure& callback,
     scoped_ptr<device::BluetoothDiscoverySession> discovery_session) {
@@ -404,10 +409,11 @@ void ExtensionBluetoothEventRouter::OnStartDiscoverySession(
   callback.Run();
 }
 
-void ExtensionBluetoothEventRouter::Observe(
+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 =
@@ -415,6 +421,11 @@ void ExtensionBluetoothEventRouter::Observe(
       CleanUpForExtension(info->extension->id());
       break;
     }
+    case chrome::NOTIFICATION_EXTENSION_HOST_DESTROYED: {
+      ExtensionHost* host = content::Details<ExtensionHost>(details).ptr();
+      CleanUpForExtension(host->extension_id());
+      break;
+    }
   }
 }