0

printing: add PDL setup metrics

These metrics will capture information on the printer's preferred,
default and supported PDLs.

Bug: b:293510216
Test: manual on BLD lab printer
Change-Id: I85de7973a7a02242e75c8cfb51ad41a95c9046c8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6069860
Reviewed-by: Benjamin Gordon <bmgordon@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Paul Moy <pmoy@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1431284}
This commit is contained in:
Paul Moy
2025-03-11 18:43:32 -07:00
committed by Chromium LUCI CQ
parent 710b5d218d
commit deadd6cc59
17 changed files with 245 additions and 53 deletions

@ -99,13 +99,26 @@ void OnPrinterQueriedForAutoConf(
ash::CupsPrintersManager* printers_manager,
mojom::LocalPrinter::GetCapabilityCallback callback,
chromeos::Printer printer,
bool is_printer_autoconf) {
bool is_printer_autoconf,
const chromeos::IppPrinterInfo& info) {
if (!is_printer_autoconf) {
std::move(callback).Run(nullptr);
return;
}
printer.mutable_ppd_reference()->autoconf = true;
printer.set_ipp_printer_info(info);
SetUpPrinter(printers_manager, printer, std::move(callback));
}
// Query the printer for setup metrics then continue with setup.
void OnPrinterQueriedForAutoConfMetricsOnly(
ash::CupsPrintersManager* printers_manager,
mojom::LocalPrinter::GetCapabilityCallback callback,
chromeos::Printer printer,
bool is_printer_autoconf,
const chromeos::IppPrinterInfo& info) {
printer.set_ipp_printer_info(info);
SetUpPrinter(printers_manager, printer, std::move(callback));
}
@ -141,7 +154,10 @@ void OnPrinterAuthenticated(
// If the printer is autoconf compatible or has a valid PPD reference then
// continue with normal setup.
if (printer.ppd_reference().IsFilled()) {
SetUpPrinter(printers_manager, printer, std::move(callback));
printers_manager->QueryPrinterForAutoConf(
printer,
base::BindOnce(OnPrinterQueriedForAutoConfMetricsOnly,
printers_manager, std::move(callback), printer));
return;
}
@ -158,7 +174,9 @@ void OnPrinterAuthenticated(
return;
}
SetUpPrinter(printers_manager, printer, std::move(callback));
printers_manager->QueryPrinterForAutoConf(
printer, base::BindOnce(OnPrinterQueriedForAutoConfMetricsOnly,
printers_manager, std::move(callback), printer));
}
void OnOAuthAccessTokenObtained(

@ -417,10 +417,10 @@ class CupsPrintersManagerImpl
PrinterConfigurer::Create(ppd_provider_, dlc_service_client_);
printers_being_setup_[id].fingerprint = fingerprint;
printers_being_setup_[id].configurer->SetUpPrinterInCups(
printer,
base::BindOnce(&CupsPrintersManagerImpl::OnPrinterSetupResult,
weak_ptr_factory_.GetWeakPtr(), id,
is_automatic_installation));
printer, base::BindOnce(
&CupsPrintersManagerImpl::OnPrinterSetupResult,
weak_ptr_factory_.GetWeakPtr(), id,
is_automatic_installation, printer.ipp_printer_info()));
}
}
@ -646,7 +646,8 @@ class CupsPrintersManagerImpl
const std::string& make_and_model,
const std::vector<std::string>& document_formats,
bool ipp_everywhere,
const chromeos::PrinterAuthenticationInfo& auth_info) {
const chromeos::PrinterAuthenticationInfo& auth_info,
const chromeos::IppPrinterInfo& ipp_printer_info) {
ParsePrinterStatusFromPrinterQuery(printer_id, std::move(cb), result,
printer_status, auth_info);
}
@ -730,9 +731,10 @@ class CupsPrintersManagerImpl
void QueryPrinterForAutoConf(
const Printer& printer,
base::OnceCallback<void(bool)> callback) override {
base::OnceCallback<void(bool, const chromeos::IppPrinterInfo&)> callback)
override {
if (!IsIppUri(printer.uri())) {
std::move(callback).Run(false);
std::move(callback).Run(false, chromeos::IppPrinterInfo{});
return;
}
@ -746,19 +748,20 @@ class CupsPrintersManagerImpl
// Callback for QueryPrinterForAutoConf
void OnQueryPrinterForAutoConf(
base::OnceCallback<void(bool)> callback,
base::OnceCallback<void(bool, const chromeos::IppPrinterInfo&)> callback,
PrinterQueryResult result,
const ::printing::PrinterStatus& printer_status,
const std::string& make_and_model,
const std::vector<std::string>& document_formats,
bool ipp_everywhere,
const chromeos::PrinterAuthenticationInfo& auth_info) {
const chromeos::PrinterAuthenticationInfo& auth_info,
const chromeos::IppPrinterInfo& ipp_printer_info) {
if (result != PrinterQueryResult::kSuccess) {
std::move(callback).Run(false);
std::move(callback).Run(false, chromeos::IppPrinterInfo{});
return;
}
std::move(callback).Run(ipp_everywhere);
std::move(callback).Run(ipp_everywhere, ipp_printer_info);
}
private:
@ -808,8 +811,10 @@ class CupsPrintersManagerImpl
return nullptr;
}
void MaybeRecordInstallation(const Printer& printer,
bool is_automatic_installation) {
void MaybeRecordInstallation(
const Printer& printer,
bool is_automatic_installation,
const std::optional<chromeos::IppPrinterInfo>& ipp_printer_info) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_);
if (synced_printers_manager_->GetPrinter(printer.id())) {
// It's just an update, not a new installation, so don't record an event.
@ -848,7 +853,8 @@ class CupsPrintersManagerImpl
} else {
mode = PrinterEventTracker::kUser;
}
event_tracker_->RecordIppPrinterInstalled(printer, mode);
event_tracker_->RecordIppPrinterInstalled(printer, mode,
ipp_printer_info);
}
}
@ -1042,9 +1048,11 @@ class CupsPrintersManagerImpl
}
// Callback for `SetUpPrinterInCups`.
void OnPrinterSetupResult(const std::string& printer_id,
bool is_automatic_installation,
PrinterSetupResult result) {
void OnPrinterSetupResult(
const std::string& printer_id,
bool is_automatic_installation,
const std::optional<chromeos::IppPrinterInfo>& ipp_printer_info,
PrinterSetupResult result) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_);
std::map<std::string, PrinterSetupTracker>::iterator it =
@ -1063,7 +1071,8 @@ class CupsPrintersManagerImpl
if (user_printers_allowed_.GetValue()) {
std::optional<chromeos::Printer> printer = printers_.Get(printer_id);
if (printer) {
MaybeRecordInstallation(*printer, is_automatic_installation);
MaybeRecordInstallation(*printer, is_automatic_installation,
ipp_printer_info);
}
}
}

@ -153,7 +153,8 @@ class CupsPrintersManager : public PrinterInstallationManager,
// Performs an IPP query on `printer` for autoconf compatibility.
virtual void QueryPrinterForAutoConf(
const chromeos::Printer& printer,
base::OnceCallback<void(bool)> callback) = 0;
base::OnceCallback<void(bool, const chromeos::IppPrinterInfo&)>
callback) = 0;
};
} // namespace ash

@ -113,9 +113,10 @@ void FakeCupsPrintersManager::SetPrinterSetupResult(
void FakeCupsPrintersManager::QueryPrinterForAutoConf(
const Printer& printer,
base::OnceCallback<void(bool)> callback) {
base::OnceCallback<void(bool, const chromeos::IppPrinterInfo&)> callback) {
std::move(callback).Run(
!printers_marked_as_not_autoconf_.contains(printer.id()));
!printers_marked_as_not_autoconf_.contains(printer.id()),
chromeos::IppPrinterInfo{});
}
void FakeCupsPrintersManager::TriggerLocalPrintersObserver() {

@ -62,7 +62,8 @@ class FakeCupsPrintersManager : public CupsPrintersManager {
void MarkPrinterAsNotAutoconfigurable(const std::string& printer_id);
void QueryPrinterForAutoConf(
const chromeos::Printer& printer,
base::OnceCallback<void(bool)> callback) override;
base::OnceCallback<void(bool, const chromeos::IppPrinterInfo&)> callback)
override;
void TriggerLocalPrintersObserver();
private:

@ -54,6 +54,21 @@ void SetNetworkPrinterInfo(metrics::PrinterEventProto* event,
}
}
// Add information to the `event` that only IPP printers have.
void SetIppPrinterInfo(metrics::PrinterEventProto* event,
const chromeos::IppPrinterInfo& info) {
if (!info.document_formats.empty()) {
event->mutable_document_format_supported()->Assign(
info.document_formats.begin(), info.document_formats.end());
}
if (!info.document_format_preferred.empty()) {
event->set_document_format_preferred(info.document_format_preferred);
}
if (!info.document_format_default.empty()) {
event->set_document_format_default(info.document_format_default);
}
}
} // namespace
PrinterEventTracker::PrinterEventTracker() = default;
@ -81,7 +96,8 @@ void PrinterEventTracker::RecordUsbPrinterInstalled(
void PrinterEventTracker::RecordIppPrinterInstalled(
const chromeos::Printer& printer,
SetupMode mode) {
SetupMode mode,
const std::optional<chromeos::IppPrinterInfo>& ipp_printer_info) {
base::AutoLock l(lock_);
if (!logging_) {
return;
@ -91,6 +107,9 @@ void PrinterEventTracker::RecordIppPrinterInstalled(
SetEventType(&event, mode);
SetPpdInfo(&event, printer.ppd_reference());
SetNetworkPrinterInfo(&event, printer);
if (ipp_printer_info.has_value()) {
SetIppPrinterInfo(&event, ipp_printer_info.value());
}
events_.push_back(event);
}

@ -49,8 +49,10 @@ class PrinterEventTracker : public KeyedService {
// Store a succesful network printer installation. |mode| indicates if
// the PPD was selected automatically or chosen by the user.
void RecordIppPrinterInstalled(const chromeos::Printer& printer,
SetupMode mode);
void RecordIppPrinterInstalled(
const chromeos::Printer& printer,
SetupMode mode,
const std::optional<chromeos::IppPrinterInfo>& ipp_printer_info);
// Record an abandoned setup.
void RecordSetupAbandoned(const chromeos::Printer& printer);

@ -6,12 +6,14 @@
#include "base/time/time.h"
#include "chromeos/printing/printer_configuration.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/metrics_proto/printer_event.pb.h"
namespace ash {
namespace {
using ::chromeos::IppPrinterInfo;
using ::chromeos::Printer;
constexpr int kVendorId = 0x3241;
@ -22,6 +24,11 @@ constexpr char kUsbModel[] = "Printer ModelName";
constexpr char kMakeAndModel[] = "Chromium RazLazer X4321er";
constexpr char kEffectiveMakeAndModel[] = "Generic PostScript";
constexpr char kDocumentFormatDefault[] = "Default";
constexpr char kDocumentFormatPreferred[] = "Preferred";
constexpr char kFirstDocumentFormatSupported[] = "First";
constexpr char kSecondDocumentFormatSupported[] = "Second";
class PrinterEventTrackerTest : public testing::Test {
public:
PrinterEventTrackerTest() = default;
@ -51,7 +58,8 @@ TEST_F(PrinterEventTrackerTest, RecordsWhenEnabled) {
test_printer.mutable_ppd_reference()->effective_make_and_model =
kEffectiveMakeAndModel;
tracker_.RecordIppPrinterInstalled(test_printer, PrinterEventTracker::kUser);
tracker_.RecordIppPrinterInstalled(test_printer, PrinterEventTracker::kUser,
chromeos::IppPrinterInfo{});
auto events = GetEvents();
EXPECT_EQ(1U, events.size());
@ -64,7 +72,8 @@ TEST_F(PrinterEventTrackerTest, DefaultLoggingOff) {
kEffectiveMakeAndModel;
tracker_.RecordIppPrinterInstalled(test_printer,
PrinterEventTracker::kAutomatic);
PrinterEventTracker::kAutomatic,
chromeos::IppPrinterInfo{});
auto events = GetEvents();
EXPECT_TRUE(events.empty());
@ -79,7 +88,8 @@ TEST_F(PrinterEventTrackerTest, DoesNotRecordWhileDisabled) {
kEffectiveMakeAndModel;
tracker_.RecordIppPrinterInstalled(test_printer,
PrinterEventTracker::kAutomatic);
PrinterEventTracker::kAutomatic,
chromeos::IppPrinterInfo{});
auto events = GetEvents();
EXPECT_TRUE(events.empty());
@ -93,7 +103,16 @@ TEST_F(PrinterEventTrackerTest, InstalledIppPrinter) {
test_printer.mutable_ppd_reference()->effective_make_and_model =
kEffectiveMakeAndModel;
tracker_.RecordIppPrinterInstalled(test_printer, PrinterEventTracker::kUser);
IppPrinterInfo ipp_printer_info;
ipp_printer_info.document_format_default = kDocumentFormatDefault;
ipp_printer_info.document_format_preferred = kDocumentFormatPreferred;
ipp_printer_info.document_formats.push_back(kFirstDocumentFormatSupported);
ipp_printer_info.document_formats.push_back(kSecondDocumentFormatSupported);
ipp_printer_info.document_formats.push_back(kDocumentFormatDefault);
ipp_printer_info.document_formats.push_back(kDocumentFormatPreferred);
tracker_.RecordIppPrinterInstalled(test_printer, PrinterEventTracker::kUser,
ipp_printer_info);
auto events = GetEvents();
ASSERT_FALSE(events.empty());
@ -103,6 +122,15 @@ TEST_F(PrinterEventTrackerTest, InstalledIppPrinter) {
EXPECT_EQ(kMakeAndModel, recorded_event.ipp_make_and_model());
EXPECT_EQ(kEffectiveMakeAndModel, recorded_event.ppd_identifier());
EXPECT_EQ(kDocumentFormatDefault, recorded_event.document_format_default());
EXPECT_EQ(kDocumentFormatPreferred,
recorded_event.document_format_preferred());
EXPECT_THAT(
recorded_event.document_format_supported(),
testing::UnorderedElementsAreArray(
{kFirstDocumentFormatSupported, kSecondDocumentFormatSupported,
kDocumentFormatDefault, kDocumentFormatPreferred}));
EXPECT_FALSE(recorded_event.has_usb_printer_manufacturer());
EXPECT_FALSE(recorded_event.has_usb_printer_model());
EXPECT_FALSE(recorded_event.has_usb_vendor_id());
@ -117,8 +145,16 @@ TEST_F(PrinterEventTrackerTest, InstalledPrinterAuto) {
test_printer.set_make_and_model(kMakeAndModel);
test_printer.mutable_ppd_reference()->autoconf = true;
IppPrinterInfo ipp_printer_info;
ipp_printer_info.document_format_default = kDocumentFormatDefault;
ipp_printer_info.document_format_preferred = kDocumentFormatPreferred;
ipp_printer_info.document_formats.push_back(kFirstDocumentFormatSupported);
ipp_printer_info.document_formats.push_back(kSecondDocumentFormatSupported);
ipp_printer_info.document_formats.push_back(kDocumentFormatDefault);
ipp_printer_info.document_formats.push_back(kDocumentFormatPreferred);
tracker_.RecordIppPrinterInstalled(
test_printer, PrinterEventTracker::SetupMode::kAutomatic);
test_printer, PrinterEventTracker::kAutomatic, ipp_printer_info);
auto events = GetEvents();
ASSERT_FALSE(events.empty());
@ -127,6 +163,16 @@ TEST_F(PrinterEventTrackerTest, InstalledPrinterAuto) {
EXPECT_EQ(metrics::PrinterEventProto::SETUP_AUTOMATIC,
recorded_event.event_type());
EXPECT_EQ(kMakeAndModel, recorded_event.ipp_make_and_model());
EXPECT_EQ(kDocumentFormatDefault, recorded_event.document_format_default());
EXPECT_EQ(kDocumentFormatPreferred,
recorded_event.document_format_preferred());
EXPECT_THAT(
recorded_event.document_format_supported(),
testing::UnorderedElementsAreArray(
{kFirstDocumentFormatSupported, kSecondDocumentFormatSupported,
kDocumentFormatDefault, kDocumentFormatPreferred}));
// For autoconf printers, ppd identifier is blank but a successful setup is
// recorded.
EXPECT_FALSE(recorded_event.has_ppd_identifier());
@ -145,8 +191,8 @@ TEST_F(PrinterEventTrackerTest, InstalledPrinterUserPpd) {
test_printer.mutable_ppd_reference()->user_supplied_ppd_url =
"file:///i_dont_record_this_field/blah/blah/blah/some_ppd.ppd";
tracker_.RecordIppPrinterInstalled(test_printer,
PrinterEventTracker::SetupMode::kUser);
tracker_.RecordIppPrinterInstalled(test_printer, PrinterEventTracker::kUser,
chromeos::IppPrinterInfo{});
auto events = GetEvents();
ASSERT_FALSE(events.empty());

@ -12,6 +12,7 @@
#include "printing/printer_query_result.h"
namespace chromeos {
struct IppPrinterInfo;
struct PrinterAuthenticationInfo;
} // namespace chromeos
@ -26,6 +27,7 @@ namespace ash {
// the raw printer-make-and-model value from the printer. |autoconf| indicates
// if we think we can compute the printer capabilities without a PPD.
// |auth_info| holds the information about authentication required by the
// printer. |ipp_printer_info| holds various IPP attributes reported by the
// printer.
using PrinterInfoCallback = base::OnceCallback<void(
::printing::PrinterQueryResult result,
@ -33,7 +35,8 @@ using PrinterInfoCallback = base::OnceCallback<void(
const std::string& make_and_model,
const std::vector<std::string>& document_formats,
bool autoconf,
const chromeos::PrinterAuthenticationInfo& auth_info)>;
const chromeos::PrinterAuthenticationInfo& auth_info,
const chromeos::IppPrinterInfo& ipp_printer_info)>;
// Dispatch an IPP request to |host| on |port| for |path| to obtain
// basic printer information.

@ -14,6 +14,7 @@
#include "base/version.h"
#include "chrome/browser/ash/printing/printer_info.h"
#include "chromeos/printing/cups_printer_status.h"
#include "chromeos/printing/printer_configuration.h"
#include "printing/backend/cups_jobs.h"
#include "printing/printer_status.h"
@ -86,15 +87,17 @@ void OnPrinterQueried(ash::PrinterInfoCallback callback,
std::move(callback).Run(result, ::printing::PrinterStatus(),
/*make_and_model=*/std::string(),
/*document_formats=*/{}, /*ipp_everywhere=*/false,
chromeos::PrinterAuthenticationInfo{});
chromeos::PrinterAuthenticationInfo{},
chromeos::IppPrinterInfo{});
return;
}
std::move(callback).Run(result, printer_status, printer_info.make_and_model,
printer_info.document_formats,
IsAutoconf(printer_info),
{.oauth_server = printer_info.oauth_server,
.oauth_scope = printer_info.oauth_scope});
std::move(callback).Run(
result, printer_status, printer_info.make_and_model,
printer_info.document_formats, IsAutoconf(printer_info),
{.oauth_server = printer_info.oauth_server,
.oauth_scope = printer_info.oauth_scope},
{printer_info.document_formats, printer_info.document_format_default,
printer_info.document_format_preferred});
}
} // namespace

@ -8,6 +8,7 @@
#include "base/functional/bind.h"
#include "base/task/sequenced_task_runner.h"
#include "chromeos/printing/cups_printer_status.h"
#include "chromeos/printing/printer_configuration.h"
#include "printing/printer_status.h"
namespace ash {
@ -24,14 +25,14 @@ void QueryIppPrinter(const std::string& host,
printer_status.reasons.push_back(
{printing::PrinterStatus::PrinterReason::Reason::kMediaJam,
printing::PrinterStatus::PrinterReason::Severity::kError});
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback),
printing::PrinterQueryResult::kSuccess,
printer_status, /*make_and_model=*/"Foo Bar",
/*document_formats=*/std::vector<std::string>{},
/*ipp_everywhere=*/false,
chromeos::PrinterAuthenticationInfo{}));
chromeos::PrinterAuthenticationInfo{},
chromeos::IppPrinterInfo{}));
}
} // namespace ash

@ -669,7 +669,8 @@ void CupsPrintersHandler::HandleGetPrinterInfo(const base::Value::List& args) {
OnAutoconfQueried(callback_id, PrinterQueryResult::kUnknownFailure,
::printing::PrinterStatus(), /*make_and_model=*/"",
/*document_formats=*/{}, /*ipp_everywhere=*/false,
chromeos::PrinterAuthenticationInfo{});
chromeos::PrinterAuthenticationInfo{},
chromeos::IppPrinterInfo{});
return;
}
@ -686,7 +687,8 @@ void CupsPrintersHandler::OnAutoconfQueriedDiscovered(
const std::string& make_and_model,
const std::vector<std::string>& document_formats,
bool ipp_everywhere,
const chromeos::PrinterAuthenticationInfo& /*auth_info*/) {
const chromeos::PrinterAuthenticationInfo& /*auth_info*/,
const chromeos::IppPrinterInfo& /*ipp_printer_info*/) {
RecordIppQueryResult(result);
const bool success = result == PrinterQueryResult::kSuccess;
@ -739,7 +741,8 @@ void CupsPrintersHandler::OnAutoconfQueried(
const std::string& make_and_model,
const std::vector<std::string>& document_formats,
bool ipp_everywhere,
const chromeos::PrinterAuthenticationInfo& /*auth_info*/) {
const chromeos::PrinterAuthenticationInfo& /*auth_info*/,
const chromeos::IppPrinterInfo& /*ipp_printer_info*/) {
RecordIppQueryResult(result);
const bool success = result == PrinterQueryResult::kSuccess;

@ -108,7 +108,8 @@ class CupsPrintersHandler : public ::settings::SettingsPageUIHandler,
const std::string& make_and_model,
const std::vector<std::string>& document_formats,
bool ipp_everywhere,
const chromeos::PrinterAuthenticationInfo& auth_info);
const chromeos::PrinterAuthenticationInfo& auth_info,
const chromeos::IppPrinterInfo& ipp_printer_info);
// Handles the callback for HandleGetPrinterInfo for a discovered printer.
void OnAutoconfQueriedDiscovered(
@ -119,7 +120,8 @@ class CupsPrintersHandler : public ::settings::SettingsPageUIHandler,
const std::string& make_and_model,
const std::vector<std::string>& document_formats,
bool ipp_everywhere,
const chromeos::PrinterAuthenticationInfo& auth_info);
const chromeos::PrinterAuthenticationInfo& auth_info,
const chromeos::IppPrinterInfo& ipp_printer_info);
// Callback for PPD matching attempts;
void OnPpdResolved(const std::string& callback_id,

@ -46,6 +46,20 @@ std::string ToString(Uri::ParserStatus status) {
}
} // namespace
IppPrinterInfo::IppPrinterInfo() = default;
IppPrinterInfo::IppPrinterInfo(const IppPrinterInfo& other) = default;
IppPrinterInfo::IppPrinterInfo(const std::vector<std::string>& document_formats,
const std::string& document_format_default,
const std::string& document_format_preferred) {
this->document_formats = document_formats;
this->document_format_default = document_format_default;
this->document_format_preferred = document_format_preferred;
}
IppPrinterInfo::~IppPrinterInfo() = default;
std::string ToString(PrinterClass pclass) {
switch (pclass) {
case PrinterClass::kEnterprise:

@ -5,7 +5,10 @@
#ifndef CHROMEOS_PRINTING_PRINTER_CONFIGURATION_H_
#define CHROMEOS_PRINTING_PRINTER_CONFIGURATION_H_
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "base/component_export.h"
#include "chromeos/printing/cups_printer_status.h"
@ -27,6 +30,27 @@ enum class COMPONENT_EXPORT(CHROMEOS_PRINTING) PrinterClass {
kSaved
};
struct COMPONENT_EXPORT(CHROMEOS_PRINTING) IppPrinterInfo {
IppPrinterInfo();
IppPrinterInfo(const std::vector<std::string>& document_formats,
const std::string& document_format_default,
const std::string& document_format_preferred);
IppPrinterInfo(const IppPrinterInfo& other);
~IppPrinterInfo();
// document-format-supported
// MIME types for supported formats.
std::vector<std::string> document_formats;
// document-format-default
// MIME type for default format.
std::string document_format_default;
// document-format-preferred
// MIME type for preferred format.
std::string document_format_preferred;
};
COMPONENT_EXPORT(CHROMEOS_PRINTING) std::string ToString(PrinterClass pclass);
// This function checks if the given URI is a valid printer URI. |uri| is
@ -224,6 +248,13 @@ class COMPONENT_EXPORT(CHROMEOS_PRINTING) Printer {
const std::string& uuid() const { return uuid_; }
void set_uuid(const std::string& uuid) { uuid_ = uuid; }
const std::optional<IppPrinterInfo>& ipp_printer_info() const {
return ipp_printer_info_;
}
void set_ipp_printer_info(std::optional<IppPrinterInfo> ipp_printer_info) {
ipp_printer_info_ = std::move(ipp_printer_info);
}
// Returns true if the printer should be automatically configured using IPP
// Everywhere. Computed using information from |ppd_reference_| and |uri_|.
bool IsIppEverywhere() const;
@ -328,6 +359,9 @@ class COMPONENT_EXPORT(CHROMEOS_PRINTING) Printer {
// This flag is set for printers that take part in the finch experiment
// created for b/184293121.
bool experimental_setup_of_usb_printer_with_ipp_and_ppd_ = false;
// IPP attributes, if available.
std::optional<IppPrinterInfo> ipp_printer_info_;
};
} // namespace chromeos

@ -48,6 +48,9 @@ constexpr std::string_view kIppVersionsSupported = "ipp-versions-supported";
constexpr std::string_view kIppFeaturesSupported = "ipp-features-supported";
constexpr std::string_view kDocumentFormatSupported =
"document-format-supported";
constexpr std::string_view kDocumentFormatPreferred =
"document-format-preferred";
constexpr std::string_view kDocumentFormatDefault = "document-format-default";
constexpr std::string_view kOauthAuthorizationServerUri =
"oauth-authorization-server-uri";
constexpr std::string_view kOauthAuthorizationScope =
@ -130,11 +133,12 @@ constexpr int kHttpConnectTimeoutMs = 1000;
constexpr std::array<const char* const, 3> kPrinterAttributes{
{kPrinterState, kPrinterStateReasons, kPrinterStateMessage}};
constexpr std::array<const char* const, 9> kPrinterInfoAndStatus{
constexpr std::array<const char* const, 11> kPrinterInfoAndStatus{
{kPrinterMakeAndModel.data(), kIppVersionsSupported.data(),
kIppFeaturesSupported.data(), kDocumentFormatSupported.data(),
kPrinterState, kPrinterStateReasons, kPrinterStateMessage,
kOauthAuthorizationServerUri.data(), kOauthAuthorizationScope.data()}};
kOauthAuthorizationServerUri.data(), kOauthAuthorizationScope.data(),
kDocumentFormatPreferred.data(), kDocumentFormatDefault.data()}};
// Converts an IPP attribute `attr` to the appropriate JobState enum.
CupsJob::JobState ToJobState(ipp_attribute_t* attr) {
@ -382,6 +386,27 @@ bool ParsePrinterInfo(ipp_t* response, PrinterInfo* printer_info) {
oauth_error = true;
LOG(WARNING) << "Cannot parse oauth-authorization-scope.";
}
} else if (name == kDocumentFormatPreferred) {
int tag = ippGetValueTag(attr);
if (tag != IPP_TAG_TEXT && tag != IPP_TAG_TEXTLANG) {
LOG(WARNING) << "document-format-preferred value tag is " << tag << ".";
}
const char* document_format_preferred_string =
ippGetString(attr, 0, nullptr);
if (document_format_preferred_string) {
printer_info->document_format_preferred =
document_format_preferred_string;
}
} else if (name == kDocumentFormatDefault) {
int tag = ippGetValueTag(attr);
if (tag != IPP_TAG_TEXT && tag != IPP_TAG_TEXTLANG) {
LOG(WARNING) << "document-format-default value tag is " << tag << ".";
}
const char* document_format_default_string =
ippGetString(attr, 0, nullptr);
if (document_format_default_string) {
printer_info->document_format_default = document_format_default_string;
}
}
}
@ -424,6 +449,8 @@ bool CupsJob::ContainsStateReason(CupsJob::JobStateReason reason) const {
PrinterInfo::PrinterInfo() = default;
PrinterInfo::PrinterInfo(const PrinterInfo& other) = default;
PrinterInfo::~PrinterInfo() = default;
const std::string_view ToJobStateReasonString(
@ -551,7 +578,7 @@ PrinterQueryResult GetPrinterInfo(const std::string& address,
return PrinterQueryResult::kUnreachable;
}
// TODO(crbug.com/821497): Use a library to canonicalize the URL.
// TODO(crbug.com/172213155): Use a library to canonicalize the URL.
size_t first_non_slash = resource.find_first_not_of('/');
const std::string path = (first_non_slash == std::string::npos)
? ""

@ -83,6 +83,14 @@ struct COMPONENT_EXPORT(PRINT_BACKEND) PrinterInfo {
// MIME types for supported formats.
std::vector<std::string> document_formats;
// document-format-default
// MIME type for default format.
std::string document_format_default;
// document-format-preferred
// MIME type for preferred format.
std::string document_format_preferred;
// ipp-versions-supported
// A collection of supported IPP protocol versions.
std::vector<base::Version> ipp_versions;