Index: chrome/android/java/src/org/chromium/chrome/browser/Tab.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/Tab.java |
index 57c7682dd27346f54afaa72dd878773e40874c85..353c9e09f3a2d56b847f787354d03625f981747f 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/Tab.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/Tab.java |
@@ -24,17 +24,21 @@ import org.chromium.chrome.browser.contextmenu.ContextMenuPopulator; |
import org.chromium.chrome.browser.contextmenu.ContextMenuPopulatorWrapper; |
import org.chromium.chrome.browser.contextmenu.EmptyChromeContextMenuItemDelegate; |
import org.chromium.chrome.browser.dom_distiller.DomDistillerFeedbackReporter; |
+import org.chromium.chrome.browser.fullscreen.FullscreenManager; |
import org.chromium.chrome.browser.infobar.InfoBarContainer; |
import org.chromium.chrome.browser.printing.TabPrinter; |
import org.chromium.chrome.browser.profiles.Profile; |
import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType; |
+import org.chromium.chrome.browser.tabmodel.TabModelBase; |
import org.chromium.chrome.browser.toolbar.ToolbarModel; |
+import org.chromium.chrome.browser.ui.toolbar.ToolbarModelSecurityLevel; |
import org.chromium.content.browser.ContentView; |
import org.chromium.content.browser.ContentViewClient; |
import org.chromium.content.browser.ContentViewCore; |
import org.chromium.content.browser.WebContentsObserver; |
import org.chromium.content_public.browser.LoadUrlParams; |
import org.chromium.content_public.browser.WebContents; |
+import org.chromium.content_public.common.TopControlsState; |
import org.chromium.printing.PrintManagerDelegateImpl; |
import org.chromium.printing.PrintingController; |
import org.chromium.printing.PrintingControllerImpl; |
@@ -167,6 +171,12 @@ public class Tab { |
*/ |
private final TabLaunchType mLaunchType; |
+ private FullscreenManager mFullscreenManager; |
+ private float mPreviousFullscreenTopControlsOffsetY = Float.NaN; |
+ private float mPreviousFullscreenContentOffsetY = Float.NaN; |
+ private float mPreviousFullscreenOverdrawBottomHeight = Float.NaN; |
+ private int mFullscreenHungRendererToken = FullscreenManager.INVALID_TOKEN; |
+ |
/** |
* A default {@link ChromeContextMenuItemDelegate} that supports some of the context menu |
* functionality. |
@@ -251,6 +261,10 @@ public class Tab { |
@Override |
public void toggleFullscreenModeForTab(boolean enableFullscreen) { |
+ if (mFullscreenManager != null) { |
+ mFullscreenManager.setPersistentFullscreenMode(enableFullscreen); |
+ } |
+ |
for (TabObserver observer : mObservers) { |
observer.onToggleFullscreenMode(Tab.this, enableFullscreen); |
} |
@@ -279,6 +293,29 @@ public class Tab { |
frameName, targetUrl, newWebContents); |
} |
} |
+ |
+ @Override |
+ public void rendererUnresponsive() { |
+ super.rendererUnresponsive(); |
+ if (mFullscreenManager == null) return; |
+ mFullscreenHungRendererToken = |
+ mFullscreenManager.showControlsPersistentAndClearOldToken( |
+ mFullscreenHungRendererToken); |
+ } |
+ |
+ @Override |
+ public void rendererResponsive() { |
+ super.rendererResponsive(); |
+ if (mFullscreenManager == null) return; |
+ mFullscreenManager.hideControlsPersistent(mFullscreenHungRendererToken); |
+ mFullscreenHungRendererToken = FullscreenManager.INVALID_TOKEN; |
+ } |
+ |
+ @Override |
+ public boolean isFullscreenForTabOrPending() { |
+ return mFullscreenManager == null |
+ ? false : mFullscreenManager.getPersistentFullscreenMode(); |
+ } |
} |
private class TabContextMenuPopulator extends ContextMenuPopulatorWrapper { |
@@ -796,6 +833,14 @@ public class Tab { |
*/ |
protected void hide() { |
if (mContentViewCore != null) mContentViewCore.onHide(); |
+ |
+ // Clean up any fullscreen state that might impact other tabs. |
+ if (mFullscreenManager != null) { |
+ mFullscreenManager.setPersistentFullscreenMode(false); |
+ mFullscreenManager.hideControlsPersistent(mFullscreenHungRendererToken); |
+ mFullscreenHungRendererToken = FullscreenManager.INVALID_TOKEN; |
+ mPreviousFullscreenOverdrawBottomHeight = Float.NaN; |
+ } |
} |
/** |
@@ -954,6 +999,9 @@ public class Tab { |
mInfoBarContainer.destroy(); |
mInfoBarContainer = null; |
} |
+ |
+ mPreviousFullscreenTopControlsOffsetY = Float.NaN; |
+ mPreviousFullscreenContentOffsetY = Float.NaN; |
} |
/** |
@@ -1287,6 +1335,170 @@ public class Tab { |
} |
/** |
+ * @return true iff the tab doesn't hold a live page. This happens before initialize() and when |
+ * the tab holds frozen WebContents state that is yet to be inflated. |
+ */ |
+ @VisibleForTesting |
+ public boolean isFrozen() { |
+ return getNativePage() == null && getContentViewCore() == null; |
+ } |
+ |
+ /** |
+ * @return An instance of a {@link FullscreenManager}. |
+ */ |
+ protected FullscreenManager getFullscreenManager() { |
+ return mFullscreenManager; |
+ } |
+ |
+ /** |
+ * Clears hung renderer state. |
+ */ |
+ protected void clearHungRendererState() { |
+ if (mFullscreenManager == null) return; |
+ |
+ mFullscreenManager.hideControlsPersistent(mFullscreenHungRendererToken); |
+ mFullscreenHungRendererToken = FullscreenManager.INVALID_TOKEN; |
+ updateFullscreenEnabledState(); |
+ } |
+ |
+ /** |
+ * Called when offset values related with fullscreen functionality has been changed by the |
+ * compositor. |
+ * @param topControlsOffsetY The Y offset of the top controls in physical pixels. |
+ * @param contentOffsetY The Y offset of the content in physical pixels. |
+ * @param overdrawBottomHeight The overdraw height. |
+ * @param isNonFullscreenPage Whether a current page is non-fullscreen page or not. |
+ */ |
+ protected void onOffsetsChanged(float topControlsOffsetY, float contentOffsetY, |
+ float overdrawBottomHeight, boolean isNonFullscreenPage) { |
+ mPreviousFullscreenTopControlsOffsetY = topControlsOffsetY; |
+ mPreviousFullscreenContentOffsetY = contentOffsetY; |
+ mPreviousFullscreenOverdrawBottomHeight = overdrawBottomHeight; |
+ |
+ if (mFullscreenManager == null) return; |
+ if (isNonFullscreenPage || isNativePage()) { |
+ mFullscreenManager.setPositionsForTabToNonFullscreen(); |
+ } else { |
+ mFullscreenManager.setPositionsForTab(topControlsOffsetY, contentOffsetY); |
+ } |
+ TabModelBase.setActualTabSwitchLatencyMetricRequired(); |
+ } |
+ |
+ /** |
+ * Push state about whether or not the top controls can show or hide to the renderer. |
+ */ |
+ public void updateFullscreenEnabledState() { |
+ if (isFrozen() || mFullscreenManager == null) return; |
+ |
+ updateTopControlsState(getTopControlsStateConstraints(), TopControlsState.BOTH, true); |
+ |
+ if (getContentViewCore() != null) { |
+ getContentViewCore().updateMultiTouchZoomSupport( |
+ !mFullscreenManager.getPersistentFullscreenMode()); |
+ } |
+ } |
+ |
+ /** |
+ * Updates the top controls state for this tab. As these values are set at the renderer |
+ * level, there is potential for this impacting other tabs that might share the same |
+ * process. |
+ * |
+ * @param constraints The constraints that determine whether the controls can be shown |
+ * or hidden at all. |
+ * @param current The desired current state for the controls. Pass |
+ * {@link TopControlsState#BOTH} to preserve the current position. |
+ * @param animate Whether the controls should animate to the specified ending condition or |
+ * should jump immediately. |
+ */ |
+ protected void updateTopControlsState(int constraints, int current, boolean animate) { |
+ if (mNativeTabAndroid == 0) return; |
+ nativeUpdateTopControlsState(mNativeTabAndroid, constraints, current, animate); |
+ } |
+ |
+ /** |
+ * Updates the top controls state for this tab. As these values are set at the renderer |
+ * level, there is potential for this impacting other tabs that might share the same |
+ * process. |
+ * |
+ * @param current The desired current state for the controls. Pass |
+ * {@link TopControlsState#BOTH} to preserve the current position. |
+ * @param animate Whether the controls should animate to the specified ending condition or |
+ * should jump immediately. |
+ */ |
+ public void updateTopControlsState(int current, boolean animate) { |
+ int constraints = getTopControlsStateConstraints(); |
+ // Do nothing if current and constraints conflict to avoid error in |
+ // renderer. |
+ if ((constraints == TopControlsState.HIDDEN && current == TopControlsState.SHOWN) |
+ || (constraints == TopControlsState.SHOWN && current == TopControlsState.HIDDEN)) { |
+ return; |
+ } |
+ updateTopControlsState(getTopControlsStateConstraints(), current, animate); |
+ } |
+ |
+ /** |
+ * @return Whether hiding top controls is enabled or not. |
+ */ |
+ protected boolean isHidingTopControlsEnabled() { |
+ String url = getUrl(); |
+ boolean enableHidingTopControls = url != null && !url.startsWith(UrlConstants.CHROME_SCHEME) |
+ && !url.startsWith(UrlConstants.CHROME_NATIVE_SCHEME); |
+ |
+ int securityState = getSecurityLevel(); |
+ enableHidingTopControls &= (securityState != ToolbarModelSecurityLevel.SECURITY_ERROR |
+ && securityState != ToolbarModelSecurityLevel.SECURITY_WARNING); |
+ |
+ enableHidingTopControls &= |
+ !AccessibilityUtil.isAccessibilityEnabled(getApplicationContext()); |
+ return enableHidingTopControls; |
+ } |
+ |
+ /** |
+ * @return The current visibility constraints for the display of top controls. |
+ * {@link TopControlsState} defines the valid return options. |
+ */ |
+ protected int getTopControlsStateConstraints() { |
+ if (mFullscreenManager == null) return TopControlsState.SHOWN; |
+ |
+ boolean enableHidingTopControls = isHidingTopControlsEnabled(); |
+ boolean enableShowingTopControls = !mFullscreenManager.getPersistentFullscreenMode(); |
+ |
+ int constraints = TopControlsState.BOTH; |
+ if (!enableShowingTopControls) { |
+ constraints = TopControlsState.HIDDEN; |
+ } else if (!enableHidingTopControls) { |
+ constraints = TopControlsState.SHOWN; |
+ } |
+ return constraints; |
+ } |
+ |
+ /** |
+ * @param manager The fullscreen manager that should be notified of changes to this tab (if |
+ * set to null, no more updates will come from this tab). |
+ */ |
+ public void setFullscreenManager(FullscreenManager manager) { |
+ mFullscreenManager = manager; |
+ if (mFullscreenManager != null) { |
+ if (Float.isNaN(mPreviousFullscreenTopControlsOffsetY) |
+ || Float.isNaN(mPreviousFullscreenContentOffsetY)) { |
+ mFullscreenManager.setPositionsForTabToNonFullscreen(); |
+ } else { |
+ mFullscreenManager.setPositionsForTab( |
+ mPreviousFullscreenTopControlsOffsetY, mPreviousFullscreenContentOffsetY); |
+ } |
+ mFullscreenManager.showControlsTransient(); |
+ updateFullscreenEnabledState(); |
+ } |
+ } |
+ |
+ /** |
+ * @return The most recent frame's overdraw bottom height in pixels. |
+ */ |
+ public float getFullscreenOverdrawBottomHeightPix() { |
+ return mPreviousFullscreenOverdrawBottomHeight; |
+ } |
+ |
+ /** |
* @return An unused id. |
*/ |
private static int generateNextId() { |
@@ -1330,4 +1542,6 @@ public class Tab { |
private native boolean nativePrint(long nativeTabAndroid); |
private native Bitmap nativeGetFavicon(long nativeTabAndroid); |
private native void nativeCreateHistoricalTab(long nativeTabAndroid); |
+ private native void nativeUpdateTopControlsState( |
+ long nativeTabAndroid, int constraints, int current, boolean animate); |
} |