| // Copyright 2017 The Chromium 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 "chromeos/dbus/biod/fake_biod_client.h" |
| |
| #include <memory> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/bind.h" |
| #include "base/single_thread_task_runner.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "dbus/object_path.h" |
| #include "third_party/cros_system_api/dbus/service_constants.h" |
| |
| namespace chromeos { |
| |
| namespace { |
| |
| // Path of an enroll session. There should only be one enroll session at a |
| // given time. |
| const char kEnrollSessionObjectPath[] = "/EnrollSession/"; |
| |
| // Header of the path of an record. A unique number will be appended when an |
| // record is created. |
| const char kRecordObjectPathPrefix[] = "/Record/"; |
| |
| // Path of an auth session. There should only be one auth sesion at a given |
| // time. |
| const char kAuthSessionObjectPath[] = "/AuthSession/"; |
| |
| } // namespace |
| |
| // FakeRecord is the definition of a fake stored fingerprint template. |
| struct FakeBiodClient::FakeRecord { |
| std::string user_id; |
| std::string label; |
| // A fake fingerprint is a vector which consists of all the strings which |
| // were "pressed" during the enroll session. |
| std::vector<std::string> fake_fingerprint; |
| }; |
| |
| FakeBiodClient::FakeBiodClient() = default; |
| |
| FakeBiodClient::~FakeBiodClient() = default; |
| |
| void FakeBiodClient::SendEnrollScanDone(const std::string& fingerprint, |
| biod::ScanResult type_result, |
| bool is_complete, |
| int percent_complete) { |
| // Enroll scan signals do nothing if an enroll session is not happening. |
| if (current_session_ != FingerprintSession::ENROLL) |
| return; |
| |
| DCHECK(current_record_); |
| // The fake fingerprint gets appended to the current fake fingerprints. |
| current_record_->fake_fingerprint.push_back(fingerprint); |
| |
| // If the enroll is complete, save the record and exit enroll mode. |
| if (is_complete) { |
| records_[current_record_path_] = std::move(current_record_); |
| current_record_path_ = dbus::ObjectPath(); |
| current_record_.reset(); |
| current_session_ = FingerprintSession::NONE; |
| } |
| |
| for (auto& observer : observers_) |
| observer.BiodEnrollScanDoneReceived(type_result, is_complete, |
| percent_complete); |
| } |
| |
| void FakeBiodClient::SendAuthScanDone(const std::string& fingerprint, |
| biod::ScanResult type_result) { |
| // Auth scan signals do nothing if an auth session is not happening. |
| if (current_session_ != FingerprintSession::AUTH) |
| return; |
| |
| AuthScanMatches matches; |
| // Iterate through all the records to check if fingerprint is a match and |
| // populate |matches| accordingly. This searches through all the records and |
| // then each record's fake fingerprint, but neither of these should ever have |
| // more than five entries. |
| for (const auto& entry : records_) { |
| const std::unique_ptr<FakeRecord>& record = entry.second; |
| if (base::ContainsValue(record->fake_fingerprint, fingerprint)) { |
| const std::string& user_id = record->user_id; |
| matches[user_id].push_back(entry.first); |
| } |
| } |
| |
| for (auto& observer : observers_) |
| observer.BiodAuthScanDoneReceived(type_result, matches); |
| } |
| |
| void FakeBiodClient::SendSessionFailed() { |
| if (current_session_ == FingerprintSession::NONE) |
| return; |
| |
| for (auto& observer : observers_) |
| observer.BiodSessionFailedReceived(); |
| } |
| |
| void FakeBiodClient::Reset() { |
| records_.clear(); |
| current_record_.reset(); |
| current_record_path_ = dbus::ObjectPath(); |
| current_session_ = FingerprintSession::NONE; |
| } |
| |
| void FakeBiodClient::Init(dbus::Bus* bus) {} |
| |
| void FakeBiodClient::AddObserver(Observer* observer) { |
| observers_.AddObserver(observer); |
| } |
| |
| void FakeBiodClient::RemoveObserver(Observer* observer) { |
| observers_.RemoveObserver(observer); |
| } |
| |
| bool FakeBiodClient::HasObserver(const Observer* observer) const { |
| return observers_.HasObserver(observer); |
| } |
| |
| void FakeBiodClient::StartEnrollSession(const std::string& user_id, |
| const std::string& label, |
| const ObjectPathCallback& callback) { |
| DCHECK_EQ(current_session_, FingerprintSession::NONE); |
| |
| // Create the enrollment with |user_id|, |label| and a empty fake fingerprint. |
| current_record_path_ = dbus::ObjectPath( |
| kRecordObjectPathPrefix + std::to_string(next_record_unique_id_++)); |
| current_record_ = std::make_unique<FakeRecord>(); |
| current_record_->user_id = user_id; |
| current_record_->label = label; |
| current_session_ = FingerprintSession::ENROLL; |
| |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, |
| base::BindOnce(callback, dbus::ObjectPath(kEnrollSessionObjectPath))); |
| } |
| |
| void FakeBiodClient::GetRecordsForUser(const std::string& user_id, |
| UserRecordsCallback callback) { |
| std::vector<dbus::ObjectPath> records_object_paths; |
| for (const auto& record : records_) { |
| if (record.second->user_id == user_id) |
| records_object_paths.push_back(record.first); |
| } |
| |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, base::BindOnce(std::move(callback), records_object_paths)); |
| } |
| |
| void FakeBiodClient::DestroyAllRecords(VoidDBusMethodCallback callback) { |
| records_.clear(); |
| |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, base::BindOnce(std::move(callback), true)); |
| } |
| |
| void FakeBiodClient::StartAuthSession(const ObjectPathCallback& callback) { |
| DCHECK_EQ(current_session_, FingerprintSession::NONE); |
| |
| current_session_ = FingerprintSession::AUTH; |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, |
| base::BindOnce(callback, dbus::ObjectPath(kAuthSessionObjectPath))); |
| } |
| |
| void FakeBiodClient::RequestType(const BiometricTypeCallback& callback) { |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, |
| base::BindOnce(callback, |
| static_cast<uint32_t>( |
| biod::BiometricType::BIOMETRIC_TYPE_FINGERPRINT))); |
| } |
| |
| void FakeBiodClient::CancelEnrollSession(VoidDBusMethodCallback callback) { |
| DCHECK_EQ(current_session_, FingerprintSession::ENROLL); |
| |
| // Clean up the in progress enrollment. |
| current_record_.reset(); |
| current_record_path_ = dbus::ObjectPath(); |
| current_session_ = FingerprintSession::NONE; |
| |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, base::BindOnce(std::move(callback), true)); |
| } |
| |
| void FakeBiodClient::EndAuthSession(VoidDBusMethodCallback callback) { |
| current_session_ = FingerprintSession::NONE; |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, base::BindOnce(std::move(callback), true)); |
| } |
| |
| void FakeBiodClient::SetRecordLabel(const dbus::ObjectPath& record_path, |
| const std::string& label, |
| VoidDBusMethodCallback callback) { |
| if (records_.find(record_path) != records_.end()) |
| records_[record_path]->label = label; |
| |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, base::BindOnce(std::move(callback), true)); |
| } |
| |
| void FakeBiodClient::RemoveRecord(const dbus::ObjectPath& record_path, |
| VoidDBusMethodCallback callback) { |
| records_.erase(record_path); |
| |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, base::BindOnce(std::move(callback), true)); |
| } |
| |
| void FakeBiodClient::RequestRecordLabel(const dbus::ObjectPath& record_path, |
| LabelCallback callback) { |
| std::string record_label; |
| if (records_.find(record_path) != records_.end()) |
| record_label = records_[record_path]->label; |
| |
| base::ThreadTaskRunnerHandle::Get()->PostTask( |
| FROM_HERE, base::BindOnce(std::move(callback), record_label)); |
| } |
| |
| } // namespace chromeos |