renewLoan method

  1. @override
Future<Try<DateTime, LcpException>> renewLoan(
  1. RenewListener listener, {
  2. bool prefersWebPage = false,
})
override

Renews the loan by starting a renew LSD interaction.

@param prefersWebPage Indicates whether the loan should be renewed through a web page if available, instead of programmatically.

Implementation

@override
Future<Try<DateTime, LcpException>> renewLoan(RenewListener listener,
    {bool prefersWebPage = false}) async {
  // Finds the renew link according to `prefersWebPage`.
  Link? findRenewLink() {
    StatusDocument? status = _documents.status;
    if (status == null) {
      return null;
    }

    List<MediaType> types = [MediaType.html, MediaType.xhtml];
    if (prefersWebPage) {
      types.add(MediaType.lcpStatusDocument);
    } else {
      types.insert(0, MediaType.lcpStatusDocument);
    }

    for (MediaType type in types) {
      Link? link = status.link(StatusRel.renew, type: type);
      if (link != null) {
        return link;
      }
    }

    // Fallback on the first renew link with no media type set and assume it's a PUT action.
    return status.linkWithNoType(StatusRel.renew);
  }

  // Programmatically renew the loan with a PUT request.
  Future<ByteData> renewProgrammatically(Link link) async {
    DateTime? endDate;
    if (link.templateParameters.contains("end")) {
      endDate = await listener.preferredEndDate(maxRenewDate);
    }

    Map<String, String> parameters = await _device.asQueryParameters;
    if (endDate != null) {
      parameters["end"] = endDate.toIso8601String();
    }

    Uri url = link.urlWithParams(parameters: parameters);

    Try<ByteData, NetworkException> result =
        await _network.fetch(url.toString(), method: Method.put);
    return result.getOrElse((error) {
      switch (error.status) {
        case HttpStatus.badRequest:
          throw LcpException.renew.renewFailed;
        case HttpStatus.forbidden:
          throw LcpException.renew.invalidRenewalPeriod(this.maxRenewDate);
        default:
          throw LcpException.renew.unexpectedServerError;
      }
    });
  }

  // Renew the loan by presenting a web page to the user.
  Future<ByteData> renewWithWebPage(Link link) {
    // The reading app will open the URL in a web view and return when it is dismissed.
    listener.openWebPage(link.url);

    Uri statusUrl;
    try {
      statusUrl = license.url(LicenseRel.status,
          preferredType: MediaType.lcpStatusDocument);
    } on LcpException {
      throw LcpException.licenseInteractionNotAvailable;
    }

    return _network
        .fetch(statusUrl.toString())
        .then((value) => value.getOrThrow());
  }

  try {
    Link? link = findRenewLink();
    if (link == null) {
      throw LcpException.licenseInteractionNotAvailable;
    }

    Future<ByteData> data;
    if (link.mediaType.isHtml) {
      data = renewWithWebPage(link);
    } else {
      data = renewProgrammatically(link);
    }

    _validateStatusDocument(await data);

    return Try.success(_documents.license.rights.end);
//     } on CancellationException {
// // Passthrough for cancelled coroutines
//       rethrow;
  } on Exception catch (e) {
    return Try.failure(LcpException.wrap(e));
  }
}