WebRequest.java (8154B)
1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- 2 * vim: ts=4 sw=4 expandtab: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 package org.mozilla.geckoview; 8 9 import androidx.annotation.AnyThread; 10 import androidx.annotation.IntDef; 11 import androidx.annotation.NonNull; 12 import androidx.annotation.Nullable; 13 import java.lang.annotation.Retention; 14 import java.lang.annotation.RetentionPolicy; 15 import java.nio.ByteBuffer; 16 import java.nio.CharBuffer; 17 import java.nio.charset.Charset; 18 import org.mozilla.gecko.annotation.WrapForJNI; 19 20 /** 21 * WebRequest represents an HTTP[S] request. The typical pattern is to create instances of this 22 * class via {@link WebRequest.Builder}, and fetch responses via {@link 23 * GeckoWebExecutor#fetch(WebRequest)}. 24 */ 25 @WrapForJNI 26 @AnyThread 27 public class WebRequest extends WebMessage { 28 /** The HTTP method for the request. Defaults to "GET". */ 29 public final @NonNull String method; 30 31 /** The body of the request. Must be a directly-allocated ByteBuffer. May be null. */ 32 public final @Nullable ByteBuffer body; 33 34 /** 35 * The cache mode for the request. See {@link #CACHE_MODE_DEFAULT}. These modes match those from 36 * the DOM Fetch API. 37 * 38 * @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Request/cache">DOM Fetch API 39 * cache modes</a> 40 */ 41 public final @CacheMode int cacheMode; 42 43 /** 44 * If true, do not use newer protocol features that might have interop problems on the Internet. 45 * Intended only for use with critical infrastructure. 46 */ 47 public final boolean beConservative; 48 49 /** The value of the Referer header for this request. */ 50 public final @Nullable String referrer; 51 52 /** The value of the origin of this request. */ 53 public final @Nullable String origin; 54 55 /** Cache mode definitions for web requests. */ 56 @Retention(RetentionPolicy.SOURCE) 57 @IntDef({ 58 CACHE_MODE_DEFAULT, 59 CACHE_MODE_NO_STORE, 60 CACHE_MODE_RELOAD, 61 CACHE_MODE_NO_CACHE, 62 CACHE_MODE_FORCE_CACHE, 63 CACHE_MODE_ONLY_IF_CACHED 64 }) 65 public @interface CacheMode {}; 66 67 /** Default cache mode. Normal caching rules apply. */ 68 public static final int CACHE_MODE_DEFAULT = 1; 69 70 /** 71 * The response will be fetched from the server without looking in the cache, and will not update 72 * the cache with the downloaded response. 73 */ 74 public static final int CACHE_MODE_NO_STORE = 2; 75 76 /** 77 * The response will be fetched from the server without looking in the cache. The cache will be 78 * updated with the downloaded response. 79 */ 80 public static final int CACHE_MODE_RELOAD = 3; 81 82 /** Forces a conditional request to the server if there is a cache match. */ 83 public static final int CACHE_MODE_NO_CACHE = 4; 84 85 /** 86 * If a response is found in the cache, it will be returned, whether it's fresh or not. If there 87 * is no match, a normal request will be made and the cache will be updated with the downloaded 88 * response. 89 */ 90 public static final int CACHE_MODE_FORCE_CACHE = 5; 91 92 /** 93 * If a response is found in the cache, it will be returned, whether it's fresh or not. If there 94 * is no match from the cache, 504 Gateway Timeout will be returned. 95 */ 96 public static final int CACHE_MODE_ONLY_IF_CACHED = 6; 97 98 /* package */ static final int CACHE_MODE_FIRST = CACHE_MODE_DEFAULT; 99 /* package */ static final int CACHE_MODE_LAST = CACHE_MODE_ONLY_IF_CACHED; 100 101 /** 102 * Constructs a WebRequest with the specified URI. 103 * 104 * @param uri A URI String, e.g. https://mozilla.org 105 */ 106 public WebRequest(final @NonNull String uri) { 107 this(new Builder(uri)); 108 } 109 110 /** Constructs a new WebRequest from a {@link WebRequest.Builder}. */ 111 /* package */ WebRequest(final @NonNull Builder builder) { 112 super(builder); 113 method = builder.mMethod; 114 cacheMode = builder.mCacheMode; 115 referrer = builder.mReferrer; 116 beConservative = builder.mBeConservative; 117 origin = builder.mOrigin; 118 119 if (builder.mBody != null) { 120 body = builder.mBody.asReadOnlyBuffer(); 121 } else { 122 body = null; 123 } 124 } 125 126 /** Builder offers a convenient way for constructing {@link WebRequest} instances. */ 127 @WrapForJNI 128 @AnyThread 129 public static class Builder extends WebMessage.Builder { 130 /* package */ String mMethod = "GET"; 131 /* package */ int mCacheMode = CACHE_MODE_DEFAULT; 132 /* package */ String mReferrer; 133 /* package */ boolean mBeConservative; 134 /* package */ String mOrigin; 135 136 /** 137 * Construct a Builder instance with the specified URI. 138 * 139 * @param uri A URI String. 140 */ 141 public Builder(final @NonNull String uri) { 142 super(uri); 143 } 144 145 @Override 146 public @NonNull Builder uri(final @NonNull String uri) { 147 super.uri(uri); 148 return this; 149 } 150 151 @Override 152 public @NonNull Builder header(final @NonNull String key, final @NonNull String value) { 153 super.header(key, value); 154 return this; 155 } 156 157 @Override 158 public @NonNull Builder addHeader(final @NonNull String key, final @NonNull String value) { 159 super.addHeader(key, value); 160 return this; 161 } 162 163 /** 164 * Set the body. 165 * 166 * @param buffer A {@link ByteBuffer} with the data. Must be allocated directly via {@link 167 * ByteBuffer#allocateDirect(int)}. 168 * @return This Builder instance. 169 */ 170 public @NonNull Builder body(final @Nullable ByteBuffer buffer) { 171 if (buffer != null && !buffer.isDirect()) { 172 throw new IllegalArgumentException("body must be directly allocated"); 173 } 174 mBody = buffer; 175 return this; 176 } 177 178 /** 179 * Set the body. 180 * 181 * @param bodyString A {@link String} with the data. 182 * @return This Builder instance. 183 */ 184 public @NonNull Builder body(final @Nullable String bodyString) { 185 if (bodyString == null) { 186 mBody = null; 187 return this; 188 } 189 final CharBuffer chars = CharBuffer.wrap(bodyString); 190 final ByteBuffer buffer = ByteBuffer.allocateDirect(bodyString.length()); 191 Charset.forName("UTF-8").newEncoder().encode(chars, buffer, true); 192 193 mBody = buffer; 194 return this; 195 } 196 197 /** 198 * Set the HTTP method. 199 * 200 * @param method The HTTP method String. 201 * @return This Builder instance. 202 */ 203 public @NonNull Builder method(final @NonNull String method) { 204 mMethod = method; 205 return this; 206 } 207 208 /** 209 * Set the cache mode. 210 * 211 * @param mode One of the {@link #CACHE_MODE_DEFAULT CACHE_*} flags. 212 * @return This Builder instance. 213 */ 214 public @NonNull Builder cacheMode(final @CacheMode int mode) { 215 if (mode < CACHE_MODE_FIRST || mode > CACHE_MODE_LAST) { 216 throw new IllegalArgumentException("Unknown cache mode"); 217 } 218 mCacheMode = mode; 219 return this; 220 } 221 222 /** 223 * Set the HTTP Referer header. 224 * 225 * @param referrer A URI String 226 * @return This Builder instance. 227 */ 228 public @NonNull Builder referrer(final @Nullable String referrer) { 229 mReferrer = referrer; 230 return this; 231 } 232 233 /** 234 * Set the beConservative property. 235 * 236 * @param beConservative If true, do not use newer protocol features that might have interop 237 * problems on the Internet. Intended only for use with critical infrastructure. 238 * @return This Builder instance. 239 */ 240 public @NonNull Builder beConservative(final boolean beConservative) { 241 mBeConservative = beConservative; 242 return this; 243 } 244 245 /** 246 * Set the origin URI. 247 * 248 * @param origin A URI String 249 * @return This Builder instance. 250 */ 251 public @NonNull Builder origin(final @Nullable String origin) { 252 mOrigin = origin; 253 return this; 254 } 255 256 /** 257 * @return A {@link WebRequest} constructed with the values from this Builder instance. 258 */ 259 public @NonNull WebRequest build() { 260 if (mUri == null) { 261 throw new IllegalStateException("Must set URI"); 262 } 263 return new WebRequest(this); 264 } 265 } 266 }