// Copyright 2016 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/biometrics_daemon.h"

#include <algorithm>
#include <utility>

#include <base/bind.h>
#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include <brillo/dbus/async_event_sequencer.h>
#include <chromeos/dbus/service_constants.h>

#include "biod/cros_fp_biometrics_manager.h"
#include "biod/cros_fp_device_factory_impl.h"
#include "biod/proto_bindings/constants.pb.h"
#include "biod/proto_bindings/messages.pb.h"

namespace biod {

using brillo::dbus_utils::AsyncEventSequencer;
using brillo::dbus_utils::DBusInterface;
using brillo::dbus_utils::DBusObject;
using brillo::dbus_utils::ExportedObjectManager;
using brillo::dbus_utils::ExportedProperty;
using brillo::dbus_utils::ExportedPropertySet;
using dbus::ObjectPath;

namespace dbus_constants {
const int kDbusTimeoutMs = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT;
const char kSessionStateStarted[] = "started";
constexpr char kSessionStateStopped[] = "stopped";
}  // namespace dbus_constants

namespace errors {
const char kDomain[] = "biod";
const char kInternalError[] = "internal_error";
const char kInvalidArguments[] = "invalid_arguments";
}  // namespace errors

void LogOnSignalConnected(const std::string& interface_name,
                          const std::string& signal_name,
                          bool success) {
  if (!success)
    LOG(ERROR) << "Failed to connect to signal " << signal_name
               << " of interface " << interface_name;
}

BiometricsManagerWrapper::BiometricsManagerWrapper(
    std::unique_ptr<BiometricsManager> biometrics_manager,
    ExportedObjectManager* object_manager,
    ObjectPath object_path,
    const AsyncEventSequencer::CompletionAction& completion_callback)
    : biometrics_manager_(std::move(biometrics_manager)),
      dbus_object_(object_manager, object_manager->GetBus(), object_path),
      object_path_(std::move(object_path)),
      enroll_session_object_path_(object_path_.value() + "/EnrollSession"),
      auth_session_object_path_(object_path_.value() + "/AuthSession") {
  CHECK(biometrics_manager_);

  biometrics_manager_->SetEnrollScanDoneHandler(base::Bind(
      &BiometricsManagerWrapper::OnEnrollScanDone, base::Unretained(this)));
  biometrics_manager_->SetAuthScanDoneHandler(base::Bind(
      &BiometricsManagerWrapper::OnAuthScanDone, base::Unretained(this)));
  biometrics_manager_->SetSessionFailedHandler(base::Bind(
      &BiometricsManagerWrapper::OnSessionFailed, base::Unretained(this)));

  dbus::ObjectProxy* bus_proxy = object_manager->GetBus()->GetObjectProxy(
      dbus::kDBusServiceName, dbus::ObjectPath(dbus::kDBusServicePath));
  bus_proxy->ConnectToSignal(
      dbus::kDBusInterface, "NameOwnerChanged",
      base::Bind(&BiometricsManagerWrapper::OnNameOwnerChanged,
                 base::Unretained(this)),
      base::Bind(&LogOnSignalConnected));

  DBusInterface* bio_interface =
      dbus_object_.AddOrGetInterface(kBiometricsManagerInterface);
  property_type_.SetValue(
      static_cast<uint32_t>(biometrics_manager_->GetType()));
  bio_interface->AddProperty(kBiometricsManagerBiometricTypeProperty,
                             &property_type_);
  bio_interface->AddSimpleMethodHandlerWithErrorAndMessage(
      kBiometricsManagerStartEnrollSessionMethod,
      base::Bind(&BiometricsManagerWrapper::StartEnrollSession,
                 base::Unretained(this)));
  bio_interface->AddSimpleMethodHandlerWithError(
      kBiometricsManagerGetRecordsForUserMethod,
      base::Bind(&BiometricsManagerWrapper::GetRecordsForUser,
                 base::Unretained(this)));
  bio_interface->AddSimpleMethodHandlerWithError(
      kBiometricsManagerDestroyAllRecordsMethod,
      base::Bind(&BiometricsManagerWrapper::DestroyAllRecords,
                 base::Unretained(this)));
  bio_interface->AddSimpleMethodHandlerWithErrorAndMessage(
      kBiometricsManagerStartAuthSessionMethod,
      base::Bind(&BiometricsManagerWrapper::StartAuthSession,
                 base::Unretained(this)));
  dbus_object_.RegisterAsync(completion_callback);

  RefreshRecordObjects();
}

BiometricsManagerWrapper::RecordWrapper::RecordWrapper(
    BiometricsManagerWrapper* biometrics_manager,
    std::unique_ptr<BiometricsManager::Record> record,
    ExportedObjectManager* object_manager,
    const ObjectPath& object_path)
    : biometrics_manager_(biometrics_manager),
      record_(std::move(record)),
      dbus_object_(object_manager, object_manager->GetBus(), object_path),
      object_path_(object_path) {
  DBusInterface* record_interface =
      dbus_object_.AddOrGetInterface(kRecordInterface);
  property_label_.SetValue(record_->GetLabel());
  record_interface->AddProperty(kRecordLabelProperty, &property_label_);
  record_interface->AddSimpleMethodHandlerWithError(
      kRecordSetLabelMethod,
      base::Bind(&RecordWrapper::SetLabel, base::Unretained(this)));
  record_interface->AddSimpleMethodHandlerWithError(
      kRecordRemoveMethod,
      base::Bind(&RecordWrapper::Remove, base::Unretained(this)));
  dbus_object_.RegisterAndBlock();
}

BiometricsManagerWrapper::RecordWrapper::~RecordWrapper() {
  dbus_object_.UnregisterAsync();
}

bool BiometricsManagerWrapper::RecordWrapper::SetLabel(
    brillo::ErrorPtr* error, const std::string& new_label) {
  if (!record_->SetLabel(new_label)) {
    *error =
        brillo::Error::Create(FROM_HERE, errors::kDomain,
                              errors::kInternalError, "Failed to set label");
    return false;
  }
  property_label_.SetValue(new_label);
  return true;
}

bool BiometricsManagerWrapper::RecordWrapper::Remove(brillo::ErrorPtr* error) {
  if (!record_->Remove()) {
    *error = brillo::Error::Create(FROM_HERE, errors::kDomain,
                                   errors::kInternalError,
                                   "Failed to remove record");
    return false;
  }
  biometrics_manager_->RefreshRecordObjects();
  return true;
}

void BiometricsManagerWrapper::FinalizeEnrollSessionObject() {
  enroll_session_owner_.clear();
  enroll_session_dbus_object_->UnregisterAsync();
  enroll_session_dbus_object_.reset();
}

void BiometricsManagerWrapper::FinalizeAuthSessionObject() {
  auth_session_owner_.clear();
  auth_session_dbus_object_->UnregisterAsync();
  auth_session_dbus_object_.reset();
}

void BiometricsManagerWrapper::OnNameOwnerChanged(dbus::Signal* sig) {
  dbus::MessageReader reader(sig);
  std::string name, old_owner, new_owner;
  if (!reader.PopString(&name) || !reader.PopString(&old_owner) ||
      !reader.PopString(&new_owner)) {
    LOG(ERROR) << "Received invalid NameOwnerChanged signal";
    return;
  }

  // We are only interested in cases where a name gets dropped from D-Bus.
  if (name.empty() || !new_owner.empty())
    return;

  // If one of the session was owned by the dropped name, the session should
  // also be dropped, as there is nobody left to end it explicitly.

  if (name == enroll_session_owner_) {
    LOG(INFO) << "EnrollSession object owner " << enroll_session_owner_
              << " has died. EnrollSession is canceled automatically.";
    if (enroll_session_)
      enroll_session_.End();

    if (enroll_session_dbus_object_)
      FinalizeEnrollSessionObject();
  }

  if (name == auth_session_owner_) {
    LOG(INFO) << "AuthSession object owner " << auth_session_owner_
              << " has died. AuthSession is ended automatically.";
    if (auth_session_)
      auth_session_.End();

    if (auth_session_dbus_object_)
      FinalizeAuthSessionObject();
  }
}

void BiometricsManagerWrapper::OnEnrollScanDone(
    ScanResult scan_result,
    const BiometricsManager::EnrollStatus& enroll_status) {
  if (!enroll_session_dbus_object_)
    return;

  dbus::Signal enroll_scan_done_signal(kBiometricsManagerInterface,
                                       kBiometricsManagerEnrollScanDoneSignal);
  dbus::MessageWriter writer(&enroll_scan_done_signal);
  EnrollScanDone proto;
  proto.set_scan_result(scan_result);
  proto.set_done(enroll_status.done);
  if (enroll_status.percent_complete >= 0) {
    proto.set_percent_complete(enroll_status.percent_complete);
  }
  writer.AppendProtoAsArrayOfBytes(proto);
  dbus_object_.SendSignal(&enroll_scan_done_signal);
  if (enroll_status.done) {
    enroll_session_.End();
    FinalizeEnrollSessionObject();
    RefreshRecordObjects();
  }
}

void BiometricsManagerWrapper::OnAuthScanDone(
    ScanResult scan_result, BiometricsManager::AttemptMatches matches) {
  if (!auth_session_dbus_object_)
    return;

  dbus::Signal auth_scan_done_signal(kBiometricsManagerInterface,
                                     kBiometricsManagerAuthScanDoneSignal);
  dbus::MessageWriter writer(&auth_scan_done_signal);
  writer.AppendUint32(static_cast<uint32_t>(scan_result));
  dbus::MessageWriter matches_writer(nullptr);
  writer.OpenArray("{sao}", &matches_writer);
  for (const auto& match : matches) {
    dbus::MessageWriter entry_writer(nullptr);
    matches_writer.OpenDictEntry(&entry_writer);
    entry_writer.AppendString(match.first);
    std::vector<ObjectPath> record_object_paths;
    record_object_paths.resize(match.second.size());
    std::transform(match.second.begin(), match.second.end(),
                   record_object_paths.begin(),
                   [this](const std::string& record_id) {
                     return ObjectPath(object_path_.value() +
                                       std::string("/Record") + record_id);
                   });
    entry_writer.AppendArrayOfObjectPaths(record_object_paths);
    matches_writer.CloseContainer(&entry_writer);
  }
  writer.CloseContainer(&matches_writer);
  dbus_object_.SendSignal(&auth_scan_done_signal);
}

void BiometricsManagerWrapper::OnSessionFailed() {
  if (enroll_session_dbus_object_) {
    dbus::Signal session_failed_signal(kBiometricsManagerInterface,
                                       kBiometricsManagerSessionFailedSignal);
    dbus_object_.SendSignal(&session_failed_signal);
    FinalizeEnrollSessionObject();
  }

  if (enroll_session_)
    enroll_session_.End();

  if (auth_session_dbus_object_) {
    dbus::Signal session_failed_signal(kBiometricsManagerInterface,
                                       kBiometricsManagerSessionFailedSignal);
    dbus_object_.SendSignal(&session_failed_signal);
    FinalizeAuthSessionObject();
  }

  if (auth_session_)
    auth_session_.End();
}

bool BiometricsManagerWrapper::StartEnrollSession(
    brillo::ErrorPtr* error,
    dbus::Message* message,
    const std::string& user_id,
    const std::string& label,
    ObjectPath* enroll_session_path) {
  BiometricsManager::EnrollSession enroll_session =
      biometrics_manager_->StartEnrollSession(user_id, label);
  if (!enroll_session) {
    *error = brillo::Error::Create(FROM_HERE, errors::kDomain,
                                   errors::kInternalError,
                                   "Failed to start EnrollSession");
    return false;
  }
  enroll_session_ = std::move(enroll_session);

  enroll_session_dbus_object_.reset(new DBusObject(
      nullptr, dbus_object_.GetBus(), enroll_session_object_path_));
  DBusInterface* enroll_session_interface =
      enroll_session_dbus_object_->AddOrGetInterface(kEnrollSessionInterface);
  enroll_session_interface->AddSimpleMethodHandlerWithError(
      kEnrollSessionCancelMethod,
      base::Bind(&BiometricsManagerWrapper::EnrollSessionCancel,
                 base::Unretained(this)));
  enroll_session_dbus_object_->RegisterAndBlock();
  *enroll_session_path = enroll_session_object_path_;
  enroll_session_owner_ = message->GetSender();

  return true;
}

bool BiometricsManagerWrapper::GetRecordsForUser(brillo::ErrorPtr* error,
                                                 const std::string& user_id,
                                                 std::vector<ObjectPath>* out) {
  for (const auto& record : records_) {
    if (record->GetUserId() == user_id)
      out->emplace_back(record->path());
  }
  return true;
}

bool BiometricsManagerWrapper::DestroyAllRecords(brillo::ErrorPtr* error) {
  if (!biometrics_manager_->DestroyAllRecords()) {
    *error = brillo::Error::Create(FROM_HERE, errors::kDomain,
                                   errors::kInternalError,
                                   "Failed to destroy all records");
    return false;
  }
  RefreshRecordObjects();
  return true;
}

bool BiometricsManagerWrapper::StartAuthSession(brillo::ErrorPtr* error,
                                                dbus::Message* message,
                                                ObjectPath* auth_session_path) {
  BiometricsManager::AuthSession auth_session =
      biometrics_manager_->StartAuthSession();
  if (!auth_session) {
    *error = brillo::Error::Create(FROM_HERE, errors::kDomain,
                                   errors::kInternalError,
                                   "Failed to start AuthSession");
    return false;
  }
  auth_session_ = std::move(auth_session);

  auth_session_dbus_object_.reset(new DBusObject(nullptr, dbus_object_.GetBus(),
                                                 auth_session_object_path_));
  DBusInterface* auth_session_interface =
      auth_session_dbus_object_->AddOrGetInterface(kAuthSessionInterface);
  auth_session_interface->AddSimpleMethodHandlerWithError(
      kAuthSessionEndMethod,
      base::Bind(&BiometricsManagerWrapper::AuthSessionEnd,
                 base::Unretained(this)));
  auth_session_dbus_object_->RegisterAndBlock();
  *auth_session_path = auth_session_object_path_;
  auth_session_owner_ = message->GetSender();

  return true;
}

bool BiometricsManagerWrapper::EnrollSessionCancel(brillo::ErrorPtr* error) {
  if (!enroll_session_) {
    LOG(WARNING) << "DBus client attempted to cancel null EnrollSession";
    *error = brillo::Error::Create(FROM_HERE, errors::kDomain,
                                   errors::kInvalidArguments,
                                   "EnrollSession object was null");
    return false;
  }
  enroll_session_.End();
  // TODO(crbug.com/715302): FpcBiometricsManager need to wait here for
  // EnrollSession to end completely before any other session could start. Wait
  // time is ~200 milliseconds.

  if (enroll_session_dbus_object_) {
    FinalizeEnrollSessionObject();
  }
  return true;
}

bool BiometricsManagerWrapper::AuthSessionEnd(brillo::ErrorPtr* error) {
  if (!auth_session_) {
    LOG(WARNING) << "DBus client attempted to cancel null AuthSession";
    *error = brillo::Error::Create(FROM_HERE, errors::kDomain,
                                   errors::kInvalidArguments,
                                   "AuthSession object was null");
    return false;
  }
  auth_session_.End();
  // TODO(crbug.com/715302): FpcBiometricsManager need to wait here for
  // AuthSession to end completely before any other session could start. Wait
  // time is ~200 milliseconds.

  if (auth_session_dbus_object_) {
    FinalizeAuthSessionObject();
  }
  return true;
}

void BiometricsManagerWrapper::RefreshRecordObjects() {
  records_.clear();
  std::vector<std::unique_ptr<BiometricsManager::Record>> records =
      biometrics_manager_->GetRecords();

  ExportedObjectManager* object_manager = dbus_object_.GetObjectManager().get();
  std::string records_root_path = object_path_.value() + std::string("/Record");

  for (std::unique_ptr<BiometricsManager::Record>& record : records) {
    ObjectPath record_path(records_root_path + record->GetId());
    records_.emplace_back(new RecordWrapper(this, std::move(record),
                                            object_manager, record_path));
  }
}

BiometricsDaemon::BiometricsDaemon() {
  dbus::Bus::Options options;
  options.bus_type = dbus::Bus::SYSTEM;
  bus_ = new dbus::Bus(options);
  CHECK(bus_->Connect()) << "Failed to connect to system D-Bus";

  object_manager_.reset(
      new ExportedObjectManager(bus_, ObjectPath(kBiodServicePath)));

  scoped_refptr<AsyncEventSequencer> sequencer(new AsyncEventSequencer());
  object_manager_->RegisterAsync(
      sequencer->GetHandler("Manager.RegisterAsync() failed.", true));

  ObjectPath cros_fp_bio_path = ObjectPath(base::StringPrintf(
      "%s/%s", kBiodServicePath, kCrosFpBiometricsManagerName));
  std::unique_ptr<BiometricsManager> cros_fp_bio =
      CrosFpBiometricsManager::Create(
          bus_, std::make_unique<CrosFpDeviceFactoryImpl>());
  if (cros_fp_bio) {
    biometrics_managers_.emplace_back(
        std::make_unique<BiometricsManagerWrapper>(
            std::move(cros_fp_bio), object_manager_.get(), cros_fp_bio_path,
            sequencer->GetHandler(
                "Failed to register CrosFpBiometricsManager object", true)));
  } else {
    LOG(INFO) << "No CrosFpBiometricsManager detected.";
  }

  session_manager_proxy_ = bus_->GetObjectProxy(
      login_manager::kSessionManagerServiceName,
      dbus::ObjectPath(login_manager::kSessionManagerServicePath));

  if (RetrievePrimarySession()) {
    for (const auto& biometrics_manager_wrapper : biometrics_managers_) {
      biometrics_manager_wrapper->get().SetDiskAccesses(true);
      biometrics_manager_wrapper->get().ReadRecordsForSingleUser(primary_user_);
      biometrics_manager_wrapper->RefreshRecordObjects();
    }
  }

  session_manager_proxy_->ConnectToSignal(
      login_manager::kSessionManagerInterface,
      login_manager::kSessionStateChangedSignal,
      base::Bind(&BiometricsDaemon::OnSessionStateChanged,
                 base::Unretained(this)),
      base::Bind(&LogOnSignalConnected));

  CHECK(bus_->RequestOwnershipAndBlock(kBiodServiceName,
                                       dbus::Bus::REQUIRE_PRIMARY));
}

bool BiometricsDaemon::RetrievePrimarySession() {
  primary_user_.clear();
  dbus::MethodCall method_call(
      login_manager::kSessionManagerInterface,
      login_manager::kSessionManagerRetrievePrimarySession);
  std::unique_ptr<dbus::Response> response =
      session_manager_proxy_->CallMethodAndBlock(
          &method_call, dbus_constants::kDbusTimeoutMs);
  if (!response.get()) {
    LOG(ERROR) << "Cannot retrieve username for primary session.";
    return false;
  }
  dbus::MessageReader response_reader(response.get());
  std::string username;
  if (!response_reader.PopString(&username)) {
    LOG(ERROR) << "Primary session username bad format.";
    return false;
  }
  std::string sanitized_username;
  if (!response_reader.PopString(&sanitized_username)) {
    LOG(ERROR) << "Primary session sanitized username bad format.";
    return false;
  }
  if (sanitized_username.empty()) {
    LOG(INFO) << "Primary session does not exist.";
    return false;
  }
  LOG(INFO) << "Primary user updated to " << sanitized_username << ".";
  primary_user_.assign(sanitized_username);
  return true;
}

void BiometricsDaemon::OnSessionStateChanged(dbus::Signal* signal) {
  dbus::MessageReader signal_reader(signal);

  std::string state;

  CHECK(signal_reader.PopString(&state));
  LOG(INFO) << "Session state changed to " << state << ".";

  if (state == dbus_constants::kSessionStateStarted) {
    // If a primary session doesn't exist, we can safely reset the sensors
    // before loading in templates. But if one exists, we should leave the
    // sensors as is.
    if (!primary_user_.empty()) {
      LOG(INFO) << "Primary user already exists. Not updating primary user.";
      return;
    }
    for (const auto& biometrics_manager_wrapper : biometrics_managers_) {
      if (!biometrics_manager_wrapper->get().ResetSensor()) {
        LOG(ERROR) << "Failed to reset biometric sensor type: "
                   << biometrics_manager_wrapper->get().GetType();
      }
    }
    if (RetrievePrimarySession()) {
      for (const auto& biometrics_manager_wrapper : biometrics_managers_) {
        biometrics_manager_wrapper->get().SetDiskAccesses(true);
        biometrics_manager_wrapper->get().ReadRecordsForSingleUser(
            primary_user_);
        biometrics_manager_wrapper->RefreshRecordObjects();
        biometrics_manager_wrapper->get().SendStatsOnLogin();
      }
    }
  } else if (state == dbus_constants::kSessionStateStopped) {
    // Assuming that log out will always log out all users at the same time.
    for (const auto& biometrics_manager_wrapper : biometrics_managers_) {
      biometrics_manager_wrapper->get().SetDiskAccesses(false);
      biometrics_manager_wrapper->get().RemoveRecordsFromMemory();
      biometrics_manager_wrapper->RefreshRecordObjects();
    }
    primary_user_.clear();
  }
}
}  // namespace biod
