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
;
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
)
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
)
57 BluetoothAPI::Get(browser_context_
)->event_router()->RemovePairingDelegate(
58 details
.extension_id
);
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 kPairingNotEnabled
[] =
75 "Pairing must be enabled to set a pairing response.";
77 const char kInvalidPairingResponseOptions
[] =
78 "Invalid pairing response options";
80 const char kAdapterNotPresent
[] =
81 "Could not find a Bluetooth adapter.";
83 // Returns true if the pairing response options passed into the
84 // setPairingResponse function are valid.
85 bool ValidatePairingResponseOptions(
86 const device::BluetoothDevice
* device
,
87 const bt_private::SetPairingResponseOptions
& options
) {
88 bool response
= options
.response
!= bt_private::PAIRING_RESPONSE_NONE
;
89 bool pincode
= options
.pincode
.get() != NULL
;
90 bool passkey
= options
.passkey
.get() != NULL
;
92 if (!response
&& !pincode
&& !passkey
)
94 if (pincode
&& passkey
)
96 if (options
.response
!= bt_private::PAIRING_RESPONSE_CONFIRM
&&
100 // Check the BluetoothDevice is in expecting the correct response.
101 if (!device
->ExpectingConfirmation() && !device
->ExpectingPinCode() &&
102 !device
->ExpectingPasskey())
104 if (pincode
&& !device
->ExpectingPinCode())
106 if (passkey
&& !device
->ExpectingPasskey())
108 if (options
.response
== bt_private::PAIRING_RESPONSE_CONFIRM
&& !pincode
&&
109 !passkey
&& !device
->ExpectingConfirmation())
117 BluetoothPrivateSetAdapterStateFunction::
118 BluetoothPrivateSetAdapterStateFunction() {}
120 BluetoothPrivateSetAdapterStateFunction::
121 ~BluetoothPrivateSetAdapterStateFunction() {}
123 bool BluetoothPrivateSetAdapterStateFunction::DoWork(
124 scoped_refptr
<device::BluetoothAdapter
> adapter
) {
125 scoped_ptr
<bt_private::SetAdapterState::Params
> params(
126 bt_private::SetAdapterState::Params::Create(*args_
));
127 EXTENSION_FUNCTION_VALIDATE(params
.get());
129 if (!adapter
->IsPresent()) {
130 SetError(kAdapterNotPresent
);
135 const bt_private::NewAdapterState
& new_state
= params
->adapter_state
;
137 // These properties are not owned.
138 std::string
* name
= new_state
.name
.get();
139 bool* powered
= new_state
.powered
.get();
140 bool* discoverable
= new_state
.discoverable
.get();
142 if (name
&& adapter
->GetName() != *name
) {
143 pending_properties_
.insert(kNameProperty
);
144 adapter
->SetName(*name
,
145 CreatePropertySetCallback(kNameProperty
),
146 CreatePropertyErrorCallback(kNameProperty
));
149 if (powered
&& adapter
->IsPowered() != *powered
) {
150 pending_properties_
.insert(kPoweredProperty
);
151 adapter
->SetPowered(*powered
,
152 CreatePropertySetCallback(kPoweredProperty
),
153 CreatePropertyErrorCallback(kPoweredProperty
));
156 if (discoverable
&& adapter
->IsDiscoverable() != *discoverable
) {
157 pending_properties_
.insert(kDiscoverableProperty
);
158 adapter
->SetDiscoverable(
160 CreatePropertySetCallback(kDiscoverableProperty
),
161 CreatePropertyErrorCallback(kDiscoverableProperty
));
164 if (pending_properties_
.empty())
170 BluetoothPrivateSetAdapterStateFunction::CreatePropertySetCallback(
171 const std::string
& property_name
) {
173 &BluetoothPrivateSetAdapterStateFunction::OnAdapterPropertySet
,
179 BluetoothPrivateSetAdapterStateFunction::CreatePropertyErrorCallback(
180 const std::string
& property_name
) {
182 &BluetoothPrivateSetAdapterStateFunction::OnAdapterPropertyError
,
187 void BluetoothPrivateSetAdapterStateFunction::OnAdapterPropertySet(
188 const std::string
& property
) {
189 DCHECK(pending_properties_
.find(property
) != pending_properties_
.end());
190 DCHECK(failed_properties_
.find(property
) == failed_properties_
.end());
192 pending_properties_
.erase(property
);
193 if (pending_properties_
.empty()) {
194 if (failed_properties_
.empty())
201 void BluetoothPrivateSetAdapterStateFunction::OnAdapterPropertyError(
202 const std::string
& property
) {
203 DCHECK(pending_properties_
.find(property
) != pending_properties_
.end());
204 DCHECK(failed_properties_
.find(property
) == failed_properties_
.end());
206 pending_properties_
.erase(property
);
207 failed_properties_
.insert(property
);
208 if (pending_properties_
.empty())
212 void BluetoothPrivateSetAdapterStateFunction::SendError() {
213 DCHECK(pending_properties_
.empty());
214 DCHECK(!failed_properties_
.empty());
216 std::vector
<std::string
> failed_vector
;
217 std::copy(failed_properties_
.begin(),
218 failed_properties_
.end(),
219 std::back_inserter(failed_vector
));
221 std::vector
<std::string
> replacements(1);
222 replacements
[0] = JoinString(failed_vector
, ", ");
224 ReplaceStringPlaceholders(kSetAdapterPropertyError
, replacements
, NULL
);
229 BluetoothPrivateSetPairingResponseFunction::
230 BluetoothPrivateSetPairingResponseFunction() {}
232 BluetoothPrivateSetPairingResponseFunction::
233 ~BluetoothPrivateSetPairingResponseFunction() {}
235 bool BluetoothPrivateSetPairingResponseFunction::DoWork(
236 scoped_refptr
<device::BluetoothAdapter
> adapter
) {
237 scoped_ptr
<bt_private::SetPairingResponse::Params
> params(
238 bt_private::SetPairingResponse::Params::Create(*args_
));
239 EXTENSION_FUNCTION_VALIDATE(params
.get());
240 const bt_private::SetPairingResponseOptions
& options
= params
->options
;
242 BluetoothEventRouter
* router
=
243 BluetoothAPI::Get(browser_context())->event_router();
244 if (!router
->GetPairingDelegate(extension_id())) {
245 SetError(kPairingNotEnabled
);
250 const std::string
& device_address
= options
.device
.address
;
251 device::BluetoothDevice
* device
= adapter
->GetDevice(device_address
);
253 SetError(kDeviceNotFoundError
);
258 if (!ValidatePairingResponseOptions(device
, options
)) {
259 SetError(kInvalidPairingResponseOptions
);
264 if (options
.pincode
.get()) {
265 device
->SetPinCode(*options
.pincode
.get());
266 } else if (options
.passkey
.get()) {
267 device
->SetPasskey(*options
.passkey
.get());
269 switch (options
.response
) {
270 case bt_private::PAIRING_RESPONSE_CONFIRM
:
271 device
->ConfirmPairing();
273 case bt_private::PAIRING_RESPONSE_REJECT
:
274 device
->RejectPairing();
276 case bt_private::PAIRING_RESPONSE_CANCEL
:
277 device
->CancelPairing();
288 } // namespace core_api
290 } // namespace extensions