Only grant permissions to new extensions from sync if they have the expected version
[chromium-blink-merge.git] / chrome / browser / resources / print_preview / print_preview.js
blobcac34757b9ff6179876c7022585ac56056c344c1
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 // TODO(rltoscano): Move data/* into print_preview.data namespace
7 <include src="component.js">
8 <include src="print_preview_focus_manager.js">
10 cr.define('print_preview', function() {
11   'use strict';
13   /**
14    * Container class for Chromium's print preview.
15    * @constructor
16    * @extends {print_preview.Component}
17    */
18   function PrintPreview() {
19     print_preview.Component.call(this);
21     /**
22      * Used to communicate with Chromium's print system.
23      * @type {!print_preview.NativeLayer}
24      * @private
25      */
26     this.nativeLayer_ = new print_preview.NativeLayer();
28     /**
29      * Event target that contains information about the logged in user.
30      * @type {!print_preview.UserInfo}
31      * @private
32      */
33     this.userInfo_ = new print_preview.UserInfo();
35     /**
36      * Application state.
37      * @type {!print_preview.AppState}
38      * @private
39      */
40     this.appState_ = new print_preview.AppState();
42     /**
43      * Data model that holds information about the document to print.
44      * @type {!print_preview.DocumentInfo}
45      * @private
46      */
47     this.documentInfo_ = new print_preview.DocumentInfo();
49     /**
50      * Data store which holds print destinations.
51      * @type {!print_preview.DestinationStore}
52      * @private
53      */
54     this.destinationStore_ = new print_preview.DestinationStore(
55         this.nativeLayer_, this.userInfo_, this.appState_);
57     /**
58      * Data store which holds printer sharing invitations.
59      * @type {!print_preview.InvitationStore}
60      * @private
61      */
62     this.invitationStore_ = new print_preview.InvitationStore(this.userInfo_);
64     /**
65      * Storage of the print ticket used to create the print job.
66      * @type {!print_preview.PrintTicketStore}
67      * @private
68      */
69     this.printTicketStore_ = new print_preview.PrintTicketStore(
70         this.destinationStore_, this.appState_, this.documentInfo_);
72     /**
73      * Holds the print and cancel buttons and renders some document statistics.
74      * @type {!print_preview.PrintHeader}
75      * @private
76      */
77     this.printHeader_ = new print_preview.PrintHeader(
78         this.printTicketStore_, this.destinationStore_);
79     this.addChild(this.printHeader_);
81     /**
82      * Component used to search for print destinations.
83      * @type {!print_preview.DestinationSearch}
84      * @private
85      */
86     this.destinationSearch_ = new print_preview.DestinationSearch(
87         this.destinationStore_, this.invitationStore_, this.userInfo_);
88     this.addChild(this.destinationSearch_);
90     /**
91      * Component that renders the print destination.
92      * @type {!print_preview.DestinationSettings}
93      * @private
94      */
95     this.destinationSettings_ = new print_preview.DestinationSettings(
96         this.destinationStore_);
97     this.addChild(this.destinationSettings_);
99     /**
100      * Component that renders UI for entering in page range.
101      * @type {!print_preview.PageSettings}
102      * @private
103      */
104     this.pageSettings_ = new print_preview.PageSettings(
105         this.printTicketStore_.pageRange);
106     this.addChild(this.pageSettings_);
108     /**
109      * Component that renders the copies settings.
110      * @type {!print_preview.CopiesSettings}
111      * @private
112      */
113     this.copiesSettings_ = new print_preview.CopiesSettings(
114         this.printTicketStore_.copies, this.printTicketStore_.collate);
115     this.addChild(this.copiesSettings_);
117     /**
118      * Component that renders the media size settings.
119      * @type {!print_preview.MediaSizeSettings}
120      * @private
121      */
122     this.mediaSizeSettings_ =
123         new print_preview.MediaSizeSettings(this.printTicketStore_.mediaSize);
124     this.addChild(this.mediaSizeSettings_);
126     /**
127      * Component that renders the layout settings.
128      * @type {!print_preview.LayoutSettings}
129      * @private
130      */
131     this.layoutSettings_ =
132         new print_preview.LayoutSettings(this.printTicketStore_.landscape);
133     this.addChild(this.layoutSettings_);
135     /**
136      * Component that renders the color options.
137      * @type {!print_preview.ColorSettings}
138      * @private
139      */
140     this.colorSettings_ =
141         new print_preview.ColorSettings(this.printTicketStore_.color);
142     this.addChild(this.colorSettings_);
144     /**
145      * Component that renders a select box for choosing margin settings.
146      * @type {!print_preview.MarginSettings}
147      * @private
148      */
149     this.marginSettings_ =
150         new print_preview.MarginSettings(this.printTicketStore_.marginsType);
151     this.addChild(this.marginSettings_);
153     /**
154      * Component that renders the DPI settings.
155      * @type {!print_preview.DpiSettings}
156      * @private
157      */
158     this.dpiSettings_ =
159         new print_preview.DpiSettings(this.printTicketStore_.dpi);
160     this.addChild(this.dpiSettings_);
162     /**
163      * Component that renders miscellaneous print options.
164      * @type {!print_preview.OtherOptionsSettings}
165      * @private
166      */
167     this.otherOptionsSettings_ = new print_preview.OtherOptionsSettings(
168         this.printTicketStore_.duplex,
169         this.printTicketStore_.fitToPage,
170         this.printTicketStore_.cssBackground,
171         this.printTicketStore_.selectionOnly,
172         this.printTicketStore_.headerFooter,
173         this.printTicketStore_.distillPage);
174     this.addChild(this.otherOptionsSettings_);
176     /**
177      * Component that renders the advanced options button.
178      * @type {!print_preview.AdvancedOptionsSettings}
179      * @private
180      */
181     this.advancedOptionsSettings_ = new print_preview.AdvancedOptionsSettings(
182         this.printTicketStore_.vendorItems, this.destinationStore_);
183     this.addChild(this.advancedOptionsSettings_);
185     /**
186      * Component used to search for print destinations.
187      * @type {!print_preview.AdvancedSettings}
188      * @private
189      */
190     this.advancedSettings_ = new print_preview.AdvancedSettings(
191         this.printTicketStore_);
192     this.addChild(this.advancedSettings_);
194     var settingsSections = [
195         this.destinationSettings_,
196         this.pageSettings_,
197         this.copiesSettings_,
198         this.mediaSizeSettings_,
199         this.layoutSettings_,
200         this.marginSettings_,
201         this.colorSettings_,
202         this.dpiSettings_,
203         this.otherOptionsSettings_,
204         this.advancedOptionsSettings_];
205     /**
206      * Component representing more/less settings button.
207      * @type {!print_preview.MoreSettings}
208      * @private
209      */
210     this.moreSettings_ = new print_preview.MoreSettings(
211         this.destinationStore_, settingsSections);
212     this.addChild(this.moreSettings_);
214     /**
215      * Area of the UI that holds the print preview.
216      * @type {!print_preview.PreviewArea}
217      * @private
218      */
219     this.previewArea_ = new print_preview.PreviewArea(this.destinationStore_,
220                                                       this.printTicketStore_,
221                                                       this.nativeLayer_,
222                                                       this.documentInfo_);
223     this.addChild(this.previewArea_);
225     /**
226      * Interface to the Google Cloud Print API. Null if Google Cloud Print
227      * integration is disabled.
228      * @type {cloudprint.CloudPrintInterface}
229      * @private
230      */
231     this.cloudPrintInterface_ = null;
233     /**
234      * Whether in kiosk mode where print preview can print automatically without
235      * user intervention. See http://crbug.com/31395. Print will start when
236      * both the print ticket has been initialized, and an initial printer has
237      * been selected.
238      * @type {boolean}
239      * @private
240      */
241     this.isInKioskAutoPrintMode_ = false;
243     /**
244      * Whether Print Preview is in App Kiosk mode, basically, use only printers
245      * available for the device.
246      * @type {boolean}
247      * @private
248      */
249     this.isInAppKioskMode_ = false;
251     /**
252      * Whether Print with System Dialog link should be hidden. Overrides the
253      * default rules for System dialog link visibility.
254      * @type {boolean}
255      * @private
256      */
257     this.hideSystemDialogLink_ = true;
259     /**
260      * State of the print preview UI.
261      * @type {print_preview.PrintPreview.UiState_}
262      * @private
263      */
264     this.uiState_ = PrintPreview.UiState_.INITIALIZING;
266     /**
267      * Whether document preview generation is in progress.
268      * @type {boolean}
269      * @private
270      */
271     this.isPreviewGenerationInProgress_ = true;
273     /**
274      * Whether to show system dialog before next printing.
275      * @type {boolean}
276      * @private
277      */
278     this.showSystemDialogBeforeNextPrint_ = false;
279   };
281   /**
282    * States of the print preview.
283    * @enum {string}
284    * @private
285    */
286   PrintPreview.UiState_ = {
287     INITIALIZING: 'initializing',
288     READY: 'ready',
289     OPENING_PDF_PREVIEW: 'opening-pdf-preview',
290     OPENING_NATIVE_PRINT_DIALOG: 'opening-native-print-dialog',
291     PRINTING: 'printing',
292     FILE_SELECTION: 'file-selection',
293     CLOSING: 'closing',
294     ERROR: 'error'
295   };
297   /**
298    * What can happen when print preview tries to print.
299    * @enum {string}
300    * @private
301    */
302   PrintPreview.PrintAttemptResult_ = {
303     NOT_READY: 'not-ready',
304     PRINTED: 'printed',
305     READY_WAITING_FOR_PREVIEW: 'ready-waiting-for-preview'
306   };
308   PrintPreview.prototype = {
309     __proto__: print_preview.Component.prototype,
311     /** Sets up the page and print preview by getting the printer list. */
312     initialize: function() {
313       this.decorate($('print-preview'));
314       if (!this.previewArea_.hasCompatiblePlugin) {
315         this.setIsEnabled_(false);
316       }
317       this.nativeLayer_.startGetInitialSettings();
318       print_preview.PrintPreviewFocusManager.getInstance().initialize();
319       cr.ui.FocusOutlineManager.forDocument(document);
320     },
322     /** @override */
323     enterDocument: function() {
324       // Native layer events.
325       this.tracker.add(
326           this.nativeLayer_,
327           print_preview.NativeLayer.EventType.INITIAL_SETTINGS_SET,
328           this.onInitialSettingsSet_.bind(this));
329       this.tracker.add(
330           this.nativeLayer_,
331           print_preview.NativeLayer.EventType.CLOUD_PRINT_ENABLE,
332           this.onCloudPrintEnable_.bind(this));
333       this.tracker.add(
334           this.nativeLayer_,
335           print_preview.NativeLayer.EventType.PRINT_TO_CLOUD,
336           this.onPrintToCloud_.bind(this));
337       this.tracker.add(
338           this.nativeLayer_,
339           print_preview.NativeLayer.EventType.FILE_SELECTION_CANCEL,
340           this.onFileSelectionCancel_.bind(this));
341       this.tracker.add(
342           this.nativeLayer_,
343           print_preview.NativeLayer.EventType.FILE_SELECTION_COMPLETE,
344           this.onFileSelectionComplete_.bind(this));
345       this.tracker.add(
346           this.nativeLayer_,
347           print_preview.NativeLayer.EventType.SETTINGS_INVALID,
348           this.onSettingsInvalid_.bind(this));
349       this.tracker.add(
350           this.nativeLayer_,
351           print_preview.NativeLayer.EventType.PRINT_PRESET_OPTIONS,
352           this.onPrintPresetOptionsFromDocument_.bind(this));
353       this.tracker.add(
354           this.nativeLayer_,
355           print_preview.NativeLayer.EventType.PRIVET_PRINT_FAILED,
356           this.onPrivetPrintFailed_.bind(this));
357       this.tracker.add(
358           this.nativeLayer_,
359           print_preview.NativeLayer.EventType.MANIPULATE_SETTINGS_FOR_TEST,
360           this.onManipulateSettingsForTest_.bind(this));
361        this.tracker.add(
362           this.nativeLayer_,
363           print_preview.NativeLayer.EventType.ALLOW_DISTILL_PAGE,
364           this.onAllowDistillPage_.bind(this));
366       if ($('system-dialog-link')) {
367         this.tracker.add(
368             $('system-dialog-link'),
369             'click',
370             this.openSystemPrintDialog_.bind(this));
371       }
372       if ($('open-pdf-in-preview-link')) {
373         this.tracker.add(
374             $('open-pdf-in-preview-link'),
375             'click',
376             this.onOpenPdfInPreviewLinkClick_.bind(this));
377       }
379       this.tracker.add(
380           this.previewArea_,
381           print_preview.PreviewArea.EventType.PREVIEW_GENERATION_IN_PROGRESS,
382           this.onPreviewGenerationInProgress_.bind(this));
383       this.tracker.add(
384           this.previewArea_,
385           print_preview.PreviewArea.EventType.PREVIEW_GENERATION_DONE,
386           this.onPreviewGenerationDone_.bind(this));
387       this.tracker.add(
388           this.previewArea_,
389           print_preview.PreviewArea.EventType.PREVIEW_GENERATION_FAIL,
390           this.onPreviewGenerationFail_.bind(this));
391       this.tracker.add(
392           this.previewArea_,
393           print_preview.PreviewArea.EventType.OPEN_SYSTEM_DIALOG_CLICK,
394           this.openSystemPrintDialog_.bind(this));
396       this.tracker.add(
397           this.destinationStore_,
398           print_preview.DestinationStore.EventType.
399               SELECTED_DESTINATION_CAPABILITIES_READY,
400           this.printIfReady_.bind(this));
401       this.tracker.add(
402           this.destinationStore_,
403           print_preview.DestinationStore.EventType.DESTINATION_SELECT,
404           this.onDestinationSelect_.bind(this));
405       this.tracker.add(
406           this.destinationStore_,
407           print_preview.DestinationStore.EventType.DESTINATION_SEARCH_DONE,
408           this.onDestinationSearchDone_.bind(this));
410       this.tracker.add(
411           this.printHeader_,
412           print_preview.PrintHeader.EventType.PRINT_BUTTON_CLICK,
413           this.onPrintButtonClick_.bind(this));
414       this.tracker.add(
415           this.printHeader_,
416           print_preview.PrintHeader.EventType.CANCEL_BUTTON_CLICK,
417           this.onCancelButtonClick_.bind(this));
419       this.tracker.add(window, 'keydown', this.onKeyDown_.bind(this));
420       this.previewArea_.setPluginKeyEventCallback(this.onKeyDown_.bind(this));
422       this.tracker.add(
423           this.destinationSettings_,
424           print_preview.DestinationSettings.EventType.CHANGE_BUTTON_ACTIVATE,
425           this.onDestinationChangeButtonActivate_.bind(this));
427       this.tracker.add(
428           this.destinationSearch_,
429           print_preview.DestinationSearch.EventType.MANAGE_CLOUD_DESTINATIONS,
430           this.onManageCloudDestinationsActivated_.bind(this));
431       this.tracker.add(
432           this.destinationSearch_,
433           print_preview.DestinationSearch.EventType.MANAGE_LOCAL_DESTINATIONS,
434           this.onManageLocalDestinationsActivated_.bind(this));
435       this.tracker.add(
436           this.destinationSearch_,
437           print_preview.DestinationSearch.EventType.ADD_ACCOUNT,
438           this.onCloudPrintSignInActivated_.bind(this, true /*addAccount*/));
439       this.tracker.add(
440           this.destinationSearch_,
441           print_preview.DestinationSearch.EventType.SIGN_IN,
442           this.onCloudPrintSignInActivated_.bind(this, false /*addAccount*/));
443       this.tracker.add(
444           this.destinationSearch_,
445           print_preview.DestinationListItem.EventType.REGISTER_PROMO_CLICKED,
446           this.onCloudPrintRegisterPromoClick_.bind(this));
448       this.tracker.add(
449           this.advancedOptionsSettings_,
450           print_preview.AdvancedOptionsSettings.EventType.BUTTON_ACTIVATED,
451           this.onAdvancedOptionsButtonActivated_.bind(this));
453       // TODO(rltoscano): Move no-destinations-promo into its own component
454       // instead being part of PrintPreview.
455       this.tracker.add(
456           this.getChildElement('#no-destinations-promo .close-button'),
457           'click',
458           this.onNoDestinationsPromoClose_.bind(this));
459       this.tracker.add(
460           this.getChildElement('#no-destinations-promo .not-now-button'),
461           'click',
462           this.onNoDestinationsPromoClose_.bind(this));
463       this.tracker.add(
464           this.getChildElement('#no-destinations-promo .add-printer-button'),
465           'click',
466           this.onNoDestinationsPromoClick_.bind(this));
467     },
469     /** @override */
470     decorateInternal: function() {
471       this.printHeader_.decorate($('print-header'));
472       this.destinationSearch_.decorate($('destination-search'));
473       this.destinationSettings_.decorate($('destination-settings'));
474       this.pageSettings_.decorate($('page-settings'));
475       this.copiesSettings_.decorate($('copies-settings'));
476       this.mediaSizeSettings_.decorate($('media-size-settings'));
477       this.layoutSettings_.decorate($('layout-settings'));
478       this.colorSettings_.decorate($('color-settings'));
479       this.marginSettings_.decorate($('margin-settings'));
480       this.dpiSettings_.decorate($('dpi-settings'));
481       this.otherOptionsSettings_.decorate($('other-options-settings'));
482       this.advancedOptionsSettings_.decorate($('advanced-options-settings'));
483       this.advancedSettings_.decorate($('advanced-settings'));
484       this.moreSettings_.decorate($('more-settings'));
485       this.previewArea_.decorate($('preview-area'));
486     },
488     /**
489      * Sets whether the controls in the print preview are enabled.
490      * @param {boolean} isEnabled Whether the controls in the print preview are
491      *     enabled.
492      * @private
493      */
494     setIsEnabled_: function(isEnabled) {
495       if ($('system-dialog-link'))
496         $('system-dialog-link').classList.toggle('disabled', !isEnabled);
497       if ($('open-pdf-in-preview-link'))
498         $('open-pdf-in-preview-link').classList.toggle('disabled', !isEnabled);
499       this.printHeader_.isEnabled = isEnabled;
500       this.destinationSettings_.isEnabled = isEnabled;
501       this.pageSettings_.isEnabled = isEnabled;
502       this.copiesSettings_.isEnabled = isEnabled;
503       this.mediaSizeSettings_.isEnabled = isEnabled;
504       this.layoutSettings_.isEnabled = isEnabled;
505       this.colorSettings_.isEnabled = isEnabled;
506       this.marginSettings_.isEnabled = isEnabled;
507       this.dpiSettings_.isEnabled = isEnabled;
508       this.otherOptionsSettings_.isEnabled = isEnabled;
509       this.advancedOptionsSettings_.isEnabled = isEnabled;
510     },
512     /**
513      * Prints the document or launches a pdf preview on the local system.
514      * @param {boolean} isPdfPreview Whether to launch the pdf preview.
515      * @private
516      */
517     printDocumentOrOpenPdfPreview_: function(isPdfPreview) {
518       assert(this.uiState_ == PrintPreview.UiState_.READY,
519              'Print document request received when not in ready state: ' +
520                  this.uiState_);
521       if (isPdfPreview) {
522         this.uiState_ = PrintPreview.UiState_.OPENING_PDF_PREVIEW;
523       } else if (this.destinationStore_.selectedDestination.id ==
524           print_preview.Destination.GooglePromotedId.SAVE_AS_PDF) {
525         this.uiState_ = PrintPreview.UiState_.FILE_SELECTION;
526       } else {
527         this.uiState_ = PrintPreview.UiState_.PRINTING;
528       }
529       this.setIsEnabled_(false);
530       this.printHeader_.isCancelButtonEnabled = true;
531       var printAttemptResult = this.printIfReady_();
532       if (printAttemptResult == PrintPreview.PrintAttemptResult_.PRINTED ||
533           printAttemptResult ==
534               PrintPreview.PrintAttemptResult_.READY_WAITING_FOR_PREVIEW) {
535         if ((this.destinationStore_.selectedDestination.isLocal &&
536              !this.destinationStore_.selectedDestination.isPrivet &&
537              !this.destinationStore_.selectedDestination.isExtension &&
538              this.destinationStore_.selectedDestination.id !=
539                  print_preview.Destination.GooglePromotedId.SAVE_AS_PDF) ||
540              this.uiState_ == PrintPreview.UiState_.OPENING_PDF_PREVIEW) {
541           // Hide the dialog for now. The actual print command will be issued
542           // when the preview generation is done.
543           this.nativeLayer_.startHideDialog();
544         }
545       }
546     },
548     /**
549      * Attempts to print if needed and if ready.
550      * @return {PrintPreview.PrintAttemptResult_} Attempt result.
551      * @private
552      */
553     printIfReady_: function() {
554       var okToPrint =
555           (this.uiState_ == PrintPreview.UiState_.PRINTING ||
556            this.uiState_ == PrintPreview.UiState_.OPENING_PDF_PREVIEW ||
557            this.uiState_ == PrintPreview.UiState_.FILE_SELECTION ||
558            this.isInKioskAutoPrintMode_) &&
559           this.destinationStore_.selectedDestination &&
560           this.destinationStore_.selectedDestination.capabilities;
561       if (!okToPrint) {
562         return PrintPreview.PrintAttemptResult_.NOT_READY;
563       }
564       if (this.isPreviewGenerationInProgress_) {
565         return PrintPreview.PrintAttemptResult_.READY_WAITING_FOR_PREVIEW;
566       }
567       assert(this.printTicketStore_.isTicketValid(),
568           'Trying to print with invalid ticket');
569       if (getIsVisible(this.moreSettings_.getElement())) {
570         new print_preview.PrintSettingsUiMetricsContext().record(
571             this.moreSettings_.isExpanded ?
572                 print_preview.Metrics.PrintSettingsUiBucket.
573                     PRINT_WITH_SETTINGS_EXPANDED :
574                 print_preview.Metrics.PrintSettingsUiBucket.
575                     PRINT_WITH_SETTINGS_COLLAPSED);
576       }
577       this.nativeLayer_.startPrint(
578           this.destinationStore_.selectedDestination,
579           this.printTicketStore_,
580           this.cloudPrintInterface_,
581           this.documentInfo_,
582           this.uiState_ == PrintPreview.UiState_.OPENING_PDF_PREVIEW,
583           this.showSystemDialogBeforeNextPrint_);
584       this.showSystemDialogBeforeNextPrint_ = false;
585       return PrintPreview.PrintAttemptResult_.PRINTED;
586     },
588     /**
589      * Closes the print preview.
590      * @private
591      */
592     close_: function() {
593       this.exitDocument();
594       this.uiState_ = PrintPreview.UiState_.CLOSING;
595       this.nativeLayer_.startCloseDialog();
596     },
598     /**
599      * Opens the native system print dialog after disabling all controls.
600      * @private
601      */
602     openSystemPrintDialog_: function() {
603       if (!this.shouldShowSystemDialogLink_())
604         return;
605       if ($('system-dialog-link').classList.contains('disabled'))
606         return;
607       if (cr.isWindows) {
608         this.showSystemDialogBeforeNextPrint_ = true;
609         this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);
610         return;
611       }
612       setIsVisible(getRequiredElement('system-dialog-throbber'), true);
613       this.setIsEnabled_(false);
614       this.uiState_ = PrintPreview.UiState_.OPENING_NATIVE_PRINT_DIALOG;
615       this.nativeLayer_.startShowSystemDialog();
616     },
618     /**
619      * Called when the native layer has initial settings to set. Sets the
620      * initial settings of the print preview and begins fetching print
621      * destinations.
622      * @param {Event} event Contains the initial print preview settings
623      *     persisted through the session.
624      * @private
625      */
626     onInitialSettingsSet_: function(event) {
627       assert(this.uiState_ == PrintPreview.UiState_.INITIALIZING,
628              'Updating initial settings when not in initializing state: ' +
629                  this.uiState_);
630       this.uiState_ = PrintPreview.UiState_.READY;
632       var settings = event.initialSettings;
633       this.isInKioskAutoPrintMode_ = settings.isInKioskAutoPrintMode;
634       this.isInAppKioskMode_ = settings.isInAppKioskMode;
636       // The following components must be initialized in this order.
637       this.appState_.init(
638           settings.serializedAppStateStr,
639           settings.systemDefaultDestinationId);
640       this.documentInfo_.init(
641           settings.isDocumentModifiable,
642           settings.documentTitle,
643           settings.documentHasSelection);
644       this.printTicketStore_.init(
645           settings.thousandsDelimeter,
646           settings.decimalDelimeter,
647           settings.unitType,
648           settings.selectionOnly);
649       this.destinationStore_.init(settings.isInAppKioskMode);
650       this.appState_.setInitialized();
652       $('document-title').innerText = settings.documentTitle;
653       this.hideSystemDialogLink_ = settings.hidePrintWithSystemDialogLink ||
654                                    settings.isInAppKioskMode;
655       if ($('system-dialog-link')) {
656         setIsVisible($('system-dialog-link'),
657                      this.shouldShowSystemDialogLink_());
658       }
659     },
661     /**
662      * Calls when the native layer enables Google Cloud Print integration.
663      * Fetches the user's cloud printers.
664      * @param {Event} event Contains the base URL of the Google Cloud Print
665      *     service.
666      * @private
667      */
668     onCloudPrintEnable_: function(event) {
669       this.cloudPrintInterface_ = new cloudprint.CloudPrintInterface(
670           event.baseCloudPrintUrl,
671           this.nativeLayer_,
672           this.userInfo_,
673           event.appKioskMode);
674       this.tracker.add(
675           this.cloudPrintInterface_,
676           cloudprint.CloudPrintInterface.EventType.SUBMIT_DONE,
677           this.onCloudPrintSubmitDone_.bind(this));
678       this.tracker.add(
679           this.cloudPrintInterface_,
680           cloudprint.CloudPrintInterface.EventType.SEARCH_FAILED,
681           this.onCloudPrintError_.bind(this));
682       this.tracker.add(
683           this.cloudPrintInterface_,
684           cloudprint.CloudPrintInterface.EventType.SUBMIT_FAILED,
685           this.onCloudPrintError_.bind(this));
686       this.tracker.add(
687           this.cloudPrintInterface_,
688           cloudprint.CloudPrintInterface.EventType.PRINTER_FAILED,
689           this.onCloudPrintError_.bind(this));
690       this.tracker.add(
691           this.cloudPrintInterface_,
692           cloudprint.CloudPrintInterface.EventType.
693               UPDATE_PRINTER_TOS_ACCEPTANCE_FAILED,
694           this.onCloudPrintError_.bind(this));
696       this.destinationStore_.setCloudPrintInterface(this.cloudPrintInterface_);
697       this.invitationStore_.setCloudPrintInterface(this.cloudPrintInterface_);
698       if (this.destinationSearch_.getIsVisible()) {
699         this.destinationStore_.startLoadCloudDestinations();
700         this.invitationStore_.startLoadingInvitations();
701       }
702     },
704     /**
705      * Called from the native layer when ready to print to Google Cloud Print.
706      * @param {Event} event Contains the body to send in the HTTP request.
707      * @private
708      */
709     onPrintToCloud_: function(event) {
710       assert(this.uiState_ == PrintPreview.UiState_.PRINTING,
711              'Document ready to be sent to the cloud when not in printing ' +
712                  'state: ' + this.uiState_);
713       assert(this.cloudPrintInterface_ != null,
714              'Google Cloud Print is not enabled');
715       this.cloudPrintInterface_.submit(
716           this.destinationStore_.selectedDestination,
717           this.printTicketStore_,
718           this.documentInfo_,
719           event.data);
720     },
722     /**
723      * Called from the native layer when the user cancels the save-to-pdf file
724      * selection dialog.
725      * @private
726      */
727     onFileSelectionCancel_: function() {
728       assert(this.uiState_ == PrintPreview.UiState_.FILE_SELECTION,
729              'File selection cancelled when not in file-selection state: ' +
730                  this.uiState_);
731       this.setIsEnabled_(true);
732       this.uiState_ = PrintPreview.UiState_.READY;
733     },
735     /**
736      * Called from the native layer when save-to-pdf file selection is complete.
737      * @private
738      */
739     onFileSelectionComplete_: function() {
740       assert(this.uiState_ == PrintPreview.UiState_.FILE_SELECTION,
741              'File selection completed when not in file-selection state: ' +
742                  this.uiState_);
743       this.previewArea_.showCustomMessage(
744           loadTimeData.getString('printingToPDFInProgress'));
745       this.uiState_ = PrintPreview.UiState_.PRINTING;
746     },
748     /**
749      * Called after successfully submitting a job to Google Cloud Print.
750      * @param {!Event} event Contains the ID of the submitted print job.
751      * @private
752      */
753     onCloudPrintSubmitDone_: function(event) {
754       assert(this.uiState_ == PrintPreview.UiState_.PRINTING,
755              'Submited job to Google Cloud Print but not in printing state ' +
756                  this.uiState_);
757       if (this.destinationStore_.selectedDestination.id ==
758               print_preview.Destination.GooglePromotedId.FEDEX) {
759         this.nativeLayer_.startForceOpenNewTab(
760             'https://www.google.com/cloudprint/fedexcode.html?jobid=' +
761             event.jobId);
762       }
763       this.close_();
764     },
766     /**
767      * Called when there was an error communicating with Google Cloud print.
768      * Displays an error message in the print header.
769      * @param {!Event} event Contains the error message.
770      * @private
771      */
772     onCloudPrintError_: function(event) {
773       if (event.status == 403) {
774         if (!this.isInAppKioskMode_) {
775           this.destinationSearch_.showCloudPrintPromo();
776         }
777       } else if (event.status == 0) {
778         return; // Ignore, the system does not have internet connectivity.
779       } else {
780         this.printHeader_.setErrorMessage(event.message);
781       }
782       if (event.status == 200) {
783         console.error('Google Cloud Print Error: (' + event.errorCode + ') ' +
784                       event.message);
785       } else {
786         console.error('Google Cloud Print Error: HTTP status ' + event.status);
787       }
788     },
790     /**
791      * Called when the preview area's preview generation is in progress.
792      * @private
793      */
794     onPreviewGenerationInProgress_: function() {
795       this.isPreviewGenerationInProgress_ = true;
796     },
798     /**
799      * Called when the preview area's preview generation is complete.
800      * @private
801      */
802     onPreviewGenerationDone_: function() {
803       this.isPreviewGenerationInProgress_ = false;
804       this.printHeader_.isPrintButtonEnabled = true;
805       this.nativeLayer_.previewReadyForTest();
806       this.printIfReady_();
807     },
809     /**
810      * Called when the preview area's preview failed to load.
811      * @private
812      */
813     onPreviewGenerationFail_: function() {
814       this.isPreviewGenerationInProgress_ = false;
815       this.printHeader_.isPrintButtonEnabled = false;
816       if (this.uiState_ == PrintPreview.UiState_.PRINTING)
817         this.nativeLayer_.startCancelPendingPrint();
818     },
820     /**
821      * Called when the 'Open pdf in preview' link is clicked. Launches the pdf
822      * preview app.
823      * @private
824      */
825     onOpenPdfInPreviewLinkClick_: function() {
826       if ($('open-pdf-in-preview-link').classList.contains('disabled'))
827         return;
828       assert(this.uiState_ == PrintPreview.UiState_.READY,
829              'Trying to open pdf in preview when not in ready state: ' +
830                  this.uiState_);
831       setIsVisible(getRequiredElement('open-preview-app-throbber'), true);
832       this.previewArea_.showCustomMessage(
833           loadTimeData.getString('openingPDFInPreview'));
834       this.printDocumentOrOpenPdfPreview_(true /*isPdfPreview*/);
835     },
837     /**
838      * Called when the print header's print button is clicked. Prints the
839      * document.
840      * @private
841      */
842     onPrintButtonClick_: function() {
843       assert(this.uiState_ == PrintPreview.UiState_.READY,
844              'Trying to print when not in ready state: ' + this.uiState_);
845       this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);
846     },
848     /**
849      * Called when the print header's cancel button is clicked. Closes the
850      * print dialog.
851      * @private
852      */
853     onCancelButtonClick_: function() {
854       this.close_();
855     },
857     /**
858      * Called when the register promo for Cloud Print is clicked.
859      * @private
860      */
861      onCloudPrintRegisterPromoClick_: function(e) {
862        var devicesUrl = 'chrome://devices/register?id=' + e.destination.id;
863        this.nativeLayer_.startForceOpenNewTab(devicesUrl);
864        this.destinationStore_.waitForRegister(e.destination.id);
865      },
867     /**
868      * Consume escape key presses and ctrl + shift + p. Delegate everything else
869      * to the preview area.
870      * @param {KeyboardEvent} e The keyboard event.
871      * @private
872      * @suppress {uselessCode}
873      * Current compiler preprocessor leaves all the code inside all the <if>s,
874      * so the compiler claims that code after first return is unreachable.
875      */
876     onKeyDown_: function(e) {
877       // Escape key closes the dialog.
878       if (e.keyCode == 27 && !e.shiftKey && !e.ctrlKey && !e.altKey &&
879           !e.metaKey) {
880         // On non-mac with toolkit-views, ESC key is handled by C++-side instead
881         // of JS-side.
882         if (cr.isMac) {
883           this.close_();
884           e.preventDefault();
885         }
886         return;
887       }
889       // On Mac, Cmd- should close the print dialog.
890       if (cr.isMac && e.keyCode == 189 && e.metaKey) {
891         this.close_();
892         e.preventDefault();
893         return;
894       }
896       // Ctrl + Shift + p / Mac equivalent.
897       if (e.keyCode == 80) {
898         if ((cr.isMac && e.metaKey && e.altKey && !e.shiftKey && !e.ctrlKey) ||
899             (!cr.isMac && e.shiftKey && e.ctrlKey && !e.altKey && !e.metaKey)) {
900           this.openSystemPrintDialog_();
901           e.preventDefault();
902           return;
903         }
904       }
906       if (e.keyCode == 13 /*enter*/ &&
907           !document.querySelector('.overlay:not([hidden])') &&
908           this.destinationStore_.selectedDestination &&
909           this.printTicketStore_.isTicketValid() &&
910           this.printHeader_.isPrintButtonEnabled) {
911         assert(this.uiState_ == PrintPreview.UiState_.READY,
912             'Trying to print when not in ready state: ' + this.uiState_);
913         var activeElementTag = document.activeElement.tagName.toUpperCase();
914         if (activeElementTag != 'BUTTON' && activeElementTag != 'SELECT' &&
915             activeElementTag != 'A') {
916           this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);
917           e.preventDefault();
918         }
919         return;
920       }
922       // Pass certain directional keyboard events to the PDF viewer.
923       this.previewArea_.handleDirectionalKeyEvent(e);
924     },
926     /**
927      * Called when native layer receives invalid settings for a print request.
928      * @private
929      */
930     onSettingsInvalid_: function() {
931       this.uiState_ = PrintPreview.UiState_.ERROR;
932       console.error('Invalid settings error reported from native layer');
933       this.previewArea_.showCustomMessage(
934           loadTimeData.getString('invalidPrinterSettings'));
935     },
937     /**
938      * Called when the destination settings' change button is activated.
939      * Displays the destination search component.
940      * @private
941      */
942     onDestinationChangeButtonActivate_: function() {
943       this.destinationSearch_.setIsVisible(true);
944     },
946     /**
947      * Called when the destination settings' change button is activated.
948      * Displays the destination search component.
949      * @private
950      */
951     onAdvancedOptionsButtonActivated_: function() {
952       this.advancedSettings_.showForDestination(
953           assert(this.destinationStore_.selectedDestination));
954     },
956     /**
957      * Called when the destination search dispatches manage cloud destinations
958      * event. Calls corresponding native layer method.
959      * @private
960      */
961     onManageCloudDestinationsActivated_: function() {
962       this.nativeLayer_.startManageCloudDestinations(this.userInfo_.activeUser);
963     },
965     /**
966      * Called when the destination search dispatches manage local destinations
967      * event. Calls corresponding native layer method.
968      * @private
969      */
970     onManageLocalDestinationsActivated_: function() {
971       this.nativeLayer_.startManageLocalDestinations();
972     },
974     /**
975      * Called when the user wants to sign in to Google Cloud Print. Calls the
976      * corresponding native layer event.
977      * @param {boolean} addAccount Whether to open an 'add a new account' or
978      *     default sign in page.
979      * @private
980      */
981     onCloudPrintSignInActivated_: function(addAccount) {
982       this.nativeLayer_.startCloudPrintSignIn(addAccount);
983     },
985     /**
986      * Updates printing options according to source document presets.
987      * @param {Event} event Contains options from source document.
988      * @private
989      */
990     onPrintPresetOptionsFromDocument_: function(event) {
991       if (event.optionsFromDocument.disableScaling) {
992         this.printTicketStore_.fitToPage.updateValue(null);
993         this.documentInfo_.updateIsScalingDisabled(true);
994       }
996       if (event.optionsFromDocument.copies > 0 &&
997           this.printTicketStore_.copies.isCapabilityAvailable()) {
998         this.printTicketStore_.copies.updateValue(
999             event.optionsFromDocument.copies);
1000       }
1002       if (event.optionsFromDocument.duplex >= 0 &&
1003           this.printTicketStore_.duplex.isCapabilityAvailable()) {
1004         this.printTicketStore_.duplex.updateValue(
1005             event.optionsFromDocument.duplex);
1006       }
1007     },
1009     /**
1010      * Called when privet printing fails.
1011      * @param {Event} event Event object representing the failure.
1012      * @private
1013      */
1014     onPrivetPrintFailed_: function(event) {
1015       console.error('Privet printing failed with error code ' +
1016                     event.httpError);
1017       this.printHeader_.setErrorMessage(
1018           loadTimeData.getString('couldNotPrint'));
1019     },
1021     /**
1022      * Called when the native layer has detected that the "Distill page"
1023      * option should be allowed.
1024      * @private
1025      */
1026     onAllowDistillPage_: function(event) {
1027       this.printTicketStore_.distillPage.setIsCapabilityAvailable(true);
1028     },
1030     /**
1031      * Called when the print preview settings need to be changed for testing.
1032      * @param {Event} event Event object that contains the option that is to
1033      *     be changed and what to set that option.
1034      * @private
1035      */
1036     onManipulateSettingsForTest_: function(event) {
1037       var settings =
1038           /** @type {print_preview.PreviewSettings} */(event.settings);
1039       if ('selectSaveAsPdfDestination' in settings) {
1040         this.saveAsPdfForTest_();  // No parameters.
1041       } else if ('layoutSettings' in settings) {
1042         this.setLayoutSettingsForTest_(settings.layoutSettings.portrait);
1043       } else if ('pageRange' in settings) {
1044         this.setPageRangeForTest_(settings.pageRange);
1045       } else if ('headersAndFooters' in settings) {
1046         this.setHeadersAndFootersForTest_(settings.headersAndFooters);
1047       } else if ('backgroundColorsAndImages' in settings) {
1048         this.setBackgroundColorsAndImagesForTest_(
1049             settings.backgroundColorsAndImages);
1050       } else if ('margins' in settings) {
1051         this.setMarginsForTest_(settings.margins);
1052       }
1053     },
1055     /**
1056      * Called by onManipulateSettingsForTest_(). Sets the print destination
1057      * as a pdf.
1058      * @private
1059      */
1060     saveAsPdfForTest_: function() {
1061       if (this.destinationStore_.selectedDestination &&
1062           print_preview.Destination.GooglePromotedId.SAVE_AS_PDF ==
1063           this.destinationStore_.selectedDestination.id) {
1064         this.nativeLayer_.previewReadyForTest();
1065         return;
1066       }
1068       var destinations = this.destinationStore_.destinations();
1069       var pdfDestination = null;
1070       for (var i = 0; i < destinations.length; i++) {
1071         if (destinations[i].id ==
1072             print_preview.Destination.GooglePromotedId.SAVE_AS_PDF) {
1073           pdfDestination = destinations[i];
1074           break;
1075         }
1076       }
1078       if (pdfDestination)
1079         this.destinationStore_.selectDestination(pdfDestination);
1080       else
1081         this.nativeLayer_.previewFailedForTest();
1082     },
1084     /**
1085      * Called by onManipulateSettingsForTest_(). Sets the layout settings to
1086      * either portrait or landscape.
1087      * @param {boolean} portrait Whether to use portrait page layout;
1088      *     if false: landscape.
1089      * @private
1090      */
1091     setLayoutSettingsForTest_: function(portrait) {
1092       var combobox = document.querySelector('.layout-settings-select');
1093       if (combobox.value == 'portrait') {
1094         this.nativeLayer_.previewReadyForTest();
1095       } else {
1096         combobox.value = 'landscape';
1097         this.layoutSettings_.onSelectChange_();
1098       }
1099     },
1101     /**
1102      * Called by onManipulateSettingsForTest_(). Sets the page range for
1103      * for the print preview settings.
1104      * @param {string} pageRange Sets the page range to the desired value(s).
1105      *     Ex: "1-5,9" means pages 1 through 5 and page 9 will be printed.
1106      * @private
1107      */
1108     setPageRangeForTest_: function(pageRange) {
1109       var textbox = document.querySelector('.page-settings-custom-input');
1110       if (textbox.value == pageRange) {
1111         this.nativeLayer_.previewReadyForTest();
1112       } else {
1113         textbox.value = pageRange;
1114         document.querySelector('.page-settings-custom-radio').click();
1115       }
1116     },
1118     /**
1119      * Called by onManipulateSettings_(). Checks or unchecks the headers and
1120      * footers option on print preview.
1121      * @param {boolean} headersAndFooters Whether the "Headers and Footers"
1122      *     checkbox should be checked.
1123      * @private
1124      */
1125     setHeadersAndFootersForTest_: function(headersAndFooters) {
1126       var checkbox = document.querySelector('.header-footer-checkbox');
1127       if (headersAndFooters == checkbox.checked)
1128         this.nativeLayer_.previewReadyForTest();
1129       else
1130         checkbox.click();
1131     },
1133     /**
1134      * Called by onManipulateSettings_(). Checks or unchecks the background
1135      * colors and images option on print preview.
1136      * @param {boolean} backgroundColorsAndImages If true, the checkbox should
1137      *     be checked. Otherwise it should be unchecked.
1138      * @private
1139      */
1140     setBackgroundColorsAndImagesForTest_: function(backgroundColorsAndImages) {
1141       var checkbox = document.querySelector('.css-background-checkbox');
1142       if (backgroundColorsAndImages == checkbox.checked)
1143         this.nativeLayer_.previewReadyForTest();
1144       else
1145         checkbox.click();
1146     },
1148     /**
1149      * Called by onManipulateSettings_(). Sets the margin settings
1150      * that are desired. Custom margin settings aren't currently supported.
1151      * @param {number} margins The desired margins combobox index. Must be
1152      *     a valid index or else the test fails.
1153      * @private
1154      */
1155     setMarginsForTest_: function(margins) {
1156       var combobox = document.querySelector('.margin-settings-select');
1157       if (margins == combobox.selectedIndex) {
1158         this.nativeLayer_.previewReadyForTest();
1159       } else if (margins >= 0 && margins < combobox.length) {
1160         combobox.selectedIndex = margins;
1161         this.marginSettings_.onSelectChange_();
1162       } else {
1163         this.nativeLayer_.previewFailedForTest();
1164       }
1165     },
1167     /**
1168      * Returns true if "Print using system dialog" link should be shown for
1169      * current destination.
1170      * @return {boolean} Returns true if link should be shown.
1171      */
1172     shouldShowSystemDialogLink_: function() {
1173       if (cr.isChromeOS || this.hideSystemDialogLink_)
1174         return false;
1175       if (!cr.isWindows)
1176         return true;
1177       var selectedDest = this.destinationStore_.selectedDestination;
1178       return !!selectedDest &&
1179              selectedDest.origin == print_preview.Destination.Origin.LOCAL &&
1180              selectedDest.id !=
1181                  print_preview.Destination.GooglePromotedId.SAVE_AS_PDF;
1182     },
1184     /**
1185      * Called when a print destination is selected. Shows/hides the "Print with
1186      * Cloud Print" link in the navbar.
1187      * @private
1188      */
1189     onDestinationSelect_: function() {
1190       if ($('system-dialog-link')) {
1191         setIsVisible($('system-dialog-link'),
1192                      this.shouldShowSystemDialogLink_());
1193       }
1194       if (this.destinationStore_.selectedDestination &&
1195           this.isInKioskAutoPrintMode_) {
1196         this.onPrintButtonClick_();
1197       }
1198     },
1200     /**
1201      * Called when the destination store loads a group of destinations. Shows
1202      * a promo on Chrome OS if the user has no print destinations promoting
1203      * Google Cloud Print.
1204      * @private
1205      */
1206     onDestinationSearchDone_: function() {
1207       var isPromoVisible = cr.isChromeOS &&
1208           this.cloudPrintInterface_ &&
1209           this.userInfo_.activeUser &&
1210           !this.appState_.isGcpPromoDismissed &&
1211           !this.destinationStore_.isLocalDestinationSearchInProgress &&
1212           !this.destinationStore_.isCloudDestinationSearchInProgress &&
1213           this.destinationStore_.hasOnlyDefaultCloudDestinations();
1214       setIsVisible(this.getChildElement('#no-destinations-promo'),
1215                    isPromoVisible);
1216       if (isPromoVisible) {
1217         new print_preview.GcpPromoMetricsContext().record(
1218             print_preview.Metrics.GcpPromoBucket.PROMO_SHOWN);
1219       }
1220     },
1222     /**
1223      * Called when the close button on the no-destinations-promotion is clicked.
1224      * Hides the promotion.
1225      * @private
1226      */
1227     onNoDestinationsPromoClose_: function() {
1228       new print_preview.GcpPromoMetricsContext().record(
1229           print_preview.Metrics.GcpPromoBucket.PROMO_CLOSED);
1230       setIsVisible(this.getChildElement('#no-destinations-promo'), false);
1231       this.appState_.persistIsGcpPromoDismissed(true);
1232     },
1234     /**
1235      * Called when the no-destinations promotion link is clicked. Opens the
1236      * Google Cloud Print management page and closes the print preview.
1237      * @private
1238      */
1239     onNoDestinationsPromoClick_: function() {
1240       new print_preview.GcpPromoMetricsContext().record(
1241           print_preview.Metrics.GcpPromoBucket.PROMO_CLICKED);
1242       this.appState_.persistIsGcpPromoDismissed(true);
1243       window.open(this.cloudPrintInterface_.baseUrl + '?user=' +
1244                   this.userInfo_.activeUser + '#printers');
1245       this.close_();
1246     }
1247   };
1249   // Export
1250   return {
1251     PrintPreview: PrintPreview
1252   };
1255 // Pull in all other scripts in a single shot.
1256 <include src="common/overlay.js">
1257 <include src="common/search_box.js">
1258 <include src="common/search_bubble.js">
1260 <include src="data/page_number_set.js">
1261 <include src="data/destination.js">
1262 <include src="data/local_parsers.js">
1263 <include src="data/cloud_parsers.js">
1264 <include src="data/destination_store.js">
1265 <include src="data/invitation.js">
1266 <include src="data/invitation_store.js">
1267 <include src="data/margins.js">
1268 <include src="data/document_info.js">
1269 <include src="data/printable_area.js">
1270 <include src="data/measurement_system.js">
1271 <include src="data/print_ticket_store.js">
1272 <include src="data/coordinate2d.js">
1273 <include src="data/size.js">
1274 <include src="data/capabilities_holder.js">
1275 <include src="data/user_info.js">
1276 <include src="data/app_state.js">
1278 <include src="data/ticket_items/ticket_item.js">
1280 <include src="data/ticket_items/custom_margins.js">
1281 <include src="data/ticket_items/collate.js">
1282 <include src="data/ticket_items/color.js">
1283 <include src="data/ticket_items/copies.js">
1284 <include src="data/ticket_items/dpi.js">
1285 <include src="data/ticket_items/duplex.js">
1286 <include src="data/ticket_items/header_footer.js">
1287 <include src="data/ticket_items/distill_page.js">
1288 <include src="data/ticket_items/media_size.js">
1289 <include src="data/ticket_items/landscape.js">
1290 <include src="data/ticket_items/margins_type.js">
1291 <include src="data/ticket_items/page_range.js">
1292 <include src="data/ticket_items/fit_to_page.js">
1293 <include src="data/ticket_items/css_background.js">
1294 <include src="data/ticket_items/selection_only.js">
1295 <include src="data/ticket_items/vendor_items.js">
1297 <include src="native_layer.js">
1298 <include src="print_preview_animations.js">
1299 <include src="cloud_print_interface.js">
1300 <include src="print_preview_utils.js">
1301 <include src="print_header.js">
1302 <include src="metrics.js">
1304 <include src="settings/settings_section.js">
1305 <include src="settings/settings_section_select.js">
1306 <include src="settings/page_settings.js">
1307 <include src="settings/copies_settings.js">
1308 <include src="settings/dpi_settings.js">
1309 <include src="settings/media_size_settings.js">
1310 <include src="settings/layout_settings.js">
1311 <include src="settings/color_settings.js">
1312 <include src="settings/margin_settings.js">
1313 <include src="settings/destination_settings.js">
1314 <include src="settings/other_options_settings.js">
1315 <include src="settings/advanced_options_settings.js">
1316 <include src="settings/advanced_settings/advanced_settings.js">
1317 <include src="settings/advanced_settings/advanced_settings_item.js">
1318 <include src="settings/more_settings.js">
1320 <include src="previewarea/margin_control.js">
1321 <include src="previewarea/margin_control_container.js">
1322 <include src="../pdf/pdf_scripting_api.js">
1323 <include src="previewarea/preview_area.js">
1324 <include src="preview_generator.js">
1326 <include src="search/destination_list.js">
1327 <include src="search/cloud_destination_list.js">
1328 <include src="search/recent_destination_list.js">
1329 <include src="search/destination_list_item.js">
1330 <include src="search/destination_search.js">
1331 <include src="search/fedex_tos.js">
1332 <include src="search/provisional_destination_resolver.js">
1334 window.addEventListener('DOMContentLoaded', function() {
1335   printPreview = new print_preview.PrintPreview();
1336   printPreview.initialize();