Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(777)

Unified Diff: printing/backend/cups_jobs.cc

Issue 2891643002: Add a method to query IPP printers for attributes. (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« printing/backend/cups_jobs.h ('K') | « printing/backend/cups_jobs.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: printing/backend/cups_jobs.cc
diff --git a/printing/backend/cups_jobs.cc b/printing/backend/cups_jobs.cc
index e73ae8fb331041aaa5754074a924856980eca18d..964a14314ecbb63d85b52c7402b62ef4c40b9b23 100644
--- a/printing/backend/cups_jobs.cc
+++ b/printing/backend/cups_jobs.cc
@@ -11,8 +11,11 @@
#include <memory>
#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
+#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
+#include "printing/backend/cups_deleters.h"
namespace printing {
namespace {
@@ -26,6 +29,10 @@ const char kPrinterState[] = "printer-state";
const char kPrinterStateReasons[] = "printer-state-reasons";
const char kPrinterStateMessage[] = "printer-state-message";
+const char kPrinterMakeAndModel[] = "printer-make-and-model";
+const char kIppVersionsSupported[] = "ipp-versions-supported";
+const char kIppFeaturesSupported[] = "ipp-features-supported";
+
// job attributes
const char kJobUri[] = "job-uri";
const char kJobId[] = "job-id";
@@ -44,6 +51,9 @@ const char kLimit[] = "limit";
const char kCompleted[] = "completed";
const char kNotCompleted[] = "not-completed";
+// ipp features
+const char kIppEverywhere[] = "ipp-everywhere";
+
// printer state severities
const char kSeverityReport[] = "report";
const char kSeverityWarn[] = "warning";
@@ -88,10 +98,17 @@ const char kInterpreterResourceUnavailable[] =
constexpr std::array<const char* const, 3> kPrinterAttributes{
{kPrinterState, kPrinterStateReasons, kPrinterStateMessage}};
-std::unique_ptr<ipp_t, void (*)(ipp_t*)> WrapIpp(ipp_t* ipp) {
- return std::unique_ptr<ipp_t, void (*)(ipp_t*)>(ipp, &ippDelete);
+constexpr std::array<const char* const, 3> kPrinterInfo{
+ {kPrinterMakeAndModel, kIppVersionsSupported, kIppFeaturesSupported}};
+
+using IppPtr = std::unique_ptr<ipp_t, void (*)(ipp_t*)>;
+
+IppPtr WrapIpp(ipp_t* ipp) {
+ return IppPtr(ipp, &ippDelete);
}
+using HttpPtr = std::unique_ptr<http_t, HttpDeleter>;
+
// Converts an IPP attribute |attr| to the appropriate JobState enum.
CupsJob::JobState ToJobState(ipp_attribute_t* attr) {
DCHECK_EQ(IPP_TAG_ENUM, ippGetValueTag(attr));
@@ -295,6 +312,10 @@ PrinterStatus::PrinterStatus(const PrinterStatus& other) = default;
PrinterStatus::~PrinterStatus() = default;
+PrinterInfo::PrinterInfo() = default;
+
+PrinterInfo::~PrinterInfo() = default;
+
void ParseJobsResponse(ipp_t* response,
const std::string& printer_id,
std::vector<CupsJob>* jobs) {
@@ -309,6 +330,80 @@ void ParseJobsResponse(ipp_t* response,
}
}
+IppPtr GetPrinterAttributes(http_t* http,
+ const std::string& printer_uri,
+ int num_attributes,
+ const char* const* attributes,
+ ipp_status_t* status) {
+ DCHECK(http);
+
+ auto request = WrapIpp(ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES));
+
+ ippAddString(request.get(), IPP_TAG_OPERATION, IPP_TAG_URI, kPrinterUri,
+ nullptr, printer_uri.data());
+
+ ippAddStrings(request.get(), IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ kRequestedAttributes, num_attributes, nullptr, attributes);
+
+ auto response =
+ WrapIpp(cupsDoRequest(http, request.release(), printer_uri.c_str()));
+ *status = ippGetStatusCode(response.get());
+
+ return response;
+}
+
+std::pair<int, int> ToVersionNumber(const std::string& version, bool* success) {
Carlson 2017/05/25 19:04:36 Not sure this is a formal thing, but it seems like
Carlson 2017/05/25 19:04:36 Function comment? (Also, shouldn't these free fun
skau 2017/05/27 02:01:20 I've seen both but returning a bool has been more
+ std::vector<base::StringPiece> pieces = SplitStringPiece(
+ version, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ DCHECK_EQ(2U, pieces.size());
Carlson 2017/05/25 19:04:36 This is input validation, and so can't be a DCHECK
skau 2017/05/27 02:01:20 Done.
+ int major;
+ int minor;
+ *success = base::StringToInt(pieces[0], &major) &&
+ base::StringToInt(pieces[1], &minor);
+
+ return {major, minor};
Carlson 2017/05/25 19:04:36 Structure this so that we return a known bad major
skau 2017/05/27 02:01:20 Done.
+}
+
+// Extracts PrinterInfo fields from |response| and populates |printer_info|.
+// Returns true if at least printer-make-and-model and ipp-versions-supported
+// were read.
+bool ParsePrinterInfo(ipp_t* response, PrinterInfo* printer_info) {
+ for (ipp_attribute_t* attr = ippFirstAttribute(response); attr != nullptr;
+ attr = ippNextAttribute(response)) {
+ base::StringPiece name = ippGetName(attr);
+ if (name.empty()) {
Carlson 2017/05/25 19:04:36 This case is not explicitly needed, but if you lik
skau 2017/05/27 02:01:19 Done.
+ continue;
+ }
+
+ if (name == kPrinterMakeAndModel) {
Carlson 2017/05/25 19:04:36 Paranoid favor, can you make the StringPiece conve
skau 2017/05/27 02:01:20 Sounds like a traumatic experience. Let's avoid t
+ DCHECK_EQ(IPP_TAG_TEXT, ippGetValueTag(attr));
+ printer_info->make_and_model = ippGetString(attr, 0, nullptr);
+ } else if (name == kIppVersionsSupported) {
+ std::vector<std::string> ipp_versions;
+ ParseCollection(attr, &ipp_versions);
+ for (const std::string& version : ipp_versions) {
+ bool success;
+ std::pair<int, int> major_minor = ToVersionNumber(version, &success);
+ if (success) {
+ printer_info->ipp_versions.push_back(major_minor);
+ }
+ }
+ } else if (name == kIppFeaturesSupported) {
+ std::vector<std::string> features;
+ ParseCollection(attr, &features);
+ for (const std::string& feature : features) {
+ if (feature == kIppEverywhere) {
+ printer_info->ipp_everywhere = true;
+ break;
+ }
+ }
+ }
+ }
+
+ return !printer_info->make_and_model.empty() &&
+ !printer_info->ipp_versions.empty();
+}
+
void ParsePrinterStatus(ipp_t* response, PrinterStatus* printer_status) {
for (ipp_attribute_t* attr = ippFirstAttribute(response); attr != nullptr;
attr = ippNextAttribute(response)) {
@@ -332,25 +427,31 @@ void ParsePrinterStatus(ipp_t* response, PrinterStatus* printer_status) {
}
}
+bool GetPrinterInfo(const std::string& address,
+ const int port,
+ const std::string& resource,
+ PrinterInfo* printer_info) {
+ ipp_status_t status;
+ HttpPtr http =
+ HttpPtr(httpConnect2(address.data(), port, nullptr, AF_INET,
+ HTTP_ENCRYPTION_IF_REQUESTED, 0, 200, nullptr));
+ auto response = GetPrinterAttributes(
+ http.get(), resource, kPrinterInfo.size(), kPrinterInfo.data(), &status);
+ return status == IPP_STATUS_OK &&
+ ParsePrinterInfo(response.get(), printer_info);
+}
+
bool GetPrinterStatus(http_t* http,
const std::string& printer_id,
PrinterStatus* printer_status) {
- DCHECK(http);
-
- auto request = WrapIpp(ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES));
-
+ ipp_status_t status;
const std::string printer_uri = PrinterUriFromName(printer_id);
- ippAddString(request.get(), IPP_TAG_OPERATION, IPP_TAG_URI, kPrinterUri,
- nullptr, printer_uri.data());
-
- ippAddStrings(request.get(), IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
- kRequestedAttributes, kPrinterAttributes.size(), nullptr,
- kPrinterAttributes.data());
auto response =
- WrapIpp(cupsDoRequest(http, request.release(), printer_uri.c_str()));
+ GetPrinterAttributes(http, printer_uri, kPrinterAttributes.size(),
+ kPrinterAttributes.data(), &status);
- if (ippGetStatusCode(response.get()) != IPP_STATUS_OK)
+ if (status != IPP_STATUS_OK)
return false;
ParsePrinterStatus(response.get(), printer_status);
« printing/backend/cups_jobs.h ('K') | « printing/backend/cups_jobs.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698