chromium/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/HostBrowserUtils.java

// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.webapk.shell_apk;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.text.TextUtils;

import org.chromium.components.webapk.lib.common.WebApkMetaDataKeys;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/** Contains methods for getting information about host browser. */
public class HostBrowserUtils {
    private static final String VERSION_NAME_DEVELOPER_BUILD = "Developer Build";

    public static String ARC_INTENT_HELPER_BROWSER = "org.chromium.arc.intent_helper";

    public static String ARC_WEBAPK_BROWSER = "org.chromium.arc.webapk";

    /** The package names of the browsers that support WebAPK notification delegation. */
    private static Set<String> sBrowsersSupportingNotificationDelegation =
            new HashSet<String>(
                    Arrays.asList(
                            "com.google.android.apps.chrome",
                            "com.android.chrome",
                            "com.chrome.beta",
                            "com.chrome.dev",
                            "com.chrome.canary",
                            "org.chromium.chrome",
                            "org.chromium.chrome.tests",
                            ARC_INTENT_HELPER_BROWSER,
                            ARC_WEBAPK_BROWSER));

    /**
     * Returns whether the passed-in browser package name supports WebAPK notification delegation.
     */
    public static boolean doesBrowserSupportNotificationDelegation(String browserPackageName) {
        return sBrowsersSupportingNotificationDelegation.contains(browserPackageName);
    }

    /**
     * Returns whether intents (android.intent.action.MAIN, android.intent.action.SEND ...) should
     * launch {@link SplashActivity} for the given host browser params.
     */
    public static boolean shouldIntentLaunchSplashActivity(HostBrowserLauncherParams params) {
        return params.isNewStyleWebApk()
                && !params.getHostBrowserPackageName().equals(ARC_INTENT_HELPER_BROWSER)
                && !params.getHostBrowserPackageName().equals(ARC_WEBAPK_BROWSER);
    }

    /**
     * Returns the package name of the host browser to launch the WebAPK, or null if we did not find
     * one.
     */
    public static String computeHostBrowserPackageName(Context context) {
        // Gets the package name of the host browser if it is specified in AndroidManifest.xml.
        String hostBrowserFromManifest = getHostBrowserFromManifest(context);
        if (!TextUtils.isEmpty(hostBrowserFromManifest)) {
            return hostBrowserFromManifest;
        }

        PackageManager packageManager = context.getPackageManager();

        // Gets the package name of the default browser on the Android device.
        // TODO(hanxi): Investigate the best way to know which browser supports WebAPKs.
        String defaultBrowser = getDefaultBrowserPackageName(packageManager);
        if (!TextUtils.isEmpty(defaultBrowser)
                && WebApkUtils.isInstalled(packageManager, defaultBrowser)) {
            return defaultBrowser;
        }

        return null;
    }

    private static String getHostBrowserFromManifest(Context context) {
        String hostBrowserFromManifest =
                WebApkUtils.readMetaDataFromManifest(context, WebApkMetaDataKeys.RUNTIME_HOST);
        if (!TextUtils.isEmpty(hostBrowserFromManifest)
                && WebApkUtils.isInstalled(context.getPackageManager(), hostBrowserFromManifest)) {
            return hostBrowserFromManifest;
        }
        return null;
    }

    static boolean isHostBrowserFromManifest(Context context, String hostBrowser) {
        if (TextUtils.isEmpty(hostBrowser)) {
            return false;
        }
        return TextUtils.equals(hostBrowser, getHostBrowserFromManifest(context));
    }

    /** Returns the package name of the default browser on the Android device. */
    private static String getDefaultBrowserPackageName(PackageManager packageManager) {
        Intent browserIntent = WebApkUtils.getQueryInstalledBrowsersIntent();
        ResolveInfo resolveInfo =
                packageManager.resolveActivity(browserIntent, PackageManager.MATCH_DEFAULT_ONLY);
        return WebApkUtils.getPackageNameFromResolveInfo(resolveInfo);
    }

    /** Deletes the internal storage for the given context. */
    private static void deleteInternalStorage(Context context) {
        DexLoader.deletePath(context.getCacheDir());
        DexLoader.deletePath(context.getFilesDir());
        DexLoader.deletePath(
                context.getDir(HostBrowserClassLoader.DEX_DIR_NAME, Context.MODE_PRIVATE));
    }
}