0

Add printable area to PrinterSemanticCapsAndDefaults::Paper

Add and retrieve information about printable area when fetching
PrinterSemanticCapsAndDefaults from the printer driver.

This will allow Print Preview to retrieve printable area information
once when calling PrintBackend::GetPrinterSemanticCapsAndDefaults(), so
Print Preview does not have to communicate with the printer driver
multiple times for the printable area.

Bug: 879284
Change-Id: If28734a35f94be7f0eb77de7ce14e3dfe588a617
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4104564
Commit-Queue: Andy Phan <andyphan@chromium.org>
Reviewed-by: Mustafa Emre Acer <meacer@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1099567}
This commit is contained in:
Andy Phan
2023-02-01 00:27:46 +00:00
committed by Chromium LUCI CQ
parent d678ebc1fc
commit d4be1cbc38
11 changed files with 139 additions and 35 deletions

@ -56,6 +56,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "url/gurl.h"
@ -228,7 +229,7 @@ class TestLocalPrinterAshWithPrinterConfigurer : public TestLocalPrinterAsh {
class LocalPrinterAshTestBase : public testing::Test {
public:
const std::vector<PrinterSemanticCapsAndDefaults::Paper> kPapers = {
{"bar", "vendor", {600, 600}}};
{"bar", "vendor", gfx::Size(600, 600), gfx::Rect(0, 0, 600, 600)}};
LocalPrinterAshTestBase() = default;
LocalPrinterAshTestBase(const LocalPrinterAshTestBase&) = delete;
@ -1035,7 +1036,7 @@ TEST(LocalPrinterAsh, StatusToMojom) {
class LocalPrinterAshWithOAuth2Test : public testing::Test {
public:
const std::vector<PrinterSemanticCapsAndDefaults::Paper> kPapers = {
{"bar", "vendor", {600, 600}}};
{"bar", "vendor", gfx::Size(600, 600), gfx::Rect(0, 0, 600, 600)}};
LocalPrinterAshWithOAuth2Test() = default;
LocalPrinterAshWithOAuth2Test(const LocalPrinterAshWithOAuth2Test&) = delete;

@ -24,6 +24,8 @@
#include "printing/print_job_constants.h"
#include "printing/printing_features.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#if BUILDFLAG(ENABLE_OOP_PRINTING)
#include "chrome/browser/printing/print_backend_service_manager.h"
@ -294,8 +296,8 @@ class LocalPrinterHandlerDefaultTestBase : public testing::Test {
bool is_default,
bool requires_elevated_permissions) {
auto caps = std::make_unique<PrinterSemanticCapsAndDefaults>();
caps->papers.emplace_back(
PrinterSemanticCapsAndDefaults::Paper{"bar", "vendor", {600, 600}});
caps->papers.emplace_back(PrinterSemanticCapsAndDefaults::Paper{
"bar", "vendor", gfx::Size(600, 600), gfx::Rect(0, 0, 600, 600)});
auto basic_info = std::make_unique<PrinterBasicInfo>(
id, display_name, description,
/*printer_status=*/0, is_default, PrinterBasicInfoOptions{});

@ -9,7 +9,10 @@
#include <vector>
#include "chrome/common/printing/print_media_l10n.h"
#include "printing/backend/print_backend.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
namespace printing {
@ -137,14 +140,18 @@ TEST(PrintMediaL10N, SortGroupsOrdered) {
// Verifies that inch paper sizes are sorted by width, height, name.
TEST(PrintMediaL10N, SortInchSizes) {
PaperWithSizeInfo p1 = {MediaSizeInfo{u"1x3", MediaSizeGroup::kSizeIn},
Paper{"1x3", "in", gfx::Size(1, 3)}};
PaperWithSizeInfo p2 = {MediaSizeInfo{u"2x1", MediaSizeGroup::kSizeIn},
Paper{"2x1", "in", gfx::Size(2, 1)}};
PaperWithSizeInfo p3 = {MediaSizeInfo{u"2x2", MediaSizeGroup::kSizeIn},
Paper{"2x2", "in", gfx::Size(2, 2)}};
PaperWithSizeInfo p4 = {MediaSizeInfo{u"2x2 B", MediaSizeGroup::kSizeIn},
Paper{"2x2 B", "in", gfx::Size(2, 2)}};
PaperWithSizeInfo p1 = {
MediaSizeInfo{u"1x3", MediaSizeGroup::kSizeIn},
Paper{"1x3", "in", gfx::Size(1, 3), gfx::Rect(0, 0, 1, 3)}};
PaperWithSizeInfo p2 = {
MediaSizeInfo{u"2x1", MediaSizeGroup::kSizeIn},
Paper{"2x1", "in", gfx::Size(2, 1), gfx::Rect(0, 0, 2, 1)}};
PaperWithSizeInfo p3 = {
MediaSizeInfo{u"2x2", MediaSizeGroup::kSizeIn},
Paper{"2x2", "in", gfx::Size(2, 2), gfx::Rect(0, 0, 2, 2)}};
PaperWithSizeInfo p4 = {
MediaSizeInfo{u"2x2 B", MediaSizeGroup::kSizeIn},
Paper{"2x2 B", "in", gfx::Size(2, 2), gfx::Rect(0, 0, 2, 2)}};
std::vector<PaperWithSizeInfo> papers = {p4, p1, p2, p3};
std::vector<PaperWithSizeInfo> expected = {p1, p2, p3, p4};
@ -156,14 +163,18 @@ TEST(PrintMediaL10N, SortInchSizes) {
// Verifies that mm paper sizes are sorted by width, height, name.
TEST(PrintMediaL10N, SortMmSizes) {
PaperWithSizeInfo p1 = {MediaSizeInfo{u"1x3", MediaSizeGroup::kSizeMm},
Paper{"1x3", "mm", gfx::Size(1, 3)}};
PaperWithSizeInfo p2 = {MediaSizeInfo{u"2x1", MediaSizeGroup::kSizeMm},
Paper{"2x1", "mm", gfx::Size(2, 1)}};
PaperWithSizeInfo p3 = {MediaSizeInfo{u"2x2", MediaSizeGroup::kSizeMm},
Paper{"2x2", "mm", gfx::Size(2, 2)}};
PaperWithSizeInfo p4 = {MediaSizeInfo{u"2x2 B", MediaSizeGroup::kSizeMm},
Paper{"2x2 B", "mm", gfx::Size(2, 2)}};
PaperWithSizeInfo p1 = {
MediaSizeInfo{u"1x3", MediaSizeGroup::kSizeMm},
Paper{"1x3", "mm", gfx::Size(1, 3), gfx::Rect(0, 0, 1, 3)}};
PaperWithSizeInfo p2 = {
MediaSizeInfo{u"2x1", MediaSizeGroup::kSizeMm},
Paper{"2x1", "mm", gfx::Size(2, 1), gfx::Rect(0, 0, 2, 1)}};
PaperWithSizeInfo p3 = {
MediaSizeInfo{u"2x2", MediaSizeGroup::kSizeMm},
Paper{"2x2", "mm", gfx::Size(2, 2), gfx::Rect(0, 0, 2, 2)}};
PaperWithSizeInfo p4 = {
MediaSizeInfo{u"2x2 B", MediaSizeGroup::kSizeMm},
Paper{"2x2 B", "mm", gfx::Size(2, 2), gfx::Rect(0, 0, 2, 2)}};
std::vector<PaperWithSizeInfo> papers = {p4, p1, p2, p3};
std::vector<PaperWithSizeInfo> expected = {p1, p2, p3, p4};
@ -175,14 +186,18 @@ TEST(PrintMediaL10N, SortMmSizes) {
// Verifies that named paper sizes are sorted by name, width, height.
TEST(PrintMediaL10N, SortNamedSizes) {
PaperWithSizeInfo p1 = {MediaSizeInfo{u"AAA", MediaSizeGroup::kSizeNamed},
Paper{"AAA", "name", gfx::Size(50, 50)}};
PaperWithSizeInfo p2 = {MediaSizeInfo{u"BBB", MediaSizeGroup::kSizeNamed},
Paper{"BBB", "name1", gfx::Size(1, 3)}};
PaperWithSizeInfo p3 = {MediaSizeInfo{u"BBB", MediaSizeGroup::kSizeNamed},
Paper{"BBB", "name2", gfx::Size(2, 2)}};
PaperWithSizeInfo p4 = {MediaSizeInfo{u"BBB", MediaSizeGroup::kSizeNamed},
Paper{"BBB", "name3", gfx::Size(2, 3)}};
PaperWithSizeInfo p1 = {
MediaSizeInfo{u"AAA", MediaSizeGroup::kSizeNamed},
Paper{"AAA", "name", gfx::Size(50, 50), gfx::Rect(0, 0, 50, 50)}};
PaperWithSizeInfo p2 = {
MediaSizeInfo{u"BBB", MediaSizeGroup::kSizeNamed},
Paper{"BBB", "name1", gfx::Size(1, 3), gfx::Rect(0, 0, 1, 3)}};
PaperWithSizeInfo p3 = {
MediaSizeInfo{u"BBB", MediaSizeGroup::kSizeNamed},
Paper{"BBB", "name2", gfx::Size(2, 2), gfx::Rect(0, 0, 2, 2)}};
PaperWithSizeInfo p4 = {
MediaSizeInfo{u"BBB", MediaSizeGroup::kSizeNamed},
Paper{"BBB", "name3", gfx::Size(2, 3), gfx::Rect(0, 0, 2, 3)}};
std::vector<PaperWithSizeInfo> papers = {p4, p1, p2, p3};
std::vector<PaperWithSizeInfo> expected = {p1, p2, p3, p4};

@ -22,11 +22,13 @@ struct PrinterBasicInfo {
// Paper used by printer semantic capabilities and defaults.
// Corresponds to `printing::PrinterSemanticCapsAndDefaults::Paper` in
// printing/backend/print_backend.h.
// For backwards compatibility, `printable_area_um` must be optional.
[Stable]
struct Paper {
string display_name;
string vendor_id;
gfx.mojom.Size size_um;
[MinVersion=1] gfx.mojom.Rect? printable_area_um;
};
// An advanced capability value for ChromeOS printing.

@ -112,8 +112,30 @@ 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);
absl::optional<gfx::Rect> printable_area_um;
if (!data.ReadDisplayName(&out->display_name) ||
!data.ReadVendorId(&out->vendor_id) || !data.ReadSizeUm(&out->size_um) ||
!data.ReadPrintableAreaUm(&printable_area_um)) {
return false;
}
// For backwards compatibility, allow printable area to be missing. Set the
// default printable area to be the page size.
out->printable_area_um = printable_area_um.value_or(gfx::Rect(out->size_um));
// Allow empty Papers, since PrinterSemanticCapsAndDefaults can have empty
// default Papers.
if (out->display_name.empty() && out->vendor_id.empty() &&
out->size_um.IsEmpty() && out->printable_area_um.IsEmpty()) {
return true;
}
// Invalid if the printable area is empty, has negative values or has a larger
// width or height than the size of the Paper.
return !out->printable_area_um.IsEmpty() && out->printable_area_um.x() >= 0 &&
out->printable_area_um.y() >= 0 &&
out->printable_area_um.width() <= out->size_um.width() &&
out->printable_area_um.height() <= out->size_um.height();
}
#if BUILDFLAG(IS_CHROMEOS)

@ -12,6 +12,7 @@
#include "printing/backend/mojom/print_backend.mojom-shared.h"
#include "printing/backend/print_backend.h"
#include "printing/mojom/print.mojom.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
namespace mojo {
@ -59,6 +60,10 @@ struct StructTraits<printing::mojom::PaperDataView,
const printing::PrinterSemanticCapsAndDefaults::Paper& p) {
return p.size_um;
}
static const gfx::Rect& printable_area_um(
const printing::PrinterSemanticCapsAndDefaults::Paper& p) {
return p.printable_area_um;
}
static bool Read(printing::mojom::PaperDataView data,
printing::PrinterSemanticCapsAndDefaults::Paper* out);

@ -88,6 +88,52 @@ TEST(PrintBackendMojomTraitsTest, TestSerializeAndDeserializePaper) {
}
}
TEST(PrintBackendMojomTraitsTest, TestPaperEmpty) {
// Empty Papers should be valid.
PrinterSemanticCapsAndDefaults::Paper input;
PrinterSemanticCapsAndDefaults::Paper output;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Paper>(input, output));
EXPECT_EQ(input, output);
}
TEST(PrintBackendMojomTraitsTest, TestPaperEmptyPrintableArea) {
// The printable area is empty, but the other fields are not, so it should be
// invalid.
PrinterSemanticCapsAndDefaults::Paper input{
/*display_name=*/"display_name", /*vendor_id=*/"vendor_id",
/*size_um=*/gfx::Size(4000, 7000),
/*printable_area_um=*/gfx::Rect(0, 100, 0, 0)};
PrinterSemanticCapsAndDefaults::Paper output;
EXPECT_FALSE(
mojo::test::SerializeAndDeserialize<mojom::Paper>(input, output));
}
TEST(PrintBackendMojomTraitsTest, TestPaperPrintableAreaLargerThanSize) {
// The printable area is larger than the size, so it should be invalid.
PrinterSemanticCapsAndDefaults::Paper input{
/*display_name=*/"display_name", /*vendor_id=*/"vendor_id",
/*size_um=*/gfx::Size(4000, 7000),
/*printable_area_um=*/gfx::Rect(0, 100, 4100, 7200)};
PrinterSemanticCapsAndDefaults::Paper output;
EXPECT_FALSE(
mojo::test::SerializeAndDeserialize<mojom::Paper>(input, output));
}
TEST(PrintBackendMojomTraitsTest, TestPaperNegativePrintableArea) {
// The printable area has negative x and y values, so it should be invalid.
PrinterSemanticCapsAndDefaults::Paper input{
/*display_name=*/"display_name", /*vendor_id=*/"vendor_id",
/*size_um=*/gfx::Size(4000, 7000),
/*printable_area_um=*/gfx::Rect(-10, -10, 2800, 6000)};
PrinterSemanticCapsAndDefaults::Paper output;
EXPECT_FALSE(
mojo::test::SerializeAndDeserialize<mojom::Paper>(input, output));
}
#if BUILDFLAG(IS_CHROMEOS)
TEST(PrintBackendMojomTraitsTest,
TestSerializeAndDeserializeAdvancedCapability) {

@ -157,7 +157,8 @@ XpsCapabilities::~XpsCapabilities() = default;
bool PrinterSemanticCapsAndDefaults::Paper::operator==(
const PrinterSemanticCapsAndDefaults::Paper& other) const {
return display_name == other.display_name && vendor_id == other.vendor_id &&
size_um == other.size_um;
size_um == other.size_um &&
printable_area_um == other.printable_area_um;
}
PrinterSemanticCapsAndDefaults::PrinterSemanticCapsAndDefaults() = default;

@ -18,6 +18,7 @@
#include "build/build_config.h"
#include "printing/mojom/print.mojom.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#if BUILDFLAG(IS_WIN)
@ -192,6 +193,9 @@ struct COMPONENT_EXPORT(PRINT_BACKEND) PrinterSemanticCapsAndDefaults {
std::string vendor_id;
gfx::Size size_um;
// Origin (x,y) is at the bottom-left.
gfx::Rect printable_area_um;
bool operator==(const Paper& other) const;
};
using Papers = std::vector<Paper>;

@ -40,16 +40,20 @@ struct OptionalSampleCapabilities {
inline const PrinterSemanticCapsAndDefaults::Paper kPaperA3{
/*display_name=*/"A3", /*vendor_id=*/"67",
/*size_um=*/gfx::Size(7016, 9921)};
/*size_um=*/gfx::Size(7016, 9921),
/*printable_area_um=*/gfx::Rect(0, 0, 7016, 9921)};
inline const PrinterSemanticCapsAndDefaults::Paper kPaperA4{
/*display_name=*/"A4", /*vendor_id=*/"12",
/*size_um=*/gfx::Size(4961, 7016)};
/*size_um=*/gfx::Size(4961, 7016),
/*printable_area_um=*/gfx::Rect(100, 200, 500, 800)};
inline const PrinterSemanticCapsAndDefaults::Paper kPaperLetter{
/*display_name=*/"Letter", /*vendor_id=*/"45",
/*size_um=*/gfx::Size(5100, 6600)};
/*size_um=*/gfx::Size(5100, 6600),
/*printable_area_um=*/gfx::Rect(0, 0, 5100, 6600)};
inline const PrinterSemanticCapsAndDefaults::Paper kPaperLedger{
/*display_name=*/"Ledger", /*vendor_id=*/"89",
/*size_um=*/gfx::Size(6600, 10200)};
/*size_um=*/gfx::Size(6600, 10200),
/*printable_area_um=*/gfx::Rect(0, 0, 6600, 10200)};
#if BUILDFLAG(IS_CHROMEOS)
inline const AdvancedCapability kAdvancedCapability1(

@ -11,6 +11,7 @@
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "printing/units.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/geometry/size_f.h"
@ -109,6 +110,7 @@ PrinterSemanticCapsAndDefaults::Paper ParsePaper(base::StringPiece value) {
PrinterSemanticCapsAndDefaults::Paper paper;
paper.vendor_id = std::string(value);
paper.size_um = DimensionsToMicrons(dimensions);
paper.printable_area_um = gfx::Rect(paper.size_um);
// Omits the final token describing the media dimensions.
pieces.pop_back();
paper.display_name = base::JoinString(pieces, " ");