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.
5 package org
.chromium
.content_shell
;
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
.inputmethod
.EditorInfo
;
14 import android
.view
.inputmethod
.InputMethodManager
;
15 import android
.widget
.EditText
;
16 import android
.widget
.FrameLayout
;
17 import android
.widget
.ImageButton
;
18 import android
.widget
.LinearLayout
;
19 import android
.widget
.TextView
;
20 import android
.widget
.TextView
.OnEditorActionListener
;
22 import org
.chromium
.base
.CalledByNative
;
23 import org
.chromium
.base
.JNINamespace
;
24 import org
.chromium
.content
.browser
.ContentView
;
25 import org
.chromium
.content
.browser
.ContentViewRenderView
;
26 import org
.chromium
.content
.browser
.LoadUrlParams
;
27 import org
.chromium
.ui
.base
.WindowAndroid
;
30 * Container for the various UI components that make up a shell window.
32 @JNINamespace("content")
33 public class Shell
extends LinearLayout
{
35 private static final long COMPLETED_PROGRESS_TIMEOUT_MS
= 200;
37 private final Runnable mClearProgressRunnable
= new Runnable() {
40 mProgressDrawable
.setLevel(0);
44 // TODO(jrg): a mContentView.destroy() call is needed, both upstream and downstream.
45 private ContentView mContentView
;
46 private EditText mUrlTextView
;
47 private ImageButton mPrevButton
;
48 private ImageButton mNextButton
;
50 private ClipDrawable mProgressDrawable
;
52 private long mNativeShell
;
53 private ContentViewRenderView mContentViewRenderView
;
54 private WindowAndroid mWindow
;
56 private boolean mLoading
= false;
59 * Constructor for inflating via XML.
61 public Shell(Context context
, AttributeSet attrs
) {
62 super(context
, attrs
);
66 * Set the SurfaceView being renderered to as soon as it is available.
68 public void setContentViewRenderView(ContentViewRenderView contentViewRenderView
) {
69 FrameLayout contentViewHolder
= (FrameLayout
) findViewById(R
.id
.contentview_holder
);
70 if (contentViewRenderView
== null) {
71 if (mContentViewRenderView
!= null) {
72 contentViewHolder
.removeView(mContentViewRenderView
);
75 contentViewHolder
.addView(contentViewRenderView
,
76 new FrameLayout
.LayoutParams(
77 FrameLayout
.LayoutParams
.MATCH_PARENT
,
78 FrameLayout
.LayoutParams
.MATCH_PARENT
));
80 mContentViewRenderView
= contentViewRenderView
;
84 * Initializes the Shell for use.
86 * @param nativeShell The pointer to the native Shell object.
87 * @param window The owning window for this shell.
89 public void initialize(long nativeShell
, WindowAndroid window
) {
90 mNativeShell
= nativeShell
;
95 * Closes the shell and cleans up the native instance, which will handle destroying all
99 if (mNativeShell
== 0) return;
100 nativeCloseShell(mNativeShell
);
104 private void onNativeDestroyed() {
107 assert !mContentView
.isAttachedToWindow()
108 : "Attempting to destroy the content view while attached to the view hierarchy.";
109 mContentView
.destroy();
113 * @return Whether the Shell has been destroyed.
114 * @see #onNativeDestroyed()
116 public boolean isDestroyed() {
117 return mNativeShell
== 0;
121 * @return Whether or not the Shell is loading content.
123 public boolean isLoading() {
128 protected void onFinishInflate() {
129 super.onFinishInflate();
131 mProgressDrawable
= (ClipDrawable
) findViewById(R
.id
.toolbar
).getBackground();
132 initializeUrlField();
133 initializeNavigationButtons();
136 private void initializeUrlField() {
137 mUrlTextView
= (EditText
) findViewById(R
.id
.url
);
138 mUrlTextView
.setOnEditorActionListener(new OnEditorActionListener() {
140 public boolean onEditorAction(TextView v
, int actionId
, KeyEvent event
) {
141 if ((actionId
!= EditorInfo
.IME_ACTION_GO
) && (event
== null ||
142 event
.getKeyCode() != KeyEvent
.KEYCODE_ENTER
||
143 event
.getAction() != KeyEvent
.ACTION_DOWN
)) {
146 loadUrl(mUrlTextView
.getText().toString());
147 setKeyboardVisibilityForUrl(false);
148 mContentView
.requestFocus();
152 mUrlTextView
.setOnFocusChangeListener(new OnFocusChangeListener() {
154 public void onFocusChange(View v
, boolean hasFocus
) {
155 setKeyboardVisibilityForUrl(hasFocus
);
156 mNextButton
.setVisibility(hasFocus ? GONE
: VISIBLE
);
157 mPrevButton
.setVisibility(hasFocus ? GONE
: VISIBLE
);
159 mUrlTextView
.setText(mContentView
.getUrl());
166 * Loads an URL. This will perform minimal amounts of sanitizing of the URL to attempt to
169 * @param url The URL to be loaded by the shell.
171 public void loadUrl(String url
) {
172 if (url
== null) return;
174 if (TextUtils
.equals(url
, mContentView
.getUrl())) {
175 mContentView
.getContentViewCore().reload(true);
177 mContentView
.loadUrl(new LoadUrlParams(sanitizeUrl(url
)));
179 mUrlTextView
.clearFocus();
180 // TODO(aurimas): Remove this when crbug.com/174541 is fixed.
181 mContentView
.clearFocus();
182 mContentView
.requestFocus();
186 * Given an URL, this performs minimal sanitizing to ensure it will be valid.
187 * @param url The url to be sanitized.
188 * @return The sanitized URL.
190 public static String
sanitizeUrl(String url
) {
191 if (url
== null) return url
;
192 if (url
.startsWith("www.") || url
.indexOf(":") == -1) url
= "http://" + url
;
196 private void initializeNavigationButtons() {
197 mPrevButton
= (ImageButton
) findViewById(R
.id
.prev
);
198 mPrevButton
.setOnClickListener(new OnClickListener() {
200 public void onClick(View v
) {
201 if (mContentView
.canGoBack()) mContentView
.goBack();
205 mNextButton
= (ImageButton
) findViewById(R
.id
.next
);
206 mNextButton
.setOnClickListener(new OnClickListener() {
208 public void onClick(View v
) {
209 if (mContentView
.canGoForward()) mContentView
.goForward();
214 @SuppressWarnings("unused")
216 private void onUpdateUrl(String url
) {
217 mUrlTextView
.setText(url
);
220 @SuppressWarnings("unused")
222 private void onLoadProgressChanged(double progress
) {
223 removeCallbacks(mClearProgressRunnable
);
224 mProgressDrawable
.setLevel((int) (10000.0 * progress
));
225 if (progress
== 1.0) postDelayed(mClearProgressRunnable
, COMPLETED_PROGRESS_TIMEOUT_MS
);
229 private void toggleFullscreenModeForTab(boolean enterFullscreen
) {
233 private boolean isFullscreenForTabOrPending() {
237 @SuppressWarnings("unused")
239 private void setIsLoading(boolean loading
) {
244 * Initializes the ContentView based on the native tab contents pointer passed in.
245 * @param nativeTabContents The pointer to the native tab contents object.
247 @SuppressWarnings("unused")
249 private void initFromNativeTabContents(long nativeTabContents
) {
250 mContentView
= ContentView
.newInstance(getContext(), nativeTabContents
, mWindow
);
251 if (mContentView
.getUrl() != null) mUrlTextView
.setText(mContentView
.getUrl());
252 ((FrameLayout
) findViewById(R
.id
.contentview_holder
)).addView(mContentView
,
253 new FrameLayout
.LayoutParams(
254 FrameLayout
.LayoutParams
.MATCH_PARENT
,
255 FrameLayout
.LayoutParams
.MATCH_PARENT
));
256 mContentView
.requestFocus();
257 mContentViewRenderView
.setCurrentContentView(mContentView
);
261 * @return The {@link ContentView} currently shown by this Shell.
263 public ContentView
getContentView() {
267 private void setKeyboardVisibilityForUrl(boolean visible
) {
268 InputMethodManager imm
= (InputMethodManager
) getContext().getSystemService(
269 Context
.INPUT_METHOD_SERVICE
);
271 imm
.showSoftInput(mUrlTextView
, InputMethodManager
.SHOW_IMPLICIT
);
273 imm
.hideSoftInputFromWindow(mUrlTextView
.getWindowToken(), 0);
277 private static native void nativeCloseShell(long shellPtr
);