Best Python code snippet using molotov_python
print_preview.js
Source:print_preview.js  
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4// TODO(rltoscano): Move data/* into print_preview.data namespace5<include src="component.js">6<include src="print_preview_focus_manager.js">7cr.define('print_preview', function() {8  'use strict';9  /**10   * Container class for Chromium's print preview.11   * @constructor12   * @extends {print_preview.Component}13   */14  function PrintPreview() {15    print_preview.Component.call(this);16    /**17     * Used to communicate with Chromium's print system.18     * @type {!print_preview.NativeLayer}19     * @private20     */21    this.nativeLayer_ = new print_preview.NativeLayer();22    /**23     * Event target that contains information about the logged in user.24     * @type {!print_preview.UserInfo}25     * @private26     */27    this.userInfo_ = new print_preview.UserInfo();28    /**29     * Application state.30     * @type {!print_preview.AppState}31     * @private32     */33    this.appState_ = new print_preview.AppState();34    /**35     * Data model that holds information about the document to print.36     * @type {!print_preview.DocumentInfo}37     * @private38     */39    this.documentInfo_ = new print_preview.DocumentInfo();40    /**41     * Data store which holds print destinations.42     * @type {!print_preview.DestinationStore}43     * @private44     */45    this.destinationStore_ = new print_preview.DestinationStore(46        this.nativeLayer_, this.userInfo_, this.appState_);47    /**48     * Data store which holds printer sharing invitations.49     * @type {!print_preview.InvitationStore}50     * @private51     */52    this.invitationStore_ = new print_preview.InvitationStore(this.userInfo_);53    /**54     * Storage of the print ticket used to create the print job.55     * @type {!print_preview.PrintTicketStore}56     * @private57     */58    this.printTicketStore_ = new print_preview.PrintTicketStore(59        this.destinationStore_, this.appState_, this.documentInfo_);60    /**61     * Holds the print and cancel buttons and renders some document statistics.62     * @type {!print_preview.PrintHeader}63     * @private64     */65    this.printHeader_ = new print_preview.PrintHeader(66        this.printTicketStore_, this.destinationStore_);67    this.addChild(this.printHeader_);68    /**69     * Component used to search for print destinations.70     * @type {!print_preview.DestinationSearch}71     * @private72     */73    this.destinationSearch_ = new print_preview.DestinationSearch(74        this.destinationStore_, this.invitationStore_, this.userInfo_);75    this.addChild(this.destinationSearch_);76    /**77     * Component that renders the print destination.78     * @type {!print_preview.DestinationSettings}79     * @private80     */81    this.destinationSettings_ = new print_preview.DestinationSettings(82        this.destinationStore_);83    this.addChild(this.destinationSettings_);84    /**85     * Component that renders UI for entering in page range.86     * @type {!print_preview.PageSettings}87     * @private88     */89    this.pageSettings_ = new print_preview.PageSettings(90        this.printTicketStore_.pageRange);91    this.addChild(this.pageSettings_);92    /**93     * Component that renders the copies settings.94     * @type {!print_preview.CopiesSettings}95     * @private96     */97    this.copiesSettings_ = new print_preview.CopiesSettings(98        this.printTicketStore_.copies, this.printTicketStore_.collate);99    this.addChild(this.copiesSettings_);100    /**101     * Component that renders the media size settings.102     * @type {!print_preview.MediaSizeSettings}103     * @private104     */105    this.mediaSizeSettings_ =106        new print_preview.MediaSizeSettings(this.printTicketStore_.mediaSize);107    this.addChild(this.mediaSizeSettings_);108    /**109     * Component that renders the layout settings.110     * @type {!print_preview.LayoutSettings}111     * @private112     */113    this.layoutSettings_ =114        new print_preview.LayoutSettings(this.printTicketStore_.landscape);115    this.addChild(this.layoutSettings_);116    /**117     * Component that renders the color options.118     * @type {!print_preview.ColorSettings}119     * @private120     */121    this.colorSettings_ =122        new print_preview.ColorSettings(this.printTicketStore_.color);123    this.addChild(this.colorSettings_);124    /**125     * Component that renders a select box for choosing margin settings.126     * @type {!print_preview.MarginSettings}127     * @private128     */129    this.marginSettings_ =130        new print_preview.MarginSettings(this.printTicketStore_.marginsType);131    this.addChild(this.marginSettings_);132    /**133     * Component that renders the DPI settings.134     * @type {!print_preview.DpiSettings}135     * @private136     */137    this.dpiSettings_ =138        new print_preview.DpiSettings(this.printTicketStore_.dpi);139    this.addChild(this.dpiSettings_);140    /**141     * Component that renders miscellaneous print options.142     * @type {!print_preview.OtherOptionsSettings}143     * @private144     */145    this.otherOptionsSettings_ = new print_preview.OtherOptionsSettings(146        this.printTicketStore_.duplex,147        this.printTicketStore_.fitToPage,148        this.printTicketStore_.cssBackground,149        this.printTicketStore_.selectionOnly,150        this.printTicketStore_.headerFooter);151    this.addChild(this.otherOptionsSettings_);152    /**153     * Component that renders the advanced options button.154     * @type {!print_preview.AdvancedOptionsSettings}155     * @private156     */157    this.advancedOptionsSettings_ = new print_preview.AdvancedOptionsSettings(158        this.printTicketStore_.vendorItems, this.destinationStore_);159    this.addChild(this.advancedOptionsSettings_);160    /**161     * Component used to search for print destinations.162     * @type {!print_preview.AdvancedSettings}163     * @private164     */165    this.advancedSettings_ = new print_preview.AdvancedSettings(166        this.printTicketStore_);167    this.addChild(this.advancedSettings_);168    var settingsSections = [169        this.destinationSettings_,170        this.pageSettings_,171        this.copiesSettings_,172        this.mediaSizeSettings_,173        this.layoutSettings_,174        this.marginSettings_,175        this.colorSettings_,176        this.dpiSettings_,177        this.otherOptionsSettings_,178        this.advancedOptionsSettings_];179    /**180     * Component representing more/less settings button.181     * @type {!print_preview.MoreSettings}182     * @private183     */184    this.moreSettings_ = new print_preview.MoreSettings(185        this.destinationStore_, settingsSections);186    this.addChild(this.moreSettings_);187    /**188     * Area of the UI that holds the print preview.189     * @type {!print_preview.PreviewArea}190     * @private191     */192    this.previewArea_ = new print_preview.PreviewArea(this.destinationStore_,193                                                      this.printTicketStore_,194                                                      this.nativeLayer_,195                                                      this.documentInfo_);196    this.addChild(this.previewArea_);197    /**198     * Interface to the Google Cloud Print API. Null if Google Cloud Print199     * integration is disabled.200     * @type {cloudprint.CloudPrintInterface}201     * @private202     */203    this.cloudPrintInterface_ = null;204    /**205     * Whether in kiosk mode where print preview can print automatically without206     * user intervention. See http://crbug.com/31395. Print will start when207     * both the print ticket has been initialized, and an initial printer has208     * been selected.209     * @type {boolean}210     * @private211     */212    this.isInKioskAutoPrintMode_ = false;213    /**214     * Whether Print Preview is in App Kiosk mode, basically, use only printers215     * available for the device.216     * @type {boolean}217     * @private218     */219    this.isInAppKioskMode_ = false;220    /**221     * Whether Print with System Dialog link should be hidden. Overrides the222     * default rules for System dialog link visibility.223     * @type {boolean}224     * @private225     */226    this.hideSystemDialogLink_ = true;227    /**228     * State of the print preview UI.229     * @type {print_preview.PrintPreview.UiState_}230     * @private231     */232    this.uiState_ = PrintPreview.UiState_.INITIALIZING;233    /**234     * Whether document preview generation is in progress.235     * @type {boolean}236     * @private237     */238    this.isPreviewGenerationInProgress_ = true;239    /**240     * Whether to show system dialog before next printing.241     * @type {boolean}242     * @private243     */244    this.showSystemDialogBeforeNextPrint_ = false;245  };246  /**247   * States of the print preview.248   * @enum {string}249   * @private250   */251  PrintPreview.UiState_ = {252    INITIALIZING: 'initializing',253    READY: 'ready',254    OPENING_PDF_PREVIEW: 'opening-pdf-preview',255    OPENING_NATIVE_PRINT_DIALOG: 'opening-native-print-dialog',256    PRINTING: 'printing',257    FILE_SELECTION: 'file-selection',258    CLOSING: 'closing',259    ERROR: 'error'260  };261  /**262   * What can happen when print preview tries to print.263   * @enum {string}264   * @private265   */266  PrintPreview.PrintAttemptResult_ = {267    NOT_READY: 'not-ready',268    PRINTED: 'printed',269    READY_WAITING_FOR_PREVIEW: 'ready-waiting-for-preview'270  };271  PrintPreview.prototype = {272    __proto__: print_preview.Component.prototype,273    /** Sets up the page and print preview by getting the printer list. */274    initialize: function() {275      this.decorate($('print-preview'));276      if (!this.previewArea_.hasCompatiblePlugin) {277        this.setIsEnabled_(false);278      }279      this.nativeLayer_.startGetInitialSettings();280      print_preview.PrintPreviewFocusManager.getInstance().initialize();281      cr.ui.FocusOutlineManager.forDocument(document);282    },283    /** @override */284    enterDocument: function() {285      // Native layer events.286      this.tracker.add(287          this.nativeLayer_,288          print_preview.NativeLayer.EventType.INITIAL_SETTINGS_SET,289          this.onInitialSettingsSet_.bind(this));290      this.tracker.add(291          this.nativeLayer_,292          print_preview.NativeLayer.EventType.CLOUD_PRINT_ENABLE,293          this.onCloudPrintEnable_.bind(this));294      this.tracker.add(295          this.nativeLayer_,296          print_preview.NativeLayer.EventType.PRINT_TO_CLOUD,297          this.onPrintToCloud_.bind(this));298      this.tracker.add(299          this.nativeLayer_,300          print_preview.NativeLayer.EventType.FILE_SELECTION_CANCEL,301          this.onFileSelectionCancel_.bind(this));302      this.tracker.add(303          this.nativeLayer_,304          print_preview.NativeLayer.EventType.FILE_SELECTION_COMPLETE,305          this.onFileSelectionComplete_.bind(this));306      this.tracker.add(307          this.nativeLayer_,308          print_preview.NativeLayer.EventType.SETTINGS_INVALID,309          this.onSettingsInvalid_.bind(this));310      this.tracker.add(311          this.nativeLayer_,312          print_preview.NativeLayer.EventType.PRINT_PRESET_OPTIONS,313          this.onPrintPresetOptionsFromDocument_.bind(this));314      this.tracker.add(315          this.nativeLayer_,316          print_preview.NativeLayer.EventType.PRIVET_PRINT_FAILED,317          this.onPrivetPrintFailed_.bind(this));318      this.tracker.add(319          this.nativeLayer_,320          print_preview.NativeLayer.EventType.MANIPULATE_SETTINGS_FOR_TEST,321          this.onManipulateSettingsForTest_.bind(this));322      if ($('system-dialog-link')) {323        this.tracker.add(324            $('system-dialog-link'),325            'click',326            this.openSystemPrintDialog_.bind(this));327      }328      if ($('open-pdf-in-preview-link')) {329        this.tracker.add(330            $('open-pdf-in-preview-link'),331            'click',332            this.onOpenPdfInPreviewLinkClick_.bind(this));333      }334      this.tracker.add(335          this.previewArea_,336          print_preview.PreviewArea.EventType.PREVIEW_GENERATION_IN_PROGRESS,337          this.onPreviewGenerationInProgress_.bind(this));338      this.tracker.add(339          this.previewArea_,340          print_preview.PreviewArea.EventType.PREVIEW_GENERATION_DONE,341          this.onPreviewGenerationDone_.bind(this));342      this.tracker.add(343          this.previewArea_,344          print_preview.PreviewArea.EventType.PREVIEW_GENERATION_FAIL,345          this.onPreviewGenerationFail_.bind(this));346      this.tracker.add(347          this.previewArea_,348          print_preview.PreviewArea.EventType.OPEN_SYSTEM_DIALOG_CLICK,349          this.openSystemPrintDialog_.bind(this));350      this.tracker.add(351          this.destinationStore_,352          print_preview.DestinationStore.EventType.353              SELECTED_DESTINATION_CAPABILITIES_READY,354          this.printIfReady_.bind(this));355      this.tracker.add(356          this.destinationStore_,357          print_preview.DestinationStore.EventType.DESTINATION_SELECT,358          this.onDestinationSelect_.bind(this));359      this.tracker.add(360          this.destinationStore_,361          print_preview.DestinationStore.EventType.DESTINATION_SEARCH_DONE,362          this.onDestinationSearchDone_.bind(this));363      this.tracker.add(364          this.printHeader_,365          print_preview.PrintHeader.EventType.PRINT_BUTTON_CLICK,366          this.onPrintButtonClick_.bind(this));367      this.tracker.add(368          this.printHeader_,369          print_preview.PrintHeader.EventType.CANCEL_BUTTON_CLICK,370          this.onCancelButtonClick_.bind(this));371      this.tracker.add(window, 'keydown', this.onKeyDown_.bind(this));372      this.previewArea_.setPluginKeyEventCallback(this.onKeyDown_.bind(this));373      this.tracker.add(374          this.destinationSettings_,375          print_preview.DestinationSettings.EventType.CHANGE_BUTTON_ACTIVATE,376          this.onDestinationChangeButtonActivate_.bind(this));377      this.tracker.add(378          this.destinationSearch_,379          print_preview.DestinationSearch.EventType.MANAGE_CLOUD_DESTINATIONS,380          this.onManageCloudDestinationsActivated_.bind(this));381      this.tracker.add(382          this.destinationSearch_,383          print_preview.DestinationSearch.EventType.MANAGE_LOCAL_DESTINATIONS,384          this.onManageLocalDestinationsActivated_.bind(this));385      this.tracker.add(386          this.destinationSearch_,387          print_preview.DestinationSearch.EventType.ADD_ACCOUNT,388          this.onCloudPrintSignInActivated_.bind(this, true /*addAccount*/));389      this.tracker.add(390          this.destinationSearch_,391          print_preview.DestinationSearch.EventType.SIGN_IN,392          this.onCloudPrintSignInActivated_.bind(this, false /*addAccount*/));393      this.tracker.add(394          this.destinationSearch_,395          print_preview.DestinationListItem.EventType.REGISTER_PROMO_CLICKED,396          this.onCloudPrintRegisterPromoClick_.bind(this));397      this.tracker.add(398          this.advancedOptionsSettings_,399          print_preview.AdvancedOptionsSettings.EventType.BUTTON_ACTIVATED,400          this.onAdvancedOptionsButtonActivated_.bind(this));401      // TODO(rltoscano): Move no-destinations-promo into its own component402      // instead being part of PrintPreview.403      this.tracker.add(404          this.getChildElement('#no-destinations-promo .close-button'),405          'click',406          this.onNoDestinationsPromoClose_.bind(this));407      this.tracker.add(408          this.getChildElement('#no-destinations-promo .not-now-button'),409          'click',410          this.onNoDestinationsPromoClose_.bind(this));411      this.tracker.add(412          this.getChildElement('#no-destinations-promo .add-printer-button'),413          'click',414          this.onNoDestinationsPromoClick_.bind(this));415    },416    /** @override */417    decorateInternal: function() {418      this.printHeader_.decorate($('print-header'));419      this.destinationSearch_.decorate($('destination-search'));420      this.destinationSettings_.decorate($('destination-settings'));421      this.pageSettings_.decorate($('page-settings'));422      this.copiesSettings_.decorate($('copies-settings'));423      this.mediaSizeSettings_.decorate($('media-size-settings'));424      this.layoutSettings_.decorate($('layout-settings'));425      this.colorSettings_.decorate($('color-settings'));426      this.marginSettings_.decorate($('margin-settings'));427      this.dpiSettings_.decorate($('dpi-settings'));428      this.otherOptionsSettings_.decorate($('other-options-settings'));429      this.advancedOptionsSettings_.decorate($('advanced-options-settings'));430      this.advancedSettings_.decorate($('advanced-settings'));431      this.moreSettings_.decorate($('more-settings'));432      this.previewArea_.decorate($('preview-area'));433    },434    /**435     * Sets whether the controls in the print preview are enabled.436     * @param {boolean} isEnabled Whether the controls in the print preview are437     *     enabled.438     * @private439     */440    setIsEnabled_: function(isEnabled) {441      if ($('system-dialog-link'))442        $('system-dialog-link').classList.toggle('disabled', !isEnabled);443      if ($('open-pdf-in-preview-link'))444        $('open-pdf-in-preview-link').classList.toggle('disabled', !isEnabled);445      this.printHeader_.isEnabled = isEnabled;446      this.destinationSettings_.isEnabled = isEnabled;447      this.pageSettings_.isEnabled = isEnabled;448      this.copiesSettings_.isEnabled = isEnabled;449      this.mediaSizeSettings_.isEnabled = isEnabled;450      this.layoutSettings_.isEnabled = isEnabled;451      this.colorSettings_.isEnabled = isEnabled;452      this.marginSettings_.isEnabled = isEnabled;453      this.dpiSettings_.isEnabled = isEnabled;454      this.otherOptionsSettings_.isEnabled = isEnabled;455      this.advancedOptionsSettings_.isEnabled = isEnabled;456    },457    /**458     * Prints the document or launches a pdf preview on the local system.459     * @param {boolean} isPdfPreview Whether to launch the pdf preview.460     * @private461     */462    printDocumentOrOpenPdfPreview_: function(isPdfPreview) {463      assert(this.uiState_ == PrintPreview.UiState_.READY,464             'Print document request received when not in ready state: ' +465                 this.uiState_);466      if (isPdfPreview) {467        this.uiState_ = PrintPreview.UiState_.OPENING_PDF_PREVIEW;468      } else if (this.destinationStore_.selectedDestination.id ==469          print_preview.Destination.GooglePromotedId.SAVE_AS_PDF) {470        this.uiState_ = PrintPreview.UiState_.FILE_SELECTION;471      } else {472        this.uiState_ = PrintPreview.UiState_.PRINTING;473      }474      this.setIsEnabled_(false);475      this.printHeader_.isCancelButtonEnabled = true;476      var printAttemptResult = this.printIfReady_();477      if (printAttemptResult == PrintPreview.PrintAttemptResult_.PRINTED ||478          printAttemptResult ==479              PrintPreview.PrintAttemptResult_.READY_WAITING_FOR_PREVIEW) {480        if ((this.destinationStore_.selectedDestination.isLocal &&481             !this.destinationStore_.selectedDestination.isPrivet &&482             !this.destinationStore_.selectedDestination.isExtension &&483             this.destinationStore_.selectedDestination.id !=484                 print_preview.Destination.GooglePromotedId.SAVE_AS_PDF) ||485             this.uiState_ == PrintPreview.UiState_.OPENING_PDF_PREVIEW) {486          // Hide the dialog for now. The actual print command will be issued487          // when the preview generation is done.488          this.nativeLayer_.startHideDialog();489        }490      }491    },492    /**493     * Attempts to print if needed and if ready.494     * @return {PrintPreview.PrintAttemptResult_} Attempt result.495     * @private496     */497    printIfReady_: function() {498      var okToPrint =499          (this.uiState_ == PrintPreview.UiState_.PRINTING ||500           this.uiState_ == PrintPreview.UiState_.OPENING_PDF_PREVIEW ||501           this.uiState_ == PrintPreview.UiState_.FILE_SELECTION ||502           this.isInKioskAutoPrintMode_) &&503          this.destinationStore_.selectedDestination &&504          this.destinationStore_.selectedDestination.capabilities;505      if (!okToPrint) {506        return PrintPreview.PrintAttemptResult_.NOT_READY;507      }508      if (this.isPreviewGenerationInProgress_) {509        return PrintPreview.PrintAttemptResult_.READY_WAITING_FOR_PREVIEW;510      }511      assert(this.printTicketStore_.isTicketValid(),512          'Trying to print with invalid ticket');513      if (getIsVisible(this.moreSettings_.getElement())) {514        new print_preview.PrintSettingsUiMetricsContext().record(515            this.moreSettings_.isExpanded ?516                print_preview.Metrics.PrintSettingsUiBucket.517                    PRINT_WITH_SETTINGS_EXPANDED :518                print_preview.Metrics.PrintSettingsUiBucket.519                    PRINT_WITH_SETTINGS_COLLAPSED);520      }521      this.nativeLayer_.startPrint(522          this.destinationStore_.selectedDestination,523          this.printTicketStore_,524          this.cloudPrintInterface_,525          this.documentInfo_,526          this.uiState_ == PrintPreview.UiState_.OPENING_PDF_PREVIEW,527          this.showSystemDialogBeforeNextPrint_);528      this.showSystemDialogBeforeNextPrint_ = false;529      return PrintPreview.PrintAttemptResult_.PRINTED;530    },531    /**532     * Closes the print preview.533     * @private534     */535    close_: function() {536      this.exitDocument();537      this.uiState_ = PrintPreview.UiState_.CLOSING;538      this.nativeLayer_.startCloseDialog();539    },540    /**541     * Opens the native system print dialog after disabling all controls.542     * @private543     */544    openSystemPrintDialog_: function() {545      if (!this.shouldShowSystemDialogLink_())546        return;547      if ($('system-dialog-link').classList.contains('disabled'))548        return;549      if (cr.isWindows) {550        this.showSystemDialogBeforeNextPrint_ = true;551        this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);552        return;553      }554      setIsVisible(getRequiredElement('system-dialog-throbber'), true);555      this.setIsEnabled_(false);556      this.uiState_ = PrintPreview.UiState_.OPENING_NATIVE_PRINT_DIALOG;557      this.nativeLayer_.startShowSystemDialog();558    },559    /**560     * Called when the native layer has initial settings to set. Sets the561     * initial settings of the print preview and begins fetching print562     * destinations.563     * @param {Event} event Contains the initial print preview settings564     *     persisted through the session.565     * @private566     */567    onInitialSettingsSet_: function(event) {568      assert(this.uiState_ == PrintPreview.UiState_.INITIALIZING,569             'Updating initial settings when not in initializing state: ' +570                 this.uiState_);571      this.uiState_ = PrintPreview.UiState_.READY;572      var settings = event.initialSettings;573      this.isInKioskAutoPrintMode_ = settings.isInKioskAutoPrintMode;574      this.isInAppKioskMode_ = settings.isInAppKioskMode;575      // The following components must be initialized in this order.576      this.appState_.init(577          settings.serializedAppStateStr,578          settings.systemDefaultDestinationId);579      this.documentInfo_.init(580          settings.isDocumentModifiable,581          settings.documentTitle,582          settings.documentHasSelection);583      this.printTicketStore_.init(584          settings.thousandsDelimeter,585          settings.decimalDelimeter,586          settings.unitType,587          settings.selectionOnly);588      this.destinationStore_.init(settings.isInAppKioskMode);589      this.appState_.setInitialized();590      $('document-title').innerText = settings.documentTitle;591      this.hideSystemDialogLink_ = settings.hidePrintWithSystemDialogLink ||592                                   settings.isInAppKioskMode;593      if ($('system-dialog-link')) {594        setIsVisible($('system-dialog-link'),595                     this.shouldShowSystemDialogLink_());596      }597    },598    /**599     * Calls when the native layer enables Google Cloud Print integration.600     * Fetches the user's cloud printers.601     * @param {Event} event Contains the base URL of the Google Cloud Print602     *     service.603     * @private604     */605    onCloudPrintEnable_: function(event) {606      this.cloudPrintInterface_ = new cloudprint.CloudPrintInterface(607          event.baseCloudPrintUrl,608          this.nativeLayer_,609          this.userInfo_,610          event.appKioskMode);611      this.tracker.add(612          this.cloudPrintInterface_,613          cloudprint.CloudPrintInterface.EventType.SUBMIT_DONE,614          this.onCloudPrintSubmitDone_.bind(this));615      this.tracker.add(616          this.cloudPrintInterface_,617          cloudprint.CloudPrintInterface.EventType.SEARCH_FAILED,618          this.onCloudPrintError_.bind(this));619      this.tracker.add(620          this.cloudPrintInterface_,621          cloudprint.CloudPrintInterface.EventType.SUBMIT_FAILED,622          this.onCloudPrintError_.bind(this));623      this.tracker.add(624          this.cloudPrintInterface_,625          cloudprint.CloudPrintInterface.EventType.PRINTER_FAILED,626          this.onCloudPrintError_.bind(this));627      this.tracker.add(628          this.cloudPrintInterface_,629          cloudprint.CloudPrintInterface.EventType.630              UPDATE_PRINTER_TOS_ACCEPTANCE_FAILED,631          this.onCloudPrintError_.bind(this));632      this.destinationStore_.setCloudPrintInterface(this.cloudPrintInterface_);633      this.invitationStore_.setCloudPrintInterface(this.cloudPrintInterface_);634      if (this.destinationSearch_.getIsVisible()) {635        this.destinationStore_.startLoadCloudDestinations();636        this.invitationStore_.startLoadingInvitations();637      }638    },639    /**640     * Called from the native layer when ready to print to Google Cloud Print.641     * @param {Event} event Contains the body to send in the HTTP request.642     * @private643     */644    onPrintToCloud_: function(event) {645      assert(this.uiState_ == PrintPreview.UiState_.PRINTING,646             'Document ready to be sent to the cloud when not in printing ' +647                 'state: ' + this.uiState_);648      assert(this.cloudPrintInterface_ != null,649             'Google Cloud Print is not enabled');650      this.cloudPrintInterface_.submit(651          this.destinationStore_.selectedDestination,652          this.printTicketStore_,653          this.documentInfo_,654          event.data);655    },656    /**657     * Called from the native layer when the user cancels the save-to-pdf file658     * selection dialog.659     * @private660     */661    onFileSelectionCancel_: function() {662      assert(this.uiState_ == PrintPreview.UiState_.FILE_SELECTION,663             'File selection cancelled when not in file-selection state: ' +664                 this.uiState_);665      this.setIsEnabled_(true);666      this.uiState_ = PrintPreview.UiState_.READY;667    },668    /**669     * Called from the native layer when save-to-pdf file selection is complete.670     * @private671     */672    onFileSelectionComplete_: function() {673      assert(this.uiState_ == PrintPreview.UiState_.FILE_SELECTION,674             'File selection completed when not in file-selection state: ' +675                 this.uiState_);676      this.previewArea_.showCustomMessage(677          loadTimeData.getString('printingToPDFInProgress'));678      this.uiState_ = PrintPreview.UiState_.PRINTING;679    },680    /**681     * Called after successfully submitting a job to Google Cloud Print.682     * @param {!Event} event Contains the ID of the submitted print job.683     * @private684     */685    onCloudPrintSubmitDone_: function(event) {686      assert(this.uiState_ == PrintPreview.UiState_.PRINTING,687             'Submited job to Google Cloud Print but not in printing state ' +688                 this.uiState_);689      if (this.destinationStore_.selectedDestination.id ==690              print_preview.Destination.GooglePromotedId.FEDEX) {691        this.nativeLayer_.startForceOpenNewTab(692            'https://www.google.com/cloudprint/fedexcode.html?jobid=' +693            event.jobId);694      }695      this.close_();696    },697    /**698     * Called when there was an error communicating with Google Cloud print.699     * Displays an error message in the print header.700     * @param {!Event} event Contains the error message.701     * @private702     */703    onCloudPrintError_: function(event) {704      if (event.status == 403) {705        if (!this.isInAppKioskMode_) {706          this.destinationSearch_.showCloudPrintPromo();707        }708      } else if (event.status == 0) {709        return; // Ignore, the system does not have internet connectivity.710      } else {711        this.printHeader_.setErrorMessage(event.message);712      }713      if (event.status == 200) {714        console.error('Google Cloud Print Error: (' + event.errorCode + ') ' +715                      event.message);716      } else {717        console.error('Google Cloud Print Error: HTTP status ' + event.status);718      }719    },720    /**721     * Called when the preview area's preview generation is in progress.722     * @private723     */724    onPreviewGenerationInProgress_: function() {725      this.isPreviewGenerationInProgress_ = true;726    },727    /**728     * Called when the preview area's preview generation is complete.729     * @private730     */731    onPreviewGenerationDone_: function() {732      this.isPreviewGenerationInProgress_ = false;733      this.printHeader_.isPrintButtonEnabled = true;734      this.nativeLayer_.previewReadyForTest();735      this.printIfReady_();736    },737    /**738     * Called when the preview area's preview failed to load.739     * @private740     */741    onPreviewGenerationFail_: function() {742      this.isPreviewGenerationInProgress_ = false;743      this.printHeader_.isPrintButtonEnabled = false;744      if (this.uiState_ == PrintPreview.UiState_.PRINTING)745        this.nativeLayer_.startCancelPendingPrint();746    },747    /**748     * Called when the 'Open pdf in preview' link is clicked. Launches the pdf749     * preview app.750     * @private751     */752    onOpenPdfInPreviewLinkClick_: function() {753      if ($('open-pdf-in-preview-link').classList.contains('disabled'))754        return;755      assert(this.uiState_ == PrintPreview.UiState_.READY,756             'Trying to open pdf in preview when not in ready state: ' +757                 this.uiState_);758      setIsVisible(getRequiredElement('open-preview-app-throbber'), true);759      this.previewArea_.showCustomMessage(760          loadTimeData.getString('openingPDFInPreview'));761      this.printDocumentOrOpenPdfPreview_(true /*isPdfPreview*/);762    },763    /**764     * Called when the print header's print button is clicked. Prints the765     * document.766     * @private767     */768    onPrintButtonClick_: function() {769      assert(this.uiState_ == PrintPreview.UiState_.READY,770             'Trying to print when not in ready state: ' + this.uiState_);771      this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);772    },773    /**774     * Called when the print header's cancel button is clicked. Closes the775     * print dialog.776     * @private777     */778    onCancelButtonClick_: function() {779      this.close_();780    },781    /**782     * Called when the register promo for Cloud Print is clicked.783     * @private784     */785     onCloudPrintRegisterPromoClick_: function(e) {786       var devicesUrl = 'chrome://devices/register?id=' + e.destination.id;787       this.nativeLayer_.startForceOpenNewTab(devicesUrl);788       this.destinationStore_.waitForRegister(e.destination.id);789     },790    /**791     * Consume escape key presses and ctrl + shift + p. Delegate everything else792     * to the preview area.793     * @param {KeyboardEvent} e The keyboard event.794     * @private795     * @suppress {uselessCode}796     * Current compiler preprocessor leaves all the code inside all the <if>s,797     * so the compiler claims that code after first return is unreachable.798     */799    onKeyDown_: function(e) {800      // Escape key closes the dialog.801      if (e.keyCode == 27 && !e.shiftKey && !e.ctrlKey && !e.altKey &&802          !e.metaKey) {803        // On non-mac with toolkit-views, ESC key is handled by C++-side instead804        // of JS-side.805        if (cr.isMac) {806          this.close_();807          e.preventDefault();808        }809        return;810      }811      // On Mac, Cmd- should close the print dialog.812      if (cr.isMac && e.keyCode == 189 && e.metaKey) {813        this.close_();814        e.preventDefault();815        return;816      }817      // Ctrl + Shift + p / Mac equivalent.818      if (e.keyCode == 80) {819        if ((cr.isMac && e.metaKey && e.altKey && !e.shiftKey && !e.ctrlKey) ||820            (!cr.isMac && e.shiftKey && e.ctrlKey && !e.altKey && !e.metaKey)) {821          this.openSystemPrintDialog_();822          e.preventDefault();823          return;824        }825      }826      if (e.keyCode == 13 /*enter*/ &&827          !document.querySelector('.overlay:not([hidden])') &&828          this.destinationStore_.selectedDestination &&829          this.printTicketStore_.isTicketValid() &&830          this.printHeader_.isPrintButtonEnabled) {831        assert(this.uiState_ == PrintPreview.UiState_.READY,832            'Trying to print when not in ready state: ' + this.uiState_);833        var activeElementTag = document.activeElement.tagName.toUpperCase();834        if (activeElementTag != 'BUTTON' && activeElementTag != 'SELECT' &&835            activeElementTag != 'A') {836          this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);837          e.preventDefault();838        }839        return;840      }841      // Pass certain directional keyboard events to the PDF viewer.842      this.previewArea_.handleDirectionalKeyEvent(e);843    },844    /**845     * Called when native layer receives invalid settings for a print request.846     * @private847     */848    onSettingsInvalid_: function() {849      this.uiState_ = PrintPreview.UiState_.ERROR;850      console.error('Invalid settings error reported from native layer');851      this.previewArea_.showCustomMessage(852          loadTimeData.getString('invalidPrinterSettings'));853    },854    /**855     * Called when the destination settings' change button is activated.856     * Displays the destination search component.857     * @private858     */859    onDestinationChangeButtonActivate_: function() {860      this.destinationSearch_.setIsVisible(true);861    },862    /**863     * Called when the destination settings' change button is activated.864     * Displays the destination search component.865     * @private866     */867    onAdvancedOptionsButtonActivated_: function() {868      this.advancedSettings_.showForDestination(869          assert(this.destinationStore_.selectedDestination));870    },871    /**872     * Called when the destination search dispatches manage cloud destinations873     * event. Calls corresponding native layer method.874     * @private875     */876    onManageCloudDestinationsActivated_: function() {877      this.nativeLayer_.startManageCloudDestinations(this.userInfo_.activeUser);878    },879    /**880     * Called when the destination search dispatches manage local destinations881     * event. Calls corresponding native layer method.882     * @private883     */884    onManageLocalDestinationsActivated_: function() {885      this.nativeLayer_.startManageLocalDestinations();886    },887    /**888     * Called when the user wants to sign in to Google Cloud Print. Calls the889     * corresponding native layer event.890     * @param {boolean} addAccount Whether to open an 'add a new account' or891     *     default sign in page.892     * @private893     */894    onCloudPrintSignInActivated_: function(addAccount) {895      this.nativeLayer_.startCloudPrintSignIn(addAccount);896    },897    /**898     * Updates printing options according to source document presets.899     * @param {Event} event Contains options from source document.900     * @private901     */902    onPrintPresetOptionsFromDocument_: function(event) {903      if (event.optionsFromDocument.disableScaling) {904        this.printTicketStore_.fitToPage.updateValue(null);905        this.documentInfo_.updateIsScalingDisabled(true);906      }907      if (event.optionsFromDocument.copies > 0 &&908          this.printTicketStore_.copies.isCapabilityAvailable()) {909        this.printTicketStore_.copies.updateValue(910            event.optionsFromDocument.copies);911      }912      if (event.optionsFromDocument.duplex >= 0 &&913          this.printTicketStore_.duplex.isCapabilityAvailable()) {914        this.printTicketStore_.duplex.updateValue(915            event.optionsFromDocument.duplex);916      }917    },918    /**919     * Called when privet printing fails.920     * @param {Event} event Event object representing the failure.921     * @private922     */923    onPrivetPrintFailed_: function(event) {924      console.error('Privet printing failed with error code ' +925                    event.httpError);926      this.printHeader_.setErrorMessage(927          loadTimeData.getString('couldNotPrint'));928    },929    /**930     * Called when the print preview settings need to be changed for testing.931     * @param {Event} event Event object that contains the option that is to932     *     be changed and what to set that option.933     * @private934     */935    onManipulateSettingsForTest_: function(event) {936      var settings =937          /** @type {print_preview.PreviewSettings} */(event.settings);938      if ('selectSaveAsPdfDestination' in settings) {939        this.saveAsPdfForTest_();  // No parameters.940      } else if ('layoutSettings' in settings) {941        this.setLayoutSettingsForTest_(settings.layoutSettings.portrait);942      } else if ('pageRange' in settings) {943        this.setPageRangeForTest_(settings.pageRange);944      } else if ('headersAndFooters' in settings) {945        this.setHeadersAndFootersForTest_(settings.headersAndFooters);946      } else if ('backgroundColorsAndImages' in settings) {947        this.setBackgroundColorsAndImagesForTest_(948            settings.backgroundColorsAndImages);949      } else if ('margins' in settings) {950        this.setMarginsForTest_(settings.margins);951      }952    },953    /**954     * Called by onManipulateSettingsForTest_(). Sets the print destination955     * as a pdf.956     * @private957     */958    saveAsPdfForTest_: function() {959      if (this.destinationStore_.selectedDestination &&960          print_preview.Destination.GooglePromotedId.SAVE_AS_PDF ==961          this.destinationStore_.selectedDestination.id) {962        this.nativeLayer_.previewReadyForTest();963        return;964      }965      var destinations = this.destinationStore_.destinations();966      var pdfDestination = null;967      for (var i = 0; i < destinations.length; i++) {968        if (destinations[i].id ==969            print_preview.Destination.GooglePromotedId.SAVE_AS_PDF) {970          pdfDestination = destinations[i];971          break;972        }973      }974      if (pdfDestination)975        this.destinationStore_.selectDestination(pdfDestination);976      else977        this.nativeLayer_.previewFailedForTest();978    },979    /**980     * Called by onManipulateSettingsForTest_(). Sets the layout settings to981     * either portrait or landscape.982     * @param {boolean} portrait Whether to use portrait page layout;983     *     if false: landscape.984     * @private985     */986    setLayoutSettingsForTest_: function(portrait) {987      var combobox = document.querySelector('.layout-settings-select');988      if (combobox.value == 'portrait') {989        this.nativeLayer_.previewReadyForTest();990      } else {991        combobox.value = 'landscape';992        this.layoutSettings_.onSelectChange_();993      }994    },995    /**996     * Called by onManipulateSettingsForTest_(). Sets the page range for997     * for the print preview settings.998     * @param {string} pageRange Sets the page range to the desired value(s).999     *     Ex: "1-5,9" means pages 1 through 5 and page 9 will be printed.1000     * @private1001     */1002    setPageRangeForTest_: function(pageRange) {1003      var textbox = document.querySelector('.page-settings-custom-input');1004      if (textbox.value == pageRange) {1005        this.nativeLayer_.previewReadyForTest();1006      } else {1007        textbox.value = pageRange;1008        document.querySelector('.page-settings-custom-radio').click();1009      }1010    },1011    /**1012     * Called by onManipulateSettings_(). Checks or unchecks the headers and1013     * footers option on print preview.1014     * @param {boolean} headersAndFooters Whether the "Headers and Footers"1015     *     checkbox should be checked.1016     * @private1017     */1018    setHeadersAndFootersForTest_: function(headersAndFooters) {1019      var checkbox = document.querySelector('.header-footer-checkbox');1020      if (headersAndFooters == checkbox.checked)1021        this.nativeLayer_.previewReadyForTest();1022      else1023        checkbox.click();1024    },1025    /**1026     * Called by onManipulateSettings_(). Checks or unchecks the background1027     * colors and images option on print preview.1028     * @param {boolean} backgroundColorsAndImages If true, the checkbox should1029     *     be checked. Otherwise it should be unchecked.1030     * @private1031     */1032    setBackgroundColorsAndImagesForTest_: function(backgroundColorsAndImages) {1033      var checkbox = document.querySelector('.css-background-checkbox');1034      if (backgroundColorsAndImages == checkbox.checked)1035        this.nativeLayer_.previewReadyForTest();1036      else1037        checkbox.click();1038    },1039    /**1040     * Called by onManipulateSettings_(). Sets the margin settings1041     * that are desired. Custom margin settings aren't currently supported.1042     * @param {number} margins The desired margins combobox index. Must be1043     *     a valid index or else the test fails.1044     * @private1045     */1046    setMarginsForTest_: function(margins) {1047      var combobox = document.querySelector('.margin-settings-select');1048      if (margins == combobox.selectedIndex) {1049        this.nativeLayer_.previewReadyForTest();1050      } else if (margins >= 0 && margins < combobox.length) {1051        combobox.selectedIndex = margins;1052        this.marginSettings_.onSelectChange_();1053      } else {1054        this.nativeLayer_.previewFailedForTest();1055      }1056    },1057    /**1058     * Returns true if "Print using system dialog" link should be shown for1059     * current destination.1060     * @return {boolean} Returns true if link should be shown.1061     */1062    shouldShowSystemDialogLink_: function() {1063      if (cr.isChromeOS || this.hideSystemDialogLink_)1064        return false;1065      if (!cr.isWindows)1066        return true;1067      var selectedDest = this.destinationStore_.selectedDestination;1068      return !!selectedDest &&1069             selectedDest.origin == print_preview.Destination.Origin.LOCAL &&1070             selectedDest.id !=1071                 print_preview.Destination.GooglePromotedId.SAVE_AS_PDF;1072    },1073    /**1074     * Called when a print destination is selected. Shows/hides the "Print with1075     * Cloud Print" link in the navbar.1076     * @private1077     */1078    onDestinationSelect_: function() {1079      if ($('system-dialog-link')) {1080        setIsVisible($('system-dialog-link'),1081                     this.shouldShowSystemDialogLink_());1082      }1083      if (this.destinationStore_.selectedDestination &&1084          this.isInKioskAutoPrintMode_) {1085        this.onPrintButtonClick_();1086      }1087    },1088    /**1089     * Called when the destination store loads a group of destinations. Shows1090     * a promo on Chrome OS if the user has no print destinations promoting1091     * Google Cloud Print.1092     * @private1093     */1094    onDestinationSearchDone_: function() {1095      var isPromoVisible = cr.isChromeOS &&1096          this.cloudPrintInterface_ &&1097          this.userInfo_.activeUser &&1098          !this.appState_.isGcpPromoDismissed &&1099          !this.destinationStore_.isLocalDestinationSearchInProgress &&1100          !this.destinationStore_.isCloudDestinationSearchInProgress &&1101          this.destinationStore_.hasOnlyDefaultCloudDestinations();1102      setIsVisible(this.getChildElement('#no-destinations-promo'),1103                   isPromoVisible);1104      if (isPromoVisible) {1105        new print_preview.GcpPromoMetricsContext().record(1106            print_preview.Metrics.GcpPromoBucket.PROMO_SHOWN);1107      }1108    },1109    /**1110     * Called when the close button on the no-destinations-promotion is clicked.1111     * Hides the promotion.1112     * @private1113     */1114    onNoDestinationsPromoClose_: function() {1115      new print_preview.GcpPromoMetricsContext().record(1116          print_preview.Metrics.GcpPromoBucket.PROMO_CLOSED);1117      setIsVisible(this.getChildElement('#no-destinations-promo'), false);1118      this.appState_.persistIsGcpPromoDismissed(true);1119    },1120    /**1121     * Called when the no-destinations promotion link is clicked. Opens the1122     * Google Cloud Print management page and closes the print preview.1123     * @private1124     */1125    onNoDestinationsPromoClick_: function() {1126      new print_preview.GcpPromoMetricsContext().record(1127          print_preview.Metrics.GcpPromoBucket.PROMO_CLICKED);1128      this.appState_.persistIsGcpPromoDismissed(true);1129      window.open(this.cloudPrintInterface_.baseUrl + '?user=' +1130                  this.userInfo_.activeUser + '#printers');1131      this.close_();1132    }1133  };1134  // Export1135  return {1136    PrintPreview: PrintPreview1137  };1138});1139// Pull in all other scripts in a single shot.1140<include src="common/overlay.js">1141<include src="common/search_box.js">1142<include src="common/search_bubble.js">1143<include src="data/page_number_set.js">1144<include src="data/destination.js">1145<include src="data/local_parsers.js">1146<include src="data/cloud_parsers.js">1147<include src="data/destination_store.js">1148<include src="data/invitation.js">1149<include src="data/invitation_store.js">1150<include src="data/margins.js">1151<include src="data/document_info.js">1152<include src="data/printable_area.js">1153<include src="data/measurement_system.js">1154<include src="data/print_ticket_store.js">1155<include src="data/coordinate2d.js">1156<include src="data/size.js">1157<include src="data/capabilities_holder.js">1158<include src="data/user_info.js">1159<include src="data/app_state.js">1160<include src="data/ticket_items/ticket_item.js">1161<include src="data/ticket_items/custom_margins.js">1162<include src="data/ticket_items/collate.js">1163<include src="data/ticket_items/color.js">1164<include src="data/ticket_items/copies.js">1165<include src="data/ticket_items/dpi.js">1166<include src="data/ticket_items/duplex.js">1167<include src="data/ticket_items/header_footer.js">1168<include src="data/ticket_items/media_size.js">1169<include src="data/ticket_items/landscape.js">1170<include src="data/ticket_items/margins_type.js">1171<include src="data/ticket_items/page_range.js">1172<include src="data/ticket_items/fit_to_page.js">1173<include src="data/ticket_items/css_background.js">1174<include src="data/ticket_items/selection_only.js">1175<include src="data/ticket_items/vendor_items.js">1176<include src="native_layer.js">1177<include src="print_preview_animations.js">1178<include src="cloud_print_interface.js">1179<include src="print_preview_utils.js">1180<include src="print_header.js">1181<include src="metrics.js">1182<include src="settings/settings_section.js">1183<include src="settings/settings_section_select.js">1184<include src="settings/page_settings.js">1185<include src="settings/copies_settings.js">1186<include src="settings/dpi_settings.js">1187<include src="settings/media_size_settings.js">1188<include src="settings/layout_settings.js">1189<include src="settings/color_settings.js">1190<include src="settings/margin_settings.js">1191<include src="settings/destination_settings.js">1192<include src="settings/other_options_settings.js">1193<include src="settings/advanced_options_settings.js">1194<include src="settings/advanced_settings/advanced_settings.js">1195<include src="settings/advanced_settings/advanced_settings_item.js">1196<include src="settings/more_settings.js">1197<include src="previewarea/margin_control.js">1198<include src="previewarea/margin_control_container.js">1199<include src="../pdf/pdf_scripting_api.js">1200<include src="previewarea/preview_area.js">1201<include src="preview_generator.js">1202<include src="search/destination_list.js">1203<include src="search/cloud_destination_list.js">1204<include src="search/recent_destination_list.js">1205<include src="search/destination_list_item.js">1206<include src="search/destination_search.js">1207<include src="search/fedex_tos.js">1208<include src="search/provisional_destination_resolver.js">1209window.addEventListener('DOMContentLoaded', function() {1210  printPreview = new print_preview.PrintPreview();1211  printPreview.initialize();...native_layer.js
Source:native_layer.js  
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4cr.exportPath('print_preview');5/**6 * @typedef {{selectSaveAsPdfDestination: boolean,7 *            layoutSettings.portrait: boolean,8 *            pageRange: string,9 *            headersAndFooters: boolean,10 *            backgroundColorsAndImages: boolean,11 *            margins: number}}12 * @see chrome/browser/printing/print_preview_pdf_generated_browsertest.cc13 */14print_preview.PreviewSettings;15cr.define('print_preview', function() {16  'use strict';17  /**18   * An interface to the native Chromium printing system layer.19   * @constructor20   * @extends {cr.EventTarget}21   */22  function NativeLayer() {23    cr.EventTarget.call(this);24    // Bind global handlers25    global.setInitialSettings = this.onSetInitialSettings_.bind(this);26    global.setUseCloudPrint = this.onSetUseCloudPrint_.bind(this);27    global.setPrinters = this.onSetPrinters_.bind(this);28    global.updateWithPrinterCapabilities =29        this.onUpdateWithPrinterCapabilities_.bind(this);30    global.failedToGetPrinterCapabilities =31        this.onFailedToGetPrinterCapabilities_.bind(this);32    global.failedToGetPrivetPrinterCapabilities =33      this.onFailedToGetPrivetPrinterCapabilities_.bind(this);34    global.failedToGetExtensionPrinterCapabilities =35        this.onFailedToGetExtensionPrinterCapabilities_.bind(this);36    global.reloadPrintersList = this.onReloadPrintersList_.bind(this);37    global.printToCloud = this.onPrintToCloud_.bind(this);38    global.fileSelectionCancelled =39        this.onFileSelectionCancelled_.bind(this);40    global.fileSelectionCompleted =41        this.onFileSelectionCompleted_.bind(this);42    global.printPreviewFailed = this.onPrintPreviewFailed_.bind(this);43    global.invalidPrinterSettings =44        this.onInvalidPrinterSettings_.bind(this);45    global.onDidGetDefaultPageLayout =46        this.onDidGetDefaultPageLayout_.bind(this);47    global.onDidGetPreviewPageCount =48        this.onDidGetPreviewPageCount_.bind(this);49    global.onDidPreviewPage = this.onDidPreviewPage_.bind(this);50    global.updatePrintPreview = this.onUpdatePrintPreview_.bind(this);51    global.onDidGetAccessToken = this.onDidGetAccessToken_.bind(this);52    global.autoCancelForTesting = this.autoCancelForTesting_.bind(this);53    global.onPrivetPrinterChanged = this.onPrivetPrinterChanged_.bind(this);54    global.onPrivetCapabilitiesSet =55        this.onPrivetCapabilitiesSet_.bind(this);56    global.onPrivetPrintFailed = this.onPrivetPrintFailed_.bind(this);57    global.onExtensionPrintersAdded =58        this.onExtensionPrintersAdded_.bind(this);59    global.onExtensionCapabilitiesSet =60        this.onExtensionCapabilitiesSet_.bind(this);61    global.onEnableManipulateSettingsForTest =62        this.onEnableManipulateSettingsForTest_.bind(this);63    global.printPresetOptionsFromDocument =64        this.onPrintPresetOptionsFromDocument_.bind(this);65    global.onProvisionalPrinterResolved =66        this.onProvisionalDestinationResolved_.bind(this);67    global.failedToResolveProvisionalPrinter =68        this.failedToResolveProvisionalDestination_.bind(this);69  };70  /**71   * Event types dispatched from the Chromium native layer.72   * @enum {string}73   * @const74   */75  NativeLayer.EventType = {76    ACCESS_TOKEN_READY: 'print_preview.NativeLayer.ACCESS_TOKEN_READY',77    CAPABILITIES_SET: 'print_preview.NativeLayer.CAPABILITIES_SET',78    CLOUD_PRINT_ENABLE: 'print_preview.NativeLayer.CLOUD_PRINT_ENABLE',79    DESTINATIONS_RELOAD: 'print_preview.NativeLayer.DESTINATIONS_RELOAD',80    DISABLE_SCALING: 'print_preview.NativeLayer.DISABLE_SCALING',81    FILE_SELECTION_CANCEL: 'print_preview.NativeLayer.FILE_SELECTION_CANCEL',82    FILE_SELECTION_COMPLETE:83        'print_preview.NativeLayer.FILE_SELECTION_COMPLETE',84    GET_CAPABILITIES_FAIL: 'print_preview.NativeLayer.GET_CAPABILITIES_FAIL',85    INITIAL_SETTINGS_SET: 'print_preview.NativeLayer.INITIAL_SETTINGS_SET',86    LOCAL_DESTINATIONS_SET: 'print_preview.NativeLayer.LOCAL_DESTINATIONS_SET',87    MANIPULATE_SETTINGS_FOR_TEST:88        'print_preview.NativeLayer.MANIPULATE_SETTINGS_FOR_TEST',89    PAGE_COUNT_READY: 'print_preview.NativeLayer.PAGE_COUNT_READY',90    PAGE_LAYOUT_READY: 'print_preview.NativeLayer.PAGE_LAYOUT_READY',91    PAGE_PREVIEW_READY: 'print_preview.NativeLayer.PAGE_PREVIEW_READY',92    PREVIEW_GENERATION_DONE:93        'print_preview.NativeLayer.PREVIEW_GENERATION_DONE',94    PREVIEW_GENERATION_FAIL:95        'print_preview.NativeLayer.PREVIEW_GENERATION_FAIL',96    PRINT_TO_CLOUD: 'print_preview.NativeLayer.PRINT_TO_CLOUD',97    SETTINGS_INVALID: 'print_preview.NativeLayer.SETTINGS_INVALID',98    PRIVET_PRINTER_CHANGED: 'print_preview.NativeLayer.PRIVET_PRINTER_CHANGED',99    PRIVET_CAPABILITIES_SET:100        'print_preview.NativeLayer.PRIVET_CAPABILITIES_SET',101    PRIVET_PRINT_FAILED: 'print_preview.NativeLayer.PRIVET_PRINT_FAILED',102    EXTENSION_PRINTERS_ADDED:103        'print_preview.NativeLayer.EXTENSION_PRINTERS_ADDED',104    EXTENSION_CAPABILITIES_SET:105        'print_preview.NativeLayer.EXTENSION_CAPABILITIES_SET',106    PRINT_PRESET_OPTIONS: 'print_preview.NativeLayer.PRINT_PRESET_OPTIONS',107    PROVISIONAL_DESTINATION_RESOLVED:108        'print_preview.NativeLayer.PROVISIONAL_DESTINATION_RESOLVED'109  };110  /**111   * Constant values matching printing::DuplexMode enum.112   * @enum {number}113   */114  NativeLayer.DuplexMode = {115    SIMPLEX: 0,116    LONG_EDGE: 1,117    UNKNOWN_DUPLEX_MODE: -1118  };119  /**120   * Enumeration of color modes used by Chromium.121   * @enum {number}122   * @private123   */124  NativeLayer.ColorMode_ = {125    GRAY: 1,126    COLOR: 2127  };128  /**129   * Version of the serialized state of the print preview.130   * @type {number}131   * @const132   * @private133   */134  NativeLayer.SERIALIZED_STATE_VERSION_ = 1;135  NativeLayer.prototype = {136    __proto__: cr.EventTarget.prototype,137    /**138     * Requests access token for cloud print requests.139     * @param {string} authType type of access token.140     */141    startGetAccessToken: function(authType) {142      chrome.send('getAccessToken', [authType]);143    },144    /** Gets the initial settings to initialize the print preview with. */145    startGetInitialSettings: function() {146      chrome.send('getInitialSettings');147    },148    /**149     * Requests the system's local print destinations. A LOCAL_DESTINATIONS_SET150     * event will be dispatched in response.151     */152    startGetLocalDestinations: function() {153      chrome.send('getPrinters');154    },155    /**156     * Requests the network's privet print destinations. A number of157     * PRIVET_PRINTER_CHANGED events will be fired in response, followed by a158     * PRIVET_SEARCH_ENDED.159     */160    startGetPrivetDestinations: function() {161      chrome.send('getPrivetPrinters');162    },163    /**164     * Requests that the privet print stack stop searching for privet print165     * destinations.166     */167    stopGetPrivetDestinations: function() {168      chrome.send('stopGetPrivetPrinters');169    },170    /**171     * Requests the privet destination's printing capabilities. A172     * PRIVET_CAPABILITIES_SET event will be dispatched in response.173     * @param {string} destinationId ID of the destination.174     */175    startGetPrivetDestinationCapabilities: function(destinationId) {176      chrome.send('getPrivetPrinterCapabilities', [destinationId]);177    },178    /**179     * Requests that extension system dispatches an event requesting the list of180     * extension managed printers.181     */182    startGetExtensionDestinations: function() {183      chrome.send('getExtensionPrinters');184    },185    /**186     * Requests an extension destination's printing capabilities. A187     * EXTENSION_CAPABILITIES_SET event will be dispatched in response.188     * @param {string} destinationId The ID of the destination whose189     *     capabilities are requested.190     */191    startGetExtensionDestinationCapabilities: function(destinationId) {192      chrome.send('getExtensionPrinterCapabilities', [destinationId]);193    },194    /**195     * Requests the destination's printing capabilities. A CAPABILITIES_SET196     * event will be dispatched in response.197     * @param {string} destinationId ID of the destination.198     */199    startGetLocalDestinationCapabilities: function(destinationId) {200      chrome.send('getPrinterCapabilities', [destinationId]);201    },202    /**203     * Requests Chrome to resolve provisional extension destination by granting204     * the provider extension access to the printer. Chrome will respond with205     * the resolved destination properties by calling206     * {@code onProvisionalPrinterResolved}, or in case of an error207     * {@code failedToResolveProvisionalPrinter}208     * @param {string} provisionalDestinationId209     */210    grantExtensionPrinterAccess: function(provisionalDestinationId) {211      chrome.send('grantExtensionPrinterAccess', [provisionalDestinationId]);212    },213    /**214     * @param {!print_preview.Destination} destination Destination to print to.215     * @param {!print_preview.ticket_items.Color} color Color ticket item.216     * @return {number} Native layer color model.217     * @private218     */219    getNativeColorModel_: function(destination, color) {220      // For non-local printers native color model is ignored anyway.221      var option = destination.isLocal ? color.getSelectedOption() : null;222      var nativeColorModel = parseInt(option ? option.vendor_id : null, 10);223      if (isNaN(nativeColorModel)) {224        return color.getValue() ?225            NativeLayer.ColorMode_.COLOR : NativeLayer.ColorMode_.GRAY;226      }227      return nativeColorModel;228    },229    /**230     * Requests that a preview be generated. The following events may be231     * dispatched in response:232     *   - PAGE_COUNT_READY233     *   - PAGE_LAYOUT_READY234     *   - PAGE_PREVIEW_READY235     *   - PREVIEW_GENERATION_DONE236     *   - PREVIEW_GENERATION_FAIL237     * @param {print_preview.Destination} destination Destination to print to.238     * @param {!print_preview.PrintTicketStore} printTicketStore Used to get the239     *     state of the print ticket.240     * @param {!print_preview.DocumentInfo} documentInfo Document data model.241     * @param {number} requestId ID of the preview request.242     */243    startGetPreview: function(244        destination, printTicketStore, documentInfo, requestId) {245      assert(printTicketStore.isTicketValidForPreview(),246             'Trying to generate preview when ticket is not valid');247      var ticket = {248        'pageRange': printTicketStore.pageRange.getDocumentPageRanges(),249        'mediaSize': printTicketStore.mediaSize.getValue(),250        'landscape': printTicketStore.landscape.getValue(),251        'color': this.getNativeColorModel_(destination, printTicketStore.color),252        'headerFooterEnabled': printTicketStore.headerFooter.getValue(),253        'marginsType': printTicketStore.marginsType.getValue(),254        'isFirstRequest': requestId == 0,255        'requestID': requestId,256        'previewModifiable': documentInfo.isModifiable,257        'printToPDF':258            destination != null &&259            destination.id ==260                print_preview.Destination.GooglePromotedId.SAVE_AS_PDF,261        'printWithCloudPrint': destination != null && !destination.isLocal,262        'printWithPrivet': destination != null && destination.isPrivet,263        'printWithExtension': destination != null && destination.isExtension,264        'deviceName': destination == null ? 'foo' : destination.id,265        'generateDraftData': documentInfo.isModifiable,266        'fitToPageEnabled': printTicketStore.fitToPage.getValue(),267        // NOTE: Even though the following fields don't directly relate to the268        // preview, they still need to be included.269        'duplex': printTicketStore.duplex.getValue() ?270            NativeLayer.DuplexMode.LONG_EDGE : NativeLayer.DuplexMode.SIMPLEX,271        'copies': 1,272        'collate': true,273        'shouldPrintBackgrounds': printTicketStore.cssBackground.getValue(),274        'shouldPrintSelectionOnly': printTicketStore.selectionOnly.getValue()275      };276      // Set 'cloudPrintID' only if the destination is not local.277      if (destination && !destination.isLocal) {278        ticket['cloudPrintID'] = destination.id;279      }280      if (printTicketStore.marginsType.isCapabilityAvailable() &&281          printTicketStore.marginsType.getValue() ==282              print_preview.ticket_items.MarginsType.Value.CUSTOM) {283        var customMargins = printTicketStore.customMargins.getValue();284        var orientationEnum =285            print_preview.ticket_items.CustomMargins.Orientation;286        ticket['marginsCustom'] = {287          'marginTop': customMargins.get(orientationEnum.TOP),288          'marginRight': customMargins.get(orientationEnum.RIGHT),289          'marginBottom': customMargins.get(orientationEnum.BOTTOM),290          'marginLeft': customMargins.get(orientationEnum.LEFT)291        };292      }293      chrome.send(294          'getPreview',295          [JSON.stringify(ticket),296           requestId > 0 ? documentInfo.pageCount : -1,297           documentInfo.isModifiable]);298    },299    /**300     * Requests that the document be printed.301     * @param {!print_preview.Destination} destination Destination to print to.302     * @param {!print_preview.PrintTicketStore} printTicketStore Used to get the303     *     state of the print ticket.304     * @param {cloudprint.CloudPrintInterface} cloudPrintInterface Interface305     *     to Google Cloud Print.306     * @param {!print_preview.DocumentInfo} documentInfo Document data model.307     * @param {boolean=} opt_isOpenPdfInPreview Whether to open the PDF in the308     *     system's preview application.309     * @param {boolean=} opt_showSystemDialog Whether to open system dialog for310     *     advanced settings.311     */312    startPrint: function(destination, printTicketStore, cloudPrintInterface,313                         documentInfo, opt_isOpenPdfInPreview,314                         opt_showSystemDialog) {315      assert(printTicketStore.isTicketValid(),316             'Trying to print when ticket is not valid');317      assert(!opt_showSystemDialog || (cr.isWindows && destination.isLocal),318             'Implemented for Windows only');319      var ticket = {320        'pageRange': printTicketStore.pageRange.getDocumentPageRanges(),321        'mediaSize': printTicketStore.mediaSize.getValue(),322        'pageCount': printTicketStore.pageRange.getPageNumberSet().size,323        'landscape': printTicketStore.landscape.getValue(),324        'color': this.getNativeColorModel_(destination, printTicketStore.color),325        'headerFooterEnabled': printTicketStore.headerFooter.getValue(),326        'marginsType': printTicketStore.marginsType.getValue(),327        'generateDraftData': true, // TODO(rltoscano): What should this be?328        'duplex': printTicketStore.duplex.getValue() ?329            NativeLayer.DuplexMode.LONG_EDGE : NativeLayer.DuplexMode.SIMPLEX,330        'copies': printTicketStore.copies.getValueAsNumber(),331        'collate': printTicketStore.collate.getValue(),332        'shouldPrintBackgrounds': printTicketStore.cssBackground.getValue(),333        'shouldPrintSelectionOnly': printTicketStore.selectionOnly.getValue(),334        'previewModifiable': documentInfo.isModifiable,335        'printToPDF': destination.id ==336            print_preview.Destination.GooglePromotedId.SAVE_AS_PDF,337        'printWithCloudPrint': !destination.isLocal,338        'printWithPrivet': destination.isPrivet,339        'printWithExtension': destination.isExtension,340        'deviceName': destination.id,341        'isFirstRequest': false,342        'requestID': -1,343        'fitToPageEnabled': printTicketStore.fitToPage.getValue(),344        'pageWidth': documentInfo.pageSize.width,345        'pageHeight': documentInfo.pageSize.height,346        'showSystemDialog': opt_showSystemDialog347      };348      if (!destination.isLocal) {349        // We can't set cloudPrintID if the destination is "Print with Cloud350        // Print" because the native system will try to print to Google Cloud351        // Print with this ID instead of opening a Google Cloud Print dialog.352        ticket['cloudPrintID'] = destination.id;353      }354      if (printTicketStore.marginsType.isCapabilityAvailable() &&355          printTicketStore.marginsType.isValueEqual(356              print_preview.ticket_items.MarginsType.Value.CUSTOM)) {357        var customMargins = printTicketStore.customMargins.getValue();358        var orientationEnum =359            print_preview.ticket_items.CustomMargins.Orientation;360        ticket['marginsCustom'] = {361          'marginTop': customMargins.get(orientationEnum.TOP),362          'marginRight': customMargins.get(orientationEnum.RIGHT),363          'marginBottom': customMargins.get(orientationEnum.BOTTOM),364          'marginLeft': customMargins.get(orientationEnum.LEFT)365        };366      }367      if (destination.isPrivet || destination.isExtension) {368        ticket['ticket'] = printTicketStore.createPrintTicket(destination);369        ticket['capabilities'] = JSON.stringify(destination.capabilities);370      }371      if (opt_isOpenPdfInPreview) {372        ticket['OpenPDFInPreview'] = true;373      }374      chrome.send('print', [JSON.stringify(ticket)]);375    },376    /** Requests that the current pending print request be cancelled. */377    startCancelPendingPrint: function() {378      chrome.send('cancelPendingPrintRequest');379    },380    /** Shows the system's native printing dialog. */381    startShowSystemDialog: function() {382      assert(!cr.isWindows);383      chrome.send('showSystemDialog');384    },385    /** Closes the print preview dialog. */386    startCloseDialog: function() {387      chrome.send('closePrintPreviewDialog');388      chrome.send('dialogClose');389    },390    /** Hide the print preview dialog and allow the native layer to close it. */391    startHideDialog: function() {392      chrome.send('hidePreview');393    },394    /**395     * Opens the Google Cloud Print sign-in tab. The DESTINATIONS_RELOAD event396     *     will be dispatched in response.397     * @param {boolean} addAccount Whether to open an 'add a new account' or398     *     default sign in page.399     */400    startCloudPrintSignIn: function(addAccount) {401      chrome.send('signIn', [addAccount]);402    },403    /** Navigates the user to the system printer settings interface. */404    startManageLocalDestinations: function() {405      chrome.send('manageLocalPrinters');406    },407    /**408     * Navigates the user to the Google Cloud Print management page.409     * @param {?string} user Email address of the user to open the management410     *     page for (user must be currently logged in, indeed) or {@code null}411     *     to open this page for the primary user.412     */413    startManageCloudDestinations: function(user) {414      chrome.send('manageCloudPrinters', [user || '']);415    },416    /** Forces browser to open a new tab with the given URL address. */417    startForceOpenNewTab: function(url) {418      chrome.send('forceOpenNewTab', [url]);419    },420    /**421     * @param {!Object} initialSettings Object containing all initial settings.422     */423    onSetInitialSettings_: function(initialSettings) {424      var numberFormatSymbols =425          print_preview.MeasurementSystem.parseNumberFormat(426              initialSettings['numberFormat']);427      var unitType = print_preview.MeasurementSystem.UnitType.IMPERIAL;428      if (initialSettings['measurementSystem'] != null) {429        unitType = initialSettings['measurementSystem'];430      }431      var nativeInitialSettings = new print_preview.NativeInitialSettings(432          initialSettings['printAutomaticallyInKioskMode'] || false,433          initialSettings['appKioskMode'] || false,434          initialSettings['hidePrintWithSystemDialogLink'] || false,435          numberFormatSymbols[0] || ',',436          numberFormatSymbols[1] || '.',437          unitType,438          initialSettings['previewModifiable'] || false,439          initialSettings['initiatorTitle'] || '',440          initialSettings['documentHasSelection'] || false,441          initialSettings['shouldPrintSelectionOnly'] || false,442          initialSettings['printerName'] || null,443          initialSettings['appState'] || null);444      var initialSettingsSetEvent = new Event(445          NativeLayer.EventType.INITIAL_SETTINGS_SET);446      initialSettingsSetEvent.initialSettings = nativeInitialSettings;447      this.dispatchEvent(initialSettingsSetEvent);448    },449    /**450     * Turn on the integration of Cloud Print.451     * @param {{cloudPrintURL: string, appKioskMode: string}} settings452     *     cloudPrintUrl: The URL to use for cloud print servers.453     * @private454     */455    onSetUseCloudPrint_: function(settings) {456      var cloudPrintEnableEvent = new Event(457          NativeLayer.EventType.CLOUD_PRINT_ENABLE);458      cloudPrintEnableEvent.baseCloudPrintUrl = settings['cloudPrintUrl'] || '';459      cloudPrintEnableEvent.appKioskMode = settings['appKioskMode'] || false;460      this.dispatchEvent(cloudPrintEnableEvent);461    },462    /**463     * Updates the print preview with local printers.464     * Called from PrintPreviewHandler::SetupPrinterList().465     * @param {Array} printers Array of printer info objects.466     * @private467     */468    onSetPrinters_: function(printers) {469      var localDestsSetEvent = new Event(470          NativeLayer.EventType.LOCAL_DESTINATIONS_SET);471      localDestsSetEvent.destinationInfos = printers;472      this.dispatchEvent(localDestsSetEvent);473    },474    /**475     * Called when native layer gets settings information for a requested local476     * destination.477     * @param {Object} settingsInfo printer setting information.478     * @private479     */480    onUpdateWithPrinterCapabilities_: function(settingsInfo) {481      var capsSetEvent = new Event(NativeLayer.EventType.CAPABILITIES_SET);482      capsSetEvent.settingsInfo = settingsInfo;483      this.dispatchEvent(capsSetEvent);484    },485    /**486     * Called when native layer gets settings information for a requested local487     * destination.488     * @param {string} destinationId Printer affected by error.489     * @private490     */491    onFailedToGetPrinterCapabilities_: function(destinationId) {492      var getCapsFailEvent = new Event(493          NativeLayer.EventType.GET_CAPABILITIES_FAIL);494      getCapsFailEvent.destinationId = destinationId;495      getCapsFailEvent.destinationOrigin =496          print_preview.Destination.Origin.LOCAL;497      this.dispatchEvent(getCapsFailEvent);498    },499    /**500     * Called when native layer gets settings information for a requested privet501     * destination.502     * @param {string} destinationId Printer affected by error.503     * @private504     */505    onFailedToGetPrivetPrinterCapabilities_: function(destinationId) {506      var getCapsFailEvent = new Event(507          NativeLayer.EventType.GET_CAPABILITIES_FAIL);508      getCapsFailEvent.destinationId = destinationId;509      getCapsFailEvent.destinationOrigin =510          print_preview.Destination.Origin.PRIVET;511      this.dispatchEvent(getCapsFailEvent);512    },513    /**514     * Called when native layer fails to get settings information for a515     * requested extension destination.516     * @param {string} destinationId Printer affected by error.517     * @private518     */519    onFailedToGetExtensionPrinterCapabilities_: function(destinationId) {520      var getCapsFailEvent = new Event(521          NativeLayer.EventType.GET_CAPABILITIES_FAIL);522      getCapsFailEvent.destinationId = destinationId;523      getCapsFailEvent.destinationOrigin =524          print_preview.Destination.Origin.EXTENSION;525      this.dispatchEvent(getCapsFailEvent);526    },527    /** Reloads the printer list. */528    onReloadPrintersList_: function() {529      cr.dispatchSimpleEvent(this, NativeLayer.EventType.DESTINATIONS_RELOAD);530    },531    /**532     * Called from the C++ layer.533     * Take the PDF data handed to us and submit it to the cloud, closing the534     * print preview dialog once the upload is successful.535     * @param {string} data Data to send as the print job.536     * @private537     */538    onPrintToCloud_: function(data) {539      var printToCloudEvent = new Event(540          NativeLayer.EventType.PRINT_TO_CLOUD);541      printToCloudEvent.data = data;542      this.dispatchEvent(printToCloudEvent);543    },544    /**545     * Called from PrintPreviewUI::OnFileSelectionCancelled to notify the print546     * preview dialog regarding the file selection cancel event.547     * @private548     */549    onFileSelectionCancelled_: function() {550      cr.dispatchSimpleEvent(this, NativeLayer.EventType.FILE_SELECTION_CANCEL);551    },552    /**553     * Called from PrintPreviewUI::OnFileSelectionCompleted to notify the print554     * preview dialog regarding the file selection completed event.555     * @private556     */557    onFileSelectionCompleted_: function() {558      // If the file selection is completed and the dialog is not already closed559      // it means that a pending print to pdf request exists.560      cr.dispatchSimpleEvent(561          this, NativeLayer.EventType.FILE_SELECTION_COMPLETE);562    },563    /**564     * Display an error message when print preview fails.565     * Called from PrintPreviewMessageHandler::OnPrintPreviewFailed().566     * @private567     */568    onPrintPreviewFailed_: function() {569      cr.dispatchSimpleEvent(570          this, NativeLayer.EventType.PREVIEW_GENERATION_FAIL);571    },572    /**573     * Display an error message when encountered invalid printer settings.574     * Called from PrintPreviewMessageHandler::OnInvalidPrinterSettings().575     * @private576     */577    onInvalidPrinterSettings_: function() {578      cr.dispatchSimpleEvent(this, NativeLayer.EventType.SETTINGS_INVALID);579    },580    /**581     * @param {{contentWidth: number, contentHeight: number, marginLeft: number,582     *          marginRight: number, marginTop: number, marginBottom: number,583     *          printableAreaX: number, printableAreaY: number,584     *          printableAreaWidth: number, printableAreaHeight: number}}585     *          pageLayout Specifies default page layout details in points.586     * @param {boolean} hasCustomPageSizeStyle Indicates whether the previewed587     *     document has a custom page size style.588     * @private589     */590    onDidGetDefaultPageLayout_: function(pageLayout, hasCustomPageSizeStyle) {591      var pageLayoutChangeEvent = new Event(592          NativeLayer.EventType.PAGE_LAYOUT_READY);593      pageLayoutChangeEvent.pageLayout = pageLayout;594      pageLayoutChangeEvent.hasCustomPageSizeStyle = hasCustomPageSizeStyle;595      this.dispatchEvent(pageLayoutChangeEvent);596    },597    /**598     * Update the page count and check the page range.599     * Called from PrintPreviewUI::OnDidGetPreviewPageCount().600     * @param {number} pageCount The number of pages.601     * @param {number} previewResponseId The preview request id that resulted in602     *      this response.603     * @private604     */605    onDidGetPreviewPageCount_: function(pageCount, previewResponseId) {606      var pageCountChangeEvent = new Event(607          NativeLayer.EventType.PAGE_COUNT_READY);608      pageCountChangeEvent.pageCount = pageCount;609      pageCountChangeEvent.previewResponseId = previewResponseId;610      this.dispatchEvent(pageCountChangeEvent);611    },612    /**613     * Notification that a print preview page has been rendered.614     * Check if the settings have changed and request a regeneration if needed.615     * Called from PrintPreviewUI::OnDidPreviewPage().616     * @param {number} pageNumber The page number, 0-based.617     * @param {number} previewUid Preview unique identifier.618     * @param {number} previewResponseId The preview request id that resulted in619     *     this response.620     * @private621     */622    onDidPreviewPage_: function(pageNumber, previewUid, previewResponseId) {623      var pagePreviewGenEvent = new Event(624          NativeLayer.EventType.PAGE_PREVIEW_READY);625      pagePreviewGenEvent.pageIndex = pageNumber;626      pagePreviewGenEvent.previewUid = previewUid;627      pagePreviewGenEvent.previewResponseId = previewResponseId;628      this.dispatchEvent(pagePreviewGenEvent);629    },630    /**631     * Notification that access token is ready.632     * @param {string} authType Type of access token.633     * @param {string} accessToken Access token.634     * @private635     */636    onDidGetAccessToken_: function(authType, accessToken) {637      var getAccessTokenEvent = new Event(638          NativeLayer.EventType.ACCESS_TOKEN_READY);639      getAccessTokenEvent.authType = authType;640      getAccessTokenEvent.accessToken = accessToken;641      this.dispatchEvent(getAccessTokenEvent);642    },643    /**644     * Update the print preview when new preview data is available.645     * Create the PDF plugin as needed.646     * Called from PrintPreviewUI::PreviewDataIsAvailable().647     * @param {number} previewUid Preview unique identifier.648     * @param {number} previewResponseId The preview request id that resulted in649     *     this response.650     * @private651     */652    onUpdatePrintPreview_: function(previewUid, previewResponseId) {653      var previewGenDoneEvent = new Event(654          NativeLayer.EventType.PREVIEW_GENERATION_DONE);655      previewGenDoneEvent.previewUid = previewUid;656      previewGenDoneEvent.previewResponseId = previewResponseId;657      this.dispatchEvent(previewGenDoneEvent);658    },659    /**660     * Updates print preset options from source PDF document.661     * Called from PrintPreviewUI::OnSetOptionsFromDocument().662     * @param {{disableScaling: boolean, copies: number,663     *          duplex: number}} options Specifies664     *     printing options according to source document presets.665     * @private666     */667    onPrintPresetOptionsFromDocument_: function(options) {668      var printPresetOptionsEvent = new Event(669          NativeLayer.EventType.PRINT_PRESET_OPTIONS);670      printPresetOptionsEvent.optionsFromDocument = options;671      this.dispatchEvent(printPresetOptionsEvent);672    },673    /**674     * Simulates a user click on the print preview dialog cancel button. Used675     * only for testing.676     * @private677     */678    autoCancelForTesting_: function() {679      var properties = {view: window, bubbles: true, cancelable: true};680      var click = new MouseEvent('click', properties);681      document.querySelector('#print-header .cancel').dispatchEvent(click);682    },683    /**684     * @param {{serviceName: string, name: string}} printer Specifies685     *     information about the printer that was added.686     * @private687     */688    onPrivetPrinterChanged_: function(printer) {689      var privetPrinterChangedEvent =690            new Event(NativeLayer.EventType.PRIVET_PRINTER_CHANGED);691      privetPrinterChangedEvent.printer = printer;692      this.dispatchEvent(privetPrinterChangedEvent);693    },694    /**695     * @param {Object} printer Specifies information about the printer that was696     *    added.697     * @private698     */699    onPrivetCapabilitiesSet_: function(printer, capabilities) {700      var privetCapabilitiesSetEvent =701            new Event(NativeLayer.EventType.PRIVET_CAPABILITIES_SET);702      privetCapabilitiesSetEvent.printer = printer;703      privetCapabilitiesSetEvent.capabilities = capabilities;704      this.dispatchEvent(privetCapabilitiesSetEvent);705    },706    /**707     * @param {string} http_error The HTTP response code or -1 if not an HTTP708     *    error.709     * @private710     */711    onPrivetPrintFailed_: function(http_error) {712      var privetPrintFailedEvent =713            new Event(NativeLayer.EventType.PRIVET_PRINT_FAILED);714      privetPrintFailedEvent.httpError = http_error;715      this.dispatchEvent(privetPrintFailedEvent);716    },717    /**718     * @param {Array<!{extensionId: string,719     *                 extensionName: string,720     *                 id: string,721     *                 name: string,722     *                 description: (string|undefined),723     *                 provisional: (boolean|undefined)}>} printers The list724     *     containing information about printers added by an extension.725     * @param {boolean} done Whether this is the final list of extension726     *     managed printers.727     */728    onExtensionPrintersAdded_: function(printers, done) {729      var event = new Event(NativeLayer.EventType.EXTENSION_PRINTERS_ADDED);730      event.printers = printers;731      event.done = done;732      this.dispatchEvent(event);733    },734    /**735     * Called when an extension responds to a request for an extension printer736     * capabilities.737     * @param {string} printerId The printer's ID.738     * @param {!Object} capabilities The reported printer capabilities.739     */740    onExtensionCapabilitiesSet_: function(printerId,741                                          capabilities) {742      var event = new Event(NativeLayer.EventType.EXTENSION_CAPABILITIES_SET);743      event.printerId = printerId;744      event.capabilities = capabilities;745      this.dispatchEvent(event);746    },747    /**748     * Called when Chrome reports that attempt to resolve a provisional749     * destination failed.750     * @param {string} destinationId The provisional destination ID.751     * @private752     */753    failedToResolveProvisionalDestination_: function(destinationId) {754      var evt = new Event(755          NativeLayer.EventType.PROVISIONAL_DESTINATION_RESOLVED);756      evt.provisionalId = destinationId;757      evt.destination = null;758      this.dispatchEvent(evt);759    },760    /**761     * Called when Chrome reports that a provisional destination has been762     * successfully resolved.763     * Currently used only for extension provided destinations.764     * @param {string} provisionalDestinationId The provisional destination id.765     * @param {!{extensionId: string,766     *           extensionName: string,767     *           id: string,768     *           name: string,769     *           description: (string|undefined)}} destinationInfo The resolved770     *     destination info.771     * @private772     */773    onProvisionalDestinationResolved_: function(provisionalDestinationId,774                                                destinationInfo) {775      var evt = new Event(776          NativeLayer.EventType.PROVISIONAL_DESTINATION_RESOLVED);777      evt.provisionalId = provisionalDestinationId;778      evt.destination = destinationInfo;779      this.dispatchEvent(evt);780    },781   /**782     * Allows for onManipulateSettings to be called783     * from the native layer.784     * @private785     */786    onEnableManipulateSettingsForTest_: function() {787      global.onManipulateSettingsForTest =788          this.onManipulateSettingsForTest_.bind(this);789    },790    /**791     * Dispatches an event to print_preview.js to change792     * a particular setting for print preview.793     * @param {!print_preview.PreviewSettings} settings Object containing the794     *     value to be changed and that value should be set to.795     * @private796     */797    onManipulateSettingsForTest_: function(settings) {798      var manipulateSettingsEvent =799          new Event(NativeLayer.EventType.MANIPULATE_SETTINGS_FOR_TEST);800      manipulateSettingsEvent.settings = settings;801      this.dispatchEvent(manipulateSettingsEvent);802    },803    /**804     * Sends a message to the test, letting it know that an805     * option has been set to a particular value and that the change has806     * finished modifying the preview area.807     */808    previewReadyForTest: function() {809      if (global.onManipulateSettingsForTest)810        chrome.send('UILoadedForTest');811    },812    /**813     * Notifies the test that the option it tried to change814     * had not been changed successfully.815     */816    previewFailedForTest: function() {817      if (global.onManipulateSettingsForTest)818        chrome.send('UIFailedLoadingForTest');819    }820  };821  /**822   * Initial settings retrieved from the native layer.823   * @param {boolean} isInKioskAutoPrintMode Whether the print preview should be824   *     in auto-print mode.825   * @param {boolean} isInAppKioskMode Whether the print preview is in App Kiosk826   *     mode.827   * @param {string} thousandsDelimeter Character delimeter of thousands digits.828   * @param {string} decimalDelimeter Character delimeter of the decimal point.829   * @param {!print_preview.MeasurementSystem.UnitType} unitType Unit type of830   *     local machine's measurement system.831   * @param {boolean} isDocumentModifiable Whether the document to print is832   *     modifiable.833   * @param {string} documentTitle Title of the document.834   * @param {boolean} documentHasSelection Whether the document has selected835   *     content.836   * @param {boolean} selectionOnly Whether only selected content should be837   *     printed.838   * @param {?string} systemDefaultDestinationId ID of the system default839   *     destination.840   * @param {?string} serializedAppStateStr Serialized app state.841   * @constructor842   */843  function NativeInitialSettings(844      isInKioskAutoPrintMode,845      isInAppKioskMode,846      hidePrintWithSystemDialogLink,847      thousandsDelimeter,848      decimalDelimeter,849      unitType,850      isDocumentModifiable,851      documentTitle,852      documentHasSelection,853      selectionOnly,854      systemDefaultDestinationId,855      serializedAppStateStr) {856    /**857     * Whether the print preview should be in auto-print mode.858     * @type {boolean}859     * @private860     */861    this.isInKioskAutoPrintMode_ = isInKioskAutoPrintMode;862    /**863     * Whether the print preview should switch to App Kiosk mode.864     * @type {boolean}865     * @private866     */867    this.isInAppKioskMode_ = isInAppKioskMode;868    /**869     * Whether we should hide the link which shows the system print dialog.870     * @type {boolean}871     * @private872     */873    this.hidePrintWithSystemDialogLink_ = hidePrintWithSystemDialogLink;874    /**875     * Character delimeter of thousands digits.876     * @type {string}877     * @private878     */879    this.thousandsDelimeter_ = thousandsDelimeter;880    /**881     * Character delimeter of the decimal point.882     * @type {string}883     * @private884     */885    this.decimalDelimeter_ = decimalDelimeter;886    /**887     * Unit type of local machine's measurement system.888     * @type {string}889     * @private890     */891    this.unitType_ = unitType;892    /**893     * Whether the document to print is modifiable.894     * @type {boolean}895     * @private896     */897    this.isDocumentModifiable_ = isDocumentModifiable;898    /**899     * Title of the document.900     * @type {string}901     * @private902     */903    this.documentTitle_ = documentTitle;904    /**905     * Whether the document has selection.906     * @type {string}907     * @private908     */909    this.documentHasSelection_ = documentHasSelection;910    /**911     * Whether selection only should be printed.912     * @type {string}913     * @private914     */915    this.selectionOnly_ = selectionOnly;916    /**917     * ID of the system default destination.918     * @type {?string}919     * @private920     */921    this.systemDefaultDestinationId_ = systemDefaultDestinationId;922    /**923     * Serialized app state.924     * @type {?string}925     * @private926     */927    this.serializedAppStateStr_ = serializedAppStateStr;928  };929  NativeInitialSettings.prototype = {930    /**931     * @return {boolean} Whether the print preview should be in auto-print mode.932     */933    get isInKioskAutoPrintMode() {934      return this.isInKioskAutoPrintMode_;935    },936    /**937     * @return {boolean} Whether the print preview should switch to App Kiosk938     *     mode.939     */940    get isInAppKioskMode() {941      return this.isInAppKioskMode_;942    },943    /**944     * @return {boolean} Whether we should hide the link which shows the945           system print dialog.946     */947    get hidePrintWithSystemDialogLink() {948      return this.hidePrintWithSystemDialogLink_;949    },950    /** @return {string} Character delimeter of thousands digits. */951    get thousandsDelimeter() {952      return this.thousandsDelimeter_;953    },954    /** @return {string} Character delimeter of the decimal point. */955    get decimalDelimeter() {956      return this.decimalDelimeter_;957    },958    /**959     * @return {!print_preview.MeasurementSystem.UnitType} Unit type of local960     *     machine's measurement system.961     */962    get unitType() {963      return this.unitType_;964    },965    /** @return {boolean} Whether the document to print is modifiable. */966    get isDocumentModifiable() {967      return this.isDocumentModifiable_;968    },969    /** @return {string} Document title. */970    get documentTitle() {971      return this.documentTitle_;972    },973    /** @return {boolean} Whether the document has selection. */974    get documentHasSelection() {975      return this.documentHasSelection_;976    },977    /** @return {boolean} Whether selection only should be printed. */978    get selectionOnly() {979      return this.selectionOnly_;980    },981    /** @return {?string} ID of the system default destination. */982    get systemDefaultDestinationId() {983      return this.systemDefaultDestinationId_;984    },985    /** @return {?string} Serialized app state. */986    get serializedAppStateStr() {987      return this.serializedAppStateStr_;988    }989  };990  // Export991  return {992    NativeInitialSettings: NativeInitialSettings,993    NativeLayer: NativeLayer994  };...print_ticket_store.js
Source:print_ticket_store.js  
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4cr.define('print_preview', function() {5  'use strict';6  // TODO(rltoscano): Maybe clear print ticket when destination changes. Or7  // better yet, carry over any print ticket state that is possible. I.e. if8  // destination changes, the new destination might not support duplex anymore,9  // so we should clear the ticket's isDuplexEnabled state.10  /**11   * Storage of the print ticket and document statistics. Dispatches events when12   * the contents of the print ticket or document statistics change. Also13   * handles validation of the print ticket against destination capabilities and14   * against the document.15   * @param {!print_preview.DestinationStore} destinationStore Used to16   *     understand which printer is selected.17   * @param {!print_preview.AppState} appState Print preview application state.18   * @param {!print_preview.DocumentInfo} documentInfo Document data model.19   * @constructor20   * @extends {cr.EventTarget}21   */22  function PrintTicketStore(destinationStore, appState, documentInfo) {23    cr.EventTarget.call(this);24    /**25     * Destination store used to understand which printer is selected.26     * @type {!print_preview.DestinationStore}27     * @private28     */29    this.destinationStore_ = destinationStore;30    /**31     * App state used to persist and load ticket values.32     * @type {!print_preview.AppState}33     * @private34     */35    this.appState_ = appState;36    /**37     * Information about the document to print.38     * @type {!print_preview.DocumentInfo}39     * @private40     */41    this.documentInfo_ = documentInfo;42    /**43     * Printing capabilities of Chromium and the currently selected destination.44     * @type {!print_preview.CapabilitiesHolder}45     * @private46     */47    this.capabilitiesHolder_ = new print_preview.CapabilitiesHolder();48    /**49     * Current measurement system. Used to work with margin measurements.50     * @type {!print_preview.MeasurementSystem}51     * @private52     */53    this.measurementSystem_ = new print_preview.MeasurementSystem(54        ',', '.', print_preview.MeasurementSystem.UnitType.IMPERIAL);55    /**56     * Collate ticket item.57     * @type {!print_preview.ticket_items.Collate}58     * @private59     */60    this.collate_ = new print_preview.ticket_items.Collate(61        this.appState_, this.destinationStore_);62    /**63     * Color ticket item.64     * @type {!print_preview.ticket_items.Color}65     * @private66     */67    this.color_ = new print_preview.ticket_items.Color(68        this.appState_, this.destinationStore_);69    /**70     * Copies ticket item.71     * @type {!print_preview.ticket_items.Copies}72     * @private73     */74    this.copies_ =75        new print_preview.ticket_items.Copies(this.destinationStore_);76    /**77     * DPI ticket item.78     * @type {!print_preview.ticket_items.Dpi}79     * @private80     */81    this.dpi_ = new print_preview.ticket_items.Dpi(82        this.appState_, this.destinationStore_);83    /**84     * Duplex ticket item.85     * @type {!print_preview.ticket_items.Duplex}86     * @private87     */88    this.duplex_ = new print_preview.ticket_items.Duplex(89        this.appState_, this.destinationStore_);90    /**91     * Page range ticket item.92     * @type {!print_preview.ticket_items.PageRange}93     * @private94     */95    this.pageRange_ =96        new print_preview.ticket_items.PageRange(this.documentInfo_);97    /**98     * Custom margins ticket item.99     * @type {!print_preview.ticket_items.CustomMargins}100     * @private101     */102    this.customMargins_ = new print_preview.ticket_items.CustomMargins(103        this.appState_, this.documentInfo_);104    /**105     * Margins type ticket item.106     * @type {!print_preview.ticket_items.MarginsType}107     * @private108     */109    this.marginsType_ = new print_preview.ticket_items.MarginsType(110        this.appState_, this.documentInfo_, this.customMargins_);111    /**112     * Media size ticket item.113     * @type {!print_preview.ticket_items.MediaSize}114     * @private115     */116    this.mediaSize_ = new print_preview.ticket_items.MediaSize(117        this.appState_,118        this.destinationStore_,119        this.documentInfo_,120        this.marginsType_,121        this.customMargins_);122    /**123     * Landscape ticket item.124     * @type {!print_preview.ticket_items.Landscape}125     * @private126     */127    this.landscape_ = new print_preview.ticket_items.Landscape(128        this.appState_,129        this.destinationStore_,130        this.documentInfo_,131        this.marginsType_,132        this.customMargins_);133    /**134     * Header-footer ticket item.135     * @type {!print_preview.ticket_items.HeaderFooter}136     * @private137     */138    this.headerFooter_ = new print_preview.ticket_items.HeaderFooter(139        this.appState_,140        this.documentInfo_,141        this.marginsType_,142        this.customMargins_);143    /**144     * Fit-to-page ticket item.145     * @type {!print_preview.ticket_items.FitToPage}146     * @private147     */148    this.fitToPage_ = new print_preview.ticket_items.FitToPage(149        this.documentInfo_, this.destinationStore_);150    /**151     * Print CSS backgrounds ticket item.152     * @type {!print_preview.ticket_items.CssBackground}153     * @private154     */155    this.cssBackground_ = new print_preview.ticket_items.CssBackground(156        this.appState_, this.documentInfo_);157    /**158     * Print selection only ticket item.159     * @type {!print_preview.ticket_items.SelectionOnly}160     * @private161     */162    this.selectionOnly_ =163        new print_preview.ticket_items.SelectionOnly(this.documentInfo_);164    /**165     * Vendor ticket items.166     * @type {!print_preview.ticket_items.VendorItems}167     * @private168     */169    this.vendorItems_ = new print_preview.ticket_items.VendorItems(170        this.appState_, this.destinationStore_);171    /**172     * Keeps track of event listeners for the print ticket store.173     * @type {!EventTracker}174     * @private175     */176    this.tracker_ = new EventTracker();177    /**178     * Whether the print preview has been initialized.179     * @type {boolean}180     * @private181     */182    this.isInitialized_ = false;183    this.addEventListeners_();184  };185  /**186   * Event types dispatched by the print ticket store.187   * @enum {string}188   */189  PrintTicketStore.EventType = {190    CAPABILITIES_CHANGE: 'print_preview.PrintTicketStore.CAPABILITIES_CHANGE',191    DOCUMENT_CHANGE: 'print_preview.PrintTicketStore.DOCUMENT_CHANGE',192    INITIALIZE: 'print_preview.PrintTicketStore.INITIALIZE',193    TICKET_CHANGE: 'print_preview.PrintTicketStore.TICKET_CHANGE'194  };195  PrintTicketStore.prototype = {196    __proto__: cr.EventTarget.prototype,197    /**198     * Whether the print preview has been initialized.199     * @type {boolean}200     */201    get isInitialized() {202      return this.isInitialized_;203    },204    get collate() {205      return this.collate_;206    },207    get color() {208      return this.color_;209    },210    get copies() {211      return this.copies_;212    },213    get cssBackground() {214      return this.cssBackground_;215    },216    get customMargins() {217      return this.customMargins_;218    },219    get dpi() {220      return this.dpi_;221    },222    get duplex() {223      return this.duplex_;224    },225    get fitToPage() {226      return this.fitToPage_;227    },228    get headerFooter() {229      return this.headerFooter_;230    },231    get mediaSize() {232      return this.mediaSize_;233    },234    get landscape() {235      return this.landscape_;236    },237    get marginsType() {238      return this.marginsType_;239    },240    get pageRange() {241      return this.pageRange_;242    },243    get selectionOnly() {244      return this.selectionOnly_;245    },246    get vendorItems() {247      return this.vendorItems_;248    },249    /**250     * @return {!print_preview.MeasurementSystem} Measurement system of the251     *     local system.252     */253    get measurementSystem() {254      return this.measurementSystem_;255    },256    /**257     * Initializes the print ticket store. Dispatches an INITIALIZE event.258     * @param {string} thousandsDelimeter Delimeter of the thousands place.259     * @param {string} decimalDelimeter Delimeter of the decimal point.260     * @param {!print_preview.MeasurementSystem.UnitType} unitType Type of unit261     *     of the local measurement system.262     * @param {boolean} selectionOnly Whether only selected content should be263     *     printed.264     */265    init: function(266        thousandsDelimeter, decimalDelimeter, unitType, selectionOnly) {267      this.measurementSystem_.setSystem(thousandsDelimeter, decimalDelimeter,268                                        unitType);269      this.selectionOnly_.updateValue(selectionOnly);270      // Initialize ticket with user's previous values.271      if (this.appState_.hasField(272          print_preview.AppState.Field.IS_COLOR_ENABLED)) {273        this.color_.updateValue(274            /** @type {!Object} */(this.appState_.getField(275            print_preview.AppState.Field.IS_COLOR_ENABLED)));276      }277      if (this.appState_.hasField(print_preview.AppState.Field.DPI)) {278        this.dpi_.updateValue(279            /** @type {!Object} */(this.appState_.getField(280            print_preview.AppState.Field.DPI)));281      }282      if (this.appState_.hasField(283          print_preview.AppState.Field.IS_DUPLEX_ENABLED)) {284        this.duplex_.updateValue(285            /** @type {!Object} */(this.appState_.getField(286            print_preview.AppState.Field.IS_DUPLEX_ENABLED)));287      }288      if (this.appState_.hasField(print_preview.AppState.Field.MEDIA_SIZE)) {289        this.mediaSize_.updateValue(290            /** @type {!Object} */(this.appState_.getField(291            print_preview.AppState.Field.MEDIA_SIZE)));292      }293      if (this.appState_.hasField(294          print_preview.AppState.Field.IS_LANDSCAPE_ENABLED)) {295        this.landscape_.updateValue(296            /** @type {!Object} */(this.appState_.getField(297            print_preview.AppState.Field.IS_LANDSCAPE_ENABLED)));298      }299      // Initialize margins after landscape because landscape may reset margins.300      if (this.appState_.hasField(print_preview.AppState.Field.MARGINS_TYPE)) {301        this.marginsType_.updateValue(302            /** @type {!Object} */(this.appState_.getField(303            print_preview.AppState.Field.MARGINS_TYPE)));304      }305      if (this.appState_.hasField(306          print_preview.AppState.Field.CUSTOM_MARGINS)) {307        this.customMargins_.updateValue(308            /** @type {!Object} */(this.appState_.getField(309            print_preview.AppState.Field.CUSTOM_MARGINS)));310      }311      if (this.appState_.hasField(312          print_preview.AppState.Field.IS_HEADER_FOOTER_ENABLED)) {313        this.headerFooter_.updateValue(314            /** @type {!Object} */(this.appState_.getField(315            print_preview.AppState.Field.IS_HEADER_FOOTER_ENABLED)));316      }317      if (this.appState_.hasField(318          print_preview.AppState.Field.IS_COLLATE_ENABLED)) {319        this.collate_.updateValue(320            /** @type {!Object} */(this.appState_.getField(321            print_preview.AppState.Field.IS_COLLATE_ENABLED)));322      }323      if (this.appState_.hasField(324          print_preview.AppState.Field.IS_CSS_BACKGROUND_ENABLED)) {325        this.cssBackground_.updateValue(326            /** @type {!Object} */(this.appState_.getField(327            print_preview.AppState.Field.IS_CSS_BACKGROUND_ENABLED)));328      }329      if (this.appState_.hasField(330          print_preview.AppState.Field.VENDOR_OPTIONS)) {331        this.vendorItems_.updateValue(332            /** @type {!Object<string>} */(this.appState_.getField(333            print_preview.AppState.Field.VENDOR_OPTIONS)));334    }335    },336    /**337     * @return {boolean} {@code true} if the stored print ticket is valid,338     *     {@code false} otherwise.339     */340    isTicketValid: function() {341      return this.isTicketValidForPreview() &&342          (!this.copies_.isCapabilityAvailable() || this.copies_.isValid()) &&343          (!this.pageRange_.isCapabilityAvailable() ||344              this.pageRange_.isValid());345    },346    /** @return {boolean} Whether the ticket is valid for preview generation. */347    isTicketValidForPreview: function() {348      return (!this.marginsType_.isCapabilityAvailable() ||349              !this.marginsType_.isValueEqual(350                  print_preview.ticket_items.MarginsType.Value.CUSTOM) ||351              this.customMargins_.isValid());352    },353    /**354     * Creates an object that represents a Google Cloud Print print ticket.355     * @param {!print_preview.Destination} destination Destination to print to.356     * @return {!Object} Google Cloud Print print ticket.357     */358    createPrintTicket: function(destination) {359      assert(!destination.isLocal ||360             destination.isPrivet || destination.isExtension,361             'Trying to create a Google Cloud Print print ticket for a local ' +362                 ' non-privet and non-extension destination');363      assert(destination.capabilities,364             'Trying to create a Google Cloud Print print ticket for a ' +365                 'destination with no print capabilities');366      var cjt = {367        version: '1.0',368        print: {}369      };370      if (this.collate.isCapabilityAvailable() && this.collate.isUserEdited()) {371        cjt.print.collate = {collate: this.collate.getValue()};372      }373      if (this.color.isCapabilityAvailable() && this.color.isUserEdited()) {374        var selectedOption = this.color.getSelectedOption();375        if (!selectedOption) {376          console.error('Could not find correct color option');377        } else {378          cjt.print.color = {type: selectedOption.type};379          if (selectedOption.hasOwnProperty('vendor_id')) {380            cjt.print.color.vendor_id = selectedOption.vendor_id;381          }382        }383      }384      if (this.copies.isCapabilityAvailable() && this.copies.isUserEdited()) {385        cjt.print.copies = {copies: this.copies.getValueAsNumber()};386      }387      if (this.duplex.isCapabilityAvailable() && this.duplex.isUserEdited()) {388        cjt.print.duplex =389            {type: this.duplex.getValue() ? 'LONG_EDGE' : 'NO_DUPLEX'};390      }391      if (this.mediaSize.isCapabilityAvailable()) {392        var value = this.mediaSize.getValue();393        cjt.print.media_size = {394          width_microns: value.width_microns,395          height_microns: value.height_microns,396          is_continuous_feed: value.is_continuous_feed,397          vendor_id: value.vendor_id398        };399      }400      if (!this.landscape.isCapabilityAvailable()) {401        // In this case "orientation" option is hidden from user, so user can't402        // adjust it for page content, see Landscape.isCapabilityAvailable().403        // We can improve results if we set AUTO here.404        if (this.landscape.hasOption('AUTO'))405          cjt.print.page_orientation = { type: 'AUTO' };406      } else if (this.landscape.isUserEdited()) {407        cjt.print.page_orientation =408            {type: this.landscape.getValue() ? 'LANDSCAPE' : 'PORTRAIT'};409      }410      if (this.dpi.isCapabilityAvailable()) {411        var value = this.dpi.getValue();412        cjt.print.dpi = {413          horizontal_dpi: value.horizontal_dpi,414          vertical_dpi: value.vertical_dpi,415          vendor_id: value.vendor_id416        };417      }418      if (this.vendorItems.isCapabilityAvailable() &&419          this.vendorItems.isUserEdited()) {420        var items = this.vendorItems.ticketItems;421        cjt.print.vendor_ticket_item = [];422        for (var itemId in items) {423          if (items.hasOwnProperty(itemId)) {424            cjt.print.vendor_ticket_item.push(425                {id: itemId, value: items[itemId]});426          }427        }428      }429      return JSON.stringify(cjt);430    },431    /**432     * Adds event listeners for the print ticket store.433     * @private434     */435    addEventListeners_: function() {436      this.tracker_.add(437          this.destinationStore_,438          print_preview.DestinationStore.EventType.DESTINATION_SELECT,439          this.onDestinationSelect_.bind(this));440      this.tracker_.add(441          this.destinationStore_,442          print_preview.DestinationStore.EventType.443              SELECTED_DESTINATION_CAPABILITIES_READY,444          this.onSelectedDestinationCapabilitiesReady_.bind(this));445      this.tracker_.add(446          this.destinationStore_,447          print_preview.DestinationStore.EventType.448              CACHED_SELECTED_DESTINATION_INFO_READY,449          this.onSelectedDestinationCapabilitiesReady_.bind(this));450      // TODO(rltoscano): Print ticket store shouldn't be re-dispatching these451      // events, the consumers of the print ticket store events should listen452      // for the events from document info instead. Will move this when453      // consumers are all migrated.454      this.tracker_.add(455          this.documentInfo_,456          print_preview.DocumentInfo.EventType.CHANGE,457          this.onDocumentInfoChange_.bind(this));458    },459    /**460     * Called when the destination selected.461     * @private462     */463    onDestinationSelect_: function() {464      // Reset user selection for certain ticket items.465      if (this.capabilitiesHolder_.get() != null) {466        this.customMargins_.updateValue(null);467        if (this.marginsType_.getValue() ==468            print_preview.ticket_items.MarginsType.Value.CUSTOM) {469          this.marginsType_.updateValue(470              print_preview.ticket_items.MarginsType.Value.DEFAULT);471        }472        this.vendorItems_.updateValue({});473      }474    },475    /**476     * Called when the capabilities of the selected destination are ready.477     * @private478     */479    onSelectedDestinationCapabilitiesReady_: function() {480      var caps = assert(481          this.destinationStore_.selectedDestination.capabilities);482      var isFirstUpdate = this.capabilitiesHolder_.get() == null;483      this.capabilitiesHolder_.set(caps);484      if (isFirstUpdate) {485        this.isInitialized_ = true;486        cr.dispatchSimpleEvent(this, PrintTicketStore.EventType.INITIALIZE);487      } else {488        cr.dispatchSimpleEvent(489            this, PrintTicketStore.EventType.CAPABILITIES_CHANGE);490      }491    },492    /**493     * Called when document data model has changed. Dispatches a print ticket494     * store event.495     * @private496     */497    onDocumentInfoChange_: function() {498      cr.dispatchSimpleEvent(this, PrintTicketStore.EventType.DOCUMENT_CHANGE);499    },500  };501  // Export502  return {503    PrintTicketStore: PrintTicketStore504  };...print_header.js
Source:print_header.js  
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4cr.define('print_preview', function() {5  'use strict';6  /**7   * Creates a PrintHeader object. This object encapsulates all the elements8   * and logic related to the top part of the left pane in print_preview.html.9   * @param {!print_preview.PrintTicketStore} printTicketStore Used to read10   *     information about the document.11   * @param {!print_preview.DestinationStore} destinationStore Used to get the12   *     selected destination.13   * @constructor14   * @extends {print_preview.Component}15   */16  function PrintHeader(printTicketStore, destinationStore) {17    print_preview.Component.call(this);18    /**19     * Used to read information about the document.20     * @type {!print_preview.PrintTicketStore}21     * @private22     */23    this.printTicketStore_ = printTicketStore;24    /**25     * Used to get the selected destination.26     * @type {!print_preview.DestinationStore}27     * @private28     */29    this.destinationStore_ = destinationStore;30    /**31     * Whether the component is enabled.32     * @type {boolean}33     * @private34     */35    this.isEnabled_ = true;36    /**37     * Whether the print button is enabled.38     * @type {boolean}39     * @private40     */41    this.isPrintButtonEnabled_ = true;42  };43  /**44   * Event types dispatched by the print header.45   * @enum {string}46   */47  PrintHeader.EventType = {48    PRINT_BUTTON_CLICK: 'print_preview.PrintHeader.PRINT_BUTTON_CLICK',49    CANCEL_BUTTON_CLICK: 'print_preview.PrintHeader.CANCEL_BUTTON_CLICK'50  };51  PrintHeader.prototype = {52    __proto__: print_preview.Component.prototype,53    set isEnabled(isEnabled) {54      this.isEnabled_ = isEnabled;55      this.updatePrintButtonEnabledState_();56      this.isCancelButtonEnabled = isEnabled;57    },58    get isPrintButtonEnabled() {59      return !this.getChildElement('button.print').disabled;60    },61    set isPrintButtonEnabled(isEnabled) {62      this.isPrintButtonEnabled_ = isEnabled;63      this.updatePrintButtonEnabledState_();64    },65    set isCancelButtonEnabled(isEnabled) {66      this.getChildElement('button.cancel').disabled = !isEnabled;67    },68    /** @param {string} message Error message to display in the print header. */69    setErrorMessage: function(message) {70      var summaryEl = this.getChildElement('.summary');71      summaryEl.innerHTML = '';72      summaryEl.textContent = message;73      this.getChildElement('button.print').classList.toggle('loading', false);74      this.getChildElement('button.cancel').classList.toggle('loading', false);75    },76    /** @override */77    decorateInternal: function() {78      cr.ui.reverseButtonStrips(this.getElement());79    },80    /** @override */81    enterDocument: function() {82      print_preview.Component.prototype.enterDocument.call(this);83      // User events84      this.tracker.add(85          this.getChildElement('button.cancel'),86          'click',87          this.onCancelButtonClick_.bind(this));88      this.tracker.add(89          this.getChildElement('button.print'),90          'click',91          this.onPrintButtonClick_.bind(this));92      // Data events.93      this.tracker.add(94          this.printTicketStore_,95          print_preview.PrintTicketStore.EventType.INITIALIZE,96          this.onTicketChange_.bind(this));97      this.tracker.add(98          this.printTicketStore_,99          print_preview.PrintTicketStore.EventType.DOCUMENT_CHANGE,100          this.onTicketChange_.bind(this));101      this.tracker.add(102          this.printTicketStore_,103          print_preview.PrintTicketStore.EventType.TICKET_CHANGE,104          this.onTicketChange_.bind(this));105      this.tracker.add(106          this.destinationStore_,107          print_preview.DestinationStore.EventType.DESTINATION_SELECT,108          this.onDestinationSelect_.bind(this));109      this.tracker.add(110          this.printTicketStore_.copies,111          print_preview.ticket_items.TicketItem.EventType.CHANGE,112          this.onTicketChange_.bind(this));113      this.tracker.add(114          this.printTicketStore_.duplex,115          print_preview.ticket_items.TicketItem.EventType.CHANGE,116          this.onTicketChange_.bind(this));117      this.tracker.add(118          this.printTicketStore_.pageRange,119          print_preview.ticket_items.TicketItem.EventType.CHANGE,120          this.onTicketChange_.bind(this));121    },122    /**123     * Updates Print Button state.124     * @private125     */126    updatePrintButtonEnabledState_: function() {127      this.getChildElement('button.print').disabled =128          this.destinationStore_.selectedDestination == null ||129          !this.isEnabled_ ||130          !this.isPrintButtonEnabled_ ||131          !this.printTicketStore_.isTicketValid();132    },133    /**134     * Updates the summary element based on the currently selected user options.135     * @private136     */137    updateSummary_: function() {138      if (!this.printTicketStore_.isTicketValid()) {139        this.getChildElement('.summary').innerHTML = '';140        return;141      }142      var summaryLabel =143          loadTimeData.getString('printPreviewSheetsLabelSingular');144      var pagesLabel = loadTimeData.getString('printPreviewPageLabelPlural');145      var saveToPdf = this.destinationStore_.selectedDestination &&146          this.destinationStore_.selectedDestination.id ==147              print_preview.Destination.GooglePromotedId.SAVE_AS_PDF;148      if (saveToPdf) {149        summaryLabel = loadTimeData.getString('printPreviewPageLabelSingular');150      }151      var numPages = this.printTicketStore_.pageRange.getPageNumberSet().size;152      var numSheets = numPages;153      if (!saveToPdf && this.printTicketStore_.duplex.getValue()) {154        numSheets = Math.ceil(numPages / 2);155      }156      var copies = this.printTicketStore_.copies.getValueAsNumber();157      numSheets *= copies;158      numPages *= copies;159      if (numSheets > 1) {160        summaryLabel = saveToPdf ? pagesLabel :161            loadTimeData.getString('printPreviewSheetsLabelPlural');162      }163      var html;164      var label;165      if (numPages != numSheets) {166        html = loadTimeData.getStringF('printPreviewSummaryFormatLong',167                                       '<b>' + numSheets + '</b>',168                                       '<b>' + summaryLabel + '</b>',169                                       numPages,170                                       pagesLabel);171        label = loadTimeData.getStringF('printPreviewSummaryFormatLong',172                                        numSheets, summaryLabel,173                                        numPages, pagesLabel);174      } else {175        html = loadTimeData.getStringF('printPreviewSummaryFormatShort',176                                       '<b>' + numSheets + '</b>',177                                       '<b>' + summaryLabel + '</b>');178        label = loadTimeData.getStringF('printPreviewSummaryFormatShort',179                                        numSheets, summaryLabel);180      }181      // Removing extra spaces from within the string.182      html = html.replace(/\s{2,}/g, ' ');183      var summary = this.getChildElement('.summary');184      summary.innerHTML = html;185      summary.setAttribute('aria-label', label);186    },187    /**188     * Called when the print button is clicked. Dispatches a PRINT_DOCUMENT189     * common event.190     * @private191     */192    onPrintButtonClick_: function() {193      if (this.destinationStore_.selectedDestination.id !=194          print_preview.Destination.GooglePromotedId.SAVE_AS_PDF) {195        this.getChildElement('button.print').classList.add('loading');196        this.getChildElement('button.cancel').classList.add('loading');197        this.getChildElement('.summary').innerHTML =198            loadTimeData.getString('printing');199      }200      cr.dispatchSimpleEvent(this, PrintHeader.EventType.PRINT_BUTTON_CLICK);201    },202    /**203     * Called when the cancel button is clicked. Dispatches a204     * CLOSE_PRINT_PREVIEW event.205     * @private206     */207    onCancelButtonClick_: function() {208      cr.dispatchSimpleEvent(this, PrintHeader.EventType.CANCEL_BUTTON_CLICK);209    },210    /**211     * Called when a new destination is selected. Updates the text on the print212     * button.213     * @private214     */215    onDestinationSelect_: function() {216      var isSaveLabel = this.destinationStore_.selectedDestination &&217          (this.destinationStore_.selectedDestination.id ==218               print_preview.Destination.GooglePromotedId.SAVE_AS_PDF ||219           this.destinationStore_.selectedDestination.id ==220               print_preview.Destination.GooglePromotedId.DOCS);221      this.getChildElement('button.print').textContent =222          loadTimeData.getString(isSaveLabel ? 'saveButton' : 'printButton');223      if (this.destinationStore_.selectedDestination) {224        this.getChildElement('button.print').focus();225      }226    },227    /**228     * Called when the print ticket has changed. Disables the print button if229     * any of the settings are invalid.230     * @private231     */232    onTicketChange_: function() {233      this.updatePrintButtonEnabledState_();234      this.updateSummary_();235      if (document.activeElement == null ||236          document.activeElement == document.body) {237        this.getChildElement('button.print').focus();238      }239    }240  };241  // Export242  return {243    PrintHeader: PrintHeader244  };...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
