Only fsync leveldb's directory when the manifest is being updated.
[chromium-blink-merge.git] / chromeos / dbus / experimental_bluetooth_agent_service_provider.cc
blob7ee45807d5d056c8e4488b0cfabc986f21dc478d
1 // Copyright (c) 2013 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/experimental_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 "chromeos/dbus/fake_bluetooth_agent_service_provider.h"
15 #include "dbus/bus.h"
16 #include "dbus/exported_object.h"
17 #include "dbus/message.h"
18 #include "dbus/object_path.h"
19 #include "third_party/cros_system_api/dbus/service_constants.h"
21 namespace chromeos {
23 // The ExperimentalBluetoothAgentServiceProvider implementation used in
24 // production.
25 class ExperimentalBluetoothAgentServiceProviderImpl
26 : public ExperimentalBluetoothAgentServiceProvider {
27 public:
28 ExperimentalBluetoothAgentServiceProviderImpl(
29 dbus::Bus* bus,
30 const dbus::ObjectPath& object_path,
31 Delegate* delegate)
32 : origin_thread_id_(base::PlatformThread::CurrentId()),
33 bus_(bus),
34 delegate_(delegate),
35 object_path_(object_path),
36 weak_ptr_factory_(this) {
37 VLOG(1) << "Creating Bluetooth Agent: " << object_path_.value();
39 exported_object_ = bus_->GetExportedObject(object_path_);
41 exported_object_->ExportMethod(
42 bluetooth_agent::kBluetoothAgentInterface,
43 bluetooth_agent::kRelease,
44 base::Bind(
45 &ExperimentalBluetoothAgentServiceProviderImpl::Release,
46 weak_ptr_factory_.GetWeakPtr()),
47 base::Bind(
48 &ExperimentalBluetoothAgentServiceProviderImpl::OnExported,
49 weak_ptr_factory_.GetWeakPtr()));
51 exported_object_->ExportMethod(
52 bluetooth_agent::kBluetoothAgentInterface,
53 bluetooth_agent::kRequestPinCode,
54 base::Bind(
55 &ExperimentalBluetoothAgentServiceProviderImpl::RequestPinCode,
56 weak_ptr_factory_.GetWeakPtr()),
57 base::Bind(
58 &ExperimentalBluetoothAgentServiceProviderImpl::OnExported,
59 weak_ptr_factory_.GetWeakPtr()));
61 exported_object_->ExportMethod(
62 bluetooth_agent::kBluetoothAgentInterface,
63 bluetooth_agent::kDisplayPinCode,
64 base::Bind(
65 &ExperimentalBluetoothAgentServiceProviderImpl::DisplayPinCode,
66 weak_ptr_factory_.GetWeakPtr()),
67 base::Bind(
68 &ExperimentalBluetoothAgentServiceProviderImpl::OnExported,
69 weak_ptr_factory_.GetWeakPtr()));
71 exported_object_->ExportMethod(
72 bluetooth_agent::kBluetoothAgentInterface,
73 bluetooth_agent::kRequestPasskey,
74 base::Bind(
75 &ExperimentalBluetoothAgentServiceProviderImpl::RequestPasskey,
76 weak_ptr_factory_.GetWeakPtr()),
77 base::Bind(
78 &ExperimentalBluetoothAgentServiceProviderImpl::OnExported,
79 weak_ptr_factory_.GetWeakPtr()));
81 exported_object_->ExportMethod(
82 bluetooth_agent::kBluetoothAgentInterface,
83 bluetooth_agent::kDisplayPasskey,
84 base::Bind(
85 &ExperimentalBluetoothAgentServiceProviderImpl::DisplayPasskey,
86 weak_ptr_factory_.GetWeakPtr()),
87 base::Bind(
88 &ExperimentalBluetoothAgentServiceProviderImpl::OnExported,
89 weak_ptr_factory_.GetWeakPtr()));
91 exported_object_->ExportMethod(
92 bluetooth_agent::kBluetoothAgentInterface,
93 bluetooth_agent::kRequestConfirmation,
94 base::Bind(
95 &ExperimentalBluetoothAgentServiceProviderImpl::RequestConfirmation,
96 weak_ptr_factory_.GetWeakPtr()),
97 base::Bind(
98 &ExperimentalBluetoothAgentServiceProviderImpl::OnExported,
99 weak_ptr_factory_.GetWeakPtr()));
101 exported_object_->ExportMethod(
102 bluetooth_agent::kBluetoothAgentInterface,
103 bluetooth_agent::kRequestAuthorization,
104 base::Bind(
105 &ExperimentalBluetoothAgentServiceProviderImpl::RequestAuthorization,
106 weak_ptr_factory_.GetWeakPtr()),
107 base::Bind(
108 &ExperimentalBluetoothAgentServiceProviderImpl::OnExported,
109 weak_ptr_factory_.GetWeakPtr()));
111 exported_object_->ExportMethod(
112 bluetooth_agent::kBluetoothAgentInterface,
113 bluetooth_agent::kAuthorizeService,
114 base::Bind(
115 &ExperimentalBluetoothAgentServiceProviderImpl::AuthorizeService,
116 weak_ptr_factory_.GetWeakPtr()),
117 base::Bind(
118 &ExperimentalBluetoothAgentServiceProviderImpl::OnExported,
119 weak_ptr_factory_.GetWeakPtr()));
121 exported_object_->ExportMethod(
122 bluetooth_agent::kBluetoothAgentInterface,
123 bluetooth_agent::kCancel,
124 base::Bind(
125 &ExperimentalBluetoothAgentServiceProviderImpl::Cancel,
126 weak_ptr_factory_.GetWeakPtr()),
127 base::Bind(
128 &ExperimentalBluetoothAgentServiceProviderImpl::OnExported,
129 weak_ptr_factory_.GetWeakPtr()));
132 virtual ~ExperimentalBluetoothAgentServiceProviderImpl() {
133 VLOG(1) << "Cleaning up Bluetooth Agent: " << object_path_.value();
135 // Unregister the object path so we can reuse with a new agent.
136 bus_->UnregisterExportedObject(object_path_);
139 private:
140 // Returns true if the current thread is on the origin thread.
141 bool OnOriginThread() {
142 return base::PlatformThread::CurrentId() == origin_thread_id_;
145 // Called by dbus:: when the agent is unregistered from the Bluetooth
146 // daemon, generally at the end of a pairing request.
147 void Release(dbus::MethodCall* method_call,
148 dbus::ExportedObject::ResponseSender response_sender) {
149 DCHECK(OnOriginThread());
150 DCHECK(delegate_);
152 delegate_->Release();
154 response_sender.Run(dbus::Response::FromMethodCall(method_call));
157 // Called by dbus:: when the Bluetooth daemon requires a PIN Code for
158 // device authentication.
159 void RequestPinCode(dbus::MethodCall* method_call,
160 dbus::ExportedObject::ResponseSender response_sender) {
161 DCHECK(OnOriginThread());
162 DCHECK(delegate_);
164 dbus::MessageReader reader(method_call);
165 dbus::ObjectPath device_path;
166 if (!reader.PopObjectPath(&device_path)) {
167 LOG(WARNING) << "RequestPinCode called with incorrect paramters: "
168 << method_call->ToString();
169 return;
172 Delegate::PinCodeCallback callback = base::Bind(
173 &ExperimentalBluetoothAgentServiceProviderImpl::OnPinCode,
174 weak_ptr_factory_.GetWeakPtr(),
175 method_call,
176 response_sender);
178 delegate_->RequestPinCode(device_path, callback);
181 // Called by dbus:: when the Bluetooth daemon requires that the user
182 // enter a PIN Code into the remote device so that it may be
183 // authenticated.
184 void DisplayPinCode(dbus::MethodCall* method_call,
185 dbus::ExportedObject::ResponseSender response_sender) {
186 DCHECK(OnOriginThread());
187 DCHECK(delegate_);
189 dbus::MessageReader reader(method_call);
190 dbus::ObjectPath device_path;
191 std::string pincode;
192 if (!reader.PopObjectPath(&device_path) ||
193 !reader.PopString(&pincode)) {
194 LOG(WARNING) << "DisplayPinCode called with incorrect paramters: "
195 << method_call->ToString();
196 return;
199 delegate_->DisplayPinCode(device_path, pincode);
201 response_sender.Run(dbus::Response::FromMethodCall(method_call));
204 // Called by dbus:: when the Bluetooth daemon requires a Passkey for
205 // device authentication.
206 void RequestPasskey(dbus::MethodCall* method_call,
207 dbus::ExportedObject::ResponseSender response_sender) {
208 DCHECK(OnOriginThread());
209 DCHECK(delegate_);
211 dbus::MessageReader reader(method_call);
212 dbus::ObjectPath device_path;
213 if (!reader.PopObjectPath(&device_path)) {
214 LOG(WARNING) << "RequestPasskey called with incorrect paramters: "
215 << method_call->ToString();
216 return;
219 Delegate::PasskeyCallback callback = base::Bind(
220 &ExperimentalBluetoothAgentServiceProviderImpl::OnPasskey,
221 weak_ptr_factory_.GetWeakPtr(),
222 method_call,
223 response_sender);
225 delegate_->RequestPasskey(device_path, callback);
228 // Called by dbus:: when the Bluetooth daemon requires that the user
229 // enter a Passkey into the remote device so that it may be
230 // authenticated.
231 void DisplayPasskey(dbus::MethodCall* method_call,
232 dbus::ExportedObject::ResponseSender response_sender) {
233 DCHECK(OnOriginThread());
234 DCHECK(delegate_);
236 dbus::MessageReader reader(method_call);
237 dbus::ObjectPath device_path;
238 uint32 passkey;
239 uint16 entered;
240 if (!reader.PopObjectPath(&device_path) ||
241 !reader.PopUint32(&passkey) ||
242 !reader.PopUint16(&entered)) {
243 LOG(WARNING) << "DisplayPasskey called with incorrect paramters: "
244 << method_call->ToString();
245 return;
248 delegate_->DisplayPasskey(device_path, passkey, entered);
250 response_sender.Run(dbus::Response::FromMethodCall(method_call));
253 // Called by dbus:: when the Bluetooth daemon requires that the user
254 // confirm that a Passkey is displayed on the screen of the remote
255 // device so that it may be authenticated.
256 void RequestConfirmation(
257 dbus::MethodCall* method_call,
258 dbus::ExportedObject::ResponseSender response_sender) {
259 DCHECK(OnOriginThread());
260 DCHECK(delegate_);
262 dbus::MessageReader reader(method_call);
263 dbus::ObjectPath device_path;
264 uint32 passkey;
265 if (!reader.PopObjectPath(&device_path) ||
266 !reader.PopUint32(&passkey)) {
267 LOG(WARNING) << "RequestConfirmation called with incorrect paramters: "
268 << method_call->ToString();
269 return;
272 Delegate::ConfirmationCallback callback = base::Bind(
273 &ExperimentalBluetoothAgentServiceProviderImpl::OnConfirmation,
274 weak_ptr_factory_.GetWeakPtr(),
275 method_call,
276 response_sender);
278 delegate_->RequestConfirmation(device_path, passkey, callback);
281 // Called by dbus:: when the Bluetooth daemon requires that the user
282 // confirm an incoming just-works pairing.
283 void RequestAuthorization(
284 dbus::MethodCall* method_call,
285 dbus::ExportedObject::ResponseSender response_sender) {
286 DCHECK(OnOriginThread());
287 DCHECK(delegate_);
289 dbus::MessageReader reader(method_call);
290 dbus::ObjectPath device_path;
291 if (!reader.PopObjectPath(&device_path)) {
292 LOG(WARNING) << "RequestAuthorization called with incorrect paramters: "
293 << method_call->ToString();
294 return;
297 Delegate::ConfirmationCallback callback = base::Bind(
298 &ExperimentalBluetoothAgentServiceProviderImpl::OnConfirmation,
299 weak_ptr_factory_.GetWeakPtr(),
300 method_call,
301 response_sender);
303 delegate_->RequestAuthorization(device_path, callback);
306 // Called by dbus:: when the Bluetooth daemon requires that the user
307 // confirm that that a remote device is authorized to connect to a service
308 // UUID.
309 void AuthorizeService(dbus::MethodCall* method_call,
310 dbus::ExportedObject::ResponseSender response_sender) {
311 DCHECK(OnOriginThread());
312 DCHECK(delegate_);
314 dbus::MessageReader reader(method_call);
315 dbus::ObjectPath device_path;
316 std::string uuid;
317 if (!reader.PopObjectPath(&device_path) ||
318 !reader.PopString(&uuid)) {
319 LOG(WARNING) << "AuthorizeService called with incorrect paramters: "
320 << method_call->ToString();
321 return;
324 Delegate::ConfirmationCallback callback = base::Bind(
325 &ExperimentalBluetoothAgentServiceProviderImpl::OnConfirmation,
326 weak_ptr_factory_.GetWeakPtr(),
327 method_call,
328 response_sender);
330 delegate_->AuthorizeService(device_path, uuid, callback);
333 // Called by dbus:: when the request failed before a reply was returned
334 // from the device.
335 void Cancel(dbus::MethodCall* method_call,
336 dbus::ExportedObject::ResponseSender response_sender) {
337 DCHECK(OnOriginThread());
338 DCHECK(delegate_);
340 delegate_->Cancel();
342 response_sender.Run(dbus::Response::FromMethodCall(method_call));
345 // Called by dbus:: when a method is exported.
346 void OnExported(const std::string& interface_name,
347 const std::string& method_name,
348 bool success) {
349 LOG_IF(WARNING, !success) << "Failed to export "
350 << interface_name << "." << method_name;
353 // Called by the Delegate to response to a method requesting a PIN code.
354 void OnPinCode(dbus::MethodCall* method_call,
355 dbus::ExportedObject::ResponseSender response_sender,
356 Delegate::Status status,
357 const std::string& pincode) {
358 DCHECK(OnOriginThread());
360 switch (status) {
361 case Delegate::SUCCESS: {
362 scoped_ptr<dbus::Response> response(
363 dbus::Response::FromMethodCall(method_call));
364 dbus::MessageWriter writer(response.get());
365 writer.AppendString(pincode);
366 response_sender.Run(response.Pass());
367 break;
369 case Delegate::REJECTED: {
370 response_sender.Run(
371 dbus::ErrorResponse::FromMethodCall(
372 method_call, bluetooth_agent::kErrorRejected, "rejected")
373 .PassAs<dbus::Response>());
374 break;
376 case Delegate::CANCELLED: {
377 response_sender.Run(
378 dbus::ErrorResponse::FromMethodCall(
379 method_call, bluetooth_agent::kErrorCanceled, "canceled")
380 .PassAs<dbus::Response>());
381 break;
383 default:
384 NOTREACHED() << "Unexpected status code from delegate: " << status;
388 // Called by the Delegate to response to a method requesting a Passkey.
389 void OnPasskey(dbus::MethodCall* method_call,
390 dbus::ExportedObject::ResponseSender response_sender,
391 Delegate::Status status,
392 uint32 passkey) {
393 DCHECK(OnOriginThread());
395 switch (status) {
396 case Delegate::SUCCESS: {
397 scoped_ptr<dbus::Response> response(
398 dbus::Response::FromMethodCall(method_call));
399 dbus::MessageWriter writer(response.get());
400 writer.AppendUint32(passkey);
401 response_sender.Run(response.Pass());
402 break;
404 case Delegate::REJECTED: {
405 response_sender.Run(
406 dbus::ErrorResponse::FromMethodCall(
407 method_call, bluetooth_agent::kErrorRejected, "rejected")
408 .PassAs<dbus::Response>());
409 break;
411 case Delegate::CANCELLED: {
412 response_sender.Run(
413 dbus::ErrorResponse::FromMethodCall(
414 method_call, bluetooth_agent::kErrorCanceled, "canceled")
415 .PassAs<dbus::Response>());
416 break;
418 default:
419 NOTREACHED() << "Unexpected status code from delegate: " << status;
423 // Called by the Delegate in response to a method requiring confirmation.
424 void OnConfirmation(dbus::MethodCall* method_call,
425 dbus::ExportedObject::ResponseSender response_sender,
426 Delegate::Status status) {
427 DCHECK(OnOriginThread());
429 switch (status) {
430 case Delegate::SUCCESS: {
431 response_sender.Run(dbus::Response::FromMethodCall(method_call));
432 break;
434 case Delegate::REJECTED: {
435 response_sender.Run(
436 dbus::ErrorResponse::FromMethodCall(
437 method_call, bluetooth_agent::kErrorRejected, "rejected")
438 .PassAs<dbus::Response>());
439 break;
441 case Delegate::CANCELLED: {
442 response_sender.Run(
443 dbus::ErrorResponse::FromMethodCall(
444 method_call, bluetooth_agent::kErrorCanceled, "canceled")
445 .PassAs<dbus::Response>());
446 break;
448 default:
449 NOTREACHED() << "Unexpected status code from delegate: " << status;
453 // Origin thread (i.e. the UI thread in production).
454 base::PlatformThreadId origin_thread_id_;
456 // D-Bus bus object is exported on, not owned by this object and must
457 // outlive it.
458 dbus::Bus* bus_;
460 // All incoming method calls are passed on to the Delegate and a callback
461 // passed to generate the reply. |delegate_| is generally the object that
462 // owns this one, and must outlive it.
463 Delegate* delegate_;
465 // D-Bus object path of object we are exporting, kept so we can unregister
466 // again in our destructor.
467 dbus::ObjectPath object_path_;
469 // D-Bus object we are exporting, owned by this object.
470 scoped_refptr<dbus::ExportedObject> exported_object_;
472 // Weak pointer factory for generating 'this' pointers that might live longer
473 // than we do.
474 // Note: This should remain the last member so it'll be destroyed and
475 // invalidate its weak pointers before any other members are destroyed.
476 base::WeakPtrFactory<ExperimentalBluetoothAgentServiceProviderImpl>
477 weak_ptr_factory_;
479 DISALLOW_COPY_AND_ASSIGN(ExperimentalBluetoothAgentServiceProviderImpl);
482 ExperimentalBluetoothAgentServiceProvider::
483 ExperimentalBluetoothAgentServiceProvider() {
486 ExperimentalBluetoothAgentServiceProvider::
487 ~ExperimentalBluetoothAgentServiceProvider() {
490 // static
491 ExperimentalBluetoothAgentServiceProvider*
492 ExperimentalBluetoothAgentServiceProvider::Create(
493 dbus::Bus* bus,
494 const dbus::ObjectPath& object_path,
495 Delegate* delegate) {
496 if (base::chromeos::IsRunningOnChromeOS()) {
497 return new ExperimentalBluetoothAgentServiceProviderImpl(
498 bus, object_path, delegate);
499 } else {
500 return new FakeBluetoothAgentServiceProvider(object_path, delegate);
504 } // namespace chromeos