1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.webkit;
18 
19 import java.io.InputStream;
20 import java.io.StringBufferInputStream;
21 import java.util.Map;
22 
23 import android.annotation.SystemApi;
24 
25 /**
26  * Encapsulates a resource response. Applications can return an instance of this
27  * class from {@link WebViewClient#shouldInterceptRequest} to provide a custom
28  * response when the WebView requests a particular resource.
29  */
30 public class WebResourceResponse {
31     private boolean mImmutable;
32     private String mMimeType;
33     private String mEncoding;
34     private int mStatusCode;
35     private String mReasonPhrase;
36     private Map<String, String> mResponseHeaders;
37     private InputStream mInputStream;
38 
39     /**
40      * Constructs a resource response with the given MIME type, encoding, and
41      * input stream. Callers must implement
42      * {@link InputStream#read(byte[]) InputStream.read(byte[])} for the input
43      * stream.
44      *
45      * @param mimeType the resource response's MIME type, for example text/html
46      * @param encoding the resource response's encoding
47      * @param data the input stream that provides the resource response's data. Must not be a
48      *             StringBufferInputStream.
49      */
WebResourceResponse(String mimeType, String encoding, InputStream data)50     public WebResourceResponse(String mimeType, String encoding,
51             InputStream data) {
52         mMimeType = mimeType;
53         mEncoding = encoding;
54         setData(data);
55     }
56 
57     /**
58      * Constructs a resource response with the given parameters. Callers must
59      * implement {@link InputStream#read(byte[]) InputStream.read(byte[])} for
60      * the input stream.
61      *
62      * @param mimeType the resource response's MIME type, for example text/html
63      * @param encoding the resource response's encoding
64      * @param statusCode the status code needs to be in the ranges [100, 299], [400, 599].
65      *                   Causing a redirect by specifying a 3xx code is not supported.
66      * @param reasonPhrase the phrase describing the status code, for example "OK". Must be non-null
67      *                     and not empty.
68      * @param responseHeaders the resource response's headers represented as a mapping of header
69      *                        name -> header value.
70      * @param data the input stream that provides the resource response's data. Must not be a
71      *             StringBufferInputStream.
72      */
WebResourceResponse(String mimeType, String encoding, int statusCode, String reasonPhrase, Map<String, String> responseHeaders, InputStream data)73     public WebResourceResponse(String mimeType, String encoding, int statusCode,
74             String reasonPhrase, Map<String, String> responseHeaders, InputStream data) {
75         this(mimeType, encoding, data);
76         setStatusCodeAndReasonPhrase(statusCode, reasonPhrase);
77         setResponseHeaders(responseHeaders);
78     }
79 
80     /**
81      * Sets the resource response's MIME type, for example &quot;text/html&quot;.
82      *
83      * @param mimeType The resource response's MIME type
84      */
setMimeType(String mimeType)85     public void setMimeType(String mimeType) {
86         checkImmutable();
87         mMimeType = mimeType;
88     }
89 
90     /**
91      * Gets the resource response's MIME type.
92      *
93      * @return The resource response's MIME type
94      */
getMimeType()95     public String getMimeType() {
96         return mMimeType;
97     }
98 
99     /**
100      * Sets the resource response's encoding, for example &quot;UTF-8&quot;. This is used
101      * to decode the data from the input stream.
102      *
103      * @param encoding The resource response's encoding
104      */
setEncoding(String encoding)105     public void setEncoding(String encoding) {
106         checkImmutable();
107         mEncoding = encoding;
108     }
109 
110     /**
111      * Gets the resource response's encoding.
112      *
113      * @return The resource response's encoding
114      */
getEncoding()115     public String getEncoding() {
116         return mEncoding;
117     }
118 
119     /**
120      * Sets the resource response's status code and reason phrase.
121      *
122      * @param statusCode the status code needs to be in the ranges [100, 299], [400, 599].
123      *                   Causing a redirect by specifying a 3xx code is not supported.
124      * @param reasonPhrase the phrase describing the status code, for example "OK". Must be non-null
125      *                     and not empty.
126      */
setStatusCodeAndReasonPhrase(int statusCode, String reasonPhrase)127     public void setStatusCodeAndReasonPhrase(int statusCode, String reasonPhrase) {
128         checkImmutable();
129         if (statusCode < 100)
130             throw new IllegalArgumentException("statusCode can't be less than 100.");
131         if (statusCode > 599)
132             throw new IllegalArgumentException("statusCode can't be greater than 599.");
133         if (statusCode > 299 && statusCode < 400)
134             throw new IllegalArgumentException("statusCode can't be in the [300, 399] range.");
135         if (reasonPhrase == null)
136             throw new IllegalArgumentException("reasonPhrase can't be null.");
137         if (reasonPhrase.trim().isEmpty())
138             throw new IllegalArgumentException("reasonPhrase can't be empty.");
139         for (int i = 0; i < reasonPhrase.length(); i++) {
140             int c = reasonPhrase.charAt(i);
141             if (c > 0x7F) {
142                 throw new IllegalArgumentException(
143                         "reasonPhrase can't contain non-ASCII characters.");
144             }
145         }
146         mStatusCode = statusCode;
147         mReasonPhrase = reasonPhrase;
148     }
149 
150     /**
151      * Gets the resource response's status code.
152      *
153      * @return The resource response's status code.
154      */
getStatusCode()155     public int getStatusCode() {
156         return mStatusCode;
157     }
158 
159     /**
160      * Gets the description of the resource response's status code.
161      *
162      * @return The description of the resource response's status code.
163      */
getReasonPhrase()164     public String getReasonPhrase() {
165         return mReasonPhrase;
166     }
167 
168     /**
169      * Sets the headers for the resource response.
170      *
171      * @param headers Mapping of header name -> header value.
172      */
setResponseHeaders(Map<String, String> headers)173     public void setResponseHeaders(Map<String, String> headers) {
174         checkImmutable();
175         mResponseHeaders = headers;
176     }
177 
178     /**
179      * Gets the headers for the resource response.
180      *
181      * @return The headers for the resource response.
182      */
getResponseHeaders()183     public Map<String, String> getResponseHeaders() {
184         return mResponseHeaders;
185     }
186 
187     /**
188      * Sets the input stream that provides the resource response's data. Callers
189      * must implement {@link InputStream#read(byte[]) InputStream.read(byte[])}.
190      *
191      * @param data the input stream that provides the resource response's data. Must not be a
192      *             StringBufferInputStream.
193      */
setData(InputStream data)194     public void setData(InputStream data) {
195         checkImmutable();
196         // If data is (or is a subclass of) StringBufferInputStream
197         if (data != null && StringBufferInputStream.class.isAssignableFrom(data.getClass())) {
198             throw new IllegalArgumentException("StringBufferInputStream is deprecated and must " +
199                 "not be passed to a WebResourceResponse");
200         }
201         mInputStream = data;
202     }
203 
204     /**
205      * Gets the input stream that provides the resource response's data.
206      *
207      * @return The input stream that provides the resource response's data
208      */
getData()209     public InputStream getData() {
210         return mInputStream;
211     }
212 
213     /**
214      * The internal version of the constructor that doesn't perform arguments checks.
215      * @hide
216      */
217     @SystemApi
WebResourceResponse(boolean immutable, String mimeType, String encoding, int statusCode, String reasonPhrase, Map<String, String> responseHeaders, InputStream data)218     public WebResourceResponse(boolean immutable, String mimeType, String encoding, int statusCode,
219             String reasonPhrase, Map<String, String> responseHeaders, InputStream data) {
220         mImmutable = immutable;
221         mMimeType = mimeType;
222         mEncoding = encoding;
223         mStatusCode = statusCode;
224         mReasonPhrase = reasonPhrase;
225         mResponseHeaders = responseHeaders;
226         mInputStream = data;
227     }
228 
checkImmutable()229     private void checkImmutable() {
230         if (mImmutable)
231             throw new IllegalStateException("This WebResourceResponse instance is immutable");
232     }
233 }
234