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