// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/sharing/sharing_sync_preference.h"

#include "base/base64.h"
#include "base/feature_list.h"
#include "base/json/values_util.h"
#include "base/strings/string_piece.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/browser/sharing/features.h"
#include "chrome/browser/sharing/proto/sharing_message.pb.h"
#include "chrome/browser/sharing/sharing_metrics.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/sync/protocol/device_info_specifics.pb.h"
#include "components/sync_device_info/device_info_sync_service.h"
#include "components/sync_device_info/local_device_info_provider.h"
#include "components/sync_preferences/pref_service_syncable.h"

namespace {

const char kVapidECPrivateKey[] = "vapid_private_key";
const char kVapidCreationTimestamp[] = "vapid_creation_timestamp";

const char kDeviceFcmToken[] = "device_fcm_token";
const char kDeviceP256dh[] = "device_p256dh";
const char kDeviceAuthSecret[] = "device_auth_secret";

const char kRegistrationAuthorizedEntity[] = "registration_authorized_entity";
const char kRegistrationTimestamp[] = "registration_timestamp";

const char kSharingInfoVapidTargetInfo[] = "vapid_target_info";
const char kSharingInfoSenderIdTargetInfo[] = "sender_id_target_info";
const char kSharingInfoEnabledFeatures[] = "enabled_features";

base::Value::Dict TargetInfoToValue(
    const syncer::DeviceInfo::SharingTargetInfo& target_info) {
  std::string base64_p256dh, base64_auth_secret;
  base::Base64Encode(target_info.p256dh, &base64_p256dh);
  base::Base64Encode(target_info.auth_secret, &base64_auth_secret);

  base::Value::Dict result;
  result.Set(kDeviceFcmToken, target_info.fcm_token);
  result.Set(kDeviceP256dh, base64_p256dh);
  result.Set(kDeviceAuthSecret, base64_auth_secret);
  return result;
}

absl::optional<syncer::DeviceInfo::SharingTargetInfo> ValueToTargetInfo(
    const base::Value::Dict& dict) {
  const std::string* fcm_token = dict.FindString(kDeviceFcmToken);
  if (!fcm_token)
    return absl::nullopt;

  const std::string* base64_p256dh = dict.FindString(kDeviceP256dh);
  const std::string* base64_auth_secret = dict.FindString(kDeviceAuthSecret);

  std::string p256dh, auth_secret;
  if (!base64_p256dh || !base64_auth_secret ||
      !base::Base64Decode(*base64_p256dh, &p256dh) ||
      !base::Base64Decode(*base64_auth_secret, &auth_secret)) {
    return absl::nullopt;
  }

  return syncer::DeviceInfo::SharingTargetInfo{*fcm_token, std::move(p256dh),
                                               std::move(auth_secret)};
}

}  // namespace

using sync_pb::SharingSpecificFields;

SharingSyncPreference::FCMRegistration::FCMRegistration(
    absl::optional<std::string> authorized_entity,
    base::Time timestamp)
    : authorized_entity(std::move(authorized_entity)), timestamp(timestamp) {}

SharingSyncPreference::FCMRegistration::FCMRegistration(
    FCMRegistration&& other) = default;

SharingSyncPreference::FCMRegistration&
SharingSyncPreference::FCMRegistration::operator=(FCMRegistration&& other) =
    default;

SharingSyncPreference::FCMRegistration::~FCMRegistration() = default;

SharingSyncPreference::SharingSyncPreference(
    PrefService* prefs,
    syncer::DeviceInfoSyncService* device_info_sync_service)
    : prefs_(prefs), device_info_sync_service_(device_info_sync_service) {
  DCHECK(prefs_);
  DCHECK(device_info_sync_service_);
  local_device_info_provider_ =
      device_info_sync_service_->GetLocalDeviceInfoProvider();
  pref_change_registrar_.Init(prefs);
}

SharingSyncPreference::~SharingSyncPreference() = default;

// static
void SharingSyncPreference::RegisterProfilePrefs(
    user_prefs::PrefRegistrySyncable* registry) {
  registry->RegisterDictionaryPref(
      prefs::kSharingVapidKey, user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
  registry->RegisterDictionaryPref(prefs::kSharingFCMRegistration);
  registry->RegisterDictionaryPref(prefs::kSharingLocalSharingInfo);
}

absl::optional<std::vector<uint8_t>> SharingSyncPreference::GetVapidKey()
    const {
  const base::Value::Dict& vapid_key = prefs_->GetDict(prefs::kSharingVapidKey);
  const std::string* base64_private_key =
      vapid_key.FindString(kVapidECPrivateKey);

  if (!base64_private_key)
    return absl::nullopt;

  std::string private_key;
  if (base::Base64Decode(*base64_private_key, &private_key)) {
    return std::vector<uint8_t>(private_key.begin(), private_key.end());
  } else {
    LOG(ERROR) << "Could not decode stored vapid keys.";
    return absl::nullopt;
  }
}

void SharingSyncPreference::SetVapidKey(
    const std::vector<uint8_t>& vapid_key) const {
  base::Time creation_timestamp = base::Time::Now();
  std::string base64_vapid_key;
  base::Base64Encode(std::string(vapid_key.begin(), vapid_key.end()),
                     &base64_vapid_key);

  ScopedDictPrefUpdate update(prefs_, prefs::kSharingVapidKey);
  update->Set(kVapidECPrivateKey, base64_vapid_key);
  update->Set(kVapidCreationTimestamp, base::TimeToValue(creation_timestamp));
}

void SharingSyncPreference::SetVapidKeyChangeObserver(
    const base::RepeatingClosure& obs) {
  ClearVapidKeyChangeObserver();
  pref_change_registrar_.Add(prefs::kSharingVapidKey, obs);
}

void SharingSyncPreference::ClearVapidKeyChangeObserver() {
  if (pref_change_registrar_.IsObserved(prefs::kSharingVapidKey))
    pref_change_registrar_.Remove(prefs::kSharingVapidKey);
}

absl::optional<SharingSyncPreference::FCMRegistration>
SharingSyncPreference::GetFCMRegistration() const {
  const base::Value::Dict& registration =
      prefs_->GetDict(prefs::kSharingFCMRegistration);
  const std::string* authorized_entity_ptr =
      registration.FindString(kRegistrationAuthorizedEntity);
  const base::Value* timestamp_value =
      registration.Find(kRegistrationTimestamp);
  if (!timestamp_value)
    return absl::nullopt;

  absl::optional<std::string> authorized_entity;
  if (authorized_entity_ptr)
    authorized_entity = *authorized_entity_ptr;

  absl::optional<base::Time> timestamp = base::ValueToTime(timestamp_value);
  if (!timestamp)
    return absl::nullopt;

  return FCMRegistration(authorized_entity, *timestamp);
}

void SharingSyncPreference::SetFCMRegistration(FCMRegistration registration) {
  ScopedDictPrefUpdate update(prefs_, prefs::kSharingFCMRegistration);
  if (registration.authorized_entity) {
    update->Set(kRegistrationAuthorizedEntity,
                std::move(*registration.authorized_entity));
  } else {
    update->Remove(kRegistrationAuthorizedEntity);
  }
  update->Set(kRegistrationTimestamp,
              base::TimeToValue(registration.timestamp));
}

void SharingSyncPreference::ClearFCMRegistration() {
  prefs_->ClearPref(prefs::kSharingFCMRegistration);
}

void SharingSyncPreference::SetLocalSharingInfo(
    syncer::DeviceInfo::SharingInfo sharing_info) {
  auto* device_info = local_device_info_provider_->GetLocalDeviceInfo();
  if (!device_info)
    return;

  // Update prefs::kSharingLocalSharingInfo to cache value locally.
  if (device_info->sharing_info() == sharing_info)
    return;

  base::Value::Dict vapid_target_info =
      TargetInfoToValue(sharing_info.vapid_target_info);
  base::Value::Dict sender_id_target_info =
      TargetInfoToValue(sharing_info.sender_id_target_info);

  base::Value::List list_value;
  for (SharingSpecificFields::EnabledFeatures feature :
       sharing_info.enabled_features) {
    list_value.Append(feature);
  }

  ScopedDictPrefUpdate local_sharing_info_update(
      prefs_, prefs::kSharingLocalSharingInfo);
  local_sharing_info_update->Set(kSharingInfoVapidTargetInfo,
                                 std::move(vapid_target_info));
  local_sharing_info_update->Set(kSharingInfoSenderIdTargetInfo,
                                 std::move(sender_id_target_info));
  local_sharing_info_update->Set(kSharingInfoEnabledFeatures,
                                 std::move(list_value));

  device_info_sync_service_->RefreshLocalDeviceInfo();
}

void SharingSyncPreference::ClearLocalSharingInfo() {
  auto* device_info = local_device_info_provider_->GetLocalDeviceInfo();
  if (!device_info)
    return;

  // Update prefs::kSharingLocalSharingInfo to clear local cache.
  prefs_->ClearPref(prefs::kSharingLocalSharingInfo);

  if (device_info->sharing_info()) {
    device_info_sync_service_->RefreshLocalDeviceInfo();
  }
}

// static
absl::optional<syncer::DeviceInfo::SharingInfo>
SharingSyncPreference::GetLocalSharingInfoForSync(PrefService* prefs) {
  const base::Value::Dict& registration =
      prefs->GetDict(prefs::kSharingLocalSharingInfo);

  const base::Value::Dict* vapid_target_info_value =
      registration.FindDict(kSharingInfoVapidTargetInfo);
  const base::Value::Dict* sender_id_target_info_value =
      registration.FindDict(kSharingInfoSenderIdTargetInfo);
  const base::Value::List* enabled_features_value =
      registration.FindList(kSharingInfoEnabledFeatures);
  if (!vapid_target_info_value || !sender_id_target_info_value ||
      !enabled_features_value) {
    return absl::nullopt;
  }

  auto vapid_target_info = ValueToTargetInfo(*vapid_target_info_value);
  auto sender_id_target_info = ValueToTargetInfo(*sender_id_target_info_value);
  if (!vapid_target_info || !sender_id_target_info)
    return absl::nullopt;

  std::set<SharingSpecificFields::EnabledFeatures> enabled_features;
  for (auto& value : *enabled_features_value) {
    DCHECK(value.is_int());
    int feature_value = value.GetInt();
    // Filter invalid enums from other browser versions.
    if (!sync_pb::SharingSpecificFields::EnabledFeatures_IsValid(feature_value))
      continue;

    enabled_features.insert(
        static_cast<SharingSpecificFields::EnabledFeatures>(feature_value));
  }

  return syncer::DeviceInfo::SharingInfo(std::move(*vapid_target_info),
                                         std::move(*sender_id_target_info),
                                         std::move(enabled_features));
}
