1 /*
2  * Copyright 2024 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 androidx.webkit;
18 
19 import org.jspecify.annotations.NonNull;
20 
21 import java.util.ArrayList;
22 import java.util.List;
23 
24 /**
25  * The No-Vary-Search header specifies a set of rules that define how a URL's
26  * query parameters will affect cache matching. These rules dictate whether
27  * the same URL with different URL parameters should be saved as separate
28  * browser cache entries.
29  * <p>
30  * See
31  * <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/No-Vary-Search">Doc here</a>
32  * to learn more about No-Vary-Search.
33  */
34 @Profile.ExperimentalUrlPrefetch
35 public class NoVarySearchHeader {
36 
37     /**
38      * If {@code true} this indicates that differences in the order of
39      * parameters between otherwise identical URLs will cause them to
40      * be cached as separate entries.
41      * <p>
42      * However, differences in the parameters present will cause them to
43      * be cached separately regardless of this flag's value.
44      * <p>
45      * To ignore any differences in parameters present for caching
46      * see {@link #ignoreDifferencesInParameters}
47      * and {@link #ignoredQueryParameters}. {@code false} otherwise.
48      */
49     public final boolean varyOnKeyOrder;
50 
51     /**
52      * A {@code true} to indicate the differences in parameters present
53      * between otherwise identical URLs will not cause them to be cached as
54      * separate entries. {@code false} otherwise.
55      */
56     public final boolean ignoreDifferencesInParameters;
57 
58     /**
59      * A {@link List} of parameters that if present,
60      * will not cause otherwise identical URLs to be cached as separate
61      * entries. Any parameters present in the URLs that are not included in
62      * this list will affect cache matching.
63      * <p>
64      * This list is irrelevant and not used if
65      * {@link #ignoreDifferencesInParameters} is {@code true}.
66      */
67     public final @NonNull List<String> ignoredQueryParameters;
68 
69     /**
70      * A {@link List} of parameters that if present, will cause otherwise
71      * identical URLs to be cached as separate entries. Any parameters present
72      * in the URLs that are not included in this list will not affect cache
73      * matching.
74      * <p>
75      * This list is irrelevant and not used if
76      * {@link #ignoreDifferencesInParameters} is {@code false}.
77      */
78     public final @NonNull List<String> consideredQueryParameters;
79 
80     /**
81      * Private constructor to prevent constructing invalid No-Vary-Search
82      * header. Static methods should be used instead e.g. {@link #neverVaryHeader}.
83      */
NoVarySearchHeader(boolean varyOnKeyOrder, boolean ignoreDifferencesInParameters, @NonNull List<String> ignoredQueryParameters, @NonNull List<String> consideredQueryParameters)84     private NoVarySearchHeader(boolean varyOnKeyOrder,
85             boolean ignoreDifferencesInParameters,
86             @NonNull List<String> ignoredQueryParameters,
87             @NonNull List<String> consideredQueryParameters) {
88         this.varyOnKeyOrder = varyOnKeyOrder;
89         this.ignoreDifferencesInParameters = ignoreDifferencesInParameters;
90         this.ignoredQueryParameters = ignoredQueryParameters;
91         this.consideredQueryParameters = consideredQueryParameters;
92     }
93 
94 
95     /**
96      * Returns No-Vary-Search header that doesn't consider any differences in
97      * query parameters (i.e. presence or ordering) between otherwise
98      * identical URLs in cache matching.
99      */
100     @Profile.ExperimentalUrlPrefetch
neverVaryHeader()101     public static @NonNull NoVarySearchHeader neverVaryHeader() {
102         return new NoVarySearchHeader(false, true, new ArrayList<>(), new ArrayList<>());
103     }
104 
105     /**
106      * Returns No-Vary-Search header that considers all differences in
107      * query parameters (i.e. presence and ordering) between otherwise
108      * identical URLs in cache matching.
109      */
110     @Profile.ExperimentalUrlPrefetch
alwaysVaryHeader()111     public static @NonNull NoVarySearchHeader alwaysVaryHeader() {
112         return new NoVarySearchHeader(true, false, new ArrayList<>(), new ArrayList<>());
113     }
114 
115     /**
116      * Returns No-Vary-Search header that doesn't consider differences in
117      * in query parameters present between otherwise identical URLs
118      * in cache matching with the exception of the ones provided
119      * in {@link #consideredQueryParameters}.
120      * <p>
121      *
122      * @param varyOnOrdering            true if the ordering of query parameters should be
123      *                                  considered in cache matching, false otherwise.
124      * @param consideredQueryParameters the query parameters to consider
125      *                                  in cache matching.
126      */
127     @Profile.ExperimentalUrlPrefetch
neverVaryExcept( boolean varyOnOrdering, @NonNull List<String> consideredQueryParameters)128     public static @NonNull NoVarySearchHeader neverVaryExcept(
129             boolean varyOnOrdering,
130             @NonNull List<String> consideredQueryParameters) {
131         return new NoVarySearchHeader(varyOnOrdering, true, new ArrayList<>(),
132                 consideredQueryParameters);
133     }
134 
135     /**
136      * Returns No-Vary-Search header that considers differences in
137      * in query parameters present between otherwise identical URLs
138      * in cache matching with the exception of the ones provided
139      * in {@link #ignoredQueryParameters}.
140      * <p>
141      *
142      * @param varyOnOrdering         true if the ordering of query parameters should be
143      *                               considered in cache matching, false otherwise.
144      * @param ignoredQueryParameters the query parameters to ignore
145      *                               in cache matching.
146      */
147     @Profile.ExperimentalUrlPrefetch
varyExcept( boolean varyOnOrdering, @NonNull List<String> ignoredQueryParameters)148     public static @NonNull NoVarySearchHeader varyExcept(
149             boolean varyOnOrdering,
150             @NonNull List<String> ignoredQueryParameters) {
151         return new NoVarySearchHeader(varyOnOrdering, false,
152                 ignoredQueryParameters, new ArrayList<>());
153     }
154 
155 }
156