| // Copyright 2020 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "biod/biod_proxy/biometrics_manager_proxy_base.h" |
| |
| #include <memory> |
| #include <string> |
| #include <utility> |
| |
| #include <base/bind.h> |
| #include <base/logging.h> |
| #include <base/memory/ptr_util.h> |
| #include <chromeos/dbus/service_constants.h> |
| |
| namespace biod { |
| |
| static const int kDbusTimeoutMs = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT; |
| |
| using FinishCallback = base::RepeatingCallback<void(bool success)>; |
| |
| const char* ScanResultToString(ScanResult result) { |
| switch (result) { |
| case ScanResult::SCAN_RESULT_SUCCESS: |
| return "Success"; |
| case ScanResult::SCAN_RESULT_PARTIAL: |
| return "Partial"; |
| case ScanResult::SCAN_RESULT_INSUFFICIENT: |
| return "Insufficient"; |
| case ScanResult::SCAN_RESULT_SENSOR_DIRTY: |
| return "Sensor Dirty"; |
| case ScanResult::SCAN_RESULT_TOO_SLOW: |
| return "Too Slow"; |
| case ScanResult::SCAN_RESULT_TOO_FAST: |
| return "Too Fast"; |
| case ScanResult::SCAN_RESULT_IMMOBILE: |
| return "Immobile"; |
| default: |
| return "Unknown Result"; |
| } |
| } |
| |
| BiometricsManagerProxyBase::BiometricsManagerProxyBase() |
| : proxy_(nullptr), weak_factory_(this), biod_auth_session_(nullptr) {} |
| |
| bool BiometricsManagerProxyBase::Initialize(const scoped_refptr<dbus::Bus>& bus, |
| const dbus::ObjectPath& path) { |
| bus_ = bus; |
| proxy_ = bus_->GetObjectProxy(biod::kBiodServiceName, path); |
| |
| if (!proxy_) |
| return false; |
| |
| proxy_->ConnectToSignal( |
| biod::kBiometricsManagerInterface, |
| biod::kBiometricsManagerSessionFailedSignal, |
| base::BindRepeating(&BiometricsManagerProxyBase::OnSessionFailed, |
| weak_factory_.GetWeakPtr()), |
| base::BindOnce(&BiometricsManagerProxyBase::OnSignalConnected, |
| weak_factory_.GetWeakPtr())); |
| return true; |
| } |
| |
| std::unique_ptr<BiometricsManagerProxyBase> BiometricsManagerProxyBase::Create( |
| const scoped_refptr<dbus::Bus>& bus, const dbus::ObjectPath& path) { |
| // Using new to access non-public constructor. See https://abseil.io/tips/134. |
| auto biometrics_manager_proxy_base = |
| base::WrapUnique(new BiometricsManagerProxyBase()); |
| |
| if (!biometrics_manager_proxy_base->Initialize(bus, path)) |
| return nullptr; |
| |
| return biometrics_manager_proxy_base; |
| } |
| |
| void BiometricsManagerProxyBase::ConnectToAuthScanDoneSignal( |
| SignalCallback signal_callback, OnConnectedCallback on_connected_callback) { |
| proxy_->ConnectToSignal(biod::kBiometricsManagerInterface, |
| biod::kBiometricsManagerAuthScanDoneSignal, |
| std::move(signal_callback), |
| std::move(on_connected_callback)); |
| } |
| |
| const dbus::ObjectPath BiometricsManagerProxyBase::path() const { |
| return proxy_->object_path(); |
| } |
| |
| void BiometricsManagerProxyBase::SetFinishHandler( |
| const FinishCallback& on_finish) { |
| on_finish_ = on_finish; |
| } |
| |
| dbus::ObjectProxy* BiometricsManagerProxyBase::HandleAuthSessionResponse( |
| dbus::Response* response) { |
| if (!response) { |
| LOG(ERROR) << biod::kBiometricsManagerStartAuthSessionMethod |
| << " had no response."; |
| return nullptr; |
| } |
| |
| dbus::MessageReader response_reader(response); |
| dbus::ObjectPath auth_path; |
| if (!response_reader.PopObjectPath(&auth_path)) { |
| LOG(ERROR) << biod::kBiometricsManagerStartAuthSessionMethod |
| << " had incorrect response."; |
| return nullptr; |
| } |
| return bus_->GetObjectProxy(biod::kBiodServiceName, auth_path); |
| } |
| |
| bool BiometricsManagerProxyBase::StartAuthSession() { |
| LOG(INFO) << "Starting biometric auth session."; |
| dbus::MethodCall method_call(biod::kBiometricsManagerInterface, |
| biod::kBiometricsManagerStartAuthSessionMethod); |
| |
| std::unique_ptr<dbus::Response> response = |
| proxy_->CallMethodAndBlock(&method_call, kDbusTimeoutMs); |
| |
| biod_auth_session_ = HandleAuthSessionResponse(response.get()); |
| return biod_auth_session_ != nullptr; |
| } |
| |
| void BiometricsManagerProxyBase::OnStartAuthSessionResp( |
| base::OnceCallback<void(bool success)> callback, dbus::Response* response) { |
| biod_auth_session_ = HandleAuthSessionResponse(response); |
| std::move(callback).Run(biod_auth_session_ != nullptr); |
| } |
| |
| void BiometricsManagerProxyBase::StartAuthSessionAsync( |
| base::OnceCallback<void(bool success)> callback) { |
| LOG(INFO) << "Starting biometric auth session."; |
| dbus::MethodCall method_call(biod::kBiometricsManagerInterface, |
| biod::kBiometricsManagerStartAuthSessionMethod); |
| |
| proxy_->CallMethod( |
| &method_call, kDbusTimeoutMs, |
| base::BindOnce(&BiometricsManagerProxyBase::OnStartAuthSessionResp, |
| base::Unretained(this), std::move(callback))); |
| } |
| |
| void BiometricsManagerProxyBase::EndAuthSession() { |
| LOG(INFO) << "Ending biometric authentication"; |
| dbus::MethodCall end_call(biod::kAuthSessionInterface, |
| biod::kAuthSessionEndMethod); |
| biod_auth_session_->CallMethodAndBlock(&end_call, kDbusTimeoutMs); |
| } |
| |
| void BiometricsManagerProxyBase::OnFinish(bool success) { |
| if (on_finish_) |
| on_finish_.Run(success); |
| } |
| |
| void BiometricsManagerProxyBase::OnSessionFailed(dbus::Signal* signal) { |
| LOG(ERROR) << "Biometric device failed"; |
| OnFinish(false); |
| } |
| |
| void BiometricsManagerProxyBase::OnSignalConnected(const std::string& interface, |
| const std::string& signal, |
| bool success) { |
| if (!success) { |
| LOG(ERROR) << "Failed to connect to signal " << signal << " on interface " |
| << interface; |
| OnFinish(false); |
| } |
| } |
| |
| } // namespace biod |