filterResponse_(type, responseAndGotProgress, context) {
    let filterOperation = shaka.util.AbortableOperation.completed(undefined);
    for (const responseFilter of this.responseFilters_) {
      // Response filters are run sequentially.
      filterOperation = filterOperation.chain(() => {
        const resp = responseAndGotProgress.response;
        if (resp.data) {
          // TODO: See TODO in filterRequest_.
          resp.data = shaka.util.BufferUtils.toArrayBuffer(resp.data);
        }
        return responseFilter(type, resp, context);
      });
    }
    // If successful, return the filtered response with whether it got
    // progress.
    return filterOperation.chain(() => {
      return responseAndGotProgress;
    }, (e) => {
      // Catch any errors thrown by request filters, and substitute
      // them with a Shaka-native error.

      // The error is assumed to be critical if the original wasn't a Shaka
      // error.
      let severity = shaka.util.Error.Severity.CRITICAL;
      if (e instanceof shaka.util.Error) {
        if (e.code == shaka.util.Error.Code.OPERATION_ABORTED) {
          // Don't change anything if the operation was aborted.
          throw e;
        }

        severity = e.severity;
      }

      throw new shaka.util.Error(
          severity,
          shaka.util.Error.Category.NETWORK,
          shaka.util.Error.Code.RESPONSE_FILTER_ERROR, e);
    });
  }
@param {shaka.net.NetworkingEngine.RequestType} type
@param {shaka.net.NetworkingEngine.ResponseAndGotProgress
       } responseAndGotProgress
@param {shaka.extern.RequestContext=} context
@return {!shaka.extern.IAbortableOperation.<
              shaka.net.NetworkingEngine.ResponseAndGotProgress>}
@private