Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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.Intent; | 7 import android.content.Intent; |
| 8 import android.graphics.Bitmap; | 8 import android.graphics.Bitmap; |
| 9 import android.graphics.Color; | 9 import android.graphics.Color; |
| 10 import android.graphics.drawable.Drawable; | 10 import android.graphics.drawable.Drawable; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 22 | 22 |
| 23 import org.chromium.base.ActivityState; | 23 import org.chromium.base.ActivityState; |
| 24 import org.chromium.base.ApiCompatibilityUtils; | 24 import org.chromium.base.ApiCompatibilityUtils; |
| 25 import org.chromium.base.ApplicationStatus; | 25 import org.chromium.base.ApplicationStatus; |
| 26 import org.chromium.base.Log; | 26 import org.chromium.base.Log; |
| 27 import org.chromium.base.StreamUtil; | 27 import org.chromium.base.StreamUtil; |
| 28 import org.chromium.base.VisibleForTesting; | 28 import org.chromium.base.VisibleForTesting; |
| 29 import org.chromium.base.metrics.RecordHistogram; | 29 import org.chromium.base.metrics.RecordHistogram; |
| 30 import org.chromium.blink_public.platform.WebDisplayMode; | 30 import org.chromium.blink_public.platform.WebDisplayMode; |
| 31 import org.chromium.chrome.R; | 31 import org.chromium.chrome.R; |
| 32 import org.chromium.chrome.browser.ShortcutHelper; | |
| 32 import org.chromium.chrome.browser.TabState; | 33 import org.chromium.chrome.browser.TabState; |
| 33 import org.chromium.chrome.browser.document.DocumentUtils; | 34 import org.chromium.chrome.browser.document.DocumentUtils; |
| 34 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; | 35 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; |
| 35 import org.chromium.chrome.browser.metrics.WebappUma; | 36 import org.chromium.chrome.browser.metrics.WebappUma; |
| 36 import org.chromium.chrome.browser.tab.EmptyTabObserver; | 37 import org.chromium.chrome.browser.tab.EmptyTabObserver; |
| 37 import org.chromium.chrome.browser.tab.Tab; | 38 import org.chromium.chrome.browser.tab.Tab; |
| 38 import org.chromium.chrome.browser.tab.TabDelegateFactory; | 39 import org.chromium.chrome.browser.tab.TabDelegateFactory; |
| 39 import org.chromium.chrome.browser.tab.TabObserver; | 40 import org.chromium.chrome.browser.tab.TabObserver; |
| 40 import org.chromium.chrome.browser.tab.TopControlsVisibilityDelegate; | 41 import org.chromium.chrome.browser.tab.TopControlsVisibilityDelegate; |
| 41 import org.chromium.chrome.browser.util.ColorUtils; | 42 import org.chromium.chrome.browser.util.ColorUtils; |
| 42 import org.chromium.chrome.browser.util.UrlUtilities; | 43 import org.chromium.chrome.browser.util.UrlUtilities; |
| 43 import org.chromium.chrome.browser.widget.ControlContainer; | 44 import org.chromium.chrome.browser.widget.ControlContainer; |
| 44 import org.chromium.components.security_state.ConnectionSecurityLevel; | 45 import org.chromium.components.security_state.ConnectionSecurityLevel; |
| 45 import org.chromium.content.browser.ScreenOrientationProvider; | 46 import org.chromium.content.browser.ScreenOrientationProvider; |
| 46 import org.chromium.content_public.browser.LoadUrlParams; | 47 import org.chromium.content_public.browser.LoadUrlParams; |
| 47 import org.chromium.net.NetworkChangeNotifier; | 48 import org.chromium.net.NetworkChangeNotifier; |
| 48 import org.chromium.ui.base.PageTransition; | 49 import org.chromium.ui.base.PageTransition; |
| 50 import org.chromium.webapk.lib.common.WebApkConstants; | |
| 49 | 51 |
| 50 import java.io.File; | 52 import java.io.File; |
| 51 import java.io.FileNotFoundException; | 53 import java.io.FileNotFoundException; |
| 52 import java.io.FileOutputStream; | 54 import java.io.FileOutputStream; |
| 53 import java.io.IOException; | 55 import java.io.IOException; |
| 54 import java.util.concurrent.TimeUnit; | 56 import java.util.concurrent.TimeUnit; |
| 55 | 57 |
| 56 /** | 58 /** |
| 57 * Displays a webapp in a nearly UI-less Chrome (InfoBars still appear). | 59 * Displays a webapp in a nearly UI-less Chrome (InfoBars still appear). |
| 58 */ | 60 */ |
| 59 public class WebappActivity extends FullScreenActivity { | 61 public class WebappActivity extends FullScreenActivity { |
| 60 public static final String WEBAPP_SCHEME = "webapp"; | 62 public static final String WEBAPP_SCHEME = "webapp"; |
| 61 | 63 |
| 62 private static final String TAG = "WebappActivity"; | 64 private static final String TAG = "WebappActivity"; |
| 63 private static final long MS_BEFORE_NAVIGATING_BACK_FROM_INTERSTITIAL = 1000 ; | 65 private static final long MS_BEFORE_NAVIGATING_BACK_FROM_INTERSTITIAL = 1000 ; |
| 64 | 66 |
| 65 private final WebappInfo mWebappInfo; | |
| 66 private final WebappDirectoryManager mDirectoryManager; | 67 private final WebappDirectoryManager mDirectoryManager; |
| 67 | 68 |
| 69 private WebappInfo mWebappInfo; | |
| 70 private boolean mIsWebApk; | |
| 71 | |
| 68 private boolean mOldWebappCleanupStarted; | 72 private boolean mOldWebappCleanupStarted; |
| 69 | 73 |
| 70 private ViewGroup mSplashScreen; | 74 private ViewGroup mSplashScreen; |
| 71 private WebappUrlBar mUrlBar; | 75 private WebappUrlBar mUrlBar; |
| 72 | 76 |
| 73 private boolean mIsInitialized; | 77 private boolean mIsInitialized; |
| 74 private Integer mBrandColor; | 78 private Integer mBrandColor; |
| 75 | 79 |
| 76 private WebappUma mWebappUma; | 80 private WebappUma mWebappUma; |
| 77 | 81 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 91 @Override | 95 @Override |
| 92 protected void onNewIntent(Intent intent) { | 96 protected void onNewIntent(Intent intent) { |
| 93 if (intent == null) return; | 97 if (intent == null) return; |
| 94 super.onNewIntent(intent); | 98 super.onNewIntent(intent); |
| 95 | 99 |
| 96 WebappInfo newWebappInfo = WebappInfo.create(intent); | 100 WebappInfo newWebappInfo = WebappInfo.create(intent); |
| 97 if (newWebappInfo == null) { | 101 if (newWebappInfo == null) { |
| 98 Log.e(TAG, "Failed to parse new Intent: " + intent); | 102 Log.e(TAG, "Failed to parse new Intent: " + intent); |
| 99 finish(); | 103 finish(); |
| 100 } else if (!TextUtils.equals(mWebappInfo.id(), newWebappInfo.id())) { | 104 } else if (!TextUtils.equals(mWebappInfo.id(), newWebappInfo.id())) { |
| 101 mWebappInfo.copy(newWebappInfo); | 105 mWebappInfo = newWebappInfo; |
| 106 mIsWebApk = isWebApk(mWebappInfo); | |
| 102 resetSavedInstanceState(); | 107 resetSavedInstanceState(); |
| 103 if (mIsInitialized) initializeUI(null); | 108 if (mIsInitialized) initializeUI(null); |
| 104 } | 109 } |
| 105 } | 110 } |
| 106 | 111 |
| 107 private void initializeUI(Bundle savedInstanceState) { | 112 private void initializeUI(Bundle savedInstanceState) { |
| 108 // We do not load URL when restoring from saved instance states. | 113 // We do not load URL when restoring from saved instance states. |
| 109 if (savedInstanceState == null && mWebappInfo.isInitialized()) { | 114 if (savedInstanceState == null && mWebappInfo.isInitialized()) { |
| 110 if (TextUtils.isEmpty(getActivityTab().getUrl())) { | 115 if (TextUtils.isEmpty(getActivityTab().getUrl())) { |
| 111 getActivityTab().loadUrl(new LoadUrlParams( | 116 getActivityTab().loadUrl(new LoadUrlParams( |
| 112 mWebappInfo.uri().toString(), PageTransition.AUTO_TOPLEV EL)); | 117 mWebappInfo.uri().toString(), PageTransition.AUTO_TOPLEV EL)); |
| 113 } | 118 } |
| 114 } else { | 119 } else { |
| 115 if (NetworkChangeNotifier.isOnline()) getActivityTab().reloadIgnorin gCache(); | 120 if (NetworkChangeNotifier.isOnline()) getActivityTab().reloadIgnorin gCache(); |
| 116 } | 121 } |
| 117 | 122 |
| 118 getActivityTab().addObserver(createTabObserver()); | 123 getActivityTab().addObserver(createTabObserver()); |
| 119 getActivityTab().getTabWebContentsDelegateAndroid().setDisplayMode( | 124 getActivityTab().getTabWebContentsDelegateAndroid().setDisplayMode( |
| 120 WebDisplayMode.Standalone); | 125 WebDisplayMode.Standalone); |
| 121 } | 126 } |
| 122 | 127 |
| 123 @Override | 128 @Override |
| 124 public void preInflationStartup() { | 129 public void preInflationStartup() { |
| 125 WebappInfo info = WebappInfo.create(getIntent()); | 130 WebappInfo info = WebappInfo.create(getIntent()); |
| 126 if (info != null) mWebappInfo.copy(info); | 131 if (info != null) { |
| 132 mWebappInfo = info; | |
| 133 mIsWebApk = isWebApk(info); | |
| 134 } | |
| 127 | 135 |
| 128 ScreenOrientationProvider.lockOrientation((byte) mWebappInfo.orientation (), this); | 136 ScreenOrientationProvider.lockOrientation((byte) mWebappInfo.orientation (), this); |
| 129 super.preInflationStartup(); | 137 super.preInflationStartup(); |
| 130 } | 138 } |
| 131 | 139 |
| 132 @Override | 140 @Override |
| 133 public void finishNativeInitialization() { | 141 public void finishNativeInitialization() { |
| 134 if (!mWebappInfo.isInitialized()) finish(); | 142 if (!mWebappInfo.isInitialized()) finish(); |
| 135 super.finishNativeInitialization(); | 143 super.finishNativeInitialization(); |
| 136 initializeUI(getSavedInstanceState()); | 144 initializeUI(getSavedInstanceState()); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 201 | 209 |
| 202 // Kick off the old web app cleanup (if we haven't already) now that we have queued the | 210 // Kick off the old web app cleanup (if we haven't already) now that we have queued the |
| 203 // current web app's storage to be opened. | 211 // current web app's storage to be opened. |
| 204 if (!mOldWebappCleanupStarted) { | 212 if (!mOldWebappCleanupStarted) { |
| 205 WebappRegistry.unregisterOldWebapps(this, System.currentTimeMillis() ); | 213 WebappRegistry.unregisterOldWebapps(this, System.currentTimeMillis() ); |
| 206 mOldWebappCleanupStarted = true; | 214 mOldWebappCleanupStarted = true; |
| 207 } | 215 } |
| 208 } | 216 } |
| 209 | 217 |
| 210 @Override | 218 @Override |
| 219 public void onPause() { | |
| 220 super.onPause(); | |
| 221 // TODO(hanxi): Change onResumeWithNative behaviour so this isn't necess ary. | |
| 222 if (mIsWebApk) { | |
| 223 getIntent().removeExtra(ShortcutHelper.EXTRA_URL); | |
| 224 } | |
| 225 } | |
| 226 | |
| 227 @Override | |
| 211 public void onResumeWithNative() { | 228 public void onResumeWithNative() { |
| 212 super.onResumeWithNative(); | 229 super.onResumeWithNative(); |
| 230 if (getIntent() != null && mIsWebApk) { | |
|
pkotwicz
2016/05/18 23:00:17
- Is this change alone sufficient or does there al
Xi Han
2016/05/19 18:31:49
This makes WebAPK can load different URL in the In
| |
| 231 // We could bring a WebAPK hosted WebappActivity to foreground and n avigate it to a | |
| 232 // different URL. For example, WebAPK "foo" is launched and navigate s to | |
| 233 // "www.foo.com/foo". A notification comes in with a link "www.foo.c om/bar" with falls | |
| 234 // in the scope of WebAPK "foo". After clicking the notification, We bAPK "foo" will be | |
| 235 // brought to foreground and navigates to "www.foo.com/bar". | |
| 236 // The extra {@link ShortcutHelper.EXTRA_URL} provides the URL that the WebAPK will | |
| 237 // navigate to. | |
| 238 String overrideUrl = getIntent().getStringExtra(ShortcutHelper.EXTRA _URL); | |
| 239 if (overrideUrl != null && getActivityTab() != null | |
| 240 && !overrideUrl.equals(getActivityTab().getUrl())) { | |
| 241 getActivityTab().loadUrl( | |
| 242 new LoadUrlParams(overrideUrl, PageTransition.AUTO_TOPLE VEL)); | |
| 243 } | |
| 244 } | |
| 213 mWebappUma.commitMetrics(); | 245 mWebappUma.commitMetrics(); |
| 214 } | 246 } |
| 215 | 247 |
| 216 @Override | 248 @Override |
| 217 protected int getControlContainerLayoutId() { | 249 protected int getControlContainerLayoutId() { |
| 218 return R.layout.webapp_control_container; | 250 return R.layout.webapp_control_container; |
| 219 } | 251 } |
| 220 | 252 |
| 221 @Override | 253 @Override |
| 222 public void postInflationStartup() { | 254 public void postInflationStartup() { |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 246 contentView.addView(mSplashScreen); | 278 contentView.addView(mSplashScreen); |
| 247 | 279 |
| 248 mWebappUma.splashscreenVisible(); | 280 mWebappUma.splashscreenVisible(); |
| 249 mWebappUma.recordSplashscreenBackgroundColor(mWebappInfo.hasValidBackgro undColor() | 281 mWebappUma.recordSplashscreenBackgroundColor(mWebappInfo.hasValidBackgro undColor() |
| 250 ? WebappUma.SPLASHSCREEN_COLOR_STATUS_CUSTOM | 282 ? WebappUma.SPLASHSCREEN_COLOR_STATUS_CUSTOM |
| 251 : WebappUma.SPLASHSCREEN_COLOR_STATUS_DEFAULT); | 283 : WebappUma.SPLASHSCREEN_COLOR_STATUS_DEFAULT); |
| 252 mWebappUma.recordSplashscreenThemeColor(mWebappInfo.hasValidThemeColor() | 284 mWebappUma.recordSplashscreenThemeColor(mWebappInfo.hasValidThemeColor() |
| 253 ? WebappUma.SPLASHSCREEN_COLOR_STATUS_CUSTOM | 285 ? WebappUma.SPLASHSCREEN_COLOR_STATUS_CUSTOM |
| 254 : WebappUma.SPLASHSCREEN_COLOR_STATUS_DEFAULT); | 286 : WebappUma.SPLASHSCREEN_COLOR_STATUS_DEFAULT); |
| 255 | 287 |
| 288 if (mIsWebApk) { | |
|
pkotwicz
2016/05/18 23:00:17
Can we introduce this change in a followup CL?
Xi Han
2016/05/19 18:31:49
I intent to add this here, since it is a bug fix.
| |
| 289 // TODO(hanxi): Removes this check when WebAPKs are registered in We bappRegistry. | |
| 290 initializeSplashScreenWidgets(backgroundColor, null); | |
| 291 return; | |
| 292 } | |
| 293 | |
| 256 final Intent intent = getIntent(); | 294 final Intent intent = getIntent(); |
| 257 WebappRegistry.getWebappDataStorage(this, mWebappInfo.id(), | 295 WebappRegistry.getWebappDataStorage(this, mWebappInfo.id(), |
| 258 new WebappRegistry.FetchWebappDataStorageCallback() { | 296 new WebappRegistry.FetchWebappDataStorageCallback() { |
| 259 @Override | 297 @Override |
| 260 public void onWebappDataStorageRetrieved(WebappDataStorage s torage) { | 298 public void onWebappDataStorageRetrieved(WebappDataStorage s torage) { |
| 261 if (storage == null) return; | 299 if (storage == null) return; |
| 262 | 300 |
| 263 // The information in the WebappDataStorage may have bee n purged by the | 301 // The information in the WebappDataStorage may have bee n purged by the |
| 264 // user clearing their history or not launching the web app recently. | 302 // user clearing their history or not launching the web app recently. |
| 265 // Restore the data if necessary from the intent. | 303 // Restore the data if necessary from the intent. |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 594 || securityLevel == ConnectionSecurityLevel.SECURITY_WARNING; | 632 || securityLevel == ConnectionSecurityLevel.SECURITY_WARNING; |
| 595 return visible; | 633 return visible; |
| 596 } | 634 } |
| 597 | 635 |
| 598 // We're temporarily disable CS on webapp since there are some issues. (http ://crbug.com/471950) | 636 // We're temporarily disable CS on webapp since there are some issues. (http ://crbug.com/471950) |
| 599 // TODO(changwan): re-enable it once the issues are resolved. | 637 // TODO(changwan): re-enable it once the issues are resolved. |
| 600 @Override | 638 @Override |
| 601 protected boolean isContextualSearchAllowed() { | 639 protected boolean isContextualSearchAllowed() { |
| 602 return false; | 640 return false; |
| 603 } | 641 } |
| 642 | |
| 643 /** | |
| 644 * Returns whether {@link info} refers to a WebAPK. | |
| 645 * Assumes that WebappLauncherActivity does not create WebappActivities for APKs whose package | |
| 646 * starts with WEBAPK_PACKAGE_PREFIX but which are not WebAPKs (due to an in correct singature). | |
| 647 * @param info | |
| 648 */ | |
| 649 private static boolean isWebApk(WebappInfo info) { | |
| 650 return info.packageName().startsWith(WebApkConstants.WEBAPK_PACKAGE_PREF IX); | |
|
pkotwicz
2016/05/18 23:00:17
Can we fully trust WebappLauncherActivity? So chan
Xi Han
2016/05/19 18:31:49
Yes, it is better to have this check first.
pkotwicz
2016/05/19 21:36:35
I was actually suggesting removing the prefix chec
Xi Han
2016/05/20 14:45:41
Done.
| |
| 651 } | |
| 604 } | 652 } |
| OLD | NEW |