blob: 4d3dee4265953e1ecd16eaa4201e065ebadf79c7 [file] [log] [blame]
John Reckfb3017f2010-10-26 19:01:24 -07001/*
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 */
Michael Kolb8233fac2010-10-26 16:08:53 -070016
Bijan Amirzada41242f22014-03-21 12:12:18 -070017package com.android.browser;
John Reckfb3017f2010-10-26 19:01:24 -070018
Michael Kolb8233fac2010-10-26 16:08:53 -070019import android.net.Uri;
20import android.util.Patterns;
21import android.webkit.URLUtil;
22
John Reckfb3017f2010-10-26 19:01:24 -070023import java.util.regex.Matcher;
24import java.util.regex.Pattern;
Vivek Sekharcc4bc5e2014-05-13 12:46:37 -070025import java.util.HashSet;
26import java.util.Arrays;
Tarun Nainani8eb00912014-07-17 12:28:32 -070027import java.net.URI;
John Reckfb3017f2010-10-26 19:01:24 -070028
Michael Kolb8233fac2010-10-26 16:08:53 -070029/**
30 * Utility methods for Url manipulation
31 */
John Reckfb3017f2010-10-26 19:01:24 -070032public class UrlUtils {
Vivek Sekharcc4bc5e2014-05-13 12:46:37 -070033 public static final String[] DOWNLOADABLE_SCHEMES_VALUES = new String[]
34 { "data", "filesystem", "http", "https" };
35
36 private static final HashSet<String> DOWNLOADABLE_SCHEMES =
37 new HashSet<String>(Arrays.asList(DOWNLOADABLE_SCHEMES_VALUES));
John Reckfb3017f2010-10-26 19:01:24 -070038
Tarun Nainani8eb00912014-07-17 12:28:32 -070039 // Schemes for which the LIVE_MENU items defined in res/menu/browser.xml
40 // should be enabled
41 public static final String[] LIVE_SCHEMES_VALUES = new String[]
42 { "http", "https" };
43
44 private static final HashSet<String> LIVE_SCHEMES =
45 new HashSet<String>(Arrays.asList(LIVE_SCHEMES_VALUES));
46
Michael Kolb8233fac2010-10-26 16:08:53 -070047 static final Pattern ACCEPTED_URI_SCHEMA = Pattern.compile(
48 "(?i)" + // switch on case insensitive matching
49 "(" + // begin group for schema
Axesh R. Ajmera6fc73692015-08-11 16:32:10 -070050 "(?:http|https|file|chrome):\\/\\/" +
Patrick Scottb92bbb42011-01-05 11:38:58 -050051 "|(?:inline|data|about|javascript):" +
Michael Kolb8233fac2010-10-26 16:08:53 -070052 ")" +
53 "(.*)" );
54
55 // Google search
56 private final static String QUICKSEARCH_G = "http://www.google.com/m?q=%s";
57 private final static String QUERY_PLACE_HOLDER = "%s";
58
John Reckfe5b94d2011-09-06 10:21:29 -070059 // Regular expression to strip http:// and optionally
John Reck434e9f82011-08-10 18:16:52 -070060 // the trailing slash
61 private static final Pattern STRIP_URL_PATTERN =
John Reckfe5b94d2011-09-06 10:21:29 -070062 Pattern.compile("^http://(.*?)/?$");
John Reckfb3017f2010-10-26 19:01:24 -070063
64 private UrlUtils() { /* cannot be instantiated */ }
65
66 /**
John Reckfe5b94d2011-09-06 10:21:29 -070067 * Strips the provided url of preceding "http://" and any trailing "/". Does not
John Reckfb3017f2010-10-26 19:01:24 -070068 * strip "https://". If the provided string cannot be stripped, the original string
69 * is returned.
70 *
71 * TODO: Put this in TextUtils to be used by other packages doing something similar.
72 *
73 * @param url a url to strip, like "http://www.google.com/"
John Reckfe5b94d2011-09-06 10:21:29 -070074 * @return a stripped url like "www.google.com", or the original string if it could
John Reckfb3017f2010-10-26 19:01:24 -070075 * not be stripped
76 */
John Reck2cb9dc22011-05-11 16:12:27 -070077 public static String stripUrl(String url) {
John Reckfb3017f2010-10-26 19:01:24 -070078 if (url == null) return null;
79 Matcher m = STRIP_URL_PATTERN.matcher(url);
John Reck434e9f82011-08-10 18:16:52 -070080 if (m.matches()) {
81 return m.group(1);
John Reckfb3017f2010-10-26 19:01:24 -070082 } else {
83 return url;
84 }
85 }
Michael Kolb8233fac2010-10-26 16:08:53 -070086
87 protected static String smartUrlFilter(Uri inUri) {
88 if (inUri != null) {
89 return smartUrlFilter(inUri.toString());
90 }
91 return null;
92 }
93
94 /**
95 * Attempts to determine whether user input is a URL or search
96 * terms. Anything with a space is passed to search.
97 *
98 * Converts to lowercase any mistakenly uppercased schema (i.e.,
99 * "Http://" converts to "http://"
100 *
101 * @return Original or modified URL
102 *
103 */
John Reck961d35d2011-06-23 09:45:54 -0700104 public static String smartUrlFilter(String url) {
John Reck71e51422011-07-01 16:49:28 -0700105 return smartUrlFilter(url, true);
106 }
Michael Kolb8233fac2010-10-26 16:08:53 -0700107
Vivek Sekharcc4bc5e2014-05-13 12:46:37 -0700108 public static boolean isDownloadableScheme(Uri uri) {
109 return DOWNLOADABLE_SCHEMES.contains(uri.getScheme());
110 }
111
112 public static boolean isDownloadableScheme(String uri) {
113 try {
Tarun Nainani8eb00912014-07-17 12:28:32 -0700114 URI uriObj = new URI(uri);
115 return isDownloadableScheme(Uri.parse(uriObj.toString()));
116 } catch (Exception e) {
117 return false;
118 }
119 }
120
121 public static boolean isLiveScheme(Uri uri) {
122 return LIVE_SCHEMES.contains(uri.getScheme());
123 }
124
125 public static boolean isLiveScheme(String uri) {
126 try {
127 return isLiveScheme(Uri.parse(uri));
Vivek Sekharcc4bc5e2014-05-13 12:46:37 -0700128 } catch (Exception e) {
129 return false;
130 }
131 }
132
John Reck71e51422011-07-01 16:49:28 -0700133 /**
134 * Attempts to determine whether user input is a URL or search
135 * terms. Anything with a space is passed to search if canBeSearch is true.
136 *
137 * Converts to lowercase any mistakenly uppercased schema (i.e.,
138 * "Http://" converts to "http://"
139 *
140 * @param canBeSearch If true, will return a search url if it isn't a valid
141 * URL. If false, invalid URLs will return null
142 * @return Original or modified URL
143 *
144 */
145 public static String smartUrlFilter(String url, boolean canBeSearch) {
Michael Kolb8233fac2010-10-26 16:08:53 -0700146 String inUrl = url.trim();
147 boolean hasSpace = inUrl.indexOf(' ') != -1;
148
149 Matcher matcher = ACCEPTED_URI_SCHEMA.matcher(inUrl);
150 if (matcher.matches()) {
151 // force scheme to lowercase
152 String scheme = matcher.group(1);
153 String lcScheme = scheme.toLowerCase();
154 if (!lcScheme.equals(scheme)) {
155 inUrl = lcScheme + matcher.group(2);
156 }
John Reck71e51422011-07-01 16:49:28 -0700157 if (hasSpace && Patterns.WEB_URL.matcher(inUrl).matches()) {
Michael Kolb8233fac2010-10-26 16:08:53 -0700158 inUrl = inUrl.replace(" ", "%20");
159 }
160 return inUrl;
161 }
162 if (!hasSpace) {
163 if (Patterns.WEB_URL.matcher(inUrl).matches()) {
164 return URLUtil.guessUrl(inUrl);
165 }
166 }
John Reck71e51422011-07-01 16:49:28 -0700167 if (canBeSearch) {
168 return URLUtil.composeSearchUrl(inUrl,
169 QUICKSEARCH_G, QUERY_PLACE_HOLDER);
170 }
171 return null;
Michael Kolb8233fac2010-10-26 16:08:53 -0700172 }
173
kaiyiz6e5b3e02013-08-19 20:02:01 +0800174 public static String fixUrl(String inUrl) {
Michael Kolb8233fac2010-10-26 16:08:53 -0700175 // FIXME: Converting the url to lower case
176 // duplicates functionality in smartUrlFilter().
177 // However, changing all current callers of fixUrl to
178 // call smartUrlFilter in addition may have unwanted
179 // consequences, and is deferred for now.
180 int colon = inUrl.indexOf(':');
181 boolean allLower = true;
182 for (int index = 0; index < colon; index++) {
183 char ch = inUrl.charAt(index);
184 if (!Character.isLetter(ch)) {
185 break;
186 }
187 allLower &= Character.isLowerCase(ch);
188 if (index == colon - 1 && !allLower) {
189 inUrl = inUrl.substring(0, colon).toLowerCase()
190 + inUrl.substring(colon);
191 }
192 }
193 if (inUrl.startsWith("http://") || inUrl.startsWith("https://"))
194 return inUrl;
195 if (inUrl.startsWith("http:") ||
196 inUrl.startsWith("https:")) {
197 if (inUrl.startsWith("http:/") || inUrl.startsWith("https:/")) {
198 inUrl = inUrl.replaceFirst("/", "//");
199 } else inUrl = inUrl.replaceFirst(":", "://");
200 }
201 return inUrl;
202 }
203
John Reck324d4402011-01-11 16:56:42 -0800204 // Returns the filtered URL. Cannot return null, but can return an empty string
205 /* package */ static String filteredUrl(String inUrl) {
206 if (inUrl == null) {
207 return "";
208 }
Axesh R. Ajmera6fc73692015-08-11 16:32:10 -0700209 if (inUrl.startsWith("content:")
210 || inUrl.startsWith("browser:")) {
John Reck324d4402011-01-11 16:56:42 -0800211 return "";
212 }
213 return inUrl;
214 }
215
John Reckfb3017f2010-10-26 19:01:24 -0700216}