John Reck | fb3017f | 2010-10-26 19:01:24 -0700 | [diff] [blame] | 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 | */ |
Michael Kolb | 8233fac | 2010-10-26 16:08:53 -0700 | [diff] [blame] | 16 | |
Bijan Amirzada | 41242f2 | 2014-03-21 12:12:18 -0700 | [diff] [blame] | 17 | package com.android.browser; |
John Reck | fb3017f | 2010-10-26 19:01:24 -0700 | [diff] [blame] | 18 | |
Michael Kolb | 8233fac | 2010-10-26 16:08:53 -0700 | [diff] [blame] | 19 | import android.net.Uri; |
Sagar Dhawan | ef06f56 | 2015-09-07 15:23:22 +0200 | [diff] [blame] | 20 | import android.text.TextUtils; |
Michael Kolb | 8233fac | 2010-10-26 16:08:53 -0700 | [diff] [blame] | 21 | import android.util.Patterns; |
| 22 | import android.webkit.URLUtil; |
| 23 | |
Sagar Dhawan | ef06f56 | 2015-09-07 15:23:22 +0200 | [diff] [blame] | 24 | import org.codeaurora.swe.util.SWEUrlUtils; |
| 25 | |
John Reck | fb3017f | 2010-10-26 19:01:24 -0700 | [diff] [blame] | 26 | import java.util.regex.Matcher; |
| 27 | import java.util.regex.Pattern; |
Vivek Sekhar | cc4bc5e | 2014-05-13 12:46:37 -0700 | [diff] [blame] | 28 | import java.util.HashSet; |
| 29 | import java.util.Arrays; |
Tarun Nainani | 8eb0091 | 2014-07-17 12:28:32 -0700 | [diff] [blame] | 30 | import java.net.URI; |
John Reck | fb3017f | 2010-10-26 19:01:24 -0700 | [diff] [blame] | 31 | |
Michael Kolb | 8233fac | 2010-10-26 16:08:53 -0700 | [diff] [blame] | 32 | /** |
| 33 | * Utility methods for Url manipulation |
| 34 | */ |
John Reck | fb3017f | 2010-10-26 19:01:24 -0700 | [diff] [blame] | 35 | public class UrlUtils { |
Sagar Dhawan | ef06f56 | 2015-09-07 15:23:22 +0200 | [diff] [blame] | 36 | // Urls defined by the browser should not be "fixedup" via the engine |
| 37 | // Urls are only handled by the browser |
| 38 | private static final String BROWSER_URLS[] = { |
| 39 | "about:debug", |
| 40 | }; |
Vivek Sekhar | cc4bc5e | 2014-05-13 12:46:37 -0700 | [diff] [blame] | 41 | public static final String[] DOWNLOADABLE_SCHEMES_VALUES = new String[] |
| 42 | { "data", "filesystem", "http", "https" }; |
| 43 | |
| 44 | private static final HashSet<String> DOWNLOADABLE_SCHEMES = |
| 45 | new HashSet<String>(Arrays.asList(DOWNLOADABLE_SCHEMES_VALUES)); |
John Reck | fb3017f | 2010-10-26 19:01:24 -0700 | [diff] [blame] | 46 | |
Tarun Nainani | 8eb0091 | 2014-07-17 12:28:32 -0700 | [diff] [blame] | 47 | // Schemes for which the LIVE_MENU items defined in res/menu/browser.xml |
| 48 | // should be enabled |
| 49 | public static final String[] LIVE_SCHEMES_VALUES = new String[] |
| 50 | { "http", "https" }; |
| 51 | |
| 52 | private static final HashSet<String> LIVE_SCHEMES = |
| 53 | new HashSet<String>(Arrays.asList(LIVE_SCHEMES_VALUES)); |
| 54 | |
Michael Kolb | 8233fac | 2010-10-26 16:08:53 -0700 | [diff] [blame] | 55 | static final Pattern ACCEPTED_URI_SCHEMA = Pattern.compile( |
| 56 | "(?i)" + // switch on case insensitive matching |
| 57 | "(" + // begin group for schema |
Axesh R. Ajmera | 6fc7369 | 2015-08-11 16:32:10 -0700 | [diff] [blame] | 58 | "(?:http|https|file|chrome):\\/\\/" + |
Patrick Scott | b92bbb4 | 2011-01-05 11:38:58 -0500 | [diff] [blame] | 59 | "|(?:inline|data|about|javascript):" + |
Michael Kolb | 8233fac | 2010-10-26 16:08:53 -0700 | [diff] [blame] | 60 | ")" + |
| 61 | "(.*)" ); |
| 62 | |
| 63 | // Google search |
| 64 | private final static String QUICKSEARCH_G = "http://www.google.com/m?q=%s"; |
| 65 | private final static String QUERY_PLACE_HOLDER = "%s"; |
| 66 | |
John Reck | fe5b94d | 2011-09-06 10:21:29 -0700 | [diff] [blame] | 67 | // Regular expression to strip http:// and optionally |
John Reck | 434e9f8 | 2011-08-10 18:16:52 -0700 | [diff] [blame] | 68 | // the trailing slash |
| 69 | private static final Pattern STRIP_URL_PATTERN = |
John Reck | fe5b94d | 2011-09-06 10:21:29 -0700 | [diff] [blame] | 70 | Pattern.compile("^http://(.*?)/?$"); |
John Reck | fb3017f | 2010-10-26 19:01:24 -0700 | [diff] [blame] | 71 | |
| 72 | private UrlUtils() { /* cannot be instantiated */ } |
| 73 | |
| 74 | /** |
John Reck | fe5b94d | 2011-09-06 10:21:29 -0700 | [diff] [blame] | 75 | * Strips the provided url of preceding "http://" and any trailing "/". Does not |
John Reck | fb3017f | 2010-10-26 19:01:24 -0700 | [diff] [blame] | 76 | * strip "https://". If the provided string cannot be stripped, the original string |
| 77 | * is returned. |
| 78 | * |
| 79 | * TODO: Put this in TextUtils to be used by other packages doing something similar. |
| 80 | * |
| 81 | * @param url a url to strip, like "http://www.google.com/" |
John Reck | fe5b94d | 2011-09-06 10:21:29 -0700 | [diff] [blame] | 82 | * @return a stripped url like "www.google.com", or the original string if it could |
John Reck | fb3017f | 2010-10-26 19:01:24 -0700 | [diff] [blame] | 83 | * not be stripped |
| 84 | */ |
John Reck | 2cb9dc2 | 2011-05-11 16:12:27 -0700 | [diff] [blame] | 85 | public static String stripUrl(String url) { |
John Reck | fb3017f | 2010-10-26 19:01:24 -0700 | [diff] [blame] | 86 | if (url == null) return null; |
| 87 | Matcher m = STRIP_URL_PATTERN.matcher(url); |
John Reck | 434e9f8 | 2011-08-10 18:16:52 -0700 | [diff] [blame] | 88 | if (m.matches()) { |
| 89 | return m.group(1); |
John Reck | fb3017f | 2010-10-26 19:01:24 -0700 | [diff] [blame] | 90 | } else { |
| 91 | return url; |
| 92 | } |
| 93 | } |
Michael Kolb | 8233fac | 2010-10-26 16:08:53 -0700 | [diff] [blame] | 94 | |
| 95 | protected static String smartUrlFilter(Uri inUri) { |
| 96 | if (inUri != null) { |
| 97 | return smartUrlFilter(inUri.toString()); |
| 98 | } |
| 99 | return null; |
| 100 | } |
| 101 | |
| 102 | /** |
| 103 | * Attempts to determine whether user input is a URL or search |
| 104 | * terms. Anything with a space is passed to search. |
| 105 | * |
| 106 | * Converts to lowercase any mistakenly uppercased schema (i.e., |
| 107 | * "Http://" converts to "http://" |
| 108 | * |
| 109 | * @return Original or modified URL |
| 110 | * |
| 111 | */ |
John Reck | 961d35d | 2011-06-23 09:45:54 -0700 | [diff] [blame] | 112 | public static String smartUrlFilter(String url) { |
John Reck | 71e5142 | 2011-07-01 16:49:28 -0700 | [diff] [blame] | 113 | return smartUrlFilter(url, true); |
| 114 | } |
Michael Kolb | 8233fac | 2010-10-26 16:08:53 -0700 | [diff] [blame] | 115 | |
Vivek Sekhar | cc4bc5e | 2014-05-13 12:46:37 -0700 | [diff] [blame] | 116 | public static boolean isDownloadableScheme(Uri uri) { |
| 117 | return DOWNLOADABLE_SCHEMES.contains(uri.getScheme()); |
| 118 | } |
| 119 | |
| 120 | public static boolean isDownloadableScheme(String uri) { |
| 121 | try { |
Tarun Nainani | 8eb0091 | 2014-07-17 12:28:32 -0700 | [diff] [blame] | 122 | URI uriObj = new URI(uri); |
| 123 | return isDownloadableScheme(Uri.parse(uriObj.toString())); |
| 124 | } catch (Exception e) { |
| 125 | return false; |
| 126 | } |
| 127 | } |
| 128 | |
| 129 | public static boolean isLiveScheme(Uri uri) { |
| 130 | return LIVE_SCHEMES.contains(uri.getScheme()); |
| 131 | } |
| 132 | |
| 133 | public static boolean isLiveScheme(String uri) { |
| 134 | try { |
| 135 | return isLiveScheme(Uri.parse(uri)); |
Vivek Sekhar | cc4bc5e | 2014-05-13 12:46:37 -0700 | [diff] [blame] | 136 | } catch (Exception e) { |
| 137 | return false; |
| 138 | } |
| 139 | } |
| 140 | |
John Reck | 71e5142 | 2011-07-01 16:49:28 -0700 | [diff] [blame] | 141 | /** |
| 142 | * Attempts to determine whether user input is a URL or search |
| 143 | * terms. Anything with a space is passed to search if canBeSearch is true. |
| 144 | * |
| 145 | * Converts to lowercase any mistakenly uppercased schema (i.e., |
| 146 | * "Http://" converts to "http://" |
| 147 | * |
| 148 | * @param canBeSearch If true, will return a search url if it isn't a valid |
| 149 | * URL. If false, invalid URLs will return null |
| 150 | * @return Original or modified URL |
| 151 | * |
| 152 | */ |
| 153 | public static String smartUrlFilter(String url, boolean canBeSearch) { |
Michael Kolb | 8233fac | 2010-10-26 16:08:53 -0700 | [diff] [blame] | 154 | String inUrl = url.trim(); |
| 155 | boolean hasSpace = inUrl.indexOf(' ') != -1; |
| 156 | |
| 157 | Matcher matcher = ACCEPTED_URI_SCHEMA.matcher(inUrl); |
| 158 | if (matcher.matches()) { |
| 159 | // force scheme to lowercase |
| 160 | String scheme = matcher.group(1); |
| 161 | String lcScheme = scheme.toLowerCase(); |
| 162 | if (!lcScheme.equals(scheme)) { |
| 163 | inUrl = lcScheme + matcher.group(2); |
| 164 | } |
John Reck | 71e5142 | 2011-07-01 16:49:28 -0700 | [diff] [blame] | 165 | if (hasSpace && Patterns.WEB_URL.matcher(inUrl).matches()) { |
Michael Kolb | 8233fac | 2010-10-26 16:08:53 -0700 | [diff] [blame] | 166 | inUrl = inUrl.replace(" ", "%20"); |
| 167 | } |
| 168 | return inUrl; |
| 169 | } |
| 170 | if (!hasSpace) { |
| 171 | if (Patterns.WEB_URL.matcher(inUrl).matches()) { |
| 172 | return URLUtil.guessUrl(inUrl); |
| 173 | } |
| 174 | } |
John Reck | 71e5142 | 2011-07-01 16:49:28 -0700 | [diff] [blame] | 175 | if (canBeSearch) { |
| 176 | return URLUtil.composeSearchUrl(inUrl, |
| 177 | QUICKSEARCH_G, QUERY_PLACE_HOLDER); |
| 178 | } |
| 179 | return null; |
Michael Kolb | 8233fac | 2010-10-26 16:08:53 -0700 | [diff] [blame] | 180 | } |
| 181 | |
Sagar Dhawan | ef06f56 | 2015-09-07 15:23:22 +0200 | [diff] [blame] | 182 | public static String fixUpUrl(String url){ |
| 183 | if (TextUtils.isEmpty(url)) |
| 184 | return url; |
| 185 | |
| 186 | for (String preDefined: BROWSER_URLS){ |
| 187 | if (url.contains(preDefined)) { |
| 188 | return url; |
| 189 | } |
| 190 | } |
| 191 | return SWEUrlUtils.fixUpUrl(url); |
| 192 | } |
| 193 | |
| 194 | @Deprecated // Use fixUpUrl instead |
kaiyiz | 6e5b3e0 | 2013-08-19 20:02:01 +0800 | [diff] [blame] | 195 | public static String fixUrl(String inUrl) { |
Michael Kolb | 8233fac | 2010-10-26 16:08:53 -0700 | [diff] [blame] | 196 | // FIXME: Converting the url to lower case |
| 197 | // duplicates functionality in smartUrlFilter(). |
| 198 | // However, changing all current callers of fixUrl to |
| 199 | // call smartUrlFilter in addition may have unwanted |
| 200 | // consequences, and is deferred for now. |
| 201 | int colon = inUrl.indexOf(':'); |
| 202 | boolean allLower = true; |
| 203 | for (int index = 0; index < colon; index++) { |
| 204 | char ch = inUrl.charAt(index); |
| 205 | if (!Character.isLetter(ch)) { |
| 206 | break; |
| 207 | } |
| 208 | allLower &= Character.isLowerCase(ch); |
| 209 | if (index == colon - 1 && !allLower) { |
| 210 | inUrl = inUrl.substring(0, colon).toLowerCase() |
| 211 | + inUrl.substring(colon); |
| 212 | } |
| 213 | } |
| 214 | if (inUrl.startsWith("http://") || inUrl.startsWith("https://")) |
| 215 | return inUrl; |
| 216 | if (inUrl.startsWith("http:") || |
| 217 | inUrl.startsWith("https:")) { |
| 218 | if (inUrl.startsWith("http:/") || inUrl.startsWith("https:/")) { |
| 219 | inUrl = inUrl.replaceFirst("/", "//"); |
| 220 | } else inUrl = inUrl.replaceFirst(":", "://"); |
| 221 | } |
| 222 | return inUrl; |
| 223 | } |
| 224 | |
John Reck | 324d440 | 2011-01-11 16:56:42 -0800 | [diff] [blame] | 225 | // Returns the filtered URL. Cannot return null, but can return an empty string |
| 226 | /* package */ static String filteredUrl(String inUrl) { |
| 227 | if (inUrl == null) { |
| 228 | return ""; |
| 229 | } |
Axesh R. Ajmera | 6fc7369 | 2015-08-11 16:32:10 -0700 | [diff] [blame] | 230 | if (inUrl.startsWith("content:") |
| 231 | || inUrl.startsWith("browser:")) { |
John Reck | 324d440 | 2011-01-11 16:56:42 -0800 | [diff] [blame] | 232 | return ""; |
| 233 | } |
| 234 | return inUrl; |
| 235 | } |
| 236 | |
John Reck | fb3017f | 2010-10-26 19:01:24 -0700 | [diff] [blame] | 237 | } |