403bf7d8d65d96d3f4c2d772c90c4aa085580857
[platform/framework/web/crosswalk.git] / src / chrome / android / java / src / org / chromium / chrome / browser / infobar / InfoBar.java
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 com.google.common.annotations.VisibleForTesting;
11
12 import org.chromium.base.CalledByNative;
13 import org.chromium.chrome.R;
14
15 /**
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.
19  */
20 public abstract class InfoBar implements InfoBarView {
21     private static final String TAG = "InfoBar";
22
23     /**
24      * Possible labels of all the infobar buttons.
25      *
26      * Make sure this set of values is aligned with the C++ correspondent in
27      * infobar_android.h
28      */
29     public static final int ACTION_TYPE_NONE = 0;
30
31     // Confirm infobar
32     public static final int ACTION_TYPE_OK = 1;
33     public static final int ACTION_TYPE_CANCEL = 2;
34
35     // Translate infobar
36     public static final int ACTION_TYPE_TRANSLATE = 3;
37     public static final int ACTION_TYPE_TRANSLATE_SHOW_ORIGINAL = 4;
38
39     private final int mIconDrawableId;
40     private final CharSequence mMessage;
41
42     private InfoBarListeners.Dismiss mListener;
43     private ContentWrapperView mContentView;
44     private InfoBarContainer mContainer;
45     private Context mContext;
46
47     private boolean mExpireOnNavigation;
48     private boolean mIsDismissed;
49     private boolean mControlsEnabled;
50
51     // This cannot be private until the swap in place infrastructure is
52     // improved since subclasses need to access a possibly replaced native
53     // pointer.
54     protected long mNativeInfoBarPtr;
55
56     // Used by tests to reference infobars.
57     private final int mId;
58     private static int sIdCounter = 0;
59     private static int generateId() {
60         return sIdCounter++;
61     }
62
63     /**
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.
67      */
68     public InfoBar(InfoBarListeners.Dismiss listener, int iconDrawableId, CharSequence message) {
69         mListener = listener;
70         mId = generateId();
71         mIconDrawableId = iconDrawableId;
72         mMessage = message;
73         mExpireOnNavigation = true;
74     }
75
76     /**
77      * @return The message shown in the infobar, useful for accessibility.
78      */
79     public CharSequence getMessage() {
80         return mMessage;
81     }
82
83     /**
84      * Stores a pointer to the native-side counterpart of this InfoBar.
85      * @param nativeInfoBarPtr Pointer to the NativeInfoBar.
86      */
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;
92         }
93     }
94
95     /**
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.
99      */
100     protected void replaceNativePointer(long newInfoBarPtr) {
101         mNativeInfoBarPtr = newInfoBarPtr;
102     }
103
104     /**
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.
110      */
111     public final boolean shouldExpire() {
112         return mExpireOnNavigation && mNativeInfoBarPtr == 0;
113     }
114
115     // Sets whether the bar should be dismissed when a navigation occurs.
116     public void setExpireOnNavigation(boolean expireOnNavigation) {
117         mExpireOnNavigation = expireOnNavigation;
118     }
119
120     /**
121      * @return true if this java infobar owns this {@code nativePointer}
122      */
123     boolean ownsNativeInfoBar(long nativePointer) {
124         return mNativeInfoBarPtr == nativePointer;
125     }
126
127     /**
128      * @return whether or not the InfoBar has been dismissed.
129      */
130     protected boolean isDismissed() {
131         return mIsDismissed;
132     }
133
134     /**
135      * Sets the Context used when creating the InfoBar.
136      */
137     protected void setContext(Context context) {
138         mContext = context;
139     }
140
141     /**
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.
144      */
145     protected Context getContext() {
146         return mContext;
147     }
148
149     /**
150      * Creates the View that represents the InfoBar.
151      * @return The View representing the InfoBar.
152      */
153     protected final View createView() {
154         assert mContext != null;
155
156         InfoBarLayout layout = new InfoBarLayout(mContext, this, mIconDrawableId, mMessage);
157         createContent(layout);
158         return layout;
159     }
160
161     /**
162      * Used to close a java only infobar.
163      */
164     public void dismissJavaOnlyInfoBar() {
165         assert mNativeInfoBarPtr == 0;
166         if (closeInfoBar() && mListener != null) {
167             mListener.onInfoBarDismissed(this);
168         }
169     }
170
171     /**
172      * @return whether the infobar actually needed closing.
173      */
174     @CalledByNative
175     public boolean closeInfoBar() {
176         if (!mIsDismissed) {
177             mIsDismissed = true;
178             if (!mContainer.hasBeenDestroyed()) {
179                 // If the container was destroyed, it's already been emptied of all its infobars.
180                 mContainer.removeInfoBar(this);
181             }
182             return true;
183         }
184         return false;
185     }
186
187     protected ContentWrapperView getContentWrapper(boolean createIfNotFound) {
188         if (mContentView == null && createIfNotFound) {
189             mContentView = new ContentWrapperView(getContext(), this, createView());
190             mContentView.setFocusable(false);
191         }
192         return mContentView;
193     }
194
195     protected InfoBarContainer getInfoBarContainer() {
196         return mContainer;
197     }
198
199     /**
200      * @return The content view for the info bar.
201      */
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         nativeOnLinkClicked(mNativeInfoBarPtr);
238     }
239
240     @Override
241     public void createContent(InfoBarLayout layout) {
242     }
243
244     /**
245      * Returns the id of the tab this infobar is showing into.
246      */
247     public int getTabId() {
248         return mContainer.getTabId();
249     }
250
251     @VisibleForTesting
252     public int getId() {
253         return mId;
254     }
255
256     @VisibleForTesting
257     public void setDismissedListener(InfoBarListeners.Dismiss listener) {
258         mListener = listener;
259     }
260
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);
265 }