generate_(initData, offlineSessionId) {
    const PatchedMediaKeysWebkit = shaka.polyfill.PatchedMediaKeysWebkit;

    if (this.initialized_) {
      const error = new Error('The session is already initialized.');
      return Promise.reject(error);
    }

    this.initialized_ = true;

    /** @type {!Uint8Array} */
    let mangledInitData;

    try {
      if (this.type_ == 'persistent-license') {
        const StringUtils = shaka.util.StringUtils;
        if (!offlineSessionId) {
          goog.asserts.assert(initData, 'expecting init data');
          // Persisting the initial license.
          // Prefix the init data with a tag to indicate persistence.
          const prefix = StringUtils.toUTF8('PERSISTENT|');
          mangledInitData = shaka.util.Uint8ArrayUtils.concat(prefix, initData);
        } else {
          // Loading a stored license.
          // Prefix the init data (which is really a session ID) with a tag to
          // indicate that we are loading a persisted session.
          mangledInitData = shaka.util.BufferUtils.toUint8(
              StringUtils.toUTF8('LOAD_SESSION|' + offlineSessionId));
        }
      } else {
        // Streaming.
        goog.asserts.assert(this.type_ == 'temporary',
            'expected temporary session');
        goog.asserts.assert(!offlineSessionId,
            'unexpected offline session ID');
        goog.asserts.assert(initData, 'expecting init data');
        mangledInitData = shaka.util.BufferUtils.toUint8(initData);
      }

      goog.asserts.assert(mangledInitData, 'init data not set!');
    } catch (exception) {
      return Promise.reject(exception);
    }

    goog.asserts.assert(this.generatePromise_ == null,
        'generatePromise_ should be null');
    this.generatePromise_ = new shaka.util.PublicPromise();

    // Because we are hacking media.src in createSession to better emulate
    // unprefixed EME's ability to create sessions and license requests without
    // a video tag, we can get ourselves into trouble.  It seems that sometimes,
    // the setting of media.src hasn't been processed by some other thread, and
    // GKR can throw an exception.  If this occurs, wait 10 ms and try again at
    // most once.  This situation should only occur when init data is available
    // ahead of the 'needkey' event.

    const generateKeyRequestName =
        PatchedMediaKeysWebkit.prefixApi_('generateKeyRequest');
    try {
      this.media_[generateKeyRequestName](this.keySystem_, mangledInitData);
    } catch (exception) {
      if (exception.name != 'InvalidStateError') {
        this.generatePromise_ = null;
        return Promise.reject(exception);
      }

      const timer = new shaka.util.Timer(() => {
        try {
          this.media_[generateKeyRequestName](this.keySystem_, mangledInitData);
        } catch (exception2) {
          this.generatePromise_.reject(exception2);
          this.generatePromise_ = null;
        }
      });

      timer.tickAfter(/* seconds= */ 0.01);
    }

    return this.generatePromise_;
  }
Logic which is shared between generateRequest() and load(), both of which
are ultimately implemented with webkitGenerateKeyRequest in prefixed EME.

@param {?BufferSource} initData
@param {?string} offlineSessionId
@return {!Promise}
@private