blob: 8d34f137bee285154b0ded818cab4b68efb4e5e7 [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
Pankaj Garg32e1b942015-06-03 18:13:24 -070018import android.animation.ArgbEvaluator;
19import android.animation.ValueAnimator;
Enrico Ros1f5a0952014-11-18 20:15:48 -080020import android.app.Activity;
John Reck0f602f32011-07-07 15:38:43 -070021import android.app.SearchManager;
kaiyizc4ada322013-07-30 09:58:07 +080022import android.content.ActivityNotFoundException;
John Reck0f602f32011-07-07 15:38:43 -070023import android.content.Context;
24import android.content.Intent;
Pankaj Garg32e1b942015-06-03 18:13:24 -070025import android.content.SharedPreferences;
John Reck0f602f32011-07-07 15:38:43 -070026import android.graphics.Bitmap;
Pankaj Garg66f8cef2015-07-07 17:29:03 -070027import android.graphics.BitmapFactory;
Pankaj Garg32e1b942015-06-03 18:13:24 -070028import android.graphics.Color;
kaiyizc4ada322013-07-30 09:58:07 +080029import android.net.Uri;
Pankaj Garg32e1b942015-06-03 18:13:24 -070030import android.net.http.SslCertificate;
31import android.net.http.SslError;
32import android.os.Build;
John Reck0f602f32011-07-07 15:38:43 -070033import android.os.Bundle;
Pankaj Garg66f8cef2015-07-07 17:29:03 -070034import android.os.Handler;
35import android.os.Message;
Narayan Kamathf3174a52011-11-17 14:43:32 +000036import android.text.Editable;
Pankaj Garg66f8cef2015-07-07 17:29:03 -070037import android.text.TextUtils;
Narayan Kamathf3174a52011-11-17 14:43:32 +000038import android.text.TextWatcher;
John Reck0f602f32011-07-07 15:38:43 -070039import android.util.AttributeSet;
kaiyizc4ada322013-07-30 09:58:07 +080040import android.util.Log;
John Reck0f602f32011-07-07 15:38:43 -070041import android.view.KeyEvent;
Enrico Ros1f5a0952014-11-18 20:15:48 -080042import android.view.Menu;
43import android.view.MenuItem;
John Reck0f602f32011-07-07 15:38:43 -070044import android.view.View;
45import android.view.View.OnClickListener;
46import android.view.View.OnFocusChangeListener;
John Reck0f602f32011-07-07 15:38:43 -070047import android.widget.ImageView;
48import android.widget.LinearLayout;
Enrico Ros1f5a0952014-11-18 20:15:48 -080049import android.widget.PopupMenu;
kaiyizc4ada322013-07-30 09:58:07 +080050import android.widget.Toast;
John Reck0f602f32011-07-07 15:38:43 -070051
Bijan Amirzada41242f22014-03-21 12:12:18 -070052import com.android.browser.UrlInputView.UrlInputListener;
Pankaj Garg32e1b942015-06-03 18:13:24 -070053import com.android.browser.preferences.SiteSpecificPreferencesFragment;
John Reck0f602f32011-07-07 15:38:43 -070054
Pankaj Garg32e1b942015-06-03 18:13:24 -070055import java.io.ByteArrayOutputStream;
kaiyizc4ada322013-07-30 09:58:07 +080056import java.io.UnsupportedEncodingException;
Pankaj Garg32e1b942015-06-03 18:13:24 -070057import java.net.MalformedURLException;
kaiyiz950eca22013-08-08 11:01:28 +080058import java.net.URISyntaxException;
Pankaj Garg32e1b942015-06-03 18:13:24 -070059import java.net.URL;
kaiyizc4ada322013-07-30 09:58:07 +080060
Dany Rybnikovbcd37da2015-04-20 11:43:15 +030061import org.codeaurora.net.NetworkServices;
Kevin Hart055e6d82014-12-19 15:53:19 -080062import org.codeaurora.swe.Engine;
Pankaj Garg32e1b942015-06-03 18:13:24 -070063import org.codeaurora.swe.WebRefiner;
Bijan Amirzada9b1e9882014-02-26 17:15:46 -080064import org.codeaurora.swe.WebView;
Pankaj Garg32e1b942015-06-03 18:13:24 -070065import org.codeaurora.swe.util.ColorUtils;
Bijan Amirzada9b1e9882014-02-26 17:15:46 -080066
John Reck42229bc2011-08-19 13:26:43 -070067public class NavigationBarBase extends LinearLayout implements
68 OnClickListener, UrlInputListener, OnFocusChangeListener,
Enrico Ros1f5a0952014-11-18 20:15:48 -080069 TextWatcher, UrlInputView.StateListener,
70 PopupMenu.OnMenuItemClickListener, PopupMenu.OnDismissListener {
John Reck0f602f32011-07-07 15:38:43 -070071
kaiyizc4ada322013-07-30 09:58:07 +080072 private final static String TAG = "NavigationBarBase";
73
John Reck0f602f32011-07-07 15:38:43 -070074 protected BaseUi mBaseUi;
75 protected TitleBar mTitleBar;
76 protected UiController mUiController;
77 protected UrlInputView mUrlInput;
Pankaj Garg66f8cef2015-07-07 17:29:03 -070078 protected ImageView mStopButton;
John Reck0f602f32011-07-07 15:38:43 -070079
Pankaj Garg66f8cef2015-07-07 17:29:03 -070080 private SiteTileView mFaviconTile;
81 private ImageView mMagnify;
82 private View mVoiceButton;
83 private ImageView mClearButton;
Enrico Ros1f5a0952014-11-18 20:15:48 -080084 private View mMore;
85 private PopupMenu mPopupMenu;
86 private boolean mOverflowMenuShowing;
Axesh R. Ajmera2e241242014-05-19 15:53:38 -070087
Pankaj Garg66f8cef2015-07-07 17:29:03 -070088 private static Bitmap mDefaultFavicon;
89
Pankaj Garg32e1b942015-06-03 18:13:24 -070090 private int mStatusBarColor;
91 private static int mDefaultStatusBarColor = -1;
92
Pankaj Garg66f8cef2015-07-07 17:29:03 -070093 private static final int WEBREFINER_COUNTER_MSG = 4242;
94 private static final int WEBREFINER_COUNTER_MSG_DELAY = 3000;
95 private Handler mHandler;
96
Pankaj Garg32e1b942015-06-03 18:13:24 -070097 private Tab.SecurityState mSecurityState = Tab.SecurityState.SECURITY_STATE_NOT_SECURE;
98
Pankaj Garg66f8cef2015-07-07 17:29:03 -070099 private static final String noSitePrefs[] = {
Axesh R. Ajmera1f998ae2015-04-21 14:16:41 -0700100 "browser://",
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700101 "about:",
102 "content:",
103 };
104
John Reck0f602f32011-07-07 15:38:43 -0700105 public NavigationBarBase(Context context) {
106 super(context);
107 }
108
109 public NavigationBarBase(Context context, AttributeSet attrs) {
110 super(context, attrs);
111 }
112
113 public NavigationBarBase(Context context, AttributeSet attrs, int defStyle) {
114 super(context, attrs, defStyle);
115 }
116
117 @Override
118 protected void onFinishInflate() {
119 super.onFinishInflate();
John Reck0f602f32011-07-07 15:38:43 -0700120 mUrlInput = (UrlInputView) findViewById(R.id.url);
121 mUrlInput.setUrlInputListener(this);
John Reck0f602f32011-07-07 15:38:43 -0700122 mUrlInput.setOnFocusChangeListener(this);
123 mUrlInput.setSelectAllOnFocus(true);
Narayan Kamathf3174a52011-11-17 14:43:32 +0000124 mUrlInput.addTextChangedListener(this);
Enrico Ros1f5a0952014-11-18 20:15:48 -0800125 mMore = findViewById(R.id.more_browser_settings);
126 mMore.setOnClickListener(this);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700127 mMagnify = (ImageView) findViewById(R.id.magnify);
128 mMagnify.setOnClickListener(this);
129 mFaviconTile = (SiteTileView) findViewById(R.id.favicon_view);
130 mFaviconTile.setOnClickListener(this);
131 mVoiceButton = findViewById(R.id.voice);
132 mVoiceButton.setOnClickListener(this);
133 mClearButton = (ImageView) findViewById(R.id.clear);
134 mClearButton.setOnClickListener(this);
135 mStopButton = (ImageView) findViewById(R.id.stop);
136 mStopButton.setOnClickListener(this);
137
138 mDefaultFavicon = BitmapFactory.decodeResource(getResources(),
139 R.drawable.ic_deco_favicon_normal);
140
141 mHandler = new Handler() {
142 @Override
143 public void handleMessage(Message m) {
144 switch (m.what) {
145 case WEBREFINER_COUNTER_MSG:
146 WebView wv = mUiController.getCurrentTopWebView();
147 if (wv != null && WebRefiner.isInitialized()) {
148 int count = WebRefiner.getInstance().getBlockedURLCount(wv);
149 if (count > 0) {
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700150 mFaviconTile.setBadgeBlockedObjectsCount(count);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700151 }
152 }
153 mHandler.sendEmptyMessageDelayed(WEBREFINER_COUNTER_MSG,
154 WEBREFINER_COUNTER_MSG_DELAY);
155 break;
156 }
157 }
158 };
John Reck0f602f32011-07-07 15:38:43 -0700159 }
160
161 public void setTitleBar(TitleBar titleBar) {
162 mTitleBar = titleBar;
163 mBaseUi = mTitleBar.getUi();
164 mUiController = mTitleBar.getUiController();
Michael Kolbb2e91fd2011-07-14 13:47:29 -0700165 mUrlInput.setController(mUiController);
John Reck0f602f32011-07-07 15:38:43 -0700166 }
167
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700168 public void setSecurityState(Tab.SecurityState securityState) {
Pankaj Garg32e1b942015-06-03 18:13:24 -0700169 mSecurityState = securityState;
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700170 switch (mSecurityState) {
171 case SECURITY_STATE_SECURE:
172 mFaviconTile.setTrustLevel(SiteTileView.TRUST_TRUSTED);
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700173 mFaviconTile.setBadgeHasCertIssues(false);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700174 break;
175 case SECURITY_STATE_MIXED:
176 mFaviconTile.setTrustLevel(SiteTileView.TRUST_UNTRUSTED);
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700177 mFaviconTile.setBadgeHasCertIssues(true);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700178 break;
179 case SECURITY_STATE_BAD_CERTIFICATE:
180 mFaviconTile.setTrustLevel(SiteTileView.TRUST_AVOID);
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700181 mFaviconTile.setBadgeHasCertIssues(true);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700182 break;
183 case SECURITY_STATE_NOT_SECURE:
184 default:
185 mFaviconTile.setTrustLevel(SiteTileView.TRUST_UNKNOWN);
John Reck0f602f32011-07-07 15:38:43 -0700186 }
187 }
188
Pankaj Garg32e1b942015-06-03 18:13:24 -0700189 public static int adjustColor(int color, float hueMultiplier,
190 float saturationMultiplier, float valueMultiplier) {
191 float[] hsv = new float[3];
192 Color.colorToHSV(color, hsv);
193 hsv[0] *= hueMultiplier;
194 hsv[1] *= saturationMultiplier;
195 hsv[2] *= valueMultiplier;
196 return Color.HSVToColor(Color.alpha(color), hsv);
197 }
198
199 public static void setStatusAndNavigationBarColor(final Activity activity, int color) {
200 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
201 int currentColor = activity.getWindow().getStatusBarColor();
202 Integer from = currentColor;
203 Integer to = color;
204 ValueAnimator animator = ValueAnimator.ofObject(new ArgbEvaluator(), from, to);
205
206 if (mDefaultStatusBarColor == -1) {
207 mDefaultStatusBarColor = activity.getWindow().getStatusBarColor();
208 }
209
210 animator.addUpdateListener(
211 new ValueAnimator.AnimatorUpdateListener() {
212 @Override
213 public void onAnimationUpdate(ValueAnimator animation) {
214 Integer value = (Integer) animation.getAnimatedValue();
215 activity.getWindow().setStatusBarColor(value.intValue());
216 //activity.getWindow().setNavigationBarColor(value.intValue());
217 }
218 }
219 );
220 animator.start();
221 }
222 }
223
224 private void updateSiteIconColor(String urlString, int color) {
225 try {
226 URL url = new URL(urlString);
227 String host = url.getHost();
228 SharedPreferences prefs = BrowserSettings.getInstance().getPreferences();
229 int currentColor = prefs.getInt(host + ":color", 0);
230 if (currentColor != color) {
231 SharedPreferences.Editor editor = prefs.edit();
232 editor.remove(host + ":color");
233 editor.putInt(host + ":color", color);
234 editor.commit();
235 }
236 } catch (MalformedURLException e) {
237 }
238 }
239
240 public static int getSiteIconColor(String urlString) {
241 try {
242 URL url = new URL(urlString);
243 String host = url.getHost();
244 SharedPreferences prefs = BrowserSettings.getInstance().getPreferences();
245 return prefs.getInt(host + ":color", 0);
246 } catch (MalformedURLException e) {
247 return 0;
248 }
249 }
250
251 public static int getDefaultStatusBarColor() {
252 return mDefaultStatusBarColor;
253 }
254
John Reck0f602f32011-07-07 15:38:43 -0700255 public void setFavicon(Bitmap icon) {
Pankaj Garg32e1b942015-06-03 18:13:24 -0700256 int color = ColorUtils.getDominantColorForBitmap(icon);
257 Tab tab = mUiController.getCurrentTab();
258
259 if (tab != null) {
260 if (tab.hasFavicon()) {
261 updateSiteIconColor(tab.getUrl(), color);
262 setStatusAndNavigationBarColor(mUiController.getActivity(),
263 adjustColor(color, 1, 1, 0.7f));
264 } else {
265 color = getSiteIconColor(tab.getUrl());
266 if (color != 0) {
267 setStatusAndNavigationBarColor(mUiController.getActivity(),
268 adjustColor(color, 1, 1, 0.7f));
269 } else {
270 setStatusAndNavigationBarColor(mUiController.getActivity(),
271 mDefaultStatusBarColor);
272 }
273 }
274 } else {
275 setStatusAndNavigationBarColor(mUiController.getActivity(), mDefaultStatusBarColor);
276 }
277
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700278 //Bitmap favicon = mUiController.getCurrentTopWebView().getFavicon();
279
280 if (mFaviconTile != null) {
281 mFaviconTile.replaceFavicon(mUiController.getCurrentTopWebView().getFavicon());
282 }
John Reck0f602f32011-07-07 15:38:43 -0700283 }
284
Pankaj Garg32e1b942015-06-03 18:13:24 -0700285 protected void showSiteSpecificSettings() {
286 WebView wv = mUiController.getCurrentTopWebView();
Pankaj Gargdbdf5aa2015-07-16 15:22:37 -0700287 int ads = 0;
288 int tracker = 0;
289 int malware = 0;
Pankaj Garg32e1b942015-06-03 18:13:24 -0700290
Pankaj Gargdbdf5aa2015-07-16 15:22:37 -0700291 WebRefiner webRefiner = WebRefiner.getInstance();
292 if (wv != null && webRefiner != null) {
293 WebRefiner.PageInfo pageInfo = webRefiner.getPageInfo(wv);
294 if (pageInfo != null) {
295 for (WebRefiner.MatchedURLInfo urlInfo : pageInfo.mMatchedURLInfoList) {
Pankaj Gargee992032015-07-24 15:59:36 -0700296 if (urlInfo.mActionTaken == WebRefiner.MatchedURLInfo.ACTION_BLOCKED) {
297 switch (urlInfo.mMatchedFilterCategory) {
298 case WebRefiner.RuleSet.CATEGORY_ADS:
299 ads++;
300 break;
301 case WebRefiner.RuleSet.CATEGORY_TRACKERS:
302 tracker++;
303 break;
304 case WebRefiner.RuleSet.CATEGORY_MALWARE_DOMAINS:
305 malware++;
306 break;
307 }
Pankaj Gargdbdf5aa2015-07-16 15:22:37 -0700308 }
309 }
310 }
Pankaj Garg32e1b942015-06-03 18:13:24 -0700311 }
312
313 Bundle bundle = new Bundle();
314 bundle.putCharSequence(SiteSpecificPreferencesFragment.EXTRA_SITE,
315 mUiController.getCurrentTab().getUrl());
Pankaj Gargdbdf5aa2015-07-16 15:22:37 -0700316
317 bundle.putInt(SiteSpecificPreferencesFragment.EXTRA_WEB_REFINER_ADS_INFO, ads);
318 bundle.putInt(SiteSpecificPreferencesFragment.EXTRA_WEB_REFINER_TRACKER_INFO, tracker);
319 bundle.putInt(SiteSpecificPreferencesFragment.EXTRA_WEB_REFINER_MALWARE_INFO, malware);
Pankaj Garg32e1b942015-06-03 18:13:24 -0700320
321 bundle.putParcelable(SiteSpecificPreferencesFragment.EXTRA_SECURITY_CERT,
322 SslCertificate.saveState(wv.getCertificate()));
323
324 SslError error = mUiController.getCurrentTab().getSslCertificateError();
325 if (error != null) {
326 int certError = 0;
327 if (error.hasError(SslError.SSL_DATE_INVALID)) {
328 certError |= (1 << SslError.SSL_DATE_INVALID);
329 }
330
331 if (error.hasError(SslError.SSL_EXPIRED)) {
332 certError |= (1 << SslError.SSL_EXPIRED);
333 }
334
335 if (error.hasError(SslError.SSL_IDMISMATCH)) {
336 certError |= (1 << SslError.SSL_IDMISMATCH);
337 }
338
339 if (error.hasError(SslError.SSL_INVALID)) {
340 certError |= (1 << SslError.SSL_INVALID);
341 }
342
343 if (error.hasError(SslError.SSL_NOTYETVALID)) {
344 certError |= (1 << SslError.SSL_NOTYETVALID);
345 }
346
347 if (error.hasError(SslError.SSL_UNTRUSTED)) {
348 certError |= (1 << SslError.SSL_UNTRUSTED);
349 }
350
351 bundle.putInt(SiteSpecificPreferencesFragment.EXTRA_SECURITY_CERT_ERR, certError);
352 }
353
Pankaj Garg68faf1c2015-06-26 17:07:37 -0700354 Bitmap favicon = mUiController.getCurrentTopWebView().getFavicon();
Pankaj Garg32e1b942015-06-03 18:13:24 -0700355 if (favicon != null) {
356 ByteArrayOutputStream baos = new ByteArrayOutputStream();
357 favicon.compress(Bitmap.CompressFormat.PNG, 50, baos);
358 bundle.putByteArray(SiteSpecificPreferencesFragment.EXTRA_FAVICON,
359 baos.toByteArray());
360 }
361 BrowserPreferencesPage.startPreferenceFragmentExtraForResult(
362 mUiController.getActivity(),
363 SiteSpecificPreferencesFragment.class.getName(), bundle, 0);
364 }
365
John Reck0f602f32011-07-07 15:38:43 -0700366 @Override
367 public void onClick(View v) {
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700368 Tab currentTab = mUiController.getCurrentTab();
369 String url = null;
370 if (currentTab != null){
371 url = currentTab.getUrl();
372 }
Enrico Ros1f5a0952014-11-18 20:15:48 -0800373 if (mMore == v) {
374 showMenu(mMore);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700375 } else if (mFaviconTile == v) {
376 if (urlHasSitePrefs(url)){
377 showSiteSpecificSettings();
378 }
379 } else if (mMagnify == v) {
380 startEditingUrl(true, true);
381 } else if (mVoiceButton == v) {
382 mUiController.startVoiceRecognizer();
383 } else if (mStopButton == v) {
384 stopOrRefresh();
385 } else if (mClearButton == v) {
386 clearOrClose();
387 mUrlInput.setText("");
388 }
389 }
390
391 private static boolean urlHasSitePrefs(String url) {
392 if (TextUtils.isEmpty(url)) {
393 return false;
394 }
395
396 for (int i = 0; i < noSitePrefs.length; i++) {
397 if (url.startsWith(noSitePrefs[i])) {
398 return false;
399 }
400 }
401 return true;
402 }
403
404 private void stopOrRefresh() {
405 if (mUiController == null) return;
406 if (mTitleBar.isInLoad()) {
407 mUiController.stopLoading();
408 } else {
409 if (mUiController.getCurrentTopWebView() != null) {
410 stopEditingUrl();
411 mUiController.getCurrentTopWebView().reload();
412 }
413 }
414 }
415
416 private void clearOrClose() {
417 if (TextUtils.isEmpty(mUrlInput.getText())) {
418 // close
419 mUrlInput.clearFocus();
420 } else {
421 // clear
422 mUrlInput.setText("");
Enrico Ros1f5a0952014-11-18 20:15:48 -0800423 }
424 }
425
426 void showMenu(View anchor) {
427 Activity activity = mUiController.getActivity();
428 if (mPopupMenu == null) {
429 mPopupMenu = new PopupMenu(getContext(), anchor);
430 mPopupMenu.setOnMenuItemClickListener(this);
431 mPopupMenu.setOnDismissListener(this);
432 if (!activity.onCreateOptionsMenu(mPopupMenu.getMenu())) {
433 mPopupMenu = null;
434 return;
435 }
436 }
437 Menu menu = mPopupMenu.getMenu();
438
439 if (mUiController instanceof Controller) {
440 Controller controller = (Controller) mUiController;
441 if (controller.onPrepareOptionsMenu(menu)) {
442 mOverflowMenuShowing = true;
443 }
444 }
John Reck0f602f32011-07-07 15:38:43 -0700445 }
446
447 @Override
448 public void onFocusChange(View view, boolean hasFocus) {
449 // if losing focus and not in touch mode, leave as is
450 if (hasFocus || view.isInTouchMode() || mUrlInput.needsUpdate()) {
451 setFocusState(hasFocus);
452 }
453 if (hasFocus) {
Kevin Hart055e6d82014-12-19 15:53:19 -0800454 Engine.warmUpChildProcessAsync(mUiController.getActivity().getApplicationContext());
John Reck0f602f32011-07-07 15:38:43 -0700455 mBaseUi.showTitleBar();
Dany Rybnikovbcd37da2015-04-20 11:43:15 +0300456 if (!BrowserSettings.getInstance().isPowerSaveModeEnabled()) {
457 //Notify about anticipated network activity
458 NetworkServices.hintUpcomingUserActivity();
459 }
John Reck0f602f32011-07-07 15:38:43 -0700460 } else if (!mUrlInput.needsUpdate()) {
461 mUrlInput.dismissDropDown();
462 mUrlInput.hideIME();
463 if (mUrlInput.getText().length() == 0) {
464 Tab currentTab = mUiController.getTabControl().getCurrentTab();
465 if (currentTab != null) {
John Reck434e9f82011-08-10 18:16:52 -0700466 setDisplayTitle(currentTab.getUrl());
John Reck0f602f32011-07-07 15:38:43 -0700467 }
468 }
John Reck0f602f32011-07-07 15:38:43 -0700469 }
470 mUrlInput.clearNeedsUpdate();
471 }
472
473 protected void setFocusState(boolean focus) {
474 }
475
John Reck0f602f32011-07-07 15:38:43 -0700476 public boolean isEditingUrl() {
477 return mUrlInput.hasFocus();
478 }
479
480 void stopEditingUrl() {
Michael Kolb0b129122012-06-04 16:31:58 -0700481 WebView currentTopWebView = mUiController.getCurrentTopWebView();
482 if (currentTopWebView != null) {
483 currentTopWebView.requestFocus();
484 }
John Reck0f602f32011-07-07 15:38:43 -0700485 }
486
487 void setDisplayTitle(String title) {
488 if (!isEditingUrl()) {
Michael Kolb29aab402012-05-29 17:22:35 -0700489 if (!title.equals(mUrlInput.getText().toString())) {
490 mUrlInput.setText(title, false);
491 }
John Reck0f602f32011-07-07 15:38:43 -0700492 }
493 }
494
John Reck0f602f32011-07-07 15:38:43 -0700495 void setIncognitoMode(boolean incognito) {
496 mUrlInput.setIncognitoMode(incognito);
497 }
498
499 void clearCompletions() {
Narayan Kamathf3174a52011-11-17 14:43:32 +0000500 mUrlInput.dismissDropDown();
John Reck0f602f32011-07-07 15:38:43 -0700501 }
502
503 // UrlInputListener implementation
504
505 /**
506 * callback from suggestion dropdown
507 * user selected a suggestion
508 */
509 @Override
510 public void onAction(String text, String extra, String source) {
Michael Kolb0b129122012-06-04 16:31:58 -0700511 stopEditingUrl();
John Reck0f602f32011-07-07 15:38:43 -0700512 if (UrlInputView.TYPED.equals(source)) {
kaiyizc4ada322013-07-30 09:58:07 +0800513 String url = null;
Panos Thomas4bdb5252014-11-13 16:20:11 -0800514 boolean wap2estore = BrowserConfig.getInstance(getContext())
515 .hasFeature(BrowserConfig.Feature.WAP2ESTORE);
Vivek Sekhar5e631472014-03-31 23:59:10 -0700516 if ((wap2estore && isEstoreTypeUrl(text)) || isRtspTypeUrl(text)
517 || isMakeCallTypeUrl(text)) {
kaiyizc4ada322013-07-30 09:58:07 +0800518 url = text;
519 } else {
520 url = UrlUtils.smartUrlFilter(text, false);
521 }
522
John Reck0f602f32011-07-07 15:38:43 -0700523 Tab t = mBaseUi.getActiveTab();
524 // Only shortcut javascript URIs for now, as there is special
525 // logic in UrlHandler for other schemas
Axesh R. Ajmera1f998ae2015-04-21 14:16:41 -0700526 if (url != null && t != null && url.startsWith("javascript:")) {
John Reck0f602f32011-07-07 15:38:43 -0700527 mUiController.loadUrl(t, url);
528 setDisplayTitle(text);
529 return;
530 }
kaiyizc4ada322013-07-30 09:58:07 +0800531
532 // add for carrier wap2estore feature
533 if (url != null && t != null && wap2estore && isEstoreTypeUrl(url)) {
Vivek Sekharb54614f2014-05-01 19:03:37 -0700534 if (handleEstoreTypeUrl(url)) {
535 setDisplayTitle(text);
536 return;
537 }
kaiyizc4ada322013-07-30 09:58:07 +0800538 }
kaiyiz950eca22013-08-08 11:01:28 +0800539 // add for rtsp scheme feature
540 if (url != null && t != null && isRtspTypeUrl(url)) {
541 if (handleRtspTypeUrl(url)) {
Vivek Sekharb54614f2014-05-01 19:03:37 -0700542 setDisplayTitle(text);
kaiyiz950eca22013-08-08 11:01:28 +0800543 return;
544 }
545 }
Vivek Sekhar5e631472014-03-31 23:59:10 -0700546 // add for "wtai://wp/mc;" scheme feature
547 if (url != null && t != null && isMakeCallTypeUrl(url)) {
548 if (handleMakeCallTypeUrl(url)) {
549 return;
550 }
551 }
John Reck0f602f32011-07-07 15:38:43 -0700552 }
553 Intent i = new Intent();
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700554 String action = Intent.ACTION_SEARCH;
John Reck0f602f32011-07-07 15:38:43 -0700555 i.setAction(action);
556 i.putExtra(SearchManager.QUERY, text);
557 if (extra != null) {
558 i.putExtra(SearchManager.EXTRA_DATA_KEY, extra);
559 }
560 if (source != null) {
561 Bundle appData = new Bundle();
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800562 appData.putString("source", source);
563 i.putExtra("source", appData);
John Reck0f602f32011-07-07 15:38:43 -0700564 }
565 mUiController.handleNewIntent(i);
566 setDisplayTitle(text);
567 }
568
Vivek Sekhar5e631472014-03-31 23:59:10 -0700569 private boolean isMakeCallTypeUrl(String url) {
570 String utf8Url = null;
571 try {
572 utf8Url = new String(url.getBytes("UTF-8"), "UTF-8");
573 } catch (UnsupportedEncodingException e) {
574 Log.e(TAG, "err " + e);
575 }
576 if (utf8Url != null && utf8Url.startsWith(UrlHandler.SCHEME_WTAI_MC)) {
577 return true;
578 }
579 return false;
580 }
581
582 private boolean handleMakeCallTypeUrl(String url) {
583 // wtai://wp/mc;number
584 // number=string(phone-number)
585 if (url.startsWith(UrlHandler.SCHEME_WTAI_MC)) {
586 Intent intent = new Intent(Intent.ACTION_VIEW,
587 Uri.parse(WebView.SCHEME_TEL +
588 url.substring(UrlHandler.SCHEME_WTAI_MC.length())));
589 getContext().startActivity(intent);
590 // before leaving BrowserActivity, close the empty child tab.
591 // If a new tab is created through JavaScript open to load this
592 // url, we would like to close it as we will load this url in a
593 // different Activity.
594 Tab current = mUiController.getCurrentTab();
595 if (current != null
596 && current.getWebView().copyBackForwardList().getSize() == 0) {
597 mUiController.closeCurrentTab();
598 }
599 return true;
600 }
601 return false;
602 }
603
kaiyizc4ada322013-07-30 09:58:07 +0800604 private boolean isEstoreTypeUrl(String url) {
Vivek Sekharb54614f2014-05-01 19:03:37 -0700605 if (url != null && url.startsWith("estore:")) {
kaiyizc4ada322013-07-30 09:58:07 +0800606 return true;
607 }
608 return false;
609 }
610
Vivek Sekharb54614f2014-05-01 19:03:37 -0700611 private boolean handleEstoreTypeUrl(String url) {
612 if (url.getBytes().length > 256) {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800613 Toast.makeText(getContext(), R.string.estore_url_warning, Toast.LENGTH_LONG).show();
Vivek Sekharb54614f2014-05-01 19:03:37 -0700614 return false;
kaiyizc4ada322013-07-30 09:58:07 +0800615 }
Vivek Sekharb54614f2014-05-01 19:03:37 -0700616
617 Intent intent;
618 // perform generic parsing of the URI to turn it into an Intent.
619 try {
620 intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
621 } catch (URISyntaxException ex) {
622 Log.w("Browser", "Bad URI " + url + ": " + ex.getMessage());
623 return false;
624 }
625
kaiyizc4ada322013-07-30 09:58:07 +0800626 try {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800627 getContext().startActivity(intent);
kaiyizc4ada322013-07-30 09:58:07 +0800628 } catch (ActivityNotFoundException ex) {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800629 String downloadUrl = getContext().getResources().getString(R.string.estore_homepage);
kaiyizc4ada322013-07-30 09:58:07 +0800630 mUiController.loadUrl(mBaseUi.getActiveTab(), downloadUrl);
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800631 Toast.makeText(getContext(), R.string.download_estore_app, Toast.LENGTH_LONG).show();
kaiyizc4ada322013-07-30 09:58:07 +0800632 }
Vivek Sekharb54614f2014-05-01 19:03:37 -0700633
634 return true;
kaiyizc4ada322013-07-30 09:58:07 +0800635 }
636
kaiyiz950eca22013-08-08 11:01:28 +0800637 private boolean isRtspTypeUrl(String url) {
638 String utf8Url = null;
639 try {
640 utf8Url = new String(url.getBytes("UTF-8"), "UTF-8");
641 } catch (UnsupportedEncodingException e) {
642 Log.e(TAG, "err " + e);
643 }
644 if (utf8Url != null && utf8Url.startsWith("rtsp://")) {
645 return true;
646 }
647 return false;
648 }
649
650 private boolean handleRtspTypeUrl(String url) {
651 Intent intent;
652 // perform generic parsing of the URI to turn it into an Intent.
653 try {
654 intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
655 } catch (URISyntaxException ex) {
656 Log.w("Browser", "Bad URI " + url + ": " + ex.getMessage());
657 return false;
658 }
659
660 try {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800661 getContext().startActivity(intent);
kaiyiz950eca22013-08-08 11:01:28 +0800662 } catch (ActivityNotFoundException ex) {
663 Log.w("Browser", "No resolveActivity " + url);
664 return false;
665 }
666 return true;
667 }
668
John Reck0f602f32011-07-07 15:38:43 -0700669 @Override
670 public void onDismiss() {
671 final Tab currentTab = mBaseUi.getActiveTab();
672 mBaseUi.hideTitleBar();
673 post(new Runnable() {
674 public void run() {
675 clearFocus();
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700676 if (currentTab != null) {
John Reck0f602f32011-07-07 15:38:43 -0700677 setDisplayTitle(currentTab.getUrl());
678 }
679 }
680 });
681 }
682
683 /**
684 * callback from the suggestion dropdown
685 * copy text to input field and stay in edit mode
686 */
687 @Override
688 public void onCopySuggestion(String text) {
689 mUrlInput.setText(text, true);
690 if (text != null) {
691 mUrlInput.setSelection(text.length());
692 }
693 }
694
695 public void setCurrentUrlIsBookmark(boolean isBookmark) {
696 }
697
698 @Override
699 public boolean dispatchKeyEventPreIme(KeyEvent evt) {
700 if (evt.getKeyCode() == KeyEvent.KEYCODE_BACK) {
701 // catch back key in order to do slightly more cleanup than usual
Michael Kolb0b129122012-06-04 16:31:58 -0700702 stopEditingUrl();
John Reck0f602f32011-07-07 15:38:43 -0700703 }
704 return super.dispatchKeyEventPreIme(evt);
705 }
706
John Reck0f602f32011-07-07 15:38:43 -0700707 /**
708 * called from the Ui when the user wants to edit
709 * @param clearInput clear the input field
710 */
Michael Kolb1f9b3562012-04-24 14:38:34 -0700711 void startEditingUrl(boolean clearInput, boolean forceIME) {
John Reck0f602f32011-07-07 15:38:43 -0700712 // editing takes preference of progress
713 setVisibility(View.VISIBLE);
John Reck0f602f32011-07-07 15:38:43 -0700714 if (!mUrlInput.hasFocus()) {
715 mUrlInput.requestFocus();
716 }
717 if (clearInput) {
718 mUrlInput.setText("");
John Reck0f602f32011-07-07 15:38:43 -0700719 }
Michael Kolb1f9b3562012-04-24 14:38:34 -0700720 if (forceIME) {
Michael Kolb4bb6fcb2012-04-13 14:25:27 -0700721 mUrlInput.showIME();
722 }
John Reck0f602f32011-07-07 15:38:43 -0700723 }
724
725 public void onProgressStarted() {
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700726 mFaviconTile.setBadgeBlockedObjectsCount(0);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700727 mFaviconTile.setTrustLevel(SiteTileView.TRUST_UNKNOWN);
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700728 mFaviconTile.setBadgeHasCertIssues(false);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700729 mFaviconTile.replaceFavicon(mDefaultFavicon);
Pankaj Garg32e1b942015-06-03 18:13:24 -0700730 mSecurityState = Tab.SecurityState.SECURITY_STATE_NOT_SECURE;
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700731 mHandler.removeMessages(WEBREFINER_COUNTER_MSG);
732 mHandler.sendEmptyMessageDelayed(WEBREFINER_COUNTER_MSG,
733 WEBREFINER_COUNTER_MSG_DELAY);
734 mStopButton.setImageResource(R.drawable.ic_action_stop);
735 mStopButton.setContentDescription(getResources().
736 getString(R.string.accessibility_button_stop));
John Reck0f602f32011-07-07 15:38:43 -0700737 }
738
739 public void onProgressStopped() {
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700740 if (!isEditingUrl()) {
741 mFaviconTile.setVisibility(View.VISIBLE);
742 }
743 mStopButton.setImageResource(R.drawable.ic_action_reload);
744 mStopButton.setContentDescription(getResources().
745 getString(R.string.accessibility_button_refresh));
John Reck0f602f32011-07-07 15:38:43 -0700746 }
747
John Reck419f6b42011-08-16 16:10:51 -0700748 public void onTabDataChanged(Tab tab) {
749 }
750
Michael Kolb0b129122012-06-04 16:31:58 -0700751 public void onVoiceResult(String s) {
752 startEditingUrl(true, true);
753 onCopySuggestion(s);
754 }
755
Narayan Kamathf3174a52011-11-17 14:43:32 +0000756 @Override
757 public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
758
759 @Override
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700760 public void onTextChanged(CharSequence s, int start, int before, int count) { }
Narayan Kamathf3174a52011-11-17 14:43:32 +0000761
762 @Override
763 public void afterTextChanged(Editable s) { }
Michael Kolb0b129122012-06-04 16:31:58 -0700764
Enrico Ros1f5a0952014-11-18 20:15:48 -0800765 @Override
766 public void onStateChanged(int state) {
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700767 mVoiceButton.setVisibility(View.GONE);
Enrico Ros1f5a0952014-11-18 20:15:48 -0800768 switch(state) {
769 case STATE_NORMAL:
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700770 mFaviconTile.setVisibility(View.VISIBLE);
771 mMagnify.setVisibility(View.GONE);
772 mClearButton.setVisibility(View.GONE);
Sagar Dhawanaff56c92015-07-13 15:57:11 -0700773 mMore.setVisibility(View.VISIBLE);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700774 if (mUiController != null) {
775 Tab currentTab = mUiController.getCurrentTab();
776 if (currentTab != null){
777 if (TextUtils.isEmpty(currentTab.getUrl())) {
778 mFaviconTile.setVisibility(View.GONE);
779 mMagnify.setVisibility(View.VISIBLE);
780 }
781 }
782 mUiController.setWindowDimming(0.0f);
783 }
784
Enrico Ros1f5a0952014-11-18 20:15:48 -0800785 break;
786 case STATE_HIGHLIGHTED:
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700787 mFaviconTile.setVisibility(View.GONE);
788 mMagnify.setVisibility(View.GONE);
789 mClearButton.setVisibility(View.GONE);
Enrico Ros1f5a0952014-11-18 20:15:48 -0800790 mMore.setVisibility(View.GONE);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700791 if (mUiController != null) {
792 mUiController.setWindowDimming(0.75f);
793 if (mUiController.supportsVoice()) {
794 mVoiceButton.setVisibility(View.VISIBLE);
795 }
796 }
Enrico Ros1f5a0952014-11-18 20:15:48 -0800797 break;
798 case STATE_EDITED:
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700799 mFaviconTile.setVisibility(View.GONE);
800 mMagnify.setVisibility(View.VISIBLE);
801 mClearButton.setVisibility(View.VISIBLE);
Enrico Ros1f5a0952014-11-18 20:15:48 -0800802 mMore.setVisibility(View.GONE);
803 break;
804 }
805 }
806
807 public boolean isMenuShowing() {
808 return mOverflowMenuShowing;
809 }
810
811
812 @Override
813 public void onDismiss(PopupMenu popupMenu) {
814 if (popupMenu == mPopupMenu) {
815 onMenuHidden();
816 }
817 }
818
819 private void onMenuHidden() {
820 mOverflowMenuShowing = false;
Enrico Ros1f5a0952014-11-18 20:15:48 -0800821 }
822
823
824 @Override
825 public boolean onMenuItemClick(MenuItem item) {
826 return mUiController.onOptionsItemSelected(item);
827 }
John Reck0f602f32011-07-07 15:38:43 -0700828}