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