diff options
author | noamsml@chromium.org <noamsml@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-09 17:23:25 +0000 |
---|---|---|
committer | noamsml@chromium.org <noamsml@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-11-09 17:23:25 +0000 |
commit | 014a62cbb9d6e9013c038b1e3c46ea764799be13 (patch) | |
tree | 8829dfc3b6fe774fafb8f2f5b76d6a04e79461f8 | |
parent | 901cf6ff7fb561ec08f245003c4e990610021f93 (diff) | |
download | chromium_src-014a62cbb9d6e9013c038b1e3c46ea764799be13.zip chromium_src-014a62cbb9d6e9013c038b1e3c46ea764799be13.tar.gz chromium_src-014a62cbb9d6e9013c038b1e3c46ea764799be13.tar.bz2 |
Print to Privet local printers
This is a first iteration of printing to a Privet local printer. It only
supports PDFs. PWG rasterization will be added separately.
BUG=311390
Review URL: https://codereview.chromium.org/59843010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@234126 0039d316-1c4b-4281-b951-d872f2087c98
11 files changed, 241 insertions, 33 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 05f6735..8bd150c 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -8691,6 +8691,9 @@ The following plug-in is unresponsive: <ph name="PLUGIN_NAME">$1 <message name="IDS_PRINT_PREVIEW_NO_DESTS_PROMO_NOT_NOW_BUTTON_LABEL" desc="Label of button to cancel the Google Cloud Print promotion."> Not now </message> + <message name="IDS_PRINT_PREVIEW_COULD_NOT_PRINT" desc="Error message when printing fails in the print preview"> + Printing failed. Please check your printer and try again. + </message> <!-- Load State --> <message name="IDS_LOAD_STATE_WAITING_FOR_SOCKET_SLOT" desc="Status text when Chrome is at its connection limit, and is waiting for a URL request to complete to free up a connection."> diff --git a/chrome/browser/resources/print_preview/data/destination_store.js b/chrome/browser/resources/print_preview/data/destination_store.js index 13330d4..58a45e8 100644 --- a/chrome/browser/resources/print_preview/data/destination_store.js +++ b/chrome/browser/resources/print_preview/data/destination_store.js @@ -680,7 +680,8 @@ cr.define('print_preview', function() { dest.capabilities = event.capabilities; this.updateDestination(dest); - if (this.selectedDestination_ == dest) { + if (this.selectedDestination_.isPrivet && + this.selectedDestination_.id == dest.id) { cr.dispatchSimpleEvent( this, DestinationStore.EventType.SELECTED_DESTINATION_CAPABILITIES_READY); diff --git a/chrome/browser/resources/print_preview/data/print_ticket_store.js b/chrome/browser/resources/print_preview/data/print_ticket_store.js index 1db2260..e99d4a8 100644 --- a/chrome/browser/resources/print_preview/data/print_ticket_store.js +++ b/chrome/browser/resources/print_preview/data/print_ticket_store.js @@ -337,9 +337,10 @@ cr.define('print_preview', function() { * @return {!Object} Google Cloud Print print ticket. */ createPrintTicket: function(destination) { - assert(!destination.isLocal, + assert(!destination.isLocal || destination.isPrivet, 'Trying to create a Google Cloud Print print ticket for a local ' + - 'destination'); + ' non-privet destination'); + assert(destination.capabilities, 'Trying to create a Google Cloud Print print ticket for a ' + 'destination with no print capabilities'); diff --git a/chrome/browser/resources/print_preview/native_layer.js b/chrome/browser/resources/print_preview/native_layer.js index 7a2fa36..112b573 100644 --- a/chrome/browser/resources/print_preview/native_layer.js +++ b/chrome/browser/resources/print_preview/native_layer.js @@ -48,6 +48,7 @@ cr.define('print_preview', function() { this.onPrivetPrinterSearchDone_.bind(this); global['onPrivetCapabilitiesSet'] = this.onPrivetCapabilitiesSet_.bind(this); + global['onPrivetPrintFailed'] = this.onPrivetPrintFailed_.bind(this); }; /** @@ -81,7 +82,8 @@ cr.define('print_preview', function() { PRIVET_PRINTER_SEARCH_DONE: 'print_preview.NativeLayer.PRIVET_PRINTER_SEARCH_DONE', PRIVET_CAPABILITIES_SET: - 'print_preview.NativeLayer.PRIVET_CAPABILITIES_SET' + 'print_preview.NativeLayer.PRIVET_CAPABILITIES_SET', + PRIVET_PRINT_FAILED: 'print_preview.NativeLayer.PRIVET_PRINT_FAILED' }; /** @@ -273,6 +275,7 @@ cr.define('print_preview', function() { 'printToPDF': destination.id == print_preview.Destination.GooglePromotedId.SAVE_AS_PDF, 'printWithCloudPrint': !destination.isLocal, + 'printWithPrivet': destination.isPrivet, 'deviceName': destination.id, 'isFirstRequest': false, 'requestID': -1, @@ -300,6 +303,10 @@ cr.define('print_preview', function() { }; } + if (destination.isPrivet) { + ticket['ticket'] = printTicketStore.createPrintTicket(destination); + } + if (opt_isOpenPdfInPreview) { ticket['OpenPDFInPreview'] = true; } @@ -654,8 +661,8 @@ cr.define('print_preview', function() { * @private */ onPrivetPrinterSearchDone_: function() { - var privetPrinterSearchDoneEvent = new Event( - NativeLayer.EventType.PRIVET_PRINTER_SEARCH_DONE); + var privetPrinterSearchDoneEvent = + new Event(NativeLayer.EventType.PRIVET_PRINTER_SEARCH_DONE); this.dispatchEvent(privetPrinterSearchDoneEvent); }, @@ -665,11 +672,23 @@ cr.define('print_preview', function() { * @private */ onPrivetCapabilitiesSet_: function(printer, capabilities) { - var privetCapabilitiesSetEvent = new Event( - NativeLayer.EventType.PRIVET_CAPABILITIES_SET); + var privetCapabilitiesSetEvent = + new Event(NativeLayer.EventType.PRIVET_CAPABILITIES_SET); privetCapabilitiesSetEvent.printer = printer; privetCapabilitiesSetEvent.capabilities = capabilities; this.dispatchEvent(privetCapabilitiesSetEvent); + }, + + /** + * @param {string} http_error The HTTP response code or -1 if not an HTTP + * error. + * @private + */ + onPrivetPrintFailed_: function(http_error) { + var privetPrintFailedEvent = + new Event(NativeLayer.EventType.PRIVET_PRINT_FAILED); + privetPrintFailedEvent.httpError = http_error; + this.dispatchEvent(privetPrintFailedEvent); } }; diff --git a/chrome/browser/resources/print_preview/print_preview.js b/chrome/browser/resources/print_preview/print_preview.js index ec356b8..c26a584 100644 --- a/chrome/browser/resources/print_preview/print_preview.js +++ b/chrome/browser/resources/print_preview/print_preview.js @@ -260,6 +260,11 @@ cr.define('print_preview', function() { this.nativeLayer_, print_preview.NativeLayer.EventType.DISABLE_SCALING, this.onDisableScaling_.bind(this)); + this.tracker.add( + this.nativeLayer_, + print_preview.NativeLayer.EventType.PRIVET_PRINT_FAILED, + this.onPrivetPrintFailed_.bind(this)); + this.tracker.add( $('system-dialog-link'), @@ -406,6 +411,7 @@ cr.define('print_preview', function() { this.setIsEnabled_(false); if (this.printIfReady_() && ((this.destinationStore_.selectedDestination.isLocal && + !this.destinationStore_.selectedDestination.isPrivet && this.destinationStore_.selectedDestination.id != print_preview.Destination.GooglePromotedId.SAVE_AS_PDF) || this.uiState_ == PrintPreview.UiState_.OPENING_PDF_PREVIEW)) { @@ -803,6 +809,18 @@ cr.define('print_preview', function() { }, /** + * Called when privet printing fails. + * @param {Event} event Event object representing the failure. + * @private + */ + onPrivetPrintFailed_: function(event) { + console.error('Privet printing failed with error code ' + + event.httpError); + this.printHeader_.setErrorMessage( + localStrings.getString('couldNotPrint')); + }, + + /** * Called when the open-cloud-print-dialog link is clicked. Opens the Google * Cloud Print web dialog. * @private diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc index aadc478..8dcfd8cd 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc @@ -37,6 +37,9 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/profile_oauth2_token_service.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" +#include "chrome/browser/signin/signin_manager.h" +#include "chrome/browser/signin/signin_manager_base.h" +#include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/chrome_select_file_policy.h" @@ -88,6 +91,7 @@ enum UserActionBuckets { INITIATOR_CRASHED, // UNUSED INITIATOR_CLOSED, PRINT_WITH_CLOUD_PRINT, + PRINT_WITH_PRIVET, USERACTION_BUCKET_BOUNDARY }; @@ -602,24 +606,10 @@ void PrintPreviewHandler::HandleGetPrivetPrinterCapabilities( bool success = args->GetString(0, &name); DCHECK(success); - const local_discovery::DeviceDescription* device_description = - printer_lister_->GetDeviceDescription(name); - - if (!device_description) { - SendPrivetCapabilitiesError(name); - return; - } - - privet_http_factory_ = - local_discovery::PrivetHTTPAsynchronousFactory::CreateInstance( - service_discovery_client_, - Profile::FromWebUI(web_ui())->GetRequestContext()); - privet_http_resolution_ = privet_http_factory_->CreatePrivetHTTP( + CreatePrivetHTTP( name, - device_description->address, - base::Bind(&PrintPreviewHandler::StartPrivetCapabilities, + base::Bind(&PrintPreviewHandler::PrivetCapabilitiesUpdateClient, base::Unretained(this))); - privet_http_resolution_->Start(); #endif } @@ -718,6 +708,7 @@ void PrintPreviewHandler::HandlePrint(const ListValue* args) { bool print_to_pdf = false; bool is_cloud_printer = false; + bool print_with_privet = false; bool open_pdf_in_preview = false; #if defined(OS_MACOSX) @@ -726,6 +717,7 @@ void PrintPreviewHandler::HandlePrint(const ListValue* args) { if (!open_pdf_in_preview) { settings->GetBoolean(printing::kSettingPrintToPDF, &print_to_pdf); + settings->GetBoolean(printing::kSettingPrintWithPrivet, &print_with_privet); is_cloud_printer = settings->HasKey(printing::kSettingCloudPrintId); } @@ -739,6 +731,26 @@ void PrintPreviewHandler::HandlePrint(const ListValue* args) { return; } +#if defined(ENABLE_MDNS) + if (print_with_privet && PrivetPrintingEnabled()) { + std::string printer_name; + std::string print_ticket; + UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintWithPrivet", + page_count); + ReportUserActionHistogram(PRINT_WITH_PRIVET); + + bool success = settings->GetString(printing::kSettingDeviceName, + &printer_name); + DCHECK(success); + success = settings->GetString(printing::kSettingTicket, + &print_ticket); + DCHECK(success); + + PrintToPrivetPrinter(printer_name, print_ticket); + return; + } +#endif + scoped_refptr<base::RefCountedBytes> data; string16 title; if (!GetPreviewDataAndTitle(&data, &title)) { @@ -1366,22 +1378,68 @@ void PrintPreviewHandler::StopPrivetPrinterSearch() { web_ui()->CallJavascriptFunction("onPrivetPrinterSearchDone"); } -void PrintPreviewHandler::StartPrivetCapabilities( +void PrintPreviewHandler::PrivetCapabilitiesUpdateClient( + scoped_ptr<local_discovery::PrivetHTTPClient> http_client) { + if (!PrivetUpdateClient(http_client.Pass())) + return; + + privet_capabilities_operation_ = + privet_http_client_->CreateCapabilitiesOperation( + this); + privet_capabilities_operation_->Start(); +} + +bool PrintPreviewHandler::PrivetUpdateClient( scoped_ptr<local_discovery::PrivetHTTPClient> http_client) { if (!http_client) { SendPrivetCapabilitiesError(privet_http_resolution_->GetName()); privet_http_resolution_.reset(); - return; + return false; } + privet_local_print_operation_.reset(); + privet_capabilities_operation_.reset(); privet_http_client_ = http_client.Pass(); - privet_capabilities_operation_ = - privet_http_client_->CreateCapabilitiesOperation( - this); + privet_http_resolution_.reset(); - privet_capabilities_operation_->Start(); + + return true; } +void PrintPreviewHandler::PrivetLocalPrintUpdateClient( + std::string print_ticket, + scoped_ptr<local_discovery::PrivetHTTPClient> http_client) { + if (!PrivetUpdateClient(http_client.Pass())) + return; + + StartPrivetLocalPrint(print_ticket); +} + +void PrintPreviewHandler::StartPrivetLocalPrint( + const std::string& print_ticket) { + privet_local_print_operation_ = + privet_http_client_->CreateLocalPrintOperation(this); + + privet_local_print_operation_->SetTicket(print_ticket); + + PrintPreviewUI* print_preview_ui = static_cast<PrintPreviewUI*>( + web_ui()->GetController()); + privet_local_print_operation_->SetJobname( + base::UTF16ToUTF8(print_preview_ui->initiator_title())); + + Profile* profile = Profile::FromWebUI(web_ui()); + SigninManagerBase* signin_manager = + SigninManagerFactory::GetForProfileIfExists(profile); + + if (signin_manager) { + privet_local_print_operation_->SetUsername( + signin_manager->GetAuthenticatedUsername()); + } + + privet_local_print_operation_->Start(); +} + + void PrintPreviewHandler::OnPrivetCapabilities( local_discovery::PrivetCapabilitiesOperation* capabilities_operation, int http_error, @@ -1420,6 +1478,75 @@ void PrintPreviewHandler::SendPrivetCapabilitiesError( name_value); } +void PrintPreviewHandler::PrintToPrivetPrinter( + const std::string& device_name, + const std::string& ticket) { + CreatePrivetHTTP( + device_name, + base::Bind(&PrintPreviewHandler::PrivetLocalPrintUpdateClient, + base::Unretained(this), + ticket)); +} + +bool PrintPreviewHandler::CreatePrivetHTTP( + const std::string& name, + const local_discovery::PrivetHTTPAsynchronousFactory::ResultCallback& + callback) { + const local_discovery::DeviceDescription* device_description = + printer_lister_->GetDeviceDescription(name); + + if (!device_description) { + SendPrivetCapabilitiesError(name); + return false; + } + + privet_http_factory_ = + local_discovery::PrivetHTTPAsynchronousFactory::CreateInstance( + service_discovery_client_, + Profile::FromWebUI(web_ui())->GetRequestContext()); + privet_http_resolution_ = privet_http_factory_->CreatePrivetHTTP( + name, + device_description->address, + callback); + privet_http_resolution_->Start(); + + return true; +} + +void PrintPreviewHandler::OnPrivetPrintingRequestPDF( + const local_discovery::PrivetLocalPrintOperation* print_operation) { + scoped_refptr<base::RefCountedBytes> data; + string16 title; + + if (!GetPreviewDataAndTitle(&data, &title)) { + base::FundamentalValue http_code_value(-1); + web_ui()->CallJavascriptFunction("onPrivetPrintFailed", http_code_value); + return; + } + + // TODO(noamsml): Move data into request without copying it? + std::string data_str((const char*)data->front(), data->size()); + + privet_local_print_operation_->SendData(data_str); +} + +void PrintPreviewHandler::OnPrivetPrintingRequestPWGRaster( + const local_discovery::PrivetLocalPrintOperation* print_operation) { + NOTIMPLEMENTED(); +} + +void PrintPreviewHandler::OnPrivetPrintingDone( + const local_discovery::PrivetLocalPrintOperation* print_operation) { + ClosePreviewDialog(); +} + +void PrintPreviewHandler::OnPrivetPrintingError( + const local_discovery::PrivetLocalPrintOperation* print_operation, + int http_code) { + base::FundamentalValue http_code_value(http_code); + web_ui()->CallJavascriptFunction("onPrivetPrintFailed", http_code_value); +} + void PrintPreviewHandler::FillPrinterDescription( const std::string& name, const local_discovery::DeviceDescription& description, diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.h b/chrome/browser/ui/webui/print_preview/print_preview_handler.h index c6ee255b..9892698 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler.h +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.h @@ -42,6 +42,7 @@ class PrintPreviewHandler #if defined(ENABLE_MDNS) public local_discovery::PrivetLocalPrinterLister::Delegate, public local_discovery::PrivetCapabilitiesOperation::Delegate, + public local_discovery::PrivetLocalPrintOperation::Delegate, #endif public ui::SelectFileDialog::Listener, public printing::PrintViewManagerObserver @@ -91,6 +92,20 @@ class PrintPreviewHandler local_discovery::PrivetCapabilitiesOperation* capabilities_operation, int http_error, const base::DictionaryValue* capabilities) OVERRIDE; + + // PrivetLocalPrintOperation::Delegate implementation. + virtual void OnPrivetPrintingRequestPDF( + const local_discovery::PrivetLocalPrintOperation* + print_operation) OVERRIDE; + virtual void OnPrivetPrintingRequestPWGRaster( + const local_discovery::PrivetLocalPrintOperation* + print_operation) OVERRIDE; + virtual void OnPrivetPrintingDone( + const local_discovery::PrivetLocalPrintOperation* + print_operation) OVERRIDE; + virtual void OnPrivetPrintingError( + const local_discovery::PrivetLocalPrintOperation* print_operation, + int http_code) OVERRIDE; #endif // ENABLE_MDNS private: @@ -237,9 +252,21 @@ class PrintPreviewHandler #if defined(ENABLE_MDNS) void StopPrivetPrinterSearch(); - void StartPrivetCapabilities( + void PrivetCapabilitiesUpdateClient( + scoped_ptr<local_discovery::PrivetHTTPClient> http_client); + void PrivetLocalPrintUpdateClient( + std::string printTicket, scoped_ptr<local_discovery::PrivetHTTPClient> http_client); + bool PrivetUpdateClient( + scoped_ptr<local_discovery::PrivetHTTPClient> http_client); + void StartPrivetLocalPrint(const std::string& print_ticket); void SendPrivetCapabilitiesError(const std::string& id); + void PrintToPrivetPrinter(const std::string& printer_name, + const std::string& print_ticket); + bool CreatePrivetHTTP( + const std::string& name, + const local_discovery::PrivetHTTPAsynchronousFactory::ResultCallback& + callback); void FillPrinterDescription( const std::string& name, const local_discovery::DeviceDescription& description, @@ -289,6 +316,8 @@ class PrintPreviewHandler scoped_ptr<local_discovery::PrivetHTTPClient> privet_http_client_; scoped_ptr<local_discovery::PrivetCapabilitiesOperation> privet_capabilities_operation_; + scoped_ptr<local_discovery::PrivetLocalPrintOperation> + privet_local_print_operation_; #endif base::WeakPtrFactory<PrintPreviewHandler> weak_factory_; diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc index e927c4d..5e99899 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc @@ -320,6 +320,8 @@ content::WebUIDataSource* CreatePrintPreviewUISource() { source->AddLocalizedString( "noDestsPromoNotNowButtonLabel", IDS_PRINT_PREVIEW_NO_DESTS_PROMO_NOT_NOW_BUTTON_LABEL); + source->AddLocalizedString("couldNotPrint", + IDS_PRINT_PREVIEW_COULD_NOT_PRINT); source->SetJsonPath("strings.js"); source->AddResourcePath("print_preview.js", IDR_PRINT_PREVIEW_JS); diff --git a/cloud_print/gcp20/prototype/print_job_handler.cc b/cloud_print/gcp20/prototype/print_job_handler.cc index a82f26f..5666143 100644 --- a/cloud_print/gcp20/prototype/print_job_handler.cc +++ b/cloud_print/gcp20/prototype/print_job_handler.cc @@ -23,7 +23,7 @@ const int kLocalPrintJobExpirationSec = 20; const int kErrorTimeoutSec = 30; // Errors simulation constants: -const double kPaperJamProbability = 0.2; +const double kPaperJamProbability = 1.0; const int kTooManyDraftsTimeout = 10; const size_t kMaxDrafts = 5; @@ -321,4 +321,3 @@ void PrintJobHandler::ForgetDraft(const std::string& id) { void PrintJobHandler::ForgetLocalJob(const std::string& id) { jobs.erase(id); } - diff --git a/printing/print_job_constants.cc b/printing/print_job_constants.cc index b2fefa8..25b5b49 100644 --- a/printing/print_job_constants.cc +++ b/printing/print_job_constants.cc @@ -119,6 +119,13 @@ const char kSettingPrinterName[] = "printerName"; // Print to PDF option: true if selected, false if not. const char kSettingPrintToPDF[] = "printToPDF"; +// Print using Privet option: true if destination is a Privet printer, false if +// not. +const char kSettingPrintWithPrivet[] = "printWithPrivet"; + +// Ticket option. Contains the ticket in CJT format. +const char kSettingTicket[] = "ticket"; + // Whether to print CSS backgrounds. const char kSettingShouldPrintBackgrounds[] = "shouldPrintBackgrounds"; diff --git a/printing/print_job_constants.h b/printing/print_job_constants.h index 526f8ee..4fd55d4 100644 --- a/printing/print_job_constants.h +++ b/printing/print_job_constants.h @@ -48,6 +48,8 @@ PRINTING_EXPORT extern const char kSettingPrintableAreaWidth[]; PRINTING_EXPORT extern const char kSettingPrintableAreaHeight[]; PRINTING_EXPORT extern const char kSettingPrinterName[]; PRINTING_EXPORT extern const char kSettingPrintToPDF[]; +PRINTING_EXPORT extern const char kSettingPrintWithPrivet[]; +PRINTING_EXPORT extern const char kSettingTicket[]; PRINTING_EXPORT extern const char kSettingShouldPrintBackgrounds[]; PRINTING_EXPORT extern const char kSettingShouldPrintSelectionOnly[]; |