Home | History | Annotate | Download | only in infobar
      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.
      4 
      5 package org.chromium.chrome.browser.infobar;
      6 
      7 import android.content.Context;
      8 import android.view.View;
      9 
     10 import org.chromium.base.CalledByNative;
     11 import org.chromium.base.VisibleForTesting;
     12 import org.chromium.chrome.R;
     13 
     14 /**
     15  * The base class for all InfoBar classes.
     16  * Note that infobars expire by default when a new navigation occurs.
     17  * Make sure to use setExpireOnNavigation(false) if you want an infobar to be sticky.
     18  */
     19 public abstract class InfoBar implements InfoBarView {
     20     private static final String TAG = "InfoBar";
     21 
     22     /**
     23      * Possible labels of all the infobar buttons.
     24      *
     25      * Make sure this set of values is aligned with the C++ correspondent in
     26      * infobar_android.h
     27      */
     28     public static final int ACTION_TYPE_NONE = 0;
     29 
     30     // Confirm infobar
     31     public static final int ACTION_TYPE_OK = 1;
     32     public static final int ACTION_TYPE_CANCEL = 2;
     33 
     34     // Translate infobar
     35     public static final int ACTION_TYPE_TRANSLATE = 3;
     36     public static final int ACTION_TYPE_TRANSLATE_SHOW_ORIGINAL = 4;
     37 
     38     private final int mIconDrawableId;
     39     private final CharSequence mMessage;
     40 
     41     private InfoBarListeners.Dismiss mListener;
     42     private ContentWrapperView mContentView;
     43     private InfoBarContainer mContainer;
     44     private Context mContext;
     45 
     46     private boolean mExpireOnNavigation;
     47     private boolean mIsDismissed;
     48     private boolean mControlsEnabled;
     49 
     50     // This cannot be private until the swap in place infrastructure is
     51     // improved since subclasses need to access a possibly replaced native
     52     // pointer.
     53     protected long mNativeInfoBarPtr;
     54 
     55     // Used by tests to reference infobars.
     56     private final int mId;
     57     private static int sIdCounter = 0;
     58     private static int generateId() {
     59         return sIdCounter++;
     60     }
     61 
     62     /**
     63      * @param listener Listens to when buttons have been clicked on the InfoBar.
     64      * @param iconDrawableId ID of the resource to use for the Icon.  If 0, no icon will be shown.
     65      * @param message The message to show in the infobar.
     66      */
     67     public InfoBar(InfoBarListeners.Dismiss listener, int iconDrawableId, CharSequence message) {
     68         mListener = listener;
     69         mId = generateId();
     70         mIconDrawableId = iconDrawableId;
     71         mMessage = message;
     72         mExpireOnNavigation = true;
     73     }
     74 
     75     /**
     76      * @return The message shown in the infobar, useful for accessibility.
     77      */
     78     public CharSequence getMessage() {
     79         return mMessage;
     80     }
     81 
     82     /**
     83      * Stores a pointer to the native-side counterpart of this InfoBar.
     84      * @param nativeInfoBarPtr Pointer to the NativeInfoBar.
     85      */
     86     protected void setNativeInfoBar(long nativeInfoBarPtr) {
     87         if (nativeInfoBarPtr != 0) {
     88             // The native code takes care of expiring infobars on navigations.
     89             mExpireOnNavigation = false;
     90             mNativeInfoBarPtr = nativeInfoBarPtr;
     91         }
     92     }
     93 
     94     /**
     95      * Change the pointer to the native-side counterpart of this InfoBar.  Native-side code is
     96      * responsible for managing the cleanup of the pointer.
     97      * @param newInfoBarPtr Pointer to the NativeInfoBar.
     98      */
     99     protected void replaceNativePointer(long newInfoBarPtr) {
    100         mNativeInfoBarPtr = newInfoBarPtr;
    101     }
    102 
    103     /**
    104      * Determine if the infobar should be dismissed when a new page starts loading. Calling
    105      * setExpireOnNavigation(true/false) causes this method always to return true/false.
    106      * This only applies to java-only infobars. C++ infobars will use the same logic
    107      * as other platforms so they are not attempted to be dismissed twice.
    108      * It should really be removed once all infobars have a C++ counterpart.
    109      */
    110     public final boolean shouldExpire() {
    111         return mExpireOnNavigation && mNativeInfoBarPtr == 0;
    112     }
    113 
    114     // Sets whether the bar should be dismissed when a navigation occurs.
    115     public void setExpireOnNavigation(boolean expireOnNavigation) {
    116         mExpireOnNavigation = expireOnNavigation;
    117     }
    118 
    119     /**
    120      * @return true if this java infobar owns this {@code nativePointer}
    121      */
    122     boolean ownsNativeInfoBar(long nativePointer) {
    123         return mNativeInfoBarPtr == nativePointer;
    124     }
    125 
    126     /**
    127      * @return whether or not the InfoBar has been dismissed.
    128      */
    129     protected boolean isDismissed() {
    130         return mIsDismissed;
    131     }
    132 
    133     /**
    134      * Sets the Context used when creating the InfoBar.
    135      */
    136     protected void setContext(Context context) {
    137         mContext = context;
    138     }
    139 
    140     /**
    141      * @return The Context used to create the InfoBar.  This will be null until the InfoBar is added
    142      *         to the InfoBarContainer, and should never be null afterward.
    143      */
    144     protected Context getContext() {
    145         return mContext;
    146     }
    147 
    148     /**
    149      * Creates the View that represents the InfoBar.
    150      * @return The View representing the InfoBar.
    151      */
    152     protected final View createView() {
    153         assert mContext != null;
    154 
    155         InfoBarLayout layout = new InfoBarLayout(mContext, this, mIconDrawableId, mMessage);
    156         createContent(layout);
    157         return layout;
    158     }
    159 
    160     /**
    161      * Used to close a java only infobar.
    162      */
    163     public void dismissJavaOnlyInfoBar() {
    164         assert mNativeInfoBarPtr == 0;
    165         if (closeInfoBar() && mListener != null) {
    166             mListener.onInfoBarDismissed(this);
    167         }
    168     }
    169 
    170     /**
    171      * @return whether the infobar actually needed closing.
    172      */
    173     @CalledByNative
    174     public boolean closeInfoBar() {
    175         if (!mIsDismissed) {
    176             mIsDismissed = true;
    177             if (!mContainer.hasBeenDestroyed()) {
    178                 // If the container was destroyed, it's already been emptied of all its infobars.
    179                 mContainer.removeInfoBar(this);
    180             }
    181             return true;
    182         }
    183         return false;
    184     }
    185 
    186     protected ContentWrapperView getContentWrapper(boolean createIfNotFound) {
    187         if (mContentView == null && createIfNotFound) {
    188             mContentView = new ContentWrapperView(getContext(), this, createView());
    189             mContentView.setFocusable(false);
    190         }
    191         return mContentView;
    192     }
    193 
    194     protected InfoBarContainer getInfoBarContainer() {
    195         return mContainer;
    196     }
    197 
    198     /**
    199      * @return The content view for the info bar.
    200      */
    201     @VisibleForTesting
    202     public ContentWrapperView getContentWrapper() {
    203         return getContentWrapper(true);
    204     }
    205 
    206     void setInfoBarContainer(InfoBarContainer container) {
    207         mContainer = container;
    208     }
    209 
    210     public boolean areControlsEnabled() {
    211         return mControlsEnabled;
    212     }
    213 
    214     @Override
    215     public void setControlsEnabled(boolean state) {
    216         mControlsEnabled = state;
    217 
    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);
    228         }
    229     }
    230 
    231     @Override
    232     public void onButtonClicked(boolean isPrimaryButton) {
    233     }
    234 
    235     @Override
    236     public void onLinkClicked() {
    237         if (mNativeInfoBarPtr != 0) {
    238             nativeOnLinkClicked(mNativeInfoBarPtr);
    239         }
    240     }
    241 
    242     @Override
    243     public void createContent(InfoBarLayout layout) {
    244     }
    245 
    246     /**
    247      * Returns the id of the tab this infobar is showing into.
    248      */
    249     public int getTabId() {
    250         return mContainer.getTabId();
    251     }
    252 
    253     @VisibleForTesting
    254     public int getId() {
    255         return mId;
    256     }
    257 
    258     @VisibleForTesting
    259     public void setDismissedListener(InfoBarListeners.Dismiss listener) {
    260         mListener = listener;
    261     }
    262 
    263     protected native void nativeOnLinkClicked(long nativeInfoBarAndroid);
    264     protected native void nativeOnButtonClicked(
    265             long nativeInfoBarAndroid, int action, String actionValue);
    266     protected native void nativeOnCloseButtonClicked(long nativeInfoBarAndroid);
    267 }
    268