diff options
author | vitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-09 22:51:37 +0000 |
---|---|---|
committer | vitalybuka@chromium.org <vitalybuka@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-09 22:51:37 +0000 |
commit | 07834e5a7510157c9f2cd8e707c80bc0aa4e720f (patch) | |
tree | 031597aea87c8b90e7d011e0bc383bba1a1644f3 /chrome/service/cloud_print | |
parent | 3dff2efd9274c6b14a69b9b0dd14d730badaae33 (diff) | |
download | chromium_src-07834e5a7510157c9f2cd8e707c80bc0aa4e720f.zip chromium_src-07834e5a7510157c9f2cd8e707c80bc0aa4e720f.tar.gz chromium_src-07834e5a7510157c9f2cd8e707c80bc0aa4e720f.tar.bz2 |
Fallback to CDD/CJT if connector can't initialize XPS API.
BUG=313274
Review URL: https://codereview.chromium.org/147953009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@250018 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/service/cloud_print')
-rw-r--r-- | chrome/service/cloud_print/cdd_conversion_win.cc | 118 | ||||
-rw-r--r-- | chrome/service/cloud_print/cdd_conversion_win.h | 9 | ||||
-rw-r--r-- | chrome/service/cloud_print/cloud_print_connector.cc | 2 | ||||
-rw-r--r-- | chrome/service/cloud_print/print_system.h | 4 | ||||
-rw-r--r-- | chrome/service/cloud_print/print_system_cups.cc | 5 | ||||
-rw-r--r-- | chrome/service/cloud_print/print_system_win.cc | 57 | ||||
-rw-r--r-- | chrome/service/cloud_print/printer_job_handler.cc | 18 | ||||
-rw-r--r-- | chrome/service/cloud_print/printer_job_handler_unittest.cc | 1 |
8 files changed, 185 insertions, 29 deletions
diff --git a/chrome/service/cloud_print/cdd_conversion_win.cc b/chrome/service/cloud_print/cdd_conversion_win.cc index 2c7a9a4..f1e8ffd 100644 --- a/chrome/service/cloud_print/cdd_conversion_win.cc +++ b/chrome/service/cloud_print/cdd_conversion_win.cc @@ -10,6 +10,124 @@ namespace cloud_print { +bool IsValidCjt(const std::string& print_ticket_data) { + cloud_devices::CloudDeviceDescription description; + return description.InitFromString(print_ticket_data); +} + +scoped_ptr<DEVMODE[]> CjtToDevMode(const base::string16& printer_name, + const std::string& print_ticket) { + cloud_devices::CloudDeviceDescription description; + if (!description.InitFromString(print_ticket)) + return scoped_ptr<DEVMODE[]>(); + + printing::ScopedPrinterHandle printer; + if (!printer.OpenPrinter(printer_name.c_str())) + return scoped_ptr<DEVMODE[]>(); + + wchar_t* mutable_name = const_cast<wchar_t*>(printer_name.c_str()); + LONG buffer_size = + DocumentProperties(NULL, printer, mutable_name, NULL, NULL, 0); + if (buffer_size <= 0) + return scoped_ptr<DEVMODE[]>(); + + scoped_ptr<DEVMODE[]> scoped_dev_mode( + reinterpret_cast<DEVMODE*>(new uint8[buffer_size])); + DEVMODE* dev_mode = scoped_dev_mode.get(); + if (DocumentProperties(NULL, printer, mutable_name, dev_mode, NULL, + DM_OUT_BUFFER) != IDOK) { + return scoped_ptr<DEVMODE[]>(); + } + + using namespace cloud_devices::printer; + ColorTicketItem color; + DuplexTicketItem duplex; + OrientationTicketItem orientation; + MarginsTicketItem margins; + DpiTicketItem dpi; + FitToPageTicketItem fit_to_page; + MediaTicketItem media; + CopiesTicketItem copies; + PageRangeTicketItem page_range; + CollateTicketItem collate; + ReverseTicketItem reverse; + + if (orientation.LoadFrom(description)) { + dev_mode->dmFields |= DM_ORIENTATION; + if (orientation.value() == LANDSCAPE) { + dev_mode->dmOrientation = DMORIENT_LANDSCAPE; + } else { + dev_mode->dmOrientation = DMORIENT_PORTRAIT; + } + } + + if (color.LoadFrom(description)) { + dev_mode->dmFields |= DM_COLOR; + if (color.value().type == STANDARD_MONOCHROME) { + dev_mode->dmColor = DMCOLOR_MONOCHROME; + } else if (color.value().type == STANDARD_COLOR) { + dev_mode->dmColor = DMCOLOR_COLOR; + } else { + NOTREACHED(); + } + } + + if (duplex.LoadFrom(description)) { + dev_mode->dmFields |= DM_DUPLEX; + if (duplex.value() == NO_DUPLEX) { + dev_mode->dmDuplex = DMDUP_SIMPLEX; + } else if (duplex.value() == LONG_EDGE) { + dev_mode->dmDuplex = DMDUP_VERTICAL; + } else if (duplex.value() == SHORT_EDGE) { + dev_mode->dmDuplex = DMDUP_HORIZONTAL; + } else { + NOTREACHED(); + } + } + + if (copies.LoadFrom(description)) { + dev_mode->dmFields |= DM_COPIES; + dev_mode->dmCopies = copies.value(); + } + + if (dpi.LoadFrom(description)) { + if (dpi.value().horizontal > 0) { + dev_mode->dmFields |= DM_PRINTQUALITY; + dev_mode->dmPrintQuality = dpi.value().horizontal; + } + if (dpi.value().vertical > 0) { + dev_mode->dmFields |= DM_YRESOLUTION; + dev_mode->dmYResolution = dpi.value().vertical; + } + } + + if (collate.LoadFrom(description)) { + dev_mode->dmFields |= DM_COLLATE; + dev_mode->dmCollate = (collate.value() ? DMCOLLATE_TRUE : DMCOLLATE_FALSE); + } + + if (media.LoadFrom(description)) { + static const size_t kFromUm = 100; // Windows uses 0.1mm. + int width = media.value().width_um / kFromUm; + int height = media.value().height_um / kFromUm; + if (width > 0) { + dev_mode->dmFields |= DM_PAPERWIDTH; + dev_mode->dmPaperWidth = width; + } + if (height > 0) { + dev_mode->dmFields |= DM_PAPERLENGTH; + dev_mode->dmPaperLength = height; + } + } + + if (DocumentProperties(NULL, printer, mutable_name, dev_mode, dev_mode, + DM_OUT_BUFFER | DM_IN_BUFFER) != IDOK) { + return scoped_ptr<DEVMODE[]>(); + } + + return scoped_dev_mode.Pass(); +} + std::string CapabilitiesToCdd( const printing::PrinterSemanticCapsAndDefaults& semantic_info) { using namespace cloud_devices::printer; diff --git a/chrome/service/cloud_print/cdd_conversion_win.h b/chrome/service/cloud_print/cdd_conversion_win.h index 0855922..cd751c4 100644 --- a/chrome/service/cloud_print/cdd_conversion_win.h +++ b/chrome/service/cloud_print/cdd_conversion_win.h @@ -6,6 +6,10 @@ #define CHROME_SERVICE_CLOUD_PRINT_CDD_CONVERSION_WIN_H_ #include <string> +#include <windows.h> + +#include "base/memory/scoped_ptr.h" +#include "base/strings/string16.h" namespace printing { struct PrinterSemanticCapsAndDefaults; @@ -13,6 +17,11 @@ struct PrinterSemanticCapsAndDefaults; namespace cloud_print { +bool IsValidCjt(const std::string& print_ticket); + +scoped_ptr<DEVMODE[]> CjtToDevMode(const base::string16& printer_name, + const std::string& print_ticket); + std::string CapabilitiesToCdd( const printing::PrinterSemanticCapsAndDefaults& semantic_info); diff --git a/chrome/service/cloud_print/cloud_print_connector.cc b/chrome/service/cloud_print/cloud_print_connector.cc index 94c18f0..59aa5dd 100644 --- a/chrome/service/cloud_print/cloud_print_connector.cc +++ b/chrome/service/cloud_print/cloud_print_connector.cc @@ -622,7 +622,7 @@ void CloudPrintConnector::OnReceivePrinterCaps( settings_.xmpp_ping_timeout_sec()), mime_boundary, std::string(), &post_data); post_data += GetPostDataForPrinterInfo(info, mime_boundary); - if (caps_and_defaults.caps_mime_type == kContentTypeCDD) { + if (caps_and_defaults.caps_mime_type == kContentTypeJSON) { net::AddMultipartValueForUpload(kUseCDD, "true", mime_boundary, std::string(), &post_data); } diff --git a/chrome/service/cloud_print/print_system.h b/chrome/service/cloud_print/print_system.h index 4181363..2da5f31 100644 --- a/chrome/service/cloud_print/print_system.h +++ b/chrome/service/cloud_print/print_system.h @@ -195,6 +195,10 @@ class PrintSystem : public base::RefCountedThreadSafe<PrintSystem> { const std::string& printer_name) = 0; virtual JobSpooler* CreateJobSpooler() = 0; + // Returns a true if connector should use CDD for capabilities and CJT as + // print ticket. + virtual bool UseCddAndCjt() = 0; + // Returns a comma separated list of mimetypes for print data that are // supported by this print system. The format of this string is the same as // that used for the HTTP Accept: header. diff --git a/chrome/service/cloud_print/print_system_cups.cc b/chrome/service/cloud_print/print_system_cups.cc index 9b14861..9b3ec23 100644 --- a/chrome/service/cloud_print/print_system_cups.cc +++ b/chrome/service/cloud_print/print_system_cups.cc @@ -96,6 +96,7 @@ class PrintSystemCUPS : public PrintSystem { virtual PrintSystem::PrinterWatcher* CreatePrinterWatcher( const std::string& printer_name) OVERRIDE; virtual PrintSystem::JobSpooler* CreateJobSpooler() OVERRIDE; + virtual bool UseCddAndCjt() OVERRIDE; virtual std::string GetSupportedMimeTypes() OVERRIDE; // Helper functions. @@ -728,6 +729,10 @@ PrintSystem::JobSpooler* PrintSystemCUPS::CreateJobSpooler() { return new JobSpoolerCUPS(this); } +bool PrintSystemCUPS::UseCddAndCjt() { + return false; +} + std::string PrintSystemCUPS::GetSupportedMimeTypes() { return supported_mime_types_; } diff --git a/chrome/service/cloud_print/print_system_win.cc b/chrome/service/cloud_print/print_system_win.cc index 36891b8..765ea0f 100644 --- a/chrome/service/cloud_print/print_system_win.cc +++ b/chrome/service/cloud_print/print_system_win.cc @@ -77,18 +77,14 @@ scoped_ptr<DEVMODE[]> XpsTicketToDevMode(const base::string16& printer_name, if (SUCCEEDED(hr)) { // Correct DEVMODE using DocumentProperties. See documentation for // PTConvertPrintTicketToDevMode. - LONG buffer_size = - DocumentProperties(NULL, printer, - const_cast<LPWSTR>(printer_name.c_str()), NULL, dm, - DM_IN_BUFFER); + wchar_t* mutable_name = const_cast<wchar_t*>(printer_name.c_str()); + LONG buffer_size = DocumentProperties(NULL, printer, mutable_name, NULL, + dm, DM_IN_BUFFER); if (buffer_size <= 0) return scoped_ptr<DEVMODE[]>(); - scoped_dev_mode.reset(reinterpret_cast<DEVMODE*>(new uint8[buffer_size])); - if (DocumentProperties(NULL, printer, - const_cast<LPWSTR>(printer_name.c_str()), - scoped_dev_mode.get(), dm, - DM_OUT_BUFFER | DM_IN_BUFFER) != IDOK) { + if (DocumentProperties(NULL, printer, mutable_name, scoped_dev_mode.get(), + dm, DM_OUT_BUFFER | DM_IN_BUFFER) != IDOK) { scoped_dev_mode.reset(); } printing::XPSModule::ReleaseMemory(dm); @@ -338,9 +334,14 @@ class JobSpoolerWin : public PrintSystem::JobSpooler { last_page_printed_ = -1; // We only support PDF and XPS documents for now. if (print_data_mime_type == kContentTypePDF) { - DCHECK(print_ticket_mime_type == kContentTypeXML); - scoped_ptr<DEVMODE[]> dev_mode = - XpsTicketToDevMode(base::UTF8ToWide(printer_name), print_ticket); + scoped_ptr<DEVMODE[]> dev_mode; + if (print_ticket_mime_type == kContentTypeJSON) { + dev_mode = CjtToDevMode(base::UTF8ToWide(printer_name), print_ticket); + } else { + DCHECK(print_ticket_mime_type == kContentTypeXML); + dev_mode = XpsTicketToDevMode(base::UTF8ToWide(printer_name), + print_ticket); + } if (!dev_mode) { NOTREACHED(); @@ -368,6 +369,7 @@ class JobSpoolerWin : public PrintSystem::JobSpooler { delegate_ = delegate; RenderNextPDFPages(); } else if (print_data_mime_type == kContentTypeXPS) { + DCHECK(print_ticket_mime_type == kContentTypeXML); bool ret = PrintXPSDocument(printer_name, job_title, print_data_file_path, @@ -627,7 +629,7 @@ class PrinterCapsHandler : public ServiceUtilityProcessHost::Client { const printing::PrinterSemanticCapsAndDefaults& semantic_info) OVERRIDE { printing::PrinterCapsAndDefaults printer_info; if (succeeded) { - printer_info.caps_mime_type = kContentTypeCDD; + printer_info.caps_mime_type = kContentTypeJSON; printer_info.printer_capabilities = CapabilitiesToCdd(semantic_info); } callback_.Run(succeeded, printer_name, printer_info); @@ -711,6 +713,7 @@ class PrintSystemWin : public PrintSystem { virtual PrintSystem::PrinterWatcher* CreatePrinterWatcher( const std::string& printer_name) OVERRIDE; virtual PrintSystem::JobSpooler* CreateJobSpooler() OVERRIDE; + virtual bool UseCddAndCjt() OVERRIDE; virtual std::string GetSupportedMimeTypes() OVERRIDE; private: @@ -718,22 +721,16 @@ class PrintSystemWin : public PrintSystem { const std::string& printer_name) const; scoped_refptr<printing::PrintBackend> print_backend_; - bool use_xps_; + bool use_cdd_; DISALLOW_COPY_AND_ASSIGN(PrintSystemWin); }; -PrintSystemWin::PrintSystemWin() : use_xps_(false) { +PrintSystemWin::PrintSystemWin() : use_cdd_(false) { print_backend_ = printing::PrintBackend::CreateInstance(NULL); } PrintSystem::PrintSystemResult PrintSystemWin::Init() { - use_xps_ = printing::XPSModule::Init(); - if (!use_xps_) { - std::string message = l10n_util::GetStringFUTF8( - IDS_CLOUD_PRINT_XPS_UNAVAILABLE, - l10n_util::GetStringUTF16(IDS_GOOGLE_CLOUD_PRINT)); - return PrintSystemResult(false, message); - } + use_cdd_ = !printing::XPSModule::Init(); return PrintSystemResult(true, std::string()); } @@ -752,7 +749,10 @@ void PrintSystemWin::GetPrinterCapsAndDefaults( PrinterCapsHandler* handler = new PrinterCapsHandler(printer_name, callback); handler->AddRef(); - handler->StartGetPrinterCapsAndDefaults(); + if (use_cdd_) + handler->StartGetPrinterSemanticCapsAndDefaults(); + else + handler->StartGetPrinterCapsAndDefaults(); } bool PrintSystemWin::IsValidPrinter(const std::string& printer_name) { @@ -764,6 +764,11 @@ bool PrintSystemWin::ValidatePrintTicket( const std::string& print_ticket_data, const std::string& print_ticket_data_mime_type) { crash_keys::ScopedPrinterInfo crash_key(GetPrinterDriverInfo(printer_name)); + + if (use_cdd_) { + return print_ticket_data_mime_type == kContentTypeJSON && + IsValidCjt(print_ticket_data); + } DCHECK(print_ticket_data_mime_type == kContentTypeXML); printing::ScopedXPSInitializer xps_initializer; @@ -862,9 +867,13 @@ PrintSystem::JobSpooler* PrintSystemWin::CreateJobSpooler() { return new JobSpoolerWin(); } +bool PrintSystemWin::UseCddAndCjt() { + return use_cdd_; +} + std::string PrintSystemWin::GetSupportedMimeTypes() { std::string result; - if (use_xps_) { + if (!use_cdd_) { result = kContentTypeXPS; result += ","; } diff --git a/chrome/service/cloud_print/printer_job_handler.cc b/chrome/service/cloud_print/printer_job_handler.cc index 0e8a3f8..bb13def 100644 --- a/chrome/service/cloud_print/printer_job_handler.cc +++ b/chrome/service/cloud_print/printer_job_handler.cc @@ -316,9 +316,18 @@ PrinterJobHandler::HandleJobMetadataResponse( JOB_HANDLER_JOB_STARTED, JOB_HANDLER_MAX); SetNextDataHandler(&PrinterJobHandler::HandlePrintTicketResponse); request_ = CloudPrintURLFetcher::Create(); - request_->StartGetRequest(CloudPrintURLFetcher::REQUEST_TICKET, - GURL(job_details_.print_ticket_url_), this, kJobDataMaxRetryCount, - std::string()); + if (print_system_->UseCddAndCjt()) { + request_->StartGetRequest( + CloudPrintURLFetcher::REQUEST_TICKET, + GetUrlForJobCjt(cloud_print_server_url_, job_details_.job_id_, + job_fetch_reason_), + this, kJobDataMaxRetryCount, std::string()); + } else { + request_->StartGetRequest( + CloudPrintURLFetcher::REQUEST_TICKET, + GURL(job_details_.print_ticket_url_), this, kJobDataMaxRetryCount, + std::string()); + } } else { job_available = false; base::MessageLoop::current()->PostDelayedTask( @@ -683,7 +692,8 @@ void PrinterJobHandler::OnReceivePrinterCaps( // Hashes don't match, we need to upload new capabilities (the defaults // go for free along with the capabilities) printer_info_cloud_.caps_hash = caps_hash; - if (caps_and_defaults.caps_mime_type == kContentTypeCDD) { + if (caps_and_defaults.caps_mime_type == kContentTypeJSON) { + DCHECK(print_system_->UseCddAndCjt()); net::AddMultipartValueForUpload(kUseCDD, "true", mime_boundary, std::string(), &post_data); } diff --git a/chrome/service/cloud_print/printer_job_handler_unittest.cc b/chrome/service/cloud_print/printer_job_handler_unittest.cc index ddaa1fe..38b67e7 100644 --- a/chrome/service/cloud_print/printer_job_handler_unittest.cc +++ b/chrome/service/cloud_print/printer_job_handler_unittest.cc @@ -421,6 +421,7 @@ class MockPrintSystem : public PrintSystem { PrintSystem::PrinterWatcher*(const std::string& printer_name)); MOCK_METHOD0(CreateJobSpooler, PrintSystem::JobSpooler*()); + MOCK_METHOD0(UseCddAndCjt, bool()); MOCK_METHOD0(GetSupportedMimeTypes, std::string()); friend class scoped_refptr<NiceMock<MockPrintSystem> >; |