Delete chrome.mediaGalleriesPrivate because the functionality unique to it has since...
[chromium-blink-merge.git] / extensions / browser / api / bluetooth / bluetooth_private_api.cc
blob27353c42a27257090fab9c5a55ebe4f2227bb029
1 // Copyright 2014 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.
5 #include "extensions/browser/api/bluetooth/bluetooth_private_api.h"
7 #include "base/callback.h"
8 #include "base/lazy_instance.h"
9 #include "base/strings/string_util.h"
10 #include "device/bluetooth/bluetooth_adapter.h"
11 #include "device/bluetooth/bluetooth_adapter_factory.h"
12 #include "extensions/browser/api/bluetooth/bluetooth_api.h"
13 #include "extensions/browser/api/bluetooth/bluetooth_event_router.h"
14 #include "extensions/common/api/bluetooth_private.h"
16 namespace bt_private = extensions::core_api::bluetooth_private;
18 namespace extensions {
20 static base::LazyInstance<BrowserContextKeyedAPIFactory<BluetoothPrivateAPI> >
21 g_factory = LAZY_INSTANCE_INITIALIZER;
23 // static
24 BrowserContextKeyedAPIFactory<BluetoothPrivateAPI>*
25 BluetoothPrivateAPI::GetFactoryInstance() {
26 return g_factory.Pointer();
29 BluetoothPrivateAPI::BluetoothPrivateAPI(content::BrowserContext* context)
30 : browser_context_(context) {
31 EventRouter::Get(browser_context_)
32 ->RegisterObserver(this, bt_private::OnPairing::kEventName);
35 BluetoothPrivateAPI::~BluetoothPrivateAPI() {}
37 void BluetoothPrivateAPI::Shutdown() {
38 EventRouter::Get(browser_context_)->UnregisterObserver(this);
41 void BluetoothPrivateAPI::OnListenerAdded(const EventListenerInfo& details) {
42 // This function can be called multiple times for the same JS listener, for
43 // example, once for the addListener call and again if it is a lazy listener.
44 if (!details.browser_context)
45 return;
47 BluetoothAPI::Get(browser_context_)->event_router()->AddPairingDelegate(
48 details.extension_id);
51 void BluetoothPrivateAPI::OnListenerRemoved(const EventListenerInfo& details) {
52 // This function can be called multiple times for the same JS listener, for
53 // example, once for the addListener call and again if it is a lazy listener.
54 if (!details.browser_context)
55 return;
57 BluetoothAPI::Get(browser_context_)->event_router()->RemovePairingDelegate(
58 details.extension_id);
61 namespace core_api {
63 namespace {
65 const char kNameProperty[] = "name";
66 const char kPoweredProperty[] = "powered";
67 const char kDiscoverableProperty[] = "discoverable";
69 const char kSetAdapterPropertyError[] = "Error setting adapter properties: $1";
71 const char kDeviceNotFoundError[] =
72 "Given address is not a valid Bluetooth device.";
74 const char kDeviceNotConnectedError[] = "Device is not connected";
76 const char kPairingNotEnabled[] =
77 "Pairing must be enabled to set a pairing response.";
79 const char kInvalidPairingResponseOptions[] =
80 "Invalid pairing response options";
82 const char kAdapterNotPresent[] =
83 "Could not find a Bluetooth adapter.";
85 const char kDisconnectError[] = "Failed to disconnect device";
87 // Returns true if the pairing response options passed into the
88 // setPairingResponse function are valid.
89 bool ValidatePairingResponseOptions(
90 const device::BluetoothDevice* device,
91 const bt_private::SetPairingResponseOptions& options) {
92 bool response = options.response != bt_private::PAIRING_RESPONSE_NONE;
93 bool pincode = options.pincode.get() != NULL;
94 bool passkey = options.passkey.get() != NULL;
96 if (!response && !pincode && !passkey)
97 return false;
98 if (pincode && passkey)
99 return false;
100 if (options.response != bt_private::PAIRING_RESPONSE_CONFIRM &&
101 (pincode || passkey))
102 return false;
104 // Check the BluetoothDevice is in expecting the correct response.
105 if (!device->ExpectingConfirmation() && !device->ExpectingPinCode() &&
106 !device->ExpectingPasskey())
107 return false;
108 if (pincode && !device->ExpectingPinCode())
109 return false;
110 if (passkey && !device->ExpectingPasskey())
111 return false;
112 if (options.response == bt_private::PAIRING_RESPONSE_CONFIRM && !pincode &&
113 !passkey && !device->ExpectingConfirmation())
114 return false;
116 return true;
119 } // namespace
121 BluetoothPrivateSetAdapterStateFunction::
122 BluetoothPrivateSetAdapterStateFunction() {}
124 BluetoothPrivateSetAdapterStateFunction::
125 ~BluetoothPrivateSetAdapterStateFunction() {}
127 bool BluetoothPrivateSetAdapterStateFunction::DoWork(
128 scoped_refptr<device::BluetoothAdapter> adapter) {
129 scoped_ptr<bt_private::SetAdapterState::Params> params(
130 bt_private::SetAdapterState::Params::Create(*args_));
131 EXTENSION_FUNCTION_VALIDATE(params.get());
133 if (!adapter->IsPresent()) {
134 SetError(kAdapterNotPresent);
135 SendResponse(false);
136 return true;
139 const bt_private::NewAdapterState& new_state = params->adapter_state;
141 // These properties are not owned.
142 std::string* name = new_state.name.get();
143 bool* powered = new_state.powered.get();
144 bool* discoverable = new_state.discoverable.get();
146 if (name && adapter->GetName() != *name) {
147 pending_properties_.insert(kNameProperty);
148 adapter->SetName(*name,
149 CreatePropertySetCallback(kNameProperty),
150 CreatePropertyErrorCallback(kNameProperty));
153 if (powered && adapter->IsPowered() != *powered) {
154 pending_properties_.insert(kPoweredProperty);
155 adapter->SetPowered(*powered,
156 CreatePropertySetCallback(kPoweredProperty),
157 CreatePropertyErrorCallback(kPoweredProperty));
160 if (discoverable && adapter->IsDiscoverable() != *discoverable) {
161 pending_properties_.insert(kDiscoverableProperty);
162 adapter->SetDiscoverable(
163 *discoverable,
164 CreatePropertySetCallback(kDiscoverableProperty),
165 CreatePropertyErrorCallback(kDiscoverableProperty));
168 if (pending_properties_.empty())
169 SendResponse(true);
170 return true;
173 base::Closure
174 BluetoothPrivateSetAdapterStateFunction::CreatePropertySetCallback(
175 const std::string& property_name) {
176 return base::Bind(
177 &BluetoothPrivateSetAdapterStateFunction::OnAdapterPropertySet,
178 this,
179 property_name);
182 base::Closure
183 BluetoothPrivateSetAdapterStateFunction::CreatePropertyErrorCallback(
184 const std::string& property_name) {
185 return base::Bind(
186 &BluetoothPrivateSetAdapterStateFunction::OnAdapterPropertyError,
187 this,
188 property_name);
191 void BluetoothPrivateSetAdapterStateFunction::OnAdapterPropertySet(
192 const std::string& property) {
193 DCHECK(pending_properties_.find(property) != pending_properties_.end());
194 DCHECK(failed_properties_.find(property) == failed_properties_.end());
196 pending_properties_.erase(property);
197 if (pending_properties_.empty()) {
198 if (failed_properties_.empty())
199 SendResponse(true);
200 else
201 SendError();
205 void BluetoothPrivateSetAdapterStateFunction::OnAdapterPropertyError(
206 const std::string& property) {
207 DCHECK(pending_properties_.find(property) != pending_properties_.end());
208 DCHECK(failed_properties_.find(property) == failed_properties_.end());
210 pending_properties_.erase(property);
211 failed_properties_.insert(property);
212 if (pending_properties_.empty())
213 SendError();
216 void BluetoothPrivateSetAdapterStateFunction::SendError() {
217 DCHECK(pending_properties_.empty());
218 DCHECK(!failed_properties_.empty());
220 std::vector<std::string> failed_vector;
221 std::copy(failed_properties_.begin(),
222 failed_properties_.end(),
223 std::back_inserter(failed_vector));
225 std::vector<std::string> replacements(1);
226 replacements[0] = JoinString(failed_vector, ", ");
227 std::string error =
228 ReplaceStringPlaceholders(kSetAdapterPropertyError, replacements, NULL);
229 SetError(error);
230 SendResponse(false);
233 BluetoothPrivateSetPairingResponseFunction::
234 BluetoothPrivateSetPairingResponseFunction() {}
236 BluetoothPrivateSetPairingResponseFunction::
237 ~BluetoothPrivateSetPairingResponseFunction() {}
239 bool BluetoothPrivateSetPairingResponseFunction::DoWork(
240 scoped_refptr<device::BluetoothAdapter> adapter) {
241 scoped_ptr<bt_private::SetPairingResponse::Params> params(
242 bt_private::SetPairingResponse::Params::Create(*args_));
243 EXTENSION_FUNCTION_VALIDATE(params.get());
244 const bt_private::SetPairingResponseOptions& options = params->options;
246 BluetoothEventRouter* router =
247 BluetoothAPI::Get(browser_context())->event_router();
248 if (!router->GetPairingDelegate(extension_id())) {
249 SetError(kPairingNotEnabled);
250 SendResponse(false);
251 return true;
254 const std::string& device_address = options.device.address;
255 device::BluetoothDevice* device = adapter->GetDevice(device_address);
256 if (!device) {
257 SetError(kDeviceNotFoundError);
258 SendResponse(false);
259 return true;
262 if (!ValidatePairingResponseOptions(device, options)) {
263 SetError(kInvalidPairingResponseOptions);
264 SendResponse(false);
265 return true;
268 if (options.pincode.get()) {
269 device->SetPinCode(*options.pincode.get());
270 } else if (options.passkey.get()) {
271 device->SetPasskey(*options.passkey.get());
272 } else {
273 switch (options.response) {
274 case bt_private::PAIRING_RESPONSE_CONFIRM:
275 device->ConfirmPairing();
276 break;
277 case bt_private::PAIRING_RESPONSE_REJECT:
278 device->RejectPairing();
279 break;
280 case bt_private::PAIRING_RESPONSE_CANCEL:
281 device->CancelPairing();
282 break;
283 default:
284 NOTREACHED();
288 SendResponse(true);
289 return true;
292 BluetoothPrivateDisconnectAllFunction::BluetoothPrivateDisconnectAllFunction() {
295 BluetoothPrivateDisconnectAllFunction::
296 ~BluetoothPrivateDisconnectAllFunction() {
299 bool BluetoothPrivateDisconnectAllFunction::DoWork(
300 scoped_refptr<device::BluetoothAdapter> adapter) {
301 scoped_ptr<bt_private::DisconnectAll::Params> params(
302 bt_private::DisconnectAll::Params::Create(*args_));
303 EXTENSION_FUNCTION_VALIDATE(params.get());
305 device::BluetoothDevice* device = adapter->GetDevice(params->device_address);
306 if (!device) {
307 SetError(kDeviceNotFoundError);
308 SendResponse(false);
309 return true;
312 if (!device->IsConnected()) {
313 SetError(kDeviceNotConnectedError);
314 SendResponse(false);
315 return true;
318 device->Disconnect(
319 base::Bind(&BluetoothPrivateDisconnectAllFunction::OnSuccessCallback,
320 this),
321 base::Bind(&BluetoothPrivateDisconnectAllFunction::OnErrorCallback, this,
322 adapter, params->device_address));
324 return true;
327 void BluetoothPrivateDisconnectAllFunction::OnSuccessCallback() {
328 SendResponse(true);
331 void BluetoothPrivateDisconnectAllFunction::OnErrorCallback(
332 scoped_refptr<device::BluetoothAdapter> adapter,
333 const std::string& device_address) {
334 // The call to Disconnect may report an error if the device was disconnected
335 // due to an external reason. In this case, report "Not Connected" as the
336 // error.
337 device::BluetoothDevice* device = adapter->GetDevice(device_address);
338 if (device && !device->IsConnected())
339 SetError(kDeviceNotConnectedError);
340 else
341 SetError(kDisconnectError);
343 SendResponse(false);
346 } // namespace core_api
348 } // namespace extensions