Home | History | Annotate | Download | only in print_preview
      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 be
      3 // found in the LICENSE file.
      4 
      5 cr.define('print_preview', function() {
      6   'use strict';
      7 
      8   /**
      9    * An interface to the native Chromium printing system layer.
     10    * @constructor
     11    * @extends {cr.EventTarget}
     12    */
     13   function NativeLayer() {
     14     cr.EventTarget.call(this);
     15 
     16     // Bind global handlers
     17     global['setInitialSettings'] = this.onSetInitialSettings_.bind(this);
     18     global['setUseCloudPrint'] = this.onSetUseCloudPrint_.bind(this);
     19     global['setPrinters'] = this.onSetPrinters_.bind(this);
     20     global['updateWithPrinterCapabilities'] =
     21         this.onUpdateWithPrinterCapabilities_.bind(this);
     22     global['failedToGetPrinterCapabilities'] =
     23         this.onFailedToGetPrinterCapabilities_.bind(this);
     24     global['failedToGetPrivetPrinterCapabilities'] =
     25       this.onFailedToGetPrivetPrinterCapabilities_.bind(this);
     26     global['reloadPrintersList'] = this.onReloadPrintersList_.bind(this);
     27     global['printToCloud'] = this.onPrintToCloud_.bind(this);
     28     global['fileSelectionCancelled'] =
     29         this.onFileSelectionCancelled_.bind(this);
     30     global['fileSelectionCompleted'] =
     31         this.onFileSelectionCompleted_.bind(this);
     32     global['printPreviewFailed'] = this.onPrintPreviewFailed_.bind(this);
     33     global['invalidPrinterSettings'] =
     34         this.onInvalidPrinterSettings_.bind(this);
     35     global['onDidGetDefaultPageLayout'] =
     36         this.onDidGetDefaultPageLayout_.bind(this);
     37     global['onDidGetPreviewPageCount'] =
     38         this.onDidGetPreviewPageCount_.bind(this);
     39     global['onDidPreviewPage'] = this.onDidPreviewPage_.bind(this);
     40     global['updatePrintPreview'] = this.onUpdatePrintPreview_.bind(this);
     41     global['printScalingDisabledForSourcePDF'] =
     42         this.onPrintScalingDisabledForSourcePDF_.bind(this);
     43     global['onDidGetAccessToken'] = this.onDidGetAccessToken_.bind(this);
     44     global['autoCancelForTesting'] = this.autoCancelForTesting_.bind(this);
     45     global['onPrivetPrinterChanged'] = this.onPrivetPrinterChanged_.bind(this);
     46     global['onPrivetCapabilitiesSet'] =
     47         this.onPrivetCapabilitiesSet_.bind(this);
     48     global['onPrivetPrintFailed'] = this.onPrivetPrintFailed_.bind(this);
     49   };
     50 
     51   /**
     52    * Event types dispatched from the Chromium native layer.
     53    * @enum {string}
     54    * @const
     55    */
     56   NativeLayer.EventType = {
     57     ACCESS_TOKEN_READY: 'print_preview.NativeLayer.ACCESS_TOKEN_READY',
     58     CAPABILITIES_SET: 'print_preview.NativeLayer.CAPABILITIES_SET',
     59     CLOUD_PRINT_ENABLE: 'print_preview.NativeLayer.CLOUD_PRINT_ENABLE',
     60     DESTINATIONS_RELOAD: 'print_preview.NativeLayer.DESTINATIONS_RELOAD',
     61     DISABLE_SCALING: 'print_preview.NativeLayer.DISABLE_SCALING',
     62     FILE_SELECTION_CANCEL: 'print_preview.NativeLayer.FILE_SELECTION_CANCEL',
     63     FILE_SELECTION_COMPLETE:
     64         'print_preview.NativeLayer.FILE_SELECTION_COMPLETE',
     65     GET_CAPABILITIES_FAIL: 'print_preview.NativeLayer.GET_CAPABILITIES_FAIL',
     66     INITIAL_SETTINGS_SET: 'print_preview.NativeLayer.INITIAL_SETTINGS_SET',
     67     LOCAL_DESTINATIONS_SET: 'print_preview.NativeLayer.LOCAL_DESTINATIONS_SET',
     68     PAGE_COUNT_READY: 'print_preview.NativeLayer.PAGE_COUNT_READY',
     69     PAGE_LAYOUT_READY: 'print_preview.NativeLayer.PAGE_LAYOUT_READY',
     70     PAGE_PREVIEW_READY: 'print_preview.NativeLayer.PAGE_PREVIEW_READY',
     71     PREVIEW_GENERATION_DONE:
     72         'print_preview.NativeLayer.PREVIEW_GENERATION_DONE',
     73     PREVIEW_GENERATION_FAIL:
     74         'print_preview.NativeLayer.PREVIEW_GENERATION_FAIL',
     75     PRINT_TO_CLOUD: 'print_preview.NativeLayer.PRINT_TO_CLOUD',
     76     SETTINGS_INVALID: 'print_preview.NativeLayer.SETTINGS_INVALID',
     77     PRIVET_PRINTER_CHANGED: 'print_preview.NativeLayer.PRIVET_PRINTER_CHANGED',
     78     PRIVET_CAPABILITIES_SET:
     79         'print_preview.NativeLayer.PRIVET_CAPABILITIES_SET',
     80     PRIVET_PRINT_FAILED: 'print_preview.NativeLayer.PRIVET_PRINT_FAILED'
     81   };
     82 
     83   /**
     84    * Constant values matching printing::DuplexMode enum.
     85    * @enum {number}
     86    */
     87   NativeLayer.DuplexMode = {
     88     SIMPLEX: 0,
     89     LONG_EDGE: 1,
     90     UNKNOWN_DUPLEX_MODE: -1
     91   };
     92 
     93   /**
     94    * Enumeration of color modes used by Chromium.
     95    * @enum {number}
     96    * @private
     97    */
     98   NativeLayer.ColorMode_ = {
     99     GRAY: 1,
    100     COLOR: 2
    101   };
    102 
    103   /**
    104    * Version of the serialized state of the print preview.
    105    * @type {number}
    106    * @const
    107    * @private
    108    */
    109   NativeLayer.SERIALIZED_STATE_VERSION_ = 1;
    110 
    111   NativeLayer.prototype = {
    112     __proto__: cr.EventTarget.prototype,
    113 
    114     /**
    115      * Requests access token for cloud print requests.
    116      * @param {string} authType type of access token.
    117      */
    118     startGetAccessToken: function(authType) {
    119       chrome.send('getAccessToken', [authType]);
    120     },
    121 
    122     /** Gets the initial settings to initialize the print preview with. */
    123     startGetInitialSettings: function() {
    124       chrome.send('getInitialSettings');
    125     },
    126 
    127     /**
    128      * Requests the system's local print destinations. A LOCAL_DESTINATIONS_SET
    129      * event will be dispatched in response.
    130      */
    131     startGetLocalDestinations: function() {
    132       chrome.send('getPrinters');
    133     },
    134 
    135     /**
    136      * Requests the network's privet print destinations. A number of
    137      * PRIVET_PRINTER_CHANGED events will be fired in response, followed by a
    138      * PRIVET_SEARCH_ENDED.
    139      */
    140     startGetPrivetDestinations: function() {
    141       chrome.send('getPrivetPrinters');
    142     },
    143 
    144     /**
    145      * Requests that the privet print stack stop searching for privet print
    146      * destinations.
    147      */
    148     stopGetPrivetDestinations: function() {
    149       chrome.send('stopGetPrivetPrinters');
    150     },
    151 
    152     /**
    153      * Requests the privet destination's printing capabilities. A
    154      * PRIVET_CAPABILITIES_SET event will be dispatched in response.
    155      * @param {string} destinationId ID of the destination.
    156      */
    157     startGetPrivetDestinationCapabilities: function(destinationId) {
    158       chrome.send('getPrivetPrinterCapabilities', [destinationId]);
    159     },
    160 
    161     /**
    162      * Requests the destination's printing capabilities. A CAPABILITIES_SET
    163      * event will be dispatched in response.
    164      * @param {string} destinationId ID of the destination.
    165      */
    166     startGetLocalDestinationCapabilities: function(destinationId) {
    167       chrome.send('getPrinterCapabilities', [destinationId]);
    168     },
    169 
    170     /**
    171      * @param {!print_preview.Destination} destination Destination to print to.
    172      * @param {!print_preview.ticket_items.Color} color Color ticket item.
    173      * @return {number} Native layer color model.
    174      * @private
    175      */
    176     getNativeColorModel_: function(destination, color) {
    177       // For non-local printers native color model is ignored anyway.
    178       var option = destination.isLocal ? color.getSelectedOption() : null;
    179       var nativeColorModel = parseInt(option ? option.vendor_id : null);
    180       if (isNaN(nativeColorModel)) {
    181         return color.getValue() ?
    182             NativeLayer.ColorMode_.COLOR : NativeLayer.ColorMode_.GRAY;
    183       }
    184       return nativeColorModel;
    185     },
    186 
    187     /**
    188      * Requests that a preview be generated. The following events may be
    189      * dispatched in response:
    190      *   - PAGE_COUNT_READY
    191      *   - PAGE_LAYOUT_READY
    192      *   - PAGE_PREVIEW_READY
    193      *   - PREVIEW_GENERATION_DONE
    194      *   - PREVIEW_GENERATION_FAIL
    195      * @param {print_preview.Destination} destination Destination to print to.
    196      * @param {!print_preview.PrintTicketStore} printTicketStore Used to get the
    197      *     state of the print ticket.
    198      * @param {!print_preview.DocumentInfo} documentInfo Document data model.
    199      * @param {number} ID of the preview request.
    200      */
    201     startGetPreview: function(
    202         destination, printTicketStore, documentInfo, requestId) {
    203       assert(printTicketStore.isTicketValidForPreview(),
    204              'Trying to generate preview when ticket is not valid');
    205 
    206       var ticket = {
    207         'pageRange': printTicketStore.pageRange.getDocumentPageRanges(),
    208         'mediaSize': printTicketStore.mediaSize.getValue(),
    209         'landscape': printTicketStore.landscape.getValue(),
    210         'color': this.getNativeColorModel_(destination, printTicketStore.color),
    211         'headerFooterEnabled': printTicketStore.headerFooter.getValue(),
    212         'marginsType': printTicketStore.marginsType.getValue(),
    213         'isFirstRequest': requestId == 0,
    214         'requestID': requestId,
    215         'previewModifiable': documentInfo.isModifiable,
    216         'printToPDF':
    217             destination != null &&
    218             destination.id ==
    219                 print_preview.Destination.GooglePromotedId.SAVE_AS_PDF,
    220         'printWithCloudPrint': destination != null && !destination.isLocal,
    221         'printWithPrivet': destination != null && destination.isPrivet,
    222         'deviceName': destination == null ? 'foo' : destination.id,
    223         'generateDraftData': documentInfo.isModifiable,
    224         'fitToPageEnabled': printTicketStore.fitToPage.getValue(),
    225 
    226         // NOTE: Even though the following fields don't directly relate to the
    227         // preview, they still need to be included.
    228         'duplex': printTicketStore.duplex.getValue() ?
    229             NativeLayer.DuplexMode.LONG_EDGE : NativeLayer.DuplexMode.SIMPLEX,
    230         'copies': printTicketStore.copies.getValueAsNumber(),
    231         'collate': printTicketStore.collate.getValue(),
    232         'shouldPrintBackgrounds': printTicketStore.cssBackground.getValue(),
    233         'shouldPrintSelectionOnly': printTicketStore.selectionOnly.getValue()
    234       };
    235 
    236       // Set 'cloudPrintID' only if the destination is not local.
    237       if (destination && !destination.isLocal) {
    238         ticket['cloudPrintID'] = destination.id;
    239       }
    240 
    241       if (printTicketStore.marginsType.isCapabilityAvailable() &&
    242           printTicketStore.marginsType.getValue() ==
    243               print_preview.ticket_items.MarginsType.Value.CUSTOM) {
    244         var customMargins = printTicketStore.customMargins.getValue();
    245         var orientationEnum =
    246             print_preview.ticket_items.CustomMargins.Orientation;
    247         ticket['marginsCustom'] = {
    248           'marginTop': customMargins.get(orientationEnum.TOP),
    249           'marginRight': customMargins.get(orientationEnum.RIGHT),
    250           'marginBottom': customMargins.get(orientationEnum.BOTTOM),
    251           'marginLeft': customMargins.get(orientationEnum.LEFT)
    252         };
    253       }
    254 
    255       chrome.send(
    256           'getPreview',
    257           [JSON.stringify(ticket),
    258            requestId > 0 ? documentInfo.pageCount : -1,
    259            documentInfo.isModifiable]);
    260     },
    261 
    262     /**
    263      * Requests that the document be printed.
    264      * @param {!print_preview.Destination} destination Destination to print to.
    265      * @param {!print_preview.PrintTicketStore} printTicketStore Used to get the
    266      *     state of the print ticket.
    267      * @param {print_preview.CloudPrintInterface} cloudPrintInterface Interface
    268      *     to Google Cloud Print.
    269      * @param {!print_preview.DocumentInfo} documentInfo Document data model.
    270      * @param {boolean=} opt_isOpenPdfInPreview Whether to open the PDF in the
    271      *     system's preview application.
    272      */
    273     startPrint: function(destination, printTicketStore, cloudPrintInterface,
    274                          documentInfo, opt_isOpenPdfInPreview) {
    275       assert(printTicketStore.isTicketValid(),
    276              'Trying to print when ticket is not valid');
    277 
    278       var ticket = {
    279         'pageRange': printTicketStore.pageRange.getDocumentPageRanges(),
    280         'mediaSize': printTicketStore.mediaSize.getValue(),
    281         'pageCount': printTicketStore.pageRange.getPageNumberSet().size,
    282         'landscape': printTicketStore.landscape.getValue(),
    283         'color': this.getNativeColorModel_(destination, printTicketStore.color),
    284         'headerFooterEnabled': printTicketStore.headerFooter.getValue(),
    285         'marginsType': printTicketStore.marginsType.getValue(),
    286         'generateDraftData': true, // TODO(rltoscano): What should this be?
    287         'duplex': printTicketStore.duplex.getValue() ?
    288             NativeLayer.DuplexMode.LONG_EDGE : NativeLayer.DuplexMode.SIMPLEX,
    289         'copies': printTicketStore.copies.getValueAsNumber(),
    290         'collate': printTicketStore.collate.getValue(),
    291         'shouldPrintBackgrounds': printTicketStore.cssBackground.getValue(),
    292         'shouldPrintSelectionOnly': printTicketStore.selectionOnly.getValue(),
    293         'previewModifiable': documentInfo.isModifiable,
    294         'printToPDF': destination.id ==
    295             print_preview.Destination.GooglePromotedId.SAVE_AS_PDF,
    296         'printWithCloudPrint': !destination.isLocal,
    297         'printWithPrivet': destination.isPrivet,
    298         'deviceName': destination.id,
    299         'isFirstRequest': false,
    300         'requestID': -1,
    301         'fitToPageEnabled': printTicketStore.fitToPage.getValue(),
    302         'pageWidth': documentInfo.pageSize.width,
    303         'pageHeight': documentInfo.pageSize.height
    304       };
    305 
    306       if (!destination.isLocal) {
    307         // We can't set cloudPrintID if the destination is "Print with Cloud
    308         // Print" because the native system will try to print to Google Cloud
    309         // Print with this ID instead of opening a Google Cloud Print dialog.
    310         ticket['cloudPrintID'] = destination.id;
    311       }
    312 
    313       if (printTicketStore.marginsType.isCapabilityAvailable() &&
    314           printTicketStore.marginsType.isValueEqual(
    315               print_preview.ticket_items.MarginsType.Value.CUSTOM)) {
    316         var customMargins = printTicketStore.customMargins.getValue();
    317         var orientationEnum =
    318             print_preview.ticket_items.CustomMargins.Orientation;
    319         ticket['marginsCustom'] = {
    320           'marginTop': customMargins.get(orientationEnum.TOP),
    321           'marginRight': customMargins.get(orientationEnum.RIGHT),
    322           'marginBottom': customMargins.get(orientationEnum.BOTTOM),
    323           'marginLeft': customMargins.get(orientationEnum.LEFT)
    324         };
    325       }
    326 
    327       if (destination.isPrivet) {
    328         ticket['ticket'] = printTicketStore.createPrintTicket(destination);
    329         ticket['capabilities'] = JSON.stringify(destination.capabilities);
    330       }
    331 
    332       if (opt_isOpenPdfInPreview) {
    333         ticket['OpenPDFInPreview'] = true;
    334       }
    335 
    336       chrome.send('print', [JSON.stringify(ticket)]);
    337     },
    338 
    339     /** Requests that the current pending print request be cancelled. */
    340     startCancelPendingPrint: function() {
    341       chrome.send('cancelPendingPrintRequest');
    342     },
    343 
    344     /** Shows the system's native printing dialog. */
    345     startShowSystemDialog: function() {
    346       chrome.send('showSystemDialog');
    347     },
    348 
    349     /** Shows Google Cloud Print's web-based print dialog.
    350      * @param {number} pageCount Number of pages to print.
    351      */
    352     startShowCloudPrintDialog: function(pageCount) {
    353       chrome.send('printWithCloudPrintDialog', [pageCount]);
    354     },
    355 
    356     /** Closes the print preview dialog. */
    357     startCloseDialog: function() {
    358       chrome.send('closePrintPreviewDialog');
    359       chrome.send('dialogClose');
    360     },
    361 
    362     /** Hide the print preview dialog and allow the native layer to close it. */
    363     startHideDialog: function() {
    364       chrome.send('hidePreview');
    365     },
    366 
    367     /**
    368      * Opens the Google Cloud Print sign-in tab. The DESTINATIONS_RELOAD event
    369      *     will be dispatched in response.
    370      * @param {boolean} addAccount Whether to open an 'add a new account' or
    371      *     default sign in page.
    372      */
    373     startCloudPrintSignIn: function(addAccount) {
    374       chrome.send('signIn', [addAccount]);
    375     },
    376 
    377     /** Navigates the user to the system printer settings interface. */
    378     startManageLocalDestinations: function() {
    379       chrome.send('manageLocalPrinters');
    380     },
    381 
    382     /** Navigates the user to the Google Cloud Print management page. */
    383     startManageCloudDestinations: function() {
    384       chrome.send('manageCloudPrinters');
    385     },
    386 
    387     /** Forces browser to open a new tab with the given URL address. */
    388     startForceOpenNewTab: function(url) {
    389       chrome.send('forceOpenNewTab', [url]);
    390     },
    391 
    392     /**
    393      * @param {!Object} initialSettings Object containing all initial settings.
    394      */
    395     onSetInitialSettings_: function(initialSettings) {
    396       var numberFormatSymbols =
    397           print_preview.MeasurementSystem.parseNumberFormat(
    398               initialSettings['numberFormat']);
    399       var unitType = print_preview.MeasurementSystem.UnitType.IMPERIAL;
    400       if (initialSettings['measurementSystem'] != null) {
    401         unitType = initialSettings['measurementSystem'];
    402       }
    403 
    404       var nativeInitialSettings = new print_preview.NativeInitialSettings(
    405           initialSettings['printAutomaticallyInKioskMode'] || false,
    406           initialSettings['hidePrintWithSystemDialogLink'] || false,
    407           numberFormatSymbols[0] || ',',
    408           numberFormatSymbols[1] || '.',
    409           unitType,
    410           initialSettings['previewModifiable'] || false,
    411           initialSettings['initiatorTitle'] || '',
    412           initialSettings['documentHasSelection'] || false,
    413           initialSettings['shouldPrintSelectionOnly'] || false,
    414           initialSettings['printerName'] || null,
    415           initialSettings['appState'] || null);
    416 
    417       var initialSettingsSetEvent = new Event(
    418           NativeLayer.EventType.INITIAL_SETTINGS_SET);
    419       initialSettingsSetEvent.initialSettings = nativeInitialSettings;
    420       this.dispatchEvent(initialSettingsSetEvent);
    421     },
    422 
    423     /**
    424      * Turn on the integration of Cloud Print.
    425      * @param {string} cloudPrintURL The URL to use for cloud print servers.
    426      * @private
    427      */
    428     onSetUseCloudPrint_: function(cloudPrintURL) {
    429       var cloudPrintEnableEvent = new Event(
    430           NativeLayer.EventType.CLOUD_PRINT_ENABLE);
    431       cloudPrintEnableEvent.baseCloudPrintUrl = cloudPrintURL;
    432       this.dispatchEvent(cloudPrintEnableEvent);
    433     },
    434 
    435     /**
    436      * Updates the print preview with local printers.
    437      * Called from PrintPreviewHandler::SetupPrinterList().
    438      * @param {Array} printers Array of printer info objects.
    439      * @private
    440      */
    441     onSetPrinters_: function(printers) {
    442       var localDestsSetEvent = new Event(
    443           NativeLayer.EventType.LOCAL_DESTINATIONS_SET);
    444       localDestsSetEvent.destinationInfos = printers;
    445       this.dispatchEvent(localDestsSetEvent);
    446     },
    447 
    448     /**
    449      * Called when native layer gets settings information for a requested local
    450      * destination.
    451      * @param {Object} settingsInfo printer setting information.
    452      * @private
    453      */
    454     onUpdateWithPrinterCapabilities_: function(settingsInfo) {
    455       var capsSetEvent = new Event(NativeLayer.EventType.CAPABILITIES_SET);
    456       capsSetEvent.settingsInfo = settingsInfo;
    457       this.dispatchEvent(capsSetEvent);
    458     },
    459 
    460     /**
    461      * Called when native layer gets settings information for a requested local
    462      * destination.
    463      * @param {string} printerId printer affected by error.
    464      * @private
    465      */
    466     onFailedToGetPrinterCapabilities_: function(destinationId) {
    467       var getCapsFailEvent = new Event(
    468           NativeLayer.EventType.GET_CAPABILITIES_FAIL);
    469       getCapsFailEvent.destinationId = destinationId;
    470       getCapsFailEvent.destinationOrigin =
    471           print_preview.Destination.Origin.LOCAL;
    472       this.dispatchEvent(getCapsFailEvent);
    473     },
    474 
    475     /**
    476      * Called when native layer gets settings information for a requested privet
    477      * destination.
    478      * @param {string} printerId printer affected by error.
    479      * @private
    480      */
    481     onFailedToGetPrivetPrinterCapabilities_: function(destinationId) {
    482       var getCapsFailEvent = new Event(
    483           NativeLayer.EventType.GET_CAPABILITIES_FAIL);
    484       getCapsFailEvent.destinationId = destinationId;
    485       getCapsFailEvent.destinationOrigin =
    486           print_preview.Destination.Origin.PRIVET;
    487       this.dispatchEvent(getCapsFailEvent);
    488     },
    489 
    490     /** Reloads the printer list. */
    491     onReloadPrintersList_: function() {
    492       cr.dispatchSimpleEvent(this, NativeLayer.EventType.DESTINATIONS_RELOAD);
    493     },
    494 
    495     /**
    496      * Called from the C++ layer.
    497      * Take the PDF data handed to us and submit it to the cloud, closing the
    498      * print preview dialog once the upload is successful.
    499      * @param {string} data Data to send as the print job.
    500      * @private
    501      */
    502     onPrintToCloud_: function(data) {
    503       var printToCloudEvent = new Event(
    504           NativeLayer.EventType.PRINT_TO_CLOUD);
    505       printToCloudEvent.data = data;
    506       this.dispatchEvent(printToCloudEvent);
    507     },
    508 
    509     /**
    510      * Called from PrintPreviewUI::OnFileSelectionCancelled to notify the print
    511      * preview dialog regarding the file selection cancel event.
    512      * @private
    513      */
    514     onFileSelectionCancelled_: function() {
    515       cr.dispatchSimpleEvent(this, NativeLayer.EventType.FILE_SELECTION_CANCEL);
    516     },
    517 
    518     /**
    519      * Called from PrintPreviewUI::OnFileSelectionCompleted to notify the print
    520      * preview dialog regarding the file selection completed event.
    521      * @private
    522      */
    523     onFileSelectionCompleted_: function() {
    524       // If the file selection is completed and the dialog is not already closed
    525       // it means that a pending print to pdf request exists.
    526       cr.dispatchSimpleEvent(
    527           this, NativeLayer.EventType.FILE_SELECTION_COMPLETE);
    528     },
    529 
    530     /**
    531      * Display an error message when print preview fails.
    532      * Called from PrintPreviewMessageHandler::OnPrintPreviewFailed().
    533      * @private
    534      */
    535     onPrintPreviewFailed_: function() {
    536       cr.dispatchSimpleEvent(
    537           this, NativeLayer.EventType.PREVIEW_GENERATION_FAIL);
    538     },
    539 
    540     /**
    541      * Display an error message when encountered invalid printer settings.
    542      * Called from PrintPreviewMessageHandler::OnInvalidPrinterSettings().
    543      * @private
    544      */
    545     onInvalidPrinterSettings_: function() {
    546       cr.dispatchSimpleEvent(this, NativeLayer.EventType.SETTINGS_INVALID);
    547     },
    548 
    549     /**
    550      * @param {{contentWidth: number, contentHeight: number, marginLeft: number,
    551      *          marginRight: number, marginTop: number, marginBottom: number,
    552      *          printableAreaX: number, printableAreaY: number,
    553      *          printableAreaWidth: number, printableAreaHeight: number}}
    554      *          pageLayout Specifies default page layout details in points.
    555      * @param {boolean} hasCustomPageSizeStyle Indicates whether the previewed
    556      *     document has a custom page size style.
    557      * @private
    558      */
    559     onDidGetDefaultPageLayout_: function(pageLayout, hasCustomPageSizeStyle) {
    560       var pageLayoutChangeEvent = new Event(
    561           NativeLayer.EventType.PAGE_LAYOUT_READY);
    562       pageLayoutChangeEvent.pageLayout = pageLayout;
    563       pageLayoutChangeEvent.hasCustomPageSizeStyle = hasCustomPageSizeStyle;
    564       this.dispatchEvent(pageLayoutChangeEvent);
    565     },
    566 
    567     /**
    568      * Update the page count and check the page range.
    569      * Called from PrintPreviewUI::OnDidGetPreviewPageCount().
    570      * @param {number} pageCount The number of pages.
    571      * @param {number} previewResponseId The preview request id that resulted in
    572      *      this response.
    573      * @private
    574      */
    575     onDidGetPreviewPageCount_: function(pageCount, previewResponseId) {
    576       var pageCountChangeEvent = new Event(
    577           NativeLayer.EventType.PAGE_COUNT_READY);
    578       pageCountChangeEvent.pageCount = pageCount;
    579       pageCountChangeEvent.previewResponseId = previewResponseId;
    580       this.dispatchEvent(pageCountChangeEvent);
    581     },
    582 
    583     /**
    584      * Notification that a print preview page has been rendered.
    585      * Check if the settings have changed and request a regeneration if needed.
    586      * Called from PrintPreviewUI::OnDidPreviewPage().
    587      * @param {number} pageNumber The page number, 0-based.
    588      * @param {number} previewUid Preview unique identifier.
    589      * @param {number} previewResponseId The preview request id that resulted in
    590      *     this response.
    591      * @private
    592      */
    593     onDidPreviewPage_: function(pageNumber, previewUid, previewResponseId) {
    594       var pagePreviewGenEvent = new Event(
    595           NativeLayer.EventType.PAGE_PREVIEW_READY);
    596       pagePreviewGenEvent.pageIndex = pageNumber;
    597       pagePreviewGenEvent.previewUid = previewUid;
    598       pagePreviewGenEvent.previewResponseId = previewResponseId;
    599       this.dispatchEvent(pagePreviewGenEvent);
    600     },
    601 
    602     /**
    603      * Notification that access token is ready.
    604      * @param {string} authType Type of access token.
    605      * @param {string} accessToken Access token.
    606      * @private
    607      */
    608     onDidGetAccessToken_: function(authType, accessToken) {
    609       var getAccessTokenEvent = new Event(
    610           NativeLayer.EventType.ACCESS_TOKEN_READY);
    611       getAccessTokenEvent.authType = authType;
    612       getAccessTokenEvent.accessToken = accessToken;
    613       this.dispatchEvent(getAccessTokenEvent);
    614     },
    615 
    616     /**
    617      * Update the print preview when new preview data is available.
    618      * Create the PDF plugin as needed.
    619      * Called from PrintPreviewUI::PreviewDataIsAvailable().
    620      * @param {number} previewUid Preview unique identifier.
    621      * @param {number} previewResponseId The preview request id that resulted in
    622      *     this response.
    623      * @private
    624      */
    625     onUpdatePrintPreview_: function(previewUid, previewResponseId) {
    626       var previewGenDoneEvent = new Event(
    627           NativeLayer.EventType.PREVIEW_GENERATION_DONE);
    628       previewGenDoneEvent.previewUid = previewUid;
    629       previewGenDoneEvent.previewResponseId = previewResponseId;
    630       this.dispatchEvent(previewGenDoneEvent);
    631     },
    632 
    633     /**
    634      * Updates the fit to page option state based on the print scaling option of
    635      * source pdf. PDF's have an option to enable/disable print scaling. When we
    636      * find out that the print scaling option is disabled for the source pdf, we
    637      * uncheck the fitToPage_ to page checkbox. This function is called from C++
    638      * code.
    639      * @private
    640      */
    641     onPrintScalingDisabledForSourcePDF_: function() {
    642       cr.dispatchSimpleEvent(this, NativeLayer.EventType.DISABLE_SCALING);
    643     },
    644 
    645     /**
    646      * Simulates a user click on the print preview dialog cancel button. Used
    647      * only for testing.
    648      * @private
    649      */
    650     autoCancelForTesting_: function() {
    651       var properties = {view: window, bubbles: true, cancelable: true};
    652       var click = new MouseEvent('click', properties);
    653       document.querySelector('#print-header .cancel').dispatchEvent(click);
    654     },
    655 
    656     /**
    657      * @param {{serviceName: string, name: string}} printer Specifies
    658      *     information about the printer that was added.
    659      * @private
    660      */
    661     onPrivetPrinterChanged_: function(printer) {
    662       var privetPrinterChangedEvent =
    663             new Event(NativeLayer.EventType.PRIVET_PRINTER_CHANGED);
    664       privetPrinterChangedEvent.printer = printer;
    665       this.dispatchEvent(privetPrinterChangedEvent);
    666     },
    667 
    668     /**
    669      * @param {Object} printer Specifies information about the printer that was
    670      *    added.
    671      * @private
    672      */
    673     onPrivetCapabilitiesSet_: function(printer, capabilities) {
    674       var privetCapabilitiesSetEvent =
    675             new Event(NativeLayer.EventType.PRIVET_CAPABILITIES_SET);
    676       privetCapabilitiesSetEvent.printer = printer;
    677       privetCapabilitiesSetEvent.capabilities = capabilities;
    678       this.dispatchEvent(privetCapabilitiesSetEvent);
    679     },
    680 
    681     /**
    682      * @param {string} http_error The HTTP response code or -1 if not an HTTP
    683      *    error.
    684      * @private
    685      */
    686     onPrivetPrintFailed_: function(http_error) {
    687       var privetPrintFailedEvent =
    688             new Event(NativeLayer.EventType.PRIVET_PRINT_FAILED);
    689       privetPrintFailedEvent.httpError = http_error;
    690       this.dispatchEvent(privetPrintFailedEvent);
    691     }
    692   };
    693 
    694   /**
    695    * Initial settings retrieved from the native layer.
    696    * @param {boolean} isInKioskAutoPrintMode Whether the print preview should be
    697    *     in auto-print mode.
    698    * @param {string} thousandsDelimeter Character delimeter of thousands digits.
    699    * @param {string} decimalDelimeter Character delimeter of the decimal point.
    700    * @param {!print_preview.MeasurementSystem.UnitType} unitType Unit type of
    701    *     local machine's measurement system.
    702    * @param {boolean} isDocumentModifiable Whether the document to print is
    703    *     modifiable.
    704    * @param {string} documentTitle Title of the document.
    705    * @param {boolean} documentHasSelection Whether the document has selected
    706    *     content.
    707    * @param {boolean} selectionOnly Whether only selected content should be
    708    *     printed.
    709    * @param {?string} systemDefaultDestinationId ID of the system default
    710    *     destination.
    711    * @param {?string} serializedAppStateStr Serialized app state.
    712    * @constructor
    713    */
    714   function NativeInitialSettings(
    715       isInKioskAutoPrintMode,
    716       hidePrintWithSystemDialogLink,
    717       thousandsDelimeter,
    718       decimalDelimeter,
    719       unitType,
    720       isDocumentModifiable,
    721       documentTitle,
    722       documentHasSelection,
    723       selectionOnly,
    724       systemDefaultDestinationId,
    725       serializedAppStateStr) {
    726 
    727     /**
    728      * Whether the print preview should be in auto-print mode.
    729      * @type {boolean}
    730      * @private
    731      */
    732     this.isInKioskAutoPrintMode_ = isInKioskAutoPrintMode;
    733 
    734     /**
    735      * Whether we should hide the link which shows the system print dialog.
    736      * @type {boolean}
    737      * @private
    738      */
    739     this.hidePrintWithSystemDialogLink_ = hidePrintWithSystemDialogLink;
    740 
    741     /**
    742      * Character delimeter of thousands digits.
    743      * @type {string}
    744      * @private
    745      */
    746     this.thousandsDelimeter_ = thousandsDelimeter;
    747 
    748     /**
    749      * Character delimeter of the decimal point.
    750      * @type {string}
    751      * @private
    752      */
    753     this.decimalDelimeter_ = decimalDelimeter;
    754 
    755     /**
    756      * Unit type of local machine's measurement system.
    757      * @type {string}
    758      * @private
    759      */
    760     this.unitType_ = unitType;
    761 
    762     /**
    763      * Whether the document to print is modifiable.
    764      * @type {boolean}
    765      * @private
    766      */
    767     this.isDocumentModifiable_ = isDocumentModifiable;
    768 
    769     /**
    770      * Title of the document.
    771      * @type {string}
    772      * @private
    773      */
    774     this.documentTitle_ = documentTitle;
    775 
    776     /**
    777      * Whether the document has selection.
    778      * @type {string}
    779      * @private
    780      */
    781     this.documentHasSelection_ = documentHasSelection;
    782 
    783     /**
    784      * Whether selection only should be printed.
    785      * @type {string}
    786      * @private
    787      */
    788     this.selectionOnly_ = selectionOnly;
    789 
    790     /**
    791      * ID of the system default destination.
    792      * @type {?string}
    793      * @private
    794      */
    795     this.systemDefaultDestinationId_ = systemDefaultDestinationId;
    796 
    797     /**
    798      * Serialized app state.
    799      * @type {?string}
    800      * @private
    801      */
    802     this.serializedAppStateStr_ = serializedAppStateStr;
    803   };
    804 
    805   NativeInitialSettings.prototype = {
    806     /**
    807      * @return {boolean} Whether the print preview should be in auto-print mode.
    808      */
    809     get isInKioskAutoPrintMode() {
    810       return this.isInKioskAutoPrintMode_;
    811     },
    812 
    813     /**
    814      * @return {boolean} Whether we should hide the link which shows the
    815            system print dialog.
    816      */
    817     get hidePrintWithSystemDialogLink() {
    818       return this.hidePrintWithSystemDialogLink_;
    819     },
    820 
    821     /** @return {string} Character delimeter of thousands digits. */
    822     get thousandsDelimeter() {
    823       return this.thousandsDelimeter_;
    824     },
    825 
    826     /** @return {string} Character delimeter of the decimal point. */
    827     get decimalDelimeter() {
    828       return this.decimalDelimeter_;
    829     },
    830 
    831     /**
    832      * @return {!print_preview.MeasurementSystem.UnitType} Unit type of local
    833      *     machine's measurement system.
    834      */
    835     get unitType() {
    836       return this.unitType_;
    837     },
    838 
    839     /** @return {boolean} Whether the document to print is modifiable. */
    840     get isDocumentModifiable() {
    841       return this.isDocumentModifiable_;
    842     },
    843 
    844     /** @return {string} Document title. */
    845     get documentTitle() {
    846       return this.documentTitle_;
    847     },
    848 
    849     /** @return {bool} Whether the document has selection. */
    850     get documentHasSelection() {
    851       return this.documentHasSelection_;
    852     },
    853 
    854     /** @return {bool} Whether selection only should be printed. */
    855     get selectionOnly() {
    856       return this.selectionOnly_;
    857     },
    858 
    859     /** @return {?string} ID of the system default destination. */
    860     get systemDefaultDestinationId() {
    861       return this.systemDefaultDestinationId_;
    862     },
    863 
    864     /** @return {?string} Serialized app state. */
    865     get serializedAppStateStr() {
    866       return this.serializedAppStateStr_;
    867     }
    868   };
    869 
    870   // Export
    871   return {
    872     NativeInitialSettings: NativeInitialSettings,
    873     NativeLayer: NativeLayer
    874   };
    875 });
    876