Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1250)

Side by Side Diff: ios/chrome/browser/passwords/resources/credential_manager.js

Issue 1456983002: Move JS-related password manager code upstream (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Indent fixed, capitalisation fixed, typo fixed Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 /**
6 * @fileoverview JavaScript implementation of the credential management API
7 * defined at http://w3c.github.io/webappsec/specs/credentialmanagement.
8 * This is a minimal implementation that sends data to the app side to
9 * integrate with the password manager. When loaded, installs the API onto
10 * the window.navigator object.
11 */
12
13 // Namespace for all credential management stuff. __gCrWeb must have already
14 // been defined.
15 __gCrWeb['credentialManager'] = {
16 /**
17 * The next ID for forwarding a call from JS to the App and tracking its
18 * associated Promise resolvers and rejecters.
19 * @private {number}
20 */
21 nextId_: 0,
22
23 /**
24 * Tracks navigator.credentials Promise resolvers.
25 * @type {!Object<number, function(?Credential|undefined)>}
26 * @private
27 */
28 resolvers_: {},
29
30 /**
31 * Tracks navigator.credentials Promise rejecters.
32 * @type {!Object<number, function(?Error)>}
33 * @private
34 */
35 rejecters_: {}
36 };
37
38
39 /** @enum {string} */
40 __gCrWeb.credentialManager.CredentialType = {
41 CREDENTIAL: 'Credential',
42 PASSWORD_CREDENTIAL: 'PasswordCredential',
43 FEDERATED_CREDENTIAL: 'FederatedCredential',
44 PENDING_CREDENTIAL: 'PendingCredential'
45 };
46
47
48 /** @typedef {
49 * type: __gCrWeb.credentialManager.CredentialType,
50 * id: string,
51 * name: (string|undefined),
52 * avatarURL: (string|undefined),
53 * federation: (string|undefined)
54 * }
55 */
56 __gCrWeb.credentialManager.SerializedCredential;
57
58
59 /**
60 * Creates and returns a Promise whose resolver and rejecter functions are
61 * stored with the associated |requestId|. They can be accessed by calling
62 * |resolve| or |reject| on __gCrWeb['credentialManager'] with that ID.
63 * @param {number} requestId An identifier to track the resolver and rejecter
64 * associated with the returned Promise.
65 * @return {!Promise<?Credential|undefined>} A new Promise.
66 * @private
67 */
68 __gCrWeb['credentialManager'].createPromise_ = function(requestId) {
69 return new Promise(function(resolve, reject) {
70 __gCrWeb['credentialManager'].resolvers_[requestId] = resolve;
71 __gCrWeb['credentialManager'].rejecters_[requestId] = reject;
72 });
73 };
74
75
76 /**
77 * Deletes the resolver and rejecter of the Promise associated with |requestId|.
78 * @param {number} requestId The identifier of the Promise.
79 * @private
80 */
81 __gCrWeb['credentialManager'].removePromise_ = function(requestId) {
82 delete __gCrWeb['credentialManager'].rejecters_[requestId];
83 delete __gCrWeb['credentialManager'].resolvers_[requestId];
84 };
85
86
87 /**
88 * Parses |credentialData| into a Credential object.
89 * @param {!__gCrWeb.credentialManager.SerializedCredential} credentialData A
90 * simple object representation of a Credential like might be obtained from
91 * Credential.prototype.serialize.
92 * @return {?Credential} A Credential object, or null if parsing was
93 * unsuccessful.
94 * @private
95 */
96 __gCrWeb['credentialManager'].parseCredential_ = function(credentialData) {
97 var CredentialType = __gCrWeb.credentialManager.CredentialType;
98 switch (credentialData['type']) {
99 case CredentialType.CREDENTIAL:
100 return Credential.parse(credentialData);
101 case CredentialType.PASSWORD_CREDENTIAL:
102 return PasswordCredential.parse(credentialData);
103 case CredentialType.FEDERATED_CREDENTIAL:
104 return FederatedCredential.parse(credentialData);
105 case CredentialType.PENDING_CREDENTIAL:
106 return PendingCredential.parse(credentialData);
107 default:
108 return null;
109 }
110 };
111
112
113 /**
114 * Resolves the Promise that was created with the given |requestId| with a
115 * Credential object parsed from |opt_credentialData| and removes that promise
116 * from the global state. Future attempts to resolve or reject the Promise will
117 * fail.
118 * @param {number} requestId The identifier of the Promise to resolve.
119 * @param {Object=} opt_credentialData An object describing a credential. If
120 * provided, this parameter will be parsed into the appropriate Credential
121 * type.
122 * @return {boolean} Indicates whether the Promise was successfully resolved.
123 */
124 __gCrWeb['credentialManager'].resolve = function(requestId,
125 opt_credentialData) {
126 var resolver = __gCrWeb['credentialManager'].resolvers_[requestId];
127 if (!resolver) {
128 return false;
129 }
130 if (opt_credentialData) {
131 var credential = null;
132 try {
133 credential =
134 __gCrWeb['credentialManager'].parseCredential_(opt_credentialData);
135 } catch (e) {
136 // Failed to parse |opt_credentialData|. The app side sent bad data.
137 return false;
138 }
139 resolver(credential);
140 } else {
141 resolver();
142 }
143 __gCrWeb['credentialManager'].removePromise_(requestId);
144 return true;
145 };
146
147
148 /**
149 * Rejects the Promise that was created with the given |requestId| and cleans up
150 * that Promise.
151 * @param {number} requestId The identifier of the Promise to resolve.
152 * @param {string} errorType The type of the Error to pass to the rejecter
153 * function. If not recognized, a standard JavaScript Error will be used.
154 * @param {string} message A human-readable description of the error.
155 * @return {boolean} Indicates whether the Promise was successfully rejected.
156 */
157 __gCrWeb['credentialManager'].reject = function(requestId, errorType, message) {
158 var rejecter = __gCrWeb['credentialManager'].rejecters_[requestId];
159 if (!rejecter) {
160 return false;
161 }
162 var error = null;
163 if (errorType == 'SecurityError') {
164 error = new SecurityError(message);
165 } else if (errorType == 'InvalidStateError') {
166 error = new InvalidStateError(message);
167 } else {
168 error = new Error(message);
169 }
170 rejecter(error);
171 __gCrWeb['credentialManager'].removePromise_(requestId);
172 return true;
173 };
174
175
176 /**
177 * Sends a command representing |method| of navigator.credentials to the app
178 * side with the given |opt_options|.
179 * @param {string} command The name of the command being sent.
180 * @param {Object=} opt_options A dictionary of additional properties to forward
181 * to the app.
182 * @return {!Promise<?Credential|undefined>} A promise for the result.
183 * @private
184 */
185 __gCrWeb['credentialManager'].invokeOnHost_ = function(command, opt_options) {
186 var requestId = __gCrWeb['credentialManager'].nextId_++;
187 var message = {
188 'command': command,
189 'requestId': requestId
190 };
191 if (opt_options) {
192 Object.keys(opt_options).forEach(function(key) {
193 message[key] = opt_options[key];
194 });
195 }
196 __gCrWeb.message.invokeOnHost(message);
197 return __gCrWeb['credentialManager'].createPromise_(requestId);
198 };
199
200
201
202 /**
203 * Creates a new SecurityError to represent failures caused by violating
204 * security requirements of the API.
205 * @param {string} message A human-readable message describing this error.
206 * @extends {Error}
207 * @constructor
208 */
209 function SecurityError(message) {
210 Error.call(this, message);
211 this.name = 'SecurityError';
212 this.message = message;
213 }
214 SecurityError.prototype = Object.create(Error.prototype);
215 SecurityError.prototype.constructor = SecurityError;
216
217
218
219 /**
220 * Creates a new InvalidStateError to represent failures caused by inconsistent
221 * internal state.
222 * @param {string} message A human-readable message describing this error.
223 * @extends {Error}
224 * @constructor
225 */
226 function InvalidStateError(message) {
227 Error.call(this, message);
228 this.name = 'InvalidStateError';
229 this.message = message;
230 }
231 InvalidStateError.prototype = Object.create(Error.prototype);
232 InvalidStateError.prototype.constructor = InvalidStateError;
233
234
235
236 /**
237 * Creates a new Credential object. For more information, see
238 * https://w3c.github.io/webappsec/specs/credentialmanagement/#credential
239 * @param {string} id The credential’s identifier. This might be a username or
240 * email address, for instance.
241 * @param {string=} opt_name A name associated with the credential, intended as
242 * a human-understandable public name.
243 * @param {string=} opt_avatarUrl A URL pointing to an avatar image for the
244 * user. This URL MUST NOT be an a priori insecure URL.
245 * @constructor
246 */
247 function Credential(id, opt_name, opt_avatarUrl) {
248 if (id === null || id === undefined)
249 throw new TypeError('id must be provided');
250 /**
251 * The credential's identifier. Read-only.
252 * @type {string}
253 */
254 this.id;
255 Object.defineProperty(this, 'id', {
256 configurable: false,
257 enumerable: true,
258 value: id,
259 writable: false
260 });
261 /**
262 * A human-understandable public name associated with the credential.
263 * Read-only.
264 * @type {string}
265 */
266 this.name;
267 Object.defineProperty(this, 'name', {
268 configurable: false,
269 enumerable: true,
270 value: opt_name || '',
271 writable: false
272 });
273 /**
274 * A URL pointing to an avatar image for the user. Read-only.
275 * NOTE: This property name deviates from the Google JavaScript style guide
276 * in order to meet the public API specification.
277 * @type {string}
278 */
279 this.avatarURL;
280 Object.defineProperty(this, 'avatarURL', {
281 configurable: false,
282 enumerable: true,
283 value: opt_avatarUrl || '',
284 writable: false
285 });
286 }
287
288
289 /**
290 * Returns a simple object representation of this credential suitable for
291 * sending to the app side.
292 * @return {__gCrWeb.credentialManager.SerializedCredential} An object
293 * representing this credential.
294 */
295 Credential.prototype.serialize = function() {
296 var serialized = {
297 'type': this.constructor.name,
298 'id': this.id,
299 'name': this.name
300 };
301 if (this.avatarURL && this.avatarURL.length > 0)
302 serialized['avatarURL'] = this.avatarURL;
303 return serialized;
304 };
305
306
307 /**
308 * Parses |credentialData| into a Credential object.
309 * @param {!__gCrWeb.credentialManager.SerializedCredential} credentialData A
310 * simple object representation of a Credential like might be obtained from
311 * Credential.prototype.serialize.
312 * @return {Credential} A Credential object.
313 */
314 Credential.parse = function(credentialData) {
315 return new Credential(credentialData['id'],
316 credentialData['name'],
317 credentialData['avatarURL']);
318 };
319
320
321
322 /**
323 * Creates a new PasswordCredential object. For more information, see
324 * https://w3c.github.io/webappsec/specs/credentialmanagement/#localcredential
325 * @param {string} id The credential’s identifier. This might be a username or
326 * email address, for instance.
327 * @param {string} password The credential's password.
328 * @param {string=} opt_name A name associated with the credential, intended as
329 * a human-understandable public name.
330 * @param {string=} opt_avatarUrl A URL pointing to an avatar image for the
331 * user. This URL MUST NOT be an a priori insecure URL.
332 * @constructor
333 * @extends {Credential}
334 */
335 function PasswordCredential(id, password, opt_name, opt_avatarUrl) {
336 if (password === null || password === undefined)
337 throw new TypeError('password must be provided');
338 Credential.call(this, id, opt_name, opt_avatarUrl);
339 var formData = new FormData();
340 formData.append('username', id);
341 formData.append('password', password);
342 /**
343 * A FormData object, containing two entries: one named username, the other
344 * named password. Read-only.
345 * @type {FormData}
346 */
347 this.formData;
348 Object.defineProperty(this, 'formData', {
349 configurable: false,
350 enumerable: true,
351 value: formData,
352 writable: false
353 });
354 /**
355 * The credential's password.
356 * @type {string}
357 * @private
358 */
359 this.password_;
360 Object.defineProperty(this, 'password_', {
361 configurable: false,
362 enumerable: false,
363 value: password,
364 writable: false
365 });
366 }
367 PasswordCredential.prototype = Object.create(Credential.prototype);
368 PasswordCredential.prototype.constructor = PasswordCredential;
369
370
371 /**
372 * Returns a simple object representation of this credential suitable for
373 * sending to the app side.
374 * @return {__gCrWeb.credentialManager.SerializedCredential} An object
375 * representing this credential.
376 */
377 PasswordCredential.prototype.serialize = function() {
378 var obj = Credential.prototype.serialize.call(this);
379 obj.password = this.password_;
380 return obj;
381 };
382
383
384 /**
385 * Parses |credentialData| into a PasswordCredential object.
386 * @param {!__gCrWeb.credentialManager.SerializedCredential} credentialData A
387 * simple object representation of a PasswordCredential like might be
388 * obtained from PasswordCredential.prototype.serialize.
389 * @return {PasswordCredential} A PasswordCredential object.
390 */
391 PasswordCredential.parse = function(credentialData) {
392 return new PasswordCredential(credentialData['id'],
393 credentialData['password'],
394 credentialData['name'],
395 credentialData['avatarURL']);
396 };
397
398
399
400 /**
401 * Creates a new FederatedCredential object. For more information, see
402 * https://w3c.github.io/webappsec/specs/credentialmanagement/#federatedcredenti al
403 * @param {string} id The credential’s identifier. This might be a username or
404 * email address, for instance.
405 * @param {string} federation The credential’s federation. For details regarding
406 * valid formats, see https://w3c.github.io/webappsec/specs/credentialmanage ment/#identifying-federations
407 * @param {string=} opt_name A name associated with the credential, intended as
408 * a human-understandable public name.
409 * @param {string=} opt_avatarUrl A URL pointing to an avatar image for the
410 * user. This URL MUST NOT be an a priori insecure URL.
411 * @constructor
412 * @extends {Credential}
413 */
414 function FederatedCredential(id, federation, opt_name, opt_avatarUrl) {
415 if (federation === null || federation === undefined)
416 throw new TypeError('federation must be provided');
417 Credential.call(this, id, opt_name, opt_avatarUrl);
418 /**
419 * The credential’s federation. Read-only.
420 * @type {string}
421 */
422 this.federation;
423 Object.defineProperty(this, 'federation', {
424 configurable: false,
425 enumerable: true,
426 value: federation,
427 writable: false
428 });
429 }
430 FederatedCredential.prototype = Object.create(Credential.prototype);
431 FederatedCredential.prototype.constructor = FederatedCredential;
432
433
434 /**
435 * Returns a simple object representation of this credential suitable for
436 * sending to the app side.
437 * @return {__gCrWeb.credentialManager.SerializedCredential} An object
438 * representing this credential.
439 */
440 FederatedCredential.prototype.serialize = function() {
441 var obj = Credential.prototype.serialize.call(this);
442 obj.federation = this.federation;
443 return obj;
444 };
445
446
447 /**
448 * Parses |credentialData| into a FederatedCredential object.
449 * @param {!__gCrWeb.credentialManager.SerializedCredential} credentialData A
450 * simple object representation of a FederatedCredential like might be
451 * obtained from FederatedCredential.prototype.serialize.
452 * @return {!FederatedCredential} A FederatedCredential object.
453 */
454 FederatedCredential.parse = function(credentialData) {
455 return new FederatedCredential(credentialData['id'],
456 credentialData['federation'],
457 credentialData['name'],
458 credentialData['avatarURL']);
459 };
460
461
462
463 /**
464 * Creates a new PendingCredential object. For more information, see
465 * https://w3c.github.io/webappsec/specs/credentialmanagement/#pendingcredential
466 * @param {string} id The credential’s identifier. This might be a username or
467 * email address, for instance.
468 * @param {string=} opt_name A name associated with the credential, intended as
469 * a human-understandable public name.
470 * @param {string=} opt_avatarUrl A URL pointing to an avatar image for the
471 * user. This URL MUST NOT be an a priori insecure URL.
472 * @constructor
473 * @extends {Credential}
474 */
475 function PendingCredential(id, opt_name, opt_avatarUrl) {
476 Credential.call(this, id, opt_name, opt_avatarUrl);
477 }
478 PendingCredential.prototype = Object.create(Credential.prototype);
479 PendingCredential.prototype.constructor = PendingCredential;
480
481
482 /**
483 * Parses |credentialData| into a PendingCredential object.
484 * @param {!__gCrWeb.credentialManager.SerializedCredential} credentialData A
485 * simple object representation of a PendingCredential like might be
486 * obtained from PendingCredential.prototype.serialize.
487 * @return {!Credential} A PendingCredential object.
488 */
489 PendingCredential.parse = function(credentialData) {
490 return new PendingCredential(credentialData['id'],
491 credentialData['name'],
492 credentialData['avatarURL']);
493 };
494
495
496
497 /**
498 * Implements the public Credential Management API. For more information, see
499 * http://w3c.github.io/webappsec/specs/credentialmanagement/#interfaces-credent ial-manager
500 * @constructor
501 */
502 function CredentialsContainer() {
503 }
504
505
506 /**
507 * Requests a credential from the credential manager.
508 * @param {{suppressUI: boolean, federations: Array<string>}=} opt_options An
509 * optional dictionary of parameters for the request. If |suppressUI| is
510 * true, the returned promise will only be resolved with a credential if
511 * this is possible without user interaction; otherwise, the returned
512 * promise will be resolved with |undefined|. |federations| specifies a
513 * list of acceptable federation providers. For more information, see
514 * https://w3c.github.io/webappsec/specs/credentialmanagement/#interfaces-re quest-options
515 * @return {!Promise<?Credential|undefined>} A promise for retrieving the result
516 * of the request.
517 */
518 CredentialsContainer.prototype.request = function(opt_options) {
519 var options = {
520 'suppressUI': !!opt_options && !!opt_options['suppressUI'],
521 'federations': (!!opt_options && opt_options['federations']) || []
522 };
523 return __gCrWeb['credentialManager'].invokeOnHost_(
524 'navigator.credentials.request', options);
525 };
526
527
528 /**
529 * Notifies the browser that the user has successfully signed in.
530 * @param {Credential=} opt_successfulCredential The credential that was used
531 * to sign in.
532 * @return {!Promise<?Credential|undefined>} A promise to wait for
533 * acknowledgement from the browser.
534 */
535 CredentialsContainer.prototype.notifySignedIn = function(
536 opt_successfulCredential) {
537 var options = opt_successfulCredential && {
538 'credential': opt_successfulCredential.serialize()
539 };
540 return __gCrWeb['credentialManager'].invokeOnHost_(
541 'navigator.credentials.notifySignedIn', options);
542 };
543
544
545 /**
546 * Notifies the browser that the user failed to sign in.
547 * @param {Credential=} opt_failedCredential The credential that failed to
548 * sign in.
549 * @return {!Promise<?Credential|undefined>} A promise to wait for
550 * acknowledgement from the browser.
551 */
552 CredentialsContainer.prototype.notifyFailedSignIn = function(
553 opt_failedCredential) {
554 var options = opt_failedCredential && {
555 'credential': opt_failedCredential.serialize()
556 };
557 return __gCrWeb['credentialManager'].invokeOnHost_(
558 'navigator.credentials.notifyFailedSignIn', options);
559 };
560
561
562 /**
563 * Notifies the browser that the user signed out.
564 * @return {!Promise<?Credential|undefined>} A promise to wait for
565 * acknowledgement from the browser.
566 */
567 CredentialsContainer.prototype.notifySignedOut = function() {
568 return __gCrWeb['credentialManager'].invokeOnHost_(
569 'navigator.credentials.notifySignedOut');
570 };
571
572
573 // Install the public interface.
574 window.navigator.credentials = new CredentialsContainer();
OLDNEW
« no previous file with comments | « ios/chrome/browser/passwords/js_password_manager.mm ('k') | ios/chrome/browser/passwords/resources/password_controller.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698