1d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// found in the LICENSE file.
4d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
5d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)package org.chromium.chrome.browser.infobar;
6d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
7d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)import android.animation.ObjectAnimator;
8d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)import android.app.Activity;
9d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)import android.graphics.Canvas;
10d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)import android.view.Gravity;
11d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)import android.view.MotionEvent;
12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)import android.view.View;
13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)import android.view.ViewGroup;
14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)import android.widget.FrameLayout;
15d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)import android.widget.LinearLayout;
16d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
17d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)import com.google.common.annotations.VisibleForTesting;
18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
19d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)import org.chromium.base.ApiCompatibilityUtils;
20d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)import org.chromium.base.CalledByNative;
21d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)import org.chromium.content.browser.DeviceUtils;
22d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)import org.chromium.ui.UiUtils;
23d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
24d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)import java.util.ArrayDeque;
25d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)import java.util.ArrayList;
26d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)import java.util.Iterator;
27d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)import java.util.LinkedList;
28d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
29d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
30d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)/**
31d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * A container for all the infobars of a specific tab.
32d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * Note that infobars creation can be initiated from Java of from native code.
33d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * When initiated from native code, special code is needed to keep the Java and native infobar in
34d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * sync, see NativeInfoBar.
35d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) */
36d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)public class InfoBarContainer extends LinearLayout {
37d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    private static final String TAG = "InfoBarContainer";
38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    private static final long REATTACH_FADE_IN_MS = 250;
39d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
40d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public interface InfoBarAnimationListener {
41d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        /**
42d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)         * Notifies the subscriber when an animation is completed.
43d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)         */
44d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        void notifyAnimationFinished(int animationType);
45d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
46d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
47d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    private static class InfoBarTransitionInfo {
48d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // InfoBar being animated.
49d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        public InfoBar target;
50d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
51d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // View to replace the current View shown by the ContentWrapperView.
52d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        public View toShow;
53d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
54d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // Which type of animation needs to be performed.
55d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        public int animationType;
56d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
57d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        public InfoBarTransitionInfo(InfoBar bar, View view, int type) {
58d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            assert type >= AnimationHelper.ANIMATION_TYPE_SHOW;
59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            assert type < AnimationHelper.ANIMATION_TYPE_BOUNDARY;
60d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
61d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            target = bar;
62d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            toShow = view;
63d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            animationType = type;
64d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
65d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
66d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
67d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    private InfoBarAnimationListener mAnimationListener;
68d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
69d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Native InfoBarContainer pointer which will be set by nativeInit()
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private long mNativeInfoBarContainer;
71d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
72d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    private final Activity mActivity;
73d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
74d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    private final AutoLoginDelegate mAutoLoginDelegate;
75d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
76d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Whether the infobar are shown on top (below the location bar) or at the bottom of the screen.
77d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    private final boolean mInfoBarsOnTop;
78d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
79d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // The list of all infobars in this container, regardless of whether they've been shown yet.
80d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    private final ArrayList<InfoBar> mInfoBars = new ArrayList<InfoBar>();
81d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
82d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // We only animate changing infobars one at a time.
83d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    private final ArrayDeque<InfoBarTransitionInfo> mInfoBarTransitions;
84d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
85d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Animation currently moving InfoBars around.
86d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    private AnimationHelper mAnimation;
87d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    private final FrameLayout mAnimationSizer;
88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
89d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // True when this container has been emptied and its native counterpart has been destroyed.
90d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    private boolean mDestroyed = false;
91d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
92d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // The id of the tab associated with us. Set to TabBase.INVALID_TAB_ID if no tab is associated.
93d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    private int mTabId;
94d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
95d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Parent view that contains us.
96d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    private ViewGroup mParentView;
97d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
98d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public InfoBarContainer(Activity activity, AutoLoginProcessor autoLoginProcessor,
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            int tabId, ViewGroup parentView, long nativeWebContents) {
100d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        super(activity);
101d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        setOrientation(LinearLayout.VERTICAL);
102d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        mAnimationListener = null;
103d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        mInfoBarTransitions = new ArrayDeque<InfoBarTransitionInfo>();
104d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
105d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        mAutoLoginDelegate = new AutoLoginDelegate(autoLoginProcessor, activity);
106d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        mActivity = activity;
107d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        mTabId = tabId;
108d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        mParentView = parentView;
109d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
110d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        mAnimationSizer = new FrameLayout(activity);
111d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        mAnimationSizer.setVisibility(INVISIBLE);
112d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
113d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // The tablet has the infobars below the location bar. On the phone they are at the bottom.
114d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        mInfoBarsOnTop = DeviceUtils.isTablet(activity);
115d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        setGravity(determineGravity());
116d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
117d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // Chromium's InfoBarContainer may add an InfoBar immediately during this initialization
118d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // call, so make sure everything in the InfoBarContainer is completely ready beforehand.
119d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        mNativeInfoBarContainer = nativeInit(nativeWebContents, mAutoLoginDelegate);
120d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
121d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
122d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public void setAnimationListener(InfoBarAnimationListener listener) {
123d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        mAnimationListener = listener;
124d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
125d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
126d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    @VisibleForTesting
127d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public InfoBarAnimationListener getAnimationListener() {
128d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        return mAnimationListener;
129d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
130d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
131d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
132d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public boolean areInfoBarsOnTop() {
133d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        return mInfoBarsOnTop;
134d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
135d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
136d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    @Override
137d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public boolean onInterceptTouchEvent(MotionEvent ev) {
138d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // Trap any attempts to fiddle with the Views while we're animating.
139d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        return mAnimation != null;
140d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
141d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
142d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    @Override
143d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public boolean onTouchEvent(MotionEvent event) {
144d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // Consume all motion events so they do not reach the ContentView.
145d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        return true;
146d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
147d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
148d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    private void addToParentView() {
149d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        if (mParentView != null && mParentView.indexOfChild(this) == -1) {
150d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            mParentView.addView(this, createLayoutParams());
151d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
152d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
153d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
154d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    private int determineGravity() {
155d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        return mInfoBarsOnTop ? Gravity.TOP : Gravity.BOTTOM;
156d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
157d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
158d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    private FrameLayout.LayoutParams createLayoutParams() {
159d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        return new FrameLayout.LayoutParams(
160d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, determineGravity());
161d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
162d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    public void removeFromParentView() {
164d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        if (getParent() != null) {
165d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            ((ViewGroup) getParent()).removeView(this);
166d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
167d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
168d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
169d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    /**
170d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * Called when the parent {@link android.view.ViewGroup} has changed for
171d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * this container.
172d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     */
173d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public void onParentViewChanged(int tabId, ViewGroup parentView) {
174d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        mTabId = tabId;
175d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        mParentView = parentView;
176d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
17733bff6d6e5e82ca5f2abf842074e33f4944cc250Ben Murdoch        removeFromParentView();
17833bff6d6e5e82ca5f2abf842074e33f4944cc250Ben Murdoch        addToParentView();
179d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
180d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
181d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    @Override
182d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
183d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        if (mAnimation == null || child != mAnimation.getTarget()) {
184d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            return super.drawChild(canvas, child, drawingTime);
185d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
186d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // When infobars are on top, the new infobar Z-order is greater than the previous infobar,
187d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // which means it shows on top during the animation. We cannot change the Z-order in the
188d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // linear layout, it is driven by the insertion index.
189d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // So we simply clip the children to their bounds to make sure the new infobar does not
190d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // paint over.
191d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        boolean retVal;
192d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        canvas.save();
193d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        canvas.clipRect(mAnimation.getTarget().getClippingRect());
194d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        retVal = super.drawChild(canvas, child, drawingTime);
195d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        canvas.restore();
196d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        return retVal;
197d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
198d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
199d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    @Override
200d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    protected void onAttachedToWindow() {
201d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        super.onAttachedToWindow();
202d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        ObjectAnimator.ofFloat(this, "alpha", 0.f, 1.f).setDuration(REATTACH_FADE_IN_MS).start();
203d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        setVisibility(VISIBLE);
204d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
205d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
206d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    @Override
207d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    protected void onDetachedFromWindow() {
208d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        super.onDetachedFromWindow();
209d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        setVisibility(INVISIBLE);
210d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
211d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
212d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public InfoBar findInfoBar(int nativeInfoBar) {
213d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        for (InfoBar infoBar : mInfoBars) {
214d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            if (infoBar.ownsNativeInfoBar(nativeInfoBar)) {
215d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                return infoBar;
216d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            }
217d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
218d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        return null;
219d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
220d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
221d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    /**
222d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * Adds an InfoBar to the view hierarchy.
223d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * @param infoBar InfoBar to add to the View hierarchy.
224d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     */
225d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    @CalledByNative
226d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public void addInfoBar(InfoBar infoBar) {
227d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        assert !mDestroyed;
228d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        if (infoBar == null) {
229d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            return;
230d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
231d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        if (mInfoBars.contains(infoBar)) {
232d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            assert false : "Trying to add an info bar that has already been added.";
233d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            return;
234d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
235d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
236d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // We add the infobar immediately to mInfoBars but we wait for the animation to end to
237d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // notify it's been added, as tests rely on this notification but expects the infobar view
238d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // to be available when they get the notification.
239d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        mInfoBars.add(infoBar);
240d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        infoBar.setContext(mActivity);
241d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        infoBar.setInfoBarContainer(this);
242d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
243d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        enqueueInfoBarAnimation(infoBar, null, AnimationHelper.ANIMATION_TYPE_SHOW);
244d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
245d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
246d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    /**
247d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * Returns the latest InfoBarTransitionInfo that deals with the given InfoBar.
248d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * @param toFind InfoBar that we're looking for.
249d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     */
250d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public InfoBarTransitionInfo findLastTransitionForInfoBar(InfoBar toFind) {
251d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        Iterator<InfoBarTransitionInfo> iterator = mInfoBarTransitions.descendingIterator();
252d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        while (iterator.hasNext()) {
253d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            InfoBarTransitionInfo info = iterator.next();
254d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            if (info.target == toFind) return info;
255d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
256d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        return null;
257d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
258d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    /**
260d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * Animates swapping out the current View in the {@code infoBar} with {@code toShow} without
261d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * destroying or dismissing the entire InfoBar.
262d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * @param infoBar InfoBar that is having its content replaced.
263d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * @param toShow View representing the InfoBar's new contents.
264d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     */
265d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public void swapInfoBarViews(InfoBar infoBar, View toShow) {
266d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        assert !mDestroyed;
267d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
268d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        if (!mInfoBars.contains(infoBar)) {
269d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            assert false : "Trying to swap an InfoBar that is not in this container.";
270d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            return;
271d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
272d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
273d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        InfoBarTransitionInfo transition = findLastTransitionForInfoBar(infoBar);
274d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        if (transition != null && transition.toShow == toShow) {
275d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            assert false : "Tried to enqueue the same swap twice in a row.";
276d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            return;
277d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
278d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
279d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        enqueueInfoBarAnimation(infoBar, toShow, AnimationHelper.ANIMATION_TYPE_SWAP);
280d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
281d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
282d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    /**
283d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * Removes an InfoBar from the view hierarchy.
284d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * @param infoBar InfoBar to remove from the View hierarchy.
285d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     */
286d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public void removeInfoBar(InfoBar infoBar) {
287d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        assert !mDestroyed;
288d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
289d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        if (!mInfoBars.remove(infoBar)) {
290d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            assert false : "Trying to remove an InfoBar that is not in this container.";
291d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            return;
292d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
293d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
294d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // If an InfoBar is told to hide itself before it has a chance to be shown, don't bother
295d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // with animating any of it.
296d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        boolean collapseAnimations = false;
297d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        ArrayDeque<InfoBarTransitionInfo> transitionCopy =
298d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                new ArrayDeque<InfoBarTransitionInfo>(mInfoBarTransitions);
299d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        for (InfoBarTransitionInfo info : transitionCopy) {
300d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            if (info.target == infoBar) {
301d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                if (info.animationType == AnimationHelper.ANIMATION_TYPE_SHOW) {
302d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                    // We can assert that two attempts to show the same InfoBar won't be in the
303d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                    // deque simultaneously because of the check in addInfoBar().
304d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                    assert !collapseAnimations;
305d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                    collapseAnimations = true;
306d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                }
307d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                if (collapseAnimations) {
308d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                    mInfoBarTransitions.remove(info);
309d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                }
310d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            }
311d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
312d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
313d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        if (!collapseAnimations) {
314d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            enqueueInfoBarAnimation(infoBar, null, AnimationHelper.ANIMATION_TYPE_HIDE);
315d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
316d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
317d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
318d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    /**
319d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * Enqueue a new animation to run and kicks off the animation sequence.
320d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     */
321d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    private void enqueueInfoBarAnimation(InfoBar infoBar, View toShow, int animationType) {
322d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        InfoBarTransitionInfo info = new InfoBarTransitionInfo(infoBar, toShow, animationType);
323d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        mInfoBarTransitions.add(info);
324d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        processPendingInfoBars();
325d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
326d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
327d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    @Override
328d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    protected void onLayout(boolean changed, int l, int t, int r, int b) {
329d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // Hide the infobars when the keyboard is showing.
330d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        boolean isShowing = (getVisibility() == View.VISIBLE);
331d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        if (UiUtils.isKeyboardShowing(mActivity, this)) {
332d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            if (isShowing) {
333d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                setVisibility(View.INVISIBLE);
334d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            }
335d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        } else {
336d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            if (!isShowing) {
337d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                setVisibility(View.VISIBLE);
338d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            }
339d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
340d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        super.onLayout(changed, l, t, r, b);
341d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
342d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
343d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    /**
344d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * @return True when this container has been emptied and its native counterpart has been
345d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     *         destroyed.
346d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     */
347d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public boolean hasBeenDestroyed() {
348d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        return mDestroyed;
349d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
350d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
351d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    private void processPendingInfoBars() {
352d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        if (mAnimation != null || mInfoBarTransitions.isEmpty()) return;
353d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
354d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // Start animating what has to be animated.
355d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        InfoBarTransitionInfo info = mInfoBarTransitions.remove();
356d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        View toShow = info.toShow;
357d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        ContentWrapperView targetView;
358d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
359d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        addToParentView();
360d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
361d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        if (info.animationType == AnimationHelper.ANIMATION_TYPE_SHOW) {
362d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            targetView = info.target.getContentWrapper(true);
363d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            assert mInfoBars.contains(info.target);
364d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            toShow = targetView.detachCurrentView();
365d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            addView(targetView, mInfoBarsOnTop ? getChildCount() : 0,
366d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                    new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
367d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        } else {
368d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            targetView = info.target.getContentWrapper(false);
369d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
370d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
371d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // Kick off the animation.
372d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        mAnimation = new AnimationHelper(this, targetView, info.target, toShow, info.animationType);
373d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        mAnimation.start();
374d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
375d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
376d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    // Called by the tab when it has started loading a new page.
377d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public void onPageStarted(String url) {
378d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        LinkedList<InfoBar> barsToRemove = new LinkedList<InfoBar>();
379d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
380d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        for (InfoBar infoBar : mInfoBars) {
381d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            if (infoBar.shouldExpire(url)) {
382d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                barsToRemove.add(infoBar);
383d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            }
384d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
385d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
386d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        for (InfoBar infoBar : barsToRemove) {
3878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            infoBar.dismissJavaOnlyInfoBar();
388d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
389d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
390d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
391d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    /**
392d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * Returns the id of the tab we are associated with.
393d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     */
394d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public int getTabId() {
395d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        return mTabId;
396d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
397d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
398d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public void destroy() {
399d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        mDestroyed = true;
400d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        removeAllViews();
401d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        if (mNativeInfoBarContainer != 0) {
402d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            nativeDestroy(mNativeInfoBarContainer);
403d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
404d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        mInfoBarTransitions.clear();
405d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
406d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
407d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    /**
408d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * @return all of the InfoBars held in this container.
409d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     */
410d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    @VisibleForTesting
411d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public ArrayList<InfoBar> getInfoBars() {
412d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        return mInfoBars;
413d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
414d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
415d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    /**
416d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * Dismisses all {@link AutoLoginInfoBar}s in this {@link InfoBarContainer} that are for
417d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * {@code accountName} and {@code authToken}.  This also resets all {@link InfoBar}s that are
418d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * for a different request.
419d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * @param accountName The name of the account request is being accessed for.
420d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * @param authToken The authentication token access is being requested for.
421d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * @param success Whether or not the authentication attempt was successful.
422d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * @param result The resulting token for the auto login request (ignored if {@code success} is
423d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     *               {@code false}.
424d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     */
425d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public void processAutoLogin(String accountName, String authToken, boolean success,
426d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            String result) {
427d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        mAutoLoginDelegate.dismissAutoLogins(accountName, authToken, success, result);
428d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
429d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
430d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    /**
431d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * Dismiss all auto logins infobars without processing any result.
432d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     */
433d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public void dismissAutoLoginInfoBars() {
434d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        mAutoLoginDelegate.dismissAutoLogins("", "", false, "");
435d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
436d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
437d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public void prepareTransition(View toShow) {
438d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        if (toShow != null) {
439d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            // In order to animate the addition of the infobar, we need a layout first.
440d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            // Attach the child to invisible layout so that we can get measurements for it without
441d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            // moving everything in the real container.
442d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            ViewGroup parent = (ViewGroup) toShow.getParent();
443d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            if (parent != null) parent.removeView(toShow);
444d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
445d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            assert mAnimationSizer.getParent() == null;
446d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            mParentView.addView(mAnimationSizer, createLayoutParams());
447d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            mAnimationSizer.addView(toShow, 0,
448d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                    new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
449d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            mAnimationSizer.requestLayout();
450d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
451d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
452d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
453d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public void startTransition() {
454d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        if (mInfoBarsOnTop) {
455d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            // We need to clip this view to its bounds while it is animated because the layout's
456d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            // z-ordering puts it on top of other infobars as it's being animated.
457d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            ApiCompatibilityUtils.postInvalidateOnAnimation(this);
458d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
459d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
460d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
461d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    /**
462d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * Finishes off whatever animation is running.
463d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     */
464d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public void finishTransition() {
465d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        assert mAnimation != null;
466d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
467d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // If the InfoBar was hidden, get rid of its View entirely.
468d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        if (mAnimation.getAnimationType() == AnimationHelper.ANIMATION_TYPE_HIDE) {
469d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            removeView(mAnimation.getTarget());
470d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
471d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
472d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // Reset all translations and put everything where they need to be.
473d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        for (int i = 0; i < getChildCount(); ++i) {
474d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            View view = getChildAt(i);
475d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            view.setTranslationY(0);
476d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
477d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        requestLayout();
478d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
479d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // If there are no infobars shown, there is no need to keep the infobar container in the
480d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // view hierarchy.
481d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        if (getChildCount() == 0) {
482d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            removeFromParentView();
483d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
484d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
485d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        if (mAnimationSizer.getParent() != null) {
486d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            ((ViewGroup) mAnimationSizer.getParent()).removeView(mAnimationSizer);
487d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
488d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
489d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        // Notify interested parties and move on to the next animation.
490d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        if (mAnimationListener != null) {
491d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            mAnimationListener.notifyAnimationFinished(mAnimation.getAnimationType());
492d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
493d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        mAnimation = null;
494d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        processPendingInfoBars();
495d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
496d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
497d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    /**
498d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * Searches a given view's child views for an instance of {@link InfoBarContainer}.
499d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     *
500d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * @param parentView View to be searched for
501d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     * @return {@link InfoBarContainer} instance if it's one of the child views;
502d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     *     otherwise {@code null}.
503d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)     */
504d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    public static InfoBarContainer childViewOf(ViewGroup parentView) {
505d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        for (int i = 0; i < parentView.getChildCount(); i++) {
506d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            if (parentView.getChildAt(i) instanceof InfoBarContainer) {
507d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                return (InfoBarContainer) parentView.getChildAt(i);
508d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)            }
509d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        }
510d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        return null;
511d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
512d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
513f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    public long getNative() {
514d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        return mNativeInfoBarContainer;
515d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
516d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
517f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native long nativeInit(long webContentsPtr, AutoLoginDelegate autoLoginDelegate);
518d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
519f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    private native void nativeDestroy(long nativeInfoBarContainerAndroid);
520d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
521