Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(599)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java

Issue 2636833003: Support "display": "fullscreen" for sites added to the home screen. (Closed)
Patch Set: disable html5 fullscreen Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/android/java/src/org/chromium/chrome/browser/webapps/FullScreenActivity.java ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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;
11 import android.net.Uri; 11 import android.net.Uri;
12 import android.os.Build;
12 import android.os.Bundle; 13 import android.os.Bundle;
13 import android.os.StrictMode; 14 import android.os.StrictMode;
14 import android.os.SystemClock; 15 import android.os.SystemClock;
15 import android.text.TextUtils; 16 import android.text.TextUtils;
16 import android.view.LayoutInflater; 17 import android.view.LayoutInflater;
17 import android.view.View; 18 import android.view.View;
19 import android.view.View.OnSystemUiVisibilityChangeListener;
18 import android.view.ViewGroup; 20 import android.view.ViewGroup;
19 import android.widget.FrameLayout; 21 import android.widget.FrameLayout;
20 import android.widget.ImageView; 22 import android.widget.ImageView;
21 import android.widget.TextView; 23 import android.widget.TextView;
22 24
23 import org.chromium.base.ActivityState; 25 import org.chromium.base.ActivityState;
24 import org.chromium.base.ApiCompatibilityUtils; 26 import org.chromium.base.ApiCompatibilityUtils;
25 import org.chromium.base.ApplicationStatus; 27 import org.chromium.base.ApplicationStatus;
26 import org.chromium.base.Log; 28 import org.chromium.base.Log;
27 import org.chromium.base.VisibleForTesting; 29 import org.chromium.base.VisibleForTesting;
28 import org.chromium.base.metrics.RecordHistogram; 30 import org.chromium.base.metrics.RecordHistogram;
29 import org.chromium.blink_public.platform.WebDisplayMode; 31 import org.chromium.blink_public.platform.WebDisplayMode;
30 import org.chromium.chrome.R; 32 import org.chromium.chrome.R;
31 import org.chromium.chrome.browser.TabState; 33 import org.chromium.chrome.browser.TabState;
32 import org.chromium.chrome.browser.document.DocumentUtils; 34 import org.chromium.chrome.browser.document.DocumentUtils;
35 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
33 import org.chromium.chrome.browser.metrics.WebappUma; 36 import org.chromium.chrome.browser.metrics.WebappUma;
34 import org.chromium.chrome.browser.tab.EmptyTabObserver; 37 import org.chromium.chrome.browser.tab.EmptyTabObserver;
35 import org.chromium.chrome.browser.tab.Tab; 38 import org.chromium.chrome.browser.tab.Tab;
36 import org.chromium.chrome.browser.tab.TabDelegateFactory; 39 import org.chromium.chrome.browser.tab.TabDelegateFactory;
37 import org.chromium.chrome.browser.tab.TabObserver; 40 import org.chromium.chrome.browser.tab.TabObserver;
38 import org.chromium.chrome.browser.util.ColorUtils; 41 import org.chromium.chrome.browser.util.ColorUtils;
39 import org.chromium.chrome.browser.util.UrlUtilities; 42 import org.chromium.chrome.browser.util.UrlUtilities;
40 import org.chromium.content.browser.ScreenOrientationProvider; 43 import org.chromium.content.browser.ScreenOrientationProvider;
41 import org.chromium.content_public.browser.LoadUrlParams; 44 import org.chromium.content_public.browser.LoadUrlParams;
42 import org.chromium.net.NetworkChangeNotifier; 45 import org.chromium.net.NetworkChangeNotifier;
43 import org.chromium.ui.base.PageTransition; 46 import org.chromium.ui.base.PageTransition;
44 47
45 import java.io.File; 48 import java.io.File;
46 import java.util.concurrent.TimeUnit; 49 import java.util.concurrent.TimeUnit;
47 50
48 /** 51 /**
49 * Displays a webapp in a nearly UI-less Chrome (InfoBars still appear). 52 * Displays a webapp in a nearly UI-less Chrome (InfoBars still appear).
50 */ 53 */
51 public class WebappActivity extends FullScreenActivity { 54 public class WebappActivity extends FullScreenActivity {
52 public static final String WEBAPP_SCHEME = "webapp"; 55 public static final String WEBAPP_SCHEME = "webapp";
53 56
54 private static final String TAG = "WebappActivity"; 57 private static final String TAG = "WebappActivity";
55 private static final long MS_BEFORE_NAVIGATING_BACK_FROM_INTERSTITIAL = 1000 ; 58 private static final long MS_BEFORE_NAVIGATING_BACK_FROM_INTERSTITIAL = 1000 ;
56 59
60 private static final int ENTER_IMMERSIVE_MODE_DELAY_MILLIS = 300;
61 private static final int RESTORE_IMMERSIVE_MODE_DELAY_MILLIS = 3000;
62 private static final int IMMERSIVE_MODE_UI_FLAGS = View.SYSTEM_UI_FLAG_LAYOU T_STABLE
63 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
64 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
65 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
66 | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
67 | View.SYSTEM_UI_FLAG_LOW_PROFILE
68 | View.SYSTEM_UI_FLAG_IMMERSIVE;
69
57 private final WebappDirectoryManager mDirectoryManager; 70 private final WebappDirectoryManager mDirectoryManager;
58 71
59 protected WebappInfo mWebappInfo; 72 protected WebappInfo mWebappInfo;
60 73
61 private ViewGroup mSplashScreen; 74 private ViewGroup mSplashScreen;
62 private WebappUrlBar mUrlBar; 75 private WebappUrlBar mUrlBar;
63 76
64 private boolean mIsInitialized; 77 private boolean mIsInitialized;
65 private Integer mBrandColor; 78 private Integer mBrandColor;
66 79
67 private WebappUma mWebappUma; 80 private WebappUma mWebappUma;
68 81
69 private Bitmap mLargestFavicon; 82 private Bitmap mLargestFavicon;
70 83
84 private Runnable mSetImmersiveRunnable;
85
71 /** 86 /**
72 * Construct all the variables that shouldn't change. We do it here both to clarify when the 87 * Construct all the variables that shouldn't change. We do it here both to clarify when the
73 * objects are created and to ensure that they exist throughout the parallel ized initialization 88 * objects are created and to ensure that they exist throughout the parallel ized initialization
74 * of the WebappActivity. 89 * of the WebappActivity.
75 */ 90 */
76 public WebappActivity() { 91 public WebappActivity() {
77 mWebappInfo = createWebappInfo(null); 92 mWebappInfo = createWebappInfo(null);
78 mDirectoryManager = new WebappDirectoryManager(); 93 mDirectoryManager = new WebappDirectoryManager();
79 mWebappUma = new WebappUma(); 94 mWebappUma = new WebappUma();
80 } 95 }
81 96
82 @Override 97 @Override
83 protected void onNewIntent(Intent intent) { 98 protected void onNewIntent(Intent intent) {
84 if (intent == null) return; 99 if (intent == null) return;
85 super.onNewIntent(intent); 100 super.onNewIntent(intent);
86 101
87 WebappInfo newWebappInfo = createWebappInfo(intent); 102 WebappInfo newWebappInfo = createWebappInfo(intent);
88 if (newWebappInfo == null) { 103 if (newWebappInfo == null) {
89 Log.e(TAG, "Failed to parse new Intent: " + intent); 104 Log.e(TAG, "Failed to parse new Intent: " + intent);
90 finish(); 105 finish();
91 } else if (!TextUtils.equals(mWebappInfo.id(), newWebappInfo.id())) { 106 } else if (!TextUtils.equals(mWebappInfo.id(), newWebappInfo.id())) {
92 mWebappInfo = newWebappInfo; 107 mWebappInfo = newWebappInfo;
93 resetSavedInstanceState(); 108 resetSavedInstanceState();
94 if (mIsInitialized) initializeUI(null); 109 if (mIsInitialized) initializeUI(null);
95 // TODO(dominickn): send the web app into fullscreen if mDisplayMode is
96 // WebDisplayMode.Fullscreen. See crbug.com/581522
97 } 110 }
98 } 111 }
99 112
100 protected boolean isInitialized() { 113 protected boolean isInitialized() {
101 return mIsInitialized; 114 return mIsInitialized;
102 } 115 }
103 116
104 protected WebappInfo createWebappInfo(Intent intent) { 117 protected WebappInfo createWebappInfo(Intent intent) {
105 return (intent == null) ? WebappInfo.createEmpty() : WebappInfo.create(i ntent); 118 return (intent == null) ? WebappInfo.createEmpty() : WebappInfo.create(i ntent);
106 } 119 }
107 120
108 private void initializeUI(Bundle savedInstanceState) { 121 private void initializeUI(Bundle savedInstanceState) {
109 // We do not load URL when restoring from saved instance states. 122 // We do not load URL when restoring from saved instance states.
110 if (savedInstanceState == null && mWebappInfo.isInitialized()) { 123 if (savedInstanceState == null && mWebappInfo.isInitialized()) {
111 if (TextUtils.isEmpty(getActivityTab().getUrl())) { 124 if (TextUtils.isEmpty(getActivityTab().getUrl())) {
112 getActivityTab().loadUrl(new LoadUrlParams( 125 getActivityTab().loadUrl(new LoadUrlParams(
113 mWebappInfo.uri().toString(), PageTransition.AUTO_TOPLEV EL)); 126 mWebappInfo.uri().toString(), PageTransition.AUTO_TOPLEV EL));
114 } 127 }
115 } else { 128 } else {
116 if (NetworkChangeNotifier.isOnline()) getActivityTab().reloadIgnorin gCache(); 129 if (NetworkChangeNotifier.isOnline()) getActivityTab().reloadIgnorin gCache();
117 } 130 }
118 131
119 getActivityTab().addObserver(createTabObserver()); 132 getActivityTab().addObserver(createTabObserver());
120 getActivityTab().getTabWebContentsDelegateAndroid().setDisplayMode( 133 getActivityTab().getTabWebContentsDelegateAndroid().setDisplayMode(
121 WebDisplayMode.Standalone); 134 mWebappInfo.displayMode());
122 // TODO(dominickn): send the web app into fullscreen if mDisplayMode is 135 if (mWebappInfo.displayMode() == WebDisplayMode.Fullscreen) {
123 // WebDisplayMode.Fullscreen. See crbug.com/581522 136 enterImmersiveMode();
137 }
124 } 138 }
125 139
126 @Override 140 @Override
127 public void preInflationStartup() { 141 public void preInflationStartup() {
128 WebappInfo info = createWebappInfo(getIntent()); 142 WebappInfo info = createWebappInfo(getIntent());
129 143
130 String id = ""; 144 String id = "";
131 if (info != null) { 145 if (info != null) {
132 mWebappInfo = info; 146 mWebappInfo = info;
133 id = info.id(); 147 id = info.id();
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 long time = SystemClock.elapsedRealtime(); 210 long time = SystemClock.elapsedRealtime();
197 TabState.saveState(tabFile, getActivityTab().getState(), false); 211 TabState.saveState(tabFile, getActivityTab().getState(), false);
198 RecordHistogram.recordTimesHistogram("Android.StrictMode.WebappSaveS tate", 212 RecordHistogram.recordTimesHistogram("Android.StrictMode.WebappSaveS tate",
199 SystemClock.elapsedRealtime() - time, TimeUnit.MILLISECONDS) ; 213 SystemClock.elapsedRealtime() - time, TimeUnit.MILLISECONDS) ;
200 } finally { 214 } finally {
201 StrictMode.setThreadPolicy(oldPolicy); 215 StrictMode.setThreadPolicy(oldPolicy);
202 } 216 }
203 } 217 }
204 218
205 @Override 219 @Override
220 public void onWindowFocusChanged(boolean hasFocus) {
221 super.onWindowFocusChanged(hasFocus);
222
223 // Re-enter immersive mode after users switch back to this Activity.
224 if (hasFocus) {
225 asyncSetImmersive(ENTER_IMMERSIVE_MODE_DELAY_MILLIS);
226 }
227 }
228
229 /**
230 * Sets activity's decor view into an immersive mode.
231 * If immersive mode is not supported, this method no-ops.
232 */
233 private void enterImmersiveMode() {
234 // Immersive mode is only supported in API 19+.
235 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
236
237 if (mSetImmersiveRunnable == null) {
238
239 final View decor = getWindow().getDecorView();
240
241 mSetImmersiveRunnable = new Runnable() {
242 @Override
243 public void run() {
244 int currentFlags = decor.getSystemUiVisibility();
245 int desiredFlags = currentFlags | IMMERSIVE_MODE_UI_FLAGS;
246 if (currentFlags != desiredFlags) {
247 decor.setSystemUiVisibility(desiredFlags);
248 }
249 }
250 };
251
252 // When we enter immersive mode for the first time, register a
253 // SystemUiVisibilityChangeListener that restores immersive mode. Th is is necessary
254 // because user actions like focusing a keyboard will break out of i mmersive mode.
255 decor.setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibility ChangeListener() {
256 @Override
257 public void onSystemUiVisibilityChange(int newFlags) {
258 if ((newFlags & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
259 asyncSetImmersive(RESTORE_IMMERSIVE_MODE_DELAY_MILLIS);
260 }
261 }
262 });
263 }
264
265 asyncSetImmersive(ENTER_IMMERSIVE_MODE_DELAY_MILLIS);
266 }
267
268 /**
269 * This method no-ops before {@link enterImmersiveMode()) is called explicit ly.
270 */
271 private void asyncSetImmersive(int delayInMills) {
272 if (mSetImmersiveRunnable == null) return;
273
274 mHandler.removeCallbacks(mSetImmersiveRunnable);
275 mHandler.postDelayed(mSetImmersiveRunnable, delayInMills);
276 }
277
278 @Override
206 public void onResume() { 279 public void onResume() {
207 if (!isFinishing()) { 280 if (!isFinishing()) {
208 if (getIntent() != null) { 281 if (getIntent() != null) {
209 // Avoid situations where Android starts two Activities with the same data. 282 // Avoid situations where Android starts two Activities with the same data.
210 DocumentUtils.finishOtherTasksWithData(getIntent().getData(), ge tTaskId()); 283 DocumentUtils.finishOtherTasksWithData(getIntent().getData(), ge tTaskId());
211 } 284 }
212 updateTaskDescription(); 285 updateTaskDescription();
213 } 286 }
214 super.onResume(); 287 super.onResume();
215 } 288 }
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 Tab tab = getActivityTab(); 438 Tab tab = getActivityTab();
366 if (tab == null || mUrlBar == null) return; 439 if (tab == null || mUrlBar == null) return;
367 mUrlBar.update(tab.getUrl(), tab.getSecurityLevel()); 440 mUrlBar.update(tab.getUrl(), tab.getSecurityLevel());
368 } 441 }
369 442
370 private boolean isWebappDomain() { 443 private boolean isWebappDomain() {
371 return UrlUtilities.sameDomainOrHost( 444 return UrlUtilities.sameDomainOrHost(
372 getActivityTab().getUrl(), getWebappInfo().uri().toString(), tru e); 445 getActivityTab().getUrl(), getWebappInfo().uri().toString(), tru e);
373 } 446 }
374 447
448 @Override
449 protected ChromeFullscreenManager createFullscreenManager() {
450 // Disable HTML5 fullscreen in PWA fullscreen mode.
451 return new ChromeFullscreenManager(this, false) {
Ted C 2017/02/17 05:51:50 I'm also not against returning null here assuming
Leo 2017/02/17 07:03:08 I prefer your suggestion. Even returning null is c
452 @Override
453 public void setPersistentFullscreenMode(boolean enabled) {
454 if (mWebappInfo.displayMode() == WebDisplayMode.Fullscreen) retu rn;
455 super.setPersistentFullscreenMode(enabled);
456 }
457
458 @Override
459 public boolean getPersistentFullscreenMode() {
460 if (mWebappInfo.displayMode() == WebDisplayMode.Fullscreen) retu rn false;
461 return super.getPersistentFullscreenMode();
462 }
463 };
464 }
465
375 protected TabObserver createTabObserver() { 466 protected TabObserver createTabObserver() {
376 return new EmptyTabObserver() { 467 return new EmptyTabObserver() {
377 468
378 @Override 469 @Override
379 public void onSSLStateUpdated(Tab tab) { 470 public void onSSLStateUpdated(Tab tab) {
380 updateUrlBar(); 471 updateUrlBar();
381 } 472 }
382 473
383 @Override 474 @Override
384 public void onDidStartProvisionalLoadForFrame( 475 public void onDidStartProvisionalLoadForFrame(
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 return new WebappDelegateFactory(this); 674 return new WebappDelegateFactory(this);
584 } 675 }
585 676
586 // We're temporarily disable CS on webapp since there are some issues. (http ://crbug.com/471950) 677 // We're temporarily disable CS on webapp since there are some issues. (http ://crbug.com/471950)
587 // TODO(changwan): re-enable it once the issues are resolved. 678 // TODO(changwan): re-enable it once the issues are resolved.
588 @Override 679 @Override
589 protected boolean isContextualSearchAllowed() { 680 protected boolean isContextualSearchAllowed() {
590 return false; 681 return false;
591 } 682 }
592 } 683 }
OLDNEW
« no previous file with comments | « chrome/android/java/src/org/chromium/chrome/browser/webapps/FullScreenActivity.java ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698