text: var AWS = require('../core');
  
  /**
   * Creates a credential provider chain that searches for AWS credentials
   * in a list of credential providers specified by the {providers} property.
   *
   * By default, the chain will use the {defaultProviders} to resolve credentials.
   * These providers will look in the environment using the
   * {AWS.EnvironmentCredentials} class with the 'AWS' and 'AMAZON' prefixes.
   *
   * ## Setting Providers
   *
   * Each provider in the {providers} list should be a function that returns
   * a {AWS.Credentials} object, or a hardcoded credentials object. The function
   * form allows for delayed execution of the credential construction.
   *
   * ## Resolving Credentials from a Chain
   *
   * Call {resolve} to return the first valid credential object that can be
   * loaded by the provider chain.
   *
   * For example, to resolve a chain with a custom provider that checks a file
   * on disk after the set of {defaultProviders}:
   *
   * ```javascript
   * var diskProvider = new AWS.FileSystemCredentials('./creds.json');
   * var chain = new AWS.CredentialProviderChain();
   * chain.providers.push(diskProvider);
   * chain.resolve();
   * ```
   *
   * The above code will return the `diskProvider` object if the
   * file contains credentials and the `defaultProviders` do not contain
   * any credential settings.
   *
   * @!attribute providers
   *   @return [Array<AWS.Credentials, Function>]
   *     a list of credentials objects or functions that return credentials
   *     objects. If the provider is a function, the function will be
   *     executed lazily when the provider needs to be checked for valid
   *     credentials. By default, this object will be set to the
   *     {defaultProviders}.
   *   @see defaultProviders
   */
  AWS.CredentialProviderChain = AWS.util.inherit(AWS.Credentials, {
  
    /**
     * Creates a new CredentialProviderChain with a default set of providers
     * specified by {defaultProviders}.
     */
    constructor: function CredentialProviderChain(providers) {
      if (providers) {
        this.providers = providers;
      } else {
        this.providers = AWS.CredentialProviderChain.defaultProviders.slice(0);
      }
      this.resolveCallbacks = [];
    },
  
    /**
     * @!method  resolvePromise()
     *   Returns a 'thenable' promise.
     *   Resolves the provider chain by searching for the first set of
     *   credentials in {providers}.
     *
     *   Two callbacks can be provided to the `then` method on the returned promise.
     *   The first callback will be called if the promise is fulfilled, and the second
     *   callback will be called if the promise is rejected.
     *   @callback fulfilledCallback function(credentials)
     *     Called if the promise is fulfilled and the provider resolves the chain
     *     to a credentials object
     *     @param credentials [AWS.Credentials] the credentials object resolved
     *       by the provider chain.
     *   @callback rejectedCallback function(error)
     *     Called if the promise is rejected.
     *     @param err [Error] the error object returned if no credentials are found.
     *   @return [Promise] A promise that represents the state of the `resolve` method call.
     *   @example Calling the `resolvePromise` method.
     *     var promise = chain.resolvePromise();
     *     promise.then(function(credentials) { ... }, function(err) { ... });
     */
  
    /**
     * Resolves the provider chain by searching for the first set of
     * credentials in {providers}.
     *
     * @callback callback function(err, credentials)
     *   Called when the provider resolves the chain to a credentials object
     *   or null if no credentials can be found.
     *
     *   @param err [Error] the error object returned if no credentials are
     *     found.
     *   @param credentials [AWS.Credentials] the credentials object resolved
     *     by the provider chain.
     * @return [AWS.CredentialProviderChain] the provider, for chaining.
     */
    resolve: function resolve(callback) {
      var self = this;
      if (self.providers.length === 0) {
        callback(new Error('No providers'));
        return self;
      }
  
      if (self.resolveCallbacks.push(callback) === 1) {
        var index = 0;
        var providers = self.providers.slice(0);
  
        function resolveNext(err, creds) {
          if ((!err && creds) || index === providers.length) {
            AWS.util.arrayEach(self.resolveCallbacks, function (callback) {
              callback(err, creds);
            });
            self.resolveCallbacks.length = 0;
            return;
          }
  
          var provider = providers[index++];
          if (typeof provider === 'function') {
            creds = provider.call();
          } else {
            creds = provider;
          }
  
          if (creds.get) {
            creds.get(function (getErr) {
              resolveNext(getErr, getErr ? null : creds);
            });
          } else {
            resolveNext(null, creds);
          }
        }
  
        resolveNext();
      }
  
      return self;
    }
  });
  
  /**
   * The default set of providers used by a vanilla CredentialProviderChain.
   *
   * In the browser:
   *
   * ```javascript
   * AWS.CredentialProviderChain.defaultProviders = []
   * ```
   *
   * In Node.js:
   *
   * ```javascript
   * AWS.CredentialProviderChain.defaultProviders = [
   *   function () { return new AWS.EnvironmentCredentials('AWS'); },
   *   function () { return new AWS.EnvironmentCredentials('AMAZON'); },
   *   function () { return new AWS.SharedIniFileCredentials(); },
   *   function () {
   *     // if AWS_CONTAINER_CREDENTIALS_RELATIVE_URI is set
   *       return new AWS.ECSCredentials();
   *     // else
   *       return new AWS.EC2MetadataCredentials();
   *   }
   * ]
   * ```
   */
  AWS.CredentialProviderChain.defaultProviders = [];
  
  /**
   * @api private
   */
  AWS.CredentialProviderChain.addPromisesToClass = function addPromisesToClass(PromiseDependency) {
    this.prototype.resolvePromise = AWS.util.promisifyMethod('resolve', PromiseDependency);
  };
  
  /**
   * @api private
   */
  AWS.CredentialProviderChain.deletePromisesFromClass = function deletePromisesFromClass() {
    delete this.prototype.resolvePromise;
  };
  
  AWS.util.addPromises(AWS.CredentialProviderChain);
  