| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.chrome.browser.webapps; | 5 package org.chromium.chrome.browser.webapps; |
| 6 | 6 |
| 7 import android.content.pm.PackageInfo; | 7 import android.content.pm.PackageInfo; |
| 8 import android.content.pm.PackageManager; | 8 import android.content.pm.PackageManager; |
| 9 import android.graphics.Bitmap; | 9 import android.graphics.Bitmap; |
| 10 import android.os.Bundle; |
| 10 | 11 |
| 11 import org.chromium.base.ContextUtils; | 12 import org.chromium.base.ContextUtils; |
| 12 import org.chromium.base.annotations.CalledByNative; | 13 import org.chromium.base.annotations.CalledByNative; |
| 13 import org.chromium.chrome.browser.tab.Tab; | 14 import org.chromium.chrome.browser.tab.Tab; |
| 15 import org.chromium.chrome.browser.util.IntentUtils; |
| 14 import org.chromium.chrome.browser.webapps.WebappRegistry.FetchWebappDataStorage
Callback; | 16 import org.chromium.chrome.browser.webapps.WebappRegistry.FetchWebappDataStorage
Callback; |
| 17 import org.chromium.webapk.lib.client.WebApkVersion; |
| 15 import org.chromium.webapk.lib.common.WebApkConstants; | 18 import org.chromium.webapk.lib.common.WebApkConstants; |
| 19 import org.chromium.webapk.lib.common.WebApkMetaDataKeys; |
| 16 | 20 |
| 17 import java.util.concurrent.TimeUnit; | 21 import java.util.concurrent.TimeUnit; |
| 18 | 22 |
| 19 /** | 23 /** |
| 20 * WebApkUpdateManager manages when to check for updates to the WebAPK's Web Man
ifest, and sends | 24 * WebApkUpdateManager manages when to check for updates to the WebAPK's Web Man
ifest, and sends |
| 21 * an update request to the WebAPK Server when an update is needed. | 25 * an update request to the WebAPK Server when an update is needed. |
| 22 */ | 26 */ |
| 23 public class WebApkUpdateManager implements ManifestUpgradeDetector.Callback { | 27 public class WebApkUpdateManager implements ManifestUpgradeDetector.Callback { |
| 24 /** Number of milliseconds between checks for whether the WebAPK's Web Manif
est has changed. */ | 28 /** Number of milliseconds between checks for whether the WebAPK's Web Manif
est has changed. */ |
| 25 static final long FULL_CHECK_UPDATE_INTERVAL = TimeUnit.DAYS.toMillis(3L); | 29 private static final long FULL_CHECK_UPDATE_INTERVAL = TimeUnit.DAYS.toMilli
s(3L); |
| 26 | 30 |
| 27 /** | 31 /** |
| 28 * Number of milliseconds to wait before re-requesting an updated WebAPK fro
m the WebAPK | 32 * Number of milliseconds to wait before re-requesting an updated WebAPK fro
m the WebAPK |
| 29 * server if the previous update attempt failed. | 33 * server if the previous update attempt failed. |
| 30 */ | 34 */ |
| 31 static final long RETRY_UPDATE_DURATION = TimeUnit.HOURS.toMillis(12L); | 35 private static final long RETRY_UPDATE_DURATION = TimeUnit.HOURS.toMillis(12
L); |
| 36 |
| 37 /** Version number of //chrome/android/webapk/shell_apk code. */ |
| 38 private int mShellApkVersion; |
| 39 |
| 40 /** Android version code of WebAPK. */ |
| 41 private int mVersionCode; |
| 42 |
| 43 /** |
| 44 * Whether a request to upgrade the WebAPK should be sent regardless of whet
her the Web Manifest |
| 45 * has changed. |
| 46 */ |
| 47 private boolean mForceUpgrade; |
| 32 | 48 |
| 33 private ManifestUpgradeDetector mUpgradeDetector; | 49 private ManifestUpgradeDetector mUpgradeDetector; |
| 34 | 50 |
| 35 /** | 51 /** |
| 36 * Checks whether the WebAPK's Web Manifest has changed. Requests an updated
WebAPK if the | 52 * Checks whether the WebAPK's Web Manifest has changed. Requests an updated
WebAPK if the |
| 37 * Web Manifest has changed. Skips the check if the check was done recently. | 53 * Web Manifest has changed. Skips the check if the check was done recently. |
| 38 * @param tab The tab of the WebAPK. | 54 * @param tab The tab of the WebAPK. |
| 39 * @param info The WebappInfo of the WebAPK. | 55 * @param info The WebappInfo of the WebAPK. |
| 40 */ | 56 */ |
| 41 public void updateIfNeeded(Tab tab, WebappInfo info) { | 57 public void updateIfNeeded(Tab tab, WebappInfo info) { |
| 42 mUpgradeDetector = new ManifestUpgradeDetector(tab, info, this); | 58 PackageInfo packageInfo = readPackageInfoFromAndroidManifest(info.webApk
PackageName()); |
| 59 if (packageInfo == null) { |
| 60 return; |
| 61 } |
| 62 |
| 63 mVersionCode = packageInfo.versionCode; |
| 64 final Bundle metadata = packageInfo.applicationInfo.metaData; |
| 65 mShellApkVersion = |
| 66 IntentUtils.safeGetInt(metadata, WebApkMetaDataKeys.SHELL_APK_VE
RSION, 0); |
| 67 |
| 68 mUpgradeDetector = new ManifestUpgradeDetector(tab, info, metadata, this
); |
| 43 | 69 |
| 44 WebappRegistry.FetchWebappDataStorageCallback callback = | 70 WebappRegistry.FetchWebappDataStorageCallback callback = |
| 45 new WebappRegistry.FetchWebappDataStorageCallback() { | 71 new WebappRegistry.FetchWebappDataStorageCallback() { |
| 46 @Override | 72 @Override |
| 47 public void onWebappDataStorageRetrieved(WebappDataStorage s
torage) { | 73 public void onWebappDataStorageRetrieved(WebappDataStorage s
torage) { |
| 74 if (forceUpgrade(storage)) { |
| 75 mForceUpgrade = true; |
| 76 } |
| 77 |
| 78 // TODO(pkotwicz|hanxi): Request upgrade if ShellAPK ver
sion changes if |
| 79 // ManifestUpgradeDetector cannot fetch the Web Manifest
. For instance, the |
| 80 // web developer may have removed the Web Manifest from
their site. |
| 81 // (http://crbug.com/639536) |
| 82 |
| 48 long sinceLastCheckDuration = System.currentTimeMillis() | 83 long sinceLastCheckDuration = System.currentTimeMillis() |
| 49 - storage.getLastCheckForWebManifestUpdateTime()
; | 84 - storage.getLastCheckForWebManifestUpdateTime()
; |
| 50 long sinceLastRequestDuration = System.currentTimeMillis
() | 85 if (sinceLastCheckDuration > FULL_CHECK_UPDATE_INTERVAL
|| mForceUpgrade) { |
| 51 - storage.getLastWebApkUpdateRequestCompletionTi
me(); | |
| 52 if (sinceLastCheckDuration > FULL_CHECK_UPDATE_INTERVAL | |
| 53 || (sinceLastRequestDuration > RETRY_UPDATE_DURA
TION | |
| 54 && !storage.getDidLastWebApkUpdateRequestSucceed
())) { | |
| 55 if (mUpgradeDetector.start()) { | 86 if (mUpgradeDetector.start()) { |
| 56 // crbug.com/636525. The timestamp of the last c
heck for updated | 87 // crbug.com/636525. The timestamp of the last c
heck for updated |
| 57 // Web Manifest should be updated after the dete
ctor finds the | 88 // Web Manifest should be updated after the dete
ctor finds the |
| 58 // Web Manifest, not when the detector is starte
d. | 89 // Web Manifest, not when the detector is starte
d. |
| 59 storage.updateTimeOfLastCheckForUpdatedWebManife
st(); | 90 storage.updateTimeOfLastCheckForUpdatedWebManife
st(); |
| 60 } | 91 } |
| 61 } | 92 } |
| 62 } | 93 } |
| 63 }; | 94 }; |
| 64 WebappRegistry.getWebappDataStorage( | 95 WebappRegistry.getWebappDataStorage( |
| 65 ContextUtils.getApplicationContext(), info.id(), callback); | 96 ContextUtils.getApplicationContext(), info.id(), callback); |
| 66 } | 97 } |
| 67 | 98 |
| 68 @Override | 99 @Override |
| 69 public void onUpgradeNeededCheckFinished(boolean needsUpgrade, WebappInfo ne
wInfo) { | 100 public void onUpgradeNeededCheckFinished(boolean needsUpgrade, WebappInfo ne
wInfo) { |
| 70 if (needsUpgrade) updateAsync(newInfo); | 101 if (needsUpgrade || mForceUpgrade) { |
| 102 updateAsync(newInfo); |
| 103 } |
| 71 if (mUpgradeDetector != null) { | 104 if (mUpgradeDetector != null) { |
| 72 mUpgradeDetector.destroy(); | 105 mUpgradeDetector.destroy(); |
| 73 } | 106 } |
| 74 mUpgradeDetector = null; | 107 mUpgradeDetector = null; |
| 75 } | 108 } |
| 76 | 109 |
| 77 /** | 110 /** |
| 78 * Sends request to WebAPK Server to update WebAPK. | 111 * Sends request to WebAPK Server to update WebAPK. |
| 79 * @param webappInfo The new fetched Web Manifest data of the WebAPK. | 112 * @param webappInfo The new fetched Web Manifest data of the WebAPK. |
| 80 */ | 113 */ |
| 81 public void updateAsync(WebappInfo webappInfo) { | 114 public void updateAsync(WebappInfo webappInfo) { |
| 82 int webApkVersion = getVersionFromMetaData(webappInfo.webApkPackageName(
)); | |
| 83 nativeUpdateAsync(webappInfo.uri().toString(), webappInfo.scopeUri().toS
tring(), | 115 nativeUpdateAsync(webappInfo.uri().toString(), webappInfo.scopeUri().toS
tring(), |
| 84 webappInfo.name(), webappInfo.shortName(), "", webappInfo.icon()
, | 116 webappInfo.name(), webappInfo.shortName(), "", webappInfo.icon()
, |
| 85 webappInfo.displayMode(), webappInfo.orientation(), webappInfo.t
hemeColor(), | 117 webappInfo.displayMode(), webappInfo.orientation(), webappInfo.t
hemeColor(), |
| 86 webappInfo.backgroundColor(), mUpgradeDetector.getManifestUrl(), | 118 webappInfo.backgroundColor(), mUpgradeDetector.getManifestUrl(), |
| 87 webappInfo.webApkPackageName(), webApkVersion); | 119 webappInfo.webApkPackageName(), mVersionCode); |
| 88 } | 120 } |
| 89 | 121 |
| 90 public void destroy() { | 122 public void destroy() { |
| 91 if (mUpgradeDetector != null) { | 123 if (mUpgradeDetector != null) { |
| 92 mUpgradeDetector.destroy(); | 124 mUpgradeDetector.destroy(); |
| 93 } | 125 } |
| 94 mUpgradeDetector = null; | 126 mUpgradeDetector = null; |
| 95 } | 127 } |
| 96 | 128 |
| 97 private static int getVersionFromMetaData(String webApkPackage) { | 129 /** |
| 130 * Reads the WebAPK's PackageInfo from the Android Manifest. |
| 131 */ |
| 132 private PackageInfo readPackageInfoFromAndroidManifest(String webApkPackage)
{ |
| 98 try { | 133 try { |
| 99 PackageManager packageManager = | 134 PackageManager packageManager = |
| 100 ContextUtils.getApplicationContext().getPackageManager(); | 135 ContextUtils.getApplicationContext().getPackageManager(); |
| 101 PackageInfo info = packageManager.getPackageInfo(webApkPackage, 0); | 136 return packageManager.getPackageInfo(webApkPackage, PackageManager.G
ET_META_DATA); |
| 102 return info.versionCode; | |
| 103 } catch (PackageManager.NameNotFoundException e) { | 137 } catch (PackageManager.NameNotFoundException e) { |
| 104 e.printStackTrace(); | 138 e.printStackTrace(); |
| 105 } | 139 } |
| 106 return 1; | 140 return null; |
| 107 } | 141 } |
| 108 | 142 |
| 109 /** | 143 /** |
| 144 * Returns whether an upgrade should be requested regardless of whether the
Web Manifest has |
| 145 * changed. |
| 146 */ |
| 147 private boolean forceUpgrade(WebappDataStorage storage) { |
| 148 long sinceLastUpdateRequestDuration = |
| 149 System.currentTimeMillis() - storage.getLastWebApkUpdateRequestC
ompletionTime(); |
| 150 if (sinceLastUpdateRequestDuration <= RETRY_UPDATE_DURATION) { |
| 151 return false; |
| 152 } |
| 153 |
| 154 return mShellApkVersion < WebApkVersion.CURRENT_SHELL_APK_VERSION |
| 155 || !storage.getDidLastWebApkUpdateRequestSucceed(); |
| 156 } |
| 157 |
| 158 /** |
| 110 * Called after either a request to update the WebAPK has been sent or the u
pdate process | 159 * Called after either a request to update the WebAPK has been sent or the u
pdate process |
| 111 * fails. | 160 * fails. |
| 112 */ | 161 */ |
| 113 @CalledByNative | 162 @CalledByNative |
| 114 private static void onBuiltWebApk(final boolean success, String webapkPackag
e) { | 163 private static void onBuiltWebApk(final boolean success, String webapkPackag
e) { |
| 115 WebappRegistry.getWebappDataStorage(ContextUtils.getApplicationContext()
, | 164 WebappRegistry.getWebappDataStorage(ContextUtils.getApplicationContext()
, |
| 116 WebApkConstants.WEBAPK_ID_PREFIX + webapkPackage, | 165 WebApkConstants.WEBAPK_ID_PREFIX + webapkPackage, |
| 117 new FetchWebappDataStorageCallback() { | 166 new FetchWebappDataStorageCallback() { |
| 118 @Override | 167 @Override |
| 119 public void onWebappDataStorageRetrieved(WebappDataStorage s
torage) { | 168 public void onWebappDataStorageRetrieved(WebappDataStorage s
torage) { |
| 120 // Update the request time and result together. It preve
nts getting a | 169 // Update the request time and result together. It preve
nts getting a |
| 121 // correct request time but a result from the previous r
equest. | 170 // correct request time but a result from the previous r
equest. |
| 122 storage.updateTimeOfLastWebApkUpdateRequestCompletion(); | 171 storage.updateTimeOfLastWebApkUpdateRequestCompletion(); |
| 123 storage.updateDidLastWebApkUpdateRequestSucceed(success)
; | 172 storage.updateDidLastWebApkUpdateRequestSucceed(success)
; |
| 124 } | 173 } |
| 125 }); | 174 }); |
| 126 } | 175 } |
| 127 | 176 |
| 128 private static native void nativeUpdateAsync(String startUrl, String scope,
String name, | 177 private static native void nativeUpdateAsync(String startUrl, String scope,
String name, |
| 129 String shortName, String iconUrl, Bitmap icon, int displayMode, int
orientation, | 178 String shortName, String iconUrl, Bitmap icon, int displayMode, int
orientation, |
| 130 long themeColor, long backgroundColor, String manifestUrl, String we
bApkPackage, | 179 long themeColor, long backgroundColor, String manifestUrl, String we
bApkPackage, |
| 131 int webApkVersion); | 180 int webApkVersion); |
| 132 } | 181 } |
| OLD | NEW |