| Index: ios/chrome/browser/passwords/resources/credential_manager.js
|
| diff --git a/ios/chrome/browser/passwords/resources/credential_manager.js b/ios/chrome/browser/passwords/resources/credential_manager.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..8e2e84079be137d63d21d310c74443f285f0f8e1
|
| --- /dev/null
|
| +++ b/ios/chrome/browser/passwords/resources/credential_manager.js
|
| @@ -0,0 +1,574 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +/**
|
| + * @fileoverview JavaScript implementation of the credential management API
|
| + * defined at http://w3c.github.io/webappsec/specs/credentialmanagement.
|
| + * This is a minimal implementation that sends data to the app side to
|
| + * integrate with the password manager. When loaded, installs the API onto
|
| + * the window.navigator object.
|
| + */
|
| +
|
| +// Namespace for all credential management stuff. __gCrWeb must have already
|
| +// been defined.
|
| +__gCrWeb['credentialManager'] = {
|
| + /**
|
| + * The next ID for forwarding a call from JS to the App and tracking its
|
| + * associated Promise resolvers and rejecters.
|
| + * @private {number}
|
| + */
|
| + nextId_: 0,
|
| +
|
| + /**
|
| + * Tracks navigator.credentials Promise resolvers.
|
| + * @type {!Object<number, function(?Credential|undefined)>}
|
| + * @private
|
| + */
|
| + resolvers_: {},
|
| +
|
| + /**
|
| + * Tracks navigator.credentials Promise rejecters.
|
| + * @type {!Object<number, function(?Error)>}
|
| + * @private
|
| + */
|
| + rejecters_: {}
|
| +};
|
| +
|
| +
|
| +/** @enum {string} */
|
| +__gCrWeb.credentialManager.CredentialType = {
|
| + CREDENTIAL: 'Credential',
|
| + PASSWORD_CREDENTIAL: 'PasswordCredential',
|
| + FEDERATED_CREDENTIAL: 'FederatedCredential',
|
| + PENDING_CREDENTIAL: 'PendingCredential'
|
| +};
|
| +
|
| +
|
| +/** @typedef {
|
| + * type: __gCrWeb.credentialManager.CredentialType,
|
| + * id: string,
|
| + * name: (string|undefined),
|
| + * avatarURL: (string|undefined),
|
| + * federation: (string|undefined)
|
| + * }
|
| + */
|
| +__gCrWeb.credentialManager.SerializedCredential;
|
| +
|
| +
|
| +/**
|
| + * Creates and returns a Promise whose resolver and rejecter functions are
|
| + * stored with the associated |requestId|. They can be accessed by calling
|
| + * |resolve| or |reject| on __gCrWeb['credentialManager'] with that ID.
|
| + * @param {number} requestId An identifier to track the resolver and rejecter
|
| + * associated with the returned Promise.
|
| + * @return {!Promise<?Credential|undefined>} A new Promise.
|
| + * @private
|
| + */
|
| +__gCrWeb['credentialManager'].createPromise_ = function(requestId) {
|
| + return new Promise(function(resolve, reject) {
|
| + __gCrWeb['credentialManager'].resolvers_[requestId] = resolve;
|
| + __gCrWeb['credentialManager'].rejecters_[requestId] = reject;
|
| + });
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Deletes the resolver and rejecter of the Promise associated with |requestId|.
|
| + * @param {number} requestId The identifier of the Promise.
|
| + * @private
|
| + */
|
| +__gCrWeb['credentialManager'].removePromise_ = function(requestId) {
|
| + delete __gCrWeb['credentialManager'].rejecters_[requestId];
|
| + delete __gCrWeb['credentialManager'].resolvers_[requestId];
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Parses |credentialData| into a Credential object.
|
| + * @param {!__gCrWeb.credentialManager.SerializedCredential} credentialData A
|
| + * simple object representation of a Credential like might be obtained from
|
| + * Credential.prototype.serialize.
|
| + * @return {?Credential} A Credential object, or null if parsing was
|
| + * unsuccessful.
|
| + * @private
|
| + */
|
| +__gCrWeb['credentialManager'].parseCredential_ = function(credentialData) {
|
| + var CredentialType = __gCrWeb.credentialManager.CredentialType;
|
| + switch (credentialData['type']) {
|
| + case CredentialType.CREDENTIAL:
|
| + return Credential.parse(credentialData);
|
| + case CredentialType.PASSWORD_CREDENTIAL:
|
| + return PasswordCredential.parse(credentialData);
|
| + case CredentialType.FEDERATED_CREDENTIAL:
|
| + return FederatedCredential.parse(credentialData);
|
| + case CredentialType.PENDING_CREDENTIAL:
|
| + return PendingCredential.parse(credentialData);
|
| + default:
|
| + return null;
|
| + }
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Resolves the Promise that was created with the given |requestId| with a
|
| + * Credential object parsed from |opt_credentialData| and removes that promise
|
| + * from the global state. Future attempts to resolve or reject the Promise will
|
| + * fail.
|
| + * @param {number} requestId The identifier of the Promise to resolve.
|
| + * @param {Object=} opt_credentialData An object describing a credential. If
|
| + * provided, this parameter will be parsed into the appropriate Credential
|
| + * type.
|
| + * @return {boolean} Indicates whether the Promise was successfully resolved.
|
| + */
|
| +__gCrWeb['credentialManager'].resolve = function(requestId,
|
| + opt_credentialData) {
|
| + var resolver = __gCrWeb['credentialManager'].resolvers_[requestId];
|
| + if (!resolver) {
|
| + return false;
|
| + }
|
| + if (opt_credentialData) {
|
| + var credential = null;
|
| + try {
|
| + credential =
|
| + __gCrWeb['credentialManager'].parseCredential_(opt_credentialData);
|
| + } catch (e) {
|
| + // Failed to parse |opt_credentialData|. The app side sent bad data.
|
| + return false;
|
| + }
|
| + resolver(credential);
|
| + } else {
|
| + resolver();
|
| + }
|
| + __gCrWeb['credentialManager'].removePromise_(requestId);
|
| + return true;
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Rejects the Promise that was created with the given |requestId| and cleans up
|
| + * that Promise.
|
| + * @param {number} requestId The identifier of the Promise to resolve.
|
| + * @param {string} errorType The type of the Error to pass to the rejecter
|
| + * function. If not recognized, a standard JavaScript Error will be used.
|
| + * @param {string} message A human-readable description of the error.
|
| + * @return {boolean} Indicates whether the Promise was successfully rejected.
|
| + */
|
| +__gCrWeb['credentialManager'].reject = function(requestId, errorType, message) {
|
| + var rejecter = __gCrWeb['credentialManager'].rejecters_[requestId];
|
| + if (!rejecter) {
|
| + return false;
|
| + }
|
| + var error = null;
|
| + if (errorType == 'SecurityError') {
|
| + error = new SecurityError(message);
|
| + } else if (errorType == 'InvalidStateError') {
|
| + error = new InvalidStateError(message);
|
| + } else {
|
| + error = new Error(message);
|
| + }
|
| + rejecter(error);
|
| + __gCrWeb['credentialManager'].removePromise_(requestId);
|
| + return true;
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Sends a command representing |method| of navigator.credentials to the app
|
| + * side with the given |opt_options|.
|
| + * @param {string} command The name of the command being sent.
|
| + * @param {Object=} opt_options A dictionary of additional properties to forward
|
| + * to the app.
|
| + * @return {!Promise<?Credential|undefined>} A promise for the result.
|
| + * @private
|
| + */
|
| +__gCrWeb['credentialManager'].invokeOnHost_ = function(command, opt_options) {
|
| + var requestId = __gCrWeb['credentialManager'].nextId_++;
|
| + var message = {
|
| + 'command': command,
|
| + 'requestId': requestId
|
| + };
|
| + if (opt_options) {
|
| + Object.keys(opt_options).forEach(function(key) {
|
| + message[key] = opt_options[key];
|
| + });
|
| + }
|
| + __gCrWeb.message.invokeOnHost(message);
|
| + return __gCrWeb['credentialManager'].createPromise_(requestId);
|
| +};
|
| +
|
| +
|
| +
|
| +/**
|
| + * Creates a new SecurityError to represent failures caused by violating
|
| + * security requirements of the API.
|
| + * @param {string} message A human-readable message describing this error.
|
| + * @extends {Error}
|
| + * @constructor
|
| + */
|
| +function SecurityError(message) {
|
| + Error.call(this, message);
|
| + this.name = 'SecurityError';
|
| + this.message = message;
|
| +}
|
| +SecurityError.prototype = Object.create(Error.prototype);
|
| +SecurityError.prototype.constructor = SecurityError;
|
| +
|
| +
|
| +
|
| +/**
|
| + * Creates a new InvalidStateError to represent failures caused by inconsistent
|
| + * internal state.
|
| + * @param {string} message A human-readable message describing this error.
|
| + * @extends {Error}
|
| + * @constructor
|
| + */
|
| +function InvalidStateError(message) {
|
| + Error.call(this, message);
|
| + this.name = 'InvalidStateError';
|
| + this.message = message;
|
| +}
|
| +InvalidStateError.prototype = Object.create(Error.prototype);
|
| +InvalidStateError.prototype.constructor = InvalidStateError;
|
| +
|
| +
|
| +
|
| +/**
|
| + * Creates a new Credential object. For more information, see
|
| + * https://w3c.github.io/webappsec/specs/credentialmanagement/#credential
|
| + * @param {string} id The credential’s identifier. This might be a username or
|
| + * email address, for instance.
|
| + * @param {string=} opt_name A name associated with the credential, intended as
|
| + * a human-understandable public name.
|
| + * @param {string=} opt_avatarUrl A URL pointing to an avatar image for the
|
| + * user. This URL MUST NOT be an a priori insecure URL.
|
| + * @constructor
|
| + */
|
| +function Credential(id, opt_name, opt_avatarUrl) {
|
| + if (id === null || id === undefined)
|
| + throw new TypeError('id must be provided');
|
| + /**
|
| + * The credential's identifier. Read-only.
|
| + * @type {string}
|
| + */
|
| + this.id;
|
| + Object.defineProperty(this, 'id', {
|
| + configurable: false,
|
| + enumerable: true,
|
| + value: id,
|
| + writable: false
|
| + });
|
| + /**
|
| + * A human-understandable public name associated with the credential.
|
| + * Read-only.
|
| + * @type {string}
|
| + */
|
| + this.name;
|
| + Object.defineProperty(this, 'name', {
|
| + configurable: false,
|
| + enumerable: true,
|
| + value: opt_name || '',
|
| + writable: false
|
| + });
|
| + /**
|
| + * A URL pointing to an avatar image for the user. Read-only.
|
| + * NOTE: This property name deviates from the Google JavaScript style guide
|
| + * in order to meet the public API specification.
|
| + * @type {string}
|
| + */
|
| + this.avatarURL;
|
| + Object.defineProperty(this, 'avatarURL', {
|
| + configurable: false,
|
| + enumerable: true,
|
| + value: opt_avatarUrl || '',
|
| + writable: false
|
| + });
|
| +}
|
| +
|
| +
|
| +/**
|
| + * Returns a simple object representation of this credential suitable for
|
| + * sending to the app side.
|
| + * @return {__gCrWeb.credentialManager.SerializedCredential} An object
|
| + * representing this credential.
|
| + */
|
| +Credential.prototype.serialize = function() {
|
| + var serialized = {
|
| + 'type': this.constructor.name,
|
| + 'id': this.id,
|
| + 'name': this.name
|
| + };
|
| + if (this.avatarURL && this.avatarURL.length > 0)
|
| + serialized['avatarURL'] = this.avatarURL;
|
| + return serialized;
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Parses |credentialData| into a Credential object.
|
| + * @param {!__gCrWeb.credentialManager.SerializedCredential} credentialData A
|
| + * simple object representation of a Credential like might be obtained from
|
| + * Credential.prototype.serialize.
|
| + * @return {Credential} A Credential object.
|
| + */
|
| +Credential.parse = function(credentialData) {
|
| + return new Credential(credentialData['id'],
|
| + credentialData['name'],
|
| + credentialData['avatarURL']);
|
| +};
|
| +
|
| +
|
| +
|
| +/**
|
| + * Creates a new PasswordCredential object. For more information, see
|
| + * https://w3c.github.io/webappsec/specs/credentialmanagement/#localcredential
|
| + * @param {string} id The credential’s identifier. This might be a username or
|
| + * email address, for instance.
|
| + * @param {string} password The credential's password.
|
| + * @param {string=} opt_name A name associated with the credential, intended as
|
| + * a human-understandable public name.
|
| + * @param {string=} opt_avatarUrl A URL pointing to an avatar image for the
|
| + * user. This URL MUST NOT be an a priori insecure URL.
|
| + * @constructor
|
| + * @extends {Credential}
|
| + */
|
| +function PasswordCredential(id, password, opt_name, opt_avatarUrl) {
|
| + if (password === null || password === undefined)
|
| + throw new TypeError('password must be provided');
|
| + Credential.call(this, id, opt_name, opt_avatarUrl);
|
| + var formData = new FormData();
|
| + formData.append('username', id);
|
| + formData.append('password', password);
|
| + /**
|
| + * A FormData object, containing two entries: one named username, the other
|
| + * named password. Read-only.
|
| + * @type {FormData}
|
| + */
|
| + this.formData;
|
| + Object.defineProperty(this, 'formData', {
|
| + configurable: false,
|
| + enumerable: true,
|
| + value: formData,
|
| + writable: false
|
| + });
|
| + /**
|
| + * The credential's password.
|
| + * @type {string}
|
| + * @private
|
| + */
|
| + this.password_;
|
| + Object.defineProperty(this, 'password_', {
|
| + configurable: false,
|
| + enumerable: false,
|
| + value: password,
|
| + writable: false
|
| + });
|
| +}
|
| +PasswordCredential.prototype = Object.create(Credential.prototype);
|
| +PasswordCredential.prototype.constructor = PasswordCredential;
|
| +
|
| +
|
| +/**
|
| + * Returns a simple object representation of this credential suitable for
|
| + * sending to the app side.
|
| + * @return {__gCrWeb.credentialManager.SerializedCredential} An object
|
| + * representing this credential.
|
| + */
|
| +PasswordCredential.prototype.serialize = function() {
|
| + var obj = Credential.prototype.serialize.call(this);
|
| + obj.password = this.password_;
|
| + return obj;
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Parses |credentialData| into a PasswordCredential object.
|
| + * @param {!__gCrWeb.credentialManager.SerializedCredential} credentialData A
|
| + * simple object representation of a PasswordCredential like might be
|
| + * obtained from PasswordCredential.prototype.serialize.
|
| + * @return {PasswordCredential} A PasswordCredential object.
|
| + */
|
| +PasswordCredential.parse = function(credentialData) {
|
| + return new PasswordCredential(credentialData['id'],
|
| + credentialData['password'],
|
| + credentialData['name'],
|
| + credentialData['avatarURL']);
|
| +};
|
| +
|
| +
|
| +
|
| +/**
|
| + * Creates a new FederatedCredential object. For more information, see
|
| + * https://w3c.github.io/webappsec/specs/credentialmanagement/#federatedcredential
|
| + * @param {string} id The credential’s identifier. This might be a username or
|
| + * email address, for instance.
|
| + * @param {string} federation The credential’s federation. For details regarding
|
| + * valid formats, see https://w3c.github.io/webappsec/specs/credentialmanagement/#identifying-federations
|
| + * @param {string=} opt_name A name associated with the credential, intended as
|
| + * a human-understandable public name.
|
| + * @param {string=} opt_avatarUrl A URL pointing to an avatar image for the
|
| + * user. This URL MUST NOT be an a priori insecure URL.
|
| + * @constructor
|
| + * @extends {Credential}
|
| + */
|
| +function FederatedCredential(id, federation, opt_name, opt_avatarUrl) {
|
| + if (federation === null || federation === undefined)
|
| + throw new TypeError('federation must be provided');
|
| + Credential.call(this, id, opt_name, opt_avatarUrl);
|
| + /**
|
| + * The credential’s federation. Read-only.
|
| + * @type {string}
|
| + */
|
| + this.federation;
|
| + Object.defineProperty(this, 'federation', {
|
| + configurable: false,
|
| + enumerable: true,
|
| + value: federation,
|
| + writable: false
|
| + });
|
| +}
|
| +FederatedCredential.prototype = Object.create(Credential.prototype);
|
| +FederatedCredential.prototype.constructor = FederatedCredential;
|
| +
|
| +
|
| +/**
|
| + * Returns a simple object representation of this credential suitable for
|
| + * sending to the app side.
|
| + * @return {__gCrWeb.credentialManager.SerializedCredential} An object
|
| + * representing this credential.
|
| + */
|
| +FederatedCredential.prototype.serialize = function() {
|
| + var obj = Credential.prototype.serialize.call(this);
|
| + obj.federation = this.federation;
|
| + return obj;
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Parses |credentialData| into a FederatedCredential object.
|
| + * @param {!__gCrWeb.credentialManager.SerializedCredential} credentialData A
|
| + * simple object representation of a FederatedCredential like might be
|
| + * obtained from FederatedCredential.prototype.serialize.
|
| + * @return {!FederatedCredential} A FederatedCredential object.
|
| + */
|
| +FederatedCredential.parse = function(credentialData) {
|
| + return new FederatedCredential(credentialData['id'],
|
| + credentialData['federation'],
|
| + credentialData['name'],
|
| + credentialData['avatarURL']);
|
| +};
|
| +
|
| +
|
| +
|
| +/**
|
| + * Creates a new PendingCredential object. For more information, see
|
| + * https://w3c.github.io/webappsec/specs/credentialmanagement/#pendingcredential
|
| + * @param {string} id The credential’s identifier. This might be a username or
|
| + * email address, for instance.
|
| + * @param {string=} opt_name A name associated with the credential, intended as
|
| + * a human-understandable public name.
|
| + * @param {string=} opt_avatarUrl A URL pointing to an avatar image for the
|
| + * user. This URL MUST NOT be an a priori insecure URL.
|
| + * @constructor
|
| + * @extends {Credential}
|
| + */
|
| +function PendingCredential(id, opt_name, opt_avatarUrl) {
|
| + Credential.call(this, id, opt_name, opt_avatarUrl);
|
| +}
|
| +PendingCredential.prototype = Object.create(Credential.prototype);
|
| +PendingCredential.prototype.constructor = PendingCredential;
|
| +
|
| +
|
| +/**
|
| + * Parses |credentialData| into a PendingCredential object.
|
| + * @param {!__gCrWeb.credentialManager.SerializedCredential} credentialData A
|
| + * simple object representation of a PendingCredential like might be
|
| + * obtained from PendingCredential.prototype.serialize.
|
| + * @return {!Credential} A PendingCredential object.
|
| + */
|
| +PendingCredential.parse = function(credentialData) {
|
| + return new PendingCredential(credentialData['id'],
|
| + credentialData['name'],
|
| + credentialData['avatarURL']);
|
| +};
|
| +
|
| +
|
| +
|
| +/**
|
| + * Implements the public Credential Management API. For more information, see
|
| + * http://w3c.github.io/webappsec/specs/credentialmanagement/#interfaces-credential-manager
|
| + * @constructor
|
| + */
|
| +function CredentialsContainer() {
|
| +}
|
| +
|
| +
|
| +/**
|
| + * Requests a credential from the credential manager.
|
| + * @param {{suppressUI: boolean, federations: Array<string>}=} opt_options An
|
| + * optional dictionary of parameters for the request. If |suppressUI| is
|
| + * true, the returned promise will only be resolved with a credential if
|
| + * this is possible without user interaction; otherwise, the returned
|
| + * promise will be resolved with |undefined|. |federations| specifies a
|
| + * list of acceptable federation providers. For more information, see
|
| + * https://w3c.github.io/webappsec/specs/credentialmanagement/#interfaces-request-options
|
| + * @return {!Promise<?Credential|undefined>} A promise for retrieving the result
|
| + * of the request.
|
| + */
|
| +CredentialsContainer.prototype.request = function(opt_options) {
|
| + var options = {
|
| + 'suppressUI': !!opt_options && !!opt_options['suppressUI'],
|
| + 'federations': (!!opt_options && opt_options['federations']) || []
|
| + };
|
| + return __gCrWeb['credentialManager'].invokeOnHost_(
|
| + 'navigator.credentials.request', options);
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Notifies the browser that the user has successfully signed in.
|
| + * @param {Credential=} opt_successfulCredential The credential that was used
|
| + * to sign in.
|
| + * @return {!Promise<?Credential|undefined>} A promise to wait for
|
| + * acknowledgement from the browser.
|
| + */
|
| +CredentialsContainer.prototype.notifySignedIn = function(
|
| + opt_successfulCredential) {
|
| + var options = opt_successfulCredential && {
|
| + 'credential': opt_successfulCredential.serialize()
|
| + };
|
| + return __gCrWeb['credentialManager'].invokeOnHost_(
|
| + 'navigator.credentials.notifySignedIn', options);
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Notifies the browser that the user failed to sign in.
|
| + * @param {Credential=} opt_failedCredential The credential that failed to
|
| + * sign in.
|
| + * @return {!Promise<?Credential|undefined>} A promise to wait for
|
| + * acknowledgement from the browser.
|
| + */
|
| +CredentialsContainer.prototype.notifyFailedSignIn = function(
|
| + opt_failedCredential) {
|
| + var options = opt_failedCredential && {
|
| + 'credential': opt_failedCredential.serialize()
|
| + };
|
| + return __gCrWeb['credentialManager'].invokeOnHost_(
|
| + 'navigator.credentials.notifyFailedSignIn', options);
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Notifies the browser that the user signed out.
|
| + * @return {!Promise<?Credential|undefined>} A promise to wait for
|
| + * acknowledgement from the browser.
|
| + */
|
| +CredentialsContainer.prototype.notifySignedOut = function() {
|
| + return __gCrWeb['credentialManager'].invokeOnHost_(
|
| + 'navigator.credentials.notifySignedOut');
|
| +};
|
| +
|
| +
|
| +// Install the public interface.
|
| +window.navigator.credentials = new CredentialsContainer();
|
|
|