cb = function(user) {
    if (user) {
      // For anonymous user upgrade, call link with credential on the external
      // Auth user. Otherwise merge conflict will always occur when linking the
      // credential to the external anonymous user after creation.
      return /** @type {!firebase.Promise<!firebase.auth.UserCredential>} */ (
          user.linkWithCredential(credential)
          .then(function(result) {
            return result;
          }, function(error) {
            // Fail directly when email already in use error thrown. This will
            // trigger account linking flow.
            // When email already exists for a new federated credential, user
            // must sign in to existing account and then link this credential to
            // that account.
            if (error &&
                error['code'] == 'auth/email-already-in-use' &&
                error['email'] && error['credential']) {
              throw error;
            }
            // Pass the same credential back in the error. This assumes the
            // credential used is not a one-time credential.
            return self.onUpgradeError(error, credential);
          }));
    } else {
      // Starts sign in with a Firebase Auth credential, typically an OAuth
      // credential. This runs on the internal Auth instance as finish sign in
      // will sign in with that same credential to developer Auth instance.
      return self.getAuth().signInWithCredential(credential);
    }
  }
Logs into Firebase with the given 3rd party credentials.
@param {!firebase.auth.AuthCredential} credential The Auth credential.
@return {!firebase.Promise<!firebase.auth.UserCredential>}