Chromium Code Reviews| 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..a303657711a651e94af3b6e924a8c8346c278848 |
| --- /dev/null |
| +++ b/components/cronet/android/java/src/org/chromium/net/UrlResponseInfo.java |
| @@ -0,0 +1,175 @@ |
| +// 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; |
| + |
| +/** |
| + * Contains basic information about a response. Sent to the embedder whenever |
| + * headers are received. |
| + */ |
| +// TODO(mef): Remove ResponseInfo after caller updates. |
|
pauljensen
2015/09/25 18:30:16
This class has pretty crazy mutability requirement
|
| +public final class UrlResponseInfo implements ResponseInfo { |
| + 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 Map<String, List<String>> mResponseHeaders; |
| + private volatile long mReceivedBytesCount; |
|
xunjieli
2015/09/25 13:54:32
We are only updating this on the network thread. O
mef
2015/09/25 15:58:27
Um, what if the app holds on to UrlResponseInfo an
xunjieli
2015/09/25 16:16:34
I see. that volatile keyword might help then.
pauljensen
2015/09/25 18:30:16
volatile is insufficient for items larger than sig
mef
2015/09/25 20:08:50
Arghh! Thanks for catching this. Done.
|
| + |
| + 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 = 0; |
| + } |
| + |
| + /** |
| + * 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. |
| + */ |
| + @Override |
| + 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. |
| + */ |
| + @Override |
| + 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. |
| + */ |
| + @Override |
| + public int getHttpStatusCode() { |
| + return mHttpStatusCode; |
| + } |
| + |
| + /** |
| + * Returns the HTTP status text of the status line. For example, if the |
| + * request has a "HTTP/1.1 200 OK" response, this method returns "OK". |
| + * @return the HTTP status text of the status line. |
| + */ |
| + @Override |
| + 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. |
| + */ |
| + @Override |
| + 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. |
| + */ |
| + @Override |
| + public Map<String, List<String>> getAllHeaders() { |
|
xunjieli
2015/09/25 13:54:32
It's sad that even though we have Map.Entry, we st
mef
2015/09/25 15:58:27
Theoretically it will help if they want to headers
xunjieli
2015/09/25 16:16:34
I see. That makes sense. Thanks!
|
| + 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. |
| + */ |
| + @Override |
| + public boolean wasCached() { |
| + return mWasCached; |
| + } |
| + |
| + /** |
| + * Returns the protocol (e.g. "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. |
| + @Override |
| + 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. |
| + */ |
| + @Override |
| + public String getProxyServer() { |
| + return mProxyServer; |
| + } |
| + |
| + /** |
| + * Returns the total amount of data received from network after SSL |
| + * decoding and proxy handling but before gzip and SDCH decompression. |
|
pauljensen
2015/09/25 18:30:17
Though this sentence is very accurate and precise,
mef
2015/09/25 20:08:50
Done.
|
| + * Available on request completion. |
|
pauljensen
2015/09/25 18:30:16
I think we need a further comment about how this v
pauljensen
2015/09/25 18:30:17
I don't think "Available on request completion." i
mef
2015/09/25 20:08:50
In order to reduce magic nature, would it make sen
pauljensen
2015/10/06 12:55:41
So I'd actually like to live in a world where it g
|
| + */ |
| + public long getReceivedBytesCount() { |
| + return mReceivedBytesCount; |
| + } |
| + |
| + @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()); |
| + } |
| + |
| + void updateReceivedBytesCount(long currentReceivedBytesCount) { |
|
xunjieli
2015/09/25 13:54:32
Maybe rename this method as "setReceivedBytesCount
mef
2015/09/25 15:58:27
Sounds good, will do. I also wonder whether it sho
xunjieli
2015/09/25 16:16:34
I will vote for that. But could also be in a separ
mef
2015/09/25 20:08:50
Acknowledged.
mef
2015/09/25 20:53:42
Done.
|
| + mReceivedBytesCount = currentReceivedBytesCount; |
| + } |
| +} |
| +; |