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
3 // found in the LICENSE file.
5 package org.chromium.chrome.browser.infobar;
7 import android.content.Context;
8 import android.view.View;
10 import com.google.common.annotations.VisibleForTesting;
12 import org.chromium.base.CalledByNative;
13 import org.chromium.chrome.R;
16 * The base class for all InfoBar classes.
17 * Note that infobars expire by default when a new navigation occurs.
18 * Make sure to use setExpireOnNavigation(false) if you want an infobar to be sticky.
20 public abstract class InfoBar implements InfoBarView {
21 private static final String TAG = "InfoBar";
24 * Possible labels of all the infobar buttons.
26 * Make sure this set of values is aligned with the C++ correspondent in
29 public static final int ACTION_TYPE_NONE = 0;
32 public static final int ACTION_TYPE_OK = 1;
33 public static final int ACTION_TYPE_CANCEL = 2;
36 public static final int ACTION_TYPE_TRANSLATE = 3;
37 public static final int ACTION_TYPE_TRANSLATE_SHOW_ORIGINAL = 4;
39 private final int mIconDrawableId;
40 private final CharSequence mMessage;
42 private InfoBarListeners.Dismiss mListener;
43 private ContentWrapperView mContentView;
44 private InfoBarContainer mContainer;
45 private Context mContext;
47 private boolean mExpireOnNavigation;
48 private boolean mIsDismissed;
49 private boolean mControlsEnabled;
51 // This cannot be private until the swap in place infrastructure is
52 // improved since subclasses need to access a possibly replaced native
54 protected long mNativeInfoBarPtr;
56 // Used by tests to reference infobars.
57 private final int mId;
58 private static int sIdCounter = 0;
59 private static int generateId() {
64 * @param listener Listens to when buttons have been clicked on the InfoBar.
65 * @param iconDrawableId ID of the resource to use for the Icon. If 0, no icon will be shown.
66 * @param message The message to show in the infobar.
68 public InfoBar(InfoBarListeners.Dismiss listener, int iconDrawableId, CharSequence message) {
71 mIconDrawableId = iconDrawableId;
73 mExpireOnNavigation = true;
77 * @return The message shown in the infobar, useful for accessibility.
79 public CharSequence getMessage() {
84 * Stores a pointer to the native-side counterpart of this InfoBar.
85 * @param nativeInfoBarPtr Pointer to the NativeInfoBar.
87 protected void setNativeInfoBar(long nativeInfoBarPtr) {
88 if (nativeInfoBarPtr != 0) {
89 // The native code takes care of expiring infobars on navigations.
90 mExpireOnNavigation = false;
91 mNativeInfoBarPtr = nativeInfoBarPtr;
96 * Change the pointer to the native-side counterpart of this InfoBar. Native-side code is
97 * responsible for managing the cleanup of the pointer.
98 * @param newInfoBarPtr Pointer to the NativeInfoBar.
100 protected void replaceNativePointer(long newInfoBarPtr) {
101 mNativeInfoBarPtr = newInfoBarPtr;
105 * Determine if the infobar should be dismissed when a new page starts loading. Calling
106 * setExpireOnNavigation(true/false) causes this method always to return true/false.
107 * This only applies to java-only infobars. C++ infobars will use the same logic
108 * as other platforms so they are not attempted to be dismissed twice.
109 * It should really be removed once all infobars have a C++ counterpart.
111 public final boolean shouldExpire() {
112 return mExpireOnNavigation && mNativeInfoBarPtr == 0;
115 // Sets whether the bar should be dismissed when a navigation occurs.
116 public void setExpireOnNavigation(boolean expireOnNavigation) {
117 mExpireOnNavigation = expireOnNavigation;
121 * @return true if this java infobar owns this {@code nativePointer}
123 boolean ownsNativeInfoBar(long nativePointer) {
124 return mNativeInfoBarPtr == nativePointer;
128 * @return whether or not the InfoBar has been dismissed.
130 protected boolean isDismissed() {
135 * Sets the Context used when creating the InfoBar.
137 protected void setContext(Context context) {
142 * @return The Context used to create the InfoBar. This will be null until the InfoBar is added
143 * to the InfoBarContainer, and should never be null afterward.
145 protected Context getContext() {
150 * Creates the View that represents the InfoBar.
151 * @return The View representing the InfoBar.
153 protected final View createView() {
154 assert mContext != null;
156 InfoBarLayout layout = new InfoBarLayout(mContext, this, mIconDrawableId, mMessage);
157 createContent(layout);
162 * Used to close a java only infobar.
164 public void dismissJavaOnlyInfoBar() {
165 assert mNativeInfoBarPtr == 0;
166 if (closeInfoBar() && mListener != null) {
167 mListener.onInfoBarDismissed(this);
172 * @return whether the infobar actually needed closing.
175 public boolean closeInfoBar() {
178 if (!mContainer.hasBeenDestroyed()) {
179 // If the container was destroyed, it's already been emptied of all its infobars.
180 mContainer.removeInfoBar(this);
187 protected ContentWrapperView getContentWrapper(boolean createIfNotFound) {
188 if (mContentView == null && createIfNotFound) {
189 mContentView = new ContentWrapperView(getContext(), this, createView());
190 mContentView.setFocusable(false);
195 protected InfoBarContainer getInfoBarContainer() {
200 * @return The content view for the info bar.
202 public ContentWrapperView getContentWrapper() {
203 return getContentWrapper(true);
206 void setInfoBarContainer(InfoBarContainer container) {
207 mContainer = container;
210 public boolean areControlsEnabled() {
211 return mControlsEnabled;
215 public void setControlsEnabled(boolean state) {
216 mControlsEnabled = state;
218 // Disable all buttons on the infobar.
219 if (mContentView != null) {
220 View closeButton = mContentView.findViewById(R.id.infobar_close_button);
221 View primaryButton = mContentView.findViewById(R.id.button_primary);
222 View secondaryButton = mContentView.findViewById(R.id.button_secondary);
223 View tertiaryButton = mContentView.findViewById(R.id.button_tertiary);
224 if (closeButton != null) closeButton.setEnabled(state);
225 if (primaryButton != null) primaryButton.setEnabled(state);
226 if (secondaryButton != null) secondaryButton.setEnabled(state);
227 if (tertiaryButton != null) tertiaryButton.setEnabled(state);
232 public void onButtonClicked(boolean isPrimaryButton) {
236 public void onLinkClicked() {
237 nativeOnLinkClicked(mNativeInfoBarPtr);
241 public void createContent(InfoBarLayout layout) {
245 * Returns the id of the tab this infobar is showing into.
247 public int getTabId() {
248 return mContainer.getTabId();
257 public void setDismissedListener(InfoBarListeners.Dismiss listener) {
258 mListener = listener;
261 protected native void nativeOnLinkClicked(long nativeInfoBarAndroid);
262 protected native void nativeOnButtonClicked(
263 long nativeInfoBarAndroid, int action, String actionValue);
264 protected native void nativeOnCloseButtonClicked(long nativeInfoBarAndroid);