// 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 "authpolicy/policy/device_policy_encoder.h"

#include <limits>
#include <memory>
#include <utility>

#include <base/bind.h>
#include <base/bind_helpers.h>
#include <base/callback.h>
#include <base/json/json_reader.h>
#include <base/stl_util.h>
#include <base/strings/string_number_conversions.h>
#include <components/policy/core/common/registry_dict.h>
#include <dbus/shill/dbus-constants.h>
#include <google/protobuf/repeated_field.h>

#include "bindings/chrome_device_policy.pb.h"
#include "bindings/policy_constants.h"

namespace em = enterprise_management;

namespace policy {
using ::google::protobuf::RepeatedPtrField;

// Types must be defined in order of definition in
// AutoUpdateSettingsProto_ConnectionType for the static_assert to work as
// expected.
constexpr std::pair<const char*, int> kConnectionTypes[] = {
    std::make_pair(
        shill::kTypeEthernet,
        em::AutoUpdateSettingsProto_ConnectionType_CONNECTION_TYPE_ETHERNET),
    std::make_pair(
        shill::kTypeWifi,
        em::AutoUpdateSettingsProto_ConnectionType_CONNECTION_TYPE_WIFI),
    std::make_pair(
        shill::kTypeCellular,
        em::AutoUpdateSettingsProto_ConnectionType_CONNECTION_TYPE_CELLULAR)};

constexpr size_t kConnectionTypesSize = base::size(kConnectionTypes);

// Integer range for DeviceLoginScreenScreenMagnifierType policy.
constexpr int kScreenMagnifierTypeRangeMin = 0;
constexpr int kScreenMagnifierTypeRangeMax = 2;

// Integer range for kDeviceCrostiniArcAdbSideloadingAllowed policy.
constexpr int kDeviceCrostiniArcAdbSideloadingAllowedRangeMin = 0;
constexpr int kDeviceCrostiniArcAdbSideloadingAllowedRangeMax = 2;

// Integer range for DeviceChromeVariations policy.
constexpr int kChromeVariationsRangeMin = 0;
constexpr int kChromeVariationsRangeMax = 2;

static_assert(em::AutoUpdateSettingsProto_ConnectionType_ConnectionType_MAX ==
                  kConnectionTypes[kConnectionTypesSize - 1].second,
              "Add all supported values here");

namespace {

// Translates string connection types to enums.
bool DecodeConnectionType(const std::string& value,
                          em::AutoUpdateSettingsProto_ConnectionType* type) {
  DCHECK(type);

  for (size_t n = 0; n < base::size(kConnectionTypes); ++n) {
    if (value.compare(kConnectionTypes[n].first) == 0) {
      int int_type = kConnectionTypes[n].second;
      DCHECK(em::AutoUpdateSettingsProto_ConnectionType_IsValid(int_type));
      *type = static_cast<em::AutoUpdateSettingsProto_ConnectionType>(int_type);
      return true;
    }
  }

  LOG(ERROR) << "Invalid connection type '" << value << "'.";
  return false;
}

// Parses the |json| string to a base::DictionaryValue. Returns nullptr on error
// and sets the |error| string.
std::unique_ptr<base::DictionaryValue> JsonToDictionary(const std::string& json,
                                                        std::string* error) {
  DCHECK(error);
  auto root = base::JSONReader::ReadAndReturnValueWithError(
      json, base::JSON_ALLOW_TRAILING_COMMAS);
  if (root.error_code != base::JSONReader::JSON_NO_ERROR) {
    *error = root.error_message;
    return nullptr;
  }

  std::unique_ptr<base::DictionaryValue> dict_value =
      base::DictionaryValue::From(
          std::make_unique<base::Value>(std::move(*root.value)));
  if (!dict_value)
    *error = "JSON is not a dictionary: '" + json + "'";
  return dict_value;
}

#define CONVERT_DAY_OF_WEEK(day_of_week)    \
  if (str == #day_of_week) {                \
    *wd = em::WeeklyTimeProto::day_of_week; \
    return true;                            \
  }

bool StringToDayOfWeek(const std::string& str,
                       em::WeeklyTimeProto::DayOfWeek* wd) {
  CONVERT_DAY_OF_WEEK(MONDAY);
  CONVERT_DAY_OF_WEEK(TUESDAY);
  CONVERT_DAY_OF_WEEK(WEDNESDAY);
  CONVERT_DAY_OF_WEEK(THURSDAY);
  CONVERT_DAY_OF_WEEK(FRIDAY);
  CONVERT_DAY_OF_WEEK(SATURDAY);
  CONVERT_DAY_OF_WEEK(SUNDAY);
  return false;
}

#undef CONVERT_WEEKDAY

// Converts a dictionary |value| to a WeeklyTimeProto |proto|.
bool EncodeWeeklyTimeProto(const base::DictionaryValue& value,
                           em::WeeklyTimeProto* proto) {
  std::string day_of_week_str;
  em::WeeklyTimeProto::DayOfWeek day_of_week = em::WeeklyTimeProto::MONDAY;
  int time = 0;
  if (!value.GetString("day_of_week", &day_of_week_str) ||
      !StringToDayOfWeek(day_of_week_str, &day_of_week) ||
      !value.GetInteger("time", &time)) {
    return false;
  }

  proto->set_day_of_week(day_of_week);
  proto->set_time(time);
  return true;
}

// Converts the dictionary |value| to a WeeklyTimeIntervalProto |proto|.
bool EncodeWeeklyTimeIntervalProto(const base::Value& value,
                                   em::WeeklyTimeIntervalProto* proto) {
  const base::DictionaryValue* dict = nullptr;
  if (!value.GetAsDictionary(&dict))
    return false;

  const base::DictionaryValue* start = nullptr;
  if (!dict->GetDictionary("start", &start))
    return false;

  const base::DictionaryValue* end = nullptr;
  if (!dict->GetDictionary("end", &end))
    return false;

  DCHECK(start && end);
  return EncodeWeeklyTimeProto(*start, proto->mutable_start()) &&
         EncodeWeeklyTimeProto(*end, proto->mutable_end());
}

void CopyStringListPolicy(const std::vector<std::string>& list,
                          RepeatedPtrField<std::string>* proto_list) {
  *proto_list = {list.begin(), list.end()};
}

// Copies either `new_list` (preferred) or `old_list` to the specified
// proto_list. At least one of new_list or old_list must have a value.
void CopyStringListPolicyWithFallback(
    const base::Optional<std::vector<std::string>>& new_list,
    const base::Optional<std::vector<std::string>>& old_list,
    RepeatedPtrField<std::string>* proto_list) {
  if (new_list) {
    CopyStringListPolicy(new_list.value(), proto_list);
  } else {
    DCHECK(old_list);
    CopyStringListPolicy(old_list.value(), proto_list);
  }
}

}  // namespace

DevicePolicyEncoder::DevicePolicyEncoder(const RegistryDict* dict,
                                         const PolicyLevel level)
    : dict_(dict), level_(level) {}

void DevicePolicyEncoder::EncodePolicy(
    em::ChromeDeviceSettingsProto* policy) const {
  LOG_IF(INFO, log_policy_values_)
      << authpolicy::kColorPolicy << "Device policy ("
      << (level_ == POLICY_LEVEL_RECOMMENDED ? "recommended" : "mandatory")
      << ")" << authpolicy::kColorReset;
  if (level_ == POLICY_LEVEL_MANDATORY) {
    // All of the following policies support only mandatory level, so there's no
    // benefit on trying re-encoding them when the supported level is
    // recommended.
    EncodeLoginPolicies(policy);
    EncodeNetworkPolicies(policy);
    EncodeAutoUpdatePolicies(policy);
    EncodeAccessibilityPolicies(policy);
    EncodeGenericPolicies(policy);
  }
  EncodePoliciesWithPolicyOptions(policy);
}

void DevicePolicyEncoder::EncodeLoginPolicies(
    em::ChromeDeviceSettingsProto* policy) const {
  if (base::Optional<bool> value = EncodeBoolean(key::kDeviceGuestModeEnabled))
    policy->mutable_guest_mode_enabled()->set_guest_mode_enabled(value.value());
  if (base::Optional<bool> value = EncodeBoolean(key::kDeviceRebootOnShutdown))
    policy->mutable_reboot_on_shutdown()->set_reboot_on_shutdown(value.value());
  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceShowUserNamesOnSignin))
    policy->mutable_show_user_names()->set_show_user_names(value.value());
  if (base::Optional<bool> value = EncodeBoolean(key::kDeviceAllowNewUsers))
    policy->mutable_allow_new_users()->set_allow_new_users(value.value());
  // The original policy has been replaced by an inclusively named version. For
  // backwards compatibility, copy the original policy to the newly named proto
  // if no value exists for the newly named proto.
  base::Optional<std::vector<std::string>> user_allowlist_values =
      EncodeStringList(key::kDeviceUserAllowlist);
  base::Optional<std::vector<std::string>> user_whitelist_values =
      EncodeStringList(key::kDeviceUserWhitelist);
  if (user_allowlist_values || user_whitelist_values) {
    CopyStringListPolicyWithFallback(
        user_allowlist_values, user_whitelist_values,
        policy->mutable_user_allowlist()->mutable_user_allowlist());
  }
  if (user_whitelist_values) {
    CopyStringListPolicy(
        user_whitelist_values.value(),
        policy->mutable_user_whitelist()->mutable_user_whitelist());
  }
  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceEphemeralUsersEnabled))
    policy->mutable_ephemeral_users_enabled()->set_ephemeral_users_enabled(
        value.value());
  if (base::Optional<bool> value = EncodeBoolean(key::kDeviceAllowBluetooth))
    policy->mutable_allow_bluetooth()->set_allow_bluetooth(value.value());
  if (base::Optional<std::vector<std::string>> values =
          EncodeStringList(key::kDeviceLoginScreenExtensions)) {
    *policy->mutable_device_login_screen_extensions()
         ->mutable_device_login_screen_extensions() = {values.value().begin(),
                                                       values.value().end()};
  }
  if (base::Optional<std::string> value =
          EncodeString(key::kDeviceLoginScreenDomainAutoComplete)) {
    policy->mutable_login_screen_domain_auto_complete()
        ->set_login_screen_domain_auto_complete(value.value());
  }
  if (base::Optional<std::vector<std::string>> values =
          EncodeStringList(key::kDeviceLoginScreenLocales)) {
    *policy->mutable_login_screen_locales()->mutable_login_screen_locales() = {
        values.value().begin(), values.value().end()};
  }
  if (base::Optional<std::vector<std::string>> values =
          EncodeStringList(key::kDeviceLoginScreenInputMethods)) {
    *policy->mutable_login_screen_input_methods()
         ->mutable_login_screen_input_methods() = {values.value().begin(),
                                                   values.value().end()};
  }
  if (base::Optional<std::vector<std::string>> values = EncodeStringList(
          key::kDeviceLoginScreenAutoSelectCertificateForUrls)) {
    *policy->mutable_device_login_screen_auto_select_certificate_for_urls()
         ->mutable_login_screen_auto_select_certificate_rules() = {
        values.value().begin(), values.value().end()};
  }

  if (base::Optional<int> value =
          EncodeInteger(key::kDeviceRebootOnUserSignout)) {
    policy->mutable_device_reboot_on_user_signout()->set_reboot_on_signout_mode(
        static_cast<em::DeviceRebootOnUserSignoutProto_RebootOnSignoutMode>(
            value.value()));
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kDevicePowerwashAllowed)) {
    policy->mutable_device_powerwash_allowed()->set_device_powerwash_allowed(
        value.value());
  }

  if (base::Optional<int> value = EncodeIntegerInRange(
          key::kDeviceChromeVariations, kChromeVariationsRangeMin,
          kChromeVariationsRangeMax)) {
    policy->mutable_device_chrome_variations_type()->set_value(value.value());
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceLoginScreenPrivacyScreenEnabled)) {
    policy->mutable_device_login_screen_privacy_screen_enabled()->set_enabled(
        value.value());
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceShowNumericKeyboardForPassword)) {
    policy->mutable_device_show_numeric_keyboard_for_password()->set_value(
        value.value());
  }

  if (base::Optional<std::vector<std::string>> values =
          EncodeStringList(key::kDeviceWebBasedAttestationAllowedUrls)) {
    *policy->mutable_device_web_based_attestation_allowed_urls()
         ->mutable_value()
         ->mutable_entries() = {values.value().begin(), values.value().end()};
  }

  if (base::Optional<std::string> value =
          EncodeString(key::kDeviceMinimumVersion))
    policy->mutable_device_minimum_version()->set_value(value.value());

  if (base::Optional<std::string> value =
          EncodeString(key::kDeviceMinimumVersionAueMessage)) {
    policy->mutable_device_minimum_version_aue_message()->set_value(
        value.value());
  }

  if (base::Optional<std::string> value =
          EncodeString(key::kRequiredClientCertificateForDevice)) {
    policy->mutable_required_client_certificate_for_device()
        ->set_required_client_certificate_for_device(value.value());
  }

  if (base::Optional<std::string> value =
          EncodeString(key::kSystemProxySettings)) {
    std::string error;
    std::unique_ptr<base::DictionaryValue> dict_value =
        JsonToDictionary(value.value(), &error);
    if (!dict_value) {
      LOG(ERROR) << "Invalid JSON string '"
                 << (!error.empty() ? error : value.value()) << "' for policy '"
                 << key::kSystemProxySettings << "', ignoring.";
    } else {
      policy->mutable_system_proxy_settings()->set_system_proxy_settings(
          value.value());
    }
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kManagedGuestSessionPrivacyWarningsEnabled)) {
    policy->mutable_managed_guest_session_privacy_warnings()->set_enabled(
        value.value());
  }
}

void DevicePolicyEncoder::EncodeNetworkPolicies(
    em::ChromeDeviceSettingsProto* policy) const {
  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceDataRoamingEnabled)) {
    policy->mutable_data_roaming_enabled()->set_data_roaming_enabled(
        value.value());
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceWiFiFastTransitionEnabled)) {
    policy->mutable_device_wifi_fast_transition_enabled()
        ->set_device_wifi_fast_transition_enabled(value.value());
  }

  if (base::Optional<std::string> value =
          EncodeString(key::kDeviceOpenNetworkConfiguration)) {
    policy->mutable_open_network_configuration()
        ->set_open_network_configuration(value.value());
  }

  if (base::Optional<std::string> value =
          EncodeString(key::kDeviceHostnameTemplate)) {
    policy->mutable_network_hostname()->set_device_hostname_template(
        value.value());
  }

  if (base::Optional<int> value =
          EncodeInteger(key::kDeviceKerberosEncryptionTypes)) {
    policy->mutable_device_kerberos_encryption_types()->set_types(
        static_cast<em::DeviceKerberosEncryptionTypesProto_Types>(
            value.value()));
  }
}

void DevicePolicyEncoder::EncodeAutoUpdatePolicies(
    em::ChromeDeviceSettingsProto* policy) const {
  if (base::Optional<std::string> value =
          EncodeString(key::kChromeOsReleaseChannel))
    policy->mutable_release_channel()->set_release_channel(value.value());
  if (base::Optional<bool> value =
          EncodeBoolean(key::kChromeOsReleaseChannelDelegated)) {
    policy->mutable_release_channel()->set_release_channel_delegated(
        value.value());
  }
  if (base::Optional<std::string> value =
          EncodeString(key::kDeviceReleaseLtsTag)) {
    policy->mutable_release_channel()->set_release_lts_tag(value.value());
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceAutoUpdateDisabled))
    policy->mutable_auto_update_settings()->set_update_disabled(value.value());
  if (base::Optional<std::string> value =
          EncodeString(key::kDeviceTargetVersionPrefix)) {
    policy->mutable_auto_update_settings()->set_target_version_prefix(
        value.value());
  }
  if (base::Optional<int> value =
          EncodeInteger(key::kDeviceRollbackToTargetVersion)) {
    policy->mutable_auto_update_settings()->set_rollback_to_target_version(
        static_cast<em::AutoUpdateSettingsProto_RollbackToTargetVersion>(
            value.value()));
  }
  if (base::Optional<int> value =
          EncodeInteger(key::kDeviceRollbackAllowedMilestones)) {
    policy->mutable_auto_update_settings()->set_rollback_allowed_milestones(
        value.value());
  }

  // target_version_display_name is not actually a policy, but a display
  // string for target_version_prefix, so we ignore it. It seems to be
  // unreferenced as well.
  if (base::Optional<int> value =
          EncodeInteger(key::kDeviceUpdateScatterFactor)) {
    policy->mutable_auto_update_settings()->set_scatter_factor_in_seconds(
        value.value());
  }
  if (base::Optional<std::vector<std::string>> values =
          EncodeStringList(key::kDeviceUpdateAllowedConnectionTypes)) {
    auto list = policy->mutable_auto_update_settings();
    list->clear_allowed_connection_types();
    for (const std::string& value : values.value()) {
      em::AutoUpdateSettingsProto_ConnectionType type;
      if (DecodeConnectionType(value, &type))
        list->add_allowed_connection_types(type);
    }
  }
  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceUpdateHttpDownloadsEnabled)) {
    policy->mutable_auto_update_settings()->set_http_downloads_enabled(
        value.value());
  }
  if (base::Optional<bool> value = EncodeBoolean(key::kRebootAfterUpdate)) {
    policy->mutable_auto_update_settings()->set_reboot_after_update(
        value.value());
  }
  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceAutoUpdateP2PEnabled))
    policy->mutable_auto_update_settings()->set_p2p_enabled(value.value());
  if (base::Optional<std::string> value =
          EncodeString(key::kDeviceAutoUpdateTimeRestrictions)) {
    policy->mutable_auto_update_settings()->set_disallowed_time_intervals(
        value.value());
  }
  if (base::Optional<std::string> value =
          EncodeString(key::kDeviceUpdateStagingSchedule))
    policy->mutable_auto_update_settings()->set_staging_schedule(value.value());
  if (base::Optional<std::string> value =
          EncodeString(key::kDeviceQuickFixBuildToken)) {
    policy->mutable_auto_update_settings()->set_device_quick_fix_build_token(
        value.value());
  }
  if (base::Optional<std::string> value =
          EncodeString(key::kDeviceLoginScreenWebUsbAllowDevicesForUrls)) {
    policy->mutable_device_login_screen_webusb_allow_devices_for_urls()
        ->set_device_login_screen_webusb_allow_devices_for_urls(value.value());
  }
  if (base::Optional<int> value =
          EncodeInteger(key::kDeviceChannelDowngradeBehavior)) {
    if (em::AutoUpdateSettingsProto::ChannelDowngradeBehavior_IsValid(
            value.value())) {
      policy->mutable_auto_update_settings()->set_channel_downgrade_behavior(
          static_cast<em::AutoUpdateSettingsProto::ChannelDowngradeBehavior>(
              value.value()));
    } else {
      LOG(ERROR) << "Invalid enum value " << value.value() << " for policy "
                 << key::kDeviceChannelDowngradeBehavior;
    }
  }
}

void DevicePolicyEncoder::EncodeAccessibilityPolicies(
    em::ChromeDeviceSettingsProto* policy) const {
  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceLoginScreenDefaultLargeCursorEnabled)) {
    policy->mutable_accessibility_settings()
        ->set_login_screen_default_large_cursor_enabled(value.value());
  }
  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceLoginScreenDefaultSpokenFeedbackEnabled)) {
    policy->mutable_accessibility_settings()
        ->set_login_screen_default_spoken_feedback_enabled(value.value());
  }
  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceLoginScreenDefaultHighContrastEnabled)) {
    policy->mutable_accessibility_settings()
        ->set_login_screen_default_high_contrast_enabled(value.value());
  }
  if (base::Optional<int> value =
          EncodeInteger(key::kDeviceLoginScreenDefaultScreenMagnifierType)) {
    policy->mutable_accessibility_settings()
        ->set_login_screen_default_screen_magnifier_type(
            static_cast<em::AccessibilitySettingsProto_ScreenMagnifierType>(
                value.value()));
  }
  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceLoginScreenDefaultVirtualKeyboardEnabled)) {
    policy->mutable_accessibility_settings()
        ->set_login_screen_default_virtual_keyboard_enabled(value.value());
  }
}

void DevicePolicyEncoder::EncodePoliciesWithPolicyOptions(
    em::ChromeDeviceSettingsProto* policy) const {
  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceLoginScreenLargeCursorEnabled)) {
    em::AccessibilitySettingsProto* accessibility_settings =
        policy->mutable_accessibility_settings();
    accessibility_settings->set_login_screen_large_cursor_enabled(
        value.value());
    SetPolicyOptions(accessibility_settings
                         ->mutable_login_screen_large_cursor_enabled_options(),
                     level_);
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceLoginScreenAutoclickEnabled)) {
    em::AccessibilitySettingsProto* accessibility_settings =
        policy->mutable_accessibility_settings();
    accessibility_settings->set_login_screen_autoclick_enabled(value.value());
    SetPolicyOptions(accessibility_settings
                         ->mutable_login_screen_autoclick_enabled_options(),
                     level_);
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceLoginScreenCaretHighlightEnabled)) {
    em::AccessibilitySettingsProto* accessibility_settings =
        policy->mutable_accessibility_settings();
    accessibility_settings->set_login_screen_caret_highlight_enabled(
        value.value());
    SetPolicyOptions(
        accessibility_settings
            ->mutable_login_screen_caret_highlight_enabled_options(),
        level_);
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceLoginScreenCursorHighlightEnabled)) {
    em::AccessibilitySettingsProto* accessibility_settings =
        policy->mutable_accessibility_settings();
    accessibility_settings->set_login_screen_cursor_highlight_enabled(
        value.value());
    SetPolicyOptions(
        accessibility_settings
            ->mutable_login_screen_cursor_highlight_enabled_options(),
        level_);
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceLoginScreenDictationEnabled)) {
    em::AccessibilitySettingsProto* accessibility_settings =
        policy->mutable_accessibility_settings();
    accessibility_settings->set_login_screen_dictation_enabled(value.value());
    SetPolicyOptions(accessibility_settings
                         ->mutable_login_screen_dictation_enabled_options(),
                     level_);
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceLoginScreenHighContrastEnabled)) {
    em::AccessibilitySettingsProto* accessibility_settings =
        policy->mutable_accessibility_settings();
    accessibility_settings->set_login_screen_high_contrast_enabled(
        value.value());
    SetPolicyOptions(accessibility_settings
                         ->mutable_login_screen_high_contrast_enabled_options(),
                     level_);
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceLoginScreenMonoAudioEnabled)) {
    em::AccessibilitySettingsProto* accessibility_settings =
        policy->mutable_accessibility_settings();
    accessibility_settings->set_login_screen_mono_audio_enabled(value.value());
    SetPolicyOptions(accessibility_settings
                         ->mutable_login_screen_mono_audio_enabled_options(),
                     level_);
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceLoginScreenSelectToSpeakEnabled)) {
    em::AccessibilitySettingsProto* accessibility_settings =
        policy->mutable_accessibility_settings();
    accessibility_settings->set_login_screen_select_to_speak_enabled(
        value.value());
    SetPolicyOptions(
        accessibility_settings
            ->mutable_login_screen_select_to_speak_enabled_options(),
        level_);
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceLoginScreenSpokenFeedbackEnabled)) {
    em::AccessibilitySettingsProto* accessibility_settings =
        policy->mutable_accessibility_settings();
    accessibility_settings->set_login_screen_spoken_feedback_enabled(
        value.value());
    SetPolicyOptions(
        accessibility_settings
            ->mutable_login_screen_spoken_feedback_enabled_options(),
        level_);
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceLoginScreenStickyKeysEnabled)) {
    em::AccessibilitySettingsProto* accessibility_settings =
        policy->mutable_accessibility_settings();
    accessibility_settings->set_login_screen_sticky_keys_enabled(value.value());
    SetPolicyOptions(accessibility_settings
                         ->mutable_login_screen_sticky_keys_enabled_options(),
                     level_);
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceLoginScreenVirtualKeyboardEnabled)) {
    em::AccessibilitySettingsProto* accessibility_settings =
        policy->mutable_accessibility_settings();
    accessibility_settings->set_login_screen_virtual_keyboard_enabled(
        value.value());
    SetPolicyOptions(
        accessibility_settings
            ->mutable_login_screen_virtual_keyboard_enabled_options(),
        level_);
  }

  if (base::Optional<int> value = EncodeIntegerInRange(
          key::kDeviceLoginScreenScreenMagnifierType,
          kScreenMagnifierTypeRangeMin, kScreenMagnifierTypeRangeMax)) {
    em::AccessibilitySettingsProto* accessibility_settings =
        policy->mutable_accessibility_settings();
    accessibility_settings->set_login_screen_screen_magnifier_type(
        value.value());
    SetPolicyOptions(accessibility_settings
                         ->mutable_login_screen_screen_magnifier_type_options(),
                     level_);
  }
}

void DevicePolicyEncoder::EncodeGenericPolicies(
    em::ChromeDeviceSettingsProto* policy) const {
  if (base::Optional<int> value =
          EncodeInteger(key::kDevicePolicyRefreshRate)) {
    policy->mutable_device_policy_refresh_rate()
        ->set_device_policy_refresh_rate(value.value());
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceMetricsReportingEnabled))
    policy->mutable_metrics_enabled()->set_metrics_enabled(value.value());

  if (base::Optional<std::string> value = EncodeString(key::kSystemTimezone))
    policy->mutable_system_timezone()->set_timezone(value.value());
  if (base::Optional<int> value =
          EncodeInteger(key::kSystemTimezoneAutomaticDetection)) {
    policy->mutable_system_timezone()->set_timezone_detection_type(
        static_cast<em::SystemTimezoneProto_AutomaticTimezoneDetectionType>(
            value.value()));
  }
  if (base::Optional<bool> value = EncodeBoolean(key::kSystemUse24HourClock))
    policy->mutable_use_24hour_clock()->set_use_24hour_clock(value.value());

  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceAllowRedeemChromeOsRegistrationOffers)) {
    policy->mutable_allow_redeem_offers()->set_allow_redeem_offers(
        value.value());
  }

  if (base::Optional<std::string> value =
          EncodeString(key::kDeviceVariationsRestrictParameter))
    policy->mutable_variations_parameter()->set_parameter(value.value());

  if (base::Optional<std::string> value =
          EncodeString(key::kDeviceLoginScreenPowerManagement)) {
    policy->mutable_login_screen_power_management()
        ->set_login_screen_power_management(value.value());
  }

  if (base::Optional<int> value = EncodeInteger(key::kDisplayRotationDefault)) {
    policy->mutable_display_rotation_default()->set_display_rotation_default(
        static_cast<em::DisplayRotationDefaultProto_Rotation>(value.value()));
  }

  if (base::Optional<std::string> value =
          EncodeString(key::kDeviceDisplayResolution)) {
    policy->mutable_device_display_resolution()->set_device_display_resolution(
        value.value());
  }

  // The original policy has been replaced by an inclusively named version. For
  // backwards compatibility, copy the original policy to the newly named proto
  // if no value exists for the newly named proto.
  base::Optional<std::vector<std::string>> usb_detachable_allowlist_values =
      EncodeStringList(key::kUsbDetachableAllowlist);
  if (base::Optional<std::vector<std::string>> values =
          EncodeStringList(key::kUsbDetachableWhitelist)) {
    auto whitelist = policy->mutable_usb_detachable_whitelist();
    auto allowlist = policy->mutable_usb_detachable_allowlist();
    DCHECK(!whitelist->id_size());
    if (!usb_detachable_allowlist_values) {
      DCHECK(!allowlist->id_size());
    }
    for (const std::string& value : values.value()) {
      std::string error;
      std::unique_ptr<base::DictionaryValue> dict_value =
          JsonToDictionary(value, &error);
      int vid, pid;
      if (!dict_value || !dict_value->GetInteger("vendor_id", &vid) ||
          !dict_value->GetInteger("product_id", &pid)) {
        LOG(ERROR) << "Invalid JSON string '"
                   << (!error.empty() ? error : value) << "' for policy '"
                   << key::kUsbDetachableWhitelist << "', ignoring. Expected: "
                   << "'{\"vendor_id\"=<vid>, \"product_id\"=<pid>}'.";
        continue;
      }

      em::UsbDeviceIdProto* whitelist_entry = whitelist->add_id();
      whitelist_entry->set_vendor_id(vid);
      whitelist_entry->set_product_id(pid);

      if (!usb_detachable_allowlist_values) {
        em::UsbDeviceIdInclusiveProto* allowlist_entry = allowlist->add_id();
        allowlist_entry->set_vendor_id(vid);
        allowlist_entry->set_product_id(pid);
      }
    }
  }

  if (usb_detachable_allowlist_values) {
    auto list = policy->mutable_usb_detachable_allowlist();
    DCHECK(!list->id_size());
    for (const std::string& value : usb_detachable_allowlist_values.value()) {
      std::string error;
      std::unique_ptr<base::DictionaryValue> dict_value =
          JsonToDictionary(value, &error);
      int vid, pid;
      if (!dict_value || !dict_value->GetInteger("vendor_id", &vid) ||
          !dict_value->GetInteger("product_id", &pid)) {
        LOG(ERROR) << "Invalid JSON string '"
                   << (!error.empty() ? error : value) << "' for policy '"
                   << key::kUsbDetachableAllowlist << "', ignoring. Expected: "
                   << "'{\"vendor_id\": <vid>, \"product_id\": <pid>}'.";
        continue;
      }

      em::UsbDeviceIdInclusiveProto* entry = list->add_id();
      entry->set_vendor_id(vid);
      entry->set_product_id(pid);
    }
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceQuirksDownloadEnabled)) {
    policy->mutable_quirks_download_enabled()->set_quirks_download_enabled(
        value.value());
  }

  if (base::Optional<std::string> value =
          EncodeString(key::kDeviceWallpaperImage)) {
    policy->mutable_device_wallpaper_image()->set_device_wallpaper_image(
        value.value());
  }

  if (base::Optional<std::string> value = EncodeString(key::kDeviceOffHours)) {
    std::string error;
    std::unique_ptr<base::DictionaryValue> dict_value =
        JsonToDictionary(value.value(), &error);
    const base::ListValue* intervals = nullptr;
    const base::ListValue* ignored_policy_proto_tags = nullptr;
    std::string timezone;
    bool is_error = !dict_value ||
                    !dict_value->GetList("intervals", &intervals) ||
                    !dict_value->GetList("ignored_policy_proto_tags",
                                         &ignored_policy_proto_tags) ||
                    !dict_value->GetString("timezone", &timezone);
    auto proto = std::make_unique<em::DeviceOffHoursProto>();
    if (!is_error) {
      proto->set_timezone(timezone);

      for (const base::Value& entry : *intervals) {
        is_error |=
            !EncodeWeeklyTimeIntervalProto(entry, proto->add_intervals());
      }

      for (const base::Value& entry : *ignored_policy_proto_tags) {
        int tag = 0;
        is_error |= !entry.GetAsInteger(&tag);
        proto->add_ignored_policy_proto_tags(tag);
      }
    }

    if (is_error) {
      LOG(ERROR) << "Invalid JSON string '"
                 << (!error.empty() ? error : value.value()) << "' for policy '"
                 << key::kDeviceOffHours << "', ignoring. "
                 << "See policy_templates.json for example.";
    } else {
      policy->set_allocated_device_off_hours(proto.release());
    }
  }

  if (base::Optional<std::string> value = EncodeString(key::kCastReceiverName))
    policy->mutable_cast_receiver_name()->set_name(value.value());

  // The original policy has been replaced by an inclusively named version. For
  // backwards compatibility, copy the original policy to the newly named proto
  // if no value exists for the newly named proto.
  base::Optional<std::string> device_printers_value =
      EncodeString(key::kDevicePrinters);
  base::Optional<std::string> device_native_printers_value =
      EncodeString(key::kDeviceNativePrinters);
  if (device_printers_value || device_native_printers_value) {
    policy->mutable_device_printers()->set_external_policy(
        device_printers_value ? device_printers_value.value()
                              : device_native_printers_value.value());
  }
  if (device_native_printers_value) {
    policy->mutable_native_device_printers()->set_external_policy(
        device_native_printers_value.value());
  }

  // The original policy has been replaced by an inclusively named version. For
  // backwards compatibility, copy the original policy to the newly named proto
  // if no value exists for the newly named proto.
  base::Optional<int> device_printers_access_mode_value =
      EncodeInteger(key::kDevicePrintersAccessMode);
  base::Optional<int> device_native_printers_access_mode_value =
      EncodeInteger(key::kDeviceNativePrintersAccessMode);
  if (device_printers_access_mode_value ||
      device_native_printers_access_mode_value) {
    policy->mutable_device_printers_access_mode()->set_access_mode(
        static_cast<em::DevicePrintersAccessModeProto_AccessMode>(
            device_printers_access_mode_value
                ? device_printers_access_mode_value.value()
                : device_native_printers_access_mode_value.value()));
  }
  if (device_native_printers_access_mode_value) {
    policy->mutable_native_device_printers_access_mode()->set_access_mode(
        static_cast<em::DeviceNativePrintersAccessModeProto_AccessMode>(
            device_native_printers_access_mode_value.value()));
  }

  // The original policy has been replaced by an inclusively named version. For
  // backwards compatibility, copy the original policy to the newly named proto
  // if no value exists for the newly named proto.
  base::Optional<std::vector<std::string>> device_printers_blocklist_value =
      EncodeStringList(key::kDevicePrintersBlocklist);
  base::Optional<std::vector<std::string>>
      device_native_printers_blacklist_value =
          EncodeStringList(key::kDeviceNativePrintersBlacklist);
  if (device_printers_blocklist_value ||
      device_native_printers_blacklist_value) {
    CopyStringListPolicyWithFallback(
        device_printers_blocklist_value, device_native_printers_blacklist_value,
        policy->mutable_device_printers_blocklist()->mutable_blocklist());
  }
  if (device_native_printers_blacklist_value) {
    CopyStringListPolicy(device_native_printers_blacklist_value.value(),
                         policy->mutable_native_device_printers_blacklist()
                             ->mutable_blacklist());
  }

  // The original policy has been replaced by an inclusively named version. For
  // backwards compatibility, copy the original policy to the newly named proto
  // if no value exists for the newly named proto.
  base::Optional<std::vector<std::string>> device_printers_allowlist_value =
      EncodeStringList(key::kDevicePrintersAllowlist);
  base::Optional<std::vector<std::string>>
      device_native_printers_whitelist_value =
          EncodeStringList(key::kDeviceNativePrintersWhitelist);
  if (device_printers_allowlist_value ||
      device_native_printers_whitelist_value) {
    CopyStringListPolicyWithFallback(
        device_printers_allowlist_value, device_native_printers_whitelist_value,
        policy->mutable_device_printers_allowlist()->mutable_allowlist());
  }
  if (device_native_printers_whitelist_value) {
    CopyStringListPolicy(device_native_printers_whitelist_value.value(),
                         policy->mutable_native_device_printers_whitelist()
                             ->mutable_whitelist());
  }

  if (base::Optional<std::string> value =
          EncodeString(key::kDeviceExternalPrintServers)) {
    policy->mutable_external_print_servers()->set_external_policy(
        value.value());
  }
  if (base::Optional<std::vector<std::string>> values =
          EncodeStringList(key::kDeviceExternalPrintServersAllowlist)) {
    *policy->mutable_external_print_servers_allowlist()->mutable_allowlist() = {
        values.value().begin(), values.value().end()};
  }

  if (base::Optional<std::string> value =
          EncodeString(key::kTPMFirmwareUpdateSettings)) {
    std::string error;
    std::unique_ptr<base::DictionaryValue> dict_value =
        JsonToDictionary(value.value(), &error);
    if (!dict_value) {
      LOG(ERROR) << "Invalid JSON string '"
                 << (!error.empty() ? error : value.value()) << "' for policy '"
                 << key::kTPMFirmwareUpdateSettings << "', ignoring.";
    } else {
      em::TPMFirmwareUpdateSettingsProto* settings =
          policy->mutable_tpm_firmware_update_settings();
      for (base::DictionaryValue::Iterator iter(*dict_value); !iter.IsAtEnd();
           iter.Advance()) {
        bool flag;
        if (iter.key() == "allow-user-initiated-powerwash" &&
            iter.value().GetAsBoolean(&flag)) {
          settings->set_allow_user_initiated_powerwash(flag);
        } else if (iter.key() == "allow-user-initiated-preserve-device-state" &&
                   iter.value().GetAsBoolean(&flag)) {
          settings->set_allow_user_initiated_preserve_device_state(flag);
        } else {
          LOG(WARNING) << "Unknown JSON key or invalid value: " << iter.key();
        }
      }
    }
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kUnaffiliatedArcAllowed)) {
    policy->mutable_unaffiliated_arc_allowed()->set_unaffiliated_arc_allowed(
        value.value());
  }

  if (base::Optional<int> value =
          EncodeInteger(key::kDeviceUserPolicyLoopbackProcessingMode)) {
    policy->mutable_device_user_policy_loopback_processing_mode()->set_mode(
        static_cast<em::DeviceUserPolicyLoopbackProcessingModeProto::Mode>(
            value.value()));
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kVirtualMachinesAllowed)) {
    policy->mutable_virtual_machines_allowed()->set_virtual_machines_allowed(
        value.value());
  }

  if (base::Optional<int> value =
          EncodeInteger(key::kDeviceMachinePasswordChangeRate)) {
    policy->mutable_device_machine_password_change_rate()->set_rate_days(
        value.value());
  }

  if (base::Optional<int> value = EncodeInteger(key::kDeviceGpoCacheLifetime)) {
    policy->mutable_device_gpo_cache_lifetime()->set_lifetime_hours(
        value.value());
  }

  if (base::Optional<int> value =
          EncodeInteger(key::kDeviceAuthDataCacheLifetime)) {
    policy->mutable_device_auth_data_cache_lifetime()->set_lifetime_hours(
        value.value());
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceUnaffiliatedCrostiniAllowed)) {
    policy->mutable_device_unaffiliated_crostini_allowed()
        ->set_device_unaffiliated_crostini_allowed(value.value());
  }

  if (base::Optional<bool> value = EncodeBoolean(key::kPluginVmAllowed))
    policy->mutable_plugin_vm_allowed()->set_plugin_vm_allowed(value.value());
  if (base::Optional<std::string> value =
          EncodeString(key::kPluginVmLicenseKey)) {
    policy->mutable_plugin_vm_license_key()->set_plugin_vm_license_key(
        value.value());
  }

  if (base::Optional<bool> value = EncodeBoolean(key::kDeviceWilcoDtcAllowed)) {
    policy->mutable_device_wilco_dtc_allowed()->set_device_wilco_dtc_allowed(
        value.value());
  }

  if (base::Optional<bool> value = EncodeBoolean(key::kDeviceBootOnAcEnabled))
    policy->mutable_device_boot_on_ac()->set_enabled(value.value());

  if (base::Optional<int> value =
          EncodeInteger(key::kDevicePowerPeakShiftBatteryThreshold)) {
    policy->mutable_device_power_peak_shift()->set_battery_threshold(
        value.value());
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kDevicePowerPeakShiftEnabled))
    policy->mutable_device_power_peak_shift()->set_enabled(value.value());

  if (base::Optional<std::string> value =
          EncodeString(key::kDevicePowerPeakShiftDayConfig))
    policy->mutable_device_power_peak_shift()->set_day_configs(value.value());

  if (base::Optional<bool> value = EncodeBoolean(key::kDeviceWiFiAllowed)) {
    policy->mutable_device_wifi_allowed()->set_device_wifi_allowed(
        value.value());
  }

  if (base::Optional<std::string> value =
          EncodeString(key::kDeviceWilcoDtcConfiguration)) {
    policy->mutable_device_wilco_dtc_configuration()
        ->set_device_wilco_dtc_configuration(value.value());
  }

  if (base::Optional<int> value =
          EncodeInteger(key::kDeviceDockMacAddressSource)) {
    policy->mutable_device_dock_mac_address_source()->set_source(
        static_cast<em::DeviceDockMacAddressSourceProto::Source>(
            value.value()));
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceAdvancedBatteryChargeModeEnabled)) {
    policy->mutable_device_advanced_battery_charge_mode()->set_enabled(
        value.value());
  }

  if (base::Optional<std::string> value =
          EncodeString(key::kDeviceAdvancedBatteryChargeModeDayConfig)) {
    policy->mutable_device_advanced_battery_charge_mode()->set_day_configs(
        value.value());
  }

  if (base::Optional<int> value =
          EncodeInteger(key::kDeviceBatteryChargeMode)) {
    policy->mutable_device_battery_charge_mode()->set_battery_charge_mode(
        static_cast<em::DeviceBatteryChargeModeProto_BatteryChargeMode>(
            value.value()));
  }

  if (base::Optional<int> value =
          EncodeInteger(key::kDeviceBatteryChargeCustomStartCharging)) {
    policy->mutable_device_battery_charge_mode()->set_custom_charge_start(
        value.value());
  }

  if (base::Optional<int> value =
          EncodeInteger(key::kDeviceBatteryChargeCustomStopCharging)) {
    policy->mutable_device_battery_charge_mode()->set_custom_charge_stop(
        value.value());
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceUsbPowerShareEnabled))
    policy->mutable_device_usb_power_share()->set_enabled(value.value());

  if (base::Optional<int> value = EncodeIntegerInRange(
          key::kDeviceCrostiniArcAdbSideloadingAllowed,
          kDeviceCrostiniArcAdbSideloadingAllowedRangeMin,
          kDeviceCrostiniArcAdbSideloadingAllowedRangeMax)) {
    policy->mutable_device_crostini_arc_adb_sideloading_allowed()->set_mode(
        static_cast<
            em::DeviceCrostiniArcAdbSideloadingAllowedProto::AllowanceMode>(
            value.value()));
  }

  if (base::Optional<bool> value =
          EncodeBoolean(key::kDeviceShowLowDiskSpaceNotification))
    policy->mutable_device_show_low_disk_space_notification()
        ->set_device_show_low_disk_space_notification(value.value());
}

base::Optional<bool> DevicePolicyEncoder::EncodeBoolean(
    const char* policy_name) const {
  return EncodeBooleanPolicy(policy_name, GetValueFromDictCallback(dict_),
                             log_policy_values_);
}

base::Optional<int> DevicePolicyEncoder::EncodeInteger(
    const char* policy_name) const {
  return EncodeIntegerInRange(policy_name, std::numeric_limits<int>::min(),
                              std::numeric_limits<int>::max());
}

base::Optional<int> DevicePolicyEncoder::EncodeIntegerInRange(
    const char* policy_name, int range_min, int range_max) const {
  return EncodeIntegerInRangePolicy(policy_name,
                                    GetValueFromDictCallback(dict_), range_min,
                                    range_max, log_policy_values_);
}

base::Optional<std::string> DevicePolicyEncoder::EncodeString(
    const char* policy_name) const {
  return EncodeStringPolicy(policy_name, GetValueFromDictCallback(dict_),
                            log_policy_values_);
}

base::Optional<std::vector<std::string>> DevicePolicyEncoder::EncodeStringList(
    const char* policy_name) const {
  const RegistryDict* key = dict_->GetKey(policy_name);
  if (!key)
    return base::nullopt;

  return EncodeStringListPolicy(policy_name, GetValueFromDictCallback(key),
                                log_policy_values_);
}

}  // namespace policy
