chromium/chrome/android/java/src/org/chromium/chrome/browser/tab/TabGestureStateListener.java

// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.tab;

import org.chromium.base.ObserverList.RewindableIterator;
import org.chromium.content_public.browser.GestureListenerManager;
import org.chromium.content_public.browser.GestureStateListener;
import org.chromium.content_public.browser.WebContents;

/**
 * {@link GestureStateListener} implementation for a {@link Tab}. Associated with an active
 * {@link WebContents} via its {@link GestureListenerManager}. The listener is managed as
 * UserData for the Tab, with WebContents updated as the active one changes over time.
 */
public final class TabGestureStateListener extends TabWebContentsUserData {
    private static final Class<TabGestureStateListener> USER_DATA_KEY =
            TabGestureStateListener.class;

    private final Tab mTab;
    private GestureStateListener mGestureListener;

    /**
     * Creates TabGestureStateListener and lets the WebContentsUserData of the Tab manage it.
     * @param tab Tab instance that the active WebContents instance gets loaded in.
     */
    public static TabGestureStateListener from(Tab tab) {
        TabGestureStateListener listener = tab.getUserDataHost().getUserData(USER_DATA_KEY);
        if (listener == null) {
            listener =
                    tab.getUserDataHost()
                            .setUserData(USER_DATA_KEY, new TabGestureStateListener(tab));
        }
        return listener;
    }

    private TabGestureStateListener(Tab tab) {
        super(tab);
        mTab = tab;
    }

    @Override
    public void initWebContents(WebContents webContents) {
        GestureListenerManager manager = GestureListenerManager.fromWebContents(webContents);
        mGestureListener =
                new GestureStateListener() {
                    @Override
                    public void onFlingStartGesture(
                            int scrollOffsetY, int scrollExtentY, boolean isDirectionUp) {
                        onScrollingStateChanged();
                    }

                    @Override
                    public void onFlingEndGesture(int scrollOffsetY, int scrollExtentY) {
                        onScrollingStateChanged();
                    }

                    @Override
                    public void onScrollStarted(
                            int scrollOffsetY, int scrollExtentY, boolean isDirectionUp) {
                        onScrollingStateChanged();
                    }

                    @Override
                    public void onScrollEnded(int scrollOffsetY, int scrollExtentY) {
                        onScrollingStateChanged();
                    }

                    @Override
                    public void onGestureBegin() {
                        RewindableIterator<TabObserver> observers =
                                ((TabImpl) mTab).getTabObservers();
                        while (observers.hasNext()) {
                            observers.next().onGestureBegin();
                        }
                    }

                    @Override
                    public void onGestureEnd() {
                        RewindableIterator<TabObserver> observers =
                                ((TabImpl) mTab).getTabObservers();
                        while (observers.hasNext()) {
                            observers.next().onGestureEnd();
                        }
                    }

                    private void onScrollingStateChanged() {
                        boolean scrolling = manager != null ? manager.isScrollInProgress() : false;
                        RewindableIterator<TabObserver> observers =
                                ((TabImpl) mTab).getTabObservers();
                        while (observers.hasNext()) {
                            observers.next().onContentViewScrollingStateChanged(scrolling);
                        }
                    }
                };
        manager.addListener(mGestureListener);
    }

    @Override
    public void cleanupWebContents(WebContents webContents) {
        if (webContents != null) {
            GestureListenerManager manager = GestureListenerManager.fromWebContents(webContents);
            if (manager != null) manager.removeListener(mGestureListener);
        }
        mGestureListener = null;
    }
}