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

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

@ -113,9 +113,10 @@ void FakeCupsPrintersManager::SetPrinterSetupResult(
void FakeCupsPrintersManager::QueryPrinterForAutoConf( void FakeCupsPrintersManager::QueryPrinterForAutoConf(
const Printer& printer, const Printer& printer,
base::OnceCallback<void(bool)> callback) { base::OnceCallback<void(bool, const chromeos::IppPrinterInfo&)> callback) {
std::move(callback).Run( 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() { void FakeCupsPrintersManager::TriggerLocalPrintersObserver() {

@ -62,7 +62,8 @@ class FakeCupsPrintersManager : public CupsPrintersManager {
void MarkPrinterAsNotAutoconfigurable(const std::string& printer_id); void MarkPrinterAsNotAutoconfigurable(const std::string& printer_id);
void QueryPrinterForAutoConf( void QueryPrinterForAutoConf(
const chromeos::Printer& printer, const chromeos::Printer& printer,
base::OnceCallback<void(bool)> callback) override; base::OnceCallback<void(bool, const chromeos::IppPrinterInfo&)> callback)
override;
void TriggerLocalPrintersObserver(); void TriggerLocalPrintersObserver();
private: 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 } // namespace
PrinterEventTracker::PrinterEventTracker() = default; PrinterEventTracker::PrinterEventTracker() = default;
@ -81,7 +96,8 @@ void PrinterEventTracker::RecordUsbPrinterInstalled(
void PrinterEventTracker::RecordIppPrinterInstalled( void PrinterEventTracker::RecordIppPrinterInstalled(
const chromeos::Printer& printer, const chromeos::Printer& printer,
SetupMode mode) { SetupMode mode,
const std::optional<chromeos::IppPrinterInfo>& ipp_printer_info) {
base::AutoLock l(lock_); base::AutoLock l(lock_);
if (!logging_) { if (!logging_) {
return; return;
@ -91,6 +107,9 @@ void PrinterEventTracker::RecordIppPrinterInstalled(
SetEventType(&event, mode); SetEventType(&event, mode);
SetPpdInfo(&event, printer.ppd_reference()); SetPpdInfo(&event, printer.ppd_reference());
SetNetworkPrinterInfo(&event, printer); SetNetworkPrinterInfo(&event, printer);
if (ipp_printer_info.has_value()) {
SetIppPrinterInfo(&event, ipp_printer_info.value());
}
events_.push_back(event); events_.push_back(event);
} }

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

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

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

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

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

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

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

@ -46,6 +46,20 @@ std::string ToString(Uri::ParserStatus status) {
} }
} // namespace } // 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) { std::string ToString(PrinterClass pclass) {
switch (pclass) { switch (pclass) {
case PrinterClass::kEnterprise: case PrinterClass::kEnterprise:

@ -5,7 +5,10 @@
#ifndef CHROMEOS_PRINTING_PRINTER_CONFIGURATION_H_ #ifndef CHROMEOS_PRINTING_PRINTER_CONFIGURATION_H_
#define CHROMEOS_PRINTING_PRINTER_CONFIGURATION_H_ #define CHROMEOS_PRINTING_PRINTER_CONFIGURATION_H_
#include <optional>
#include <string> #include <string>
#include <utility>
#include <vector>
#include "base/component_export.h" #include "base/component_export.h"
#include "chromeos/printing/cups_printer_status.h" #include "chromeos/printing/cups_printer_status.h"
@ -27,6 +30,27 @@ enum class COMPONENT_EXPORT(CHROMEOS_PRINTING) PrinterClass {
kSaved 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); COMPONENT_EXPORT(CHROMEOS_PRINTING) std::string ToString(PrinterClass pclass);
// This function checks if the given URI is a valid printer URI. |uri| is // 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_; } const std::string& uuid() const { return uuid_; }
void set_uuid(const std::string& uuid) { uuid_ = 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 // Returns true if the printer should be automatically configured using IPP
// Everywhere. Computed using information from |ppd_reference_| and |uri_|. // Everywhere. Computed using information from |ppd_reference_| and |uri_|.
bool IsIppEverywhere() const; 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 // This flag is set for printers that take part in the finch experiment
// created for b/184293121. // created for b/184293121.
bool experimental_setup_of_usb_printer_with_ipp_and_ppd_ = false; bool experimental_setup_of_usb_printer_with_ipp_and_ppd_ = false;
// IPP attributes, if available.
std::optional<IppPrinterInfo> ipp_printer_info_;
}; };
} // namespace chromeos } // 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 kIppFeaturesSupported = "ipp-features-supported";
constexpr std::string_view kDocumentFormatSupported = constexpr std::string_view kDocumentFormatSupported =
"document-format-supported"; "document-format-supported";
constexpr std::string_view kDocumentFormatPreferred =
"document-format-preferred";
constexpr std::string_view kDocumentFormatDefault = "document-format-default";
constexpr std::string_view kOauthAuthorizationServerUri = constexpr std::string_view kOauthAuthorizationServerUri =
"oauth-authorization-server-uri"; "oauth-authorization-server-uri";
constexpr std::string_view kOauthAuthorizationScope = constexpr std::string_view kOauthAuthorizationScope =
@ -130,11 +133,12 @@ constexpr int kHttpConnectTimeoutMs = 1000;
constexpr std::array<const char* const, 3> kPrinterAttributes{ constexpr std::array<const char* const, 3> kPrinterAttributes{
{kPrinterState, kPrinterStateReasons, kPrinterStateMessage}}; {kPrinterState, kPrinterStateReasons, kPrinterStateMessage}};
constexpr std::array<const char* const, 9> kPrinterInfoAndStatus{ constexpr std::array<const char* const, 11> kPrinterInfoAndStatus{
{kPrinterMakeAndModel.data(), kIppVersionsSupported.data(), {kPrinterMakeAndModel.data(), kIppVersionsSupported.data(),
kIppFeaturesSupported.data(), kDocumentFormatSupported.data(), kIppFeaturesSupported.data(), kDocumentFormatSupported.data(),
kPrinterState, kPrinterStateReasons, kPrinterStateMessage, 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. // Converts an IPP attribute `attr` to the appropriate JobState enum.
CupsJob::JobState ToJobState(ipp_attribute_t* attr) { CupsJob::JobState ToJobState(ipp_attribute_t* attr) {
@ -382,6 +386,27 @@ bool ParsePrinterInfo(ipp_t* response, PrinterInfo* printer_info) {
oauth_error = true; oauth_error = true;
LOG(WARNING) << "Cannot parse oauth-authorization-scope."; 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() = default;
PrinterInfo::PrinterInfo(const PrinterInfo& other) = default;
PrinterInfo::~PrinterInfo() = default; PrinterInfo::~PrinterInfo() = default;
const std::string_view ToJobStateReasonString( const std::string_view ToJobStateReasonString(
@ -551,7 +578,7 @@ PrinterQueryResult GetPrinterInfo(const std::string& address,
return PrinterQueryResult::kUnreachable; 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('/'); size_t first_non_slash = resource.find_first_not_of('/');
const std::string path = (first_non_slash == std::string::npos) 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. // MIME types for supported formats.
std::vector<std::string> document_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 // ipp-versions-supported
// A collection of supported IPP protocol versions. // A collection of supported IPP protocol versions.
std::vector<base::Version> ipp_versions; std::vector<base::Version> ipp_versions;