blob: eb3116ff8a95dca955691d88aee22a6c9e4f3e1c [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// 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.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import org.chromium.webapk.lib.common.WebApkConstants;
import org.chromium.webapk.lib.common.WebApkMetaDataKeys;
import java.util.List;
/** Selects host browser to launch, showing a dialog to select browser if necessary. */
public class LaunchHostBrowserSelector {
private static final String LAST_RESORT_HOST_BROWSER = "com.android.chrome";
private static final String LAST_RESORT_HOST_BROWSER_APPLICATION_NAME = "Google Chrome";
private static final String TAG = "cr_LaunchHostBrowserSelector";
private Context mContext;
/** Parent activity for any dialogs. */
private Activity mParentActivity;
/**
* Called once {@link #selectHostBrowser()} has selected the host browser either
* via a shared preferences/<meta-data> lookup or via the user selecting the host
* browser from a dialog.
*/
public static interface Callback {
void onBrowserSelected(String hostBrowserPackageName, boolean dialogShown);
}
public LaunchHostBrowserSelector(Activity parentActivity) {
mParentActivity = parentActivity;
mContext = parentActivity.getApplicationContext();
}
/**
* Creates install Intent.
* @param packageName Package to install.
* @return The intent.
*/
private static Intent createInstallIntent(String packageName) {
String marketUrl = "market://details?id=" + packageName;
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(marketUrl));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
return intent;
}
/**
* Selects host browser to launch, showing a dialog to select browser if necessary. Calls
* {@link selectCallback} with the result.
*/
public void selectHostBrowser(Callback selectCallback) {
Bundle metadata = WebApkUtils.readMetaData(mContext);
if (metadata == null) {
selectCallback.onBrowserSelected(null, false /* dialogShown */);
return;
}
String packageName = mContext.getPackageName();
Log.v(TAG, "Package name of the WebAPK:" + packageName);
String runtimeHostInPreferences =
HostBrowserUtils.getHostBrowserFromSharedPreference(mContext);
String runtimeHost = HostBrowserUtils.getHostBrowserPackageName(mContext);
if (!TextUtils.isEmpty(runtimeHostInPreferences)
&& !runtimeHostInPreferences.equals(runtimeHost)) {
deleteSharedPref();
deleteInternalStorage();
}
if (!TextUtils.isEmpty(runtimeHost)) {
selectCallback.onBrowserSelected(runtimeHost, false /* dialogShown */);
return;
}
List<ResolveInfo> infos =
WebApkUtils.getInstalledBrowserResolveInfos(mContext.getPackageManager());
if (hasBrowserSupportingWebApks(infos)) {
showChooseHostBrowserDialog(infos, selectCallback);
} else {
showInstallHostBrowserDialog(metadata, selectCallback);
}
}
/** Deletes the SharedPreferences. */
private void deleteSharedPref() {
SharedPreferences sharedPref =
mContext.getSharedPreferences(WebApkConstants.PREF_PACKAGE, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.clear();
editor.apply();
}
/** Deletes the internal storage. */
private void deleteInternalStorage() {
DexLoader.deletePath(mContext.getCacheDir());
DexLoader.deletePath(mContext.getFilesDir());
DexLoader.deletePath(
mContext.getDir(HostBrowserClassLoader.DEX_DIR_NAME, Context.MODE_PRIVATE));
}
/**
* Launches the Play Store with the host browser's page.
*/
private void installBrowser(String hostBrowserPackageName) {
try {
mParentActivity.startActivity(createInstallIntent(hostBrowserPackageName));
} catch (ActivityNotFoundException e) {
}
}
/** Returns whether there is any installed browser supporting WebAPKs. */
private static boolean hasBrowserSupportingWebApks(List<ResolveInfo> resolveInfos) {
List<String> browsersSupportingWebApk = HostBrowserUtils.getBrowsersSupportingWebApk();
for (ResolveInfo info : resolveInfos) {
if (browsersSupportingWebApk.contains(info.activityInfo.packageName)) {
return true;
}
}
return false;
}
/** Shows a dialog to choose the host browser. */
private void showChooseHostBrowserDialog(List<ResolveInfo> infos, Callback selectCallback) {
ChooseHostBrowserDialog.DialogListener listener =
new ChooseHostBrowserDialog.DialogListener() {
@Override
public void onHostBrowserSelected(String selectedHostBrowser) {
HostBrowserUtils.writeHostBrowserToSharedPref(
mContext, selectedHostBrowser);
selectCallback.onBrowserSelected(
selectedHostBrowser, true /* dialogShown */);
}
@Override
public void onQuit() {
selectCallback.onBrowserSelected(null, true /* dialogShown */);
}
};
ChooseHostBrowserDialog.show(
mParentActivity, listener, infos, mContext.getString(R.string.name));
}
/** Shows a dialog to install the host browser. */
private void showInstallHostBrowserDialog(Bundle metadata, Callback selectCallback) {
String lastResortHostBrowserPackageName =
metadata.getString(WebApkMetaDataKeys.RUNTIME_HOST);
String lastResortHostBrowserApplicationName =
metadata.getString(WebApkMetaDataKeys.RUNTIME_HOST_APPLICATION_NAME);
if (TextUtils.isEmpty(lastResortHostBrowserPackageName)) {
// WebAPKs without runtime host specified in the AndroidManifest.xml always install
// Google Chrome as the default host browser.
lastResortHostBrowserPackageName = LAST_RESORT_HOST_BROWSER;
lastResortHostBrowserApplicationName = LAST_RESORT_HOST_BROWSER_APPLICATION_NAME;
}
InstallHostBrowserDialog.DialogListener listener =
new InstallHostBrowserDialog.DialogListener() {
@Override
public void onConfirmInstall(String packageName) {
installBrowser(packageName);
HostBrowserUtils.writeHostBrowserToSharedPref(mContext, packageName);
selectCallback.onBrowserSelected(null, true /* dialogShown */);
}
@Override
public void onConfirmQuit() {
selectCallback.onBrowserSelected(null, true /* dialogShown */);
}
};
InstallHostBrowserDialog.show(mParentActivity, listener, mContext.getString(R.string.name),
lastResortHostBrowserPackageName, lastResortHostBrowserApplicationName,
R.drawable.last_resort_runtime_host_logo);
}
}