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 5ac4b9d5f0987380001ce309a25499f6c15d60cc..bc15be819631876d8f7cf869701ad140b1c3526b 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,7 +6,9 @@ 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; |
@@ -25,20 +27,67 @@ 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"; |
+ /** |
+ * Gets the long value from a Bundle. The long should be terminated with 'L'. |
+ * According to https://developer.android.com/guide/topics/manifest/meta-data-element.html |
+ * numeric <meta-data> values can only be retrieved via {@link Bundle#getInt()} and |
+ * {@link Bundle#getFloat()}. We cannot use {@link Bundle#getFloat()} due to loss of precision. |
+ * Returns 0 if the value cannot 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 +121,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 +148,27 @@ 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, long iconMurmur2Hash, Bitmap iconBitmap, int displayMode, |
+ int orientation, long themeColor, long backgroundColor) { |
mFetcher.destroy(); |
mFetcher = null; |
+ FetchedManifestData fetchedData = new FetchedManifestData(); |
+ fetchedData.startUrl = startUrl; |
+ fetchedData.scopeUrl = scopeUrl; |
+ fetchedData.name = name; |
+ fetchedData.shortName = shortName; |
+ fetchedData.iconUrl = iconUrl; |
+ fetchedData.iconMurmur2Hash = iconMurmur2Hash; |
+ fetchedData.icon = iconBitmap; |
+ fetchedData.displayMode = displayMode; |
+ fetchedData.orientation = orientation; |
+ fetchedData.themeColor = themeColor; |
+ fetchedData.backgroundColor = backgroundColor; |
+ |
// 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(fetchedData)) { |
upgrade(); |
} |
@@ -114,27 +176,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; |
} |