Interface NetworkGuard


public interface NetworkGuard

Interception point for cross-cutting network policy: decorating outgoing requests, and vetting the TLS certificate chain before a request body is written.

At most one guard is installed per app, via NetworkManager.setNetworkGuard(NetworkGuard), and the slot seals after the first call. AppShield is the intended consumer, but the interface is deliberately generic and carries no dependency on it.

This does not replace the per-request certificate hook

[ConnectionRequest#checkSSLCertificates(ConnectionRequest.SSLCertificate[])] remains the way an individual request pins for itself, and it still runs first and unchanged. The guard runs afterwards, so an app that already pins manually keeps working and simply gains a second, app-wide layer.

  • Method Details

    • beforeRequest

      void beforeRequest(ConnectionRequest request) throws IOException

      Called on the network thread immediately before the connection is opened, and again on each retry or redirect so a stale token is never reused.

      May block -- it is off the EDT and outside the network queue's lock. Add headers here. Throwing fails the request through the normal error path.

      Throws:
      IOException
    • isCertificateCheckRequired

      boolean isCertificateCheckRequired(String url)

      Whether this URL's certificate chain needs to be inspected, i.e. whether the host has pins.

      Must be fast and purely local. On iOS this is consulted from the TLS delegate thread while the handshake is held open.

      Returning true has a cost beyond the check itself: the framework asks the platform for the richer certificate details, including public-key digests, which it does not otherwise collect. Return false for hosts with no pins.

    • checkCertificates

      void checkCertificates(ConnectionRequest request, ConnectionRequest.SSLCertificate[] certificates) throws IOException

      Vets the certificate chain, after the handshake and before any request body is written.

      Throwing an IOException aborts the request and surfaces through the request's normal error handling, rather than completing it with an empty response.

      Must be local and non-blocking, for the same delegate-thread reason as isCertificateCheckRequired(String). In particular it must not try to fetch a fresh pin set: use the last known one and let a mismatch stand.

      Throws:
      IOException
    • interestingResponseHeaders

      String[] interestingResponseHeaders()

      Response header names this guard wants captured, or null for none.

      Asked once per response, while the connection is still open. The framework does not retain arbitrary response headers, and by the time afterResponse(ConnectionRequest, int, String[]) runs the connection has been closed -- so anything a guard needs to see has to be named here first.

    • afterResponse

      void afterResponse(ConnectionRequest request, int responseCode, String[] headers)

      Called once the response code is known, including for failed requests.

      This is how a token layer learns its token was refused -- a 401 or 403 from a protected host usually means the cached token should be discarded before the next attempt. Must not throw; exceptions here are logged and swallowed so a telemetry problem cannot fail a request that otherwise succeeded.

      Parameters:
      headers - values for the names returned by interestingResponseHeaders(), in the same order; an entry is null when the response did not carry that header