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

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

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

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

@@ -112,8 +112,30 @@ bool StructTraits<printing::mojom::PaperDataView,
printing::PrinterSemanticCapsAndDefaults::Paper>:: printing::PrinterSemanticCapsAndDefaults::Paper>::
Read(printing::mojom::PaperDataView data, Read(printing::mojom::PaperDataView data,
printing::PrinterSemanticCapsAndDefaults::Paper* out) { printing::PrinterSemanticCapsAndDefaults::Paper* out) {
return data.ReadDisplayName(&out->display_name) && absl::optional<gfx::Rect> printable_area_um;
data.ReadVendorId(&out->vendor_id) && data.ReadSizeUm(&out->size_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) #if BUILDFLAG(IS_CHROMEOS)

@@ -12,6 +12,7 @@
#include "printing/backend/mojom/print_backend.mojom-shared.h" #include "printing/backend/mojom/print_backend.mojom-shared.h"
#include "printing/backend/print_backend.h" #include "printing/backend/print_backend.h"
#include "printing/mojom/print.mojom.h" #include "printing/mojom/print.mojom.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
namespace mojo { namespace mojo {
@@ -59,6 +60,10 @@ struct StructTraits<printing::mojom::PaperDataView,
const printing::PrinterSemanticCapsAndDefaults::Paper& p) { const printing::PrinterSemanticCapsAndDefaults::Paper& p) {
return p.size_um; 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, static bool Read(printing::mojom::PaperDataView data,
printing::PrinterSemanticCapsAndDefaults::Paper* out); 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) #if BUILDFLAG(IS_CHROMEOS)
TEST(PrintBackendMojomTraitsTest, TEST(PrintBackendMojomTraitsTest,
TestSerializeAndDeserializeAdvancedCapability) { TestSerializeAndDeserializeAdvancedCapability) {

@@ -157,7 +157,8 @@ XpsCapabilities::~XpsCapabilities() = default;
bool PrinterSemanticCapsAndDefaults::Paper::operator==( bool PrinterSemanticCapsAndDefaults::Paper::operator==(
const PrinterSemanticCapsAndDefaults::Paper& other) const { const PrinterSemanticCapsAndDefaults::Paper& other) const {
return display_name == other.display_name && vendor_id == other.vendor_id && 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; PrinterSemanticCapsAndDefaults::PrinterSemanticCapsAndDefaults() = default;

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

@@ -40,16 +40,20 @@ struct OptionalSampleCapabilities {
inline const PrinterSemanticCapsAndDefaults::Paper kPaperA3{ inline const PrinterSemanticCapsAndDefaults::Paper kPaperA3{
/*display_name=*/"A3", /*vendor_id=*/"67", /*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{ inline const PrinterSemanticCapsAndDefaults::Paper kPaperA4{
/*display_name=*/"A4", /*vendor_id=*/"12", /*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{ inline const PrinterSemanticCapsAndDefaults::Paper kPaperLetter{
/*display_name=*/"Letter", /*vendor_id=*/"45", /*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{ inline const PrinterSemanticCapsAndDefaults::Paper kPaperLedger{
/*display_name=*/"Ledger", /*vendor_id=*/"89", /*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) #if BUILDFLAG(IS_CHROMEOS)
inline const AdvancedCapability kAdvancedCapability1( inline const AdvancedCapability kAdvancedCapability1(

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