blob: a8f52fecf83fe7214ebc7dde88650b4e6342cfba [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;
John Reck0f602f32011-07-07 15:38:43 -070040
kaiyizc4ada322013-07-30 09:58:07 +080041import java.io.UnsupportedEncodingException;
kaiyiz950eca22013-08-08 11:01:28 +080042import java.net.URISyntaxException;
kaiyizc4ada322013-07-30 09:58:07 +080043
Bijan Amirzada9b1e9882014-02-26 17:15:46 -080044import org.codeaurora.swe.WebView;
45
John Reck42229bc2011-08-19 13:26:43 -070046public class NavigationBarBase extends LinearLayout implements
47 OnClickListener, UrlInputListener, OnFocusChangeListener,
Narayan Kamathf3174a52011-11-17 14:43:32 +000048 TextWatcher {
John Reck0f602f32011-07-07 15:38:43 -070049
kaiyizc4ada322013-07-30 09:58:07 +080050 private final static String TAG = "NavigationBarBase";
51
John Reck0f602f32011-07-07 15:38:43 -070052 protected BaseUi mBaseUi;
53 protected TitleBar mTitleBar;
54 protected UiController mUiController;
55 protected UrlInputView mUrlInput;
Axesh R. Ajmera2e241242014-05-19 15:53:38 -070056 protected LocationButton mLocationButton;
John Reck0f602f32011-07-07 15:38:43 -070057
58 private ImageView mFavicon;
59 private ImageView mLockIcon;
John Reck0f602f32011-07-07 15:38:43 -070060
Axesh R. Ajmera2e241242014-05-19 15:53:38 -070061
John Reck0f602f32011-07-07 15:38:43 -070062 public NavigationBarBase(Context context) {
63 super(context);
64 }
65
66 public NavigationBarBase(Context context, AttributeSet attrs) {
67 super(context, attrs);
68 }
69
70 public NavigationBarBase(Context context, AttributeSet attrs, int defStyle) {
71 super(context, attrs, defStyle);
72 }
73
74 @Override
75 protected void onFinishInflate() {
76 super.onFinishInflate();
77 mLockIcon = (ImageView) findViewById(R.id.lock);
Tarun Nainaniea28dde2014-08-27 17:25:09 -070078 //SWE-FIXME
79 //mLocationButton = (LocationButton) findViewById(R.id.location_button);
John Reck0f602f32011-07-07 15:38:43 -070080 mFavicon = (ImageView) findViewById(R.id.favicon);
81 mUrlInput = (UrlInputView) findViewById(R.id.url);
82 mUrlInput.setUrlInputListener(this);
John Reck0f602f32011-07-07 15:38:43 -070083 mUrlInput.setOnFocusChangeListener(this);
84 mUrlInput.setSelectAllOnFocus(true);
Narayan Kamathf3174a52011-11-17 14:43:32 +000085 mUrlInput.addTextChangedListener(this);
John Reck0f602f32011-07-07 15:38:43 -070086 }
87
88 public void setTitleBar(TitleBar titleBar) {
89 mTitleBar = titleBar;
90 mBaseUi = mTitleBar.getUi();
91 mUiController = mTitleBar.getUiController();
Michael Kolbb2e91fd2011-07-14 13:47:29 -070092 mUrlInput.setController(mUiController);
John Reck0f602f32011-07-07 15:38:43 -070093 }
94
95 public void setLock(Drawable d) {
96 if (mLockIcon == null) return;
97 if (d == null) {
98 mLockIcon.setVisibility(View.GONE);
99 } else {
100 mLockIcon.setImageDrawable(d);
101 mLockIcon.setVisibility(View.VISIBLE);
102 }
103 }
104
105 public void setFavicon(Bitmap icon) {
106 if (mFavicon == null) return;
107 mFavicon.setImageDrawable(mBaseUi.getFaviconDrawable(icon));
108 }
109
John Reck0f602f32011-07-07 15:38:43 -0700110 @Override
111 public void onClick(View v) {
John Reck0f602f32011-07-07 15:38:43 -0700112 }
113
114 @Override
115 public void onFocusChange(View view, boolean hasFocus) {
116 // if losing focus and not in touch mode, leave as is
117 if (hasFocus || view.isInTouchMode() || mUrlInput.needsUpdate()) {
118 setFocusState(hasFocus);
119 }
120 if (hasFocus) {
121 mBaseUi.showTitleBar();
John Reck0f602f32011-07-07 15:38:43 -0700122 } else if (!mUrlInput.needsUpdate()) {
123 mUrlInput.dismissDropDown();
124 mUrlInput.hideIME();
125 if (mUrlInput.getText().length() == 0) {
126 Tab currentTab = mUiController.getTabControl().getCurrentTab();
127 if (currentTab != null) {
John Reck434e9f82011-08-10 18:16:52 -0700128 setDisplayTitle(currentTab.getUrl());
John Reck0f602f32011-07-07 15:38:43 -0700129 }
130 }
131 mBaseUi.suggestHideTitleBar();
132 }
133 mUrlInput.clearNeedsUpdate();
134 }
135
136 protected void setFocusState(boolean focus) {
137 }
138
John Reck0f602f32011-07-07 15:38:43 -0700139 public boolean isEditingUrl() {
140 return mUrlInput.hasFocus();
141 }
142
143 void stopEditingUrl() {
Michael Kolb0b129122012-06-04 16:31:58 -0700144 WebView currentTopWebView = mUiController.getCurrentTopWebView();
145 if (currentTopWebView != null) {
146 currentTopWebView.requestFocus();
147 }
John Reck0f602f32011-07-07 15:38:43 -0700148 }
149
150 void setDisplayTitle(String title) {
151 if (!isEditingUrl()) {
Michael Kolb29aab402012-05-29 17:22:35 -0700152 if (!title.equals(mUrlInput.getText().toString())) {
153 mUrlInput.setText(title, false);
154 }
John Reck0f602f32011-07-07 15:38:43 -0700155 }
156 }
157
John Reck0f602f32011-07-07 15:38:43 -0700158 void setIncognitoMode(boolean incognito) {
159 mUrlInput.setIncognitoMode(incognito);
160 }
161
162 void clearCompletions() {
Narayan Kamathf3174a52011-11-17 14:43:32 +0000163 mUrlInput.dismissDropDown();
John Reck0f602f32011-07-07 15:38:43 -0700164 }
165
166 // UrlInputListener implementation
167
168 /**
169 * callback from suggestion dropdown
170 * user selected a suggestion
171 */
172 @Override
173 public void onAction(String text, String extra, String source) {
Michael Kolb0b129122012-06-04 16:31:58 -0700174 stopEditingUrl();
John Reck0f602f32011-07-07 15:38:43 -0700175 if (UrlInputView.TYPED.equals(source)) {
kaiyizc4ada322013-07-30 09:58:07 +0800176 String url = null;
Bijan Amirzadae75909d2014-05-06 14:18:54 -0700177 boolean wap2estore = getContext().getResources().getBoolean(R.bool.wap2estore);
Vivek Sekhar5e631472014-03-31 23:59:10 -0700178 if ((wap2estore && isEstoreTypeUrl(text)) || isRtspTypeUrl(text)
179 || isMakeCallTypeUrl(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)) {
Vivek Sekharb54614f2014-05-01 19:03:37 -0700196 if (handleEstoreTypeUrl(url)) {
197 setDisplayTitle(text);
198 return;
199 }
kaiyizc4ada322013-07-30 09:58:07 +0800200 }
kaiyiz950eca22013-08-08 11:01:28 +0800201 // add for rtsp scheme feature
202 if (url != null && t != null && isRtspTypeUrl(url)) {
203 if (handleRtspTypeUrl(url)) {
Vivek Sekharb54614f2014-05-01 19:03:37 -0700204 setDisplayTitle(text);
kaiyiz950eca22013-08-08 11:01:28 +0800205 return;
206 }
207 }
Vivek Sekhar5e631472014-03-31 23:59:10 -0700208 // add for "wtai://wp/mc;" scheme feature
209 if (url != null && t != null && isMakeCallTypeUrl(url)) {
210 if (handleMakeCallTypeUrl(url)) {
211 return;
212 }
213 }
John Reck0f602f32011-07-07 15:38:43 -0700214 }
215 Intent i = new Intent();
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700216 String action = Intent.ACTION_SEARCH;
John Reck0f602f32011-07-07 15:38:43 -0700217 i.setAction(action);
218 i.putExtra(SearchManager.QUERY, text);
219 if (extra != null) {
220 i.putExtra(SearchManager.EXTRA_DATA_KEY, extra);
221 }
222 if (source != null) {
223 Bundle appData = new Bundle();
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800224 appData.putString("source", source);
225 i.putExtra("source", appData);
John Reck0f602f32011-07-07 15:38:43 -0700226 }
227 mUiController.handleNewIntent(i);
228 setDisplayTitle(text);
229 }
230
Vivek Sekhar5e631472014-03-31 23:59:10 -0700231 private boolean isMakeCallTypeUrl(String url) {
232 String utf8Url = null;
233 try {
234 utf8Url = new String(url.getBytes("UTF-8"), "UTF-8");
235 } catch (UnsupportedEncodingException e) {
236 Log.e(TAG, "err " + e);
237 }
238 if (utf8Url != null && utf8Url.startsWith(UrlHandler.SCHEME_WTAI_MC)) {
239 return true;
240 }
241 return false;
242 }
243
244 private boolean handleMakeCallTypeUrl(String url) {
245 // wtai://wp/mc;number
246 // number=string(phone-number)
247 if (url.startsWith(UrlHandler.SCHEME_WTAI_MC)) {
248 Intent intent = new Intent(Intent.ACTION_VIEW,
249 Uri.parse(WebView.SCHEME_TEL +
250 url.substring(UrlHandler.SCHEME_WTAI_MC.length())));
251 getContext().startActivity(intent);
252 // before leaving BrowserActivity, close the empty child tab.
253 // If a new tab is created through JavaScript open to load this
254 // url, we would like to close it as we will load this url in a
255 // different Activity.
256 Tab current = mUiController.getCurrentTab();
257 if (current != null
258 && current.getWebView().copyBackForwardList().getSize() == 0) {
259 mUiController.closeCurrentTab();
260 }
261 return true;
262 }
263 return false;
264 }
265
kaiyizc4ada322013-07-30 09:58:07 +0800266 private boolean isEstoreTypeUrl(String url) {
Vivek Sekharb54614f2014-05-01 19:03:37 -0700267 if (url != null && url.startsWith("estore:")) {
kaiyizc4ada322013-07-30 09:58:07 +0800268 return true;
269 }
270 return false;
271 }
272
Vivek Sekharb54614f2014-05-01 19:03:37 -0700273 private boolean handleEstoreTypeUrl(String url) {
274 if (url.getBytes().length > 256) {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800275 Toast.makeText(getContext(), R.string.estore_url_warning, Toast.LENGTH_LONG).show();
Vivek Sekharb54614f2014-05-01 19:03:37 -0700276 return false;
kaiyizc4ada322013-07-30 09:58:07 +0800277 }
Vivek Sekharb54614f2014-05-01 19:03:37 -0700278
279 Intent intent;
280 // perform generic parsing of the URI to turn it into an Intent.
281 try {
282 intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
283 } catch (URISyntaxException ex) {
284 Log.w("Browser", "Bad URI " + url + ": " + ex.getMessage());
285 return false;
286 }
287
kaiyizc4ada322013-07-30 09:58:07 +0800288 try {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800289 getContext().startActivity(intent);
kaiyizc4ada322013-07-30 09:58:07 +0800290 } catch (ActivityNotFoundException ex) {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800291 String downloadUrl = getContext().getResources().getString(R.string.estore_homepage);
kaiyizc4ada322013-07-30 09:58:07 +0800292 mUiController.loadUrl(mBaseUi.getActiveTab(), downloadUrl);
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800293 Toast.makeText(getContext(), R.string.download_estore_app, Toast.LENGTH_LONG).show();
kaiyizc4ada322013-07-30 09:58:07 +0800294 }
Vivek Sekharb54614f2014-05-01 19:03:37 -0700295
296 return true;
kaiyizc4ada322013-07-30 09:58:07 +0800297 }
298
kaiyiz950eca22013-08-08 11:01:28 +0800299 private boolean isRtspTypeUrl(String url) {
300 String utf8Url = null;
301 try {
302 utf8Url = new String(url.getBytes("UTF-8"), "UTF-8");
303 } catch (UnsupportedEncodingException e) {
304 Log.e(TAG, "err " + e);
305 }
306 if (utf8Url != null && utf8Url.startsWith("rtsp://")) {
307 return true;
308 }
309 return false;
310 }
311
312 private boolean handleRtspTypeUrl(String url) {
313 Intent intent;
314 // perform generic parsing of the URI to turn it into an Intent.
315 try {
316 intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
317 } catch (URISyntaxException ex) {
318 Log.w("Browser", "Bad URI " + url + ": " + ex.getMessage());
319 return false;
320 }
321
322 try {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800323 getContext().startActivity(intent);
kaiyiz950eca22013-08-08 11:01:28 +0800324 } catch (ActivityNotFoundException ex) {
325 Log.w("Browser", "No resolveActivity " + url);
326 return false;
327 }
328 return true;
329 }
330
John Reck0f602f32011-07-07 15:38:43 -0700331 @Override
332 public void onDismiss() {
333 final Tab currentTab = mBaseUi.getActiveTab();
334 mBaseUi.hideTitleBar();
335 post(new Runnable() {
336 public void run() {
337 clearFocus();
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700338 if (currentTab != null) {
John Reck0f602f32011-07-07 15:38:43 -0700339 setDisplayTitle(currentTab.getUrl());
340 }
341 }
342 });
343 }
344
345 /**
346 * callback from the suggestion dropdown
347 * copy text to input field and stay in edit mode
348 */
349 @Override
350 public void onCopySuggestion(String text) {
351 mUrlInput.setText(text, true);
352 if (text != null) {
353 mUrlInput.setSelection(text.length());
354 }
355 }
356
357 public void setCurrentUrlIsBookmark(boolean isBookmark) {
358 }
359
360 @Override
361 public boolean dispatchKeyEventPreIme(KeyEvent evt) {
362 if (evt.getKeyCode() == KeyEvent.KEYCODE_BACK) {
363 // catch back key in order to do slightly more cleanup than usual
Michael Kolb0b129122012-06-04 16:31:58 -0700364 stopEditingUrl();
John Reck0f602f32011-07-07 15:38:43 -0700365 }
366 return super.dispatchKeyEventPreIme(evt);
367 }
368
John Reck0f602f32011-07-07 15:38:43 -0700369 /**
370 * called from the Ui when the user wants to edit
371 * @param clearInput clear the input field
372 */
Michael Kolb1f9b3562012-04-24 14:38:34 -0700373 void startEditingUrl(boolean clearInput, boolean forceIME) {
John Reck0f602f32011-07-07 15:38:43 -0700374 // editing takes preference of progress
375 setVisibility(View.VISIBLE);
376 if (mTitleBar.useQuickControls()) {
377 mTitleBar.getProgressView().setVisibility(View.GONE);
378 }
379 if (!mUrlInput.hasFocus()) {
380 mUrlInput.requestFocus();
381 }
382 if (clearInput) {
383 mUrlInput.setText("");
John Reck0f602f32011-07-07 15:38:43 -0700384 }
Michael Kolb1f9b3562012-04-24 14:38:34 -0700385 if (forceIME) {
Michael Kolb4bb6fcb2012-04-13 14:25:27 -0700386 mUrlInput.showIME();
387 }
John Reck0f602f32011-07-07 15:38:43 -0700388 }
389
390 public void onProgressStarted() {
391 }
392
393 public void onProgressStopped() {
394 }
395
John Reck58891902011-08-11 17:48:53 -0700396 public boolean isMenuShowing() {
John Reck42229bc2011-08-19 13:26:43 -0700397 return false;
John Reck58891902011-08-11 17:48:53 -0700398 }
399
John Reck419f6b42011-08-16 16:10:51 -0700400 public void onTabDataChanged(Tab tab) {
Tarun Nainaniea28dde2014-08-27 17:25:09 -0700401 //SWE-FIXME
402 //mLocationButton.onTabDataChanged(tab);
John Reck419f6b42011-08-16 16:10:51 -0700403 }
404
Michael Kolb0b129122012-06-04 16:31:58 -0700405 public void onVoiceResult(String s) {
406 startEditingUrl(true, true);
407 onCopySuggestion(s);
408 }
409
Narayan Kamathf3174a52011-11-17 14:43:32 +0000410 @Override
411 public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
412
413 @Override
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700414 public void onTextChanged(CharSequence s, int start, int before, int count) { }
Narayan Kamathf3174a52011-11-17 14:43:32 +0000415
416 @Override
417 public void afterTextChanged(Editable s) { }
Michael Kolb0b129122012-06-04 16:31:58 -0700418
John Reck0f602f32011-07-07 15:38:43 -0700419}