chromium/chrome/browser/ash/printing/enterprise/managed_printer_translator.cc

// Copyright 2024 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/ash/printing/enterprise/managed_printer_translator.h"

#include <optional>
#include <string>

#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "chrome/browser/ash/printing/enterprise/managed_printer_configuration.pb.h"
#include "url/gurl.h"

namespace chromeos {

namespace {

// Top-level field names.
const char kDisplayName[] = "display_name";
const char kDescription[] = "description";
const char kUri[] = "uri";
const char kPpdResource[] = "ppd_resource";
const char kGuid[] = "guid";

// PpdResource field names.
const char kUserSuppliedPpdUri[] = "user_supplied_ppd_uri";
const char kEffectiveModel[] = "effective_model";
const char kAutoconf[] = "autoconf";

std::optional<ManagedPrinterConfiguration::PpdResource> PpdResourceFromDict(
    const base::Value::Dict& ppd_resource) {
  std::optional<bool> autoconf = ppd_resource.FindBool(kAutoconf);
  const std::string* effective_model = ppd_resource.FindString(kEffectiveModel);
  const std::string* user_supplied_ppd_uri =
      ppd_resource.FindString(kUserSuppliedPpdUri);

  bool has_autoconf = autoconf.has_value();
  bool has_effective_model = (effective_model != nullptr);
  bool has_user_supplied_ppd_uri = (user_supplied_ppd_uri != nullptr);

  bool has_one_ppd_resource =
      (has_autoconf + has_effective_model + has_user_supplied_ppd_uri) == 1;
  if (!has_one_ppd_resource) {
    LOG(WARNING) << base::StringPrintf(
        "Could not convert a dictionary to PpdResource: multiple values set "
        "for the 'resource' oneof field: %s",
        ppd_resource.DebugString().c_str());
    return std::nullopt;
  }

  ManagedPrinterConfiguration::PpdResource result;
  if (autoconf.has_value()) {
    result.set_autoconf(autoconf.value());
  }
  if (effective_model) {
    result.set_effective_model(*effective_model);
  }
  if (user_supplied_ppd_uri) {
    result.set_user_supplied_ppd_uri(*user_supplied_ppd_uri);
  }

  return result;
}

std::optional<Printer::PpdReference> ManagedPpdResourceToPpdReference(
    const ManagedPrinterConfiguration::PpdResource& ppd_resource) {
  Printer::PpdReference ppd_reference;
  switch (ppd_resource.resource_case()) {
    case ManagedPrinterConfiguration::PpdResource::kAutoconf: {
      if (!ppd_resource.autoconf()) {
        LOG(WARNING) << base::StringPrintf(
            "Invalid PPD resource - autoconf must either be unset or set to "
            "true: %s",
            ppd_resource.SerializeAsString().c_str());
        return std::nullopt;
      }
      ppd_reference.autoconf = ppd_resource.autoconf();
      break;
    }
    case ManagedPrinterConfiguration::PpdResource::kUserSuppliedPpdUri: {
      GURL url(ppd_resource.user_supplied_ppd_uri());
      if (!url.is_valid() || !url.SchemeIsHTTPOrHTTPS()) {
        LOG(WARNING) << base::StringPrintf(
            "Invalid PPD resource - invalid user_supplied_ppd_url resource: %s",
            ppd_resource.SerializeAsString().c_str());
        return std::nullopt;
      }
      ppd_reference.user_supplied_ppd_url =
          ppd_resource.user_supplied_ppd_uri();
      break;
    }
    case ManagedPrinterConfiguration::PpdResource::kEffectiveModel: {
      ppd_reference.effective_make_and_model = ppd_resource.effective_model();
      break;
    }
    case ManagedPrinterConfiguration::PpdResource::RESOURCE_NOT_SET: {
      LOG(WARNING) << "Invalid PPD resource - resource is not set";
      return std::nullopt;
    }
  }
  return ppd_reference;
}

}  // namespace

std::optional<ManagedPrinterConfiguration> ManagedPrinterConfigFromDict(
    const base::Value::Dict& config) {
  const std::string* guid = config.FindString(kGuid);
  const std::string* display_name = config.FindString(kDisplayName);
  const std::string* uri = config.FindString(kUri);
  const base::Value::Dict* ppd_resource = config.FindDict(kPpdResource);
  const std::string* description = config.FindString(kDescription);

  ManagedPrinterConfiguration result;
  if (guid) {
    result.set_guid(*guid);
  }
  if (display_name) {
    result.set_display_name(*display_name);
  }
  if (uri) {
    result.set_uri(*uri);
  }
  if (description) {
    result.set_description(*description);
  }
  if (ppd_resource) {
    auto ppd_resource_opt = PpdResourceFromDict(*ppd_resource);
    if (!ppd_resource_opt) {
      LOG(WARNING) << base::StringPrintf(
          "Could not convert a dictionary to ManagedPrinterConfiguration: "
          "invalid 'ppd_resource' field: %s",
          config.DebugString().c_str());
      return std::nullopt;
    }
    *result.mutable_ppd_resource() = *ppd_resource_opt;
  }
  return result;
}

std::optional<Printer> PrinterFromManagedPrinterConfig(
    const ManagedPrinterConfiguration& managed_printer) {
  static auto LogRequiredFieldMissing = [](std::string_view field) {
    LOG(WARNING) << "Managed printer is missing required field: " << field;
  };

  if (!managed_printer.has_guid()) {
    LogRequiredFieldMissing(kGuid);
    return std::nullopt;
  }
  if (!managed_printer.has_display_name()) {
    LogRequiredFieldMissing(kDisplayName);
    return std::nullopt;
  }
  if (!managed_printer.has_uri()) {
    LogRequiredFieldMissing(kUri);
    return std::nullopt;
  }
  if (!managed_printer.has_ppd_resource()) {
    LogRequiredFieldMissing(kPpdResource);
    return std::nullopt;
  }

  Printer printer(managed_printer.guid());
  printer.set_source(Printer::SRC_POLICY);
  printer.set_display_name(managed_printer.display_name());
  std::string set_uri_error_message;
  if (!printer.SetUri(managed_printer.uri(), &set_uri_error_message)) {
    LOG(WARNING) << base::StringPrintf(
        "Managed printer '%s' has invalid %s value: %s, error: %s",
        managed_printer.display_name().c_str(), kUri,
        managed_printer.uri().c_str(), set_uri_error_message.c_str());
    return std::nullopt;
  }

  auto ppd_reference =
      ManagedPpdResourceToPpdReference(managed_printer.ppd_resource());
  if (!ppd_reference.has_value()) {
    LOG(WARNING) << base::StringPrintf(
        "Managed printer '%s' has invalid %s value: %s",
        managed_printer.display_name().c_str(), kPpdResource,
        managed_printer.ppd_resource().SerializeAsString().c_str());
    return std::nullopt;
  }
  *printer.mutable_ppd_reference() = *ppd_reference;

  if (managed_printer.has_description()) {
    printer.set_description(managed_printer.description());
  }
  return printer;
}

}  // namespace chromeos