blob: 5d43e211e03b06547efc591f6b8772f2f88e4497 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// TODO(rltoscano): Move data/* into print_preview.data namespace
var localStrings = new LocalStrings(templateData);
<include src="component.js"/>
<include src="print_preview_focus_manager.js"/>
cr.define('print_preview', function() {
'use strict';
/**
* Container class for Chromium's print preview.
* @constructor
* @extends {print_preview.Component}
*/
function PrintPreview() {
print_preview.Component.call(this);
/**
* Used to communicate with Chromium's print system.
* @type {!print_preview.NativeLayer}
* @private
*/
this.nativeLayer_ = new print_preview.NativeLayer();
/**
* Event target that contains information about the logged in user.
* @type {!print_preview.UserInfo}
* @private
*/
this.userInfo_ = new print_preview.UserInfo();
/**
* Application state.
* @type {!print_preview.AppState}
* @private
*/
this.appState_ = new print_preview.AppState();
/**
* Data model that holds information about the document to print.
* @type {!print_preview.DocumentInfo}
* @private
*/
this.documentInfo_ = new print_preview.DocumentInfo();
/**
* Data store which holds print destinations.
* @type {!print_preview.DestinationStore}
* @private
*/
this.destinationStore_ = new print_preview.DestinationStore(
this.nativeLayer_, this.userInfo_, this.appState_);
/**
* Storage of the print ticket used to create the print job.
* @type {!print_preview.PrintTicketStore}
* @private
*/
this.printTicketStore_ = new print_preview.PrintTicketStore(
this.destinationStore_, this.appState_, this.documentInfo_);
/**
* Holds the print and cancel buttons and renders some document statistics.
* @type {!print_preview.PrintHeader}
* @private
*/
this.printHeader_ = new print_preview.PrintHeader(
this.printTicketStore_, this.destinationStore_);
this.addChild(this.printHeader_);
/**
* Component used to search for print destinations.
* @type {!print_preview.DestinationSearch}
* @private
*/
this.destinationSearch_ = new print_preview.DestinationSearch(
this.destinationStore_, this.userInfo_);
this.addChild(this.destinationSearch_);
/**
* Component that renders the print destination.
* @type {!print_preview.DestinationSettings}
* @private
*/
this.destinationSettings_ = new print_preview.DestinationSettings(
this.destinationStore_);
this.addChild(this.destinationSettings_);
/**
* Component that renders UI for entering in page range.
* @type {!print_preview.PageSettings}
* @private
*/
this.pageSettings_ = new print_preview.PageSettings(
this.printTicketStore_.pageRange);
this.addChild(this.pageSettings_);
/**
* Component that renders the copies settings.
* @type {!print_preview.CopiesSettings}
* @private
*/
this.copiesSettings_ = new print_preview.CopiesSettings(
this.printTicketStore_.copies, this.printTicketStore_.collate);
this.addChild(this.copiesSettings_);
/**
* Component that renders the media size settings.
* @type {!print_preview.MediaSizeSettings}
* @private
*/
this.mediaSizeSettings_ =
new print_preview.MediaSizeSettings(this.printTicketStore_.mediaSize);
this.addChild(this.mediaSizeSettings_);
/**
* Component that renders the layout settings.
* @type {!print_preview.LayoutSettings}
* @private
*/
this.layoutSettings_ =
new print_preview.LayoutSettings(this.printTicketStore_.landscape);
this.addChild(this.layoutSettings_);
/**
* Component that renders the color options.
* @type {!print_preview.ColorSettings}
* @private
*/
this.colorSettings_ =
new print_preview.ColorSettings(this.printTicketStore_.color);
this.addChild(this.colorSettings_);
/**
* Component that renders a select box for choosing margin settings.
* @type {!print_preview.MarginSettings}
* @private
*/
this.marginSettings_ =
new print_preview.MarginSettings(this.printTicketStore_.marginsType);
this.addChild(this.marginSettings_);
/**
* Component that renders miscellaneous print options.
* @type {!print_preview.OtherOptionsSettings}
* @private
*/
this.otherOptionsSettings_ = new print_preview.OtherOptionsSettings(
this.printTicketStore_.duplex,
this.printTicketStore_.fitToPage,
this.printTicketStore_.cssBackground,
this.printTicketStore_.selectionOnly,
this.printTicketStore_.headerFooter);
this.addChild(this.otherOptionsSettings_);
/**
* Component that renders the advanced options button.
* @type {!print_preview.AdvancedOptionsSettings}
* @private
*/
this.advancedOptionsSettings_ = new print_preview.AdvancedOptionsSettings(
this.destinationStore_);
this.addChild(this.advancedOptionsSettings_);
/**
* Component used to search for print destinations.
* @type {!print_preview.AdvancedSettings}
* @private
*/
this.advancedSettings_ = new print_preview.AdvancedSettings(
this.printTicketStore_);
this.addChild(this.advancedSettings_);
/**
* Area of the UI that holds the print preview.
* @type {!print_preview.PreviewArea}
* @private
*/
this.previewArea_ = new print_preview.PreviewArea(this.destinationStore_,
this.printTicketStore_,
this.nativeLayer_,
this.documentInfo_);
this.addChild(this.previewArea_);
/**
* Interface to the Google Cloud Print API. Null if Google Cloud Print
* integration is disabled.
* @type {cloudprint.CloudPrintInterface}
* @private
*/
this.cloudPrintInterface_ = null;
/**
* Whether in kiosk mode where print preview can print automatically without
* user intervention. See http://crbug.com/31395. Print will start when
* both the print ticket has been initialized, and an initial printer has
* been selected.
* @type {boolean}
* @private
*/
this.isInKioskAutoPrintMode_ = false;
/**
* Whether Print Preview is in App Kiosk mode, basically, use only printers
* available for the device.
* @type {boolean}
* @private
*/
this.isInAppKioskMode_ = false;
/**
* State of the print preview UI.
* @type {print_preview.PrintPreview.UiState_}
* @private
*/
this.uiState_ = PrintPreview.UiState_.INITIALIZING;
/**
* Whether document preview generation is in progress.
* @type {boolean}
* @private
*/
this.isPreviewGenerationInProgress_ = true;
};
/**
* States of the print preview.
* @enum {string}
* @private
*/
PrintPreview.UiState_ = {
INITIALIZING: 'initializing',
READY: 'ready',
OPENING_PDF_PREVIEW: 'opening-pdf-preview',
OPENING_CLOUD_PRINT_DIALOG: 'opening-cloud-print-dialog',
OPENING_NATIVE_PRINT_DIALOG: 'opening-native-print-dialog',
PRINTING: 'printing',
FILE_SELECTION: 'file-selection',
CLOSING: 'closing',
ERROR: 'error'
};
/**
* What can happen when print preview tries to print.
* @enum {string}
* @private
*/
PrintPreview.PrintAttemptResult_ = {
NOT_READY: 'not-ready',
PRINTED: 'printed',
READY_WAITING_FOR_PREVIEW: 'ready-waiting-for-preview'
};
PrintPreview.prototype = {
__proto__: print_preview.Component.prototype,
/** Sets up the page and print preview by getting the printer list. */
initialize: function() {
this.decorate($('print-preview'));
i18nTemplate.process(document, templateData);
if (!this.previewArea_.hasCompatiblePlugin) {
this.setIsEnabled_(false);
}
this.nativeLayer_.startGetInitialSettings();
print_preview.PrintPreviewFocusManager.getInstance().initialize();
cr.ui.FocusOutlineManager.forDocument(document);
},
/** @override */
enterDocument: function() {
// Native layer events.
this.tracker.add(
this.nativeLayer_,
print_preview.NativeLayer.EventType.INITIAL_SETTINGS_SET,
this.onInitialSettingsSet_.bind(this));
this.tracker.add(
this.nativeLayer_,
print_preview.NativeLayer.EventType.CLOUD_PRINT_ENABLE,
this.onCloudPrintEnable_.bind(this));
this.tracker.add(
this.nativeLayer_,
print_preview.NativeLayer.EventType.PRINT_TO_CLOUD,
this.onPrintToCloud_.bind(this));
this.tracker.add(
this.nativeLayer_,
print_preview.NativeLayer.EventType.FILE_SELECTION_CANCEL,
this.onFileSelectionCancel_.bind(this));
this.tracker.add(
this.nativeLayer_,
print_preview.NativeLayer.EventType.FILE_SELECTION_COMPLETE,
this.onFileSelectionComplete_.bind(this));
this.tracker.add(
this.nativeLayer_,
print_preview.NativeLayer.EventType.SETTINGS_INVALID,
this.onSettingsInvalid_.bind(this));
this.tracker.add(
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(
this.nativeLayer_,
print_preview.NativeLayer.EventType.MANIPULATE_SETTINGS_FOR_TEST,
this.onManipulateSettingsForTest_.bind(this));
this.tracker.add(
$('system-dialog-link'),
'click',
this.openSystemPrintDialog_.bind(this));
this.tracker.add(
$('cloud-print-dialog-link'),
'click',
this.onCloudPrintDialogLinkClick_.bind(this));
this.tracker.add(
$('open-pdf-in-preview-link'),
'click',
this.onOpenPdfInPreviewLinkClick_.bind(this));
this.tracker.add(
this.previewArea_,
print_preview.PreviewArea.EventType.PREVIEW_GENERATION_IN_PROGRESS,
this.onPreviewGenerationInProgress_.bind(this));
this.tracker.add(
this.previewArea_,
print_preview.PreviewArea.EventType.PREVIEW_GENERATION_DONE,
this.onPreviewGenerationDone_.bind(this));
this.tracker.add(
this.previewArea_,
print_preview.PreviewArea.EventType.PREVIEW_GENERATION_FAIL,
this.onPreviewGenerationFail_.bind(this));
this.tracker.add(
this.previewArea_,
print_preview.PreviewArea.EventType.OPEN_SYSTEM_DIALOG_CLICK,
this.openSystemPrintDialog_.bind(this));
this.tracker.add(
this.destinationStore_,
print_preview.DestinationStore.EventType.
SELECTED_DESTINATION_CAPABILITIES_READY,
this.printIfReady_.bind(this));
this.tracker.add(
this.destinationStore_,
print_preview.DestinationStore.EventType.DESTINATION_SELECT,
this.onDestinationSelect_.bind(this));
this.tracker.add(
this.destinationStore_,
print_preview.DestinationStore.EventType.DESTINATION_SEARCH_DONE,
this.onDestinationSearchDone_.bind(this));
this.tracker.add(
this.printHeader_,
print_preview.PrintHeader.EventType.PRINT_BUTTON_CLICK,
this.onPrintButtonClick_.bind(this));
this.tracker.add(
this.printHeader_,
print_preview.PrintHeader.EventType.CANCEL_BUTTON_CLICK,
this.onCancelButtonClick_.bind(this));
this.tracker.add(window, 'keydown', this.onKeyDown_.bind(this));
this.tracker.add(
this.destinationSettings_,
print_preview.DestinationSettings.EventType.CHANGE_BUTTON_ACTIVATE,
this.onDestinationChangeButtonActivate_.bind(this));
this.tracker.add(
this.destinationSearch_,
print_preview.DestinationSearch.EventType.MANAGE_CLOUD_DESTINATIONS,
this.onManageCloudDestinationsActivated_.bind(this));
this.tracker.add(
this.destinationSearch_,
print_preview.DestinationSearch.EventType.MANAGE_LOCAL_DESTINATIONS,
this.onManageLocalDestinationsActivated_.bind(this));
this.tracker.add(
this.destinationSearch_,
print_preview.DestinationSearch.EventType.ADD_ACCOUNT,
this.onCloudPrintSignInActivated_.bind(this, true /*addAccount*/));
this.tracker.add(
this.destinationSearch_,
print_preview.DestinationSearch.EventType.SIGN_IN,
this.onCloudPrintSignInActivated_.bind(this, false /*addAccount*/));
this.tracker.add(
this.destinationSearch_,
print_preview.DestinationListItem.EventType.REGISTER_PROMO_CLICKED,
this.onCloudPrintRegisterPromoClick_.bind(this));
this.tracker.add(
this.advancedOptionsSettings_,
print_preview.AdvancedOptionsSettings.EventType.BUTTON_ACTIVATED,
this.onAdvancedOptionsButtonActivated_.bind(this));
// TODO(rltoscano): Move no-destinations-promo into its own component
// instead being part of PrintPreview.
this.tracker.add(
this.getChildElement('#no-destinations-promo .close-button'),
'click',
this.onNoDestinationsPromoClose_.bind(this));
this.tracker.add(
this.getChildElement('#no-destinations-promo .not-now-button'),
'click',
this.onNoDestinationsPromoClose_.bind(this));
this.tracker.add(
this.getChildElement('#no-destinations-promo .add-printer-button'),
'click',
this.onNoDestinationsPromoClick_.bind(this));
},
/** @override */
decorateInternal: function() {
this.printHeader_.decorate($('print-header'));
this.destinationSearch_.decorate($('destination-search'));
this.destinationSettings_.decorate($('destination-settings'));
this.pageSettings_.decorate($('page-settings'));
this.copiesSettings_.decorate($('copies-settings'));
this.mediaSizeSettings_.decorate($('media-size-settings'));
this.layoutSettings_.decorate($('layout-settings'));
this.colorSettings_.decorate($('color-settings'));
this.marginSettings_.decorate($('margin-settings'));
this.otherOptionsSettings_.decorate($('other-options-settings'));
this.advancedOptionsSettings_.decorate($('advanced-options-settings'));
this.advancedSettings_.decorate($('advanced-settings'));
this.previewArea_.decorate($('preview-area'));
setIsVisible($('open-pdf-in-preview-link'), cr.isMac);
},
/**
* Sets whether the controls in the print preview are enabled.
* @param {boolean} isEnabled Whether the controls in the print preview are
* enabled.
* @private
*/
setIsEnabled_: function(isEnabled) {
$('system-dialog-link').disabled = !isEnabled;
$('cloud-print-dialog-link').disabled = !isEnabled;
$('open-pdf-in-preview-link').disabled = !isEnabled;
this.printHeader_.isEnabled = isEnabled;
this.destinationSettings_.isEnabled = isEnabled;
this.pageSettings_.isEnabled = isEnabled;
this.copiesSettings_.isEnabled = isEnabled;
this.mediaSizeSettings_.isEnabled = isEnabled;
this.layoutSettings_.isEnabled = isEnabled;
this.colorSettings_.isEnabled = isEnabled;
this.marginSettings_.isEnabled = isEnabled;
this.otherOptionsSettings_.isEnabled = isEnabled;
this.advancedOptionsSettings_.isEnabled = isEnabled;
},
/**
* Prints the document or launches a pdf preview on the local system.
* @param {boolean} isPdfPreview Whether to launch the pdf preview.
* @private
*/
printDocumentOrOpenPdfPreview_: function(isPdfPreview) {
assert(this.uiState_ == PrintPreview.UiState_.READY,
'Print document request received when not in ready state: ' +
this.uiState_);
if (isPdfPreview) {
this.uiState_ = PrintPreview.UiState_.OPENING_PDF_PREVIEW;
} else if (this.destinationStore_.selectedDestination.id ==
print_preview.Destination.GooglePromotedId.SAVE_AS_PDF) {
this.uiState_ = PrintPreview.UiState_.FILE_SELECTION;
} else {
this.uiState_ = PrintPreview.UiState_.PRINTING;
}
this.setIsEnabled_(false);
this.printHeader_.isCancelButtonEnabled = true;
var printAttemptResult = this.printIfReady_();
if (printAttemptResult == PrintPreview.PrintAttemptResult_.PRINTED ||
printAttemptResult ==
PrintPreview.PrintAttemptResult_.READY_WAITING_FOR_PREVIEW) {
if ((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) {
// Hide the dialog for now. The actual print command will be issued
// when the preview generation is done.
this.nativeLayer_.startHideDialog();
}
}
},
/**
* Attempts to print if needed and if ready.
* @return {PrintPreview.PrintAttemptResult_} Attempt result.
* @private
*/
printIfReady_: function() {
var okToPrint =
(this.uiState_ == PrintPreview.UiState_.PRINTING ||
this.uiState_ == PrintPreview.UiState_.OPENING_PDF_PREVIEW ||
this.uiState_ == PrintPreview.UiState_.FILE_SELECTION ||
this.uiState_ == PrintPreview.UiState_.OPENING_CLOUD_PRINT_DIALOG ||
this.isInKioskAutoPrintMode_) &&
this.destinationStore_.selectedDestination &&
this.destinationStore_.selectedDestination.capabilities;
if (!okToPrint) {
return PrintPreview.PrintAttemptResult_.NOT_READY;
}
if (this.isPreviewGenerationInProgress_) {
return PrintPreview.PrintAttemptResult_.READY_WAITING_FOR_PREVIEW;
}
assert(this.printTicketStore_.isTicketValid(),
'Trying to print with invalid ticket');
if (this.uiState_ == PrintPreview.UiState_.OPENING_CLOUD_PRINT_DIALOG) {
this.nativeLayer_.startShowCloudPrintDialog(
this.printTicketStore_.pageRange.getPageNumberSet().size);
} else {
this.nativeLayer_.startPrint(
this.destinationStore_.selectedDestination,
this.printTicketStore_,
this.cloudPrintInterface_,
this.documentInfo_,
this.uiState_ == PrintPreview.UiState_.OPENING_PDF_PREVIEW);
}
return PrintPreview.PrintAttemptResult_.PRINTED;
},
/**
* Closes the print preview.
* @private
*/
close_: function() {
this.exitDocument();
this.uiState_ = PrintPreview.UiState_.CLOSING;
this.nativeLayer_.startCloseDialog();
},
/**
* Opens the native system print dialog after disabling all controls.
* @private
*/
openSystemPrintDialog_: function() {
setIsVisible($('system-dialog-throbber'), true);
this.setIsEnabled_(false);
this.uiState_ = PrintPreview.UiState_.OPENING_NATIVE_PRINT_DIALOG;
this.nativeLayer_.startShowSystemDialog();
},
/**
* Called when the native layer has initial settings to set. Sets the
* initial settings of the print preview and begins fetching print
* destinations.
* @param {Event} event Contains the initial print preview settings
* persisted through the session.
* @private
*/
onInitialSettingsSet_: function(event) {
assert(this.uiState_ == PrintPreview.UiState_.INITIALIZING,
'Updating initial settings when not in initializing state: ' +
this.uiState_);
this.uiState_ = PrintPreview.UiState_.READY;
var settings = event.initialSettings;
this.isInKioskAutoPrintMode_ = settings.isInKioskAutoPrintMode;
this.isInAppKioskMode_ = settings.isInAppKioskMode;
// The following components must be initialized in this order.
this.appState_.init(
settings.serializedAppStateStr,
settings.systemDefaultDestinationId);
this.documentInfo_.init(
settings.isDocumentModifiable,
settings.documentTitle,
settings.documentHasSelection);
this.printTicketStore_.init(
settings.thousandsDelimeter,
settings.decimalDelimeter,
settings.unitType,
settings.selectionOnly);
this.destinationStore_.init(settings.isInAppKioskMode);
this.appState_.setInitialized();
$('document-title').innerText = settings.documentTitle;
setIsVisible($('system-dialog-link'),
!settings.hidePrintWithSystemDialogLink &&
!settings.isInAppKioskMode);
},
/**
* Calls when the native layer enables Google Cloud Print integration.
* Fetches the user's cloud printers.
* @param {Event} event Contains the base URL of the Google Cloud Print
* service.
* @private
*/
onCloudPrintEnable_: function(event) {
this.cloudPrintInterface_ = new cloudprint.CloudPrintInterface(
event.baseCloudPrintUrl,
this.nativeLayer_,
this.userInfo_,
event.appKioskMode);
this.tracker.add(
this.cloudPrintInterface_,
cloudprint.CloudPrintInterface.EventType.SUBMIT_DONE,
this.onCloudPrintSubmitDone_.bind(this));
this.tracker.add(
this.cloudPrintInterface_,
cloudprint.CloudPrintInterface.EventType.SEARCH_FAILED,
this.onCloudPrintError_.bind(this));
this.tracker.add(
this.cloudPrintInterface_,
cloudprint.CloudPrintInterface.EventType.SUBMIT_FAILED,
this.onCloudPrintError_.bind(this));
this.tracker.add(
this.cloudPrintInterface_,
cloudprint.CloudPrintInterface.EventType.PRINTER_FAILED,
this.onCloudPrintError_.bind(this));
this.tracker.add(
this.cloudPrintInterface_,
cloudprint.CloudPrintInterface.EventType.
UPDATE_PRINTER_TOS_ACCEPTANCE_FAILED,
this.onCloudPrintError_.bind(this));
this.destinationStore_.setCloudPrintInterface(this.cloudPrintInterface_);
if (this.destinationSearch_.getIsVisible()) {
this.destinationStore_.startLoadCloudDestinations();
}
},
/**
* Called from the native layer when ready to print to Google Cloud Print.
* @param {Event} event Contains the body to send in the HTTP request.
* @private
*/
onPrintToCloud_: function(event) {
assert(this.uiState_ == PrintPreview.UiState_.PRINTING,
'Document ready to be sent to the cloud when not in printing ' +
'state: ' + this.uiState_);
assert(this.cloudPrintInterface_ != null,
'Google Cloud Print is not enabled');
this.cloudPrintInterface_.submit(
this.destinationStore_.selectedDestination,
this.printTicketStore_,
this.documentInfo_,
event.data);
},
/**
* Called from the native layer when the user cancels the save-to-pdf file
* selection dialog.
* @private
*/
onFileSelectionCancel_: function() {
assert(this.uiState_ == PrintPreview.UiState_.FILE_SELECTION,
'File selection cancelled when not in file-selection state: ' +
this.uiState_);
this.setIsEnabled_(true);
this.uiState_ = PrintPreview.UiState_.READY;
},
/**
* Called from the native layer when save-to-pdf file selection is complete.
* @private
*/
onFileSelectionComplete_: function() {
assert(this.uiState_ == PrintPreview.UiState_.FILE_SELECTION,
'File selection completed when not in file-selection state: ' +
this.uiState_);
this.previewArea_.showCustomMessage(
localStrings.getString('printingToPDFInProgress'));
this.uiState_ = PrintPreview.UiState_.PRINTING;
},
/**
* Called after successfully submitting a job to Google Cloud Print.
* @param {!Event} event Contains the ID of the submitted print job.
* @private
*/
onCloudPrintSubmitDone_: function(event) {
assert(this.uiState_ == PrintPreview.UiState_.PRINTING,
'Submited job to Google Cloud Print but not in printing state ' +
this.uiState_);
if (this.destinationStore_.selectedDestination.id ==
print_preview.Destination.GooglePromotedId.FEDEX) {
this.nativeLayer_.startForceOpenNewTab(
'https://www.google.com/cloudprint/fedexcode.html?jobid=' +
event.jobId);
}
this.close_();
},
/**
* Called when there was an error communicating with Google Cloud print.
* Displays an error message in the print header.
* @param {!Event} event Contains the error message.
* @private
*/
onCloudPrintError_: function(event) {
if (event.status == 403) {
if (!this.isInAppKioskMode_) {
this.destinationSearch_.showCloudPrintPromo();
}
} else if (event.status == 0) {
return; // Ignore, the system does not have internet connectivity.
} else {
this.printHeader_.setErrorMessage(event.message);
}
if (event.status == 200) {
console.error('Google Cloud Print Error: (' + event.errorCode + ') ' +
event.message);
} else {
console.error('Google Cloud Print Error: HTTP status ' + event.status);
}
},
/**
* Called when the preview area's preview generation is in progress.
* @private
*/
onPreviewGenerationInProgress_: function() {
this.isPreviewGenerationInProgress_ = true;
},
/**
* Called when the preview area's preview generation is complete.
* @private
*/
onPreviewGenerationDone_: function() {
this.isPreviewGenerationInProgress_ = false;
this.printHeader_.isPrintButtonEnabled = true;
this.nativeLayer_.previewReadyForTest();
this.printIfReady_();
},
/**
* Called when the preview area's preview failed to load.
* @private
*/
onPreviewGenerationFail_: function() {
this.isPreviewGenerationInProgress_ = false;
this.printHeader_.isPrintButtonEnabled = false;
if (this.uiState_ == PrintPreview.UiState_.PRINTING) {
this.nativeLayer_.startCancelPendingPrint();
} else if (this.uiState_ ==
PrintPreview.UiState_.OPENING_CLOUD_PRINT_DIALOG) {
this.uiState_ = PrintPreview.UiState_.READY;
}
},
/**
* Called when the 'Open pdf in preview' link is clicked. Launches the pdf
* preview app.
* @private
*/
onOpenPdfInPreviewLinkClick_: function() {
assert(this.uiState_ == PrintPreview.UiState_.READY,
'Trying to open pdf in preview when not in ready state: ' +
this.uiState_);
setIsVisible($('open-preview-app-throbber'), true);
this.previewArea_.showCustomMessage(
localStrings.getString('openingPDFInPreview'));
this.printDocumentOrOpenPdfPreview_(true /*isPdfPreview*/);
},
/**
* Called when the print header's print button is clicked. Prints the
* document.
* @private
*/
onPrintButtonClick_: function() {
assert(this.uiState_ == PrintPreview.UiState_.READY,
'Trying to print when not in ready state: ' + this.uiState_);
this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);
},
/**
* Called when the print header's cancel button is clicked. Closes the
* print dialog.
* @private
*/
onCancelButtonClick_: function() {
this.close_();
},
/**
* Called when the register promo for Cloud Print is clicked.
* @private
*/
onCloudPrintRegisterPromoClick_: function(e) {
var devicesUrl = 'chrome://devices/register?id=' + e.destination.id;
this.nativeLayer_.startForceOpenNewTab(devicesUrl);
this.destinationStore_.waitForRegister(e.destination.id);
},
/**
* Consume escape key presses and ctrl + shift + p. Delegate everything else
* to the preview area.
* @param {KeyboardEvent} e The keyboard event.
* @private
*/
onKeyDown_: function(e) {
// Escape key closes the dialog.
if (e.keyCode == 27 && !e.shiftKey && !e.ctrlKey && !e.altKey &&
!e.metaKey) {
<if expr="toolkit_views">
// On the toolkit_views environment, ESC key is handled by C++-side
// instead of JS-side.
return;
</if>
<if expr="not toolkit_views">
this.close_();
</if>
e.preventDefault();
return;
}
// Ctrl + Shift + p / Mac equivalent.
if (e.keyCode == 80) {
if ((cr.isMac && e.metaKey && e.altKey && !e.shiftKey && !e.ctrlKey) ||
(!cr.isMac && e.shiftKey && e.ctrlKey && !e.altKey && !e.metaKey)) {
this.openSystemPrintDialog_();
e.preventDefault();
return;
}
}
if (e.keyCode == 13 /*enter*/ &&
!document.querySelector('.overlay:not([hidden])') &&
this.destinationStore_.selectedDestination &&
this.printTicketStore_.isTicketValid()) {
assert(this.uiState_ == PrintPreview.UiState_.READY,
'Trying to print when not in ready state: ' + this.uiState_);
var activeElementTag = document.activeElement ?
document.activeElement.tagName.toUpperCase() : '';
if (activeElementTag != 'BUTTON' && activeElementTag != 'SELECT') {
this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);
e.preventDefault();
}
return;
}
// Pass certain directional keyboard events to the PDF viewer.
this.previewArea_.handleDirectionalKeyEvent(e);
},
/**
* Called when native layer receives invalid settings for a print request.
* @private
*/
onSettingsInvalid_: function() {
this.uiState_ = PrintPreview.UiState_.ERROR;
console.error('Invalid settings error reported from native layer');
this.previewArea_.showCustomMessage(
localStrings.getString('invalidPrinterSettings'));
},
/**
* Called when the destination settings' change button is activated.
* Displays the destination search component.
* @private
*/
onDestinationChangeButtonActivate_: function() {
this.destinationSearch_.setIsVisible(true);
this.destinationStore_.startLoadCloudDestinations();
this.destinationStore_.startLoadLocalDestinations();
this.destinationStore_.startLoadPrivetDestinations();
},
/**
* Called when the destination settings' change button is activated.
* Displays the destination search component.
* @private
*/
onAdvancedOptionsButtonActivated_: function() {
this.advancedSettings_.showForDestination(
this.destinationStore_.selectedDestination);
},
/**
* Called when the destination search dispatches manage cloud destinations
* event. Calls corresponding native layer method.
* @private
*/
onManageCloudDestinationsActivated_: function() {
this.nativeLayer_.startManageCloudDestinations();
},
/**
* Called when the destination search dispatches manage local destinations
* event. Calls corresponding native layer method.
* @private
*/
onManageLocalDestinationsActivated_: function() {
this.nativeLayer_.startManageLocalDestinations();
},
/**
* Called when the user wants to sign in to Google Cloud Print. Calls the
* corresponding native layer event.
* @param {boolean} addAccount Whether to open an 'add a new account' or
* default sign in page.
* @private
*/
onCloudPrintSignInActivated_: function(addAccount) {
this.nativeLayer_.startCloudPrintSignIn(addAccount);
},
/**
* Called when the native layer dispatches a DISABLE_SCALING event. Resets
* fit-to-page selection and updates document info.
* @private
*/
onDisableScaling_: function() {
this.printTicketStore_.fitToPage.updateValue(null);
this.documentInfo_.updateIsScalingDisabled(true);
},
/**
* 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 print preview settings need to be changed for testing.
* @param {Event} event Event object that contains the option that is to
* be changed and what to set that option.
* @private
*/
onManipulateSettingsForTest_: function(event) {
if ('selectSaveAsPdfDestination' in event.settings) {
this.saveAsPdfForTest_(); // No parameters.
} else if ('layoutSettings' in event.settings) {
this.setLayoutSettingsForTest_(event.settings.layoutSettings.portrait);
} else if ('pageRange' in event.settings) {
this.setPageRangeForTest_(event.settings.pageRange);
} else if ('headersAndFooters' in event.settings) {
this.setHeadersAndFootersForTest_(event.settings.headersAndFooters);
} else if ('backgroundColorsAndImages' in event.settings) {
this.setBackgroundColorsAndImagesForTest_(
event.settings.backgroundColorsAndImages);
} else if ('margins' in event.settings) {
this.setMarginsForTest_(event.settings.margins);
}
},
/**
* Called by onManipulateSettingsForTest_(). Sets the print destination
* as a pdf.
* @private
*/
saveAsPdfForTest_: function() {
if (this.destinationStore_.selectedDestination &&
print_preview.Destination.GooglePromotedId.SAVE_AS_PDF ==
this.destinationStore_.selectedDestination.id) {
this.nativeLayer_.previewReadyForTest();
return;
}
var destinations = this.destinationStore_.destinations();
var pdfDestination = null;
for (var i = 0; i < destinations.length; i++) {
if (destinations[i].id ==
print_preview.Destination.GooglePromotedId.SAVE_AS_PDF) {
pdfDestination = destinations[i];
break;
}
}
if (pdfDestination)
this.destinationStore_.selectDestination(pdfDestination);
else
this.nativeLayer_.previewFailedForTest();
},
/**
* Called by onManipulateSettingsForTest_(). Sets the layout settings to
* either portrait or landscape.
* @param {boolean} portrait Whether to use portrait page layout;
* if false: landscape.
* @private
*/
setLayoutSettingsForTest_: function(portrait) {
var element = document.querySelector(portrait ?
'.layout-settings-portrait-radio' :
'.layout-settings-landscape-radio');
if (element.checked)
this.nativeLayer_.previewReadyForTest();
else
element.click();
},
/**
* Called by onManipulateSettingsForTest_(). Sets the page range for
* for the print preview settings.
* @param {string} pageRange Sets the page range to the desired value(s).
* Ex: "1-5,9" means pages 1 through 5 and page 9 will be printed.
* @private
*/
setPageRangeForTest_: function(pageRange) {
var textbox = document.querySelector('.page-settings-custom-input');
if (textbox.value == pageRange) {
this.nativeLayer_.previewReadyForTest();
} else {
textbox.value = pageRange;
document.querySelector('.page-settings-custom-radio').click();
}
},
/**
* Called by onManipulateSettings_(). Checks or unchecks the headers and
* footers option on print preview.
* @param {boolean} headersAndFooters Whether the "Headers and Footers"
* checkbox should be checked.
* @private
*/
setHeadersAndFootersForTest_: function(headersAndFooters) {
var checkbox = document.querySelector('.header-footer-checkbox');
if (headersAndFooters == checkbox.checked)
this.nativeLayer_.previewReadyForTest();
else
checkbox.click();
},
/**
* Called by onManipulateSettings_(). Checks or unchecks the background
* colors and images option on print preview.
* @param {boolean} backgroundColorsAndImages If true, the checkbox should
* be checked. Otherwise it should be unchecked.
* @private
*/
setBackgroundColorsAndImagesForTest_: function(backgroundColorsAndImages) {
var checkbox = document.querySelector('.css-background-checkbox');
if (backgroundColorsAndImages == checkbox.checked)
this.nativeLayer_.previewReadyForTest();
else
checkbox.click();
},
/**
* Called by onManipulateSettings_(). Sets the margin settings
* that are desired. Custom margin settings aren't currently supported.
* @param {number} margins The desired margins combobox index. Must be
* a valid index or else the test fails.
* @private
*/
setMarginsForTest_: function(margins) {
var combobox = document.querySelector('.margin-settings-select');
if (margins == combobox.selectedIndex) {
this.nativeLayer_.previewReadyForTest();
} else if (margins >= 0 && margins < combobox.length) {
combobox.selectedIndex = margins;
this.marginSettings_.onSelectChange_();
} else {
this.nativeLayer_.previewFailedForTest();
}
},
/**
* Called when the open-cloud-print-dialog link is clicked. Opens the Google
* Cloud Print web dialog.
* @private
*/
onCloudPrintDialogLinkClick_: function() {
assert(this.uiState_ == PrintPreview.UiState_.READY,
'Opening Google Cloud Print dialog when not in ready state: ' +
this.uiState_);
setIsVisible($('cloud-print-dialog-throbber'), true);
this.setIsEnabled_(false);
this.uiState_ = PrintPreview.UiState_.OPENING_CLOUD_PRINT_DIALOG;
this.printIfReady_();
},
/**
* Called when a print destination is selected. Shows/hides the "Print with
* Cloud Print" link in the navbar.
* @private
*/
onDestinationSelect_: function() {
var selectedDest = this.destinationStore_.selectedDestination;
setIsVisible(
$('cloud-print-dialog-link'),
selectedDest && !cr.isChromeOS && !selectedDest.isLocal);
if (selectedDest && this.isInKioskAutoPrintMode_) {
this.onPrintButtonClick_();
}
},
/**
* Called when the destination store loads a group of destinations. Shows
* a promo on Chrome OS if the user has no print destinations promoting
* Google Cloud Print.
* @private
*/
onDestinationSearchDone_: function() {
var isPromoVisible = cr.isChromeOS &&
this.cloudPrintInterface_ &&
this.userInfo_.activeUser &&
!this.appState_.isGcpPromoDismissed &&
!this.destinationStore_.isLocalDestinationsSearchInProgress &&
!this.destinationStore_.isCloudDestinationsSearchInProgress &&
this.destinationStore_.hasOnlyDefaultCloudDestinations();
setIsVisible(this.getChildElement('#no-destinations-promo'),
isPromoVisible);
if (isPromoVisible) {
new print_preview.GcpPromoMetricsContext().record(
print_preview.Metrics.GcpPromoBucket.PROMO_SHOWN);
}
},
/**
* Called when the close button on the no-destinations-promotion is clicked.
* Hides the promotion.
* @private
*/
onNoDestinationsPromoClose_: function() {
new print_preview.GcpPromoMetricsContext().record(
print_preview.Metrics.GcpPromoBucket.PROMO_CLOSED);
setIsVisible(this.getChildElement('#no-destinations-promo'), false);
this.appState_.persistIsGcpPromoDismissed(true);
},
/**
* Called when the no-destinations promotion link is clicked. Opens the
* Google Cloud Print management page and closes the print preview.
* @private
*/
onNoDestinationsPromoClick_: function() {
new print_preview.GcpPromoMetricsContext().record(
print_preview.Metrics.GcpPromoBucket.PROMO_CLICKED);
this.appState_.persistIsGcpPromoDismissed(true);
window.open(this.cloudPrintInterface_.baseUrl + '?user=' +
this.userInfo_.activeUser + '#printers');
this.close_();
}
};
// Export
return {
PrintPreview: PrintPreview
};
});
// Pull in all other scripts in a single shot.
<include src="common/overlay.js"/>
<include src="common/search_box.js"/>
<include src="data/page_number_set.js"/>
<include src="data/destination.js"/>
<include src="data/local_parsers.js"/>
<include src="data/cloud_parsers.js"/>
<include src="data/destination_store.js"/>
<include src="data/margins.js"/>
<include src="data/document_info.js"/>
<include src="data/printable_area.js"/>
<include src="data/measurement_system.js"/>
<include src="data/print_ticket_store.js"/>
<include src="data/coordinate2d.js"/>
<include src="data/size.js"/>
<include src="data/capabilities_holder.js"/>
<include src="data/user_info.js"/>
<include src="data/app_state.js"/>
<include src="data/ticket_items/ticket_item.js"/>
<include src="data/ticket_items/custom_margins.js"/>
<include src="data/ticket_items/collate.js"/>
<include src="data/ticket_items/color.js"/>
<include src="data/ticket_items/copies.js"/>
<include src="data/ticket_items/duplex.js"/>
<include src="data/ticket_items/header_footer.js"/>
<include src="data/ticket_items/media_size.js"/>
<include src="data/ticket_items/landscape.js"/>
<include src="data/ticket_items/margins_type.js"/>
<include src="data/ticket_items/page_range.js"/>
<include src="data/ticket_items/fit_to_page.js"/>
<include src="data/ticket_items/css_background.js"/>
<include src="data/ticket_items/selection_only.js"/>
<include src="native_layer.js"/>
<include src="print_preview_animations.js"/>
<include src="cloud_print_interface.js"/>
<include src="print_preview_utils.js"/>
<include src="print_header.js"/>
<include src="metrics.js"/>
<include src="settings/page_settings.js"/>
<include src="settings/copies_settings.js"/>
<include src="settings/media_size_settings.js"/>
<include src="settings/layout_settings.js"/>
<include src="settings/color_settings.js"/>
<include src="settings/margin_settings.js"/>
<include src="settings/destination_settings.js"/>
<include src="settings/other_options_settings.js"/>
<include src="settings/advanced_options_settings.js"/>
<include src="settings/advanced_settings/advanced_settings.js"/>
<include src="settings/advanced_settings/advanced_settings_item.js"/>
<include src="previewarea/margin_control.js"/>
<include src="previewarea/margin_control_container.js"/>
<include src="../pdf/pdf_scripting_api.js" />
<include src="previewarea/preview_area.js"/>
<include src="preview_generator.js"/>
<include src="search/destination_list.js"/>
<include src="search/cloud_destination_list.js"/>
<include src="search/recent_destination_list.js"/>
<include src="search/destination_list_item.js"/>
<include src="search/destination_search.js"/>
<include src="search/fedex_tos.js"/>
window.addEventListener('DOMContentLoaded', function() {
printPreview = new print_preview.PrintPreview();
printPreview.initialize();
});