Chromium Code Reviews| 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..9555cca5dc777559d867be35b701fb5ef56bb832 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 an installation in progress. */ |
|
pkotwicz
2016/08/30 04:06:24
How about: "Monitors installation progress."
Xi Han
2016/08/30 17:49:29
Done.
|
| + 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. If user could cancel the |
|
pkotwicz
2016/08/30 04:06:24
How about: "... A user can cancel the installation
Xi Han
2016/08/30 17:49:29
It is better, thanks.
|
| + * installation when Android installation dialog shows, the only way to know |
| + * 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); |
| } |