update_(promise, response) {
    const PatchedMediaKeysWebkit = shaka.polyfill.PatchedMediaKeysWebkit;

    if (this.updatePromise_) {
      // We already have an update in-progress, so defer this one until after
      // the old one is resolved.  Execute this whether the original one
      // succeeds or fails.
      this.updatePromise_.then(() => this.update_(promise, response))
          .catch(() => this.update_(promise, response));
      return;
    }

    this.updatePromise_ = promise;

    let key;
    let keyId;

    if (this.keySystem_ == 'webkit-org.w3.clearkey') {
      // The current EME version of clearkey wants a structured JSON response.
      // The v0.1b version wants just a raw key.  Parse the JSON response and
      // extract the key and key ID.
      const StringUtils = shaka.util.StringUtils;
      const Uint8ArrayUtils = shaka.util.Uint8ArrayUtils;
      const licenseString = StringUtils.fromUTF8(response);
      const jwkSet = /** @type {JWKSet} */ (JSON.parse(licenseString));
      const kty = jwkSet.keys[0].kty;
      if (kty != 'oct') {
        // Reject the promise.
        this.updatePromise_.reject(new Error(
            'Response is not a valid JSON Web Key Set.'));
        this.updatePromise_ = null;
      }
      key = Uint8ArrayUtils.fromBase64(jwkSet.keys[0].k);
      keyId = Uint8ArrayUtils.fromBase64(jwkSet.keys[0].kid);
    } else {
      // The key ID is not required.
      key = shaka.util.BufferUtils.toUint8(response);
      keyId = null;
    }

    const addKeyName = PatchedMediaKeysWebkit.prefixApi_('addKey');
    try {
      this.media_[addKeyName](this.keySystem_, key, keyId, this.sessionId);
    } catch (exception) {
      // Reject the promise.
      this.updatePromise_.reject(exception);
      this.updatePromise_ = null;
    }
  }
An internal version of update which defers new calls while old ones are in
progress.

@param {!shaka.util.PublicPromise} promise  The promise associated with
  this call.
@param {BufferSource} response
@private