Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / shell / android / java / src / org / chromium / content_shell / Shell.java
1 // Copyright 2012 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.content_shell;
6
7 import android.content.Context;
8 import android.graphics.drawable.ClipDrawable;
9 import android.text.TextUtils;
10 import android.util.AttributeSet;
11 import android.view.KeyEvent;
12 import android.view.View;
13 import android.view.ViewGroup;
14 import android.view.inputmethod.EditorInfo;
15 import android.view.inputmethod.InputMethodManager;
16 import android.widget.EditText;
17 import android.widget.FrameLayout;
18 import android.widget.ImageButton;
19 import android.widget.LinearLayout;
20 import android.widget.TextView;
21 import android.widget.TextView.OnEditorActionListener;
22
23 import org.chromium.base.CalledByNative;
24 import org.chromium.base.JNINamespace;
25 import org.chromium.content.browser.ContentView;
26 import org.chromium.content.browser.ContentViewClient;
27 import org.chromium.content.browser.ContentViewCore;
28 import org.chromium.content.browser.ContentViewRenderView;
29 import org.chromium.content_public.browser.LoadUrlParams;
30 import org.chromium.content_public.browser.NavigationController;
31 import org.chromium.content_public.browser.WebContents;
32 import org.chromium.ui.base.WindowAndroid;
33
34 /**
35  * Container for the various UI components that make up a shell window.
36  */
37 @JNINamespace("content")
38 public class Shell extends LinearLayout {
39
40     private static final long COMPLETED_PROGRESS_TIMEOUT_MS = 200;
41
42     private final Runnable mClearProgressRunnable = new Runnable() {
43         @Override
44         public void run() {
45             mProgressDrawable.setLevel(0);
46         }
47     };
48
49     private ContentViewCore mContentViewCore;
50     private WebContents mWebContents;
51     private NavigationController mNavigationController;
52     private ContentViewClient mContentViewClient;
53     private EditText mUrlTextView;
54     private ImageButton mPrevButton;
55     private ImageButton mNextButton;
56     private ImageButton mStopButton;
57     private ImageButton mReloadButton;
58
59     private ClipDrawable mProgressDrawable;
60
61     private long mNativeShell;
62     private ContentViewRenderView mContentViewRenderView;
63     private WindowAndroid mWindow;
64
65     private boolean mLoading = false;
66     private boolean mIsFullscreen = false;
67
68     /**
69      * Constructor for inflating via XML.
70      */
71     public Shell(Context context, AttributeSet attrs) {
72         super(context, attrs);
73     }
74
75     /**
76      * Set the SurfaceView being renderered to as soon as it is available.
77      */
78     public void setContentViewRenderView(ContentViewRenderView contentViewRenderView) {
79         FrameLayout contentViewHolder = (FrameLayout) findViewById(R.id.contentview_holder);
80         if (contentViewRenderView == null) {
81             if (mContentViewRenderView != null) {
82                 contentViewHolder.removeView(mContentViewRenderView);
83             }
84         } else {
85             contentViewHolder.addView(contentViewRenderView,
86                     new FrameLayout.LayoutParams(
87                             FrameLayout.LayoutParams.MATCH_PARENT,
88                             FrameLayout.LayoutParams.MATCH_PARENT));
89         }
90         mContentViewRenderView = contentViewRenderView;
91     }
92
93     /**
94      * Initializes the Shell for use.
95      *
96      * @param nativeShell The pointer to the native Shell object.
97      * @param window The owning window for this shell.
98      * @param client The {@link ContentViewClient} to be bound to any current or new
99      *               {@link ContentViewCore}s associated with this shell.
100      */
101     public void initialize(long nativeShell, WindowAndroid window, ContentViewClient client) {
102         mNativeShell = nativeShell;
103         mWindow = window;
104         mContentViewClient = client;
105     }
106
107     /**
108      * Closes the shell and cleans up the native instance, which will handle destroying all
109      * dependencies.
110      */
111     public void close() {
112         if (mNativeShell == 0) return;
113         nativeCloseShell(mNativeShell);
114     }
115
116     @CalledByNative
117     private void onNativeDestroyed() {
118         mWindow = null;
119         mNativeShell = 0;
120         mContentViewCore.destroy();
121     }
122
123     /**
124      * @return Whether the Shell has been destroyed.
125      * @see #onNativeDestroyed()
126      */
127     public boolean isDestroyed() {
128         return mNativeShell == 0;
129     }
130
131     /**
132      * @return Whether or not the Shell is loading content.
133      */
134     public boolean isLoading() {
135         return mLoading;
136     }
137
138     @Override
139     protected void onFinishInflate() {
140         super.onFinishInflate();
141
142         mProgressDrawable = (ClipDrawable) findViewById(R.id.toolbar).getBackground();
143         initializeUrlField();
144         initializeNavigationButtons();
145     }
146
147     private void initializeUrlField() {
148         mUrlTextView = (EditText) findViewById(R.id.url);
149         mUrlTextView.setOnEditorActionListener(new OnEditorActionListener() {
150             @Override
151             public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
152                 if ((actionId != EditorInfo.IME_ACTION_GO) && (event == null ||
153                         event.getKeyCode() != KeyEvent.KEYCODE_ENTER ||
154                         event.getAction() != KeyEvent.ACTION_DOWN)) {
155                     return false;
156                 }
157                 loadUrl(mUrlTextView.getText().toString());
158                 setKeyboardVisibilityForUrl(false);
159                 mContentViewCore.getContainerView().requestFocus();
160                 return true;
161             }
162         });
163         mUrlTextView.setOnFocusChangeListener(new OnFocusChangeListener() {
164             @Override
165             public void onFocusChange(View v, boolean hasFocus) {
166                 setKeyboardVisibilityForUrl(hasFocus);
167                 mNextButton.setVisibility(hasFocus ? GONE : VISIBLE);
168                 mPrevButton.setVisibility(hasFocus ? GONE : VISIBLE);
169                 if (!hasFocus) {
170                     mUrlTextView.setText(mWebContents.getUrl());
171                 }
172             }
173         });
174         mUrlTextView.setOnKeyListener(new OnKeyListener() {
175             @Override
176             public boolean onKey(View v, int keyCode, KeyEvent event) {
177                 if (keyCode == KeyEvent.KEYCODE_BACK) {
178                     mContentViewCore.getContainerView().requestFocus();
179                     return true;
180                 }
181                 return false;
182             }
183         });
184     }
185
186     /**
187      * Loads an URL.  This will perform minimal amounts of sanitizing of the URL to attempt to
188      * make it valid.
189      *
190      * @param url The URL to be loaded by the shell.
191      */
192     public void loadUrl(String url) {
193         if (url == null) return;
194
195         if (TextUtils.equals(url, mWebContents.getUrl())) {
196             mNavigationController.reload(true);
197         } else {
198             mNavigationController.loadUrl(new LoadUrlParams(sanitizeUrl(url)));
199         }
200         mUrlTextView.clearFocus();
201         // TODO(aurimas): Remove this when crbug.com/174541 is fixed.
202         mContentViewCore.getContainerView().clearFocus();
203         mContentViewCore.getContainerView().requestFocus();
204     }
205
206     /**
207      * Given an URL, this performs minimal sanitizing to ensure it will be valid.
208      * @param url The url to be sanitized.
209      * @return The sanitized URL.
210      */
211     public static String sanitizeUrl(String url) {
212         if (url == null) return null;
213         if (url.startsWith("www.") || url.indexOf(":") == -1) url = "http://" + url;
214         return url;
215     }
216
217     private void initializeNavigationButtons() {
218         mPrevButton = (ImageButton) findViewById(R.id.prev);
219         mPrevButton.setOnClickListener(new OnClickListener() {
220             @Override
221             public void onClick(View v) {
222                 if (mNavigationController.canGoBack()) mNavigationController.goBack();
223             }
224         });
225
226         mNextButton = (ImageButton) findViewById(R.id.next);
227         mNextButton.setOnClickListener(new OnClickListener() {
228             @Override
229             public void onClick(View v) {
230                 if (mNavigationController.canGoForward()) mNavigationController.goForward();
231             }
232         });
233         mStopButton = (ImageButton) findViewById(R.id.stop);
234         mStopButton.setOnClickListener(new OnClickListener() {
235             @Override
236             public void onClick(View v) {
237                 if (mLoading) mWebContents.stop();
238             }
239         });
240         mReloadButton = (ImageButton) findViewById(R.id.reload);
241         mReloadButton.setOnClickListener(new OnClickListener() {
242             @Override
243             public void onClick(View v) {
244                 mNavigationController.reload(true);
245             }
246         });
247     }
248
249     @SuppressWarnings("unused")
250     @CalledByNative
251     private void onUpdateUrl(String url) {
252         mUrlTextView.setText(url);
253     }
254
255     @SuppressWarnings("unused")
256     @CalledByNative
257     private void onLoadProgressChanged(double progress) {
258         removeCallbacks(mClearProgressRunnable);
259         mProgressDrawable.setLevel((int) (10000.0 * progress));
260         if (progress == 1.0) postDelayed(mClearProgressRunnable, COMPLETED_PROGRESS_TIMEOUT_MS);
261     }
262
263     @CalledByNative
264     private void toggleFullscreenModeForTab(boolean enterFullscreen) {
265         mIsFullscreen = enterFullscreen;
266         LinearLayout toolBar = (LinearLayout) findViewById(R.id.toolbar);
267         toolBar.setVisibility(enterFullscreen ? GONE : VISIBLE);
268     }
269
270     @CalledByNative
271     private boolean isFullscreenForTabOrPending() {
272         return mIsFullscreen;
273     }
274
275     @SuppressWarnings("unused")
276     @CalledByNative
277     private void setIsLoading(boolean loading) {
278         mLoading = loading;
279     }
280
281     /**
282      * Initializes the ContentView based on the native tab contents pointer passed in.
283      * @param nativeWebContents The pointer to the native tab contents object.
284      */
285     @SuppressWarnings("unused")
286     @CalledByNative
287     private void initFromNativeTabContents(long nativeWebContents) {
288         Context context = getContext();
289         mContentViewCore = new ContentViewCore(context);
290         ContentView cv = ContentView.newInstance(context, mContentViewCore);
291         mContentViewCore.initialize(cv, cv, nativeWebContents, mWindow);
292         mContentViewCore.setContentViewClient(mContentViewClient);
293         mWebContents = mContentViewCore.getWebContents();
294         mNavigationController = mWebContents.getNavigationController();
295         if (getParent() != null) mContentViewCore.onShow();
296         if (mWebContents.getUrl() != null) {
297             mUrlTextView.setText(mWebContents.getUrl());
298         }
299         ((FrameLayout) findViewById(R.id.contentview_holder)).addView(cv,
300                 new FrameLayout.LayoutParams(
301                         FrameLayout.LayoutParams.MATCH_PARENT,
302                         FrameLayout.LayoutParams.MATCH_PARENT));
303         cv.requestFocus();
304         mContentViewRenderView.setCurrentContentViewCore(mContentViewCore);
305     }
306
307     /**
308      * Enable/Disable navigation(Prev/Next) button if navigation is allowed/disallowed
309      * in respective direction.
310      * @param controlId Id of button to update
311      * @param enabled enable/disable value
312      */
313     @CalledByNative
314     private void enableUiControl(int controlId, boolean enabled) {
315         if (controlId == 0) mPrevButton.setEnabled(enabled);
316         else if (controlId == 1) mNextButton.setEnabled(enabled);
317         else if (controlId == 2) {
318             mStopButton.setVisibility(enabled ? VISIBLE : GONE);
319             mReloadButton.setVisibility(enabled ? GONE : VISIBLE);
320         }
321     }
322
323     /**
324      * @return The {@link ViewGroup} currently shown by this Shell.
325      */
326     public ViewGroup getContentView() {
327         return mContentViewCore.getContainerView();
328     }
329
330     /**
331      * @return The {@link ContentViewCore} currently managing the view shown by this Shell.
332      */
333     public ContentViewCore getContentViewCore() {
334         return mContentViewCore;
335     }
336
337      /**
338      * @return The {@link WebContents} currently managing the content shown by this Shell.
339      */
340     public WebContents getWebContents() {
341         return mWebContents;
342     }
343
344     private void setKeyboardVisibilityForUrl(boolean visible) {
345         InputMethodManager imm = (InputMethodManager) getContext().getSystemService(
346                 Context.INPUT_METHOD_SERVICE);
347         if (visible) {
348             imm.showSoftInput(mUrlTextView, InputMethodManager.SHOW_IMPLICIT);
349         } else {
350             imm.hideSoftInputFromWindow(mUrlTextView.getWindowToken(), 0);
351         }
352     }
353
354     private static native void nativeCloseShell(long shellPtr);
355 }