Commit 988896a6 authored by Gavin Williams's avatar Gavin Williams Committed by Commit Bot

Add printer status querying to CupsPrintersManager

- Adds functionality to CupsPrinterManager for allowing
  other classes to query for printer statuses.

- CupsPrinterManager accepts a list of printer ids then kicks off an
  asynchronous printer status query for each printer. The printer
  status is cached using SavePrinterStatus.

Bug: 1059607
Change-Id: Ie9ea5192fc046b106e3e299bf75cadb43e746605
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2102770
Commit-Queue: Gavin Williams <gavinwill@chromium.org>
Reviewed-by: default avatarZentaro Kavanagh <zentaro@chromium.org>
Reviewed-by: default avatarBailey Berro <baileyberro@chromium.org>
Cr-Commit-Position: refs/heads/master@{#760230}
parent 5ebbd153
......@@ -15,6 +15,7 @@
#include "base/sequence_checker.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/chromeos/printing/automatic_usb_printer_configurer.h"
#include "chrome/browser/chromeos/printing/cups_printer_status_creator.h"
#include "chrome/browser/chromeos/printing/enterprise_printers_provider.h"
#include "chrome/browser/chromeos/printing/ppd_provider_factory.h"
#include "chrome/browser/chromeos/printing/ppd_resolution_tracker.h"
......@@ -22,6 +23,7 @@
#include "chrome/browser/chromeos/printing/printer_configurer.h"
#include "chrome/browser/chromeos/printing/printer_event_tracker.h"
#include "chrome/browser/chromeos/printing/printer_event_tracker_factory.h"
#include "chrome/browser/chromeos/printing/printer_info.h"
#include "chrome/browser/chromeos/printing/printers_map.h"
#include "chrome/browser/chromeos/printing/server_printers_provider.h"
#include "chrome/browser/chromeos/printing/server_printers_provider_factory.h"
......@@ -33,6 +35,9 @@
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "chromeos/printing/cups_printer_status.h"
#include "chromeos/printing/printing_constants.h"
#include "chromeos/printing/uri_components.h"
#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
#include "components/device_event_log/device_event_log.h"
#include "components/policy/policy_constants.h"
......@@ -41,10 +46,25 @@
#include "components/prefs/pref_service.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "printing/printer_query_result.h"
namespace chromeos {
bool IsIppUri(base::StringPiece printer_uri) {
base::StringPiece::size_type separator_location =
printer_uri.find(url::kStandardSchemeSeparator);
if (separator_location == base::StringPiece::npos) {
return false;
}
base::StringPiece scheme_part = printer_uri.substr(0, separator_location);
return scheme_part == kIppScheme || scheme_part == kIppsScheme;
}
namespace {
using printing::PrinterQueryResult;
class CupsPrintersManagerImpl
: public CupsPrintersManager,
public EnterprisePrintersProvider::Observer,
......@@ -295,6 +315,99 @@ class CupsPrintersManagerImpl
OnPrintersFound(kPrintServerDetector, printers);
}
void FetchPrinterStatus(const std::string& printer_id,
PrinterStatusCallback cb) override {
base::Optional<Printer> printer = GetPrinter(printer_id);
if (!printer) {
PRINTER_LOG(ERROR) << "Unable to complete printer status request. "
<< "Printer not found. Printer id: " << printer_id;
CupsPrinterStatus printer_status(printer_id);
printer_status.AddStatusReason(
CupsPrinterStatus::CupsPrinterStatusReason::Reason::kUnknownReason,
CupsPrinterStatus::CupsPrinterStatusReason::Severity::kWarning);
std::move(cb).Run(std::move(printer_status));
return;
}
base::Optional<UriComponents> parsed_uri = ParseUri(printer->uri());
// Behavior for querying a non-IPP uri is undefined and disallowed.
if (!parsed_uri || !IsIppUri(printer->uri())) {
PRINTER_LOG(ERROR) << "Unable to complete printer status request. "
<< "Printer uri is invalid. Printer id: "
<< printer_id;
CupsPrinterStatus printer_status(printer_id);
printer_status.AddStatusReason(
CupsPrinterStatus::CupsPrinterStatusReason::Reason::kUnknownReason,
CupsPrinterStatus::CupsPrinterStatusReason::Severity::kWarning);
std::move(cb).Run(std::move(printer_status));
return;
}
const UriComponents& uri = parsed_uri.value();
QueryIppPrinter(
uri.host(), uri.port(), uri.path(), uri.encrypted(),
base::BindOnce(&CupsPrintersManagerImpl::OnPrinterInfoFetched,
weak_ptr_factory_.GetWeakPtr(), printer_id,
std::move(cb)));
}
// Callback for FetchPrinterStatus
void OnPrinterInfoFetched(const std::string& printer_id,
PrinterStatusCallback cb,
PrinterQueryResult result,
const ::printing::PrinterStatus& printer_status,
const std::string& make,
const std::string& model,
const std::string& make_and_model,
const std::vector<std::string>& document_formats,
bool ipp_everywhere) {
SendPrinterStatus(printer_id, std::move(cb), result, printer_status);
}
void SendPrinterStatus(const std::string& printer_id,
PrinterStatusCallback cb,
PrinterQueryResult result,
const ::printing::PrinterStatus& printer_status) {
if (result == PrinterQueryResult::UNREACHABLE) {
PRINTER_LOG(ERROR)
<< "Printer status request failed. Could not reach printer "
<< printer_id;
CupsPrinterStatus error_printer_status(printer_id);
error_printer_status.AddStatusReason(
CupsPrinterStatus::CupsPrinterStatusReason::Reason::
kPrinterUnreachable,
CupsPrinterStatus::CupsPrinterStatusReason::Severity::kError);
std::move(cb).Run(std::move(error_printer_status));
return;
}
if (result == PrinterQueryResult::UNKNOWN_FAILURE) {
PRINTER_LOG(ERROR) << "Printer status request failed. Unknown failure "
"trying to reach printer "
<< printer_id;
CupsPrinterStatus error_printer_status(printer_id);
error_printer_status.AddStatusReason(
CupsPrinterStatus::CupsPrinterStatusReason::Reason::kUnknownReason,
CupsPrinterStatus::CupsPrinterStatusReason::Severity::kWarning);
std::move(cb).Run(std::move(error_printer_status));
return;
}
if (result == PrinterQueryResult::SUCCESS) {
// Convert printing::PrinterStatus to printing::CupsPrinterStatus
CupsPrinterStatus cups_printers_status =
PrinterStatusToCupsPrinterStatus(printer_id, printer_status);
// Save the PrinterStatus so it can be attached along side future Printer
// retrievals.
printers_.SavePrinterStatus(printer_id, cups_printers_status);
// Send status back to the handler through PrinterStatusCallback.
std::move(cb).Run(std::move(cups_printers_status));
return;
}
}
private:
base::Optional<Printer> GetEnterprisePrinter(const std::string& id) const {
return printers_.Get(PrinterClass::kEnterprise, id);
......
......@@ -33,6 +33,9 @@ class UsbPrinterNotificationController;
enum class PrinterSetupSource;
// Returns true if |printer_uri| is an IPP uri.
bool IsIppUri(base::StringPiece printer_uri);
// Top level manager of available CUPS printers in ChromeOS. All functions
// in this class must be called from a sequenced context.
class CupsPrintersManager : public PrinterInstallationManager,
......@@ -52,6 +55,9 @@ class CupsPrintersManager : public PrinterInstallationManager,
virtual ~Observer() = default;
};
using PrinterStatusCallback =
base::OnceCallback<void(const CupsPrinterStatus&)>;
// Factory function.
static std::unique_ptr<CupsPrintersManager> Create(Profile* profile);
......@@ -112,6 +118,11 @@ class CupsPrintersManager : public PrinterInstallationManager,
// Log an event that the user started trying to set up the given printer,
// but setup was not completed for some reason.
virtual void RecordSetupAbandoned(const Printer& printer) = 0;
// Performs individual printer status requests for each printer provided.
// Passes retrieved printer status to the callbacks.
virtual void FetchPrinterStatus(const std::string& printer_id,
PrinterStatusCallback cb) = 0;
};
} // namespace chromeos
......
......@@ -891,5 +891,18 @@ TEST_F(CupsPrintersManagerTest,
usb_notif_controller_->IsConfigurationNotification("Discovered"));
}
TEST_F(CupsPrintersManagerTest, IsIppUri) {
// IPP protocol
ASSERT_TRUE(IsIppUri("ipp://1.2.3.4"));
// IPPS protocol
ASSERT_TRUE(IsIppUri("ipps://1.2.3.4"));
// USB protocol
ASSERT_FALSE(IsIppUri("usb://1.2.3.4"));
// Malformed URI
ASSERT_FALSE(IsIppUri("ipp/1.2.3.4"));
// Empty URI
ASSERT_FALSE(IsIppUri(""));
}
} // namespace
} // namespace chromeos
......@@ -31,6 +31,8 @@ class StubCupsPrintersManager : public CupsPrintersManager {
bool is_automatic,
PrinterSetupSource source) override {}
void RecordSetupAbandoned(const Printer& printer) override {}
void FetchPrinterStatus(const std::string& printer_id,
PrinterStatusCallback cb) override {}
};
class StubPrinterConfigurer : public PrinterConfigurer {
......
......@@ -94,18 +94,6 @@ void RecordIppQueryResult(const PrinterQueryResult& result) {
}
}
// Returns true if |printer_uri| is an IPP uri.
bool IsIppUri(base::StringPiece printer_uri) {
base::StringPiece::size_type separator_location =
printer_uri.find(url::kStandardSchemeSeparator);
if (separator_location == base::StringPiece::npos) {
return false;
}
base::StringPiece scheme_part = printer_uri.substr(0, separator_location);
return scheme_part == kIppScheme || scheme_part == kIppsScheme;
}
// Query an IPP printer to check for autoconf support where the printer is
// located at |printer_uri|. Results are reported through |callback|. It is an
// error to attempt this with a non-IPP printer.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment