Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3476)

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/webapps/ManifestUpgradeDetector.java

Issue 2206493002: Update WebAPK if homescreen icon changed. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Merge branch 'webapk_updater_images0' into webapk_updater_images2 Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/android/java/src/org/chromium/chrome/browser/webapps/ManifestUpgradeDetector.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/ManifestUpgradeDetector.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/ManifestUpgradeDetector.java
index 58708fd6fdcdff4ee538f08c0d1e849cb41cc057..11e529a464f9701bb9d477688d9e9cb237e644de 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/ManifestUpgradeDetector.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/ManifestUpgradeDetector.java
@@ -6,18 +6,22 @@ package org.chromium.chrome.browser.webapps;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
import android.net.Uri;
+import android.os.Bundle;
import android.text.TextUtils;
import org.chromium.base.ContextUtils;
import org.chromium.base.Log;
+import org.chromium.chrome.browser.ShortcutHelper;
import org.chromium.chrome.browser.tab.Tab;
/**
* This class checks whether the WebAPK needs to be re-installed and sends a request to re-install
* the WebAPK if it needs to be re-installed.
*/
-public class ManifestUpgradeDetector implements ManifestUpgradeDetectorFetcher.Callback {
+public class ManifestUpgradeDetector implements ManifestUpgradeDetectorFetcher.Callback,
+ ShortcutHelper.FetchHomescreenImageCallback {
/**
* The names of <meta-data> in the WebAPK's AndroidManifest.xml whose values are needed to
* determine whether a WebAPK needs to be upgraded but which are not present in
@@ -25,20 +29,70 @@ public class ManifestUpgradeDetector implements ManifestUpgradeDetectorFetcher.C
* {@linkorg.chromium.webapk.lib.runtime_library.HostBrowserLauncher}.
*/
public static final String META_DATA_START_URL = "org.chromium.webapk.shell_apk.startUrl";
+ public static final String META_DATA_ICON_URL = "org.chromium.webapk.shell_apk.iconUrl";
+ public static final String META_DATA_ICON_MURMUR2_HASH =
+ "org.chromium.webapk.shell_apk.iconMurmur2Hash";
+
+ private static final String TAG = "cr_UpgradeDetector";
+
+ /**
+ * Fetched Web Manifest data.
+ */
+ private static class FetchedManifestData {
+ public String startUrl;
+ public String scopeUrl;
+ public String name;
+ public String shortName;
+ public String iconUrl;
+
+ // Hash of untransformed icon bytes. The hash should have been taken prior to any
+ // encoding/decoding.
+ public long iconMurmur2Hash;
+
+ public Bitmap icon;
+ public int displayMode;
+ public int orientation;
+ public long themeColor;
+ public long backgroundColor;
+ }
/** The WebAPK's tab. */
private final Tab mTab;
+ /**
+ * Web Manifest data at time that the WebAPK was generated.
+ */
private WebappInfo mWebappInfo;
-
private String mStartUrl;
+ private String mIconUrl;
+ private long mIconMurmur2Hash;
/**
* Fetches the WebAPK's Web Manifest from the web.
*/
private ManifestUpgradeDetectorFetcher mFetcher;
- private static final String TAG = "cr_UpgradeDetector";
+ /**
+ * Fetched Web Manifest data.
+ */
+ private FetchedManifestData mFetchedData;
+
+ /**
+ * Gets the long value from a Bundle. The long should be terminated with 'L'. This function is
+ * more reliable than {@link Bundle#getLong()} which returns 0 if the value is below
+ * Float.MAX_VALUE. Returns 0 if the value could not be parsed.
+ */
+ private static long getLongFromBundle(Bundle bundle, String key) {
+ String value = bundle.getString(key);
+ if (value == null || !value.endsWith("L")) {
+ return 0;
+ }
+ try {
+ return Long.parseLong(value.substring(0, value.length() - 1));
+ } catch (NumberFormatException e) {
+ }
+ return 0;
+ }
public ManifestUpgradeDetector(Tab tab, WebappInfo info) {
mTab = tab;
@@ -72,10 +126,13 @@ public class ManifestUpgradeDetector implements ManifestUpgradeDetectorFetcher.C
private void getMetaDataFromAndroidManifest() {
try {
- ApplicationInfo appinfo =
+ ApplicationInfo appInfo =
ContextUtils.getApplicationContext().getPackageManager().getApplicationInfo(
mWebappInfo.webApkPackageName(), PackageManager.GET_META_DATA);
- mStartUrl = appinfo.metaData.getString(META_DATA_START_URL);
+ Bundle metaData = appInfo.metaData;
+ mStartUrl = metaData.getString(META_DATA_START_URL);
+ mIconUrl = metaData.getString(META_DATA_ICON_URL);
+ mIconMurmur2Hash = getLongFromBundle(metaData, META_DATA_ICON_MURMUR2_HASH);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
@@ -96,17 +153,61 @@ public class ManifestUpgradeDetector implements ManifestUpgradeDetectorFetcher.C
*/
@Override
public void onGotManifestData(String startUrl, String scopeUrl, String name, String shortName,
- int displayMode, int orientation, long themeColor, long backgroundColor) {
+ String iconUrl, int displayMode, int orientation, long themeColor,
+ long backgroundColor) {
mFetcher.destroy();
mFetcher = null;
+ if (TextUtils.isEmpty(iconUrl)) {
+ /**
+ * The icon URL in the fetched manifest is empty when:
+ * - The Web Manifest specified an icon at the time that the WebAPK was generated but no
+ * longer does.
+ * - The page's favicon was used as the WebAPK's homescreen icon when the WebAPK was
+ * generated and the Web Manifest still does not specify any icons.
+ * For the sake of simplicity fetch the old homescreen icon to check whether it has
+ * changed. We do not support downgrading a WebAPK from using a custom icon (specified
+ * by the Web Manifest or by the page favicon) to not using an icon at all.
+ */
+ iconUrl = mIconUrl;
+ }
+
+ mFetchedData = new FetchedManifestData();
+ mFetchedData.startUrl = startUrl;
+ mFetchedData.scopeUrl = scopeUrl;
+ mFetchedData.name = name;
+ mFetchedData.shortName = shortName;
+ mFetchedData.iconUrl = iconUrl;
+ mFetchedData.displayMode = displayMode;
+ mFetchedData.orientation = orientation;
+ mFetchedData.themeColor = themeColor;
+ mFetchedData.backgroundColor = backgroundColor;
+
+ if (!TextUtils.isEmpty(iconUrl)) {
+ fetchHomescreenImage(iconUrl, this);
+ } else {
+ onFetchedHomescreenImage(null, 0);
+ }
+ }
+
+ /**
+ * Fetches the image at {@link imageUrl} and scales it so that it can be used on the homescreen.
+ * In dedicated function for the sake of tests.
+ */
+ protected void fetchHomescreenImage(
+ String imageUrl, ShortcutHelper.FetchHomescreenImageCallback callback) {
+ ShortcutHelper.fetchHomescreenImage(mTab.getWebContents(), imageUrl, callback);
+ }
+
+ @Override
+ public void onFetchedHomescreenImage(Bitmap bitmap, long murmur2Hash) {
+ mFetchedData.icon = bitmap;
+ mFetchedData.iconMurmur2Hash = murmur2Hash;
+
// TODO(hanxi): crbug.com/627824. Validate whether the new WebappInfo is
// WebAPK-compatible.
- final WebappInfo newInfo = WebappInfo.create(mWebappInfo.id(), startUrl,
- scopeUrl, mWebappInfo.encodedIcon(), name, shortName, displayMode, orientation,
- mWebappInfo.source(), themeColor, backgroundColor, mWebappInfo.isIconGenerated(),
- mWebappInfo.webApkPackageName(), mWebappInfo.webManifestUri().toString());
- if (requireUpgrade(newInfo)) {
+
+ if (requireUpgrade(mFetchedData)) {
upgrade();
}
@@ -114,27 +215,37 @@ public class ManifestUpgradeDetector implements ManifestUpgradeDetectorFetcher.C
}
/**
- * Checks whether the WebAPK needs to be upgraded provided the new Web Manifest info.
+ * Checks whether the WebAPK needs to be upgraded provided the fetched manifest data.
*/
- private boolean requireUpgrade(WebappInfo newInfo) {
- boolean scopeMatch = mWebappInfo.scopeUri().equals(newInfo.scopeUri());
+ private boolean requireUpgrade(FetchedManifestData fetchedData) {
+ /**
+ * Only check whether icon URL differs if Chrome was able to fetch the bitmap at the icon
+ * URL (no 404).
+ */
+ if (fetchedData.icon != null) {
+ if (!TextUtils.equals(mIconUrl, fetchedData.iconUrl)
+ || mIconMurmur2Hash != fetchedData.iconMurmur2Hash) {
+ return true;
+ }
+ }
+
+ boolean scopeMatch = mWebappInfo.scopeUri().toString().equals(fetchedData.scopeUrl);
if (!scopeMatch) {
// Sometimes the scope doesn't match due to a missing "/" at the end of the scope URL.
// Print log to find such cases.
Log.d(TAG, "Needs to request update since the scope from WebappInfo (%s) doesn't match"
+ "the one fetched from Web Manifest(%s).", mWebappInfo.scopeUri().toString(),
- newInfo.scopeUri().toString());
+ fetchedData.scopeUrl);
return true;
}
- // TODO(hanxi): Add icon comparison.
- if (!TextUtils.equals(mStartUrl, newInfo.uri().toString())
- || !TextUtils.equals(mWebappInfo.shortName(), newInfo.shortName())
- || !TextUtils.equals(mWebappInfo.name(), newInfo.name())
- || mWebappInfo.backgroundColor() != newInfo.backgroundColor()
- || mWebappInfo.themeColor() != newInfo.themeColor()
- || mWebappInfo.orientation() != newInfo.orientation()
- || mWebappInfo.displayMode() != newInfo.displayMode()) {
+ if (!TextUtils.equals(mStartUrl, fetchedData.startUrl)
+ || !TextUtils.equals(mWebappInfo.shortName(), fetchedData.shortName)
+ || !TextUtils.equals(mWebappInfo.name(), fetchedData.name)
+ || mWebappInfo.backgroundColor() != fetchedData.backgroundColor
+ || mWebappInfo.themeColor() != fetchedData.themeColor
+ || mWebappInfo.orientation() != fetchedData.orientation
+ || mWebappInfo.displayMode() != fetchedData.displayMode) {
return true;
}

Powered by Google App Engine
This is Rietveld 408576698