summaryrefslogtreecommitdiffstats
path: root/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/StringUtils.java
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/StringUtils.java')
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/StringUtils.java293
1 files changed, 293 insertions, 0 deletions
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/StringUtils.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/StringUtils.java
new file mode 100644
index 000000000..308168f43
--- /dev/null
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/StringUtils.java
@@ -0,0 +1,293 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.mozilla.gecko.util;
+
+import android.net.Uri;
+import android.support.annotation.NonNull;
+import android.text.TextUtils;
+
+import org.mozilla.gecko.AppConstants.Versions;
+
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+public class StringUtils {
+ private static final String LOGTAG = "GeckoStringUtils";
+
+ private static final String FILTER_URL_PREFIX = "filter://";
+ private static final String USER_ENTERED_URL_PREFIX = "user-entered:";
+
+ /*
+ * This method tries to guess if the given string could be a search query or URL,
+ * and returns a previous result if there is ambiguity
+ *
+ * Search examples:
+ * foo
+ * foo bar.com
+ * foo http://bar.com
+ *
+ * URL examples
+ * foo.com
+ * foo.c
+ * :foo
+ * http://foo.com bar
+ *
+ * wasSearchQuery specifies whether text was a search query before the latest change
+ * in text. In ambiguous cases where the new text can be either a search or a URL,
+ * wasSearchQuery is returned
+ */
+ public static boolean isSearchQuery(String text, boolean wasSearchQuery) {
+ // We remove leading and trailing white spaces when decoding URLs
+ text = text.trim();
+ if (text.length() == 0)
+ return wasSearchQuery;
+
+ int colon = text.indexOf(':');
+ int dot = text.indexOf('.');
+ int space = text.indexOf(' ');
+
+ // If a space is found before any dot and colon, we assume this is a search query
+ if (space > -1 && (colon == -1 || space < colon) && (dot == -1 || space < dot)) {
+ return true;
+ }
+ // Otherwise, if a dot or a colon is found, we assume this is a URL
+ if (dot > -1 || colon > -1) {
+ return false;
+ }
+ // Otherwise, text is ambiguous, and we keep its status unchanged
+ return wasSearchQuery;
+ }
+
+ /**
+ * Strip the ref from a URL, if present
+ *
+ * @return The base URL, without the ref. The original String is returned if it has no ref,
+ * of if the input is malformed.
+ */
+ public static String stripRef(final String inputURL) {
+ if (inputURL == null) {
+ return null;
+ }
+
+ final int refIndex = inputURL.indexOf('#');
+
+ if (refIndex >= 0) {
+ return inputURL.substring(0, refIndex);
+ }
+
+ return inputURL;
+ }
+
+ public static class UrlFlags {
+ public static final int NONE = 0;
+ public static final int STRIP_HTTPS = 1;
+ }
+
+ public static String stripScheme(String url) {
+ return stripScheme(url, UrlFlags.NONE);
+ }
+
+ public static String stripScheme(String url, int flags) {
+ if (url == null) {
+ return url;
+ }
+
+ String newURL = url;
+
+ if (newURL.startsWith("http://")) {
+ newURL = newURL.replace("http://", "");
+ } else if (newURL.startsWith("https://") && flags == UrlFlags.STRIP_HTTPS) {
+ newURL = newURL.replace("https://", "");
+ }
+
+ if (newURL.endsWith("/")) {
+ newURL = newURL.substring(0, newURL.length()-1);
+ }
+
+ return newURL;
+ }
+
+ public static boolean isHttpOrHttps(String url) {
+ if (TextUtils.isEmpty(url)) {
+ return false;
+ }
+
+ return url.startsWith("http://") || url.startsWith("https://");
+ }
+
+ public static String stripCommonSubdomains(String host) {
+ if (host == null) {
+ return host;
+ }
+
+ // In contrast to desktop, we also strip mobile subdomains,
+ // since its unlikely users are intentionally typing them
+ int start = 0;
+
+ if (host.startsWith("www.")) {
+ start = 4;
+ } else if (host.startsWith("mobile.")) {
+ start = 7;
+ } else if (host.startsWith("m.")) {
+ start = 2;
+ }
+
+ return host.substring(start);
+ }
+
+ /**
+ * Searches the url query string for the first value with the given key.
+ */
+ public static String getQueryParameter(String url, String desiredKey) {
+ if (TextUtils.isEmpty(url) || TextUtils.isEmpty(desiredKey)) {
+ return null;
+ }
+
+ final String[] urlParts = url.split("\\?");
+ if (urlParts.length < 2) {
+ return null;
+ }
+
+ final String query = urlParts[1];
+ for (final String param : query.split("&")) {
+ final String pair[] = param.split("=");
+ final String key = Uri.decode(pair[0]);
+
+ // Key is empty or does not match the key we're looking for, discard
+ if (TextUtils.isEmpty(key) || !key.equals(desiredKey)) {
+ continue;
+ }
+ // No value associated with key, discard
+ if (pair.length < 2) {
+ continue;
+ }
+ final String value = Uri.decode(pair[1]);
+ if (TextUtils.isEmpty(value)) {
+ return null;
+ }
+ return value;
+ }
+
+ return null;
+ }
+
+ public static boolean isFilterUrl(String url) {
+ if (TextUtils.isEmpty(url)) {
+ return false;
+ }
+
+ return url.startsWith(FILTER_URL_PREFIX);
+ }
+
+ public static String getFilterFromUrl(String url) {
+ if (TextUtils.isEmpty(url)) {
+ return null;
+ }
+
+ return url.substring(FILTER_URL_PREFIX.length());
+ }
+
+ public static boolean isShareableUrl(final String url) {
+ final String scheme = Uri.parse(url).getScheme();
+ return !("about".equals(scheme) || "chrome".equals(scheme) ||
+ "file".equals(scheme) || "resource".equals(scheme));
+ }
+
+ public static boolean isUserEnteredUrl(String url) {
+ return (url != null && url.startsWith(USER_ENTERED_URL_PREFIX));
+ }
+
+ /**
+ * Given a url with a user-entered scheme, extract the
+ * scheme-specific component. For e.g, given "user-entered://www.google.com",
+ * this method returns "//www.google.com". If the passed url
+ * does not have a user-entered scheme, the same url will be returned.
+ *
+ * @param url to be decoded
+ * @return url component entered by user
+ */
+ public static String decodeUserEnteredUrl(String url) {
+ Uri uri = Uri.parse(url);
+ if ("user-entered".equals(uri.getScheme())) {
+ return uri.getSchemeSpecificPart();
+ }
+ return url;
+ }
+
+ public static String encodeUserEnteredUrl(String url) {
+ return Uri.fromParts("user-entered", url, null).toString();
+ }
+
+ /**
+ * Compatibility layer for API < 11.
+ *
+ * Returns a set of the unique names of all query parameters. Iterating
+ * over the set will return the names in order of their first occurrence.
+ *
+ * @param uri
+ * @throws UnsupportedOperationException if this isn't a hierarchical URI
+ *
+ * @return a set of decoded names
+ */
+ public static Set<String> getQueryParameterNames(Uri uri) {
+ return uri.getQueryParameterNames();
+ }
+
+ public static String safeSubstring(@NonNull final String str, final int start, final int end) {
+ return str.substring(
+ Math.max(0, start),
+ Math.min(end, str.length()));
+ }
+
+ /**
+ * Check if this might be a RTL (right-to-left) text by looking at the first character.
+ */
+ public static boolean isRTL(String text) {
+ if (TextUtils.isEmpty(text)) {
+ return false;
+ }
+
+ final char character = text.charAt(0);
+ final byte directionality = Character.getDirectionality(character);
+
+ return directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT
+ || directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC
+ || directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_EMBEDDING
+ || directionality == Character.DIRECTIONALITY_RIGHT_TO_LEFT_OVERRIDE;
+ }
+
+ /**
+ * Force LTR (left-to-right) by prepending the text with the "left-to-right mark" (U+200E) if needed.
+ */
+ public static String forceLTR(String text) {
+ if (!isRTL(text)) {
+ return text;
+ }
+
+ return "\u200E" + text;
+ }
+
+ /**
+ * Joining together a sequence of strings with a separator.
+ */
+ public static String join(@NonNull String separator, @NonNull List<String> parts) {
+ if (parts.size() == 0) {
+ return "";
+ }
+
+ final StringBuilder builder = new StringBuilder();
+ builder.append(parts.get(0));
+
+ for (int i = 1; i < parts.size(); i++) {
+ builder.append(separator);
+ builder.append(parts.get(i));
+ }
+
+ return builder.toString();
+ }
+}