blob: 0cf23ee0a7b0ede152c86db9cfcedcfd1f3708eb [file] [log] [blame]
John Reck0f602f32011-07-07 15:38:43 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Bijan Amirzada41242f22014-03-21 12:12:18 -070016package com.android.browser;
John Reck0f602f32011-07-07 15:38:43 -070017
18import android.app.SearchManager;
kaiyizc4ada322013-07-30 09:58:07 +080019import android.content.ActivityNotFoundException;
John Reck0f602f32011-07-07 15:38:43 -070020import android.content.Context;
21import android.content.Intent;
22import android.graphics.Bitmap;
23import android.graphics.drawable.Drawable;
kaiyizc4ada322013-07-30 09:58:07 +080024import android.net.Uri;
John Reck0f602f32011-07-07 15:38:43 -070025import android.os.Bundle;
Narayan Kamathf3174a52011-11-17 14:43:32 +000026import android.text.Editable;
27import android.text.TextWatcher;
John Reck0f602f32011-07-07 15:38:43 -070028import android.util.AttributeSet;
kaiyizc4ada322013-07-30 09:58:07 +080029import android.util.Log;
John Reck0f602f32011-07-07 15:38:43 -070030import android.view.KeyEvent;
John Reck0f602f32011-07-07 15:38:43 -070031import android.view.View;
32import android.view.View.OnClickListener;
33import android.view.View.OnFocusChangeListener;
John Reck0f602f32011-07-07 15:38:43 -070034import android.widget.ImageView;
35import android.widget.LinearLayout;
kaiyizc4ada322013-07-30 09:58:07 +080036import android.widget.Toast;
John Reck0f602f32011-07-07 15:38:43 -070037
Bijan Amirzada41242f22014-03-21 12:12:18 -070038import com.android.browser.R;
39import com.android.browser.UrlInputView.UrlInputListener;
40import com.android.browser.reflect.ReflectHelper;
John Reck0f602f32011-07-07 15:38:43 -070041
kaiyizc4ada322013-07-30 09:58:07 +080042import java.io.UnsupportedEncodingException;
kaiyiz950eca22013-08-08 11:01:28 +080043import java.net.URISyntaxException;
kaiyizc4ada322013-07-30 09:58:07 +080044
Bijan Amirzada9b1e9882014-02-26 17:15:46 -080045import org.codeaurora.swe.WebView;
46
John Reck42229bc2011-08-19 13:26:43 -070047public class NavigationBarBase extends LinearLayout implements
48 OnClickListener, UrlInputListener, OnFocusChangeListener,
Narayan Kamathf3174a52011-11-17 14:43:32 +000049 TextWatcher {
John Reck0f602f32011-07-07 15:38:43 -070050
kaiyizc4ada322013-07-30 09:58:07 +080051 private final static String TAG = "NavigationBarBase";
52
John Reck0f602f32011-07-07 15:38:43 -070053 protected BaseUi mBaseUi;
54 protected TitleBar mTitleBar;
55 protected UiController mUiController;
56 protected UrlInputView mUrlInput;
John Reck0f602f32011-07-07 15:38:43 -070057
58 private ImageView mFavicon;
59 private ImageView mLockIcon;
John Reck0f602f32011-07-07 15:38:43 -070060
61 public NavigationBarBase(Context context) {
62 super(context);
63 }
64
65 public NavigationBarBase(Context context, AttributeSet attrs) {
66 super(context, attrs);
67 }
68
69 public NavigationBarBase(Context context, AttributeSet attrs, int defStyle) {
70 super(context, attrs, defStyle);
71 }
72
73 @Override
74 protected void onFinishInflate() {
75 super.onFinishInflate();
76 mLockIcon = (ImageView) findViewById(R.id.lock);
77 mFavicon = (ImageView) findViewById(R.id.favicon);
78 mUrlInput = (UrlInputView) findViewById(R.id.url);
79 mUrlInput.setUrlInputListener(this);
John Reck0f602f32011-07-07 15:38:43 -070080 mUrlInput.setOnFocusChangeListener(this);
81 mUrlInput.setSelectAllOnFocus(true);
Narayan Kamathf3174a52011-11-17 14:43:32 +000082 mUrlInput.addTextChangedListener(this);
John Reck0f602f32011-07-07 15:38:43 -070083 }
84
85 public void setTitleBar(TitleBar titleBar) {
86 mTitleBar = titleBar;
87 mBaseUi = mTitleBar.getUi();
88 mUiController = mTitleBar.getUiController();
Michael Kolbb2e91fd2011-07-14 13:47:29 -070089 mUrlInput.setController(mUiController);
John Reck0f602f32011-07-07 15:38:43 -070090 }
91
92 public void setLock(Drawable d) {
93 if (mLockIcon == null) return;
94 if (d == null) {
95 mLockIcon.setVisibility(View.GONE);
96 } else {
97 mLockIcon.setImageDrawable(d);
98 mLockIcon.setVisibility(View.VISIBLE);
99 }
100 }
101
102 public void setFavicon(Bitmap icon) {
103 if (mFavicon == null) return;
104 mFavicon.setImageDrawable(mBaseUi.getFaviconDrawable(icon));
105 }
106
John Reck0f602f32011-07-07 15:38:43 -0700107 @Override
108 public void onClick(View v) {
John Reck0f602f32011-07-07 15:38:43 -0700109 }
110
111 @Override
112 public void onFocusChange(View view, boolean hasFocus) {
113 // if losing focus and not in touch mode, leave as is
114 if (hasFocus || view.isInTouchMode() || mUrlInput.needsUpdate()) {
115 setFocusState(hasFocus);
116 }
117 if (hasFocus) {
118 mBaseUi.showTitleBar();
John Reck0f602f32011-07-07 15:38:43 -0700119 } else if (!mUrlInput.needsUpdate()) {
120 mUrlInput.dismissDropDown();
121 mUrlInput.hideIME();
122 if (mUrlInput.getText().length() == 0) {
123 Tab currentTab = mUiController.getTabControl().getCurrentTab();
124 if (currentTab != null) {
John Reck434e9f82011-08-10 18:16:52 -0700125 setDisplayTitle(currentTab.getUrl());
John Reck0f602f32011-07-07 15:38:43 -0700126 }
127 }
128 mBaseUi.suggestHideTitleBar();
129 }
130 mUrlInput.clearNeedsUpdate();
131 }
132
133 protected void setFocusState(boolean focus) {
134 }
135
John Reck0f602f32011-07-07 15:38:43 -0700136 public boolean isEditingUrl() {
137 return mUrlInput.hasFocus();
138 }
139
140 void stopEditingUrl() {
Michael Kolb0b129122012-06-04 16:31:58 -0700141 WebView currentTopWebView = mUiController.getCurrentTopWebView();
142 if (currentTopWebView != null) {
143 currentTopWebView.requestFocus();
144 }
John Reck0f602f32011-07-07 15:38:43 -0700145 }
146
147 void setDisplayTitle(String title) {
148 if (!isEditingUrl()) {
Michael Kolb29aab402012-05-29 17:22:35 -0700149 if (!title.equals(mUrlInput.getText().toString())) {
150 mUrlInput.setText(title, false);
151 }
John Reck0f602f32011-07-07 15:38:43 -0700152 }
153 }
154
John Reck0f602f32011-07-07 15:38:43 -0700155 void setIncognitoMode(boolean incognito) {
156 mUrlInput.setIncognitoMode(incognito);
157 }
158
159 void clearCompletions() {
Narayan Kamathf3174a52011-11-17 14:43:32 +0000160 mUrlInput.dismissDropDown();
John Reck0f602f32011-07-07 15:38:43 -0700161 }
162
163 // UrlInputListener implementation
164
165 /**
166 * callback from suggestion dropdown
167 * user selected a suggestion
168 */
169 @Override
170 public void onAction(String text, String extra, String source) {
Michael Kolb0b129122012-06-04 16:31:58 -0700171 stopEditingUrl();
John Reck0f602f32011-07-07 15:38:43 -0700172 if (UrlInputView.TYPED.equals(source)) {
kaiyizc4ada322013-07-30 09:58:07 +0800173 String url = null;
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800174 Object[] params = {new String("persist.env.browser.wap2estore"),
175 Boolean.valueOf(false)};
176 Class[] type = new Class[] {String.class, boolean.class};
177 Boolean wap2estore = (Boolean) ReflectHelper.invokeStaticMethod(
178 "android.os.SystemProperties", "getBoolean", type, params);
179 if ((wap2estore && isEstoreTypeUrl(text)) || isRtspTypeUrl(text)) {
kaiyizc4ada322013-07-30 09:58:07 +0800180 url = text;
181 } else {
182 url = UrlUtils.smartUrlFilter(text, false);
183 }
184
John Reck0f602f32011-07-07 15:38:43 -0700185 Tab t = mBaseUi.getActiveTab();
186 // Only shortcut javascript URIs for now, as there is special
187 // logic in UrlHandler for other schemas
188 if (url != null && t != null && url.startsWith("javascript:")) {
189 mUiController.loadUrl(t, url);
190 setDisplayTitle(text);
191 return;
192 }
kaiyizc4ada322013-07-30 09:58:07 +0800193
194 // add for carrier wap2estore feature
195 if (url != null && t != null && wap2estore && isEstoreTypeUrl(url)) {
196 handleEstoreTypeUrl(url);
197 setDisplayTitle(text);
198 return;
199 }
kaiyiz950eca22013-08-08 11:01:28 +0800200 // add for rtsp scheme feature
201 if (url != null && t != null && isRtspTypeUrl(url)) {
202 if (handleRtspTypeUrl(url)) {
203 return;
204 }
205 }
John Reck0f602f32011-07-07 15:38:43 -0700206 }
207 Intent i = new Intent();
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700208 String action = Intent.ACTION_SEARCH;
John Reck0f602f32011-07-07 15:38:43 -0700209 i.setAction(action);
210 i.putExtra(SearchManager.QUERY, text);
211 if (extra != null) {
212 i.putExtra(SearchManager.EXTRA_DATA_KEY, extra);
213 }
214 if (source != null) {
215 Bundle appData = new Bundle();
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800216 appData.putString("source", source);
217 i.putExtra("source", appData);
John Reck0f602f32011-07-07 15:38:43 -0700218 }
219 mUiController.handleNewIntent(i);
220 setDisplayTitle(text);
221 }
222
kaiyizc4ada322013-07-30 09:58:07 +0800223 private boolean isEstoreTypeUrl(String url) {
224 String utf8Url = null;
225 try {
226 utf8Url = new String(url.getBytes("UTF-8"), "UTF-8");
227 } catch (UnsupportedEncodingException e) {
228 Log.e(TAG, "err " + e);
229 }
230 if (utf8Url != null && utf8Url.startsWith("estore:")) {
231 return true;
232 }
233 return false;
234 }
235
236 private void handleEstoreTypeUrl(String url) {
237 String utf8Url = null, finalUrl = null;
238 try {
239 utf8Url = new String(url.getBytes("UTF-8"), "UTF-8");
240 } catch (UnsupportedEncodingException e) {
241 Log.e(TAG, "err " + e);
242 }
243 if (utf8Url != null) {
244 finalUrl = utf8Url;
245 } else {
246 finalUrl = url;
247 }
248 if (finalUrl.replaceFirst("estore:", "").length() > 256) {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800249 Toast.makeText(getContext(), R.string.estore_url_warning, Toast.LENGTH_LONG).show();
kaiyizc4ada322013-07-30 09:58:07 +0800250 return;
251 }
252 Intent intent = new Intent(Intent.ACTION_VIEW);
253 intent.setData(Uri.parse(finalUrl));
254 try {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800255 getContext().startActivity(intent);
kaiyizc4ada322013-07-30 09:58:07 +0800256 } catch (ActivityNotFoundException ex) {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800257 String downloadUrl = getContext().getResources().getString(R.string.estore_homepage);
kaiyizc4ada322013-07-30 09:58:07 +0800258 mUiController.loadUrl(mBaseUi.getActiveTab(), downloadUrl);
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800259 Toast.makeText(getContext(), R.string.download_estore_app, Toast.LENGTH_LONG).show();
kaiyizc4ada322013-07-30 09:58:07 +0800260 }
261 }
262
kaiyiz950eca22013-08-08 11:01:28 +0800263 private boolean isRtspTypeUrl(String url) {
264 String utf8Url = null;
265 try {
266 utf8Url = new String(url.getBytes("UTF-8"), "UTF-8");
267 } catch (UnsupportedEncodingException e) {
268 Log.e(TAG, "err " + e);
269 }
270 if (utf8Url != null && utf8Url.startsWith("rtsp://")) {
271 return true;
272 }
273 return false;
274 }
275
276 private boolean handleRtspTypeUrl(String url) {
277 Intent intent;
278 // perform generic parsing of the URI to turn it into an Intent.
279 try {
280 intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
281 } catch (URISyntaxException ex) {
282 Log.w("Browser", "Bad URI " + url + ": " + ex.getMessage());
283 return false;
284 }
285
286 try {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800287 getContext().startActivity(intent);
kaiyiz950eca22013-08-08 11:01:28 +0800288 } catch (ActivityNotFoundException ex) {
289 Log.w("Browser", "No resolveActivity " + url);
290 return false;
291 }
292 return true;
293 }
294
John Reck0f602f32011-07-07 15:38:43 -0700295 @Override
296 public void onDismiss() {
297 final Tab currentTab = mBaseUi.getActiveTab();
298 mBaseUi.hideTitleBar();
299 post(new Runnable() {
300 public void run() {
301 clearFocus();
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700302 if (currentTab != null) {
John Reck0f602f32011-07-07 15:38:43 -0700303 setDisplayTitle(currentTab.getUrl());
304 }
305 }
306 });
307 }
308
309 /**
310 * callback from the suggestion dropdown
311 * copy text to input field and stay in edit mode
312 */
313 @Override
314 public void onCopySuggestion(String text) {
315 mUrlInput.setText(text, true);
316 if (text != null) {
317 mUrlInput.setSelection(text.length());
318 }
319 }
320
321 public void setCurrentUrlIsBookmark(boolean isBookmark) {
322 }
323
324 @Override
325 public boolean dispatchKeyEventPreIme(KeyEvent evt) {
326 if (evt.getKeyCode() == KeyEvent.KEYCODE_BACK) {
327 // catch back key in order to do slightly more cleanup than usual
Michael Kolb0b129122012-06-04 16:31:58 -0700328 stopEditingUrl();
John Reck0f602f32011-07-07 15:38:43 -0700329 return true;
330 }
331 return super.dispatchKeyEventPreIme(evt);
332 }
333
John Reck0f602f32011-07-07 15:38:43 -0700334 /**
335 * called from the Ui when the user wants to edit
336 * @param clearInput clear the input field
337 */
Michael Kolb1f9b3562012-04-24 14:38:34 -0700338 void startEditingUrl(boolean clearInput, boolean forceIME) {
John Reck0f602f32011-07-07 15:38:43 -0700339 // editing takes preference of progress
340 setVisibility(View.VISIBLE);
341 if (mTitleBar.useQuickControls()) {
342 mTitleBar.getProgressView().setVisibility(View.GONE);
343 }
344 if (!mUrlInput.hasFocus()) {
345 mUrlInput.requestFocus();
346 }
347 if (clearInput) {
348 mUrlInput.setText("");
John Reck0f602f32011-07-07 15:38:43 -0700349 }
Michael Kolb1f9b3562012-04-24 14:38:34 -0700350 if (forceIME) {
Michael Kolb4bb6fcb2012-04-13 14:25:27 -0700351 mUrlInput.showIME();
352 }
John Reck0f602f32011-07-07 15:38:43 -0700353 }
354
355 public void onProgressStarted() {
356 }
357
358 public void onProgressStopped() {
359 }
360
John Reck58891902011-08-11 17:48:53 -0700361 public boolean isMenuShowing() {
John Reck42229bc2011-08-19 13:26:43 -0700362 return false;
John Reck58891902011-08-11 17:48:53 -0700363 }
364
John Reck419f6b42011-08-16 16:10:51 -0700365 public void onTabDataChanged(Tab tab) {
366 }
367
Michael Kolb0b129122012-06-04 16:31:58 -0700368 public void onVoiceResult(String s) {
369 startEditingUrl(true, true);
370 onCopySuggestion(s);
371 }
372
Narayan Kamathf3174a52011-11-17 14:43:32 +0000373 @Override
374 public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
375
376 @Override
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700377 public void onTextChanged(CharSequence s, int start, int before, int count) { }
Narayan Kamathf3174a52011-11-17 14:43:32 +0000378
379 @Override
380 public void afterTextChanged(Editable s) { }
Michael Kolb0b129122012-06-04 16:31:58 -0700381
John Reck0f602f32011-07-07 15:38:43 -0700382}