| 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..3b3efda710ec17764bc66f490af9e8eed63d49c7
|
| --- /dev/null
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/ManifestUpgradeDetector.java
|
| @@ -0,0 +1,184 @@
|
| +// 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 android.text.TextUtils;
|
| +
|
| +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 {
|
| + /**
|
| + * 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;
|
| +
|
| + /**
|
| + * A flag for whether metadata is set via {@link set*ForTesting()}, rather than set
|
| + * from WebAPK's AndroidManifest.xml.
|
| + */
|
| + private boolean mOverrideMetadataForTesting = false;
|
| +
|
| + private static final String TAG = "cr_UpgradeDetector";
|
| +
|
| + public ManifestUpgradeDetector(Tab tab, WebappInfo info) {
|
| + mTab = tab;
|
| + mWebappInfo = info;
|
| + }
|
| +
|
| + @VisibleForTesting
|
| + public void setOverrideMetadataForTesting(boolean overrideMetadataForTesting) {
|
| + mOverrideMetadataForTesting = overrideMetadataForTesting;
|
| + }
|
| +
|
| + @VisibleForTesting
|
| + public void setStartUrlForTesting(String startUrl) {
|
| + 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 (mOverrideMetadataForTesting) {
|
| + // The metadata are set via {@link set*ForTesting()}.
|
| + 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)) {
|
| + upgrade();
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Checks whether the WebAPK needs to be upgraded provided the new Web Manifest info.
|
| + */
|
| + protected boolean requireUpgrade(WebappInfo newInfo) {
|
| + 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 (!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()) {
|
| + 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);
|
| +}
|
|
|