blob: ca7a99e5182d0f2bf5b09b164c53555e4b696935 [file] [log] [blame]
// Copyright 2020 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 "printing/backend/mojom/print_backend_mojom_traits.h"
#include <map>
#include "base/logging.h"
#include "build/chromeos_buildflags.h"
#include "ui/gfx/geometry/mojom/geometry.mojom-shared.h"
#include "ui/gfx/geometry/mojom/geometry_mojom_traits.h"
// Implementations of std::less<> here are for purposes of detecting duplicate
// entries in arrays. They do not require strict checks of all fields, but
// instead focus on identifying attributes that would be used to clearly
// distinguish properties to a user. E.g., if two entries have the same
// displayable name but different corresponding values, consider that to be a
// duplicate for these purposes.
namespace std {
template <>
struct less<::gfx::Size> {
bool operator()(const ::gfx::Size& lhs, const ::gfx::Size& rhs) const {
if (lhs.width() < rhs.width())
return true;
return lhs.height() < rhs.height();
}
};
template <>
struct less<::printing::PrinterSemanticCapsAndDefaults::Paper> {
bool operator()(
const ::printing::PrinterSemanticCapsAndDefaults::Paper& lhs,
const ::printing::PrinterSemanticCapsAndDefaults::Paper& rhs) const {
if (lhs.display_name < rhs.display_name)
return true;
return lhs.vendor_id < rhs.vendor_id;
}
};
#if BUILDFLAG(IS_CHROMEOS_ASH)
template <>
struct less<::printing::AdvancedCapability> {
bool operator()(const ::printing::AdvancedCapability& lhs,
const ::printing::AdvancedCapability& rhs) const {
if (lhs.name < rhs.name)
return true;
return lhs.display_name < rhs.display_name;
}
};
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
} // namespace std
namespace mojo {
namespace {
template <class Key>
class DuplicateChecker {
public:
bool HasDuplicates(const std::vector<Key>& items) {
std::map<Key, bool> items_encountered;
for (auto it = items.begin(); it != items.end(); ++it) {
auto found = items_encountered.find(*it);
if (found != items_encountered.end())
return true;
items_encountered[*it] = true;
}
return false;
}
};
} // namespace
// static
bool StructTraits<printing::mojom::PrinterBasicInfoDataView,
printing::PrinterBasicInfo>::
Read(printing::mojom::PrinterBasicInfoDataView data,
printing::PrinterBasicInfo* out) {
if (!data.ReadPrinterName(&out->printer_name) ||
!data.ReadDisplayName(&out->display_name) ||
!data.ReadPrinterDescription(&out->printer_description)) {
return false;
}
out->printer_status = data.printer_status();
out->is_default = data.is_default();
if (!data.ReadOptions(&out->options))
return false;
// There should be a non-empty value for `printer_name` since it needs to
// uniquely identify the printer with the operating system among multiple
// possible destinations.
if (out->printer_name.empty()) {
DLOG(ERROR) << "The printer name must not be empty.";
return false;
}
// There should be a non-empty value for `display_name` since it needs to
// uniquely identify the printer in user dialogs among multiple possible
// destinations.
if (out->display_name.empty()) {
DLOG(ERROR) << "The printer's display name must not be empty.";
return false;
}
return true;
}
// static
bool StructTraits<printing::mojom::PaperDataView,
printing::PrinterSemanticCapsAndDefaults::Paper>::
Read(printing::mojom::PaperDataView data,
printing::PrinterSemanticCapsAndDefaults::Paper* out) {
return data.ReadDisplayName(&out->display_name) &&
data.ReadVendorId(&out->vendor_id) && data.ReadSizeUm(&out->size_um);
}
#if BUILDFLAG(IS_CHROMEOS_ASH)
// static
printing::mojom::AdvancedCapabilityType
EnumTraits<printing::mojom::AdvancedCapabilityType,
::printing::AdvancedCapability::Type>::
ToMojom(::printing::AdvancedCapability::Type input) {
switch (input) {
case ::printing::AdvancedCapability::Type::kBoolean:
return printing::mojom::AdvancedCapabilityType::kBoolean;
case ::printing::AdvancedCapability::Type::kFloat:
return printing::mojom::AdvancedCapabilityType::kFloat;
case ::printing::AdvancedCapability::Type::kInteger:
return printing::mojom::AdvancedCapabilityType::kInteger;
case ::printing::AdvancedCapability::Type::kString:
return printing::mojom::AdvancedCapabilityType::kString;
}
NOTREACHED();
return printing::mojom::AdvancedCapabilityType::kString;
}
// static
bool EnumTraits<printing::mojom::AdvancedCapabilityType,
::printing::AdvancedCapability::Type>::
FromMojom(printing::mojom::AdvancedCapabilityType input,
::printing::AdvancedCapability::Type* output) {
switch (input) {
case printing::mojom::AdvancedCapabilityType::kBoolean:
*output = ::printing::AdvancedCapability::Type::kBoolean;
return true;
case printing::mojom::AdvancedCapabilityType::kFloat:
*output = ::printing::AdvancedCapability::Type::kFloat;
return true;
case printing::mojom::AdvancedCapabilityType::kInteger:
*output = ::printing::AdvancedCapability::Type::kInteger;
return true;
case printing::mojom::AdvancedCapabilityType::kString:
*output = ::printing::AdvancedCapability::Type::kString;
return true;
}
NOTREACHED();
return false;
}
// static
bool StructTraits<printing::mojom::AdvancedCapabilityValueDataView,
::printing::AdvancedCapabilityValue>::
Read(printing::mojom::AdvancedCapabilityValueDataView data,
::printing::AdvancedCapabilityValue* out) {
return data.ReadName(&out->name) && data.ReadDisplayName(&out->display_name);
}
// static
bool StructTraits<printing::mojom::AdvancedCapabilityDataView,
::printing::AdvancedCapability>::
Read(printing::mojom::AdvancedCapabilityDataView data,
::printing::AdvancedCapability* out) {
return data.ReadName(&out->name) &&
data.ReadDisplayName(&out->display_name) &&
data.ReadType(&out->type) &&
data.ReadDefaultValue(&out->default_value) &&
data.ReadValues(&out->values);
}
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
// static
bool StructTraits<printing::mojom::PrinterSemanticCapsAndDefaultsDataView,
printing::PrinterSemanticCapsAndDefaults>::
Read(printing::mojom::PrinterSemanticCapsAndDefaultsDataView data,
printing::PrinterSemanticCapsAndDefaults* out) {
out->collate_capable = data.collate_capable();
out->collate_default = data.collate_default();
out->copies_max = data.copies_max();
if (!data.ReadDuplexModes(&out->duplex_modes) ||
!data.ReadDuplexDefault(&out->duplex_default)) {
return false;
}
out->color_changeable = data.color_changeable();
out->color_default = data.color_default();
if (!data.ReadColorModel(&out->color_model) ||
!data.ReadBwModel(&out->bw_model) || !data.ReadPapers(&out->papers) ||
!data.ReadUserDefinedPapers(&out->user_defined_papers) ||
!data.ReadDefaultPaper(&out->default_paper) ||
!data.ReadDpis(&out->dpis) || !data.ReadDefaultDpi(&out->default_dpi)) {
return false;
}
#if BUILDFLAG(IS_CHROMEOS_ASH)
out->pin_supported = data.pin_supported();
if (!data.ReadAdvancedCapabilities(&out->advanced_capabilities))
return false;
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
// Extra validity checks.
// Can not have less than one copy.
if (out->copies_max < 1) {
DLOG(ERROR) << "Must have copies_max greater than zero.";
return false;
}
// There should be at least one item in `papers`.
if (out->papers.empty()) {
DLOG(ERROR) << "The available papers must not be empty.";
return false;
}
// There should not be duplicates in any of the arrays.
DuplicateChecker<printing::mojom::DuplexMode> duplex_modes_dup_checker;
if (duplex_modes_dup_checker.HasDuplicates(out->duplex_modes)) {
DLOG(ERROR) << "Duplicate duplex_modes detected.";
return false;
}
DuplicateChecker<printing::PrinterSemanticCapsAndDefaults::Paper>
papers_dup_checker;
if (papers_dup_checker.HasDuplicates(out->papers)) {
DLOG(ERROR) << "Duplicate papers detected.";
return false;
}
DuplicateChecker<printing::PrinterSemanticCapsAndDefaults::Paper>
user_defined_papers_dup_checker;
if (user_defined_papers_dup_checker.HasDuplicates(out->user_defined_papers)) {
DLOG(ERROR) << "Duplicate user_defined_papers detected.";
return false;
}
DuplicateChecker<gfx::Size> dpis_dup_checker;
if (dpis_dup_checker.HasDuplicates(out->dpis)) {
DLOG(ERROR) << "Duplicate dpis detected.";
return false;
}
#if BUILDFLAG(IS_CHROMEOS_ASH)
DuplicateChecker<printing::AdvancedCapability>
advanced_capabilities_dup_checker;
if (advanced_capabilities_dup_checker.HasDuplicates(
out->advanced_capabilities)) {
DLOG(ERROR) << "Duplicate advanced_capabilities detected.";
return false;
}
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
return true;
}
} // namespace mojo