| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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.infobar; | 5 package org.chromium.chrome.browser.infobar; |
| 6 | 6 |
| 7 import android.content.Context; | 7 import android.content.Context; |
| 8 import android.view.Gravity; | 8 import android.view.Gravity; |
| 9 import android.view.View; |
| 10 import android.view.View.OnLayoutChangeListener; |
| 9 import android.view.ViewGroup; | 11 import android.view.ViewGroup; |
| 10 import android.widget.FrameLayout; | 12 import android.widget.FrameLayout; |
| 11 | 13 |
| 12 import org.chromium.base.ObserverList; | 14 import org.chromium.base.ObserverList; |
| 13 import org.chromium.base.VisibleForTesting; | 15 import org.chromium.base.VisibleForTesting; |
| 14 import org.chromium.base.annotations.CalledByNative; | 16 import org.chromium.base.annotations.CalledByNative; |
| 15 import org.chromium.chrome.browser.banners.SwipableOverlayView; | 17 import org.chromium.chrome.browser.banners.SwipableOverlayView; |
| 18 import org.chromium.chrome.browser.tab.EmptyTabObserver; |
| 16 import org.chromium.chrome.browser.tab.Tab; | 19 import org.chromium.chrome.browser.tab.Tab; |
| 20 import org.chromium.chrome.browser.tab.TabObserver; |
| 17 import org.chromium.content.browser.ContentViewCore; | 21 import org.chromium.content.browser.ContentViewCore; |
| 18 import org.chromium.content_public.browser.WebContents; | 22 import org.chromium.content_public.browser.WebContents; |
| 23 import org.chromium.ui.UiUtils; |
| 19 import org.chromium.ui.base.DeviceFormFactor; | 24 import org.chromium.ui.base.DeviceFormFactor; |
| 20 | 25 |
| 21 import java.util.ArrayList; | 26 import java.util.ArrayList; |
| 22 | 27 |
| 23 | 28 |
| 24 /** | 29 /** |
| 25 * A container for all the infobars of a specific tab. | 30 * A container for all the infobars of a specific tab. |
| 26 * Note that infobars creation can be initiated from Java of from native code. | 31 * Note that infobars creation can be initiated from Java of from native code. |
| 27 * When initiated from native code, special code is needed to keep the Java and
native infobar in | 32 * When initiated from native code, special code is needed to keep the Java and
native infobar in |
| 28 * sync, see NativeInfoBar. | 33 * sync, see NativeInfoBar. |
| 29 */ | 34 */ |
| 30 public class InfoBarContainer extends SwipableOverlayView { | 35 public class InfoBarContainer extends SwipableOverlayView { |
| 31 private static final String TAG = "InfoBarContainer"; | 36 private static final String TAG = "InfoBarContainer"; |
| 32 | 37 |
| 33 /** Top margin, including the toolbar and tabstrip height and 48dp of web co
ntents. */ | 38 /** Top margin, including the toolbar and tabstrip height and 48dp of web co
ntents. */ |
| 34 private static final int TOP_MARGIN_PHONE_DP = 104; | 39 private static final int TOP_MARGIN_PHONE_DP = 104; |
| 35 private static final int TOP_MARGIN_TABLET_DP = 144; | 40 private static final int TOP_MARGIN_TABLET_DP = 144; |
| 36 | 41 |
| 42 /** Length of the animation to fade the InfoBarContainer back into View. */ |
| 43 private static final long REATTACH_FADE_IN_MS = 250; |
| 44 |
| 37 /** Whether or not the InfoBarContainer is allowed to hide when the user scr
olls. */ | 45 /** Whether or not the InfoBarContainer is allowed to hide when the user scr
olls. */ |
| 38 private static boolean sIsAllowedToAutoHide = true; | 46 private static boolean sIsAllowedToAutoHide = true; |
| 39 | 47 |
| 40 /** | 48 /** |
| 41 * A listener for the InfoBar animations. | 49 * A listener for the InfoBar animations. |
| 42 */ | 50 */ |
| 43 public interface InfoBarAnimationListener { | 51 public interface InfoBarAnimationListener { |
| 44 public static final int ANIMATION_TYPE_SHOW = 0; | 52 public static final int ANIMATION_TYPE_SHOW = 0; |
| 45 public static final int ANIMATION_TYPE_SWAP = 1; | 53 public static final int ANIMATION_TYPE_SWAP = 1; |
| 46 public static final int ANIMATION_TYPE_HIDE = 2; | 54 public static final int ANIMATION_TYPE_HIDE = 2; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 65 | 73 |
| 66 /** | 74 /** |
| 67 * Called when an {@link InfoBar} is about to be removed (before the ani
mation). | 75 * Called when an {@link InfoBar} is about to be removed (before the ani
mation). |
| 68 * @param container The notifying {@link InfoBarContainer} | 76 * @param container The notifying {@link InfoBarContainer} |
| 69 * @param infoBar An {@link InfoBar} being removed | 77 * @param infoBar An {@link InfoBar} being removed |
| 70 * @param isLast Whether the infobar container is going to be empty | 78 * @param isLast Whether the infobar container is going to be empty |
| 71 */ | 79 */ |
| 72 void onRemoveInfoBar(InfoBarContainer container, InfoBar infoBar, boolea
n isLast); | 80 void onRemoveInfoBar(InfoBarContainer container, InfoBar infoBar, boolea
n isLast); |
| 73 } | 81 } |
| 74 | 82 |
| 83 /** Toggles visibility of the InfoBarContainer when the keyboard appears. */ |
| 84 private OnLayoutChangeListener mParentLayoutListener = new OnLayoutChangeLis
tener() { |
| 85 @Override |
| 86 public void onLayoutChange(View v, int left, int top, int right, int bot
tom, int oldLeft, |
| 87 int oldTop, int oldRight, int oldBottom) { |
| 88 // This check is posted because this is triggered during the layout
pass of the parent. |
| 89 // Setting the visibility on this View (its child) immediately resul
ts in Android giving |
| 90 // warnings about triggering another layout (via setVisibility) duri
ng the current one. |
| 91 post(new Runnable() { |
| 92 @Override |
| 93 public void run() { |
| 94 // Hide the View when the keyboard is showing. |
| 95 boolean isShowing = (getVisibility() == View.VISIBLE); |
| 96 if (UiUtils.isKeyboardShowing(getContext(), InfoBarContainer
.this)) { |
| 97 if (isShowing) { |
| 98 setVisibility(View.GONE); |
| 99 } |
| 100 } else { |
| 101 if (!isShowing && !mIsObscured) { |
| 102 setVisibility(View.VISIBLE); |
| 103 } |
| 104 } |
| 105 } |
| 106 }); |
| 107 } |
| 108 }; |
| 109 |
| 110 /** Resets the state of the InfoBarContainer when the user navigates. */ |
| 111 private final TabObserver mTabObserver = new EmptyTabObserver() { |
| 112 @Override |
| 113 public void onDidNavigateMainFrame(Tab tab, String url, String baseUrl, |
| 114 boolean isNavigationToDifferentPage, boolean isFragmentNavigatio
n, |
| 115 int statusCode) { |
| 116 setIsObscuredByOtherView(false); |
| 117 } |
| 118 }; |
| 119 |
| 75 private final InfoBarContainerLayout mLayout; | 120 private final InfoBarContainerLayout mLayout; |
| 76 | 121 |
| 77 /** Native InfoBarContainer pointer which will be set by nativeInit(). */ | 122 /** Native InfoBarContainer pointer which will be set by nativeInit(). */ |
| 78 private final long mNativeInfoBarContainer; | 123 private final long mNativeInfoBarContainer; |
| 79 | 124 |
| 80 private final Context mContext; | |
| 81 | |
| 82 /** The list of all InfoBars in this container, regardless of whether they'v
e been shown yet. */ | 125 /** The list of all InfoBars in this container, regardless of whether they'v
e been shown yet. */ |
| 83 private final ArrayList<InfoBar> mInfoBars = new ArrayList<InfoBar>(); | 126 private final ArrayList<InfoBar> mInfoBars = new ArrayList<InfoBar>(); |
| 84 | 127 |
| 85 /** True when this container has been emptied and its native counterpart has
been destroyed. */ | 128 /** True when this container has been emptied and its native counterpart has
been destroyed. */ |
| 86 private boolean mDestroyed = false; | 129 private boolean mDestroyed = false; |
| 87 | 130 |
| 88 /** The id of the tab associated with us. Set to Tab.INVALID_TAB_ID if no ta
b is associated. */ | 131 /** The id of the tab associated with us. Set to Tab.INVALID_TAB_ID if no ta
b is associated. */ |
| 89 private int mTabId; | 132 private int mTabId; |
| 90 | 133 |
| 91 /** Parent view that contains the InfoBarContainerLayout. */ | 134 /** Parent view that contains the InfoBarContainerLayout. */ |
| 92 private ViewGroup mParentView; | 135 private ViewGroup mParentView; |
| 93 | 136 |
| 137 /** Whether or not another View is occupying the same space as this one. */ |
| 138 private boolean mIsObscured; |
| 139 |
| 94 private final ObserverList<InfoBarContainerObserver> mObservers = | 140 private final ObserverList<InfoBarContainerObserver> mObservers = |
| 95 new ObserverList<InfoBarContainerObserver>(); | 141 new ObserverList<InfoBarContainerObserver>(); |
| 96 | 142 |
| 97 public InfoBarContainer(Context context, int tabId, ViewGroup parentView, Ta
b tab) { | 143 public InfoBarContainer(Context context, int tabId, ViewGroup parentView, Ta
b tab) { |
| 98 super(context, null); | 144 super(context, null); |
| 99 tab.addObserver(getTabObserver()); | 145 tab.addObserver(mTabObserver); |
| 100 | 146 |
| 101 // TODO(newt): move this workaround into the infobar views if/when they'
re scrollable. | 147 // TODO(newt): move this workaround into the infobar views if/when they'
re scrollable. |
| 102 // Workaround for http://crbug.com/407149. See explanation in onMeasure(
) below. | 148 // Workaround for http://crbug.com/407149. See explanation in onMeasure(
) below. |
| 103 setVerticalScrollBarEnabled(false); | 149 setVerticalScrollBarEnabled(false); |
| 104 | 150 |
| 105 FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( | 151 FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( |
| 106 LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, Gravity.BO
TTOM); | 152 LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, Gravity.BO
TTOM); |
| 107 int topMarginDp = DeviceFormFactor.isTablet(context) | 153 int topMarginDp = DeviceFormFactor.isTablet(context) |
| 108 ? TOP_MARGIN_TABLET_DP : TOP_MARGIN_PHONE_DP; | 154 ? TOP_MARGIN_TABLET_DP : TOP_MARGIN_PHONE_DP; |
| 109 lp.topMargin = Math.round(topMarginDp * getResources().getDisplayMetrics
().density); | 155 lp.topMargin = Math.round(topMarginDp * getResources().getDisplayMetrics
().density); |
| 110 setLayoutParams(lp); | 156 setLayoutParams(lp); |
| 111 | 157 |
| 112 mContext = context; | |
| 113 mTabId = tabId; | 158 mTabId = tabId; |
| 114 mParentView = parentView; | 159 mParentView = parentView; |
| 115 | 160 |
| 116 mLayout = new InfoBarContainerLayout(context); | 161 mLayout = new InfoBarContainerLayout(context); |
| 117 addView(mLayout, new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, | 162 addView(mLayout, new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, |
| 118 LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL)); | 163 LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL)); |
| 119 | 164 |
| 120 // Chromium's InfoBarContainer may add an InfoBar immediately during thi
s initialization | 165 // Chromium's InfoBarContainer may add an InfoBar immediately during thi
s initialization |
| 121 // call, so make sure everything in the InfoBarContainer is completely r
eady beforehand. | 166 // call, so make sure everything in the InfoBarContainer is completely r
eady beforehand. |
| 122 mNativeInfoBarContainer = nativeInit(); | 167 mNativeInfoBarContainer = nativeInit(); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 /** | 199 /** |
| 155 * Returns true if any animations are pending or in progress. | 200 * Returns true if any animations are pending or in progress. |
| 156 */ | 201 */ |
| 157 @VisibleForTesting | 202 @VisibleForTesting |
| 158 public boolean isAnimating() { | 203 public boolean isAnimating() { |
| 159 return mLayout.isAnimating(); | 204 return mLayout.isAnimating(); |
| 160 } | 205 } |
| 161 | 206 |
| 162 private void addToParentView() { | 207 private void addToParentView() { |
| 163 super.addToParentView(mParentView); | 208 super.addToParentView(mParentView); |
| 209 if (mParentView != null) { |
| 210 mParentView.addOnLayoutChangeListener(mParentLayoutListener); |
| 211 } |
| 164 } | 212 } |
| 165 | 213 |
| 166 /** | 214 /** |
| 167 * Called when the parent {@link android.view.ViewGroup} has changed for | 215 * Called when the parent {@link android.view.ViewGroup} has changed for |
| 168 * this container. | 216 * this container. |
| 169 */ | 217 */ |
| 170 public void onParentViewChanged(int tabId, ViewGroup parentView) { | 218 public void onParentViewChanged(int tabId, ViewGroup parentView) { |
| 171 mTabId = tabId; | 219 mTabId = tabId; |
| 172 mParentView = parentView; | 220 mParentView = parentView; |
| 173 | 221 |
| 174 removeFromParentView(); | 222 removeFromParentView(); |
| 175 addToParentView(); | 223 addToParentView(); |
| 176 } | 224 } |
| 177 | 225 |
| 226 @Override |
| 227 public boolean removeFromParentView() { |
| 228 if (mParentView != null) { |
| 229 mParentView.addOnLayoutChangeListener(mParentLayoutListener); |
| 230 } |
| 231 return super.removeFromParentView(); |
| 232 } |
| 233 |
| 178 /** | 234 /** |
| 179 * Adds an InfoBar to the view hierarchy. | 235 * Adds an InfoBar to the view hierarchy. |
| 180 * @param infoBar InfoBar to add to the View hierarchy. | 236 * @param infoBar InfoBar to add to the View hierarchy. |
| 181 */ | 237 */ |
| 182 @CalledByNative | 238 @CalledByNative |
| 183 private void addInfoBar(InfoBar infoBar) { | 239 private void addInfoBar(InfoBar infoBar) { |
| 184 assert !mDestroyed; | 240 assert !mDestroyed; |
| 185 if (infoBar == null) { | 241 if (infoBar == null) { |
| 186 return; | 242 return; |
| 187 } | 243 } |
| 188 if (mInfoBars.contains(infoBar)) { | 244 if (mInfoBars.contains(infoBar)) { |
| 189 assert false : "Trying to add an info bar that has already been adde
d."; | 245 assert false : "Trying to add an info bar that has already been adde
d."; |
| 190 return; | 246 return; |
| 191 } | 247 } |
| 192 addToParentView(); | 248 addToParentView(); |
| 193 | 249 |
| 194 // We notify observers immediately (before the animation starts). | 250 // We notify observers immediately (before the animation starts). |
| 195 for (InfoBarContainerObserver observer : mObservers) { | 251 for (InfoBarContainerObserver observer : mObservers) { |
| 196 observer.onAddInfoBar(this, infoBar, mInfoBars.isEmpty()); | 252 observer.onAddInfoBar(this, infoBar, mInfoBars.isEmpty()); |
| 197 } | 253 } |
| 198 | 254 |
| 199 // We add the infobar immediately to mInfoBars but we wait for the anima
tion to end to | 255 // We add the infobar immediately to mInfoBars but we wait for the anima
tion to end to |
| 200 // notify it's been added, as tests rely on this notification but expect
s the infobar view | 256 // notify it's been added, as tests rely on this notification but expect
s the infobar view |
| 201 // to be available when they get the notification. | 257 // to be available when they get the notification. |
| 202 mInfoBars.add(infoBar); | 258 mInfoBars.add(infoBar); |
| 203 infoBar.setContext(mContext); | 259 infoBar.setContext(getContext()); |
| 204 infoBar.setInfoBarContainer(this); | 260 infoBar.setInfoBarContainer(this); |
| 205 infoBar.createView(); | 261 infoBar.createView(); |
| 206 | 262 |
| 207 mLayout.addInfoBar(infoBar); | 263 mLayout.addInfoBar(infoBar); |
| 208 } | 264 } |
| 209 | 265 |
| 210 /** | 266 /** |
| 211 * Notifies that an infobar's View ({@link InfoBar#getView}) has changed. If
the infobar is | 267 * Notifies that an infobar's View ({@link InfoBar#getView}) has changed. If
the infobar is |
| 212 * visible, a view swapping animation will be run. | 268 * visible, a view swapping animation will be run. |
| 213 */ | 269 */ |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 | 310 |
| 255 /** | 311 /** |
| 256 * @return all of the InfoBars held in this container. | 312 * @return all of the InfoBars held in this container. |
| 257 */ | 313 */ |
| 258 @VisibleForTesting | 314 @VisibleForTesting |
| 259 public ArrayList<InfoBar> getInfoBarsForTesting() { | 315 public ArrayList<InfoBar> getInfoBarsForTesting() { |
| 260 return mInfoBars; | 316 return mInfoBars; |
| 261 } | 317 } |
| 262 | 318 |
| 263 /** | 319 /** |
| 320 * Tells this class that a View with higher priority is occupying the same s
pace. |
| 321 * |
| 322 * Causes this View to hide itself until the obscuring View goes away. |
| 323 * |
| 324 * @param isObscured Whether this View is obscured by another one. |
| 325 */ |
| 326 public void setIsObscuredByOtherView(boolean isObscured) { |
| 327 mIsObscured = isObscured; |
| 328 if (isObscured) { |
| 329 setVisibility(View.GONE); |
| 330 } else { |
| 331 setVisibility(View.VISIBLE); |
| 332 } |
| 333 } |
| 334 |
| 335 /** |
| 264 * Sets whether the InfoBarContainer is allowed to auto-hide when the user s
crolls the page. | 336 * Sets whether the InfoBarContainer is allowed to auto-hide when the user s
crolls the page. |
| 265 * Expected to be called when Touch Exploration is enabled. | 337 * Expected to be called when Touch Exploration is enabled. |
| 266 * @param isAllowed Whether auto-hiding is allowed. | 338 * @param isAllowed Whether auto-hiding is allowed. |
| 267 */ | 339 */ |
| 268 public static void setIsAllowedToAutoHide(boolean isAllowed) { | 340 public static void setIsAllowedToAutoHide(boolean isAllowed) { |
| 269 sIsAllowedToAutoHide = isAllowed; | 341 sIsAllowedToAutoHide = isAllowed; |
| 270 } | 342 } |
| 271 | 343 |
| 272 @Override | 344 @Override |
| 273 protected boolean isAllowedToAutoHide() { | 345 protected boolean isAllowedToAutoHide() { |
| 274 return sIsAllowedToAutoHide; | 346 return sIsAllowedToAutoHide; |
| 275 } | 347 } |
| 276 | 348 |
| 349 @Override |
| 350 protected void onAttachedToWindow() { |
| 351 super.onAttachedToWindow(); |
| 352 if (!mIsObscured) { |
| 353 setVisibility(VISIBLE); |
| 354 setAlpha(0f); |
| 355 animate().alpha(1f).setDuration(REATTACH_FADE_IN_MS); |
| 356 } |
| 357 } |
| 358 |
| 277 private native long nativeInit(); | 359 private native long nativeInit(); |
| 278 private native void nativeSetWebContents( | 360 private native void nativeSetWebContents( |
| 279 long nativeInfoBarContainerAndroid, WebContents webContents); | 361 long nativeInfoBarContainerAndroid, WebContents webContents); |
| 280 private native void nativeDestroy(long nativeInfoBarContainerAndroid); | 362 private native void nativeDestroy(long nativeInfoBarContainerAndroid); |
| 281 } | 363 } |
| OLD | NEW |