// Copyright 2013 The Chromium Authors. All rights reserved. // 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.infobar; import android.content.Context; import android.view.View; import android.widget.ImageButton; import org.chromium.chrome.R; import com.google.common.annotations.VisibleForTesting; import org.chromium.base.CalledByNative; /** * The base class for all InfoBar classes. * Note that infobars expire by default when a new navigation occurs. * Make sure to use setExpireOnNavigation(false) if you want an infobar to be sticky. */ public abstract class InfoBar implements InfoBarView { private static final String TAG = "InfoBar"; /** * Possible labels of all the infobar buttons. * * Make sure this set of values is aligned with the C++ correspondent in * infobar_android.h */ public static final int ACTION_TYPE_NONE = 0; // Confirm infobar public static final int ACTION_TYPE_OK = 1; public static final int ACTION_TYPE_CANCEL = 2; // Translate infobar public static final int ACTION_TYPE_TRANSLATE = 3; public static final int ACTION_TYPE_TRANSLATE_SHOW_ORIGINAL = 4; // Background types public static final int BACKGROUND_TYPE_INFO = 0; public static final int BACKGROUND_TYPE_WARNING = 1; private final int mBackgroundType; private final int mIconDrawableId; private InfoBarListeners.Dismiss mListener; private ContentWrapperView mContentView; private InfoBarContainer mContainer; private Context mContext; private boolean mExpireOnNavigation; private boolean mIsDismissed; private boolean mControlsEnabled; // This cannot be private until the swap in place infrastructure is // improved since subclasses need to access a possibly replaced native // pointer. protected int mNativeInfoBarPtr; // Used by tests to reference infobars. private final int mId; private static int sIdCounter = 0; private static int generateId() { return sIdCounter++; } /** * @param listener Listens to when buttons have been clicked on the InfoBar. * @param backgroundType Background type to use (INFO or WARNING). * @param iconDrawableId ID of the resource to use for the Icon. If 0, no icon will be shown. */ public InfoBar(InfoBarListeners.Dismiss listener, int backgroundType, int iconDrawableId) { mListener = listener; mId = generateId(); mBackgroundType = backgroundType; mIconDrawableId = iconDrawableId; mExpireOnNavigation = true; } /** * Stores a pointer to the native-side counterpart of this InfoBar. * @param nativeInfoBarPtr Pointer to the NativeInfoBar. */ protected void setNativeInfoBar(int nativeInfoBarPtr) { if (nativeInfoBarPtr != 0) { // The native code takes care of expiring infobars on navigations. mExpireOnNavigation = false; mNativeInfoBarPtr = nativeInfoBarPtr; } } /** * Change the pointer to the native-side counterpart of this InfoBar. Native-side code is * responsible for managing the cleanup of the pointer. * @param nativeInfoBarPtr Pointer to the NativeInfoBar. */ protected void replaceNativePointer(int newInfoBarPtr) { mNativeInfoBarPtr = newInfoBarPtr; } // Determine if the infobar should be dismissed when |url| is loaded. Calling // setExpireOnNavigation(true/false) causes this method always to return true/false. // This only applies to java-only infobars. C++ infobars will use the same logic // as other platforms so they are not attempted to be dismissed twice. // It should really be removed once all infobars have a C++ counterpart. public final boolean shouldExpire(String url) { return mExpireOnNavigation && mNativeInfoBarPtr == 0; } // Sets whether the bar should be dismissed when a navigation occurs. public void setExpireOnNavigation(boolean expireOnNavigation) { mExpireOnNavigation = expireOnNavigation; } /** * @return true if this java infobar owns this {@code nativePointer} */ boolean ownsNativeInfoBar(int nativePointer) { return mNativeInfoBarPtr == nativePointer; } /** * @return whether or not the InfoBar has been dismissed. */ protected boolean isDismissed() { return mIsDismissed; } /** * Sets the Context used when creating the InfoBar. */ protected void setContext(Context context) { mContext = context; } /** * @return The Context used to create the InfoBar. This will be null until the InfoBar is added * to the InfoBarContainer, and should never be null afterward. */ protected Context getContext() { return mContext; } /** * Creates the View that represents the InfoBar. * @return The View representing the InfoBar. */ protected final View createView() { assert mContext != null; return new InfoBarLayout(mContext, this, mBackgroundType, mIconDrawableId); } /** * Used to close a java only infobar. */ public void dismissJavaOnlyInfoBar() { assert mNativeInfoBarPtr == 0; if (closeInfoBar() && mListener != null) { mListener.onInfoBarDismissed(this); } } /** * @return whether the infobar actually needed closing. */ @CalledByNative public boolean closeInfoBar() { if (!mIsDismissed) { mIsDismissed = true; if (!mContainer.hasBeenDestroyed()) { // If the container was destroyed, it's already been emptied of all its infobars. mContainer.removeInfoBar(this); } return true; } return false; } protected ContentWrapperView getContentWrapper(boolean createIfNotFound) { if (mContentView == null && createIfNotFound) { mContentView = new ContentWrapperView(getContext(), this, mBackgroundType, createView(), getInfoBarContainer().areInfoBarsOnTop()); mContentView.setFocusable(false); } return mContentView; } protected InfoBarContainer getInfoBarContainer() { return mContainer; } /** * @return The content view for the info bar. */ public ContentWrapperView getContentWrapper() { return getContentWrapper(true); } void setInfoBarContainer(InfoBarContainer container) { mContainer = container; } public boolean areControlsEnabled() { return mControlsEnabled; } @Override public void setControlsEnabled(boolean state) { mControlsEnabled = state; // Handle the close button. if (mContentView != null) { View closeButton = mContentView.findViewById(R.id.infobar_close_button); if (closeButton != null) closeButton.setEnabled(state); } } @Override public void onButtonClicked(boolean isPrimaryButton) { } @Override public void onLinkClicked() { nativeOnLinkClicked(mNativeInfoBarPtr); } @Override public void createContent(InfoBarLayout layout) { } @Override public String getPrimaryButtonText(Context context) { return null; } @Override public String getSecondaryButtonText(Context context) { return null; } /** * Returns the id of the tab this infobar is showing into. */ public int getTabId() { return mContainer.getTabId(); } @VisibleForTesting public int getId() { return mId; } @VisibleForTesting public void setDismissedListener(InfoBarListeners.Dismiss listener) { mListener = listener; } protected native void nativeOnLinkClicked(int nativeInfoBarAndroid); protected native void nativeOnButtonClicked( int nativeInfoBarAndroid, int action, String actionValue); protected native void nativeOnCloseButtonClicked(int nativeInfoBarAndroid); }