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

Unified Diff: printing/backend/cups_jobs.cc

Issue 2891643002: Add a method to query IPP printers for attributes. (Closed)
Patch Set: check empty Created 3 years, 6 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
« no previous file with comments | « 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..80daed78723f5dba657dd4c7814f2f55d4dc3887 100644
--- a/printing/backend/cups_jobs.cc
+++ b/printing/backend/cups_jobs.cc
@@ -11,8 +11,12 @@
#include <memory>
#include "base/logging.h"
+#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
+#include "base/threading/thread_restrictions.h"
+#include "base/version.h"
+#include "printing/backend/cups_deleters.h"
namespace printing {
namespace {
@@ -26,6 +30,11 @@ 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";
+const char kDocumentFormatSupported[] = "document-format-supported";
+
// job attributes
const char kJobUri[] = "job-uri";
const char kJobId[] = "job-id";
@@ -44,6 +53,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 +100,18 @@ 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, 4> kPrinterInfo{
+ {kPrinterMakeAndModel, kIppVersionsSupported, kIppFeaturesSupported,
+ kDocumentFormatSupported}};
+
+using ScopedIppPtr = std::unique_ptr<ipp_t, void (*)(ipp_t*)>;
+
+ScopedIppPtr WrapIpp(ipp_t* ipp) {
+ return ScopedIppPtr(ipp, &ippDelete);
}
+using ScopedHttpPtr = 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));
@@ -281,6 +301,40 @@ std::string PrinterUriFromName(const std::string& id) {
return base::StringPrintf("ipp://localhost/printers/%s", id.c_str());
}
+// 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 == base::StringPiece(kPrinterMakeAndModel)) {
+ DCHECK_EQ(IPP_TAG_TEXT, ippGetValueTag(attr));
+ printer_info->make_and_model = ippGetString(attr, 0, nullptr);
+ } else if (name == base::StringPiece(kIppVersionsSupported)) {
+ std::vector<std::string> ipp_versions;
+ ParseCollection(attr, &ipp_versions);
+ for (const std::string& version : ipp_versions) {
+ base::Version major_minor(version);
+ if (major_minor.IsValid()) {
+ printer_info->ipp_versions.push_back(major_minor);
+ }
+ }
+ } else if (name == base::StringPiece(kIppFeaturesSupported)) {
+ std::vector<std::string> features;
+ ParseCollection(attr, &features);
+ printer_info->ipp_everywhere =
+ base::ContainsValue(features, kIppEverywhere);
+ } else if (name == base::StringPiece(kDocumentFormatSupported)) {
+ ParseCollection(attr, &printer_info->document_formats);
+ }
+ }
+
+ return !printer_info->make_and_model.empty() &&
+ !printer_info->ipp_versions.empty();
+}
+
} // namespace
CupsJob::CupsJob() = default;
@@ -295,6 +349,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 +367,40 @@ void ParseJobsResponse(ipp_t* response,
}
}
+// Returns an IPP response for a Get-Printer-Attributes request to |http|. For
+// print servers, |printer_uri| is used as the printer-uri value.
+// |resource_path| specifies the path portion of the server URI.
+// |num_attributes| is the number of attributes in |attributes| which should be
+// a list of IPP attributes. |status| is updated with status code for the
+// request. A successful request will have the |status| IPP_STATUS_OK.
+ScopedIppPtr GetPrinterAttributes(http_t* http,
+ const std::string& printer_uri,
+ const std::string& resource_path,
+ int num_attributes,
+ const char* const* attributes,
+ ipp_status_t* status) {
+ base::ThreadRestrictions::AssertIOAllowed();
+ DCHECK(http);
+
+ // CUPS expects a leading slash for resource names. Add one if it's missing.
+ std::string rp = !resource_path.empty() && resource_path.front() == '/'
+ ? resource_path
+ : "/" + resource_path;
+
+ 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(), rp.c_str()));
+ *status = ippGetStatusCode(response.get());
+
+ return response;
+}
+
void ParsePrinterStatus(ipp_t* response, PrinterStatus* printer_status) {
for (ipp_attribute_t* attr = ippFirstAttribute(response); attr != nullptr;
attr = ippNextAttribute(response)) {
@@ -332,25 +424,45 @@ void ParsePrinterStatus(ipp_t* response, PrinterStatus* printer_status) {
}
}
+bool GetPrinterInfo(const std::string& address,
+ const int port,
+ const std::string& resource,
+ PrinterInfo* printer_info) {
+ base::ThreadRestrictions::AssertIOAllowed();
+
+ ScopedHttpPtr http = ScopedHttpPtr(
+ httpConnect2(address.data(), port, nullptr, AF_INET,
+ HTTP_ENCRYPTION_IF_REQUESTED, 0, 200, nullptr));
+ if (!http) {
+ LOG(WARNING) << "Could not connect to host";
+ return false;
+ }
+
+ ipp_status_t status;
+ ScopedIppPtr response =
+ GetPrinterAttributes(http.get(), resource, resource, kPrinterInfo.size(),
+ kPrinterInfo.data(), &status);
+ if (status != IPP_STATUS_OK || response.get() == nullptr) {
+ LOG(WARNING) << "Get attributes failure: " << status;
+ return false;
+ }
+
+ return 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));
+ base::ThreadRestrictions::AssertIOAllowed();
+ 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()));
+ ScopedIppPtr response =
+ 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);
@@ -363,6 +475,7 @@ bool GetCupsJobs(http_t* http,
int limit,
JobCompletionState which,
std::vector<CupsJob>* jobs) {
+ base::ThreadRestrictions::AssertIOAllowed();
DCHECK(http);
auto request = WrapIpp(ippNewRequest(IPP_OP_GET_JOBS));
@@ -390,12 +503,11 @@ bool GetCupsJobs(http_t* http,
}
// cupsDoRequest will delete the request.
- auto response =
- WrapIpp(cupsDoRequest(http, request.release(), printer_uri.c_str()));
+ auto response = WrapIpp(cupsDoRequest(http, request.release(), "/"));
ipp_status_t status = ippGetStatusCode(response.get());
- if (status != IPP_OK) {
+ if (status != IPP_STATUS_OK) {
LOG(WARNING) << "IPP Error: " << cupsLastErrorString();
return false;
}
« no previous file with comments | « printing/backend/cups_jobs.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698