1 // Copyright 2015 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() {
12 GRANTING_PERMISSION
: 'GRANTING_PERMISSION',
18 * Utility class for bundling a promise object with it's resolver methods.
19 * @param {!Promise<!print_preview.Destination>} promise A promise returning
21 * @param {function(!print_preview.Destination)} resolve Function resolving
23 * @param {function()} reject Function for rejecting the promise.
24 * @constructor @struct
26 function PromiseResolver(promise
, resolve
, reject
) {
27 /** @type {!Promise<!print_preview.Destination>} */
28 this.promise
= promise
;
29 /** @type {function(!print_preview.Destination)} */
30 this.resolve
= resolve
;
31 /** @type {function()} */
36 * Create a Promise and an associated PromiseResolver.
37 * @return {!PromiseResolver}
39 PromiseResolver
.create = function() {
42 /** @type {!Promise<!print_preview.Destination>} */
43 var promise
= new Promise(function(resolvePromise
, rejectPromise
) {
44 resolve
= /** @type {function(!print_preview.Destination)}*/(
46 reject
= /** @type {function()} */(rejectPromise
);
49 return new PromiseResolver(promise
, resolve
, reject
);
53 * Overlay used to resolve a provisional extension destination. The user is
54 * prompted to allow print preview to grant a USB device access to an
55 * extension associated with the destination. If user agrees destination
56 * resolvement is attempted (which includes granting the extension USB access
57 * and requesting destination description from the extension). The overlay is
58 * hidden when destination resolving is done.
60 * @param {!print_preview.DestinationStore} destinationStore The destination
61 * store containing the destination. Used as a proxy to native layer for
62 * resolving the destination.
63 * @param {!print_preview.Destination} destination The destination that has
66 * @extends {print_preview.Overlay}
68 function ProvisionalDestinationResolver(destinationStore
, destination
) {
69 print_preview
.Overlay
.call(this);
71 /** @private {!print_preview.DestinationStore} */
72 this.destinationStore_
= destinationStore
;
73 /** @private {!print_preview.Destination} */
74 this.destination_
= destination
;
76 /** @private {ResolverState} */
77 this.state_
= ResolverState
.INITIAL
;
80 * Promise resolver for promise returned by {@code this.run}.
81 * @private {?PromiseResolver}
83 this.promiseResolver_
= null;
87 * @param {!print_preview.DestinationStore} store
88 * @param {!print_preview.Destination} destination
89 * @return {?ProvisionalDestinationResolver}
91 ProvisionalDestinationResolver
.create = function(store
, destination
) {
92 if (destination
.provisionalType
!=
93 print_preview
.Destination
.ProvisionalType
.NEEDS_USB_PERMISSION
) {
96 return new ProvisionalDestinationResolver(store
, destination
);
99 ProvisionalDestinationResolver
.prototype = {
100 __proto__
: print_preview
.Overlay
.prototype,
103 enterDocument: function() {
104 print_preview
.Overlay
.prototype.enterDocument
.call(this);
107 this.getChildElement('.usb-permission-ok-button'),
109 this.startResolveDestination_
.bind(this));
111 this.getChildElement('.cancel'),
113 this.cancel
.bind(this));
116 this.destinationStore_
,
117 print_preview
.DestinationStore
.EventType
118 .PROVISIONAL_DESTINATION_RESOLVED
,
119 this.onDestinationResolved_
.bind(this));
123 onSetVisibleInternal: function(visible
) {
125 assert(this.state_
== ResolverState
.INITIAL
,
126 'Showing overlay while not in initial state.');
127 assert(!this.promiseResolver_
, 'Promise resolver already set.');
128 this.setState_(ResolverState
.ACTIVE
);
129 this.promiseResolver_
= PromiseResolver
.create();
130 this.getChildElement('.default').focus();
131 } else if (this.state_
!= ResolverState
.DONE
) {
132 assert(this.state_
!= ResolverState
.INITIAL
, 'Hiding in initial state');
133 this.setState_(ResolverState
.DONE
);
134 this.promiseResolver_
.reject();
135 this.promiseResolver_
= null;
140 createDom: function() {
141 this.setElementInternal(this.cloneTemplateInternal(
142 'extension-usb-resolver'));
144 var extNameEl
= this.getChildElement('.usb-permission-extension-name');
145 extNameEl
.title
= this.destination_
.extensionName
;
146 extNameEl
.textContent
= this.destination_
.extensionName
;
148 var extIconEl
= this.getChildElement('.usb-permission-extension-icon');
149 extIconEl
.style
.backgroundImage
= '-webkit-image-set(' +
150 'url(chrome://extension-icon/' +
151 this.destination_
.extensionId
+ '/24/1) 1x,' +
152 'url(chrome://extension-icon/' +
153 this.destination_
.extensionId
+ '/48/1) 2x)';
157 * Handler for click on OK button. It initiates destination resolving.
160 startResolveDestination_: function() {
161 assert(this.state_
== ResolverState
.ACTIVE
,
162 'Invalid state in request grant permission');
164 this.setState_(ResolverState
.GRANTING_PERMISSION
);
165 this.destinationStore_
.resolveProvisionalDestination(this.destination_
);
169 * Handler for PROVISIONAL_DESTINATION_RESOLVED event. It finalizes the
170 * resolver state once the destination associated with the resolver gets
172 * @param {Event} event
175 onDestinationResolved_: function(event
) {
176 if (this.state_
== ResolverState
.DONE
)
179 if (event
.provisionalId
!= this.destination_
.id
)
182 if (event
.destination
) {
183 this.setState_(ResolverState
.DONE
);
184 this.promiseResolver_
.resolve(event
.destination
);
185 this.promiseResolver_
= null;
186 this.setIsVisible(false);
188 this.setState_(ResolverState
.ERROR
);
193 * Sets new resolver state and updates the UI accordingly.
194 * @param {ResolverState} state
197 setState_: function(state
) {
198 if (this.state_
== state
)
206 * Updates the resolver overlay UI to match the resolver state.
209 updateUI_: function() {
210 this.getChildElement('.usb-permission-ok-button').hidden
=
211 this.state_
== ResolverState
.ERROR
;
212 this.getChildElement('.usb-permission-ok-button').disabled
=
213 this.state_
!= ResolverState
.ACTIVE
;
215 // If OK button is disabled, make sure Cancel button gets focus.
216 if (this.state_
!= ResolverState
.ACTIVE
)
217 this.getChildElement('.cancel').focus();
219 this.getChildElement('.throbber-placeholder').classList
.toggle(
221 this.state_
== ResolverState
.GRANTING_PERMISSION
);
223 this.getChildElement('.usb-permission-extension-desc').hidden
=
224 this.state_
== ResolverState
.ERROR
;
226 this.getChildElement('.usb-permission-message').textContent
=
227 this.state_
== ResolverState
.ERROR
?
228 loadTimeData
.getStringF('resolveExtensionUSBErrorMessage',
229 this.destination_
.extensionName
) :
230 loadTimeData
.getString('resolveExtensionUSBPermissionMessage');
234 * Initiates and shows the resolver overlay.
235 * @param {!HTMLElement} parent The element that should parent the resolver
237 * @return {!Promise<!print_preview.Destination>} Promise that will be
238 * fulfilled when the destination resolving is finished.
240 run: function(parent
) {
242 this.setIsVisible(true);
244 assert(this.promiseResolver_
, 'Promise resolver not created.');
245 return this.promiseResolver_
.promise
;
250 ProvisionalDestinationResolver
: ProvisionalDestinationResolver