1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 cr.define('print_preview', function() {
9 * A data store that stores destinations and dispatches events when the data
11 * @param {!print_preview.NativeLayer} nativeLayer Used to fetch local print
13 * @param {!print_preview.UserInfo} userInfo User information repository.
14 * @param {!print_preview.AppState} appState Application state.
16 * @extends {cr.EventTarget}
18 function DestinationStore(nativeLayer, userInfo, appState) {
19 cr.EventTarget.call(this);
22 * Used to fetch local print destinations.
23 * @type {!print_preview.NativeLayer}
26 this.nativeLayer_ = nativeLayer;
29 * User information repository.
30 * @type {!print_preview.UserInfo}
33 this.userInfo_ = userInfo;
36 * Used to load and persist the selected destination.
37 * @type {!print_preview.AppState}
40 this.appState_ = appState;
43 * Used to track metrics.
44 * @type {!print_preview.DestinationSearchMetricsContext}
47 this.metrics_ = new print_preview.DestinationSearchMetricsContext();
50 * Internal backing store for the data store.
51 * @type {!Array.<!print_preview.Destination>}
54 this.destinations_ = [];
57 * Cache used for constant lookup of destinations by origin and id.
58 * @type {Object.<string, !print_preview.Destination>}
61 this.destinationMap_ = {};
64 * Currently selected destination.
65 * @type {print_preview.Destination}
68 this.selectedDestination_ = null;
71 * Whether the destination store will auto select the destination that
72 * matches the last used destination stored in appState_.
76 this.isInAutoSelectMode_ = false;
79 * Event tracker used to track event listeners of the destination store.
80 * @type {!EventTracker}
83 this.tracker_ = new EventTracker();
86 * Whether PDF printer is enabled. It's disabled, for example, in App Kiosk
91 this.pdfPrinterEnabled_ = false;
94 * Used to fetch cloud-based print destinations.
95 * @type {cloudprint.CloudPrintInterface}
98 this.cloudPrintInterface_ = null;
101 * Maps user account to the list of origins for which destinations are
103 * @type {!Object.<string, Array.<print_preview.Destination.Origin>>}
106 this.loadedCloudOrigins_ = {};
109 * ID of a timeout after the initial destination ID is set. If no inserted
110 * destination matches the initial destination ID after the specified
111 * timeout, the first destination in the store will be automatically
116 this.autoSelectTimeout_ = null;
119 * Whether a search for local destinations is in progress.
123 this.isLocalDestinationSearchInProgress_ = false;
126 * Whether the destination store has already loaded or is loading all local
131 this.hasLoadedAllLocalDestinations_ = false;
134 * Whether a search for privet destinations is in progress.
138 this.isPrivetDestinationSearchInProgress_ = false;
141 * Whether the destination store has already loaded or is loading all privet
146 this.hasLoadedAllPrivetDestinations_ = false;
149 * ID of a timeout after the start of a privet search to end that privet
154 this.privetSearchTimeout_ = null;
157 * MDNS service name of destination that we are waiting to register.
161 this.waitForRegisterDestination_ = null;
163 this.addEventListeners_();
168 * Event types dispatched by the data store.
171 DestinationStore.EventType = {
172 DESTINATION_SEARCH_DONE:
173 'print_preview.DestinationStore.DESTINATION_SEARCH_DONE',
174 DESTINATION_SEARCH_STARTED:
175 'print_preview.DestinationStore.DESTINATION_SEARCH_STARTED',
176 DESTINATION_SELECT: 'print_preview.DestinationStore.DESTINATION_SELECT',
177 DESTINATIONS_INSERTED:
178 'print_preview.DestinationStore.DESTINATIONS_INSERTED',
179 CACHED_SELECTED_DESTINATION_INFO_READY:
180 'print_preview.DestinationStore.CACHED_SELECTED_DESTINATION_INFO_READY',
181 SELECTED_DESTINATION_CAPABILITIES_READY:
182 'print_preview.DestinationStore.SELECTED_DESTINATION_CAPABILITIES_READY'
186 * Delay in milliseconds before the destination store ignores the initial
187 * destination ID and just selects any printer (since the initial destination
193 DestinationStore.AUTO_SELECT_TIMEOUT_ = 15000;
196 * Amount of time spent searching for privet destination, in milliseconds.
201 DestinationStore.PRIVET_SEARCH_DURATION_ = 2000;
204 * Localizes printer capabilities.
205 * @param {!Object} capabilities Printer capabilities to localize.
206 * @return {!Object} Localized capabilities.
209 DestinationStore.localizeCapabilities_ = function(capabilities) {
210 var mediaSize = capabilities.printer.media_size;
212 var mediaDisplayNames = {
215 'NA_LETTER': 'Letter',
217 'NA_LEDGER': 'Tabloid'
219 for (var i = 0, media; media = mediaSize.option[i]; i++) {
220 media.custom_display_name =
221 media.custom_display_name ||
222 mediaDisplayNames[media.name] ||
229 DestinationStore.prototype = {
230 __proto__: cr.EventTarget.prototype,
233 * @param {string=} opt_account Account to filter destinations by. When
234 * omitted, all destinations are returned.
235 * @return {!Array.<!print_preview.Destination>} List of destinations
236 * accessible by the {@code account}.
238 destinations: function(opt_account) {
240 return this.destinations_.filter(function(destination) {
241 return !destination.account || destination.account == opt_account;
244 return this.destinations_.slice(0);
249 * @return {print_preview.Destination} The currently selected destination or
250 * {@code null} if none is selected.
252 get selectedDestination() {
253 return this.selectedDestination_;
256 /** @return {boolean} Whether destination selection is pending or not. */
257 get isAutoSelectDestinationInProgress() {
258 return this.selectedDestination_ == null &&
259 this.autoSelectTimeout_ != null;
263 * @return {boolean} Whether a search for local destinations is in progress.
265 get isLocalDestinationSearchInProgress() {
266 return this.isLocalDestinationSearchInProgress_ ||
267 this.isPrivetDestinationSearchInProgress_;
271 * @return {boolean} Whether a search for cloud destinations is in progress.
273 get isCloudDestinationSearchInProgress() {
274 return !!this.cloudPrintInterface_ &&
275 this.cloudPrintInterface_.isCloudDestinationSearchInProgress;
279 * Initializes the destination store. Sets the initially selected
280 * destination. If any inserted destinations match this ID, that destination
281 * will be automatically selected. This method must be called after the
282 * print_preview.AppState has been initialized.
283 * @param {boolean} isInAppKioskMode Whether the print preview is in App
286 init: function(isInAppKioskMode) {
287 this.pdfPrinterEnabled_ = !isInAppKioskMode;
288 this.isInAutoSelectMode_ = true;
289 this.createLocalPdfPrintDestination_();
290 if (!this.appState_.selectedDestinationId ||
291 !this.appState_.selectedDestinationOrigin) {
292 this.selectDefaultDestination_();
294 assert(typeof this.appState_.selectedDestinationAccount == 'string');
295 var key = this.getDestinationKey_(
296 this.appState_.selectedDestinationOrigin,
297 this.appState_.selectedDestinationId,
298 this.appState_.selectedDestinationAccount);
299 var candidate = this.destinationMap_[key];
300 if (candidate != null) {
301 this.selectDestination(candidate);
302 } else if (this.appState_.selectedDestinationOrigin ==
303 print_preview.Destination.Origin.LOCAL) {
304 this.nativeLayer_.startGetLocalDestinationCapabilities(
305 this.appState_.selectedDestinationId);
306 } else if (this.cloudPrintInterface_ &&
307 (this.appState_.selectedDestinationOrigin ==
308 print_preview.Destination.Origin.COOKIES ||
309 this.appState_.selectedDestinationOrigin ==
310 print_preview.Destination.Origin.DEVICE)) {
311 this.cloudPrintInterface_.printer(
312 this.appState_.selectedDestinationId,
313 this.appState_.selectedDestinationOrigin,
314 this.appState_.selectedDestinationAccount);
315 } else if (this.appState_.selectedDestinationOrigin ==
316 print_preview.Destination.Origin.PRIVET) {
317 // TODO(noamsml): Resolve a specific printer instead of listing all
318 // privet printers in this case.
319 this.nativeLayer_.startGetPrivetDestinations();
321 var destinationName = this.appState_.selectedDestinationName || '';
323 // Create a fake selectedDestination_ that is not actually in the
324 // destination store. When the real destination is created, this
325 // destination will be overwritten.
326 this.selectedDestination_ = new print_preview.Destination(
327 this.appState_.selectedDestinationId,
328 print_preview.Destination.Type.LOCAL,
329 print_preview.Destination.Origin.PRIVET,
332 print_preview.Destination.ConnectionStatus.ONLINE);
333 this.selectedDestination_.capabilities =
334 this.appState_.selectedDestinationCapabilities;
336 cr.dispatchSimpleEvent(
338 DestinationStore.EventType.CACHED_SELECTED_DESTINATION_INFO_READY);
340 this.selectDefaultDestination_();
346 * Sets the destination store's Google Cloud Print interface.
347 * @param {!cloudprint.CloudPrintInterface} cloudPrintInterface Interface
350 setCloudPrintInterface: function(cloudPrintInterface) {
351 this.cloudPrintInterface_ = cloudPrintInterface;
353 this.cloudPrintInterface_,
354 cloudprint.CloudPrintInterface.EventType.SEARCH_DONE,
355 this.onCloudPrintSearchDone_.bind(this));
357 this.cloudPrintInterface_,
358 cloudprint.CloudPrintInterface.EventType.SEARCH_FAILED,
359 this.onCloudPrintSearchDone_.bind(this));
361 this.cloudPrintInterface_,
362 cloudprint.CloudPrintInterface.EventType.PRINTER_DONE,
363 this.onCloudPrintPrinterDone_.bind(this));
365 this.cloudPrintInterface_,
366 cloudprint.CloudPrintInterface.EventType.PRINTER_FAILED,
367 this.onCloudPrintPrinterFailed_.bind(this));
369 this.cloudPrintInterface_,
370 cloudprint.CloudPrintInterface.EventType.PROCESS_INVITE_DONE,
371 this.onCloudPrintProcessInviteDone_.bind(this));
375 * @return {boolean} Whether only default cloud destinations have been
378 hasOnlyDefaultCloudDestinations: function() {
379 // TODO: Move the logic to print_preview.
380 return this.destinations_.every(function(dest) {
381 return dest.isLocal ||
382 dest.id == print_preview.Destination.GooglePromotedId.DOCS ||
383 dest.id == print_preview.Destination.GooglePromotedId.FEDEX;
388 * @param {print_preview.Destination} destination Destination to select.
390 selectDestination: function(destination) {
391 this.isInAutoSelectMode_ = false;
392 // When auto select expires, DESTINATION_SELECT event has to be dispatched
393 // anyway (see isAutoSelectDestinationInProgress() logic).
394 if (this.autoSelectTimeout_) {
395 clearTimeout(this.autoSelectTimeout_);
396 this.autoSelectTimeout_ = null;
397 } else if (destination == this.selectedDestination_) {
400 if (destination == null) {
401 this.selectedDestination_ = null;
402 cr.dispatchSimpleEvent(
403 this, DestinationStore.EventType.DESTINATION_SELECT);
406 // Update and persist selected destination.
407 this.selectedDestination_ = destination;
408 this.selectedDestination_.isRecent = true;
409 if (destination.id == print_preview.Destination.GooglePromotedId.FEDEX &&
410 !destination.isTosAccepted) {
411 assert(this.cloudPrintInterface_ != null,
412 'Selected FedEx destination, but GCP API is not available');
413 destination.isTosAccepted = true;
414 this.cloudPrintInterface_.updatePrinterTosAcceptance(destination, true);
416 this.appState_.persistSelectedDestination(this.selectedDestination_);
418 if (destination.cloudID &&
419 this.destinations_.some(function(otherDestination) {
420 return otherDestination.cloudID == destination.cloudID &&
421 otherDestination != destination;
423 this.metrics_.record(destination.isPrivet ?
424 print_preview.Metrics.DestinationSearchBucket.
425 PRIVET_DUPLICATE_SELECTED :
426 print_preview.Metrics.DestinationSearchBucket.
427 CLOUD_DUPLICATE_SELECTED);
429 // Notify about selected destination change.
430 cr.dispatchSimpleEvent(
431 this, DestinationStore.EventType.DESTINATION_SELECT);
432 // Request destination capabilities, of not known yet.
433 if (destination.capabilities == null) {
434 if (destination.isPrivet) {
435 this.nativeLayer_.startGetPrivetDestinationCapabilities(
438 else if (destination.isLocal) {
439 this.nativeLayer_.startGetLocalDestinationCapabilities(
442 assert(this.cloudPrintInterface_ != null,
443 'Cloud destination selected, but GCP is not enabled');
444 this.cloudPrintInterface_.printer(
445 destination.id, destination.origin, destination.account);
448 cr.dispatchSimpleEvent(
450 DestinationStore.EventType.SELECTED_DESTINATION_CAPABILITIES_READY);
455 * Selects 'Save to PDF' destination (since it always exists).
458 selectDefaultDestination_: function() {
459 var saveToPdfKey = this.getDestinationKey_(
460 print_preview.Destination.Origin.LOCAL,
461 print_preview.Destination.GooglePromotedId.SAVE_AS_PDF,
463 this.selectDestination(
464 this.destinationMap_[saveToPdfKey] || this.destinations_[0] || null);
467 /** Initiates loading of local print destinations. */
468 startLoadLocalDestinations: function() {
469 if (!this.hasLoadedAllLocalDestinations_) {
470 this.hasLoadedAllLocalDestinations_ = true;
471 this.nativeLayer_.startGetLocalDestinations();
472 this.isLocalDestinationSearchInProgress_ = true;
473 cr.dispatchSimpleEvent(
474 this, DestinationStore.EventType.DESTINATION_SEARCH_STARTED);
478 /** Initiates loading of privet print destinations. */
479 startLoadPrivetDestinations: function() {
480 if (!this.hasLoadedAllPrivetDestinations_) {
481 this.isPrivetDestinationSearchInProgress_ = true;
482 this.nativeLayer_.startGetPrivetDestinations();
483 cr.dispatchSimpleEvent(
484 this, DestinationStore.EventType.DESTINATION_SEARCH_STARTED);
485 this.privetSearchTimeout_ = setTimeout(
486 this.endPrivetPrinterSearch_.bind(this),
487 DestinationStore.PRIVET_SEARCH_DURATION_);
492 * Initiates loading of cloud destinations.
493 * @param {print_preview.Destination.Origin=} opt_origin Search destinations
494 * for the specified origin only.
496 startLoadCloudDestinations: function(opt_origin) {
497 if (this.cloudPrintInterface_ != null) {
498 var origins = this.loadedCloudOrigins_[this.userInfo_.activeUser] || [];
499 if (origins.length == 0 ||
500 (opt_origin && origins.indexOf(opt_origin) < 0)) {
501 this.cloudPrintInterface_.search(
502 this.userInfo_.activeUser, opt_origin);
503 cr.dispatchSimpleEvent(
504 this, DestinationStore.EventType.DESTINATION_SEARCH_STARTED);
509 /** Requests load of COOKIE based cloud destinations. */
510 reloadUserCookieBasedDestinations: function() {
511 var origins = this.loadedCloudOrigins_[this.userInfo_.activeUser] || [];
512 if (origins.indexOf(print_preview.Destination.Origin.COOKIES) >= 0) {
513 cr.dispatchSimpleEvent(
514 this, DestinationStore.EventType.DESTINATION_SEARCH_DONE);
516 this.startLoadCloudDestinations(
517 print_preview.Destination.Origin.COOKIES);
521 /** Initiates loading of all known destination types. */
522 startLoadAllDestinations: function() {
523 this.startLoadCloudDestinations();
524 this.startLoadLocalDestinations();
525 this.startLoadPrivetDestinations();
529 * Wait for a privet device to be registered.
531 waitForRegister: function(id) {
532 this.nativeLayer_.startGetPrivetDestinations();
533 this.waitForRegisterDestination_ = id;
537 * Inserts {@code destination} to the data store and dispatches a
538 * DESTINATIONS_INSERTED event.
539 * @param {!print_preview.Destination} destination Print destination to
543 insertDestination_: function(destination) {
544 if (this.insertIntoStore_(destination)) {
545 this.destinationsInserted_(destination);
550 * Inserts multiple {@code destinations} to the data store and dispatches
551 * single DESTINATIONS_INSERTED event.
552 * @param {!Array.<print_preview.Destination>} destinations Print
553 * destinations to insert.
556 insertDestinations_: function(destinations) {
557 var inserted = false;
558 destinations.forEach(function(destination) {
559 inserted = this.insertIntoStore_(destination) || inserted;
562 this.destinationsInserted_();
567 * Dispatches DESTINATIONS_INSERTED event. In auto select mode, tries to
568 * update selected destination to match {@code appState_} settings.
569 * @param {print_preview.Destination=} opt_destination The only destination
570 * that was changed or skipped if possibly more than one destination was
571 * changed. Used as a hint to limit destination search scope in
572 * {@code isInAutoSelectMode_).
574 destinationsInserted_: function(opt_destination) {
575 cr.dispatchSimpleEvent(
576 this, DestinationStore.EventType.DESTINATIONS_INSERTED);
577 if (this.isInAutoSelectMode_) {
578 var destinationsToSearch =
579 opt_destination && [opt_destination] || this.destinations_;
580 destinationsToSearch.some(function(destination) {
581 if (this.matchPersistedDestination_(destination)) {
582 this.selectDestination(destination);
590 * Updates an existing print destination with capabilities and display name
591 * information. If the destination doesn't already exist, it will be added.
592 * @param {!print_preview.Destination} destination Destination to update.
593 * @return {!print_preview.Destination} The existing destination that was
594 * updated or {@code null} if it was the new destination.
597 updateDestination_: function(destination) {
598 assert(destination.constructor !== Array, 'Single printer expected');
599 var existingDestination = this.destinationMap_[this.getKey_(destination)];
600 if (existingDestination != null) {
601 existingDestination.capabilities = destination.capabilities;
603 this.insertDestination_(destination);
606 if (existingDestination == this.selectedDestination_ ||
607 destination == this.selectedDestination_) {
608 this.appState_.persistSelectedDestination(this.selectedDestination_);
609 cr.dispatchSimpleEvent(
611 DestinationStore.EventType.SELECTED_DESTINATION_CAPABILITIES_READY);
614 return existingDestination;
618 * Called when the search for Privet printers is done.
621 endPrivetPrinterSearch_: function() {
622 this.nativeLayer_.stopGetPrivetDestinations();
623 this.isPrivetDestinationSearchInProgress_ = false;
624 this.hasLoadedAllPrivetDestinations_ = true;
625 cr.dispatchSimpleEvent(
626 this, DestinationStore.EventType.DESTINATION_SEARCH_DONE);
630 * Inserts a destination into the store without dispatching any events.
631 * @return {boolean} Whether the inserted destination was not already in the
635 insertIntoStore_: function(destination) {
636 var key = this.getKey_(destination);
637 var existingDestination = this.destinationMap_[key];
638 if (existingDestination == null) {
639 this.destinations_.push(destination);
640 this.destinationMap_[key] = destination;
642 } else if (existingDestination.connectionStatus ==
643 print_preview.Destination.ConnectionStatus.UNKNOWN &&
644 destination.connectionStatus !=
645 print_preview.Destination.ConnectionStatus.UNKNOWN) {
646 existingDestination.connectionStatus = destination.connectionStatus;
654 * Binds handlers to events.
657 addEventListeners_: function() {
660 print_preview.NativeLayer.EventType.LOCAL_DESTINATIONS_SET,
661 this.onLocalDestinationsSet_.bind(this));
664 print_preview.NativeLayer.EventType.CAPABILITIES_SET,
665 this.onLocalDestinationCapabilitiesSet_.bind(this));
668 print_preview.NativeLayer.EventType.GET_CAPABILITIES_FAIL,
669 this.onGetCapabilitiesFail_.bind(this));
672 print_preview.NativeLayer.EventType.DESTINATIONS_RELOAD,
673 this.onDestinationsReload_.bind(this));
676 print_preview.NativeLayer.EventType.PRIVET_PRINTER_CHANGED,
677 this.onPrivetPrinterAdded_.bind(this));
680 print_preview.NativeLayer.EventType.PRIVET_CAPABILITIES_SET,
681 this.onPrivetCapabilitiesSet_.bind(this));
685 * Creates a local PDF print destination.
686 * @return {!print_preview.Destination} Created print destination.
689 createLocalPdfPrintDestination_: function() {
690 // TODO(alekseys): Create PDF printer in the native code and send its
691 // capabilities back with other local printers.
692 if (this.pdfPrinterEnabled_) {
693 this.insertDestination_(new print_preview.Destination(
694 print_preview.Destination.GooglePromotedId.SAVE_AS_PDF,
695 print_preview.Destination.Type.LOCAL,
696 print_preview.Destination.Origin.LOCAL,
697 loadTimeData.getString('printToPDF'),
699 print_preview.Destination.ConnectionStatus.ONLINE));
704 * Resets the state of the destination store to its initial state.
708 this.destinations_ = [];
709 this.destinationMap_ = {};
710 this.selectDestination(null);
711 this.loadedCloudOrigins_ = {};
712 this.hasLoadedAllLocalDestinations_ = false;
714 clearTimeout(this.autoSelectTimeout_);
715 this.autoSelectTimeout_ = setTimeout(
716 this.selectDefaultDestination_.bind(this),
717 DestinationStore.AUTO_SELECT_TIMEOUT_);
721 * Called when the local destinations have been got from the native layer.
722 * @param {Event} event Contains the local destinations.
725 onLocalDestinationsSet_: function(event) {
726 var localDestinations = event.destinationInfos.map(function(destInfo) {
727 return print_preview.LocalDestinationParser.parse(destInfo);
729 this.insertDestinations_(localDestinations);
730 this.isLocalDestinationSearchInProgress_ = false;
731 cr.dispatchSimpleEvent(
732 this, DestinationStore.EventType.DESTINATION_SEARCH_DONE);
736 * Called when the native layer retrieves the capabilities for the selected
737 * local destination. Updates the destination with new capabilities if the
738 * destination already exists, otherwise it creates a new destination and
739 * then updates its capabilities.
740 * @param {Event} event Contains the capabilities of the local print
744 onLocalDestinationCapabilitiesSet_: function(event) {
745 var destinationId = event.settingsInfo['printerId'];
746 var key = this.getDestinationKey_(
747 print_preview.Destination.Origin.LOCAL,
750 var destination = this.destinationMap_[key];
751 var capabilities = DestinationStore.localizeCapabilities_(
752 event.settingsInfo.capabilities);
753 // Special case for PDF printer (until local printers capabilities are
754 // reported in CDD format too).
756 print_preview.Destination.GooglePromotedId.SAVE_AS_PDF) {
758 destination.capabilities = capabilities;
762 // In case there were multiple capabilities request for this local
763 // destination, just ignore the later ones.
764 if (destination.capabilities != null) {
767 destination.capabilities = capabilities;
769 // TODO(rltoscano): This makes the assumption that the "deviceName" is
770 // the same as "printerName". We should include the "printerName" in
771 // the response. See http://crbug.com/132831.
772 destination = print_preview.LocalDestinationParser.parse(
773 {deviceName: destinationId, printerName: destinationId});
774 destination.capabilities = capabilities;
775 this.insertDestination_(destination);
778 if (this.selectedDestination_ &&
779 this.selectedDestination_.id == destinationId) {
780 cr.dispatchSimpleEvent(this,
781 DestinationStore.EventType.
782 SELECTED_DESTINATION_CAPABILITIES_READY);
787 * Called when a request to get a local destination's print capabilities
788 * fails. If the destination is the initial destination, auto-select another
789 * destination instead.
790 * @param {Event} event Contains the destination ID that failed.
793 onGetCapabilitiesFail_: function(event) {
794 console.error('Failed to get print capabilities for printer ' +
795 event.destinationId);
796 if (this.isInAutoSelectMode_ &&
797 this.sameAsPersistedDestination_(event.destinationId,
798 event.destinationOrigin)) {
799 this.selectDefaultDestination_();
804 * Called when the /search call completes, either successfully or not.
805 * In case of success, stores fetched destinations.
806 * @param {Event} event Contains the request result.
809 onCloudPrintSearchDone_: function(event) {
810 if (event.printers) {
811 this.insertDestinations_(event.printers);
813 if (event.searchDone) {
814 var origins = this.loadedCloudOrigins_[event.user] || [];
815 if (origins.indexOf(event.origin) < 0) {
816 this.loadedCloudOrigins_[event.user] = origins.concat([event.origin]);
819 cr.dispatchSimpleEvent(
820 this, DestinationStore.EventType.DESTINATION_SEARCH_DONE);
824 * Called when /printer call completes. Updates the specified destination's
825 * print capabilities.
826 * @param {Event} event Contains detailed information about the
830 onCloudPrintPrinterDone_: function(event) {
831 this.updateDestination_(event.printer);
835 * Called when the Google Cloud Print interface fails to lookup a
836 * destination. Selects another destination if the failed destination was
837 * the initial destination.
838 * @param {Object} event Contains the ID of the destination that was failed
842 onCloudPrintPrinterFailed_: function(event) {
843 if (this.isInAutoSelectMode_ &&
844 this.sameAsPersistedDestination_(event.destinationId,
845 event.destinationOrigin)) {
847 'Failed to fetch last used printer caps: ' + event.destinationId);
848 this.selectDefaultDestination_();
853 * Called when printer sharing invitation was processed successfully.
854 * @param {Event} event Contains detailed information about the invite and
855 * newly accepted destination (if known).
858 onCloudPrintProcessInviteDone_: function(event) {
859 if (event.accept && event.printer) {
860 // Hint the destination list to promote this new destination.
861 event.printer.isRecent = true;
862 this.insertDestination_(event.printer);
867 * Called when a Privet printer is added to the local network.
868 * @param {Object} event Contains information about the added printer.
871 onPrivetPrinterAdded_: function(event) {
872 if (event.printer.serviceName == this.waitForRegisterDestination_ &&
873 !event.printer.isUnregistered) {
874 this.waitForRegisterDestination_ = null;
875 this.onDestinationsReload_();
877 this.insertDestinations_(
878 print_preview.PrivetDestinationParser.parse(event.printer));
883 * Called when capabilities for a privet printer are set.
884 * @param {Object} event Contains the capabilities and printer ID.
887 onPrivetCapabilitiesSet_: function(event) {
888 var destinationId = event.printerId;
890 print_preview.PrivetDestinationParser.parse(event.printer);
891 destinations.forEach(function(dest) {
892 dest.capabilities = event.capabilities;
893 this.updateDestination_(dest);
898 * Called from native layer after the user was requested to sign in, and did
902 onDestinationsReload_: function() {
904 this.isInAutoSelectMode_ = true;
905 this.createLocalPdfPrintDestination_();
906 this.startLoadAllDestinations();
909 // TODO(vitalybuka): Remove three next functions replacing Destination.id
910 // and Destination.origin by complex ID.
912 * Returns key to be used with {@code destinationMap_}.
913 * @param {!print_preview.Destination.Origin} origin Destination origin.
914 * @param {string} id Destination id.
915 * @param {string} account User account destination is registered for.
918 getDestinationKey_: function(origin, id, account) {
919 return origin + '/' + id + '/' + account;
923 * Returns key to be used with {@code destinationMap_}.
924 * @param {!print_preview.Destination} destination Destination.
927 getKey_: function(destination) {
928 return this.getDestinationKey_(
929 destination.origin, destination.id, destination.account);
933 * @param {!print_preview.Destination} destination Destination to match.
934 * @return {boolean} Whether {@code destination} matches the last user
938 matchPersistedDestination_: function(destination) {
939 return !this.appState_.selectedDestinationId ||
940 !this.appState_.selectedDestinationOrigin ||
941 this.sameAsPersistedDestination_(
942 destination.id, destination.origin);
946 * @param {?string} id Id of the destination.
947 * @param {?string} origin Oring of the destination.
948 * @return {boolean} Whether destination is the same as initial.
951 sameAsPersistedDestination_: function(id, origin) {
952 return id == this.appState_.selectedDestinationId &&
953 origin == this.appState_.selectedDestinationOrigin;
959 DestinationStore: DestinationStore