chromium/chrome/browser/policy/status_provider/ash_lacros_policy_stack_bridge.cc

// Copyright 2022 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/policy/status_provider/ash_lacros_policy_stack_bridge.h"

#include <utility>

#include "base/functional/callback_forward.h"
#include "base/values.h"
#include "chrome/browser/policy/status_provider/status_provider_util.h"
#include "chromeos/crosapi/mojom/device_settings_service.mojom.h"
#include "chromeos/crosapi/mojom/policy_service.mojom.h"
#include "chromeos/lacros/lacros_service.h"
#include "components/policy/core/browser/policy_conversions.h"
#include "components/policy/core/browser/webui/policy_status_provider.h"

AshLacrosPolicyStackBridge::AshLacrosPolicyStackBridge() {
  LoadDevicePolicy();
}

AshLacrosPolicyStackBridge::~AshLacrosPolicyStackBridge() {}

base::Value::Dict AshLacrosPolicyStackBridge::GetStatus() {
  base::Value::Dict device_policy_status = device_policy_status_.Clone();
  // Set the policy status description as device policy.
  device_policy_status.Set(policy::kPolicyDescriptionKey,
                           kDevicePolicyStatusDescription);
  return device_policy_status;
}

base::Value::Dict AshLacrosPolicyStackBridge::GetValues() {
  if (device_policy_.empty())
    return {};
  base::Value::Dict lacros_policies;
  lacros_policies.Set(policy::kPoliciesKey, device_policy_.Clone());
  base::Value::Dict policy_values;
  policy_values.Set(policy::kChromePoliciesId, std::move(lacros_policies));
  return policy_values;
}

base::Value::Dict AshLacrosPolicyStackBridge::GetNames() {
  return {};
}

void AshLacrosPolicyStackBridge::Refresh() {
  chromeos::LacrosService* service = chromeos::LacrosService::Get();
  if (!service->IsAvailable<crosapi::mojom::DeviceSettingsService>()) {
    return;
  }
  // Send request to Ash to reload the policy. This will reload the device
  // policy and the device account policy. Then Ash will send the updates to
  // Lacros the same way it happens when that policy gets invalidated.
  // TODO(crbug.com/1260935): Add here the request for remote commands to be
  // sent.
  service->GetRemote<crosapi::mojom::PolicyService>()->ReloadPolicy();
  NotifyValueChange();
}

void AshLacrosPolicyStackBridge::LoadDevicePolicy() {
  chromeos::LacrosService* service = chromeos::LacrosService::Get();
  if (!service->IsAvailable<crosapi::mojom::DeviceSettingsService>()) {
    return;
  }
  if (service->GetInterfaceVersion<crosapi::mojom::DeviceSettingsService>() >=
      static_cast<int>(
          crosapi::mojom::DeviceSettingsService::kGetDevicePolicyMinVersion)) {
    service->GetRemote<crosapi::mojom::DeviceSettingsService>()
        ->GetDevicePolicy(
            base::BindOnce(&AshLacrosPolicyStackBridge::OnDevicePolicyLoaded,
                           weak_ptr_factory_.GetWeakPtr()));
  } else if (service->GetInterfaceVersion<
                 crosapi::mojom::DeviceSettingsService>() >=
             static_cast<int>(crosapi::mojom::DeviceSettingsService::
                                  kGetDevicePolicyDeprecatedMinVersion)) {
    service->GetRemote<crosapi::mojom::DeviceSettingsService>()
        ->GetDevicePolicyDeprecated(base::BindOnce(
            &AshLacrosPolicyStackBridge::OnDevicePolicyLoadedDeprecated,
            weak_ptr_factory_.GetWeakPtr()));
  }
}

void AshLacrosPolicyStackBridge::OnDevicePolicyLoadedDeprecated(
    base::Value device_policy,
    base::Value legend_data) {
  base::Value::Dict device_policy_dict;
  base::Value::Dict legend_data_dict;
  if (device_policy.is_dict()) {
    device_policy_dict = std::move(device_policy).TakeDict();
  }
  if (legend_data.is_dict()) {
    legend_data_dict = std::move(legend_data).TakeDict();
  }
  OnDevicePolicyLoaded(std::move(device_policy_dict),
                       std::move(legend_data_dict));
}

void AshLacrosPolicyStackBridge::OnDevicePolicyLoaded(
    base::Value::Dict device_policy,
    base::Value::Dict legend_data) {
  if (device_policy != device_policy_) {
    device_policy_ = std::move(device_policy);
    device_policy_status_ = std::move(legend_data);
  }
  NotifyStatusChange();
  NotifyValueChange();
}