| Index: chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInstaller.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInstaller.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInstaller.java
|
| index fa7633e5d192a15fef52043d68a79bb7d9d46609..adfdbb5ba95f1913e53a4bd2eb0d73d043f7cbd4 100644
|
| --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInstaller.java
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInstaller.java
|
| @@ -5,27 +5,58 @@
|
| package org.chromium.chrome.browser.webapps;
|
|
|
| import android.content.ActivityNotFoundException;
|
| -import android.content.BroadcastReceiver;
|
| import android.content.Context;
|
| import android.content.Intent;
|
| -import android.content.IntentFilter;
|
| +import android.content.pm.PackageManager;
|
| import android.net.Uri;
|
| +import android.os.Looper;
|
| import android.provider.Settings;
|
|
|
| +import org.chromium.base.ApplicationState;
|
| +import org.chromium.base.ApplicationStatus;
|
| import org.chromium.base.ContextUtils;
|
| import org.chromium.base.Log;
|
| import org.chromium.base.annotations.CalledByNative;
|
| import org.chromium.chrome.browser.ShortcutHelper;
|
| +import org.chromium.chrome.browser.banners.InstallerDelegate;
|
|
|
| import java.io.File;
|
|
|
| /**
|
| * Java counterpart to webapk_installer.h
|
| * Contains functionality to install / update WebAPKs.
|
| + * This Java object is created by and owned by the native WebApkInstaller.
|
| */
|
| public class WebApkInstaller {
|
| private static final String TAG = "WebApkInstaller";
|
|
|
| + /** The WebAPK's package name. */
|
| + private String mWebApkPackageName;
|
| +
|
| + /** Monitors for application state changes. */
|
| + private ApplicationStatus.ApplicationStateListener mListener;
|
| +
|
| + /** Monitors installation progress. */
|
| + private InstallerDelegate mInstallTask;
|
| +
|
| + /** Weak pointer to the native WebApkInstaller. */
|
| + private long mNativePointer;
|
| +
|
| + private WebApkInstaller(long nativePtr) {
|
| + mNativePointer = nativePtr;
|
| + }
|
| +
|
| + @CalledByNative
|
| + private static WebApkInstaller create(long nativePtr) {
|
| + return new WebApkInstaller(nativePtr);
|
| + }
|
| +
|
| + @CalledByNative
|
| + private void destroy() {
|
| + ApplicationStatus.unregisterApplicationStateListener(mListener);
|
| + mNativePointer = 0;
|
| + }
|
| +
|
| /**
|
| * Installs a WebAPK.
|
| * @param filePath File to install.
|
| @@ -34,18 +65,28 @@ public class WebApkInstaller {
|
| * install succeeds.
|
| */
|
| @CalledByNative
|
| - static boolean installAsyncFromNative(String filePath, String packageName) {
|
| + private boolean installAsyncFromNative(String filePath, String packageName) {
|
| if (!installingFromUnknownSourcesAllowed()) {
|
| Log.e(TAG,
|
| "WebAPK install failed because installation from unknown sources is disabled.");
|
| return false;
|
| }
|
| + mWebApkPackageName = packageName;
|
| +
|
| + // Start monitoring the installation.
|
| + PackageManager packageManager = ContextUtils.getApplicationContext().getPackageManager();
|
| + mInstallTask = new InstallerDelegate(Looper.getMainLooper(), packageManager,
|
| + createInstallerDelegateObserver(), packageName);
|
| + mInstallTask.start();
|
| + // Start monitoring the application state changes.
|
| + mListener = createApplicationStateListener();
|
| + ApplicationStatus.registerApplicationStateListener(mListener);
|
| +
|
| Intent intent = new Intent(Intent.ACTION_VIEW);
|
| Uri fileUri = Uri.fromFile(new File(filePath));
|
| intent.setDataAndType(fileUri, "application/vnd.android.package-archive");
|
| intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
| try {
|
| - listenForPackageInstallation(packageName);
|
| ContextUtils.getApplicationContext().startActivity(intent);
|
| } catch (ActivityNotFoundException e) {
|
| return false;
|
| @@ -53,34 +94,27 @@ public class WebApkInstaller {
|
| return true;
|
| }
|
|
|
| - private static class WebApkInstallObserver extends BroadcastReceiver {
|
| - private final String mPackageName;
|
| - public WebApkInstallObserver(String packageName) {
|
| - mPackageName = packageName;
|
| - }
|
| -
|
| - private static String getPackageName(Intent intent) {
|
| - Uri uri = intent.getData();
|
| - String pkg = uri != null ? uri.getSchemeSpecificPart() : null;
|
| - return pkg;
|
| - }
|
| -
|
| - @Override
|
| - public void onReceive(Context context, Intent intent) {
|
| - if (mPackageName.equals(getPackageName(intent))) {
|
| - ShortcutHelper.addWebApkShortcut(context, mPackageName);
|
| - context.unregisterReceiver(this);
|
| + private InstallerDelegate.Observer createInstallerDelegateObserver() {
|
| + return new InstallerDelegate.Observer() {
|
| + @Override
|
| + public void onInstallFinished(InstallerDelegate task, boolean success) {
|
| + if (mInstallTask != task) return;
|
| + onInstallFinishedInternal(success);
|
| }
|
| - }
|
| + };
|
| }
|
|
|
| - private static void listenForPackageInstallation(String packageName) {
|
| - IntentFilter iFilter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
|
| - iFilter.addDataScheme("package");
|
| - ContextUtils.getApplicationContext().registerReceiver(
|
| - new WebApkInstallObserver(packageName), iFilter);
|
| + private void onInstallFinishedInternal(boolean success) {
|
| + ApplicationStatus.unregisterApplicationStateListener(mListener);
|
| + mInstallTask = null;
|
| + if (mNativePointer != 0) {
|
| + nativeOnInstallFinished(mNativePointer, success);
|
| + }
|
| + if (success) {
|
| + ShortcutHelper.addWebApkShortcut(ContextUtils.getApplicationContext(),
|
| + mWebApkPackageName);
|
| + }
|
| }
|
| -
|
| /**
|
| * Updates a WebAPK.
|
| * @param filePath File to update.
|
| @@ -89,7 +123,9 @@ public class WebApkInstaller {
|
| * update succeeds.
|
| */
|
| @CalledByNative
|
| - private static boolean updateAsyncFromNative(String filePath, String packageName) {
|
| + private boolean updateAsyncFromNative(String filePath, String packageName) {
|
| + // TODO(hanxi): Calls back to C++ when the updating is complete or return a failure status
|
| + // if fails.
|
| return false;
|
| }
|
|
|
| @@ -107,4 +143,32 @@ public class WebApkInstaller {
|
| return false;
|
| }
|
| }
|
| +
|
| + private ApplicationStatus.ApplicationStateListener createApplicationStateListener() {
|
| + return new ApplicationStatus.ApplicationStateListener() {
|
| + @Override
|
| + public void onApplicationStateChange(int newState) {
|
| + if (!ApplicationStatus.hasVisibleActivities()) return;
|
| + /**
|
| + * Currently WebAPKs aren't installed by Play. A user can cancel the installation
|
| + * when the Android native installation dialog shows. The only way to detect the
|
| + * user cancelling the installation is to check whether the WebAPK is installed
|
| + * when Chrome is resumed. The monitoring of application state changes will be
|
| + * removed once WebAPKs are installed by Play.
|
| + */
|
| + if (newState == ApplicationState.HAS_RUNNING_ACTIVITIES
|
| + && !isWebApkInstalled(mWebApkPackageName)) {
|
| + onInstallFinishedInternal(false);
|
| + return;
|
| + }
|
| + }
|
| + };
|
| + }
|
| +
|
| + private boolean isWebApkInstalled(String packageName) {
|
| + PackageManager packageManager = ContextUtils.getApplicationContext().getPackageManager();
|
| + return InstallerDelegate.isInstalled(packageManager, packageName);
|
| + }
|
| +
|
| + private native void nativeOnInstallFinished(long nativeWebApkInstaller, boolean success);
|
| }
|
|
|