1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "extensions/browser/api/bluetooth/bluetooth_api.h" 6 7 #include <string> 8 9 #include "base/bind_helpers.h" 10 #include "base/lazy_instance.h" 11 #include "base/memory/ref_counted.h" 12 #include "content/public/browser/browser_thread.h" 13 #include "device/bluetooth/bluetooth_adapter.h" 14 #include "device/bluetooth/bluetooth_device.h" 15 #include "extensions/browser/api/bluetooth/bluetooth_api_utils.h" 16 #include "extensions/browser/api/bluetooth/bluetooth_event_router.h" 17 #include "extensions/browser/event_router.h" 18 #include "extensions/common/api/bluetooth.h" 19 20 using content::BrowserContext; 21 using content::BrowserThread; 22 23 using device::BluetoothAdapter; 24 using device::BluetoothDevice; 25 26 namespace bluetooth = extensions::core_api::bluetooth; 27 namespace GetDevice = extensions::core_api::bluetooth::GetDevice; 28 namespace GetDevices = extensions::core_api::bluetooth::GetDevices; 29 30 namespace { 31 32 const char kInvalidDevice[] = "Invalid device"; 33 const char kStartDiscoveryFailed[] = "Starting discovery failed"; 34 const char kStopDiscoveryFailed[] = "Failed to stop discovery"; 35 36 extensions::BluetoothEventRouter* GetEventRouter(BrowserContext* context) { 37 // Note: |context| is valid on UI thread only. 38 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 39 return extensions::BluetoothAPI::Get(context)->event_router(); 40 } 41 42 } // namespace 43 44 namespace extensions { 45 46 static base::LazyInstance<BrowserContextKeyedAPIFactory<BluetoothAPI> > 47 g_factory = LAZY_INSTANCE_INITIALIZER; 48 49 // static 50 BrowserContextKeyedAPIFactory<BluetoothAPI>* 51 BluetoothAPI::GetFactoryInstance() { 52 return g_factory.Pointer(); 53 } 54 55 // static 56 BluetoothAPI* BluetoothAPI::Get(BrowserContext* context) { 57 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 58 return GetFactoryInstance()->Get(context); 59 } 60 61 BluetoothAPI::BluetoothAPI(content::BrowserContext* context) 62 : browser_context_(context) { 63 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 64 EventRouter* event_router = EventRouter::Get(browser_context_); 65 event_router->RegisterObserver(this, 66 bluetooth::OnAdapterStateChanged::kEventName); 67 event_router->RegisterObserver(this, bluetooth::OnDeviceAdded::kEventName); 68 event_router->RegisterObserver(this, bluetooth::OnDeviceChanged::kEventName); 69 event_router->RegisterObserver(this, bluetooth::OnDeviceRemoved::kEventName); 70 } 71 72 BluetoothAPI::~BluetoothAPI() {} 73 74 BluetoothEventRouter* BluetoothAPI::event_router() { 75 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 76 if (!event_router_) { 77 event_router_.reset(new BluetoothEventRouter(browser_context_)); 78 } 79 return event_router_.get(); 80 } 81 82 void BluetoothAPI::Shutdown() { 83 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 84 EventRouter::Get(browser_context_)->UnregisterObserver(this); 85 } 86 87 void BluetoothAPI::OnListenerAdded(const EventListenerInfo& details) { 88 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 89 if (event_router()->IsBluetoothSupported()) 90 event_router()->OnListenerAdded(); 91 } 92 93 void BluetoothAPI::OnListenerRemoved(const EventListenerInfo& details) { 94 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 95 if (event_router()->IsBluetoothSupported()) 96 event_router()->OnListenerRemoved(); 97 } 98 99 namespace core_api { 100 101 BluetoothGetAdapterStateFunction::~BluetoothGetAdapterStateFunction() {} 102 103 bool BluetoothGetAdapterStateFunction::DoWork( 104 scoped_refptr<BluetoothAdapter> adapter) { 105 bluetooth::AdapterState state; 106 PopulateAdapterState(*adapter.get(), &state); 107 results_ = bluetooth::GetAdapterState::Results::Create(state); 108 SendResponse(true); 109 return true; 110 } 111 112 BluetoothGetDevicesFunction::~BluetoothGetDevicesFunction() {} 113 114 bool BluetoothGetDevicesFunction::DoWork( 115 scoped_refptr<BluetoothAdapter> adapter) { 116 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 117 118 base::ListValue* device_list = new base::ListValue; 119 SetResult(device_list); 120 121 BluetoothAdapter::DeviceList devices = adapter->GetDevices(); 122 for (BluetoothAdapter::DeviceList::const_iterator iter = devices.begin(); 123 iter != devices.end(); 124 ++iter) { 125 const BluetoothDevice* device = *iter; 126 DCHECK(device); 127 128 bluetooth::Device extension_device; 129 bluetooth::BluetoothDeviceToApiDevice(*device, &extension_device); 130 131 device_list->Append(extension_device.ToValue().release()); 132 } 133 134 SendResponse(true); 135 136 return true; 137 } 138 139 BluetoothGetDeviceFunction::~BluetoothGetDeviceFunction() {} 140 141 bool BluetoothGetDeviceFunction::DoWork( 142 scoped_refptr<BluetoothAdapter> adapter) { 143 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 144 145 scoped_ptr<GetDevice::Params> params(GetDevice::Params::Create(*args_)); 146 EXTENSION_FUNCTION_VALIDATE(params.get() != NULL); 147 148 BluetoothDevice* device = adapter->GetDevice(params->device_address); 149 if (device) { 150 bluetooth::Device extension_device; 151 bluetooth::BluetoothDeviceToApiDevice(*device, &extension_device); 152 SetResult(extension_device.ToValue().release()); 153 SendResponse(true); 154 } else { 155 SetError(kInvalidDevice); 156 SendResponse(false); 157 } 158 159 return false; 160 } 161 162 void BluetoothStartDiscoveryFunction::OnSuccessCallback() { 163 SendResponse(true); 164 } 165 166 void BluetoothStartDiscoveryFunction::OnErrorCallback() { 167 SetError(kStartDiscoveryFailed); 168 SendResponse(false); 169 } 170 171 bool BluetoothStartDiscoveryFunction::DoWork( 172 scoped_refptr<BluetoothAdapter> adapter) { 173 GetEventRouter(browser_context())->StartDiscoverySession( 174 adapter.get(), 175 extension_id(), 176 base::Bind(&BluetoothStartDiscoveryFunction::OnSuccessCallback, this), 177 base::Bind(&BluetoothStartDiscoveryFunction::OnErrorCallback, this)); 178 179 return true; 180 } 181 182 void BluetoothStopDiscoveryFunction::OnSuccessCallback() { 183 SendResponse(true); 184 } 185 186 void BluetoothStopDiscoveryFunction::OnErrorCallback() { 187 SetError(kStopDiscoveryFailed); 188 SendResponse(false); 189 } 190 191 bool BluetoothStopDiscoveryFunction::DoWork( 192 scoped_refptr<BluetoothAdapter> adapter) { 193 GetEventRouter(browser_context())->StopDiscoverySession( 194 adapter.get(), 195 extension_id(), 196 base::Bind(&BluetoothStopDiscoveryFunction::OnSuccessCallback, this), 197 base::Bind(&BluetoothStopDiscoveryFunction::OnErrorCallback, this)); 198 199 return true; 200 } 201 202 } // namespace core_api 203 } // namespace extensions 204