| Index: chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java
|
| index b7394bd188161b8d20252ce1e43477f60ba4e1f6..5433a710d1f5f5b90fcf2e00f04a939ce39fb7c2 100644
|
| --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkUpdateManager.java
|
| @@ -7,7 +7,6 @@ package org.chromium.chrome.browser.webapps;
|
| import android.content.pm.PackageInfo;
|
| import android.content.pm.PackageManager;
|
| import android.graphics.Bitmap;
|
| -import android.os.Bundle;
|
|
|
| import org.chromium.base.CommandLine;
|
| import org.chromium.base.ContextUtils;
|
| @@ -15,9 +14,7 @@ import org.chromium.base.Log;
|
| import org.chromium.base.annotations.CalledByNative;
|
| import org.chromium.chrome.browser.ChromeSwitches;
|
| import org.chromium.chrome.browser.tab.Tab;
|
| -import org.chromium.chrome.browser.util.IntentUtils;
|
| import org.chromium.webapk.lib.client.WebApkVersion;
|
| -import org.chromium.webapk.lib.common.WebApkMetaDataKeys;
|
|
|
| import java.util.concurrent.TimeUnit;
|
|
|
| @@ -37,16 +34,17 @@ public class WebApkUpdateManager implements ManifestUpgradeDetector.Callback {
|
| */
|
| public static final long RETRY_UPDATE_DURATION = TimeUnit.HOURS.toMillis(12L);
|
|
|
| - /**
|
| - * Id of WebAPK data in WebappDataStorage
|
| - */
|
| + /** Id of WebAPK data in WebappDataStorage */
|
| private String mId;
|
|
|
| /** WebAPK package name. */
|
| private String mWebApkPackageName;
|
|
|
| - /** Android version code of WebAPK. */
|
| - private int mVersionCode;
|
| + /** Meta data from the WebAPK's Android Manifest */
|
| + private WebApkMetaData mMetaData;
|
| +
|
| + /** WebAPK's icon. */
|
| + private Bitmap mIcon;
|
|
|
| /**
|
| * Whether the previous WebAPK update succeeded. True if there has not been any update attempts.
|
| @@ -62,30 +60,19 @@ public class WebApkUpdateManager implements ManifestUpgradeDetector.Callback {
|
| * @param info The WebappInfo of the WebAPK.
|
| */
|
| public void updateIfNeeded(Tab tab, WebappInfo info) {
|
| - PackageInfo packageInfo = readPackageInfoFromAndroidManifest(info.webApkPackageName());
|
| - if (packageInfo == null) {
|
| - return;
|
| - }
|
| + mMetaData = WebApkMetaDataUtils.extractMetaDataFromWebApk(info.webApkPackageName());
|
| + if (mMetaData == null) return;
|
|
|
| mWebApkPackageName = info.webApkPackageName();
|
| mId = info.id();
|
| - mVersionCode = packageInfo.versionCode;
|
| - final Bundle metadata = packageInfo.applicationInfo.metaData;
|
| - int shellApkVersion =
|
| - IntentUtils.safeGetInt(metadata, WebApkMetaDataKeys.SHELL_APK_VERSION, 0);
|
| + mIcon = info.icon();
|
|
|
| WebappDataStorage storage = WebappRegistry.getInstance().getWebappDataStorage(mId);
|
| mPreviousUpdateSucceeded = didPreviousUpdateSucceed(storage);
|
|
|
| - // TODO(pkotwicz|hanxi): Request upgrade if ShellAPK version changes if
|
| - // ManifestUpgradeDetector cannot fetch the Web Manifest. For instance, the web developer
|
| - // may have removed the Web Manifest from their site. (http://crbug.com/639536)
|
| + if (!shouldCheckIfWebManifestUpdated(storage, mMetaData, mPreviousUpdateSucceeded)) return;
|
|
|
| - if (!shouldCheckIfWebManifestUpdated(storage, shellApkVersion, mPreviousUpdateSucceeded)) {
|
| - return;
|
| - }
|
| -
|
| - mUpgradeDetector = buildManifestUpgradeDetector(tab, info, metadata);
|
| + mUpgradeDetector = buildManifestUpgradeDetector(tab, mMetaData);
|
| if (!mUpgradeDetector.start()) return;
|
|
|
| // crbug.com/636525. The timestamp of the last manifest update check should be updated after
|
| @@ -93,16 +80,40 @@ public class WebApkUpdateManager implements ManifestUpgradeDetector.Callback {
|
| storage.updateTimeOfLastCheckForUpdatedWebManifest();
|
| }
|
|
|
| - @Override
|
| - public void onUpgradeNeededCheckFinished(boolean needsUpgrade,
|
| - ManifestUpgradeDetector.FetchedManifestData data) {
|
| - String manifestUrl = mUpgradeDetector.getManifestUrl();
|
| + public void destroy() {
|
| + destroyUpgradeDetector();
|
| + }
|
|
|
| - mUpgradeDetector.destroy();
|
| - mUpgradeDetector = null;
|
| + @Override
|
| + public void onFinishedFetchingWebManifestForInitialUrl(
|
| + boolean needsUpgrade, ManifestUpgradeDetector.FetchedManifestData data) {
|
| + onGotManifestData(needsUpgrade, data);
|
| + }
|
|
|
| + @Override
|
| + public void onGotManifestData(
|
| + boolean needsUpgrade, ManifestUpgradeDetector.FetchedManifestData data) {
|
| + boolean gotManifest = (data != null);
|
| + needsUpgrade |= isShellApkVersionOutOfDate(mMetaData);
|
| + Log.v(TAG, "Got Manifest: " + gotManifest);
|
| Log.v(TAG, "WebAPK upgrade needed: " + needsUpgrade);
|
|
|
| + // If the Web Manifest was not found and an upgrade is requested, stop fetching Web
|
| + // Manifests as the user navigates to avoid sending multiple WebAPK update requests. In
|
| + // particular:
|
| + // - A WebAPK update request on the initial load because the Shell APK version is out of
|
| + // date.
|
| + // - A second WebAPK update request once the user navigates to a page which points to the
|
| + // correct Web Manifest URL because the Web Manifest has been updated by the Web
|
| + // developer.
|
| + //
|
| + // If the Web Manifest was not found and an upgrade is not requested, keep on fetching
|
| + // Web Manifests as the user navigates. For instance, the WebAPK's start_url might not
|
| + // point to a Web Manifest because start_url redirects to the WebAPK's main page.
|
| + if (gotManifest || needsUpgrade) {
|
| + destroyUpgradeDetector();
|
| + }
|
| +
|
| if (!needsUpgrade) {
|
| if (!mPreviousUpdateSucceeded) {
|
| recordUpdateInWebappDataStorage(mId, true);
|
| @@ -113,31 +124,54 @@ public class WebApkUpdateManager implements ManifestUpgradeDetector.Callback {
|
| // Set WebAPK update as having failed in case that Chrome is killed prior to
|
| // {@link onBuiltWebApk} being called.
|
| recordUpdateInWebappDataStorage(mId, false);
|
| - updateAsync(manifestUrl, data);
|
| +
|
| + if (data != null) {
|
| + updateAsync(data.startUrl, data.scopeUrl, data.name, data.shortName, data.iconUrl,
|
| + data.iconMurmur2Hash, data.icon, data.displayMode, data.orientation,
|
| + data.themeColor, data.backgroundColor);
|
| + return;
|
| + }
|
| +
|
| + updateAsyncUsingAndroidManifestMetaData();
|
| }
|
|
|
| /**
|
| * Builds {@link ManifestUpgradeDetector}. In a separate function for the sake of tests.
|
| */
|
| protected ManifestUpgradeDetector buildManifestUpgradeDetector(
|
| - Tab tab, WebappInfo info, Bundle metaData) {
|
| - return new ManifestUpgradeDetector(tab, info, metaData, this);
|
| + Tab tab, WebApkMetaData metaData) {
|
| + return new ManifestUpgradeDetector(tab, metaData, this);
|
| + }
|
| +
|
| + /**
|
| + * Sends a request to WebAPK Server to update WebAPK using the meta data from the WebAPK's
|
| + * Android Manifest.
|
| + */
|
| + private void updateAsyncUsingAndroidManifestMetaData() {
|
| + updateAsync(mMetaData.startUrl, mMetaData.scope, mMetaData.name, mMetaData.shortName,
|
| + mMetaData.iconUrl, mMetaData.iconMurmur2Hash, mIcon, mMetaData.displayMode,
|
| + mMetaData.orientation, mMetaData.themeColor, mMetaData.backgroundColor);
|
| }
|
|
|
| /**
|
| * Sends request to WebAPK Server to update WebAPK.
|
| */
|
| - public void updateAsync(String manifestUrl, ManifestUpgradeDetector.FetchedManifestData data) {
|
| - nativeUpdateAsync(mId, data.startUrl, data.scopeUrl, data.name, data.shortName,
|
| - data.iconUrl, data.iconMurmur2Hash, data.icon, data.displayMode, data.orientation,
|
| - data.themeColor, data.backgroundColor, manifestUrl, mWebApkPackageName,
|
| - mVersionCode);
|
| + protected void updateAsync(String startUrl, String scopeUrl, String name, String shortName,
|
| + String iconUrl, String iconMurmur2Hash, Bitmap icon, int displayMode, int orientation,
|
| + long themeColor, long backgroundColor) {
|
| + int versionCode = readVersionCodeFromAndroidManifest(mWebApkPackageName);
|
| + nativeUpdateAsync(mId, startUrl, scopeUrl, name, shortName, iconUrl, iconMurmur2Hash, icon,
|
| + displayMode, orientation, themeColor, backgroundColor, mMetaData.manifestUrl,
|
| + mWebApkPackageName, versionCode);
|
| }
|
|
|
| - public void destroy() {
|
| - if (mUpgradeDetector != null) {
|
| - mUpgradeDetector.destroy();
|
| - }
|
| + /**
|
| + * Destroys {@link mUpgradeDetector}. In a separate function for the sake of tests.
|
| + */
|
| + protected void destroyUpgradeDetector() {
|
| + if (mUpgradeDetector == null) return;
|
| +
|
| + mUpgradeDetector.destroy();
|
| mUpgradeDetector = null;
|
| }
|
|
|
| @@ -147,17 +181,18 @@ public class WebApkUpdateManager implements ManifestUpgradeDetector.Callback {
|
| }
|
|
|
| /**
|
| - * Reads the WebAPK's PackageInfo from the Android Manifest.
|
| + * Reads the WebAPK's version code. Returns 0 on failure.
|
| */
|
| - private PackageInfo readPackageInfoFromAndroidManifest(String webApkPackage) {
|
| + private int readVersionCodeFromAndroidManifest(String webApkPackage) {
|
| try {
|
| PackageManager packageManager =
|
| ContextUtils.getApplicationContext().getPackageManager();
|
| - return packageManager.getPackageInfo(webApkPackage, PackageManager.GET_META_DATA);
|
| + PackageInfo packageInfo = packageManager.getPackageInfo(webApkPackage, 0);
|
| + return packageInfo.versionCode;
|
| } catch (PackageManager.NameNotFoundException e) {
|
| e.printStackTrace();
|
| }
|
| - return null;
|
| + return 0;
|
| }
|
|
|
| /**
|
| @@ -174,21 +209,28 @@ public class WebApkUpdateManager implements ManifestUpgradeDetector.Callback {
|
| }
|
|
|
| /**
|
| + * Whether there is a new version of the //chrome/android/webapk/shell_apk code.
|
| + */
|
| + private static boolean isShellApkVersionOutOfDate(WebApkMetaData metaData) {
|
| + return metaData.shellApkVersion < WebApkVersion.CURRENT_SHELL_APK_VERSION;
|
| + }
|
| +
|
| + /**
|
| * Returns whether the Web Manifest should be refetched to check whether it has been updated.
|
| * TODO: Make this method static once there is a static global clock class.
|
| * @param storage WebappDataStorage with the WebAPK's cached data.
|
| - * @param shellApkVersion Version number of //chrome/android/webapk/shell_apk code.
|
| + * @param metaData Meta data from WebAPK's Android Manifest.
|
| * @param previousUpdateSucceeded Whether the previous update attempt succeeded.
|
| * True if there has not been any update attempts.
|
| */
|
| private boolean shouldCheckIfWebManifestUpdated(
|
| - WebappDataStorage storage, int shellApkVersion, boolean previousUpdateSucceeded) {
|
| + WebappDataStorage storage, WebApkMetaData metaData, boolean previousUpdateSucceeded) {
|
| if (CommandLine.getInstance().hasSwitch(
|
| ChromeSwitches.CHECK_FOR_WEB_MANIFEST_UPDATE_ON_STARTUP)) {
|
| return true;
|
| }
|
|
|
| - if (shellApkVersion < WebApkVersion.CURRENT_SHELL_APK_VERSION) return true;
|
| + if (isShellApkVersionOutOfDate(metaData)) return true;
|
|
|
| long now = currentTimeMillis();
|
| long sinceLastCheckDurationMs = now - storage.getLastCheckForWebManifestUpdateTime();
|
|
|