blob: bd2acc04deaf2910ce116da8f63fa9d07a7996fc [file] [log] [blame]
// Copyright 2019 The Chromium 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 "chrome/browser/chromeos/extensions/printing/printing_api_utils.h"
#include <algorithm>
#include <memory>
#include <utility>
#include "base/json/json_reader.h"
#include "base/stl_util.h"
#include "base/values.h"
#include "chromeos/printing/printer_configuration.h"
#include "components/cloud_devices/common/cloud_device_description.h"
#include "components/cloud_devices/common/printer_description.h"
#include "printing/backend/print_backend.h"
#include "printing/mojom/print.mojom.h"
#include "printing/print_settings.h"
#include "third_party/re2/src/re2/re2.h"
namespace extensions {
namespace idl = api::printing;
namespace {
constexpr char kLocal[] = "local";
constexpr char kKind[] = "kind";
constexpr char kIdPattern[] = "idPattern";
constexpr char kNamePattern[] = "namePattern";
idl::PrinterSource PrinterSourceToIdl(chromeos::Printer::Source source) {
switch (source) {
case chromeos::Printer::Source::SRC_USER_PREFS:
return idl::PRINTER_SOURCE_USER;
case chromeos::Printer::Source::SRC_POLICY:
return idl::PRINTER_SOURCE_POLICY;
}
NOTREACHED();
return idl::PRINTER_SOURCE_USER;
}
bool DoesPrinterMatchDefaultPrinterRules(
const chromeos::Printer& printer,
const base::Optional<DefaultPrinterRules>& rules) {
if (!rules.has_value())
return false;
return (rules->kind.empty() || rules->kind == kLocal) &&
(rules->id_pattern.empty() ||
RE2::FullMatch(printer.id(), rules->id_pattern)) &&
(rules->name_pattern.empty() ||
RE2::FullMatch(printer.display_name(), rules->name_pattern));
}
} // namespace
base::Optional<DefaultPrinterRules> GetDefaultPrinterRules(
const std::string& default_destination_selection_rules) {
if (default_destination_selection_rules.empty())
return base::nullopt;
base::Optional<base::Value> default_destination_selection_rules_value =
base::JSONReader::Read(default_destination_selection_rules);
if (!default_destination_selection_rules_value)
return base::nullopt;
DefaultPrinterRules default_printer_rules;
const std::string* kind =
default_destination_selection_rules_value->FindStringKey(kKind);
if (kind)
default_printer_rules.kind = *kind;
const std::string* id_pattern =
default_destination_selection_rules_value->FindStringKey(kIdPattern);
if (id_pattern)
default_printer_rules.id_pattern = *id_pattern;
const std::string* name_pattern =
default_destination_selection_rules_value->FindStringKey(kNamePattern);
if (name_pattern)
default_printer_rules.name_pattern = *name_pattern;
return default_printer_rules;
}
idl::Printer PrinterToIdl(
const chromeos::Printer& printer,
const base::Optional<DefaultPrinterRules>& default_printer_rules,
const base::flat_map<std::string, int>& recently_used_ranks) {
idl::Printer idl_printer;
idl_printer.id = printer.id();
idl_printer.name = printer.display_name();
idl_printer.description = printer.description();
idl_printer.uri = printer.uri().GetNormalized();
idl_printer.source = PrinterSourceToIdl(printer.source());
idl_printer.is_default =
DoesPrinterMatchDefaultPrinterRules(printer, default_printer_rules);
auto it = recently_used_ranks.find(printer.id());
if (it != recently_used_ranks.end())
idl_printer.recently_used_rank = std::make_unique<int>(it->second);
else
idl_printer.recently_used_rank = nullptr;
return idl_printer;
}
idl::PrinterStatus PrinterStatusToIdl(chromeos::PrinterErrorCode status) {
switch (status) {
case chromeos::PrinterErrorCode::NO_ERROR:
return idl::PRINTER_STATUS_AVAILABLE;
case chromeos::PrinterErrorCode::PAPER_JAM:
return idl::PRINTER_STATUS_PAPER_JAM;
case chromeos::PrinterErrorCode::OUT_OF_PAPER:
return idl::PRINTER_STATUS_OUT_OF_PAPER;
case chromeos::PrinterErrorCode::OUT_OF_INK:
return idl::PRINTER_STATUS_OUT_OF_INK;
case chromeos::PrinterErrorCode::DOOR_OPEN:
return idl::PRINTER_STATUS_DOOR_OPEN;
case chromeos::PrinterErrorCode::PRINTER_UNREACHABLE:
return idl::PRINTER_STATUS_UNREACHABLE;
case chromeos::PrinterErrorCode::TRAY_MISSING:
return idl::PRINTER_STATUS_TRAY_MISSING;
case chromeos::PrinterErrorCode::OUTPUT_FULL:
return idl::PRINTER_STATUS_OUTPUT_FULL;
case chromeos::PrinterErrorCode::STOPPED:
return idl::PRINTER_STATUS_STOPPED;
default:
return idl::PRINTER_STATUS_GENERIC_ISSUE;
}
return idl::PRINTER_STATUS_GENERIC_ISSUE;
}
std::unique_ptr<printing::PrintSettings> ParsePrintTicket(base::Value ticket) {
cloud_devices::CloudDeviceDescription description;
if (!description.InitFromValue(std::move(ticket)))
return nullptr;
auto settings = std::make_unique<printing::PrintSettings>();
cloud_devices::printer::ColorTicketItem color;
if (!color.LoadFrom(description))
return nullptr;
switch (color.value().type) {
case cloud_devices::printer::ColorType::STANDARD_MONOCHROME:
case cloud_devices::printer::ColorType::CUSTOM_MONOCHROME:
settings->set_color(printing::GRAY);
break;
case cloud_devices::printer::ColorType::STANDARD_COLOR:
case cloud_devices::printer::ColorType::CUSTOM_COLOR:
case cloud_devices::printer::ColorType::AUTO_COLOR:
settings->set_color(printing::COLOR);
break;
default:
NOTREACHED();
break;
}
cloud_devices::printer::DuplexTicketItem duplex;
if (!duplex.LoadFrom(description))
return nullptr;
switch (duplex.value()) {
case cloud_devices::printer::DuplexType::NO_DUPLEX:
settings->set_duplex_mode(printing::mojom::DuplexMode::kSimplex);
break;
case cloud_devices::printer::DuplexType::LONG_EDGE:
settings->set_duplex_mode(printing::mojom::DuplexMode::kLongEdge);
break;
case cloud_devices::printer::DuplexType::SHORT_EDGE:
settings->set_duplex_mode(printing::mojom::DuplexMode::kShortEdge);
break;
default:
NOTREACHED();
break;
}
cloud_devices::printer::OrientationTicketItem orientation;
if (!orientation.LoadFrom(description))
return nullptr;
switch (orientation.value()) {
case cloud_devices::printer::OrientationType::LANDSCAPE:
settings->SetOrientation(/*landscape=*/true);
break;
case cloud_devices::printer::OrientationType::PORTRAIT:
settings->SetOrientation(/*landscape=*/false);
break;
default:
NOTREACHED();
break;
}
cloud_devices::printer::CopiesTicketItem copies;
if (!copies.LoadFrom(description) || copies.value() < 1)
return nullptr;
settings->set_copies(copies.value());
cloud_devices::printer::DpiTicketItem dpi;
if (!dpi.LoadFrom(description))
return nullptr;
settings->set_dpi_xy(dpi.value().horizontal, dpi.value().vertical);
cloud_devices::printer::MediaTicketItem media;
if (!media.LoadFrom(description))
return nullptr;
cloud_devices::printer::Media media_value = media.value();
printing::PrintSettings::RequestedMedia requested_media;
if (media_value.width_um <= 0 || media_value.height_um <= 0 ||
media_value.vendor_id.empty()) {
return nullptr;
}
requested_media.size_microns =
gfx::Size(media_value.width_um, media_value.height_um);
requested_media.vendor_id = media_value.vendor_id;
settings->set_requested_media(requested_media);
cloud_devices::printer::CollateTicketItem collate;
if (!collate.LoadFrom(description))
return nullptr;
settings->set_collate(collate.value());
return settings;
}
bool CheckSettingsAndCapabilitiesCompatibility(
const printing::PrintSettings& settings,
const printing::PrinterSemanticCapsAndDefaults& capabilities) {
if (settings.collate() && !capabilities.collate_capable)
return false;
if (settings.copies() > capabilities.copies_max)
return false;
if (!base::Contains(capabilities.duplex_modes, settings.duplex_mode()))
return false;
base::Optional<bool> is_color =
::printing::IsColorModelSelected(settings.color());
bool color_mode_selected = is_color.has_value() && is_color.value();
if (!color_mode_selected &&
capabilities.bw_model == printing::UNKNOWN_COLOR_MODEL) {
return false;
}
if (color_mode_selected &&
capabilities.color_model == printing::UNKNOWN_COLOR_MODEL) {
return false;
}
if (!base::Contains(capabilities.dpis, settings.dpi_size()))
return false;
const printing::PrintSettings::RequestedMedia& requested_media =
settings.requested_media();
return std::any_of(
capabilities.papers.begin(), capabilities.papers.end(),
[&requested_media](
const printing::PrinterSemanticCapsAndDefaults::Paper& paper) {
return paper.size_um == requested_media.size_microns &&
paper.vendor_id == requested_media.vendor_id;
});
}
} // namespace extensions