Index: components/cronet/android/java/src/org/chromium/net/UrlResponseInfo.java |
diff --git a/components/cronet/android/java/src/org/chromium/net/UrlResponseInfo.java b/components/cronet/android/java/src/org/chromium/net/UrlResponseInfo.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..2a914d254ae5c7f361a63e9c44be49320e5c1d26 |
--- /dev/null |
+++ b/components/cronet/android/java/src/org/chromium/net/UrlResponseInfo.java |
@@ -0,0 +1,172 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+package org.chromium.net; |
+ |
+import java.util.ArrayList; |
+import java.util.Collections; |
+import java.util.List; |
+import java.util.Locale; |
+import java.util.Map; |
+import java.util.TreeMap; |
+import java.util.concurrent.atomic.AtomicLong; |
+ |
+/** |
+ * Contains basic information about a response. Included in {@link UrlRequestListener} callbacks. |
+ * Each {@link UrlRequestListener#onReceivedRedirect UrlRequestListener.onReceivedRedirect()} |
+ * callback gets a different copy of UrlResponseInfo describing a particular redirect response. |
+ */ |
+public final class UrlResponseInfo { |
+ private final List<String> mResponseInfoUrlChain; |
+ private final int mHttpStatusCode; |
+ private final String mHttpStatusText; |
+ private final boolean mWasCached; |
+ private final String mNegotiatedProtocol; |
+ private final String mProxyServer; |
+ private final List<Map.Entry<String, String>> mAllHeadersList; |
+ private final AtomicLong mReceivedBytesCount; |
+ private Map<String, List<String>> mResponseHeaders; |
+ |
+ UrlResponseInfo(List<String> urlChain, int httpStatusCode, String httpStatusText, |
+ List<Map.Entry<String, String>> allHeadersList, boolean wasCached, |
+ String negotiatedProtocol, String proxyServer) { |
+ mResponseInfoUrlChain = Collections.unmodifiableList(urlChain); |
+ mHttpStatusCode = httpStatusCode; |
+ mHttpStatusText = httpStatusText; |
+ mAllHeadersList = Collections.unmodifiableList(allHeadersList); |
+ mWasCached = wasCached; |
+ mNegotiatedProtocol = negotiatedProtocol; |
+ mProxyServer = proxyServer; |
+ mReceivedBytesCount = new AtomicLong(); |
+ } |
+ |
+ /** |
+ * Returns the URL the response is for. This is the URL after following |
+ * redirects, so it may not be the originally requested URL. |
+ * @return the URL the response is for. |
+ */ |
+ public String getUrl() { |
+ return mResponseInfoUrlChain.get(mResponseInfoUrlChain.size() - 1); |
+ } |
+ |
+ /** |
+ * Returns the URL chain. The first entry is the origianlly requested URL; |
+ * the following entries are redirects followed. |
+ * @return the URL chain. |
+ */ |
+ public List<String> getUrlChain() { |
+ return mResponseInfoUrlChain; |
+ } |
+ |
+ /** |
+ * Returns the HTTP status code. When a resource is retrieved from the cache, |
+ * whether it was revalidated or not, the original status code is returned. |
+ * @return the HTTP status code. |
+ */ |
+ public int getHttpStatusCode() { |
+ return mHttpStatusCode; |
+ } |
+ |
+ /** |
+ * Returns the HTTP status text of the status line. For example, if the |
+ * request received a "HTTP/1.1 200 OK" response, this method returns "OK". |
+ * @return the HTTP status text of the status line. |
+ */ |
+ public String getHttpStatusText() { |
+ return mHttpStatusText; |
+ } |
+ |
+ /** |
+ * Returns an unmodifiable list of response header field and value pairs. |
+ * The headers are in the same order they are received over the wire. |
+ * @return an unmodifiable list of response header field and value pairs. |
+ */ |
+ public List<Map.Entry<String, String>> getAllHeadersAsList() { |
+ return mAllHeadersList; |
+ } |
+ |
+ /** |
+ * Returns an unmodifiable map of the response-header fields and values. |
+ * Each list of values for a single header field is in the same order they |
+ * were received over the wire. |
+ * @return an unmodifiable map of the response-header fields and values. |
+ */ |
+ public Map<String, List<String>> getAllHeaders() { |
+ if (mResponseHeaders != null) { |
+ return mResponseHeaders; |
+ } |
+ Map<String, List<String>> map = |
+ new TreeMap<String, List<String>>(String.CASE_INSENSITIVE_ORDER); |
+ for (Map.Entry<String, String> entry : mAllHeadersList) { |
+ List<String> values = new ArrayList<String>(); |
+ if (map.containsKey(entry.getKey())) { |
+ values.addAll(map.get(entry.getKey())); |
+ } |
+ values.add(entry.getValue()); |
+ map.put(entry.getKey(), Collections.unmodifiableList(values)); |
+ } |
+ mResponseHeaders = Collections.unmodifiableMap(map); |
+ return mResponseHeaders; |
+ } |
+ |
+ /** |
+ * Returns {@code true} if the response came from the cache, including |
+ * requests that were revalidated over the network before being retrieved |
+ * from the cache. |
+ * @return {@code true} if the response came from the cache, {@code false} |
+ * otherwise. |
+ */ |
+ public boolean wasCached() { |
+ return mWasCached; |
+ } |
+ |
+ /** |
+ * Returns the protocol (for example 'quic/1+spdy/3') negotiated with the server. |
+ * Returns an empty string if no protocol was negotiated, the protocol is |
+ * not known, or when using plain HTTP or HTTPS. |
+ * @return the protocol negotiated with the server. |
+ */ |
+ // TODO(mef): Figure out what this returns in the cached case, both with |
+ // and without a revalidation request. |
+ public String getNegotiatedProtocol() { |
+ return mNegotiatedProtocol; |
+ } |
+ |
+ /** |
+ * Returns the proxy server that was used for the request. |
+ * @return the proxy server that was used for the request. |
+ */ |
+ public String getProxyServer() { |
+ return mProxyServer; |
+ } |
+ |
+ /** |
+ * Returns a minimum count of bytes received from the network to process this |
+ * request. This count may ignore certain overheads (for example IP and TCP/UDP framing, |
+ * SSL handshake and framing, proxy handling). This count is taken prior to decompression |
+ * (for example GZIP and SDCH) and includes headers and data from all redirects. |
+ * |
+ * This value may change (even for one {@link UrlResponseInfo} instance) as the request |
+ * progresses until completion, when {@link UrlRequestListener#onSucceeded} or |
+ * {@link UrlRequestListener#onFailed} is called. |
+ */ |
+ public long getReceivedBytesCount() { |
+ return mReceivedBytesCount.get(); |
+ } |
+ |
+ @Override |
+ public String toString() { |
+ return String.format(Locale.ROOT, "UrlResponseInfo[%s]: urlChain = %s, " |
+ + "httpStatus = %d %s, headers = %s, wasCached = %b, " |
+ + "negotiatedProtocol = %s, proxyServer= %s, receivedBytesCount = %d", |
+ getUrl(), getUrlChain().toString(), getHttpStatusCode(), getHttpStatusText(), |
+ getAllHeadersAsList().toString(), wasCached(), getNegotiatedProtocol(), |
+ getProxyServer(), getReceivedBytesCount()); |
+ } |
+ |
+ // Sets mReceivedBytesCount. Must not be called after request completion or cancellation. |
+ void setReceivedBytesCount(long currentReceivedBytesCount) { |
+ mReceivedBytesCount.set(currentReceivedBytesCount); |
+ } |
+} |