Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / chromeos / dbus / bluetooth_agent_service_provider.cc
blob786935c25f38c393506d4db5393f5bc426d12014
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.
5 #include "chromeos/dbus/bluetooth_agent_service_provider.h"
7 #include <string>
9 #include "base/bind.h"
10 #include "base/chromeos/chromeos_version.h"
11 #include "base/logging.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/threading/platform_thread.h"
14 #include "dbus/bus.h"
15 #include "dbus/exported_object.h"
16 #include "dbus/message.h"
17 #include "dbus/object_path.h"
18 #include "third_party/cros_system_api/dbus/service_constants.h"
20 namespace {
22 // Constants used by BlueZ for the ConfirmModeChange method.
23 const char kModeOff[] = "off";
24 const char kModeConnectable[] = "connectable";
25 const char kModeDiscoverable[] = "discoverable";
27 } // namespace
29 namespace chromeos {
31 // The BluetoothAgentServiceProvider implementation used in production.
32 class BluetoothAgentServiceProviderImpl : public BluetoothAgentServiceProvider {
33 public:
34 BluetoothAgentServiceProviderImpl(dbus::Bus* bus,
35 const dbus::ObjectPath& object_path,
36 Delegate* delegate)
37 : origin_thread_id_(base::PlatformThread::CurrentId()),
38 bus_(bus),
39 delegate_(delegate),
40 object_path_(object_path),
41 weak_ptr_factory_(this) {
42 VLOG(1) << "Creating BluetoothAdapterClientImpl for "
43 << object_path.value();
45 exported_object_ = bus_->GetExportedObject(object_path_);
47 exported_object_->ExportMethod(
48 bluetooth_agent::kBluetoothAgentInterface,
49 bluetooth_agent::kRelease,
50 base::Bind(&BluetoothAgentServiceProviderImpl::Release,
51 weak_ptr_factory_.GetWeakPtr()),
52 base::Bind(&BluetoothAgentServiceProviderImpl::ReleaseExported,
53 weak_ptr_factory_.GetWeakPtr()));
55 exported_object_->ExportMethod(
56 bluetooth_agent::kBluetoothAgentInterface,
57 bluetooth_agent::kRequestPinCode,
58 base::Bind(&BluetoothAgentServiceProviderImpl::RequestPinCode,
59 weak_ptr_factory_.GetWeakPtr()),
60 base::Bind(&BluetoothAgentServiceProviderImpl::RequestPinCodeExported,
61 weak_ptr_factory_.GetWeakPtr()));
63 exported_object_->ExportMethod(
64 bluetooth_agent::kBluetoothAgentInterface,
65 bluetooth_agent::kRequestPasskey,
66 base::Bind(&BluetoothAgentServiceProviderImpl::RequestPasskey,
67 weak_ptr_factory_.GetWeakPtr()),
68 base::Bind(&BluetoothAgentServiceProviderImpl::RequestPasskeyExported,
69 weak_ptr_factory_.GetWeakPtr()));
71 exported_object_->ExportMethod(
72 bluetooth_agent::kBluetoothAgentInterface,
73 bluetooth_agent::kDisplayPinCode,
74 base::Bind(&BluetoothAgentServiceProviderImpl::DisplayPinCode,
75 weak_ptr_factory_.GetWeakPtr()),
76 base::Bind(&BluetoothAgentServiceProviderImpl::DisplayPinCodeExported,
77 weak_ptr_factory_.GetWeakPtr()));
79 exported_object_->ExportMethod(
80 bluetooth_agent::kBluetoothAgentInterface,
81 bluetooth_agent::kDisplayPasskey,
82 base::Bind(&BluetoothAgentServiceProviderImpl::DisplayPasskey,
83 weak_ptr_factory_.GetWeakPtr()),
84 base::Bind(&BluetoothAgentServiceProviderImpl::DisplayPasskeyExported,
85 weak_ptr_factory_.GetWeakPtr()));
87 exported_object_->ExportMethod(
88 bluetooth_agent::kBluetoothAgentInterface,
89 bluetooth_agent::kRequestConfirmation,
90 base::Bind(&BluetoothAgentServiceProviderImpl::RequestConfirmation,
91 weak_ptr_factory_.GetWeakPtr()),
92 base::Bind(
93 &BluetoothAgentServiceProviderImpl::RequestConfirmationExported,
94 weak_ptr_factory_.GetWeakPtr()));
96 exported_object_->ExportMethod(
97 bluetooth_agent::kBluetoothAgentInterface,
98 bluetooth_agent::kAuthorize,
99 base::Bind(&BluetoothAgentServiceProviderImpl::Authorize,
100 weak_ptr_factory_.GetWeakPtr()),
101 base::Bind(&BluetoothAgentServiceProviderImpl::AuthorizeExported,
102 weak_ptr_factory_.GetWeakPtr()));
104 exported_object_->ExportMethod(
105 bluetooth_agent::kBluetoothAgentInterface,
106 bluetooth_agent::kConfirmModeChange,
107 base::Bind(&BluetoothAgentServiceProviderImpl::ConfirmModeChange,
108 weak_ptr_factory_.GetWeakPtr()),
109 base::Bind(
110 &BluetoothAgentServiceProviderImpl::ConfirmModeChangeExported,
111 weak_ptr_factory_.GetWeakPtr()));
113 exported_object_->ExportMethod(
114 bluetooth_agent::kBluetoothAgentInterface,
115 bluetooth_agent::kCancel,
116 base::Bind(&BluetoothAgentServiceProviderImpl::Cancel,
117 weak_ptr_factory_.GetWeakPtr()),
118 base::Bind(&BluetoothAgentServiceProviderImpl::CancelExported,
119 weak_ptr_factory_.GetWeakPtr()));
122 virtual ~BluetoothAgentServiceProviderImpl() {
123 // Unregister the object path so we can reuse with a new agent.
124 bus_->UnregisterExportedObject(object_path_);
127 private:
128 // Returns true if the current thread is on the origin thread.
129 bool OnOriginThread() {
130 return base::PlatformThread::CurrentId() == origin_thread_id_;
133 // Called by dbus:: when the agent is unregistered from the Bluetooth
134 // daemon, generally at the end of a pairing request.
135 void Release(dbus::MethodCall* method_call,
136 dbus::ExportedObject::ResponseSender response_sender) {
137 DCHECK(OnOriginThread());
138 DCHECK(delegate_);
140 delegate_->Release();
142 response_sender.Run(dbus::Response::FromMethodCall(method_call));
145 // Called by dbus:: when the Release method is exported.
146 void ReleaseExported(const std::string& interface_name,
147 const std::string& method_name,
148 bool success) {
149 LOG_IF(WARNING, !success) << "Failed to export "
150 << interface_name << "." << method_name;
153 // Called by dbus:: when the Bluetooth daemon requires a PIN Code for
154 // device authentication.
155 void RequestPinCode(dbus::MethodCall* method_call,
156 dbus::ExportedObject::ResponseSender response_sender) {
157 DCHECK(OnOriginThread());
158 DCHECK(delegate_);
160 dbus::MessageReader reader(method_call);
161 dbus::ObjectPath device_path;
162 if (!reader.PopObjectPath(&device_path)) {
163 LOG(WARNING) << "RequestPinCode called with incorrect paramters: "
164 << method_call->ToString();
165 return;
168 Delegate::PinCodeCallback callback = base::Bind(
169 &BluetoothAgentServiceProviderImpl::OnPinCode,
170 weak_ptr_factory_.GetWeakPtr(),
171 method_call,
172 response_sender);
174 delegate_->RequestPinCode(device_path, callback);
177 // Called by dbus:: when the RequestPinCode method is exported.
178 void RequestPinCodeExported(const std::string& interface_name,
179 const std::string& method_name,
180 bool success) {
181 LOG_IF(WARNING, !success) << "Failed to export "
182 << interface_name << "." << method_name;
185 // Called by dbus:: when the Bluetooth daemon requires a Passkey for
186 // device authentication.
187 void RequestPasskey(dbus::MethodCall* method_call,
188 dbus::ExportedObject::ResponseSender response_sender) {
189 DCHECK(OnOriginThread());
190 DCHECK(delegate_);
192 dbus::MessageReader reader(method_call);
193 dbus::ObjectPath device_path;
194 if (!reader.PopObjectPath(&device_path)) {
195 LOG(WARNING) << "RequestPasskey called with incorrect paramters: "
196 << method_call->ToString();
197 return;
200 Delegate::PasskeyCallback callback = base::Bind(
201 &BluetoothAgentServiceProviderImpl::OnPasskey,
202 weak_ptr_factory_.GetWeakPtr(),
203 method_call,
204 response_sender);
206 delegate_->RequestPasskey(device_path, callback);
209 // Called by dbus:: when the RequestPasskey method is exported.
210 void RequestPasskeyExported(const std::string& interface_name,
211 const std::string& method_name,
212 bool success) {
213 LOG_IF(WARNING, !success) << "Failed to export "
214 << interface_name << "." << method_name;
217 // Called by dbus:: when the Bluetooth daemon requires that the user
218 // enter a PIN Code into the remote device so that it may be
219 // authenticated.
220 void DisplayPinCode(dbus::MethodCall* method_call,
221 dbus::ExportedObject::ResponseSender response_sender) {
222 DCHECK(OnOriginThread());
223 DCHECK(delegate_);
225 dbus::MessageReader reader(method_call);
226 dbus::ObjectPath device_path;
227 std::string pincode;
228 if (!reader.PopObjectPath(&device_path) ||
229 !reader.PopString(&pincode)) {
230 LOG(WARNING) << "DisplayPinCode called with incorrect paramters: "
231 << method_call->ToString();
232 return;
235 delegate_->DisplayPinCode(device_path, pincode);
237 response_sender.Run(dbus::Response::FromMethodCall(method_call));
240 // Called by dbus:: when the DisplayPinCode method is exported.
241 void DisplayPinCodeExported(const std::string& interface_name,
242 const std::string& method_name,
243 bool success) {
244 LOG_IF(WARNING, !success) << "Failed to export "
245 << interface_name << "." << method_name;
248 // Called by dbus:: when the Bluetooth daemon requires that the user
249 // enter a Passkey into the remote device so that it may be
250 // authenticated.
251 void DisplayPasskey(dbus::MethodCall* method_call,
252 dbus::ExportedObject::ResponseSender response_sender) {
253 DCHECK(OnOriginThread());
254 DCHECK(delegate_);
256 dbus::MessageReader reader(method_call);
257 dbus::ObjectPath device_path;
258 uint32 passkey;
259 if (!reader.PopObjectPath(&device_path) ||
260 !reader.PopUint32(&passkey)) {
261 LOG(WARNING) << "DisplayPasskey called with incorrect paramters: "
262 << method_call->ToString();
263 return;
266 delegate_->DisplayPasskey(device_path, passkey);
268 response_sender.Run(dbus::Response::FromMethodCall(method_call));
271 // Called by dbus:: when the DisplayPasskey method is exported.
272 void DisplayPasskeyExported(const std::string& interface_name,
273 const std::string& method_name,
274 bool success) {
275 LOG_IF(WARNING, !success) << "Failed to export "
276 << interface_name << "." << method_name;
279 // Called by dbus:: when the Bluetooth daemon requires that the user
280 // confirm that a Passkey is displayed on the screen of the remote
281 // device so that it may be authenticated.
282 void RequestConfirmation(
283 dbus::MethodCall* method_call,
284 dbus::ExportedObject::ResponseSender response_sender) {
285 DCHECK(OnOriginThread());
286 DCHECK(delegate_);
288 dbus::MessageReader reader(method_call);
289 dbus::ObjectPath device_path;
290 uint32 passkey;
291 if (!reader.PopObjectPath(&device_path) ||
292 !reader.PopUint32(&passkey)) {
293 LOG(WARNING) << "RequestConfirmation called with incorrect paramters: "
294 << method_call->ToString();
295 return;
298 Delegate::ConfirmationCallback callback = base::Bind(
299 &BluetoothAgentServiceProviderImpl::OnConfirmation,
300 weak_ptr_factory_.GetWeakPtr(),
301 method_call,
302 response_sender);
304 delegate_->RequestConfirmation(device_path, passkey, callback);
307 // Called by dbus:: when the RequestConfirmation method is exported.
308 void RequestConfirmationExported(const std::string& interface_name,
309 const std::string& method_name,
310 bool success) {
311 LOG_IF(WARNING, !success) << "Failed to export "
312 << interface_name << "." << method_name;
315 // Called by dbus:: when the Bluetooth daemon requires that the user
316 // confirm that that a remote device is authorized to connect to a service
317 // UUID.
318 void Authorize(dbus::MethodCall* method_call,
319 dbus::ExportedObject::ResponseSender response_sender) {
320 DCHECK(OnOriginThread());
321 DCHECK(delegate_);
323 dbus::MessageReader reader(method_call);
324 dbus::ObjectPath device_path;
325 std::string uuid;
326 if (!reader.PopObjectPath(&device_path) ||
327 !reader.PopString(&uuid)) {
328 LOG(WARNING) << "Authorize called with incorrect paramters: "
329 << method_call->ToString();
330 return;
333 Delegate::ConfirmationCallback callback = base::Bind(
334 &BluetoothAgentServiceProviderImpl::OnConfirmation,
335 weak_ptr_factory_.GetWeakPtr(),
336 method_call,
337 response_sender);
339 delegate_->Authorize(device_path, uuid, callback);
342 // Called by dbus:: when the Authorize method is exported.
343 void AuthorizeExported(const std::string& interface_name,
344 const std::string& method_name,
345 bool success) {
346 LOG_IF(WARNING, !success) << "Failed to export "
347 << interface_name << "." << method_name;
350 // Called by dbus:: when the Bluetooth daemon requires that the user
351 // confirm that the adapter may change mode.
352 void ConfirmModeChange(dbus::MethodCall* method_call,
353 dbus::ExportedObject::ResponseSender response_sender) {
354 DCHECK(OnOriginThread());
355 DCHECK(delegate_);
357 dbus::MessageReader reader(method_call);
358 std::string mode_str;
359 if (!reader.PopString(&mode_str)) {
360 LOG(WARNING) << "ConfirmModeChange called with incorrect paramters: "
361 << method_call->ToString();
362 return;
365 Delegate::Mode mode;
366 if (mode_str == kModeOff) {
367 mode = Delegate::OFF;
368 } else if (mode_str == kModeConnectable) {
369 mode = Delegate::CONNECTABLE;
370 } else if (mode_str == kModeDiscoverable) {
371 mode = Delegate::DISCOVERABLE;
372 } else {
373 LOG(WARNING) << "ConfirmModeChange called with unknown mode: "
374 << mode_str;
375 return;
378 Delegate::ConfirmationCallback callback = base::Bind(
379 &BluetoothAgentServiceProviderImpl::OnConfirmation,
380 weak_ptr_factory_.GetWeakPtr(),
381 method_call,
382 response_sender);
384 delegate_->ConfirmModeChange(mode, callback);
387 // Called by dbus:: when the ConfirmModeChange method is exported.
388 void ConfirmModeChangeExported(const std::string& interface_name,
389 const std::string& method_name,
390 bool success) {
391 LOG_IF(WARNING, !success) << "Failed to export "
392 << interface_name << "." << method_name;
395 // Called by dbus:: when the request failed before a reply was returned
396 // from the device.
397 void Cancel(dbus::MethodCall* method_call,
398 dbus::ExportedObject::ResponseSender response_sender) {
399 DCHECK(OnOriginThread());
400 DCHECK(delegate_);
402 delegate_->Cancel();
404 response_sender.Run(dbus::Response::FromMethodCall(method_call));
407 // Called by dbus:: when the Cancel method is exported.
408 void CancelExported(const std::string& interface_name,
409 const std::string& method_name,
410 bool success) {
411 LOG_IF(WARNING, !success) << "Failed to export "
412 << interface_name << "." << method_name;
415 // Called by the Delegate to response to a method requesting a PIN code.
416 void OnPinCode(dbus::MethodCall* method_call,
417 dbus::ExportedObject::ResponseSender response_sender,
418 Delegate::Status status,
419 const std::string& pincode) {
420 DCHECK(OnOriginThread());
422 switch (status) {
423 case Delegate::SUCCESS: {
424 scoped_ptr<dbus::Response> response(
425 dbus::Response::FromMethodCall(method_call));
426 dbus::MessageWriter writer(response.get());
427 writer.AppendString(pincode);
428 response_sender.Run(response.Pass());
429 break;
431 case Delegate::REJECTED: {
432 response_sender.Run(
433 dbus::ErrorResponse::FromMethodCall(
434 method_call, bluetooth_agent::kErrorRejected, "rejected")
435 .PassAs<dbus::Response>());
436 break;
438 case Delegate::CANCELLED: {
439 response_sender.Run(
440 dbus::ErrorResponse::FromMethodCall(
441 method_call, bluetooth_agent::kErrorCanceled, "canceled")
442 .PassAs<dbus::Response>());
443 break;
445 default:
446 NOTREACHED() << "Unexpected status code from delegate: " << status;
450 // Called by the Delegate to response to a method requesting a Passkey.
451 void OnPasskey(dbus::MethodCall* method_call,
452 dbus::ExportedObject::ResponseSender response_sender,
453 Delegate::Status status,
454 uint32 passkey) {
455 DCHECK(OnOriginThread());
457 switch (status) {
458 case Delegate::SUCCESS: {
459 scoped_ptr<dbus::Response> response(
460 dbus::Response::FromMethodCall(method_call));
461 dbus::MessageWriter writer(response.get());
462 writer.AppendUint32(passkey);
463 response_sender.Run(response.Pass());
464 break;
466 case Delegate::REJECTED: {
467 response_sender.Run(
468 dbus::ErrorResponse::FromMethodCall(
469 method_call, bluetooth_agent::kErrorRejected, "rejected")
470 .PassAs<dbus::Response>());
471 break;
473 case Delegate::CANCELLED: {
474 response_sender.Run(
475 dbus::ErrorResponse::FromMethodCall(
476 method_call, bluetooth_agent::kErrorCanceled, "canceled")
477 .PassAs<dbus::Response>());
478 break;
480 default:
481 NOTREACHED() << "Unexpected status code from delegate: " << status;
485 // Called by the Delegate in response to a method requiring confirmation.
486 void OnConfirmation(dbus::MethodCall* method_call,
487 dbus::ExportedObject::ResponseSender response_sender,
488 Delegate::Status status) {
489 DCHECK(OnOriginThread());
491 switch (status) {
492 case Delegate::SUCCESS: {
493 response_sender.Run(dbus::Response::FromMethodCall(method_call));
494 break;
496 case Delegate::REJECTED: {
497 response_sender.Run(
498 dbus::ErrorResponse::FromMethodCall(
499 method_call, bluetooth_agent::kErrorRejected, "rejected")
500 .PassAs<dbus::Response>());
501 break;
503 case Delegate::CANCELLED: {
504 response_sender.Run(
505 dbus::ErrorResponse::FromMethodCall(
506 method_call, bluetooth_agent::kErrorCanceled, "canceled")
507 .PassAs<dbus::Response>());
508 break;
510 default:
511 NOTREACHED() << "Unexpected status code from delegate: " << status;
515 // Origin thread (i.e. the UI thread in production).
516 base::PlatformThreadId origin_thread_id_;
518 // D-Bus bus object is exported on, not owned by this object and must
519 // outlive it.
520 dbus::Bus* bus_;
522 // All incoming method calls are passed on to the Delegate and a callback
523 // passed to generate the reply. |delegate_| is generally the object that
524 // owns this one, and must outlive it.
525 Delegate* delegate_;
527 // D-Bus object path of object we are exporting, kept so we can unregister
528 // again in our destructor.
529 dbus::ObjectPath object_path_;
531 // D-Bus object we are exporting, owned by this object.
532 scoped_refptr<dbus::ExportedObject> exported_object_;
534 // Weak pointer factory for generating 'this' pointers that might live longer
535 // than we do.
536 // Note: This should remain the last member so it'll be destroyed and
537 // invalidate its weak pointers before any other members are destroyed.
538 base::WeakPtrFactory<BluetoothAgentServiceProviderImpl> weak_ptr_factory_;
540 DISALLOW_COPY_AND_ASSIGN(BluetoothAgentServiceProviderImpl);
543 // The BluetoothAgentServiceProvider implementation used on Linux desktop,
544 // which does nothing.
545 class BluetoothAgentServiceProviderStubImpl
546 : public BluetoothAgentServiceProvider {
547 public:
548 explicit BluetoothAgentServiceProviderStubImpl(Delegate* delegate_) {
551 virtual ~BluetoothAgentServiceProviderStubImpl() {
555 BluetoothAgentServiceProvider::BluetoothAgentServiceProvider() {
558 BluetoothAgentServiceProvider::~BluetoothAgentServiceProvider() {
561 // static
562 BluetoothAgentServiceProvider* BluetoothAgentServiceProvider::Create(
563 dbus::Bus* bus,
564 const dbus::ObjectPath& object_path,
565 Delegate* delegate) {
566 if (base::chromeos::IsRunningOnChromeOS()) {
567 return new BluetoothAgentServiceProviderImpl(bus, object_path, delegate);
568 } else {
569 return new BluetoothAgentServiceProviderStubImpl(delegate);
573 } // namespace chromeos