| // 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 <cstdint> |
| #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 "chrome/browser/ash/printing/enterprise/print_job_options_translator.h" |
| #include "url/gurl.h" |
| |
| namespace chromeos { |
| |
| namespace { |
| |
| // Top-level field names. |
| const char kGuid[] = "guid"; |
| const char kDisplayName[] = "display_name"; |
| const char kDescription[] = "description"; |
| const char kUri[] = "uri"; |
| const char kPpdResource[] = "ppd_resource"; |
| const char kPrintJobOptions[] = "print_job_options"; |
| |
| // 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* description = config.FindString(kDescription); |
| const std::string* uri = config.FindString(kUri); |
| const base::Value::Dict* ppd_resource = config.FindDict(kPpdResource); |
| const base::Value::Dict* print_job_options = |
| config.FindDict(kPrintJobOptions); |
| |
| 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; |
| } |
| if (print_job_options) { |
| *result.mutable_print_job_options() = |
| ManagedPrintOptionsProtoFromDict(*print_job_options); |
| } |
| 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()); |
| } |
| |
| if (managed_printer.has_print_job_options()) { |
| std::optional<Printer::ManagedPrintOptions> print_job_options = |
| ChromeOsPrintOptionsFromManagedPrintOptions( |
| managed_printer.print_job_options()); |
| if (!print_job_options) { |
| LOG(WARNING) << base::StringPrintf( |
| "Managed printer '%s' has invalid %s value: %s", |
| managed_printer.display_name().c_str(), kPrintJobOptions, |
| managed_printer.print_job_options().SerializeAsString().c_str()); |
| return std::nullopt; |
| } |
| printer.set_print_job_options(print_job_options.value()); |
| } |
| |
| return printer; |
| } |
| |
| } // namespace chromeos |