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