Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / browser / resources / print_preview / native_layer.js
blob94123fae6e3430f9da020f84b680aaea0731e55e
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.
5 cr.exportPath('print_preview');
7 /**
8  * @typedef {{selectSaveAsPdfDestination: boolean,
9  *            layoutSettings.portrait: boolean,
10  *            pageRange: string,
11  *            headersAndFooters: boolean,
12  *            backgroundColorsAndImages: boolean,
13  *            margins: number}}
14  * @see chrome/browser/printing/print_preview_pdf_generated_browsertest.cc
15  */
16 print_preview.PreviewSettings;
18 cr.define('print_preview', function() {
19   'use strict';
21   /**
22    * An interface to the native Chromium printing system layer.
23    * @constructor
24    * @extends {cr.EventTarget}
25    */
26   function NativeLayer() {
27     cr.EventTarget.call(this);
29     // Bind global handlers
30     global.setInitialSettings = this.onSetInitialSettings_.bind(this);
31     global.setUseCloudPrint = this.onSetUseCloudPrint_.bind(this);
32     global.setPrinters = this.onSetPrinters_.bind(this);
33     global.updateWithPrinterCapabilities =
34         this.onUpdateWithPrinterCapabilities_.bind(this);
35     global.failedToGetPrinterCapabilities =
36         this.onFailedToGetPrinterCapabilities_.bind(this);
37     global.failedToGetPrivetPrinterCapabilities =
38       this.onFailedToGetPrivetPrinterCapabilities_.bind(this);
39     global.failedToGetExtensionPrinterCapabilities =
40         this.onFailedToGetExtensionPrinterCapabilities_.bind(this);
41     global.reloadPrintersList = this.onReloadPrintersList_.bind(this);
42     global.printToCloud = this.onPrintToCloud_.bind(this);
43     global.fileSelectionCancelled =
44         this.onFileSelectionCancelled_.bind(this);
45     global.fileSelectionCompleted =
46         this.onFileSelectionCompleted_.bind(this);
47     global.printPreviewFailed = this.onPrintPreviewFailed_.bind(this);
48     global.invalidPrinterSettings =
49         this.onInvalidPrinterSettings_.bind(this);
50     global.onDidGetDefaultPageLayout =
51         this.onDidGetDefaultPageLayout_.bind(this);
52     global.onDidGetPreviewPageCount =
53         this.onDidGetPreviewPageCount_.bind(this);
54     global.onDidPreviewPage = this.onDidPreviewPage_.bind(this);
55     global.updatePrintPreview = this.onUpdatePrintPreview_.bind(this);
56     global.onDidGetAccessToken = this.onDidGetAccessToken_.bind(this);
57     global.autoCancelForTesting = this.autoCancelForTesting_.bind(this);
58     global.onPrivetPrinterChanged = this.onPrivetPrinterChanged_.bind(this);
59     global.onPrivetCapabilitiesSet =
60         this.onPrivetCapabilitiesSet_.bind(this);
61     global.onPrivetPrintFailed = this.onPrivetPrintFailed_.bind(this);
62     global.onExtensionPrintersAdded =
63         this.onExtensionPrintersAdded_.bind(this);
64     global.onExtensionCapabilitiesSet =
65         this.onExtensionCapabilitiesSet_.bind(this);
66     global.onEnableManipulateSettingsForTest =
67         this.onEnableManipulateSettingsForTest_.bind(this);
68     global.printPresetOptionsFromDocument =
69         this.onPrintPresetOptionsFromDocument_.bind(this);
70    global.detectDistillablePage =
71         this.detectDistillablePage_.bind(this);
72     global.onProvisionalPrinterResolved =
73         this.onProvisionalDestinationResolved_.bind(this);
74     global.failedToResolveProvisionalPrinter =
75         this.failedToResolveProvisionalDestination_.bind(this);
76   };
78   /**
79    * Event types dispatched from the Chromium native layer.
80    * @enum {string}
81    * @const
82    */
83   NativeLayer.EventType = {
84     ACCESS_TOKEN_READY: 'print_preview.NativeLayer.ACCESS_TOKEN_READY',
85     ALLOW_DISTILL_PAGE: 'print_preview.NativeLayer.ALLOW_DISTILL_PAGE',
86     CAPABILITIES_SET: 'print_preview.NativeLayer.CAPABILITIES_SET',
87     CLOUD_PRINT_ENABLE: 'print_preview.NativeLayer.CLOUD_PRINT_ENABLE',
88     DESTINATIONS_RELOAD: 'print_preview.NativeLayer.DESTINATIONS_RELOAD',
89     DISABLE_SCALING: 'print_preview.NativeLayer.DISABLE_SCALING',
90     FILE_SELECTION_CANCEL: 'print_preview.NativeLayer.FILE_SELECTION_CANCEL',
91     FILE_SELECTION_COMPLETE:
92         'print_preview.NativeLayer.FILE_SELECTION_COMPLETE',
93     GET_CAPABILITIES_FAIL: 'print_preview.NativeLayer.GET_CAPABILITIES_FAIL',
94     INITIAL_SETTINGS_SET: 'print_preview.NativeLayer.INITIAL_SETTINGS_SET',
95     LOCAL_DESTINATIONS_SET: 'print_preview.NativeLayer.LOCAL_DESTINATIONS_SET',
96     MANIPULATE_SETTINGS_FOR_TEST:
97         'print_preview.NativeLayer.MANIPULATE_SETTINGS_FOR_TEST',
98     PAGE_COUNT_READY: 'print_preview.NativeLayer.PAGE_COUNT_READY',
99     PAGE_LAYOUT_READY: 'print_preview.NativeLayer.PAGE_LAYOUT_READY',
100     PAGE_PREVIEW_READY: 'print_preview.NativeLayer.PAGE_PREVIEW_READY',
101     PREVIEW_GENERATION_DONE:
102         'print_preview.NativeLayer.PREVIEW_GENERATION_DONE',
103     PREVIEW_GENERATION_FAIL:
104         'print_preview.NativeLayer.PREVIEW_GENERATION_FAIL',
105     PRINT_TO_CLOUD: 'print_preview.NativeLayer.PRINT_TO_CLOUD',
106     SETTINGS_INVALID: 'print_preview.NativeLayer.SETTINGS_INVALID',
107     PRIVET_PRINTER_CHANGED: 'print_preview.NativeLayer.PRIVET_PRINTER_CHANGED',
108     PRIVET_CAPABILITIES_SET:
109         'print_preview.NativeLayer.PRIVET_CAPABILITIES_SET',
110     PRIVET_PRINT_FAILED: 'print_preview.NativeLayer.PRIVET_PRINT_FAILED',
111     EXTENSION_PRINTERS_ADDED:
112         'print_preview.NativeLayer.EXTENSION_PRINTERS_ADDED',
113     EXTENSION_CAPABILITIES_SET:
114         'print_preview.NativeLayer.EXTENSION_CAPABILITIES_SET',
115     PRINT_PRESET_OPTIONS: 'print_preview.NativeLayer.PRINT_PRESET_OPTIONS',
116     PROVISIONAL_DESTINATION_RESOLVED:
117         'print_preview.NativeLayer.PROVISIONAL_DESTINATION_RESOLVED'
118   };
120   /**
121    * Constant values matching printing::DuplexMode enum.
122    * @enum {number}
123    */
124   NativeLayer.DuplexMode = {
125     SIMPLEX: 0,
126     LONG_EDGE: 1,
127     UNKNOWN_DUPLEX_MODE: -1
128   };
130   /**
131    * Enumeration of color modes used by Chromium.
132    * @enum {number}
133    * @private
134    */
135   NativeLayer.ColorMode_ = {
136     GRAY: 1,
137     COLOR: 2
138   };
140   /**
141    * Version of the serialized state of the print preview.
142    * @type {number}
143    * @const
144    * @private
145    */
146   NativeLayer.SERIALIZED_STATE_VERSION_ = 1;
148   NativeLayer.prototype = {
149     __proto__: cr.EventTarget.prototype,
151     /**
152      * Requests access token for cloud print requests.
153      * @param {string} authType type of access token.
154      */
155     startGetAccessToken: function(authType) {
156       chrome.send('getAccessToken', [authType]);
157     },
159     /** Gets the initial settings to initialize the print preview with. */
160     startGetInitialSettings: function() {
161       chrome.send('getInitialSettings');
162     },
164     /**
165      * Requests the system's local print destinations. A LOCAL_DESTINATIONS_SET
166      * event will be dispatched in response.
167      */
168     startGetLocalDestinations: function() {
169       chrome.send('getPrinters');
170     },
172     /**
173      * Requests the network's privet print destinations. A number of
174      * PRIVET_PRINTER_CHANGED events will be fired in response, followed by a
175      * PRIVET_SEARCH_ENDED.
176      */
177     startGetPrivetDestinations: function() {
178       chrome.send('getPrivetPrinters');
179     },
181     /**
182      * Requests that the privet print stack stop searching for privet print
183      * destinations.
184      */
185     stopGetPrivetDestinations: function() {
186       chrome.send('stopGetPrivetPrinters');
187     },
189     /**
190      * Requests the privet destination's printing capabilities. A
191      * PRIVET_CAPABILITIES_SET event will be dispatched in response.
192      * @param {string} destinationId ID of the destination.
193      */
194     startGetPrivetDestinationCapabilities: function(destinationId) {
195       chrome.send('getPrivetPrinterCapabilities', [destinationId]);
196     },
198     /**
199      * Requests that extension system dispatches an event requesting the list of
200      * extension managed printers.
201      */
202     startGetExtensionDestinations: function() {
203       chrome.send('getExtensionPrinters');
204     },
206     /**
207      * Requests an extension destination's printing capabilities. A
208      * EXTENSION_CAPABILITIES_SET event will be dispatched in response.
209      * @param {string} destinationId The ID of the destination whose
210      *     capabilities are requested.
211      */
212     startGetExtensionDestinationCapabilities: function(destinationId) {
213       chrome.send('getExtensionPrinterCapabilities', [destinationId]);
214     },
216     /**
217      * Requests the destination's printing capabilities. A CAPABILITIES_SET
218      * event will be dispatched in response.
219      * @param {string} destinationId ID of the destination.
220      */
221     startGetLocalDestinationCapabilities: function(destinationId) {
222       chrome.send('getPrinterCapabilities', [destinationId]);
223     },
225     /**
226      * Requests Chrome to resolve provisional extension destination by granting
227      * the provider extension access to the printer. Chrome will respond with
228      * the resolved destination properties by calling
229      * {@code onProvisionalPrinterResolved}, or in case of an error
230      * {@code failedToResolveProvisionalPrinter}
231      * @param {string} provisionalDestinationId
232      */
233     grantExtensionPrinterAccess: function(provisionalDestinationId) {
234       chrome.send('grantExtensionPrinterAccess', [provisionalDestinationId]);
235     },
237     /**
238      * @param {!print_preview.Destination} destination Destination to print to.
239      * @param {!print_preview.ticket_items.Color} color Color ticket item.
240      * @return {number} Native layer color model.
241      * @private
242      */
243     getNativeColorModel_: function(destination, color) {
244       // For non-local printers native color model is ignored anyway.
245       var option = destination.isLocal ? color.getSelectedOption() : null;
246       var nativeColorModel = parseInt(option ? option.vendor_id : null, 10);
247       if (isNaN(nativeColorModel)) {
248         return color.getValue() ?
249             NativeLayer.ColorMode_.COLOR : NativeLayer.ColorMode_.GRAY;
250       }
251       return nativeColorModel;
252     },
254     /**
255      * Requests that a preview be generated. The following events may be
256      * dispatched in response:
257      *   - PAGE_COUNT_READY
258      *   - PAGE_LAYOUT_READY
259      *   - PAGE_PREVIEW_READY
260      *   - PREVIEW_GENERATION_DONE
261      *   - PREVIEW_GENERATION_FAIL
262      * @param {print_preview.Destination} destination Destination to print to.
263      * @param {!print_preview.PrintTicketStore} printTicketStore Used to get the
264      *     state of the print ticket.
265      * @param {!print_preview.DocumentInfo} documentInfo Document data model.
266      * @param {number} requestId ID of the preview request.
267      */
268     startGetPreview: function(
269         destination, printTicketStore, documentInfo, requestId) {
270       assert(printTicketStore.isTicketValidForPreview(),
271              'Trying to generate preview when ticket is not valid');
273       var ticket = {
274         'pageRange': printTicketStore.pageRange.getDocumentPageRanges(),
275         'mediaSize': printTicketStore.mediaSize.getValue(),
276         'landscape': printTicketStore.landscape.getValue(),
277         'color': this.getNativeColorModel_(destination, printTicketStore.color),
278         'headerFooterEnabled': printTicketStore.headerFooter.getValue(),
279         'distillPage': printTicketStore.distillPage.getValue(),
280         'marginsType': printTicketStore.marginsType.getValue(),
281         'isFirstRequest': requestId == 0,
282         'requestID': requestId,
283         'previewModifiable': documentInfo.isModifiable,
284         'printToPDF':
285             destination != null &&
286             destination.id ==
287                 print_preview.Destination.GooglePromotedId.SAVE_AS_PDF,
288         'printWithCloudPrint': destination != null && !destination.isLocal,
289         'printWithPrivet': destination != null && destination.isPrivet,
290         'printWithExtension': destination != null && destination.isExtension,
291         'deviceName': destination == null ? 'foo' : destination.id,
292         'generateDraftData': documentInfo.isModifiable,
293         'fitToPageEnabled': printTicketStore.fitToPage.getValue(),
295         // NOTE: Even though the following fields don't directly relate to the
296         // preview, they still need to be included.
297         'duplex': printTicketStore.duplex.getValue() ?
298             NativeLayer.DuplexMode.LONG_EDGE : NativeLayer.DuplexMode.SIMPLEX,
299         'copies': 1,
300         'collate': true,
301         'shouldPrintBackgrounds': printTicketStore.cssBackground.getValue(),
302         'shouldPrintSelectionOnly': printTicketStore.selectionOnly.getValue()
303       };
305       // Set 'cloudPrintID' only if the destination is not local.
306       if (destination && !destination.isLocal) {
307         ticket['cloudPrintID'] = destination.id;
308       }
310       if (printTicketStore.marginsType.isCapabilityAvailable() &&
311           printTicketStore.marginsType.getValue() ==
312               print_preview.ticket_items.MarginsType.Value.CUSTOM) {
313         var customMargins = printTicketStore.customMargins.getValue();
314         var orientationEnum =
315             print_preview.ticket_items.CustomMargins.Orientation;
316         ticket['marginsCustom'] = {
317           'marginTop': customMargins.get(orientationEnum.TOP),
318           'marginRight': customMargins.get(orientationEnum.RIGHT),
319           'marginBottom': customMargins.get(orientationEnum.BOTTOM),
320           'marginLeft': customMargins.get(orientationEnum.LEFT)
321         };
322       }
324       chrome.send(
325           'getPreview',
326           [JSON.stringify(ticket),
327            requestId > 0 ? documentInfo.pageCount : -1,
328            documentInfo.isModifiable]);
329     },
331     /**
332      * Requests that the document be printed.
333      * @param {!print_preview.Destination} destination Destination to print to.
334      * @param {!print_preview.PrintTicketStore} printTicketStore Used to get the
335      *     state of the print ticket.
336      * @param {cloudprint.CloudPrintInterface} cloudPrintInterface Interface
337      *     to Google Cloud Print.
338      * @param {!print_preview.DocumentInfo} documentInfo Document data model.
339      * @param {boolean=} opt_isOpenPdfInPreview Whether to open the PDF in the
340      *     system's preview application.
341      * @param {boolean=} opt_showSystemDialog Whether to open system dialog for
342      *     advanced settings.
343      */
344     startPrint: function(destination, printTicketStore, cloudPrintInterface,
345                          documentInfo, opt_isOpenPdfInPreview,
346                          opt_showSystemDialog) {
347       assert(printTicketStore.isTicketValid(),
348              'Trying to print when ticket is not valid');
350       assert(!opt_showSystemDialog || (cr.isWindows && destination.isLocal),
351              'Implemented for Windows only');
353       var ticket = {
354         'pageRange': printTicketStore.pageRange.getDocumentPageRanges(),
355         'mediaSize': printTicketStore.mediaSize.getValue(),
356         'pageCount': printTicketStore.pageRange.getPageNumberSet().size,
357         'landscape': printTicketStore.landscape.getValue(),
358         'color': this.getNativeColorModel_(destination, printTicketStore.color),
359         'headerFooterEnabled': printTicketStore.headerFooter.getValue(),
360         'marginsType': printTicketStore.marginsType.getValue(),
361         'generateDraftData': true, // TODO(rltoscano): What should this be?
362         'duplex': printTicketStore.duplex.getValue() ?
363             NativeLayer.DuplexMode.LONG_EDGE : NativeLayer.DuplexMode.SIMPLEX,
364         'copies': printTicketStore.copies.getValueAsNumber(),
365         'collate': printTicketStore.collate.getValue(),
366         'shouldPrintBackgrounds': printTicketStore.cssBackground.getValue(),
367         'shouldPrintSelectionOnly': printTicketStore.selectionOnly.getValue(),
368         'previewModifiable': documentInfo.isModifiable,
369         'printToPDF': destination.id ==
370             print_preview.Destination.GooglePromotedId.SAVE_AS_PDF,
371         'printWithCloudPrint': !destination.isLocal,
372         'printWithPrivet': destination.isPrivet,
373         'printWithExtension': destination.isExtension,
374         'deviceName': destination.id,
375         'isFirstRequest': false,
376         'requestID': -1,
377         'fitToPageEnabled': printTicketStore.fitToPage.getValue(),
378         'pageWidth': documentInfo.pageSize.width,
379         'pageHeight': documentInfo.pageSize.height,
380         'showSystemDialog': opt_showSystemDialog
381       };
383       if (!destination.isLocal) {
384         // We can't set cloudPrintID if the destination is "Print with Cloud
385         // Print" because the native system will try to print to Google Cloud
386         // Print with this ID instead of opening a Google Cloud Print dialog.
387         ticket['cloudPrintID'] = destination.id;
388       }
390       if (printTicketStore.marginsType.isCapabilityAvailable() &&
391           printTicketStore.marginsType.isValueEqual(
392               print_preview.ticket_items.MarginsType.Value.CUSTOM)) {
393         var customMargins = printTicketStore.customMargins.getValue();
394         var orientationEnum =
395             print_preview.ticket_items.CustomMargins.Orientation;
396         ticket['marginsCustom'] = {
397           'marginTop': customMargins.get(orientationEnum.TOP),
398           'marginRight': customMargins.get(orientationEnum.RIGHT),
399           'marginBottom': customMargins.get(orientationEnum.BOTTOM),
400           'marginLeft': customMargins.get(orientationEnum.LEFT)
401         };
402       }
404       if (destination.isPrivet || destination.isExtension) {
405         ticket['ticket'] = printTicketStore.createPrintTicket(destination);
406         ticket['capabilities'] = JSON.stringify(destination.capabilities);
407       }
409       if (opt_isOpenPdfInPreview) {
410         ticket['OpenPDFInPreview'] = true;
411       }
413       chrome.send('print', [JSON.stringify(ticket)]);
414     },
416     /** Requests that the current pending print request be cancelled. */
417     startCancelPendingPrint: function() {
418       chrome.send('cancelPendingPrintRequest');
419     },
421     /** Shows the system's native printing dialog. */
422     startShowSystemDialog: function() {
423       assert(!cr.isWindows);
424       chrome.send('showSystemDialog');
425     },
427     /** Closes the print preview dialog. */
428     startCloseDialog: function() {
429       chrome.send('closePrintPreviewDialog');
430       chrome.send('dialogClose');
431     },
433     /** Hide the print preview dialog and allow the native layer to close it. */
434     startHideDialog: function() {
435       chrome.send('hidePreview');
436     },
438     /**
439      * Opens the Google Cloud Print sign-in tab. The DESTINATIONS_RELOAD event
440      *     will be dispatched in response.
441      * @param {boolean} addAccount Whether to open an 'add a new account' or
442      *     default sign in page.
443      */
444     startCloudPrintSignIn: function(addAccount) {
445       chrome.send('signIn', [addAccount]);
446     },
448     /** Navigates the user to the system printer settings interface. */
449     startManageLocalDestinations: function() {
450       chrome.send('manageLocalPrinters');
451     },
453     /**
454      * Navigates the user to the Google Cloud Print management page.
455      * @param {?string} user Email address of the user to open the management
456      *     page for (user must be currently logged in, indeed) or {@code null}
457      *     to open this page for the primary user.
458      */
459     startManageCloudDestinations: function(user) {
460       chrome.send('manageCloudPrinters', [user || '']);
461     },
463     /** Forces browser to open a new tab with the given URL address. */
464     startForceOpenNewTab: function(url) {
465       chrome.send('forceOpenNewTab', [url]);
466     },
468     /**
469      * @param {!Object} initialSettings Object containing all initial settings.
470      */
471     onSetInitialSettings_: function(initialSettings) {
472       var numberFormatSymbols =
473           print_preview.MeasurementSystem.parseNumberFormat(
474               initialSettings['numberFormat']);
475       var unitType = print_preview.MeasurementSystem.UnitType.IMPERIAL;
476       if (initialSettings['measurementSystem'] != null) {
477         unitType = initialSettings['measurementSystem'];
478       }
480       var nativeInitialSettings = new print_preview.NativeInitialSettings(
481           initialSettings['printAutomaticallyInKioskMode'] || false,
482           initialSettings['appKioskMode'] || false,
483           initialSettings['hidePrintWithSystemDialogLink'] || false,
484           numberFormatSymbols[0] || ',',
485           numberFormatSymbols[1] || '.',
486           unitType,
487           initialSettings['previewModifiable'] || false,
488           initialSettings['initiatorTitle'] || '',
489           initialSettings['documentHasSelection'] || false,
490           initialSettings['shouldPrintSelectionOnly'] || false,
491           initialSettings['printerName'] || null,
492           initialSettings['appState'] || null);
494       var initialSettingsSetEvent = new Event(
495           NativeLayer.EventType.INITIAL_SETTINGS_SET);
496       initialSettingsSetEvent.initialSettings = nativeInitialSettings;
497       this.dispatchEvent(initialSettingsSetEvent);
498     },
500     /**
501      * Turn on the integration of Cloud Print.
502      * @param {{cloudPrintURL: string, appKioskMode: string}} settings
503      *     cloudPrintUrl: The URL to use for cloud print servers.
504      * @private
505      */
506     onSetUseCloudPrint_: function(settings) {
507       var cloudPrintEnableEvent = new Event(
508           NativeLayer.EventType.CLOUD_PRINT_ENABLE);
509       cloudPrintEnableEvent.baseCloudPrintUrl = settings['cloudPrintUrl'] || '';
510       cloudPrintEnableEvent.appKioskMode = settings['appKioskMode'] || false;
511       this.dispatchEvent(cloudPrintEnableEvent);
512     },
514     /**
515      * Updates the print preview with local printers.
516      * Called from PrintPreviewHandler::SetupPrinterList().
517      * @param {Array} printers Array of printer info objects.
518      * @private
519      */
520     onSetPrinters_: function(printers) {
521       var localDestsSetEvent = new Event(
522           NativeLayer.EventType.LOCAL_DESTINATIONS_SET);
523       localDestsSetEvent.destinationInfos = printers;
524       this.dispatchEvent(localDestsSetEvent);
525     },
527     /**
528      * Called when native layer gets settings information for a requested local
529      * destination.
530      * @param {Object} settingsInfo printer setting information.
531      * @private
532      */
533     onUpdateWithPrinterCapabilities_: function(settingsInfo) {
534       var capsSetEvent = new Event(NativeLayer.EventType.CAPABILITIES_SET);
535       capsSetEvent.settingsInfo = settingsInfo;
536       this.dispatchEvent(capsSetEvent);
537     },
539     /**
540      * Called when native layer gets settings information for a requested local
541      * destination.
542      * @param {string} destinationId Printer affected by error.
543      * @private
544      */
545     onFailedToGetPrinterCapabilities_: function(destinationId) {
546       var getCapsFailEvent = new Event(
547           NativeLayer.EventType.GET_CAPABILITIES_FAIL);
548       getCapsFailEvent.destinationId = destinationId;
549       getCapsFailEvent.destinationOrigin =
550           print_preview.Destination.Origin.LOCAL;
551       this.dispatchEvent(getCapsFailEvent);
552     },
554     /**
555      * Called when native layer gets settings information for a requested privet
556      * destination.
557      * @param {string} destinationId Printer affected by error.
558      * @private
559      */
560     onFailedToGetPrivetPrinterCapabilities_: function(destinationId) {
561       var getCapsFailEvent = new Event(
562           NativeLayer.EventType.GET_CAPABILITIES_FAIL);
563       getCapsFailEvent.destinationId = destinationId;
564       getCapsFailEvent.destinationOrigin =
565           print_preview.Destination.Origin.PRIVET;
566       this.dispatchEvent(getCapsFailEvent);
567     },
569     /**
570      * Called when native layer fails to get settings information for a
571      * requested extension destination.
572      * @param {string} destinationId Printer affected by error.
573      * @private
574      */
575     onFailedToGetExtensionPrinterCapabilities_: function(destinationId) {
576       var getCapsFailEvent = new Event(
577           NativeLayer.EventType.GET_CAPABILITIES_FAIL);
578       getCapsFailEvent.destinationId = destinationId;
579       getCapsFailEvent.destinationOrigin =
580           print_preview.Destination.Origin.EXTENSION;
581       this.dispatchEvent(getCapsFailEvent);
582     },
584     /** Reloads the printer list. */
585     onReloadPrintersList_: function() {
586       cr.dispatchSimpleEvent(this, NativeLayer.EventType.DESTINATIONS_RELOAD);
587     },
589     /**
590      * Called from the C++ layer.
591      * Take the PDF data handed to us and submit it to the cloud, closing the
592      * print preview dialog once the upload is successful.
593      * @param {string} data Data to send as the print job.
594      * @private
595      */
596     onPrintToCloud_: function(data) {
597       var printToCloudEvent = new Event(
598           NativeLayer.EventType.PRINT_TO_CLOUD);
599       printToCloudEvent.data = data;
600       this.dispatchEvent(printToCloudEvent);
601     },
603     /**
604      * Called from PrintPreviewUI::OnFileSelectionCancelled to notify the print
605      * preview dialog regarding the file selection cancel event.
606      * @private
607      */
608     onFileSelectionCancelled_: function() {
609       cr.dispatchSimpleEvent(this, NativeLayer.EventType.FILE_SELECTION_CANCEL);
610     },
612     /**
613      * Called from PrintPreviewUI::OnFileSelectionCompleted to notify the print
614      * preview dialog regarding the file selection completed event.
615      * @private
616      */
617     onFileSelectionCompleted_: function() {
618       // If the file selection is completed and the dialog is not already closed
619       // it means that a pending print to pdf request exists.
620       cr.dispatchSimpleEvent(
621           this, NativeLayer.EventType.FILE_SELECTION_COMPLETE);
622     },
624     /**
625      * Display an error message when print preview fails.
626      * Called from PrintPreviewMessageHandler::OnPrintPreviewFailed().
627      * @private
628      */
629     onPrintPreviewFailed_: function() {
630       cr.dispatchSimpleEvent(
631           this, NativeLayer.EventType.PREVIEW_GENERATION_FAIL);
632     },
634     /**
635      * Display an error message when encountered invalid printer settings.
636      * Called from PrintPreviewMessageHandler::OnInvalidPrinterSettings().
637      * @private
638      */
639     onInvalidPrinterSettings_: function() {
640       cr.dispatchSimpleEvent(this, NativeLayer.EventType.SETTINGS_INVALID);
641     },
643     /**
644      * @param {{contentWidth: number, contentHeight: number, marginLeft: number,
645      *          marginRight: number, marginTop: number, marginBottom: number,
646      *          printableAreaX: number, printableAreaY: number,
647      *          printableAreaWidth: number, printableAreaHeight: number}}
648      *          pageLayout Specifies default page layout details in points.
649      * @param {boolean} hasCustomPageSizeStyle Indicates whether the previewed
650      *     document has a custom page size style.
651      * @private
652      */
653     onDidGetDefaultPageLayout_: function(pageLayout, hasCustomPageSizeStyle) {
654       var pageLayoutChangeEvent = new Event(
655           NativeLayer.EventType.PAGE_LAYOUT_READY);
656       pageLayoutChangeEvent.pageLayout = pageLayout;
657       pageLayoutChangeEvent.hasCustomPageSizeStyle = hasCustomPageSizeStyle;
658       this.dispatchEvent(pageLayoutChangeEvent);
659     },
661     /**
662      * Update the page count and check the page range.
663      * Called from PrintPreviewUI::OnDidGetPreviewPageCount().
664      * @param {number} pageCount The number of pages.
665      * @param {number} previewResponseId The preview request id that resulted in
666      *      this response.
667      * @private
668      */
669     onDidGetPreviewPageCount_: function(pageCount, previewResponseId) {
670       var pageCountChangeEvent = new Event(
671           NativeLayer.EventType.PAGE_COUNT_READY);
672       pageCountChangeEvent.pageCount = pageCount;
673       pageCountChangeEvent.previewResponseId = previewResponseId;
674       this.dispatchEvent(pageCountChangeEvent);
675     },
677     /**
678      * Notification that a print preview page has been rendered.
679      * Check if the settings have changed and request a regeneration if needed.
680      * Called from PrintPreviewUI::OnDidPreviewPage().
681      * @param {number} pageNumber The page number, 0-based.
682      * @param {number} previewUid Preview unique identifier.
683      * @param {number} previewResponseId The preview request id that resulted in
684      *     this response.
685      * @private
686      */
687     onDidPreviewPage_: function(pageNumber, previewUid, previewResponseId) {
688       var pagePreviewGenEvent = new Event(
689           NativeLayer.EventType.PAGE_PREVIEW_READY);
690       pagePreviewGenEvent.pageIndex = pageNumber;
691       pagePreviewGenEvent.previewUid = previewUid;
692       pagePreviewGenEvent.previewResponseId = previewResponseId;
693       this.dispatchEvent(pagePreviewGenEvent);
694     },
696     /**
697      * Notification that access token is ready.
698      * @param {string} authType Type of access token.
699      * @param {string} accessToken Access token.
700      * @private
701      */
702     onDidGetAccessToken_: function(authType, accessToken) {
703       var getAccessTokenEvent = new Event(
704           NativeLayer.EventType.ACCESS_TOKEN_READY);
705       getAccessTokenEvent.authType = authType;
706       getAccessTokenEvent.accessToken = accessToken;
707       this.dispatchEvent(getAccessTokenEvent);
708     },
710     /**
711      * Update the print preview when new preview data is available.
712      * Create the PDF plugin as needed.
713      * Called from PrintPreviewUI::PreviewDataIsAvailable().
714      * @param {number} previewUid Preview unique identifier.
715      * @param {number} previewResponseId The preview request id that resulted in
716      *     this response.
717      * @private
718      */
719     onUpdatePrintPreview_: function(previewUid, previewResponseId) {
720       var previewGenDoneEvent = new Event(
721           NativeLayer.EventType.PREVIEW_GENERATION_DONE);
722       previewGenDoneEvent.previewUid = previewUid;
723       previewGenDoneEvent.previewResponseId = previewResponseId;
724       this.dispatchEvent(previewGenDoneEvent);
725     },
727     /**
728      * Updates print preset options from source PDF document.
729      * Called from PrintPreviewUI::OnSetOptionsFromDocument().
730      * @param {{disableScaling: boolean, copies: number,
731      *          duplex: number}} options Specifies
732      *     printing options according to source document presets.
733      * @private
734      */
735     onPrintPresetOptionsFromDocument_: function(options) {
736       var printPresetOptionsEvent = new Event(
737           NativeLayer.EventType.PRINT_PRESET_OPTIONS);
738       printPresetOptionsEvent.optionsFromDocument = options;
739       this.dispatchEvent(printPresetOptionsEvent);
740     },
742     /**
743       * Updates the interface to show the "Distill Page" option
744       * when PrintPreviewHandler::HandleIsPageDistillableResult
745       * determines that this page can be distilled with the
746       * DOM Distiller.
747       * @private
748       */
749      detectDistillablePage_: function() {
750        var allowDistillPageEvent = new Event(
751            NativeLayer.EventType.ALLOW_DISTILL_PAGE);
752        this.dispatchEvent(allowDistillPageEvent);
753      },
755     /**
756      * Simulates a user click on the print preview dialog cancel button. Used
757      * only for testing.
758      * @private
759      */
760     autoCancelForTesting_: function() {
761       var properties = {view: window, bubbles: true, cancelable: true};
762       var click = new MouseEvent('click', properties);
763       document.querySelector('#print-header .cancel').dispatchEvent(click);
764     },
766     /**
767      * @param {{serviceName: string, name: string}} printer Specifies
768      *     information about the printer that was added.
769      * @private
770      */
771     onPrivetPrinterChanged_: function(printer) {
772       var privetPrinterChangedEvent =
773             new Event(NativeLayer.EventType.PRIVET_PRINTER_CHANGED);
774       privetPrinterChangedEvent.printer = printer;
775       this.dispatchEvent(privetPrinterChangedEvent);
776     },
778     /**
779      * @param {Object} printer Specifies information about the printer that was
780      *    added.
781      * @private
782      */
783     onPrivetCapabilitiesSet_: function(printer, capabilities) {
784       var privetCapabilitiesSetEvent =
785             new Event(NativeLayer.EventType.PRIVET_CAPABILITIES_SET);
786       privetCapabilitiesSetEvent.printer = printer;
787       privetCapabilitiesSetEvent.capabilities = capabilities;
788       this.dispatchEvent(privetCapabilitiesSetEvent);
789     },
791     /**
792      * @param {string} http_error The HTTP response code or -1 if not an HTTP
793      *    error.
794      * @private
795      */
796     onPrivetPrintFailed_: function(http_error) {
797       var privetPrintFailedEvent =
798             new Event(NativeLayer.EventType.PRIVET_PRINT_FAILED);
799       privetPrintFailedEvent.httpError = http_error;
800       this.dispatchEvent(privetPrintFailedEvent);
801     },
803     /**
804      * @param {Array<!{extensionId: string,
805      *                 extensionName: string,
806      *                 id: string,
807      *                 name: string,
808      *                 description: (string|undefined),
809      *                 provisional: (boolean|undefined)}>} printers The list
810      *     containing information about printers added by an extension.
811      * @param {boolean} done Whether this is the final list of extension
812      *     managed printers.
813      */
814     onExtensionPrintersAdded_: function(printers, done) {
815       var event = new Event(NativeLayer.EventType.EXTENSION_PRINTERS_ADDED);
816       event.printers = printers;
817       event.done = done;
818       this.dispatchEvent(event);
819     },
821     /**
822      * Called when an extension responds to a request for an extension printer
823      * capabilities.
824      * @param {string} printerId The printer's ID.
825      * @param {!Object} capabilities The reported printer capabilities.
826      */
827     onExtensionCapabilitiesSet_: function(printerId,
828                                           capabilities) {
829       var event = new Event(NativeLayer.EventType.EXTENSION_CAPABILITIES_SET);
830       event.printerId = printerId;
831       event.capabilities = capabilities;
832       this.dispatchEvent(event);
833     },
835     /**
836      * Called when Chrome reports that attempt to resolve a provisional
837      * destination failed.
838      * @param {string} destinationId The provisional destination ID.
839      * @private
840      */
841     failedToResolveProvisionalDestination_: function(destinationId) {
842       var evt = new Event(
843           NativeLayer.EventType.PROVISIONAL_DESTINATION_RESOLVED);
844       evt.provisionalId = destinationId;
845       evt.destination = null;
846       this.dispatchEvent(evt);
847     },
849     /**
850      * Called when Chrome reports that a provisional destination has been
851      * successfully resolved.
852      * Currently used only for extension provided destinations.
853      * @param {string} provisionalDestinationId The provisional destination id.
854      * @param {!{extensionId: string,
855      *           extensionName: string,
856      *           id: string,
857      *           name: string,
858      *           description: (string|undefined)}} destinationInfo The resolved
859      *     destination info.
860      * @private
861      */
862     onProvisionalDestinationResolved_: function(provisionalDestinationId,
863                                                 destinationInfo) {
864       var evt = new Event(
865           NativeLayer.EventType.PROVISIONAL_DESTINATION_RESOLVED);
866       evt.provisionalId = provisionalDestinationId;
867       evt.destination = destinationInfo;
868       this.dispatchEvent(evt);
869     },
871    /**
872      * Allows for onManipulateSettings to be called
873      * from the native layer.
874      * @private
875      */
876     onEnableManipulateSettingsForTest_: function() {
877       global.onManipulateSettingsForTest =
878           this.onManipulateSettingsForTest_.bind(this);
879     },
881     /**
882      * Dispatches an event to print_preview.js to change
883      * a particular setting for print preview.
884      * @param {!print_preview.PreviewSettings} settings Object containing the
885      *     value to be changed and that value should be set to.
886      * @private
887      */
888     onManipulateSettingsForTest_: function(settings) {
889       var manipulateSettingsEvent =
890           new Event(NativeLayer.EventType.MANIPULATE_SETTINGS_FOR_TEST);
891       manipulateSettingsEvent.settings = settings;
892       this.dispatchEvent(manipulateSettingsEvent);
893     },
895     /**
896      * Sends a message to the test, letting it know that an
897      * option has been set to a particular value and that the change has
898      * finished modifying the preview area.
899      */
900     previewReadyForTest: function() {
901       if (global.onManipulateSettingsForTest)
902         chrome.send('UILoadedForTest');
903     },
905     /**
906      * Notifies the test that the option it tried to change
907      * had not been changed successfully.
908      */
909     previewFailedForTest: function() {
910       if (global.onManipulateSettingsForTest)
911         chrome.send('UIFailedLoadingForTest');
912     }
913   };
915   /**
916    * Initial settings retrieved from the native layer.
917    * @param {boolean} isInKioskAutoPrintMode Whether the print preview should be
918    *     in auto-print mode.
919    * @param {boolean} isInAppKioskMode Whether the print preview is in App Kiosk
920    *     mode.
921    * @param {string} thousandsDelimeter Character delimeter of thousands digits.
922    * @param {string} decimalDelimeter Character delimeter of the decimal point.
923    * @param {!print_preview.MeasurementSystem.UnitType} unitType Unit type of
924    *     local machine's measurement system.
925    * @param {boolean} isDocumentModifiable Whether the document to print is
926    *     modifiable.
927    * @param {string} documentTitle Title of the document.
928    * @param {boolean} documentHasSelection Whether the document has selected
929    *     content.
930    * @param {boolean} selectionOnly Whether only selected content should be
931    *     printed.
932    * @param {?string} systemDefaultDestinationId ID of the system default
933    *     destination.
934    * @param {?string} serializedAppStateStr Serialized app state.
935    * @constructor
936    */
937   function NativeInitialSettings(
938       isInKioskAutoPrintMode,
939       isInAppKioskMode,
940       hidePrintWithSystemDialogLink,
941       thousandsDelimeter,
942       decimalDelimeter,
943       unitType,
944       isDocumentModifiable,
945       documentTitle,
946       documentHasSelection,
947       selectionOnly,
948       systemDefaultDestinationId,
949       serializedAppStateStr) {
951     /**
952      * Whether the print preview should be in auto-print mode.
953      * @type {boolean}
954      * @private
955      */
956     this.isInKioskAutoPrintMode_ = isInKioskAutoPrintMode;
958     /**
959      * Whether the print preview should switch to App Kiosk mode.
960      * @type {boolean}
961      * @private
962      */
963     this.isInAppKioskMode_ = isInAppKioskMode;
965     /**
966      * Whether we should hide the link which shows the system print dialog.
967      * @type {boolean}
968      * @private
969      */
970     this.hidePrintWithSystemDialogLink_ = hidePrintWithSystemDialogLink;
972     /**
973      * Character delimeter of thousands digits.
974      * @type {string}
975      * @private
976      */
977     this.thousandsDelimeter_ = thousandsDelimeter;
979     /**
980      * Character delimeter of the decimal point.
981      * @type {string}
982      * @private
983      */
984     this.decimalDelimeter_ = decimalDelimeter;
986     /**
987      * Unit type of local machine's measurement system.
988      * @type {string}
989      * @private
990      */
991     this.unitType_ = unitType;
993     /**
994      * Whether the document to print is modifiable.
995      * @type {boolean}
996      * @private
997      */
998     this.isDocumentModifiable_ = isDocumentModifiable;
1000     /**
1001      * Title of the document.
1002      * @type {string}
1003      * @private
1004      */
1005     this.documentTitle_ = documentTitle;
1007     /**
1008      * Whether the document has selection.
1009      * @type {string}
1010      * @private
1011      */
1012     this.documentHasSelection_ = documentHasSelection;
1014     /**
1015      * Whether selection only should be printed.
1016      * @type {string}
1017      * @private
1018      */
1019     this.selectionOnly_ = selectionOnly;
1021     /**
1022      * ID of the system default destination.
1023      * @type {?string}
1024      * @private
1025      */
1026     this.systemDefaultDestinationId_ = systemDefaultDestinationId;
1028     /**
1029      * Serialized app state.
1030      * @type {?string}
1031      * @private
1032      */
1033     this.serializedAppStateStr_ = serializedAppStateStr;
1034   };
1036   NativeInitialSettings.prototype = {
1037     /**
1038      * @return {boolean} Whether the print preview should be in auto-print mode.
1039      */
1040     get isInKioskAutoPrintMode() {
1041       return this.isInKioskAutoPrintMode_;
1042     },
1044     /**
1045      * @return {boolean} Whether the print preview should switch to App Kiosk
1046      *     mode.
1047      */
1048     get isInAppKioskMode() {
1049       return this.isInAppKioskMode_;
1050     },
1052     /**
1053      * @return {boolean} Whether we should hide the link which shows the
1054            system print dialog.
1055      */
1056     get hidePrintWithSystemDialogLink() {
1057       return this.hidePrintWithSystemDialogLink_;
1058     },
1060     /** @return {string} Character delimeter of thousands digits. */
1061     get thousandsDelimeter() {
1062       return this.thousandsDelimeter_;
1063     },
1065     /** @return {string} Character delimeter of the decimal point. */
1066     get decimalDelimeter() {
1067       return this.decimalDelimeter_;
1068     },
1070     /**
1071      * @return {!print_preview.MeasurementSystem.UnitType} Unit type of local
1072      *     machine's measurement system.
1073      */
1074     get unitType() {
1075       return this.unitType_;
1076     },
1078     /** @return {boolean} Whether the document to print is modifiable. */
1079     get isDocumentModifiable() {
1080       return this.isDocumentModifiable_;
1081     },
1083     /** @return {string} Document title. */
1084     get documentTitle() {
1085       return this.documentTitle_;
1086     },
1088     /** @return {boolean} Whether the document has selection. */
1089     get documentHasSelection() {
1090       return this.documentHasSelection_;
1091     },
1093     /** @return {boolean} Whether selection only should be printed. */
1094     get selectionOnly() {
1095       return this.selectionOnly_;
1096     },
1098     /** @return {?string} ID of the system default destination. */
1099     get systemDefaultDestinationId() {
1100       return this.systemDefaultDestinationId_;
1101     },
1103     /** @return {?string} Serialized app state. */
1104     get serializedAppStateStr() {
1105       return this.serializedAppStateStr_;
1106     }
1107   };
1109   // Export
1110   return {
1111     NativeInitialSettings: NativeInitialSettings,
1112     NativeLayer: NativeLayer
1113   };