Index: chrome/android/java/src/org/chromium/chrome/browser/infobar/AppBannerInfoBarDelegateAndroid.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AppBannerInfoBarDelegateAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AppBannerInfoBarDelegateAndroid.java |
index 989024241efeb1c31242977cc736eee29bf2dc45..4954dd35defae263a1affde7f6d3000ee5ca9e79 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AppBannerInfoBarDelegateAndroid.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AppBannerInfoBarDelegateAndroid.java |
@@ -11,15 +11,19 @@ import android.content.Intent; |
import android.content.pm.PackageManager; |
import android.os.Looper; |
+import org.chromium.base.ApplicationState; |
import org.chromium.base.ApplicationStatus; |
import org.chromium.base.ContextUtils; |
+import org.chromium.base.ThreadUtils; |
import org.chromium.base.VisibleForTesting; |
import org.chromium.base.annotations.CalledByNative; |
import org.chromium.base.annotations.JNINamespace; |
+import org.chromium.chrome.R; |
import org.chromium.chrome.browser.banners.AppData; |
import org.chromium.chrome.browser.banners.InstallerDelegate; |
import org.chromium.chrome.browser.tab.Tab; |
import org.chromium.ui.base.WindowAndroid; |
+import org.chromium.ui.widget.Toast; |
/** |
* Handles the promotion and installation of an app specified by the current web page. This Java |
@@ -39,6 +43,23 @@ public class AppBannerInfoBarDelegateAndroid { |
/** Monitors for application state changes. */ |
private final ApplicationStatus.ApplicationStateListener mListener; |
+ /** |
+ * Indicates whether a request to install a WebPK has started. This flag is set before |
+ * the package name of the WebAPK is available. |
+ */ |
+ private boolean mIsWebApkInstalling = false; |
+ |
+ private String mWebApkPackage; |
+ |
+ /** |
+ * Indicates whether to monitor the installation of the downloaded WebAPK. Currently WebAPKs |
+ * aren't installed by Play, so user could cancel the installation when Android installation |
+ * dialog shows. The only way to know whether user cancels the installation is to check whether |
+ * the WebAPK is installed when Chrome is resumed. This flag is set to true once the |
+ * installation Intent is sent to Android System. |
+ */ |
+ private boolean mStartMonitoringWebApkInstallation = false; |
+ |
/** Overrides the PackageManager for testing. */ |
@VisibleForTesting |
public static void setPackageManagerForTesting(PackageManager manager) { |
@@ -56,6 +77,13 @@ public class AppBannerInfoBarDelegateAndroid { |
@Override |
public void onApplicationStateChange(int newState) { |
if (!ApplicationStatus.hasVisibleActivities()) return; |
+ if (mStartMonitoringWebApkInstallation |
+ && newState == ApplicationState.HAS_RUNNING_ACTIVITIES) { |
+ if (nativeCloseAppBannerInfobarIfNeeded(mNativePointer)) { |
+ mStartMonitoringWebApkInstallation = false; |
+ return; |
+ } |
+ } |
nativeUpdateInstallState(mNativePointer); |
} |
}; |
@@ -79,10 +107,7 @@ public class AppBannerInfoBarDelegateAndroid { |
if (InstallerDelegate.isInstalled(packageManager, packageName)) { |
// Open the app. |
- Intent launchIntent = packageManager.getLaunchIntentForPackage(packageName); |
- if (launchIntent == null) return true; |
- context.startActivity(launchIntent); |
- return true; |
+ return openApp(context, packageName); |
} else { |
// Try installing the app. If the installation was kicked off, return false to prevent |
// the infobar from disappearing. |
@@ -96,6 +121,14 @@ public class AppBannerInfoBarDelegateAndroid { |
} |
} |
+ private boolean openApp(Context context, String packageName) { |
+ Intent launchIntent = getPackageManager(context).getLaunchIntentForPackage(packageName); |
+ if (launchIntent != null) { |
+ context.startActivity(launchIntent); |
+ } |
+ return true; |
+ } |
+ |
private WindowAndroid.IntentCallback createIntentCallback(final AppData appData) { |
return new WindowAndroid.IntentCallback() { |
@Override |
@@ -129,18 +162,64 @@ public class AppBannerInfoBarDelegateAndroid { |
} |
@CalledByNative |
+ private boolean installOrOpenWebApk(String packageName) { |
+ mWebApkPackage = packageName; |
+ Context context = ContextUtils.getApplicationContext(); |
+ PackageManager packageManager = getPackageManager(context); |
+ |
+ if (InstallerDelegate.isInstalled(packageManager, packageName)) { |
+ // Open the WebApk. |
+ mWebApkPackage = null; |
+ mStartMonitoringWebApkInstallation = false; |
+ return openApp(context, packageName); |
+ } else { |
+ // Try installing the WebAPK. If the installation was kicked off, return false to |
+ // prevent the infobar from disappearing. |
+ // Start monitoring the install. |
+ mInstallTask = new InstallerDelegate(Looper.getMainLooper(), packageManager, |
+ createInstallerDelegateObserver(), packageName); |
+ mInstallTask.start(); |
+ mStartMonitoringWebApkInstallation = true; |
+ return false; |
+ } |
+ } |
+ |
+ @CalledByNative |
private void showAppDetails(Tab tab, AppData appData) { |
tab.getWindowAndroid().showIntent(appData.detailsIntent(), null, null); |
} |
@CalledByNative |
private int determineInstallState(AppData data) { |
+ if (mIsWebApkInstalling) return AppBannerInfoBarAndroid.INSTALL_STATE_INSTALLING_WEBAPK; |
if (mInstallTask != null) return AppBannerInfoBarAndroid.INSTALL_STATE_INSTALLING; |
PackageManager pm = getPackageManager(ContextUtils.getApplicationContext()); |
- boolean isInstalled = InstallerDelegate.isInstalled(pm, data.packageName()); |
- return isInstalled ? AppBannerInfoBarAndroid.INSTALL_STATE_INSTALLED |
- : AppBannerInfoBarAndroid.INSTALL_STATE_NOT_INSTALLED; |
+ String packageName = data != null ? data.packageName() : mWebApkPackage; |
+ |
+ boolean isInstalled = InstallerDelegate.isInstalled(pm, packageName); |
+ if (!isInstalled) return AppBannerInfoBarAndroid.INSTALL_STATE_NOT_INSTALLED; |
+ return data != null ? AppBannerInfoBarAndroid.INSTALL_STATE_INSTALLED |
+ : AppBannerInfoBarAndroid.INSTALL_STATE_INSTALLED_WEBAPK; |
+ } |
+ |
+ @CalledByNative |
+ /** Set the flag of whether a installation process is started for the WebAPK. */ |
+ private void setWebApkInstallingState(boolean isInstalling) { |
+ mIsWebApkInstalling = isInstalling; |
+ } |
+ |
+ @CalledByNative |
+ private static void showWebApkInstallFailureToast() { |
+ ThreadUtils.runOnUiThread(new Runnable() { |
+ @Override |
+ public void run() { |
+ Context applicationContext = ContextUtils.getApplicationContext(); |
+ Toast toast = Toast.makeText(applicationContext, R.string.fail_to_install_webapk, |
+ Toast.LENGTH_SHORT); |
+ toast.show(); |
+ } |
+ }); |
} |
private PackageManager getPackageManager(Context context) { |
@@ -153,9 +232,18 @@ public class AppBannerInfoBarDelegateAndroid { |
return new AppBannerInfoBarDelegateAndroid(nativePtr); |
} |
+ @CalledByNative |
+ private boolean isWebApkInstalled(String packageName) { |
+ PackageManager packageManager = getPackageManager(ContextUtils.getApplicationContext()); |
+ boolean result = InstallerDelegate.isInstalled(packageManager, packageName); |
+ return result; |
+ } |
+ |
private native void nativeOnInstallIntentReturned( |
long nativeAppBannerInfoBarDelegateAndroid, boolean isInstalling); |
private native void nativeOnInstallFinished( |
long nativeAppBannerInfoBarDelegateAndroid, boolean success); |
private native void nativeUpdateInstallState(long nativeAppBannerInfoBarDelegateAndroid); |
+ private native boolean nativeCloseAppBannerInfobarIfNeeded( |
+ long nativeAppBannerInfoBarDelegateAndroid); |
} |