165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/*
265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Copyright (C) 2014 The Android Open Source Project
365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Licensed under the Apache License, Version 2.0 (the "License");
565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * you may not use this file except in compliance with the License.
665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * You may obtain a copy of the License at
765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *      http://www.apache.org/licenses/LICENSE-2.0
965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
1065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Unless required by applicable law or agreed to in writing, software
1165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * distributed under the License is distributed on an "AS IS" BASIS,
1265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * See the License for the specific language governing permissions and
1465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * limitations under the License.
1565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */
1665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
1765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepackage com.android.tv.settings.util;
1865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
1965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.ContentResolver;
2065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Intent.ShortcutIconResource;
2165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.net.Uri;
2265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
2365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/**
2465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Utilities for working with URIs.
2565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */
2665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepublic final class UriUtils {
2765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
2865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String SCHEME_SHORTCUT_ICON_RESOURCE = "shortcut.icon.resource";
2965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String SCHEME_DELIMITER = "://";
3065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String URI_PATH_DELIMITER = "/";
3165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String URI_PACKAGE_DELIMITER = ":";
3265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String HTTP_PREFIX = "http";
3365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String HTTPS_PREFIX = "https";
3465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String SCHEME_ACCOUNT_IMAGE = "image.account";
3565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String ACCOUNT_IMAGE_CHANGE_NOTIFY_URI = "change_notify_uri";
3665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
3765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
3865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Non instantiable.
3965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
4065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private UriUtils() {}
4165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
4265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
4365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Gets a URI with short cut icon scheme.
4465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
4565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static Uri getShortcutIconResourceUri(ShortcutIconResource iconResource) {
4665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return Uri.parse(SCHEME_SHORTCUT_ICON_RESOURCE + SCHEME_DELIMITER + iconResource.packageName
4765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                + URI_PATH_DELIMITER
4865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                + iconResource.resourceName.replace(URI_PACKAGE_DELIMITER, URI_PATH_DELIMITER));
4965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
5065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
5165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
5265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Checks if the URI refers to an Android resource.
5365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
5465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static boolean isAndroidResourceUri(Uri uri) {
5565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return ContentResolver.SCHEME_ANDROID_RESOURCE.equals(uri.getScheme());
5665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
5765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
5865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
5965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Checks if the URI refers to an account image.
6065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
6165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static boolean isAccountImageUri(Uri uri) {
626e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantler        return uri != null && SCHEME_ACCOUNT_IMAGE.equals(uri.getScheme());
6365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
6465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
6565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static String getAccountName(Uri uri) {
6665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (isAccountImageUri(uri)) {
676e995161147d9110d77ae1fe38b697e52891d3f2Tony Mantler            return uri.getAuthority() + uri.getPath();
6865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else {
6965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            throw new IllegalArgumentException("Invalid account image URI. " + uri);
7065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
7165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
7265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
7365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static Uri getAccountImageChangeNotifyUri(Uri uri) {
7465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (isAccountImageUri(uri)) {
7565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            String notifyUri = uri.getQueryParameter(ACCOUNT_IMAGE_CHANGE_NOTIFY_URI);
7665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            if (notifyUri == null) {
7765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                return null;
7865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } else {
7965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                return Uri.parse(notifyUri);
8065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
8165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else {
8265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            throw new IllegalArgumentException("Invalid account image URI. " + uri);
8365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
8465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
8565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
8665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
8765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Returns {@code true} if the URI refers to a content URI which can be opened via
8865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * {@link ContentResolver#openInputStream(Uri)}.
8965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
9065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static boolean isContentUri(Uri uri) {
9165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return ContentResolver.SCHEME_CONTENT.equals(uri.getScheme()) ||
9265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                ContentResolver.SCHEME_FILE.equals(uri.getScheme());
9365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
9465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
9565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
9665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Checks if the URI refers to an shortcut icon resource.
9765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
9865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static boolean isShortcutIconResourceUri(Uri uri) {
9965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return SCHEME_SHORTCUT_ICON_RESOURCE.equals(uri.getScheme());
10065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
10165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
10265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
10365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Creates a shortcut icon resource object from an Android resource URI.
10465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
10565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static ShortcutIconResource getIconResource(Uri uri) {
10665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if(isAndroidResourceUri(uri)) {
10765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            ShortcutIconResource iconResource = new ShortcutIconResource();
10865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            iconResource.packageName = uri.getAuthority();
10965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            // Trim off the scheme + 3 extra for "://", then replace the first "/" with a ":"
11065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            iconResource.resourceName = uri.toString().substring(
11165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    ContentResolver.SCHEME_ANDROID_RESOURCE.length() + SCHEME_DELIMITER.length())
11265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .replaceFirst(URI_PATH_DELIMITER, URI_PACKAGE_DELIMITER);
11365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return iconResource;
11465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else if(isShortcutIconResourceUri(uri)) {
11565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            ShortcutIconResource iconResource = new ShortcutIconResource();
11665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            iconResource.packageName = uri.getAuthority();
11765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            iconResource.resourceName = uri.toString().substring(
11865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    SCHEME_SHORTCUT_ICON_RESOURCE.length() + SCHEME_DELIMITER.length()
11965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    + iconResource.packageName.length() + URI_PATH_DELIMITER.length())
12065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    .replaceFirst(URI_PATH_DELIMITER, URI_PACKAGE_DELIMITER);
12165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return iconResource;
12265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } else {
12365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            throw new IllegalArgumentException("Invalid resource URI. " + uri);
12465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
12565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
12665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
12765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
12865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Returns {@code true} if this is a web URI.
12965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
13065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public static boolean isWebUri(Uri resourceUri) {
13165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        String scheme = resourceUri.getScheme() == null ? null
13265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                : resourceUri.getScheme().toLowerCase();
13365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return HTTP_PREFIX.equals(scheme) || HTTPS_PREFIX.equals(scheme);
13465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
13565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
13665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane}
137