blob: da3f3da2607b223305722231c1c193e8030171c3 [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;
John Reck0f602f32011-07-07 15:38:43 -070056
57 private ImageView mFavicon;
58 private ImageView mLockIcon;
John Reck0f602f32011-07-07 15:38:43 -070059
60 public NavigationBarBase(Context context) {
61 super(context);
62 }
63
64 public NavigationBarBase(Context context, AttributeSet attrs) {
65 super(context, attrs);
66 }
67
68 public NavigationBarBase(Context context, AttributeSet attrs, int defStyle) {
69 super(context, attrs, defStyle);
70 }
71
72 @Override
73 protected void onFinishInflate() {
74 super.onFinishInflate();
75 mLockIcon = (ImageView) findViewById(R.id.lock);
76 mFavicon = (ImageView) findViewById(R.id.favicon);
77 mUrlInput = (UrlInputView) findViewById(R.id.url);
78 mUrlInput.setUrlInputListener(this);
John Reck0f602f32011-07-07 15:38:43 -070079 mUrlInput.setOnFocusChangeListener(this);
80 mUrlInput.setSelectAllOnFocus(true);
Narayan Kamathf3174a52011-11-17 14:43:32 +000081 mUrlInput.addTextChangedListener(this);
John Reck0f602f32011-07-07 15:38:43 -070082 }
83
84 public void setTitleBar(TitleBar titleBar) {
85 mTitleBar = titleBar;
86 mBaseUi = mTitleBar.getUi();
87 mUiController = mTitleBar.getUiController();
Michael Kolbb2e91fd2011-07-14 13:47:29 -070088 mUrlInput.setController(mUiController);
John Reck0f602f32011-07-07 15:38:43 -070089 }
90
91 public void setLock(Drawable d) {
92 if (mLockIcon == null) return;
93 if (d == null) {
94 mLockIcon.setVisibility(View.GONE);
95 } else {
96 mLockIcon.setImageDrawable(d);
97 mLockIcon.setVisibility(View.VISIBLE);
98 }
99 }
100
101 public void setFavicon(Bitmap icon) {
102 if (mFavicon == null) return;
103 mFavicon.setImageDrawable(mBaseUi.getFaviconDrawable(icon));
104 }
105
John Reck0f602f32011-07-07 15:38:43 -0700106 @Override
107 public void onClick(View v) {
John Reck0f602f32011-07-07 15:38:43 -0700108 }
109
110 @Override
111 public void onFocusChange(View view, boolean hasFocus) {
112 // if losing focus and not in touch mode, leave as is
113 if (hasFocus || view.isInTouchMode() || mUrlInput.needsUpdate()) {
114 setFocusState(hasFocus);
115 }
116 if (hasFocus) {
117 mBaseUi.showTitleBar();
John Reck0f602f32011-07-07 15:38:43 -0700118 } else if (!mUrlInput.needsUpdate()) {
119 mUrlInput.dismissDropDown();
120 mUrlInput.hideIME();
121 if (mUrlInput.getText().length() == 0) {
122 Tab currentTab = mUiController.getTabControl().getCurrentTab();
123 if (currentTab != null) {
John Reck434e9f82011-08-10 18:16:52 -0700124 setDisplayTitle(currentTab.getUrl());
John Reck0f602f32011-07-07 15:38:43 -0700125 }
126 }
127 mBaseUi.suggestHideTitleBar();
128 }
129 mUrlInput.clearNeedsUpdate();
130 }
131
132 protected void setFocusState(boolean focus) {
133 }
134
John Reck0f602f32011-07-07 15:38:43 -0700135 public boolean isEditingUrl() {
136 return mUrlInput.hasFocus();
137 }
138
139 void stopEditingUrl() {
Michael Kolb0b129122012-06-04 16:31:58 -0700140 WebView currentTopWebView = mUiController.getCurrentTopWebView();
141 if (currentTopWebView != null) {
142 currentTopWebView.requestFocus();
143 }
John Reck0f602f32011-07-07 15:38:43 -0700144 }
145
146 void setDisplayTitle(String title) {
147 if (!isEditingUrl()) {
Michael Kolb29aab402012-05-29 17:22:35 -0700148 if (!title.equals(mUrlInput.getText().toString())) {
149 mUrlInput.setText(title, false);
150 }
John Reck0f602f32011-07-07 15:38:43 -0700151 }
152 }
153
John Reck0f602f32011-07-07 15:38:43 -0700154 void setIncognitoMode(boolean incognito) {
155 mUrlInput.setIncognitoMode(incognito);
156 }
157
158 void clearCompletions() {
Narayan Kamathf3174a52011-11-17 14:43:32 +0000159 mUrlInput.dismissDropDown();
John Reck0f602f32011-07-07 15:38:43 -0700160 }
161
162 // UrlInputListener implementation
163
164 /**
165 * callback from suggestion dropdown
166 * user selected a suggestion
167 */
168 @Override
169 public void onAction(String text, String extra, String source) {
Michael Kolb0b129122012-06-04 16:31:58 -0700170 stopEditingUrl();
John Reck0f602f32011-07-07 15:38:43 -0700171 if (UrlInputView.TYPED.equals(source)) {
kaiyizc4ada322013-07-30 09:58:07 +0800172 String url = null;
Bijan Amirzadae75909d2014-05-06 14:18:54 -0700173 boolean wap2estore = getContext().getResources().getBoolean(R.bool.wap2estore);
Vivek Sekhar5e631472014-03-31 23:59:10 -0700174 if ((wap2estore && isEstoreTypeUrl(text)) || isRtspTypeUrl(text)
175 || isMakeCallTypeUrl(text)) {
kaiyizc4ada322013-07-30 09:58:07 +0800176 url = text;
177 } else {
178 url = UrlUtils.smartUrlFilter(text, false);
179 }
180
John Reck0f602f32011-07-07 15:38:43 -0700181 Tab t = mBaseUi.getActiveTab();
182 // Only shortcut javascript URIs for now, as there is special
183 // logic in UrlHandler for other schemas
184 if (url != null && t != null && url.startsWith("javascript:")) {
185 mUiController.loadUrl(t, url);
186 setDisplayTitle(text);
187 return;
188 }
kaiyizc4ada322013-07-30 09:58:07 +0800189
190 // add for carrier wap2estore feature
191 if (url != null && t != null && wap2estore && isEstoreTypeUrl(url)) {
Vivek Sekharb54614f2014-05-01 19:03:37 -0700192 if (handleEstoreTypeUrl(url)) {
193 setDisplayTitle(text);
194 return;
195 }
kaiyizc4ada322013-07-30 09:58:07 +0800196 }
kaiyiz950eca22013-08-08 11:01:28 +0800197 // add for rtsp scheme feature
198 if (url != null && t != null && isRtspTypeUrl(url)) {
199 if (handleRtspTypeUrl(url)) {
Vivek Sekharb54614f2014-05-01 19:03:37 -0700200 setDisplayTitle(text);
kaiyiz950eca22013-08-08 11:01:28 +0800201 return;
202 }
203 }
Vivek Sekhar5e631472014-03-31 23:59:10 -0700204 // add for "wtai://wp/mc;" scheme feature
205 if (url != null && t != null && isMakeCallTypeUrl(url)) {
206 if (handleMakeCallTypeUrl(url)) {
207 return;
208 }
209 }
John Reck0f602f32011-07-07 15:38:43 -0700210 }
211 Intent i = new Intent();
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700212 String action = Intent.ACTION_SEARCH;
John Reck0f602f32011-07-07 15:38:43 -0700213 i.setAction(action);
214 i.putExtra(SearchManager.QUERY, text);
215 if (extra != null) {
216 i.putExtra(SearchManager.EXTRA_DATA_KEY, extra);
217 }
218 if (source != null) {
219 Bundle appData = new Bundle();
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800220 appData.putString("source", source);
221 i.putExtra("source", appData);
John Reck0f602f32011-07-07 15:38:43 -0700222 }
223 mUiController.handleNewIntent(i);
224 setDisplayTitle(text);
225 }
226
Vivek Sekhar5e631472014-03-31 23:59:10 -0700227 private boolean isMakeCallTypeUrl(String url) {
228 String utf8Url = null;
229 try {
230 utf8Url = new String(url.getBytes("UTF-8"), "UTF-8");
231 } catch (UnsupportedEncodingException e) {
232 Log.e(TAG, "err " + e);
233 }
234 if (utf8Url != null && utf8Url.startsWith(UrlHandler.SCHEME_WTAI_MC)) {
235 return true;
236 }
237 return false;
238 }
239
240 private boolean handleMakeCallTypeUrl(String url) {
241 // wtai://wp/mc;number
242 // number=string(phone-number)
243 if (url.startsWith(UrlHandler.SCHEME_WTAI_MC)) {
244 Intent intent = new Intent(Intent.ACTION_VIEW,
245 Uri.parse(WebView.SCHEME_TEL +
246 url.substring(UrlHandler.SCHEME_WTAI_MC.length())));
247 getContext().startActivity(intent);
248 // before leaving BrowserActivity, close the empty child tab.
249 // If a new tab is created through JavaScript open to load this
250 // url, we would like to close it as we will load this url in a
251 // different Activity.
252 Tab current = mUiController.getCurrentTab();
253 if (current != null
254 && current.getWebView().copyBackForwardList().getSize() == 0) {
255 mUiController.closeCurrentTab();
256 }
257 return true;
258 }
259 return false;
260 }
261
kaiyizc4ada322013-07-30 09:58:07 +0800262 private boolean isEstoreTypeUrl(String url) {
Vivek Sekharb54614f2014-05-01 19:03:37 -0700263 if (url != null && url.startsWith("estore:")) {
kaiyizc4ada322013-07-30 09:58:07 +0800264 return true;
265 }
266 return false;
267 }
268
Vivek Sekharb54614f2014-05-01 19:03:37 -0700269 private boolean handleEstoreTypeUrl(String url) {
270 if (url.getBytes().length > 256) {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800271 Toast.makeText(getContext(), R.string.estore_url_warning, Toast.LENGTH_LONG).show();
Vivek Sekharb54614f2014-05-01 19:03:37 -0700272 return false;
kaiyizc4ada322013-07-30 09:58:07 +0800273 }
Vivek Sekharb54614f2014-05-01 19:03:37 -0700274
275 Intent intent;
276 // perform generic parsing of the URI to turn it into an Intent.
277 try {
278 intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
279 } catch (URISyntaxException ex) {
280 Log.w("Browser", "Bad URI " + url + ": " + ex.getMessage());
281 return false;
282 }
283
kaiyizc4ada322013-07-30 09:58:07 +0800284 try {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800285 getContext().startActivity(intent);
kaiyizc4ada322013-07-30 09:58:07 +0800286 } catch (ActivityNotFoundException ex) {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800287 String downloadUrl = getContext().getResources().getString(R.string.estore_homepage);
kaiyizc4ada322013-07-30 09:58:07 +0800288 mUiController.loadUrl(mBaseUi.getActiveTab(), downloadUrl);
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800289 Toast.makeText(getContext(), R.string.download_estore_app, Toast.LENGTH_LONG).show();
kaiyizc4ada322013-07-30 09:58:07 +0800290 }
Vivek Sekharb54614f2014-05-01 19:03:37 -0700291
292 return true;
kaiyizc4ada322013-07-30 09:58:07 +0800293 }
294
kaiyiz950eca22013-08-08 11:01:28 +0800295 private boolean isRtspTypeUrl(String url) {
296 String utf8Url = null;
297 try {
298 utf8Url = new String(url.getBytes("UTF-8"), "UTF-8");
299 } catch (UnsupportedEncodingException e) {
300 Log.e(TAG, "err " + e);
301 }
302 if (utf8Url != null && utf8Url.startsWith("rtsp://")) {
303 return true;
304 }
305 return false;
306 }
307
308 private boolean handleRtspTypeUrl(String url) {
309 Intent intent;
310 // perform generic parsing of the URI to turn it into an Intent.
311 try {
312 intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
313 } catch (URISyntaxException ex) {
314 Log.w("Browser", "Bad URI " + url + ": " + ex.getMessage());
315 return false;
316 }
317
318 try {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800319 getContext().startActivity(intent);
kaiyiz950eca22013-08-08 11:01:28 +0800320 } catch (ActivityNotFoundException ex) {
321 Log.w("Browser", "No resolveActivity " + url);
322 return false;
323 }
324 return true;
325 }
326
John Reck0f602f32011-07-07 15:38:43 -0700327 @Override
328 public void onDismiss() {
329 final Tab currentTab = mBaseUi.getActiveTab();
330 mBaseUi.hideTitleBar();
331 post(new Runnable() {
332 public void run() {
333 clearFocus();
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700334 if (currentTab != null) {
John Reck0f602f32011-07-07 15:38:43 -0700335 setDisplayTitle(currentTab.getUrl());
336 }
337 }
338 });
339 }
340
341 /**
342 * callback from the suggestion dropdown
343 * copy text to input field and stay in edit mode
344 */
345 @Override
346 public void onCopySuggestion(String text) {
347 mUrlInput.setText(text, true);
348 if (text != null) {
349 mUrlInput.setSelection(text.length());
350 }
351 }
352
353 public void setCurrentUrlIsBookmark(boolean isBookmark) {
354 }
355
356 @Override
357 public boolean dispatchKeyEventPreIme(KeyEvent evt) {
358 if (evt.getKeyCode() == KeyEvent.KEYCODE_BACK) {
359 // catch back key in order to do slightly more cleanup than usual
Michael Kolb0b129122012-06-04 16:31:58 -0700360 stopEditingUrl();
John Reck0f602f32011-07-07 15:38:43 -0700361 }
362 return super.dispatchKeyEventPreIme(evt);
363 }
364
John Reck0f602f32011-07-07 15:38:43 -0700365 /**
366 * called from the Ui when the user wants to edit
367 * @param clearInput clear the input field
368 */
Michael Kolb1f9b3562012-04-24 14:38:34 -0700369 void startEditingUrl(boolean clearInput, boolean forceIME) {
John Reck0f602f32011-07-07 15:38:43 -0700370 // editing takes preference of progress
371 setVisibility(View.VISIBLE);
372 if (mTitleBar.useQuickControls()) {
373 mTitleBar.getProgressView().setVisibility(View.GONE);
374 }
375 if (!mUrlInput.hasFocus()) {
376 mUrlInput.requestFocus();
377 }
378 if (clearInput) {
379 mUrlInput.setText("");
John Reck0f602f32011-07-07 15:38:43 -0700380 }
Michael Kolb1f9b3562012-04-24 14:38:34 -0700381 if (forceIME) {
Michael Kolb4bb6fcb2012-04-13 14:25:27 -0700382 mUrlInput.showIME();
383 }
John Reck0f602f32011-07-07 15:38:43 -0700384 }
385
386 public void onProgressStarted() {
387 }
388
389 public void onProgressStopped() {
390 }
391
John Reck58891902011-08-11 17:48:53 -0700392 public boolean isMenuShowing() {
John Reck42229bc2011-08-19 13:26:43 -0700393 return false;
John Reck58891902011-08-11 17:48:53 -0700394 }
395
John Reck419f6b42011-08-16 16:10:51 -0700396 public void onTabDataChanged(Tab tab) {
397 }
398
Michael Kolb0b129122012-06-04 16:31:58 -0700399 public void onVoiceResult(String s) {
400 startEditingUrl(true, true);
401 onCopySuggestion(s);
402 }
403
Narayan Kamathf3174a52011-11-17 14:43:32 +0000404 @Override
405 public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
406
407 @Override
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700408 public void onTextChanged(CharSequence s, int start, int before, int count) { }
Narayan Kamathf3174a52011-11-17 14:43:32 +0000409
410 @Override
411 public void afterTextChanged(Editable s) { }
Michael Kolb0b129122012-06-04 16:31:58 -0700412
John Reck0f602f32011-07-07 15:38:43 -0700413}