17d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
57d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "chromeos/dbus/bluetooth_agent_service_provider.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <string>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/logging.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/ref_counted.h"
124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/sys_info.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/threading/platform_thread.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/dbus/fake_bluetooth_agent_service_provider.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "dbus/bus.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "dbus/exported_object.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "dbus/message.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "dbus/object_path.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "third_party/cros_system_api/dbus/service_constants.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace chromeos {
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// The BluetoothAgentServiceProvider implementation used in production.
247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)class BluetoothAgentServiceProviderImpl
257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    : public BluetoothAgentServiceProvider {
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  BluetoothAgentServiceProviderImpl(dbus::Bus* bus,
287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                    const dbus::ObjectPath& object_path,
297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                    Delegate* delegate)
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : origin_thread_id_(base::PlatformThread::CurrentId()),
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        bus_(bus),
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        delegate_(delegate),
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        object_path_(object_path),
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        weak_ptr_factory_(this) {
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    VLOG(1) << "Creating Bluetooth Agent: " << object_path_.value();
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    exported_object_ = bus_->GetExportedObject(object_path_);
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    exported_object_->ExportMethod(
40868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        bluetooth_agent::kBluetoothAgentInterface,
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        bluetooth_agent::kRelease,
427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        base::Bind(&BluetoothAgentServiceProviderImpl::Release,
437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        base::Bind(&BluetoothAgentServiceProviderImpl::OnExported,
457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    exported_object_->ExportMethod(
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        bluetooth_agent::kBluetoothAgentInterface,
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        bluetooth_agent::kRequestPinCode,
507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        base::Bind(&BluetoothAgentServiceProviderImpl::RequestPinCode,
517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        base::Bind(&BluetoothAgentServiceProviderImpl::OnExported,
537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    exported_object_->ExportMethod(
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        bluetooth_agent::kBluetoothAgentInterface,
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        bluetooth_agent::kDisplayPinCode,
587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        base::Bind(&BluetoothAgentServiceProviderImpl::DisplayPinCode,
597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        base::Bind(&BluetoothAgentServiceProviderImpl::OnExported,
617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    exported_object_->ExportMethod(
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        bluetooth_agent::kBluetoothAgentInterface,
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        bluetooth_agent::kRequestPasskey,
667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        base::Bind(&BluetoothAgentServiceProviderImpl::RequestPasskey,
677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        base::Bind(&BluetoothAgentServiceProviderImpl::OnExported,
697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    exported_object_->ExportMethod(
72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        bluetooth_agent::kBluetoothAgentInterface,
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        bluetooth_agent::kDisplayPasskey,
747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        base::Bind(&BluetoothAgentServiceProviderImpl::DisplayPasskey,
757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        base::Bind(&BluetoothAgentServiceProviderImpl::OnExported,
777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    exported_object_->ExportMethod(
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        bluetooth_agent::kBluetoothAgentInterface,
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        bluetooth_agent::kRequestConfirmation,
827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        base::Bind(&BluetoothAgentServiceProviderImpl::RequestConfirmation,
837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        base::Bind(&BluetoothAgentServiceProviderImpl::OnExported,
857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    exported_object_->ExportMethod(
88868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        bluetooth_agent::kBluetoothAgentInterface,
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        bluetooth_agent::kRequestAuthorization,
907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        base::Bind(&BluetoothAgentServiceProviderImpl::RequestAuthorization,
917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        base::Bind(&BluetoothAgentServiceProviderImpl::OnExported,
937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    exported_object_->ExportMethod(
96868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        bluetooth_agent::kBluetoothAgentInterface,
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        bluetooth_agent::kAuthorizeService,
987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        base::Bind(&BluetoothAgentServiceProviderImpl::AuthorizeService,
997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
1007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        base::Bind(&BluetoothAgentServiceProviderImpl::OnExported,
1017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    exported_object_->ExportMethod(
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        bluetooth_agent::kBluetoothAgentInterface,
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        bluetooth_agent::kCancel,
1067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        base::Bind(&BluetoothAgentServiceProviderImpl::Cancel,
1077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()),
1087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        base::Bind(&BluetoothAgentServiceProviderImpl::OnExported,
1097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  virtual ~BluetoothAgentServiceProviderImpl() {
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    VLOG(1) << "Cleaning up Bluetooth Agent: " << object_path_.value();
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Unregister the object path so we can reuse with a new agent.
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bus_->UnregisterExportedObject(object_path_);
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Returns true if the current thread is on the origin thread.
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool OnOriginThread() {
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return base::PlatformThread::CurrentId() == origin_thread_id_;
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Called by dbus:: when the agent is unregistered from the Bluetooth
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // daemon, generally at the end of a pairing request.
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void Release(dbus::MethodCall* method_call,
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)               dbus::ExportedObject::ResponseSender response_sender) {
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(OnOriginThread());
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(delegate_);
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    delegate_->Release();
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    response_sender.Run(dbus::Response::FromMethodCall(method_call));
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Called by dbus:: when the Bluetooth daemon requires a PIN Code for
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // device authentication.
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void RequestPinCode(dbus::MethodCall* method_call,
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      dbus::ExportedObject::ResponseSender response_sender) {
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(OnOriginThread());
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(delegate_);
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MessageReader reader(method_call);
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::ObjectPath device_path;
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!reader.PopObjectPath(&device_path)) {
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      LOG(WARNING) << "RequestPinCode called with incorrect paramters: "
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   << method_call->ToString();
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Delegate::PinCodeCallback callback = base::Bind(
1537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        &BluetoothAgentServiceProviderImpl::OnPinCode,
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        weak_ptr_factory_.GetWeakPtr(),
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        method_call,
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        response_sender);
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    delegate_->RequestPinCode(device_path, callback);
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Called by dbus:: when the Bluetooth daemon requires that the user
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // enter a PIN Code into the remote device so that it may be
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // authenticated.
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void DisplayPinCode(dbus::MethodCall* method_call,
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      dbus::ExportedObject::ResponseSender response_sender) {
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(OnOriginThread());
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(delegate_);
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MessageReader reader(method_call);
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::ObjectPath device_path;
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string pincode;
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!reader.PopObjectPath(&device_path) ||
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        !reader.PopString(&pincode)) {
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      LOG(WARNING) << "DisplayPinCode called with incorrect paramters: "
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   << method_call->ToString();
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    delegate_->DisplayPinCode(device_path, pincode);
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    response_sender.Run(dbus::Response::FromMethodCall(method_call));
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Called by dbus:: when the Bluetooth daemon requires a Passkey for
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // device authentication.
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void RequestPasskey(dbus::MethodCall* method_call,
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      dbus::ExportedObject::ResponseSender response_sender) {
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(OnOriginThread());
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(delegate_);
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MessageReader reader(method_call);
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::ObjectPath device_path;
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!reader.PopObjectPath(&device_path)) {
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      LOG(WARNING) << "RequestPasskey called with incorrect paramters: "
195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   << method_call->ToString();
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Delegate::PasskeyCallback callback = base::Bind(
2007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        &BluetoothAgentServiceProviderImpl::OnPasskey,
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        weak_ptr_factory_.GetWeakPtr(),
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        method_call,
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        response_sender);
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    delegate_->RequestPasskey(device_path, callback);
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Called by dbus:: when the Bluetooth daemon requires that the user
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // enter a Passkey into the remote device so that it may be
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // authenticated.
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void DisplayPasskey(dbus::MethodCall* method_call,
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      dbus::ExportedObject::ResponseSender response_sender) {
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(OnOriginThread());
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(delegate_);
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MessageReader reader(method_call);
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::ObjectPath device_path;
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    uint32 passkey;
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    uint16 entered;
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!reader.PopObjectPath(&device_path) ||
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        !reader.PopUint32(&passkey) ||
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        !reader.PopUint16(&entered)) {
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      LOG(WARNING) << "DisplayPasskey called with incorrect paramters: "
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   << method_call->ToString();
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    delegate_->DisplayPasskey(device_path, passkey, entered);
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    response_sender.Run(dbus::Response::FromMethodCall(method_call));
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Called by dbus:: when the Bluetooth daemon requires that the user
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // confirm that a Passkey is displayed on the screen of the remote
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // device so that it may be authenticated.
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void RequestConfirmation(
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      dbus::MethodCall* method_call,
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      dbus::ExportedObject::ResponseSender response_sender) {
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(OnOriginThread());
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(delegate_);
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MessageReader reader(method_call);
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::ObjectPath device_path;
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    uint32 passkey;
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!reader.PopObjectPath(&device_path) ||
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        !reader.PopUint32(&passkey)) {
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      LOG(WARNING) << "RequestConfirmation called with incorrect paramters: "
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   << method_call->ToString();
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Delegate::ConfirmationCallback callback = base::Bind(
2537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        &BluetoothAgentServiceProviderImpl::OnConfirmation,
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        weak_ptr_factory_.GetWeakPtr(),
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        method_call,
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        response_sender);
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    delegate_->RequestConfirmation(device_path, passkey, callback);
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Called by dbus:: when the Bluetooth daemon requires that the user
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // confirm an incoming just-works pairing.
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void RequestAuthorization(
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        dbus::MethodCall* method_call,
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        dbus::ExportedObject::ResponseSender response_sender) {
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(OnOriginThread());
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(delegate_);
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MessageReader reader(method_call);
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::ObjectPath device_path;
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!reader.PopObjectPath(&device_path)) {
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      LOG(WARNING) << "RequestAuthorization called with incorrect paramters: "
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   << method_call->ToString();
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Delegate::ConfirmationCallback callback = base::Bind(
2787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        &BluetoothAgentServiceProviderImpl::OnConfirmation,
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        weak_ptr_factory_.GetWeakPtr(),
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        method_call,
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        response_sender);
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    delegate_->RequestAuthorization(device_path, callback);
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Called by dbus:: when the Bluetooth daemon requires that the user
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // confirm that that a remote device is authorized to connect to a service
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // UUID.
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void AuthorizeService(dbus::MethodCall* method_call,
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        dbus::ExportedObject::ResponseSender response_sender) {
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(OnOriginThread());
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(delegate_);
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::MessageReader reader(method_call);
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    dbus::ObjectPath device_path;
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string uuid;
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!reader.PopObjectPath(&device_path) ||
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        !reader.PopString(&uuid)) {
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      LOG(WARNING) << "AuthorizeService called with incorrect paramters: "
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   << method_call->ToString();
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Delegate::ConfirmationCallback callback = base::Bind(
3057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        &BluetoothAgentServiceProviderImpl::OnConfirmation,
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        weak_ptr_factory_.GetWeakPtr(),
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        method_call,
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        response_sender);
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    delegate_->AuthorizeService(device_path, uuid, callback);
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Called by dbus:: when the request failed before a reply was returned
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // from the device.
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void Cancel(dbus::MethodCall* method_call,
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              dbus::ExportedObject::ResponseSender response_sender) {
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(OnOriginThread());
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(delegate_);
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    delegate_->Cancel();
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    response_sender.Run(dbus::Response::FromMethodCall(method_call));
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Called by dbus:: when a method is exported.
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void OnExported(const std::string& interface_name,
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                  const std::string& method_name,
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                  bool success) {
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG_IF(WARNING, !success) << "Failed to export "
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              << interface_name << "." << method_name;
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Called by the Delegate to response to a method requesting a PIN code.
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void OnPinCode(dbus::MethodCall* method_call,
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 dbus::ExportedObject::ResponseSender response_sender,
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 Delegate::Status status,
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 const std::string& pincode) {
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(OnOriginThread());
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    switch (status) {
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case Delegate::SUCCESS: {
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        scoped_ptr<dbus::Response> response(
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            dbus::Response::FromMethodCall(method_call));
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        dbus::MessageWriter writer(response.get());
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        writer.AppendString(pincode);
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        response_sender.Run(response.Pass());
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case Delegate::REJECTED: {
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        response_sender.Run(
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            dbus::ErrorResponse::FromMethodCall(
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                method_call, bluetooth_agent::kErrorRejected, "rejected")
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            .PassAs<dbus::Response>());
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case Delegate::CANCELLED: {
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        response_sender.Run(
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            dbus::ErrorResponse::FromMethodCall(
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                method_call, bluetooth_agent::kErrorCanceled, "canceled")
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            .PassAs<dbus::Response>());
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      default:
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        NOTREACHED() << "Unexpected status code from delegate: " << status;
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Called by the Delegate to response to a method requesting a Passkey.
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void OnPasskey(dbus::MethodCall* method_call,
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 dbus::ExportedObject::ResponseSender response_sender,
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 Delegate::Status status,
372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 uint32 passkey) {
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(OnOriginThread());
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    switch (status) {
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case Delegate::SUCCESS: {
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        scoped_ptr<dbus::Response> response(
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            dbus::Response::FromMethodCall(method_call));
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        dbus::MessageWriter writer(response.get());
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        writer.AppendUint32(passkey);
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        response_sender.Run(response.Pass());
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case Delegate::REJECTED: {
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        response_sender.Run(
386c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            dbus::ErrorResponse::FromMethodCall(
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                method_call, bluetooth_agent::kErrorRejected, "rejected")
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            .PassAs<dbus::Response>());
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case Delegate::CANCELLED: {
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        response_sender.Run(
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            dbus::ErrorResponse::FromMethodCall(
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                method_call, bluetooth_agent::kErrorCanceled, "canceled")
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            .PassAs<dbus::Response>());
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      default:
399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        NOTREACHED() << "Unexpected status code from delegate: " << status;
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Called by the Delegate in response to a method requiring confirmation.
404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void OnConfirmation(dbus::MethodCall* method_call,
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      dbus::ExportedObject::ResponseSender response_sender,
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      Delegate::Status status) {
407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(OnOriginThread());
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    switch (status) {
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case Delegate::SUCCESS: {
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        response_sender.Run(dbus::Response::FromMethodCall(method_call));
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case Delegate::REJECTED: {
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        response_sender.Run(
416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            dbus::ErrorResponse::FromMethodCall(
417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                method_call, bluetooth_agent::kErrorRejected, "rejected")
418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            .PassAs<dbus::Response>());
419c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
420c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
421c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case Delegate::CANCELLED: {
422c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        response_sender.Run(
423c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            dbus::ErrorResponse::FromMethodCall(
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                method_call, bluetooth_agent::kErrorCanceled, "canceled")
425c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            .PassAs<dbus::Response>());
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      default:
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        NOTREACHED() << "Unexpected status code from delegate: " << status;
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Origin thread (i.e. the UI thread in production).
434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::PlatformThreadId origin_thread_id_;
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // D-Bus bus object is exported on, not owned by this object and must
437c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // outlive it.
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dbus::Bus* bus_;
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // All incoming method calls are passed on to the Delegate and a callback
441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // passed to generate the reply. |delegate_| is generally the object that
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // owns this one, and must outlive it.
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Delegate* delegate_;
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // D-Bus object path of object we are exporting, kept so we can unregister
446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // again in our destructor.
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  dbus::ObjectPath object_path_;
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // D-Bus object we are exporting, owned by this object.
450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<dbus::ExportedObject> exported_object_;
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Weak pointer factory for generating 'this' pointers that might live longer
453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // than we do.
454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Note: This should remain the last member so it'll be destroyed and
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // invalidate its weak pointers before any other members are destroyed.
4567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::WeakPtrFactory<BluetoothAgentServiceProviderImpl> weak_ptr_factory_;
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(BluetoothAgentServiceProviderImpl);
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)BluetoothAgentServiceProvider::BluetoothAgentServiceProvider() {
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)BluetoothAgentServiceProvider::~BluetoothAgentServiceProvider() {
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
4687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)BluetoothAgentServiceProvider* BluetoothAgentServiceProvider::Create(
4697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    dbus::Bus* bus,
4707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const dbus::ObjectPath& object_path,
4717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    Delegate* delegate) {
4724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (base::SysInfo::IsRunningOnChromeOS()) {
4737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return new BluetoothAgentServiceProviderImpl(bus, object_path, delegate);
474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return new FakeBluetoothAgentServiceProvider(object_path, delegate);
476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace chromeos
480