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
5cr.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