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.
15 * @param {!print_preview.Metrics} metrics Metrics.
17 * @extends {cr.EventTarget}
19 function DestinationStore(nativeLayer, userInfo, appState, metrics) {
20 cr.EventTarget.call(this);
23 * Used to fetch local print destinations.
24 * @type {!print_preview.NativeLayer}
27 this.nativeLayer_ = nativeLayer;
30 * User information repository.
31 * @type {!print_preview.UserInfo}
34 this.userInfo_ = userInfo;
37 * Used to load and persist the selected destination.
38 * @type {!print_preview.AppState}
41 this.appState_ = appState;
44 * Used to track metrics.
45 * @type {!print_preview.AppState}
48 this.metrics_ = metrics;
51 * Internal backing store for the data store.
52 * @type {!Array.<!print_preview.Destination>}
55 this.destinations_ = [];
58 * Cache used for constant lookup of destinations by origin and id.
59 * @type {object.<string, !print_preview.Destination>}
62 this.destinationMap_ = {};
65 * Currently selected destination.
66 * @type {print_preview.Destination}
69 this.selectedDestination_ = null;
72 * Whether the destination store will auto select the destination that
73 * matches the last used destination stored in appState_.
77 this.isInAutoSelectMode_ = false;
80 * Event tracker used to track event listeners of the destination store.
81 * @type {!EventTracker}
84 this.tracker_ = new EventTracker();
87 * Used to fetch cloud-based print destinations.
88 * @type {print_preview.CloudPrintInterface}
91 this.cloudPrintInterface_ = null;
94 * Maps user account to the list of origins for which destinations are
96 * @type {!Object.<string, Array.<print_preview.Destination.Origin>>}
99 this.loadedCloudOrigins_ = {};
102 * ID of a timeout after the initial destination ID is set. If no inserted
103 * destination matches the initial destination ID after the specified
104 * timeout, the first destination in the store will be automatically
109 this.autoSelectTimeout_ = null;
112 * Whether a search for local destinations is in progress.
116 this.isLocalDestinationSearchInProgress_ = false;
119 * Whether the destination store has already loaded or is loading all local
124 this.hasLoadedAllLocalDestinations_ = false;
127 * Whether a search for privet destinations is in progress.
131 this.isPrivetDestinationSearchInProgress_ = false;
134 * Whether the destination store has already loaded or is loading all privet
139 this.hasLoadedAllPrivetDestinations_ = false;
142 * ID of a timeout after the start of a privet search to end that privet
147 this.privetSearchTimeout_ = null;
150 * MDNS service name of destination that we are waiting to register.
154 this.waitForRegisterDestination_ = null;
156 this.addEventListeners_();
161 * Event types dispatched by the data store.
164 DestinationStore.EventType = {
165 DESTINATION_SEARCH_DONE:
166 'print_preview.DestinationStore.DESTINATION_SEARCH_DONE',
167 DESTINATION_SEARCH_STARTED:
168 'print_preview.DestinationStore.DESTINATION_SEARCH_STARTED',
169 DESTINATION_SELECT: 'print_preview.DestinationStore.DESTINATION_SELECT',
170 DESTINATIONS_INSERTED:
171 'print_preview.DestinationStore.DESTINATIONS_INSERTED',
172 CACHED_SELECTED_DESTINATION_INFO_READY:
173 'print_preview.DestinationStore.CACHED_SELECTED_DESTINATION_INFO_READY',
174 SELECTED_DESTINATION_CAPABILITIES_READY:
175 'print_preview.DestinationStore.SELECTED_DESTINATION_CAPABILITIES_READY'
179 * Delay in milliseconds before the destination store ignores the initial
180 * destination ID and just selects any printer (since the initial destination
186 DestinationStore.AUTO_SELECT_TIMEOUT_ = 15000;
189 * Amount of time spent searching for privet destination, in milliseconds.
194 DestinationStore.PRIVET_SEARCH_DURATION_ = 2000;
197 * Creates a local PDF print destination.
198 * @return {!print_preview.Destination} Created print destination.
201 DestinationStore.createLocalPdfPrintDestination_ = function() {
202 var dest = new print_preview.Destination(
203 print_preview.Destination.GooglePromotedId.SAVE_AS_PDF,
204 print_preview.Destination.Type.LOCAL,
205 print_preview.Destination.Origin.LOCAL,
206 localStrings.getString('printToPDF'),
208 print_preview.Destination.ConnectionStatus.ONLINE);
209 dest.capabilities = {
214 {type: 'AUTO', is_default: true},
219 color: { option: [{type: 'STANDARD_COLOR', is_default: true}] }
225 DestinationStore.prototype = {
226 __proto__: cr.EventTarget.prototype,
229 * @param {string=} opt_account Account to filter destinations by. When
230 * omitted, all destinations are returned.
231 * @return {!Array.<!print_preview.Destination>} List of destinations
232 * accessible by the {@code account}.
234 destinations: function(opt_account) {
236 return this.destinations_.filter(function(destination) {
237 return !destination.account || destination.account == opt_account;
240 return this.destinations_.slice(0);
245 * @return {print_preview.Destination} The currently selected destination or
246 * {@code null} if none is selected.
248 get selectedDestination() {
249 return this.selectedDestination_;
253 * @return {boolean} Whether a search for local destinations is in progress.
255 get isLocalDestinationSearchInProgress() {
256 return this.isLocalDestinationSearchInProgress_ ||
257 this.isPrivetDestinationSearchInProgress_;
261 * @return {boolean} Whether a search for cloud destinations is in progress.
263 get isCloudDestinationSearchInProgress() {
264 return this.cloudPrintInterface_ &&
265 this.cloudPrintInterface_.isCloudDestinationSearchInProgress;
269 * Initializes the destination store. Sets the initially selected
270 * destination. If any inserted destinations match this ID, that destination
271 * will be automatically selected. This method must be called after the
272 * print_preview.AppState has been initialized.
276 this.isInAutoSelectMode_ = true;
277 if (!this.appState_.selectedDestinationId ||
278 !this.appState_.selectedDestinationOrigin) {
279 this.onAutoSelectFailed_();
281 var key = this.getDestinationKey_(
282 this.appState_.selectedDestinationOrigin,
283 this.appState_.selectedDestinationId,
284 this.appState_.selectedDestinationAccount);
285 var candidate = this.destinationMap_[key];
286 if (candidate != null) {
287 this.selectDestination(candidate);
288 } else if (this.appState_.selectedDestinationOrigin ==
289 print_preview.Destination.Origin.LOCAL) {
290 this.nativeLayer_.startGetLocalDestinationCapabilities(
291 this.appState_.selectedDestinationId);
292 } else if (this.cloudPrintInterface_ &&
293 (this.appState_.selectedDestinationOrigin ==
294 print_preview.Destination.Origin.COOKIES ||
295 this.appState_.selectedDestinationOrigin ==
296 print_preview.Destination.Origin.DEVICE)) {
297 this.cloudPrintInterface_.printer(
298 this.appState_.selectedDestinationId,
299 this.appState_.selectedDestinationOrigin,
300 this.appState_.selectedDestinationAccount);
301 } else if (this.appState_.selectedDestinationOrigin ==
302 print_preview.Destination.Origin.PRIVET) {
303 // TODO(noamsml): Resolve a specific printer instead of listing all
304 // privet printers in this case.
305 this.nativeLayer_.startGetPrivetDestinations();
307 var destinationName = this.appState_.selectedDestinationName || '';
309 // Create a fake selectedDestination_ that is not actually in the
310 // destination store. When the real destination is created, this
311 // destination will be overwritten.
312 this.selectedDestination_ = new print_preview.Destination(
313 this.appState_.selectedDestinationId,
314 print_preview.Destination.Type.LOCAL,
315 print_preview.Destination.Origin.PRIVET,
318 print_preview.Destination.ConnectionStatus.ONLINE);
319 this.selectedDestination_.capabilities =
320 this.appState_.selectedDestinationCapabilities;
322 cr.dispatchSimpleEvent(
324 DestinationStore.EventType.CACHED_SELECTED_DESTINATION_INFO_READY);
327 this.onAutoSelectFailed_();
333 * Sets the destination store's Google Cloud Print interface.
334 * @param {!print_preview.CloudPrintInterface} cloudPrintInterface Interface
337 setCloudPrintInterface: function(cloudPrintInterface) {
338 this.cloudPrintInterface_ = cloudPrintInterface;
340 this.cloudPrintInterface_,
341 cloudprint.CloudPrintInterface.EventType.SEARCH_DONE,
342 this.onCloudPrintSearchDone_.bind(this));
344 this.cloudPrintInterface_,
345 cloudprint.CloudPrintInterface.EventType.SEARCH_FAILED,
346 this.onCloudPrintSearchDone_.bind(this));
348 this.cloudPrintInterface_,
349 cloudprint.CloudPrintInterface.EventType.PRINTER_DONE,
350 this.onCloudPrintPrinterDone_.bind(this));
352 this.cloudPrintInterface_,
353 cloudprint.CloudPrintInterface.EventType.PRINTER_FAILED,
354 this.onCloudPrintPrinterFailed_.bind(this));
358 * @return {boolean} Whether only default cloud destinations have been
361 hasOnlyDefaultCloudDestinations: function() {
362 // TODO: Move the logic to print_preview.
363 return this.destinations_.every(function(dest) {
364 return dest.isLocal ||
365 dest.id == print_preview.Destination.GooglePromotedId.DOCS ||
366 dest.id == print_preview.Destination.GooglePromotedId.FEDEX;
370 /** @param {!print_preview.Destination} Destination to select. */
371 selectDestination: function(destination) {
372 this.isInAutoSelectMode_ = false;
373 this.cancelAutoSelectTimeout_();
374 if (destination == this.selectedDestination_) {
377 if (destination == null) {
378 this.selectedDestination_ = null;
379 cr.dispatchSimpleEvent(
380 this, DestinationStore.EventType.DESTINATION_SELECT);
383 // Update and persist selected destination.
384 this.selectedDestination_ = destination;
385 this.selectedDestination_.isRecent = true;
386 if (destination.id == print_preview.Destination.GooglePromotedId.FEDEX &&
387 !destination.isTosAccepted) {
388 assert(this.cloudPrintInterface_ != null,
389 'Selected FedEx destination, but GCP API is not available');
390 destination.isTosAccepted = true;
391 this.cloudPrintInterface_.updatePrinterTosAcceptance(destination, true);
393 this.appState_.persistSelectedDestination(this.selectedDestination_);
395 if (destination.cloudID &&
396 this.destinations_.some(function(otherDestination) {
397 return otherDestination.cloudID == destination.cloudID &&
398 otherDestination != destination;
400 if (destination.isPrivet) {
401 this.metrics_.incrementDestinationSearchBucket(
402 print_preview.Metrics.DestinationSearchBucket.
403 PRIVET_DUPLICATE_SELECTED);
405 this.metrics_.incrementDestinationSearchBucket(
406 print_preview.Metrics.DestinationSearchBucket.
407 CLOUD_DUPLICATE_SELECTED);
410 // Notify about selected destination change.
411 cr.dispatchSimpleEvent(
412 this, DestinationStore.EventType.DESTINATION_SELECT);
413 // Request destination capabilities, of not known yet.
414 if (destination.capabilities == null) {
415 if (destination.isPrivet) {
416 this.nativeLayer_.startGetPrivetDestinationCapabilities(
419 else if (destination.isLocal) {
420 this.nativeLayer_.startGetLocalDestinationCapabilities(
423 assert(this.cloudPrintInterface_ != null,
424 'Cloud destination selected, but GCP is not enabled');
425 this.cloudPrintInterface_.printer(
426 destination.id, destination.origin, destination.account);
429 cr.dispatchSimpleEvent(
431 DestinationStore.EventType.SELECTED_DESTINATION_CAPABILITIES_READY);
436 * Selects 'Save to PDF' destination (since it always exists).
439 selectDefaultDestination_: function() {
440 var destination = this.destinationMap_[this.getDestinationKey_(
441 print_preview.Destination.Origin.LOCAL,
442 print_preview.Destination.GooglePromotedId.SAVE_AS_PDF,
444 assert(destination != null, 'Save to PDF printer not found');
445 this.selectDestination(destination);
448 /** Initiates loading of local print destinations. */
449 startLoadLocalDestinations: function() {
450 if (!this.hasLoadedAllLocalDestinations_) {
451 this.hasLoadedAllLocalDestinations_ = true;
452 this.nativeLayer_.startGetLocalDestinations();
453 this.isLocalDestinationSearchInProgress_ = true;
454 cr.dispatchSimpleEvent(
455 this, DestinationStore.EventType.DESTINATION_SEARCH_STARTED);
459 /** Initiates loading of privet print destinations. */
460 startLoadPrivetDestinations: function() {
461 if (!this.hasLoadedAllPrivetDestinations_) {
462 this.isPrivetDestinationSearchInProgress_ = true;
463 this.nativeLayer_.startGetPrivetDestinations();
464 cr.dispatchSimpleEvent(
465 this, DestinationStore.EventType.DESTINATION_SEARCH_STARTED);
466 this.privetSearchTimeout_ = setTimeout(
467 this.endPrivetPrinterSearch_.bind(this),
468 DestinationStore.PRIVET_SEARCH_DURATION_);
473 * Initiates loading of cloud destinations.
474 * @param {print_preview.Destination.Origin=} opt_origin Search destinations
475 * for the specified origin only.
477 startLoadCloudDestinations: function(opt_origin) {
478 if (this.cloudPrintInterface_ != null) {
479 var origins = this.loadedCloudOrigins_[this.userInfo_.activeUser] || [];
480 if (origins.length == 0 ||
481 (opt_origin && origins.indexOf(opt_origin) < 0)) {
482 this.cloudPrintInterface_.search(
483 this.userInfo_.activeUser, opt_origin);
484 cr.dispatchSimpleEvent(
485 this, DestinationStore.EventType.DESTINATION_SEARCH_STARTED);
490 /** Requests load of COOKIE based cloud destinations. */
491 reloadUserCookieBasedDestinations: function() {
492 var origins = this.loadedCloudOrigins_[this.userInfo_.activeUser] || [];
493 if (origins.indexOf(print_preview.Destination.Origin.COOKIES) >= 0) {
494 cr.dispatchSimpleEvent(
495 this, DestinationStore.EventType.DESTINATION_SEARCH_DONE);
497 this.startLoadCloudDestinations(
498 print_preview.Destination.Origin.COOKIES);
503 * Wait for a privet device to be registered.
505 waitForRegister: function(id) {
506 this.nativeLayer_.startGetPrivetDestinations();
507 this.waitForRegisterDestination_ = id;
511 * Inserts {@code destination} to the data store and dispatches a
512 * DESTINATIONS_INSERTED event.
513 * @param {!print_preview.Destination} destination Print destination to
517 insertDestination_: function(destination) {
518 if (this.insertIntoStore_(destination)) {
519 this.destinationsInserted_(destination);
524 * Inserts multiple {@code destinations} to the data store and dispatches
525 * single DESTINATIONS_INSERTED event.
526 * @param {!Array.<print_preview.Destination>} destinations Print
527 * destinations to insert.
530 insertDestinations_: function(destinations) {
531 var inserted = false;
532 destinations.forEach(function(destination) {
533 inserted = this.insertIntoStore_(destination) || inserted;
536 this.destinationsInserted_();
541 * Dispatches DESTINATIONS_INSERTED event. In auto select mode, tries to
542 * update selected destination to match {@code appState_} settings.
543 * @param {print_preview.Destination=} opt_destination The only destination
544 * that was changed or skipped if possibly more than one destination was
545 * changed. Used as a hint to limit destination search scope in
546 * {@code isInAutoSelectMode_).
548 destinationsInserted_: function(opt_destination) {
549 cr.dispatchSimpleEvent(
550 this, DestinationStore.EventType.DESTINATIONS_INSERTED);
551 if (this.isInAutoSelectMode_) {
552 var destinationsToSearch =
553 opt_destination && [opt_destination] || this.destinations_;
554 destinationsToSearch.some(function(destination) {
555 if (this.matchPersistedDestination_(destination)) {
556 this.selectDestination(destination);
564 * Updates an existing print destination with capabilities and display name
565 * information. If the destination doesn't already exist, it will be added.
566 * @param {!print_preview.Destination} destination Destination to update.
567 * @return {!print_preview.Destination} The existing destination that was
568 * updated or {@code null} if it was the new destination.
571 updateDestination_: function(destination) {
572 assert(destination.constructor !== Array, 'Single printer expected');
573 var existingDestination = this.destinationMap_[this.getKey_(destination)];
574 if (existingDestination != null) {
575 existingDestination.capabilities = destination.capabilities;
577 this.insertDestination_(destination);
580 if (existingDestination == this.selectedDestination_ ||
581 destination == this.selectedDestination_) {
582 this.appState_.persistSelectedDestination(this.selectedDestination_);
583 cr.dispatchSimpleEvent(
585 DestinationStore.EventType.SELECTED_DESTINATION_CAPABILITIES_READY);
588 return existingDestination;
592 * Called when the search for Privet printers is done.
595 endPrivetPrinterSearch_: function() {
596 this.nativeLayer_.stopGetPrivetDestinations();
597 this.isPrivetDestinationSearchInProgress_ = false;
598 this.hasLoadedAllPrivetDestinations_ = true;
599 cr.dispatchSimpleEvent(
600 this, DestinationStore.EventType.DESTINATION_SEARCH_DONE);
604 * Inserts a destination into the store without dispatching any events.
605 * @return {boolean} Whether the inserted destination was not already in the
609 insertIntoStore_: function(destination) {
610 var key = this.getKey_(destination);
611 var existingDestination = this.destinationMap_[key];
612 if (existingDestination == null) {
613 this.destinations_.push(destination);
614 this.destinationMap_[key] = destination;
616 } else if (existingDestination.connectionStatus ==
617 print_preview.Destination.ConnectionStatus.UNKNOWN &&
618 destination.connectionStatus !=
619 print_preview.Destination.ConnectionStatus.UNKNOWN) {
620 existingDestination.connectionStatus = destination.connectionStatus;
628 * Binds handlers to events.
631 addEventListeners_: function() {
634 print_preview.NativeLayer.EventType.LOCAL_DESTINATIONS_SET,
635 this.onLocalDestinationsSet_.bind(this));
638 print_preview.NativeLayer.EventType.CAPABILITIES_SET,
639 this.onLocalDestinationCapabilitiesSet_.bind(this));
642 print_preview.NativeLayer.EventType.GET_CAPABILITIES_FAIL,
643 this.onGetCapabilitiesFail_.bind(this));
646 print_preview.NativeLayer.EventType.DESTINATIONS_RELOAD,
647 this.onDestinationsReload_.bind(this));
650 print_preview.NativeLayer.EventType.PRIVET_PRINTER_CHANGED,
651 this.onPrivetPrinterAdded_.bind(this));
654 print_preview.NativeLayer.EventType.PRIVET_CAPABILITIES_SET,
655 this.onPrivetCapabilitiesSet_.bind(this));
659 * Resets the state of the destination store to its initial state.
663 this.destinations_ = [];
664 this.destinationMap_ = {};
665 this.selectDestination(null);
666 this.loadedCloudOrigins_ = {};
667 this.hasLoadedAllLocalDestinations_ = false;
668 this.insertDestination_(
669 DestinationStore.createLocalPdfPrintDestination_());
670 this.resetAutoSelectTimeout_();
674 * Resets destination auto selection timeout.
677 resetAutoSelectTimeout_: function() {
678 this.cancelAutoSelectTimeout_();
679 this.autoSelectTimeout_ =
680 setTimeout(this.onAutoSelectFailed_.bind(this),
681 DestinationStore.AUTO_SELECT_TIMEOUT_);
685 * Cancels destination auto selection timeout.
688 cancelAutoSelectTimeout_: function() {
689 if (this.autoSelectTimeout_ != null) {
690 clearTimeout(this.autoSelectTimeout_);
691 this.autoSelectTimeout_ = null;
696 * Called when the local destinations have been got from the native layer.
697 * @param {Event} Contains the local destinations.
700 onLocalDestinationsSet_: function(event) {
701 var localDestinations = event.destinationInfos.map(function(destInfo) {
702 return print_preview.LocalDestinationParser.parse(destInfo);
704 this.insertDestinations_(localDestinations);
705 this.isLocalDestinationSearchInProgress_ = false;
706 cr.dispatchSimpleEvent(
707 this, DestinationStore.EventType.DESTINATION_SEARCH_DONE);
711 * Called when the native layer retrieves the capabilities for the selected
712 * local destination. Updates the destination with new capabilities if the
713 * destination already exists, otherwise it creates a new destination and
714 * then updates its capabilities.
715 * @param {Event} event Contains the capabilities of the local print
719 onLocalDestinationCapabilitiesSet_: function(event) {
720 var destinationId = event.settingsInfo['printerId'];
721 var key = this.getDestinationKey_(
722 print_preview.Destination.Origin.LOCAL,
725 var destination = this.destinationMap_[key];
726 var capabilities = print_preview.LocalCapabilitiesParser.parse(
729 // In case there were multiple capabilities request for this local
730 // destination, just ignore the later ones.
731 if (destination.capabilities != null) {
734 destination.capabilities = capabilities;
736 // TODO(rltoscano): This makes the assumption that the "deviceName" is
737 // the same as "printerName". We should include the "printerName" in the
738 // response. See http://crbug.com/132831.
739 destination = print_preview.LocalDestinationParser.parse(
740 {deviceName: destinationId, printerName: destinationId});
741 destination.capabilities = capabilities;
742 this.insertDestination_(destination);
744 if (this.selectedDestination_ &&
745 this.selectedDestination_.id == destinationId) {
746 cr.dispatchSimpleEvent(this,
747 DestinationStore.EventType.
748 SELECTED_DESTINATION_CAPABILITIES_READY);
753 * Called when a request to get a local destination's print capabilities
754 * fails. If the destination is the initial destination, auto-select another
755 * destination instead.
756 * @param {Event} event Contains the destination ID that failed.
759 onGetCapabilitiesFail_: function(event) {
760 console.error('Failed to get print capabilities for printer ' +
761 event.destinationId);
762 if (this.isInAutoSelectMode_ &&
763 this.sameAsPersistedDestination_(event.destinationId,
764 event.destinationOrigin)) {
765 this.selectDefaultDestination_();
770 * Called when the /search call completes, either successfully or not.
771 * In case of success, stores fetched destinations.
772 * @param {Event} event Contains the request result.
775 onCloudPrintSearchDone_: function(event) {
776 if (event.printers) {
777 this.insertDestinations_(event.printers);
779 if (event.searchDone) {
780 var origins = this.loadedCloudOrigins_[event.user] || [];
781 if (origins.indexOf(event.origin) < 0) {
782 this.loadedCloudOrigins_[event.user] = origins.concat([event.origin]);
785 cr.dispatchSimpleEvent(
786 this, DestinationStore.EventType.DESTINATION_SEARCH_DONE);
790 * Called when /printer call completes. Updates the specified destination's
791 * print capabilities.
792 * @param {Event} event Contains detailed information about the
796 onCloudPrintPrinterDone_: function(event) {
797 this.updateDestination_(event.printer);
801 * Called when the Google Cloud Print interface fails to lookup a
802 * destination. Selects another destination if the failed destination was
803 * the initial destination.
804 * @param {object} event Contains the ID of the destination that was failed
808 onCloudPrintPrinterFailed_: function(event) {
809 if (this.isInAutoSelectMode_ &&
810 this.sameAsPersistedDestination_(event.destinationId,
811 event.destinationOrigin)) {
813 'Failed to fetch last used printer caps: ' + event.destinationId);
814 this.selectDefaultDestination_();
819 * Called when a Privet printer is added to the local network.
820 * @param {object} event Contains information about the added printer.
823 onPrivetPrinterAdded_: function(event) {
824 if (event.printer.serviceName == this.waitForRegisterDestination_ &&
825 !event.printer.isUnregistered) {
826 this.waitForRegisterDestination_ = null;
827 this.onDestinationsReload_();
829 this.insertDestinations_(
830 print_preview.PrivetDestinationParser.parse(event.printer));
835 * Called when capabilities for a privet printer are set.
836 * @param {object} event Contains the capabilities and printer ID.
839 onPrivetCapabilitiesSet_: function(event) {
840 var destinationId = event.printerId;
842 print_preview.PrivetDestinationParser.parse(event.printer);
843 destinations.forEach(function(dest) {
844 dest.capabilities = event.capabilities;
845 this.updateDestination_(dest);
850 * Called from native layer after the user was requested to sign in, and did
854 onDestinationsReload_: function() {
856 this.isInAutoSelectMode_ = true;
857 this.startLoadLocalDestinations();
858 this.startLoadCloudDestinations();
859 this.startLoadPrivetDestinations();
863 * Called when auto-selection fails. Selects the first destination in store.
866 onAutoSelectFailed_: function() {
867 this.cancelAutoSelectTimeout_();
868 this.selectDefaultDestination_();
871 // TODO(vitalybuka): Remove three next functions replacing Destination.id
872 // and Destination.origin by complex ID.
874 * Returns key to be used with {@code destinationMap_}.
875 * @param {!print_preview.Destination.Origin} origin Destination origin.
876 * @return {string} id Destination id.
877 * @return {string} account User account destination is registered for.
880 getDestinationKey_: function(origin, id, account) {
881 return origin + '/' + id + '/' + account;
885 * Returns key to be used with {@code destinationMap_}.
886 * @param {!print_preview.Destination} destination Destination.
889 getKey_: function(destination) {
890 return this.getDestinationKey_(
891 destination.origin, destination.id, destination.account);
895 * @param {!print_preview.Destination} destination Destination to match.
896 * @return {boolean} Whether {@code destination} matches the last user
900 matchPersistedDestination_: function(destination) {
901 return !this.appState_.selectedDestinationId ||
902 !this.appState_.selectedDestinationOrigin ||
903 this.sameAsPersistedDestination_(
904 destination.id, destination.origin);
908 * @param {?string} id Id of the destination.
909 * @param {?string} origin Oring of the destination.
910 * @return {boolean} Whether destination is the same as initial.
913 sameAsPersistedDestination_: function(id, origin) {
914 return id == this.appState_.selectedDestinationId &&
915 origin == this.appState_.selectedDestinationOrigin;
921 DestinationStore: DestinationStore