| Index: chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
|
| index 988ecb2b0e68f2ca19d25d1188a852f89b937f11..310d1eb2dd8afd8bbe9278353cfee3ade5f877a2 100644
|
| --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanel.java
|
| @@ -9,28 +9,18 @@ import android.os.Handler;
|
| import android.view.View.MeasureSpec;
|
|
|
| import org.chromium.base.VisibleForTesting;
|
| -import org.chromium.base.annotations.CalledByNative;
|
| import org.chromium.chrome.browser.ChromeActivity;
|
| -import org.chromium.chrome.browser.WebContentsFactory;
|
| +import org.chromium.chrome.browser.compositor.bottombar.OverlayContentProgressObserver;
|
| +import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelContent;
|
| import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost;
|
| -import org.chromium.chrome.browser.contextualsearch.ContextualSearchContentController;
|
| -import org.chromium.chrome.browser.externalnav.ExternalNavigationHandler;
|
| -import org.chromium.components.navigation_interception.InterceptNavigationDelegate;
|
| -import org.chromium.components.navigation_interception.NavigationParams;
|
| -import org.chromium.components.web_contents_delegate_android.WebContentsDelegateAndroid;
|
| -import org.chromium.content.browser.ContentView;
|
| import org.chromium.content.browser.ContentViewClient;
|
| import org.chromium.content.browser.ContentViewCore;
|
| -import org.chromium.content_public.browser.LoadUrlParams;
|
| -import org.chromium.content_public.browser.WebContents;
|
| -import org.chromium.content_public.browser.WebContentsObserver;
|
| -import org.chromium.ui.base.WindowAndroid;
|
|
|
| /**
|
| * Controls the Contextual Search Panel.
|
| */
|
| public class ContextualSearchPanel extends ContextualSearchPanelAnimation
|
| - implements ContextualSearchPanelDelegate, ContextualSearchContentController {
|
| + implements ContextualSearchPanelDelegate {
|
|
|
| /**
|
| * State of the Contextual Search Panel.
|
| @@ -73,56 +63,11 @@ public class ContextualSearchPanel extends ContextualSearchPanelAnimation
|
| private static final long INTERCEPT_NAVIGATION_PROMOTION_ANIMATION_DURATION_MS = 40;
|
|
|
| /**
|
| - * The ContentViewCore that this panel will display.
|
| - */
|
| - private ContentViewCore mContentViewCore;
|
| -
|
| - /**
|
| - * The pointer to the native version of this class.
|
| - */
|
| - private long mNativeContextualSearchPanelPtr;
|
| -
|
| - /**
|
| - * Used for progress bar handling.
|
| - */
|
| - private final WebContentsDelegateAndroid mWebContentsDelegate;
|
| -
|
| - /**
|
| * The activity this panel is in.
|
| */
|
| private ChromeActivity mActivity;
|
|
|
| /**
|
| - * The window android for the above activity.
|
| - */
|
| - private WindowAndroid mWindowAndroid;
|
| -
|
| - /**
|
| - * Observes the ContentViewCore for this panel.
|
| - */
|
| - private WebContentsObserver mWebContentsObserver;
|
| -
|
| - /**
|
| - * Used to detect if a URL was loaded in the ContentViewCore.
|
| - */
|
| - private boolean mDidLoadAnyUrl;
|
| -
|
| - /**
|
| - * Used to track if the ContentViewCore is showing.
|
| - */
|
| - private boolean mIsContentViewShowing;
|
| -
|
| - /**
|
| - * This is primarily used for injecting test functionaluty into the panel for creating and
|
| - * destroying ContentViewCores.
|
| - */
|
| - private ContextualSearchContentController mContentController;
|
| -
|
| - // http://crbug.com/522266 : An instance of InterceptNavigationDelegateImpl should be kept in
|
| - // java layer. Otherwise, the instance could be garbage-collected unexpectedly.
|
| - private InterceptNavigationDelegateImpl mInterceptNavigationDelegate;
|
| -
|
| - /**
|
| * The delay after which the hide progress will be hidden.
|
| */
|
| private static final long HIDE_PROGRESS_BAR_DELAY = 1000 / 60 * 4;
|
| @@ -152,6 +97,11 @@ public class ContextualSearchPanel extends ContextualSearchPanelAnimation
|
| */
|
| private ContextualSearchPanelHost mSearchPanelHost;
|
|
|
| + /**
|
| + * Container for content the panel will show.
|
| + */
|
| + private OverlayPanelContent mOverlayPanelContent;
|
| +
|
| // ============================================================================================
|
| // Constructor
|
| // ============================================================================================
|
| @@ -162,41 +112,65 @@ public class ContextualSearchPanel extends ContextualSearchPanelAnimation
|
| */
|
| public ContextualSearchPanel(Context context, LayoutUpdateHost updateHost) {
|
| super(context, updateHost);
|
| - nativeInit();
|
| -
|
| - // TODO(mdjones): The following is for testing purposes, refactor the need for this out.
|
| - mContentController = this;
|
| -
|
| - mWebContentsDelegate = new WebContentsDelegateAndroid() {
|
| - @Override
|
| - public void onLoadStarted() {
|
| - super.onLoadStarted();
|
| - setProgressBarCompletion(0);
|
| - setProgressBarVisible(true);
|
| - requestUpdate();
|
| - }
|
| + }
|
|
|
| - @Override
|
| - public void onLoadStopped() {
|
| - super.onLoadStopped();
|
| - // Hides the Progress Bar after a delay to make sure it is rendered for at least
|
| - // a few frames, otherwise its completion won't be visually noticeable.
|
| - new Handler().postDelayed(new Runnable() {
|
| - @Override
|
| - public void run() {
|
| - setProgressBarVisible(false);
|
| - requestUpdate();
|
| - }
|
| - }, HIDE_PROGRESS_BAR_DELAY);
|
| - }
|
| + /**
|
| + * Create a new OverlayPanelContent object. This can be overridden for tests.
|
| + */
|
| + public OverlayPanelContent createNewOverlayPanelContent() {
|
| + OverlayPanelContent overlayPanelContent = new OverlayPanelContent(
|
| + getManagementDelegate().getOverlayContentDelegate(), new PanelProgressObserver(),
|
| + mActivity);
|
|
|
| - @Override
|
| - public void onLoadProgressChanged(int progress) {
|
| - super.onLoadProgressChanged(progress);
|
| - setProgressBarCompletion(progress);
|
| - requestUpdate();
|
| - }
|
| - };
|
| + // Adds a ContentViewClient to override the default fullscreen size.
|
| + if (!isFullscreenSizePanel()) {
|
| + overlayPanelContent.setContentViewClient(new ContentViewClient() {
|
| + @Override
|
| + public int getDesiredWidthMeasureSpec() {
|
| + return MeasureSpec.makeMeasureSpec(
|
| + getSearchContentViewWidthPx(),
|
| + MeasureSpec.EXACTLY);
|
| + }
|
| +
|
| + @Override
|
| + public int getDesiredHeightMeasureSpec() {
|
| + return MeasureSpec.makeMeasureSpec(
|
| + getSearchContentViewHeightPx(),
|
| + MeasureSpec.EXACTLY);
|
| + }
|
| + });
|
| + }
|
| +
|
| + return overlayPanelContent;
|
| + }
|
| +
|
| + /**
|
| + * Default loading animation for a panel.
|
| + */
|
| + public class PanelProgressObserver extends OverlayContentProgressObserver {
|
| +
|
| + public void onProgressBarStarted() {
|
| + setProgressBarCompletion(0);
|
| + setProgressBarVisible(true);
|
| + requestUpdate();
|
| + }
|
| +
|
| + public void onProgressBarUpdated(int progress) {
|
| + setProgressBarCompletion(progress);
|
| + requestUpdate();
|
| + }
|
| +
|
| + public void onProgressBarFinished() {
|
| + // Hides the Progress Bar after a delay to make sure it is rendered for at least
|
| + // a few frames, otherwise its completion won't be visually noticeable.
|
| + new Handler().postDelayed(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + setProgressBarVisible(false);
|
| + requestUpdate();
|
| + }
|
| + }, HIDE_PROGRESS_BAR_DELAY);
|
| + }
|
| }
|
|
|
| // ============================================================================================
|
| @@ -236,7 +210,9 @@ public class ContextualSearchPanel extends ContextualSearchPanelAnimation
|
|
|
| @Override
|
| protected void onClose(StateChangeReason reason) {
|
| - mContentController.destroyContentView();
|
| + if (mOverlayPanelContent != null) {
|
| + mOverlayPanelContent.destroyContentView();
|
| + }
|
| getManagementDelegate().onCloseContextualSearch(reason);
|
| }
|
|
|
| @@ -265,7 +241,7 @@ public class ContextualSearchPanel extends ContextualSearchPanelAnimation
|
| if (ty > 0 && getPanelState() == PanelState.MAXIMIZED) {
|
| // Resets the Search Content View scroll position when swiping the Panel down
|
| // after being maximized.
|
| - resetSearchContentViewScroll();
|
| + mOverlayPanelContent.resetContentViewScroll();
|
| }
|
|
|
| // Negative ty value means an upward movement so subtracting ty means expanding the panel.
|
| @@ -450,175 +426,25 @@ public class ContextualSearchPanel extends ContextualSearchPanelAnimation
|
| }
|
|
|
| // ============================================================================================
|
| - // ContextualSearchContentController
|
| + // Utilities
|
| // ============================================================================================
|
|
|
| - @Override
|
| - public void createNewContentView() {
|
| - // If the ContentViewCore has already been created, but never used,
|
| - // then there's no need to create a new one.
|
| - if (mContentViewCore != null && !mDidLoadAnyUrl) {
|
| - return;
|
| - }
|
| -
|
| - mContentController.destroyContentView();
|
| - mContentViewCore = new ContentViewCore(mActivity);
|
| -
|
| - // Adds a ContentViewClient to override the default fullscreen size.
|
| - if (!isFullscreenSizePanel()) {
|
| - mContentViewCore.setContentViewClient(new ContentViewClient() {
|
| - @Override
|
| - public int getDesiredWidthMeasureSpec() {
|
| - return MeasureSpec.makeMeasureSpec(
|
| - getSearchContentViewWidthPx(),
|
| - MeasureSpec.EXACTLY);
|
| - }
|
| -
|
| - @Override
|
| - public int getDesiredHeightMeasureSpec() {
|
| - return MeasureSpec.makeMeasureSpec(
|
| - getSearchContentViewHeightPx(),
|
| - MeasureSpec.EXACTLY);
|
| - }
|
| - });
|
| - }
|
| -
|
| - ContentView cv = ContentView.createContentView(mActivity, mContentViewCore);
|
| - // Creates an initially hidden WebContents which gets shown when the panel is opened.
|
| - mContentViewCore.initialize(cv, cv,
|
| - WebContentsFactory.createWebContents(false, true), mWindowAndroid);
|
| -
|
| - // Transfers the ownership of the WebContents to the native ContextualSearchManager.
|
| - nativeSetWebContents(mNativeContextualSearchPanelPtr, mContentViewCore,
|
| - mWebContentsDelegate);
|
| -
|
| - mWebContentsObserver =
|
| - new WebContentsObserver(mContentViewCore.getWebContents()) {
|
| - @Override
|
| - public void didStartLoading(String url) {
|
| - getManagementDelegate().onStartedLoading();
|
| - }
|
| -
|
| - @Override
|
| - public void didStartProvisionalLoadForFrame(long frameId, long parentFrameId,
|
| - boolean isMainFrame, String validatedUrl, boolean isErrorPage,
|
| - boolean isIframeSrcdoc) {
|
| - if (isMainFrame) getManagementDelegate().onExternalNavigation(validatedUrl);
|
| - }
|
| -
|
| - @Override
|
| - public void didNavigateMainFrame(String url, String baseUrl,
|
| - boolean isNavigationToDifferentPage, boolean isNavigationInPage,
|
| - int httpResultCode) {
|
| - getManagementDelegate().handleDidNavigateMainFrame(url, httpResultCode);
|
| - mDidLoadAnyUrl = false;
|
| - }
|
| -
|
| - @Override
|
| - public void didFinishLoad(long frameId, String validatedUrl,
|
| - boolean isMainFrame) {
|
| - getManagementDelegate().onSearchResultsLoaded();
|
| - }
|
| - };
|
| -
|
| - mInterceptNavigationDelegate = new InterceptNavigationDelegateImpl();
|
| - nativeSetInterceptNavigationDelegate(mNativeContextualSearchPanelPtr,
|
| - mInterceptNavigationDelegate, mContentViewCore.getWebContents());
|
| -
|
| - getManagementDelegate().onContentViewCreated(mContentViewCore);
|
| - }
|
| -
|
| - @Override
|
| - public void destroyContentView() {
|
| - // TODO(mdjones): This should not be a public API.
|
| - if (mContentViewCore != null) {
|
| - nativeDestroyWebContents(mNativeContextualSearchPanelPtr);
|
| - mContentViewCore.getWebContents().destroy();
|
| - mContentViewCore.destroy();
|
| - mContentViewCore = null;
|
| - if (mWebContentsObserver != null) {
|
| - mWebContentsObserver.destroy();
|
| - mWebContentsObserver = null;
|
| - }
|
| -
|
| - getManagementDelegate().onContentViewDestroyed();
|
| - }
|
| -
|
| - // This should be called last here. The setSearchContentViewVisibility method
|
| - // will change the visibility the SearchContentView but also set the value of the
|
| - // internal property mIsSearchContentViewShowing. If we call this after deleting
|
| - // the SearchContentView, it will be faster, because only the internal property
|
| - // will be changed, since there will be no need to change the visibility of the
|
| - // SearchContentView.
|
| - //
|
| - // Also, this should be called outside the block above because tests will not
|
| - // create a ContentView, therefore if this call is placed inside the block,
|
| - // it will not be called on tests, which will cause some tests to fail.
|
| - setSearchContentViewVisibility(false);
|
| - }
|
| -
|
| - @Override
|
| - public void loadUrl(String url) {
|
| - createNewPanelContentView();
|
| -
|
| - if (mContentViewCore != null && mContentViewCore.getWebContents() != null) {
|
| - mDidLoadAnyUrl = true;
|
| - mContentViewCore.getWebContents().getNavigationController().loadUrl(
|
| - new LoadUrlParams(url));
|
| - }
|
| - }
|
| -
|
| - public void resetSearchContentViewScroll() {
|
| - if (mContentViewCore != null) {
|
| - mContentViewCore.scrollTo(0, 0);
|
| - }
|
| - }
|
| -
|
| + /**
|
| + * @return The vertical scroll position of the content.
|
| + */
|
| public float getSearchContentViewVerticalScroll() {
|
| - return mContentViewCore != null
|
| - ? mContentViewCore.computeVerticalScrollOffset() : -1.f;
|
| + return mOverlayPanelContent.getContentViewVerticalScroll();
|
| }
|
|
|
| /**
|
| - * Sets the visibility of the Search Content View.
|
| - * @param isVisible True to make it visible.
|
| + * @return A new OverlayPanelContent if the instance was null or the existing one.
|
| */
|
| - public void setSearchContentViewVisibility(boolean isVisible) {
|
| - if (mIsContentViewShowing == isVisible) return;
|
| -
|
| - mIsContentViewShowing = isVisible;
|
| - getManagementDelegate().onContentViewVisibilityChanged(isVisible);
|
| -
|
| - if (isVisible) {
|
| - // The CVC is created with the search request, but if none was made we'll need
|
| - // one in order to display an empty panel.
|
| - if (mContentViewCore == null) {
|
| - createNewPanelContentView();
|
| - }
|
| - if (mContentViewCore != null) mContentViewCore.onShow();
|
| - setWasSearchContentViewSeen();
|
| - } else {
|
| - if (mContentViewCore != null) mContentViewCore.onHide();
|
| - }
|
| - }
|
| -
|
| - // ============================================================================================
|
| - // InterceptNavigationDelegateImpl
|
| - // ============================================================================================
|
| -
|
| - // Used to intercept intent navigations.
|
| - // TODO(jeremycho): Consider creating a Tab with the Panel's ContentViewCore,
|
| - // which would also handle functionality like long-press-to-paste.
|
| - private class InterceptNavigationDelegateImpl implements InterceptNavigationDelegate {
|
| - final ExternalNavigationHandler mExternalNavHandler = new ExternalNavigationHandler(
|
| - mActivity);
|
| - @Override
|
| - public boolean shouldIgnoreNavigation(NavigationParams navigationParams) {
|
| - // TODO(mdjones): Rather than passing the two navigation params, instead consider
|
| - // passing a boolean to make this API simpler.
|
| - return getManagementDelegate().shouldInterceptNavigation(mExternalNavHandler,
|
| - navigationParams);
|
| + public OverlayPanelContent getOverlayPanelContent() {
|
| + // Only create the content when necessary
|
| + if (mOverlayPanelContent == null) {
|
| + mOverlayPanelContent = createNewOverlayPanelContent();
|
| }
|
| + return mOverlayPanelContent;
|
| }
|
|
|
| // ============================================================================================
|
| @@ -719,6 +545,7 @@ public class ContextualSearchPanel extends ContextualSearchPanelAnimation
|
| super.setDidSearchInvolvePromo();
|
| }
|
|
|
| + @Override
|
| public void setWasSearchContentViewSeen() {
|
| // NOTE(pedrosimonetti): exposing superclass method to the interface.
|
| super.setWasSearchContentViewSeen();
|
| @@ -774,43 +601,23 @@ public class ContextualSearchPanel extends ContextualSearchPanelAnimation
|
|
|
| @Override
|
| public boolean isContentViewShowing() {
|
| - return mIsContentViewShowing;
|
| + return mOverlayPanelContent != null && mOverlayPanelContent.isContentViewShowing();
|
| }
|
|
|
| @Override
|
| public void setChromeActivity(ChromeActivity activity) {
|
| mActivity = activity;
|
| - mWindowAndroid = mActivity.getWindowAndroid();
|
| - }
|
| -
|
| - @Override
|
| - public void createNewPanelContentView() {
|
| - mContentController.createNewContentView();
|
| }
|
|
|
| @Override
|
| public void loadUrlInPanel(String url) {
|
| - mContentController.loadUrl(url);
|
| - }
|
| -
|
| - @Override
|
| - public void setContentController(ContextualSearchContentController controller) {
|
| - mContentController = controller;
|
| - }
|
| -
|
| - @VisibleForTesting
|
| - @Override
|
| - public ContextualSearchContentController getContentController() {
|
| - return this;
|
| - }
|
| -
|
| - @Override
|
| - public boolean didLoadAnyUrl() {
|
| - return mDidLoadAnyUrl;
|
| + getOverlayPanelContent().loadUrl(url);
|
| }
|
|
|
| @Override
|
| public void updateTopControlState() {
|
| + if (mOverlayPanelContent == null) return;
|
| +
|
| if (isFullscreenSizePanel()) {
|
| // Consider the ContentView height to be fullscreen, and inform the system that
|
| // the Toolbar is always visible (from the Compositor's perspective), even though
|
| @@ -819,51 +626,48 @@ public class ContextualSearchPanel extends ContextualSearchPanelAnimation
|
| // minus the Toolbar height.
|
| //
|
| // This is necessary to fix the bugs: crbug.com/510205 and crbug.com/510206
|
| - mContentViewCore.getWebContents().updateTopControlsState(false, true, false);
|
| + mOverlayPanelContent.updateTopControlsState(false, true, false);
|
| } else {
|
| - mContentViewCore.getWebContents().updateTopControlsState(true, false, false);
|
| + mOverlayPanelContent.updateTopControlsState(true, false, false);
|
| }
|
| }
|
|
|
| - // ============================================================================================
|
| - // Methods for managing this panel's ContentViewCore.
|
| - // ============================================================================================
|
| -
|
| - @CalledByNative
|
| - public void clearNativePanelContentPtr() {
|
| - assert mNativeContextualSearchPanelPtr != 0;
|
| - mNativeContextualSearchPanelPtr = 0;
|
| - }
|
| -
|
| - @CalledByNative
|
| - public void setNativePanelContentPtr(long nativePtr) {
|
| - assert mNativeContextualSearchPanelPtr == 0;
|
| - mNativeContextualSearchPanelPtr = nativePtr;
|
| + @Override
|
| + public boolean didLoadAnyUrl() {
|
| + return mOverlayPanelContent != null && mOverlayPanelContent.didLoadAnyUrl();
|
| }
|
|
|
| @Override
|
| public ContentViewCore getContentViewCore() {
|
| - return mContentViewCore;
|
| + // Expose OverlayPanelContent method.
|
| + return mOverlayPanelContent != null ? mOverlayPanelContent.getContentViewCore() : null;
|
| }
|
|
|
| @Override
|
| public void removeLastHistoryEntry(String historyUrl, long urlTimeMs) {
|
| - nativeRemoveLastHistoryEntry(mNativeContextualSearchPanelPtr, historyUrl, urlTimeMs);
|
| + if (mOverlayPanelContent == null) return;
|
| + // Expose OverlayPanelContent method.
|
| + mOverlayPanelContent.removeLastHistoryEntry(historyUrl, urlTimeMs);
|
| }
|
|
|
| - @VisibleForTesting
|
| + @Override
|
| + public void setSearchContentViewVisibility(boolean isVisible) {
|
| + getOverlayPanelContent().setVisibility(isVisible);
|
| + }
|
| +
|
| + /**
|
| + * Destroy the native components associated with this panel's content.
|
| + */
|
| public void destroy() {
|
| - nativeDestroy(mNativeContextualSearchPanelPtr);
|
| - }
|
| -
|
| - // Native calls.
|
| - protected native long nativeInit();
|
| - private native void nativeDestroy(long nativeContextualSearchPanel);
|
| - private native void nativeRemoveLastHistoryEntry(
|
| - long nativeContextualSearchPanel, String historyUrl, long urlTimeMs);
|
| - private native void nativeSetWebContents(long nativeContextualSearchPanel,
|
| - ContentViewCore contentViewCore, WebContentsDelegateAndroid delegate);
|
| - private native void nativeDestroyWebContents(long nativeContextualSearchPanel);
|
| - private native void nativeSetInterceptNavigationDelegate(long nativeContextualSearchPanel,
|
| - InterceptNavigationDelegate delegate, WebContents webContents);
|
| + // It is possible that an OverlayPanelContent was never created for this panel.
|
| + if (mOverlayPanelContent != null) {
|
| + mOverlayPanelContent.destroy();
|
| + }
|
| + }
|
| +
|
| + @Override
|
| + @VisibleForTesting
|
| + public void setOverlayPanelContent(OverlayPanelContent panelContent) {
|
| + mOverlayPanelContent = panelContent;
|
| + }
|
| }
|
|
|