Chromium Code Reviews| 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 |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..d99e4e30727f5338901425976e0ed866b9787840 |
| --- /dev/null |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/ManifestUpgradeDetector.java |
| @@ -0,0 +1,176 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +package org.chromium.chrome.browser.webapps; |
| + |
| +import android.content.pm.ApplicationInfo; |
| +import android.content.pm.PackageManager; |
| +import android.net.Uri; |
| + |
| +import org.chromium.base.CommandLine; |
| +import org.chromium.base.ContextUtils; |
| +import org.chromium.base.Log; |
| +import org.chromium.base.VisibleForTesting; |
| +import org.chromium.base.annotations.CalledByNative; |
| +import org.chromium.chrome.browser.tab.EmptyTabObserver; |
| +import org.chromium.chrome.browser.tab.Tab; |
| +import org.chromium.content_public.browser.WebContents; |
| + |
| +/** |
| + * This class interacts with C++ to detect whether resources in web manifest of a WebAPK have been |
| + * updated. |
| + */ |
| +public class ManifestUpgradeDetector extends EmptyTabObserver { |
| + @VisibleForTesting |
| + public static final String SWITCH_DO_NOT_USE_META_DATA_FROM_WEBAPK_FOR_TESTING = |
|
pkotwicz
2016/07/25 17:35:53
Nit: Remove "switch-" from switch
Xi Han
2016/07/25 20:01:37
Done.
|
| + "switch-do-not-use-meta-data-from-webapk-for-testing"; |
| + /** |
| + * 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 |
| + * {@link WebappInfo}. The names must stay in sync with |
| + * {@linkorg.chromium.webapk.lib.runtime_library.HostBrowserLauncher}. |
| + */ |
| + private static final String META_DATA_START_URL = "startUrl"; |
| + |
| + /** Pointer to the native side ManifestUpgradeDetector. */ |
| + private long mNativePointer; |
| + |
| + /** The tab that is being observed. */ |
| + private final Tab mTab; |
| + |
| + private WebappInfo mWebappInfo; |
| + private String mStartUrl; |
| + |
| + private static final String TAG = "cr_UpgradeDetector"; |
| + |
| + public ManifestUpgradeDetector(Tab tab, WebappInfo info) { |
| + mTab = tab; |
| + mWebappInfo = info; |
| + } |
| + |
| + @VisibleForTesting |
| + public void setMetadataForTesting(String startUrl) { |
|
Yaron
2016/07/25 15:55:02
If you rename this to: overrideMetadataForTesting
Xi Han
2016/07/25 20:01:37
Done.
Yaron
2016/07/25 22:29:06
I meant that you can collapse these two into one f
Xi Han
2016/07/27 00:38:15
Acknowledged.
|
| + mStartUrl = startUrl; |
| + } |
| + |
| + /** |
| + * Starts fetching the web manifest resources. |
| + */ |
| + public void start() { |
| + if (mWebappInfo.webManifestUri() == null |
| + || mWebappInfo.webManifestUri().equals(Uri.EMPTY)) { |
| + return; |
| + } |
| + |
| + if (mNativePointer != 0) return; |
| + |
| + getMetaDataFromAndroidManifest(); |
| + mNativePointer = nativeInitialize(mTab.getWebContents(), |
| + mWebappInfo.scopeUri().toString(), mWebappInfo.webManifestUri().toString()); |
| + |
| + mTab.addObserver(this); |
| + nativeStart(mNativePointer); |
| + } |
| + |
| + private void getMetaDataFromAndroidManifest() { |
| + if (CommandLine.getInstance().hasSwitch( |
| + SWITCH_DO_NOT_USE_META_DATA_FROM_WEBAPK_FOR_TESTING)) { |
| + // The metadata are set via {@link setMetadataForTesting()}. |
| + return; |
| + } |
| + try { |
| + ApplicationInfo appinfo = |
| + ContextUtils.getApplicationContext().getPackageManager().getApplicationInfo( |
| + mWebappInfo.webApkPackageName(), PackageManager.GET_META_DATA); |
| + mStartUrl = appinfo.metaData.getString(META_DATA_START_URL); |
| + } catch (PackageManager.NameNotFoundException e) { |
| + e.printStackTrace(); |
| + } |
| + } |
| + |
| + /** |
| + * Puts the object in a state where it is safe to be destroyed. |
| + */ |
| + public void destroy() { |
| + if (mNativePointer != 0) { |
| + nativeDestroy(mNativePointer); |
| + } |
| + mNativePointer = 0; |
| + } |
| + |
| + @Override |
| + public void onWebContentsSwapped(Tab tab, boolean didStartLoad, |
| + boolean didFinishLoad) { |
| + updatePointers(); |
| + } |
| + |
| + @Override |
| + public void onContentChanged(Tab tab) { |
| + updatePointers(); |
| + } |
| + |
| + /** |
| + * Updates which WebContents the native ManifestUpgradeDetector is monitoring. |
| + */ |
| + private void updatePointers() { |
| + nativeReplaceWebContents(mNativePointer, mTab.getWebContents()); |
| + } |
| + |
| + /** |
| + * Called when the updated Web Manifest has been fetched. |
| + */ |
| + @CalledByNative |
| + private void onDataAvailable(String startUrl, String scope, String name, String shortName, |
| + int displayMode, int orientation, long themeColor, long backgroundColor) { |
| + mTab.removeObserver(this); |
| + destroy(); |
| + |
| + // TODO(hanxi): crbug.com/627824. Validate whether the new WebappInfo is |
| + // WebAPK-compatible. |
| + final WebappInfo newInfo = WebappInfo.create(mWebappInfo.id(), startUrl, |
| + scope, mWebappInfo.encodedIcon(), name, shortName, displayMode, orientation, |
| + mWebappInfo.source(), themeColor, backgroundColor, mWebappInfo.isIconGenerated(), |
| + mWebappInfo.webApkPackageName(), mWebappInfo.webManifestUri().toString()); |
| + if (requireUpgrade(newInfo, startUrl)) { |
| + upgrade(); |
| + } |
| + } |
| + |
| + /** |
| + * Checks whether the WebAPK needs to be upgraded provided the new Web Manifest info. |
| + */ |
| + protected boolean requireUpgrade(WebappInfo newInfo, String startUrl) { |
| + boolean scopeMatch = mWebappInfo.scopeUri().equals(newInfo.scopeUri()); |
| + 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()); |
| + return true; |
| + } |
| + |
| + // TODO(hanxi): Add icon comparison. |
| + if (!mStartUrl.equals(startUrl) |
| + || !mWebappInfo.shortName().equals(newInfo.shortName()) |
|
Yaron
2016/07/25 15:55:01
If these can be null (first-glance seems no, but n
Yaron
2016/07/25 15:55:02
we should consider adding a helper method to WebAp
Xi Han
2016/07/25 20:01:37
It can't be null, will fallback to "". But I am ok
Xi Han
2016/07/25 20:01:37
Acknowledged.
|
| + || !mWebappInfo.name().equals(newInfo.name()) |
| + || mWebappInfo.backgroundColor() != newInfo.backgroundColor() |
| + || mWebappInfo.themeColor() != newInfo.themeColor() |
| + || mWebappInfo.orientation() != newInfo.orientation() |
| + || mWebappInfo.displayMode() != newInfo.displayMode()) { |
| + return true; |
| + } |
| + |
| + return false; |
| + } |
| + |
| + private void upgrade() {} |
| + |
| + private native long nativeInitialize(WebContents webContents, String scope, |
| + String webManifestUrl); |
| + private native void nativeReplaceWebContents(long nativeManifestUpgradeDetector, |
| + WebContents webContents); |
| + private native void nativeDestroy(long nativeManifestUpgradeDetector); |
| + private native void nativeStart(long nativeManifestUpgradeDetector); |
| +} |