Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(521)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/UrlUtilities.java

Issue 1059413004: Add a validator for intent:// URLs. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Allow Extras; require that standard keys appear only once; use Matchers; more test cases. Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.chrome.browser; 5 package org.chromium.chrome.browser;
6 6
7 import android.text.TextUtils; 7 import android.text.TextUtils;
8 8
9 import org.chromium.base.CollectionUtil; 9 import org.chromium.base.CollectionUtil;
10 10
11 import java.net.URI; 11 import java.net.URI;
12 import java.net.URISyntaxException; 12 import java.net.URISyntaxException;
13 import java.util.HashSet; 13 import java.util.HashSet;
14 import java.util.regex.Matcher;
15 import java.util.regex.Pattern;
14 16
15 /** 17 /**
16 * Utilities for working with URIs (and URLs). These methods may be used in secu rity-sensitive 18 * Utilities for working with URIs (and URLs). These methods may be used in secu rity-sensitive
17 * contexts (after all, origins are the security boundary on the web), and so th e correctness bar 19 * contexts (after all, origins are the security boundary on the web), and so th e correctness bar
18 * must be high. 20 * must be high.
19 */ 21 */
20 public class UrlUtilities { 22 public class UrlUtilities {
21 /** 23 /**
22 * URI schemes that ContentView can handle. 24 * URI schemes that ContentView can handle.
23 */ 25 */
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 * no subdomains, from the given URI. Returns an empty string if the URI is invalid, has no host 202 * no subdomains, from the given URI. Returns an empty string if the URI is invalid, has no host
201 * (e.g. a file: URI), has multiple trailing dots, is an IP address, has onl y one subcomponent 203 * (e.g. a file: URI), has multiple trailing dots, is an IP address, has onl y one subcomponent
202 * (i.e. no dots other than leading/trailing ones), or is itself a recognize d registry 204 * (i.e. no dots other than leading/trailing ones), or is itself a recognize d registry
203 * identifier. 205 * identifier.
204 */ 206 */
205 public static String getDomainAndRegistry(String uri, boolean includePrivate Registries) { 207 public static String getDomainAndRegistry(String uri, boolean includePrivate Registries) {
206 if (TextUtils.isEmpty(uri)) return uri; 208 if (TextUtils.isEmpty(uri)) return uri;
207 return nativeGetDomainAndRegistry(uri, includePrivateRegistries); 209 return nativeGetDomainAndRegistry(uri, includePrivateRegistries);
208 } 210 }
209 211
212 // Patterns used in validateIntentUrl.
213 private static final Pattern DNS_HOSTNAME_PATTERN =
214 Pattern.compile("^[\\w\\.-]*$");
215 private static final Pattern JAVA_PACKAGE_NAME_PATTERN =
216 Pattern.compile("^[\\w\\.-]*$");
217 private static final Pattern URL_SCHEME_PATTERN =
218 Pattern.compile("^[a-zA-Z]+$");
219
220 /**
221 * @param url An Android intent:// URL to validate.
222 *
223 * @throws URISyntaxException if url is not a valid Android intent://
224 * URL, as specified at
225 * https://developer.chrome.com/multidevice/android/intents#syntax.
226 */
227 public static boolean validateIntentUrl(String url) {
228 URI parsed = null;
229 try {
230 parsed = new URI(url);
231 } catch (URISyntaxException e) {
232 return false;
233 }
234
235 if (!parsed.getScheme().equals("intent")) return false;
236
237 Matcher m = DNS_HOSTNAME_PATTERN.matcher(parsed.getHost());
238 if (!m.matches()) return false;
239
240 if (!parsed.getPath().isEmpty() && !parsed.getPath().equals("/")) {
241 return false;
242 }
243
244 String[] parts = parsed.getFragment().split(";");
245 if (parts.length < 3
246 || !parts[0].equals("Intent")
247 || !parts[parts.length - 1].equals("end")) {
248 return false;
249 }
250
251 boolean seenPackage = false;
252 boolean seenAction = false;
253 boolean seenCategory = false;
254 boolean seenComponent = false;
255 boolean seenScheme = false;
256
257 for (int i = 1; i < parts.length - 1; ++i) {
258 // This is OK *only* because no valid package, action, category,
259 // component, or scheme contains "=".
260 String[] pair = parts[i].split("=");
261 if (2 != pair.length) return false;
Yaron 2015/04/24 20:38:17 I think this breaks "extras". see below
262
263 m = JAVA_PACKAGE_NAME_PATTERN.matcher(pair[1]);
264 if (pair[0].equals("package")) {
265 if (seenPackage || !m.matches()) return false;
266 seenPackage = true;
267 } else if (pair[0].equals("action")) {
268 if (seenAction || !m.matches()) return false;
269 seenAction = true;
270 } else if (pair[0].equals("category")) {
271 if (seenCategory || !m.matches()) return false;
272 seenCategory = true;
273 } else if (pair[0].equals("component")) {
274 if (seenComponent || !m.matches()) return false;
275 seenComponent = true;
276 } else if (pair[0].equals("scheme")) {
277 if (seenScheme) return false;
278 Matcher schemeMatcher = URL_SCHEME_PATTERN.matcher(pair[1]);
279 if (!schemeMatcher.matches()) return false;
280 seenScheme = true;
281 } else {
282 // Assume we are seeing an Intent Extra. Require that the
283 // key be a valid Java package name, and that the value also
284 // fit that rather restrictive pattern. The latter
285 // requirement may have to be relaxed in the future, but
286 // beware: Here Lurks Madness.
Yaron 2015/04/24 20:38:17 I guess this is a deliberate "fail closed" but I w
287 Matcher keyMatcher = JAVA_PACKAGE_NAME_PATTERN.matcher(pair[0]);
288 if (!m.matches() || !keyMatcher.matches()) return false;
289 }
290 }
291
292 return true;
293 }
294
210 private static native boolean nativeSameDomainOrHost(String primaryUrl, Stri ng secondaryUrl, 295 private static native boolean nativeSameDomainOrHost(String primaryUrl, Stri ng secondaryUrl,
211 boolean includePrivateRegistries); 296 boolean includePrivateRegistries);
212 private static native String nativeGetDomainAndRegistry(String url, 297 private static native String nativeGetDomainAndRegistry(String url,
213 boolean includePrivateRegistries); 298 boolean includePrivateRegistries);
214 public static native boolean nativeIsGoogleSearchUrl(String url); 299 public static native boolean nativeIsGoogleSearchUrl(String url);
215 public static native boolean nativeIsGoogleHomePageUrl(String url); 300 public static native boolean nativeIsGoogleHomePageUrl(String url);
216 private static native String nativeFixupUrl(String url, String desiredTld); 301 private static native String nativeFixupUrl(String url, String desiredTld);
217 } 302 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698