• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 package org.chromium.net.impl;
6 
7 import org.chromium.net.UrlResponseInfo;
8 
9 import java.util.ArrayList;
10 import java.util.Collections;
11 import java.util.List;
12 import java.util.Locale;
13 import java.util.Map;
14 import java.util.TreeMap;
15 import java.util.concurrent.atomic.AtomicLong;
16 
17 /**
18  * Implements the container for basic information about a response. Included in
19  * {@link org.chromium.net.UrlRequest.Callback} callbacks. Each
20  * {@link org.chromium.net.UrlRequest.Callback#onRedirectReceived onRedirectReceived()}
21  * callback gets a different copy of {@code UrlResponseInfo} describing a particular
22  * redirect response.
23  */
24 public final class UrlResponseInfoImpl extends UrlResponseInfo {
25     private final List<String> mResponseInfoUrlChain;
26     private final int mHttpStatusCode;
27     private final String mHttpStatusText;
28     private final boolean mWasCached;
29     private final String mNegotiatedProtocol;
30     private final String mProxyServer;
31     private final AtomicLong mReceivedByteCount;
32     private final HeaderBlockImpl mHeaders;
33 
34     /** Unmodifiable container of response headers or trailers. */
35     public static final class HeaderBlockImpl extends HeaderBlock {
36         private final List<Map.Entry<String, String>> mAllHeadersList;
37         private Map<String, List<String>> mHeadersMap;
38 
HeaderBlockImpl(List<Map.Entry<String, String>> allHeadersList)39         HeaderBlockImpl(List<Map.Entry<String, String>> allHeadersList) {
40             mAllHeadersList = allHeadersList;
41         }
42 
43         @Override
getAsList()44         public List<Map.Entry<String, String>> getAsList() {
45             return mAllHeadersList;
46         }
47 
48         @Override
getAsMap()49         public Map<String, List<String>> getAsMap() {
50             // This is potentially racy...but races will only result in wasted resource.
51             if (mHeadersMap != null) {
52                 return mHeadersMap;
53             }
54             Map<String, List<String>> map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
55             for (Map.Entry<String, String> entry : mAllHeadersList) {
56                 List<String> values = new ArrayList<String>();
57                 if (map.containsKey(entry.getKey())) {
58                     values.addAll(map.get(entry.getKey()));
59                 }
60                 values.add(entry.getValue());
61                 map.put(entry.getKey(), Collections.unmodifiableList(values));
62             }
63             mHeadersMap = Collections.unmodifiableMap(map);
64             return mHeadersMap;
65         }
66     }
67 
68     /**
69      * Creates an implementation of {@link UrlResponseInfo}.
70      *
71      * @param urlChain the URL chain. The first entry is the originally requested URL;
72      *         the following entries are redirects followed.
73      * @param httpStatusCode the HTTP status code.
74      * @param httpStatusText the HTTP status text of the status line.
75      * @param allHeadersList list of response header field and value pairs.
76      * @param wasCached {@code true} if the response came from the cache, {@code false}
77      *         otherwise.
78      * @param negotiatedProtocol the protocol negotiated with the server.
79      * @param proxyServer the proxy server that was used for the request.
80      * @param receivedByteCount minimum count of bytes received from the network to process this
81      *         request.
82      */
UrlResponseInfoImpl( List<String> urlChain, int httpStatusCode, String httpStatusText, List<Map.Entry<String, String>> allHeadersList, boolean wasCached, String negotiatedProtocol, String proxyServer, long receivedByteCount)83     public UrlResponseInfoImpl(
84             List<String> urlChain,
85             int httpStatusCode,
86             String httpStatusText,
87             List<Map.Entry<String, String>> allHeadersList,
88             boolean wasCached,
89             String negotiatedProtocol,
90             String proxyServer,
91             long receivedByteCount) {
92         mResponseInfoUrlChain = Collections.unmodifiableList(urlChain);
93         mHttpStatusCode = httpStatusCode;
94         mHttpStatusText = httpStatusText;
95         mHeaders = new HeaderBlockImpl(Collections.unmodifiableList(allHeadersList));
96         mWasCached = wasCached;
97         mNegotiatedProtocol = negotiatedProtocol;
98         mProxyServer = proxyServer;
99         mReceivedByteCount = new AtomicLong(receivedByteCount);
100     }
101 
102     /** Constructor for backwards compatibility.  See main constructor above for more info. */
103     @Deprecated
UrlResponseInfoImpl( List<String> urlChain, int httpStatusCode, String httpStatusText, List<Map.Entry<String, String>> allHeadersList, boolean wasCached, String negotiatedProtocol, String proxyServer)104     public UrlResponseInfoImpl(
105             List<String> urlChain,
106             int httpStatusCode,
107             String httpStatusText,
108             List<Map.Entry<String, String>> allHeadersList,
109             boolean wasCached,
110             String negotiatedProtocol,
111             String proxyServer) {
112         this(
113                 urlChain,
114                 httpStatusCode,
115                 httpStatusText,
116                 allHeadersList,
117                 wasCached,
118                 negotiatedProtocol,
119                 proxyServer,
120                 0);
121     }
122 
123     @Override
getUrl()124     public String getUrl() {
125         return mResponseInfoUrlChain.get(mResponseInfoUrlChain.size() - 1);
126     }
127 
128     @Override
getUrlChain()129     public List<String> getUrlChain() {
130         return mResponseInfoUrlChain;
131     }
132 
133     @Override
getHttpStatusCode()134     public int getHttpStatusCode() {
135         return mHttpStatusCode;
136     }
137 
138     @Override
getHttpStatusText()139     public String getHttpStatusText() {
140         return mHttpStatusText;
141     }
142 
143     @Override
getAllHeadersAsList()144     public List<Map.Entry<String, String>> getAllHeadersAsList() {
145         return mHeaders.getAsList();
146     }
147 
148     @Override
getAllHeaders()149     public Map<String, List<String>> getAllHeaders() {
150         return mHeaders.getAsMap();
151     }
152 
153     @Override
wasCached()154     public boolean wasCached() {
155         return mWasCached;
156     }
157 
158     @Override
getNegotiatedProtocol()159     public String getNegotiatedProtocol() {
160         return mNegotiatedProtocol;
161     }
162 
163     @Override
getProxyServer()164     public String getProxyServer() {
165         return mProxyServer;
166     }
167 
168     @Override
getReceivedByteCount()169     public long getReceivedByteCount() {
170         return mReceivedByteCount.get();
171     }
172 
173     @Override
toString()174     public String toString() {
175         return String.format(
176                 Locale.ROOT,
177                 "UrlResponseInfo@[%s][%s]: urlChain = %s, "
178                         + "httpStatus = %d %s, headers = %s, wasCached = %b, "
179                         + "negotiatedProtocol = %s, proxyServer= %s, receivedByteCount = %d",
180                 // Prevent asserting on the contents of this string
181                 Integer.toHexString(System.identityHashCode(this)),
182                 getUrl(),
183                 getUrlChain().toString(),
184                 getHttpStatusCode(),
185                 getHttpStatusText(),
186                 getAllHeadersAsList().toString(),
187                 wasCached(),
188                 getNegotiatedProtocol(),
189                 getProxyServer(),
190                 getReceivedByteCount());
191     }
192 
193     /** Sets mReceivedByteCount. Must not be called after request completion or cancellation. */
setReceivedByteCount(long currentReceivedByteCount)194     public void setReceivedByteCount(long currentReceivedByteCount) {
195         mReceivedByteCount.set(currentReceivedByteCount);
196     }
197 }
198