blob: 53bd9731a25114630f541a3edc997c72e70d83db [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;
Pankaj Garg32e1b942015-06-03 18:13:24 -070031import android.os.Build;
John Reck0f602f32011-07-07 15:38:43 -070032import android.os.Bundle;
Pankaj Garg66f8cef2015-07-07 17:29:03 -070033import android.os.Handler;
34import android.os.Message;
Narayan Kamathf3174a52011-11-17 14:43:32 +000035import android.text.Editable;
Pankaj Garg66f8cef2015-07-07 17:29:03 -070036import android.text.TextUtils;
Narayan Kamathf3174a52011-11-17 14:43:32 +000037import android.text.TextWatcher;
John Reck0f602f32011-07-07 15:38:43 -070038import android.util.AttributeSet;
kaiyizc4ada322013-07-30 09:58:07 +080039import android.util.Log;
John Reck0f602f32011-07-07 15:38:43 -070040import android.view.KeyEvent;
Enrico Ros1f5a0952014-11-18 20:15:48 -080041import android.view.Menu;
42import android.view.MenuItem;
John Reck0f602f32011-07-07 15:38:43 -070043import android.view.View;
44import android.view.View.OnClickListener;
45import android.view.View.OnFocusChangeListener;
John Reck0f602f32011-07-07 15:38:43 -070046import android.widget.ImageView;
47import android.widget.LinearLayout;
Enrico Ros1f5a0952014-11-18 20:15:48 -080048import android.widget.PopupMenu;
kaiyizc4ada322013-07-30 09:58:07 +080049import android.widget.Toast;
John Reck0f602f32011-07-07 15:38:43 -070050
Bijan Amirzada41242f22014-03-21 12:12:18 -070051import com.android.browser.UrlInputView.UrlInputListener;
Pankaj Garg32e1b942015-06-03 18:13:24 -070052import com.android.browser.preferences.SiteSpecificPreferencesFragment;
John Reck0f602f32011-07-07 15:38:43 -070053
Pankaj Garg32e1b942015-06-03 18:13:24 -070054import java.io.ByteArrayOutputStream;
kaiyizc4ada322013-07-30 09:58:07 +080055import java.io.UnsupportedEncodingException;
Pankaj Garg32e1b942015-06-03 18:13:24 -070056import java.net.MalformedURLException;
kaiyiz950eca22013-08-08 11:01:28 +080057import java.net.URISyntaxException;
Pankaj Garg32e1b942015-06-03 18:13:24 -070058import java.net.URL;
kaiyizc4ada322013-07-30 09:58:07 +080059
Dany Rybnikovbcd37da2015-04-20 11:43:15 +030060import org.codeaurora.net.NetworkServices;
Pankaj Garg32e1b942015-06-03 18:13:24 -070061import org.codeaurora.swe.WebRefiner;
Bijan Amirzada9b1e9882014-02-26 17:15:46 -080062import org.codeaurora.swe.WebView;
Pankaj Garg32e1b942015-06-03 18:13:24 -070063import org.codeaurora.swe.util.ColorUtils;
Bijan Amirzada9b1e9882014-02-26 17:15:46 -080064
John Reck42229bc2011-08-19 13:26:43 -070065public class NavigationBarBase extends LinearLayout implements
66 OnClickListener, UrlInputListener, OnFocusChangeListener,
Enrico Ros1f5a0952014-11-18 20:15:48 -080067 TextWatcher, UrlInputView.StateListener,
68 PopupMenu.OnMenuItemClickListener, PopupMenu.OnDismissListener {
John Reck0f602f32011-07-07 15:38:43 -070069
kaiyizc4ada322013-07-30 09:58:07 +080070 private final static String TAG = "NavigationBarBase";
71
John Reck0f602f32011-07-07 15:38:43 -070072 protected BaseUi mBaseUi;
73 protected TitleBar mTitleBar;
74 protected UiController mUiController;
75 protected UrlInputView mUrlInput;
Pankaj Garg66f8cef2015-07-07 17:29:03 -070076 protected ImageView mStopButton;
John Reck0f602f32011-07-07 15:38:43 -070077
Pankaj Garg66f8cef2015-07-07 17:29:03 -070078 private SiteTileView mFaviconTile;
Pankaj Garg66f8cef2015-07-07 17:29:03 -070079 private View mVoiceButton;
80 private ImageView mClearButton;
Enrico Ros1f5a0952014-11-18 20:15:48 -080081 private View mMore;
82 private PopupMenu mPopupMenu;
83 private boolean mOverflowMenuShowing;
Axesh R. Ajmera2e241242014-05-19 15:53:38 -070084
Pankaj Garg66f8cef2015-07-07 17:29:03 -070085 private static Bitmap mDefaultFavicon;
86
Pankaj Garg32e1b942015-06-03 18:13:24 -070087 private int mStatusBarColor;
88 private static int mDefaultStatusBarColor = -1;
89
Pankaj Garg66f8cef2015-07-07 17:29:03 -070090 private static final int WEBREFINER_COUNTER_MSG = 4242;
91 private static final int WEBREFINER_COUNTER_MSG_DELAY = 3000;
92 private Handler mHandler;
93
Pankaj Garg8d2e98f2015-08-07 10:01:49 -070094 protected int mTrustLevel = SiteTileView.TRUST_UNKNOWN;
95
Pankaj Garg66f8cef2015-07-07 17:29:03 -070096 private static final String noSitePrefs[] = {
Axesh R. Ajmera6fc73692015-08-11 16:32:10 -070097 "chrome://",
Pankaj Garg66f8cef2015-07-07 17:29:03 -070098 "about:",
99 "content:",
100 };
101
John Reck0f602f32011-07-07 15:38:43 -0700102 public NavigationBarBase(Context context) {
103 super(context);
104 }
105
106 public NavigationBarBase(Context context, AttributeSet attrs) {
107 super(context, attrs);
108 }
109
110 public NavigationBarBase(Context context, AttributeSet attrs, int defStyle) {
111 super(context, attrs, defStyle);
112 }
113
114 @Override
115 protected void onFinishInflate() {
116 super.onFinishInflate();
John Reck0f602f32011-07-07 15:38:43 -0700117 mUrlInput = (UrlInputView) findViewById(R.id.url);
118 mUrlInput.setUrlInputListener(this);
John Reck0f602f32011-07-07 15:38:43 -0700119 mUrlInput.setOnFocusChangeListener(this);
120 mUrlInput.setSelectAllOnFocus(true);
Narayan Kamathf3174a52011-11-17 14:43:32 +0000121 mUrlInput.addTextChangedListener(this);
Enrico Ros1f5a0952014-11-18 20:15:48 -0800122 mMore = findViewById(R.id.more_browser_settings);
123 mMore.setOnClickListener(this);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700124 mFaviconTile = (SiteTileView) findViewById(R.id.favicon_view);
125 mFaviconTile.setOnClickListener(this);
126 mVoiceButton = findViewById(R.id.voice);
127 mVoiceButton.setOnClickListener(this);
128 mClearButton = (ImageView) findViewById(R.id.clear);
129 mClearButton.setOnClickListener(this);
130 mStopButton = (ImageView) findViewById(R.id.stop);
131 mStopButton.setOnClickListener(this);
132
133 mDefaultFavicon = BitmapFactory.decodeResource(getResources(),
134 R.drawable.ic_deco_favicon_normal);
135
136 mHandler = new Handler() {
137 @Override
138 public void handleMessage(Message m) {
139 switch (m.what) {
140 case WEBREFINER_COUNTER_MSG:
141 WebView wv = mUiController.getCurrentTopWebView();
142 if (wv != null && WebRefiner.isInitialized()) {
143 int count = WebRefiner.getInstance().getBlockedURLCount(wv);
144 if (count > 0) {
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700145 mFaviconTile.setBadgeBlockedObjectsCount(count);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700146 }
147 }
148 mHandler.sendEmptyMessageDelayed(WEBREFINER_COUNTER_MSG,
149 WEBREFINER_COUNTER_MSG_DELAY);
150 break;
151 }
152 }
153 };
John Reck0f602f32011-07-07 15:38:43 -0700154 }
155
156 public void setTitleBar(TitleBar titleBar) {
157 mTitleBar = titleBar;
158 mBaseUi = mTitleBar.getUi();
159 mUiController = mTitleBar.getUiController();
Michael Kolbb2e91fd2011-07-14 13:47:29 -0700160 mUrlInput.setController(mUiController);
John Reck0f602f32011-07-07 15:38:43 -0700161 }
162
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700163 public void setSecurityState(Tab.SecurityState securityState) {
Pankaj Garg96d0ccd2015-07-30 16:49:47 -0700164 switch (securityState) {
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700165 case SECURITY_STATE_SECURE:
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700166 mTrustLevel = SiteTileView.TRUST_TRUSTED;
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700167 mFaviconTile.setBadgeHasCertIssues(false);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700168 break;
169 case SECURITY_STATE_MIXED:
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700170 mTrustLevel = SiteTileView.TRUST_UNTRUSTED;
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700171 mFaviconTile.setBadgeHasCertIssues(true);
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700172 mTitleBar.showTopControls(false);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700173 break;
174 case SECURITY_STATE_BAD_CERTIFICATE:
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700175 mTrustLevel = SiteTileView.TRUST_AVOID;
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700176 mFaviconTile.setBadgeHasCertIssues(true);
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700177 mTitleBar.showTopControls(false);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700178 break;
179 case SECURITY_STATE_NOT_SECURE:
180 default:
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700181 mTrustLevel = SiteTileView.TRUST_UNKNOWN;
John Reck0f602f32011-07-07 15:38:43 -0700182 }
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700183 mFaviconTile.setTrustLevel(mTrustLevel);
184 }
185
186 public int getTrustLevel() {
187 return mTrustLevel;
John Reck0f602f32011-07-07 15:38:43 -0700188 }
189
Pankaj Garg32e1b942015-06-03 18:13:24 -0700190 public static int adjustColor(int color, float hueMultiplier,
191 float saturationMultiplier, float valueMultiplier) {
192 float[] hsv = new float[3];
193 Color.colorToHSV(color, hsv);
194 hsv[0] *= hueMultiplier;
195 hsv[1] *= saturationMultiplier;
196 hsv[2] *= valueMultiplier;
197 return Color.HSVToColor(Color.alpha(color), hsv);
198 }
199
200 public static void setStatusAndNavigationBarColor(final Activity activity, int color) {
201 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
202 int currentColor = activity.getWindow().getStatusBarColor();
203 Integer from = currentColor;
204 Integer to = color;
205 ValueAnimator animator = ValueAnimator.ofObject(new ArgbEvaluator(), from, to);
206
207 if (mDefaultStatusBarColor == -1) {
208 mDefaultStatusBarColor = activity.getWindow().getStatusBarColor();
209 }
210
211 animator.addUpdateListener(
212 new ValueAnimator.AnimatorUpdateListener() {
213 @Override
214 public void onAnimationUpdate(ValueAnimator animation) {
215 Integer value = (Integer) animation.getAnimatedValue();
216 activity.getWindow().setStatusBarColor(value.intValue());
217 //activity.getWindow().setNavigationBarColor(value.intValue());
218 }
219 }
220 );
221 animator.start();
222 }
223 }
224
225 private void updateSiteIconColor(String urlString, int color) {
226 try {
227 URL url = new URL(urlString);
228 String host = url.getHost();
229 SharedPreferences prefs = BrowserSettings.getInstance().getPreferences();
230 int currentColor = prefs.getInt(host + ":color", 0);
231 if (currentColor != color) {
232 SharedPreferences.Editor editor = prefs.edit();
233 editor.remove(host + ":color");
234 editor.putInt(host + ":color", color);
235 editor.commit();
236 }
237 } catch (MalformedURLException e) {
238 }
239 }
240
241 public static int getSiteIconColor(String urlString) {
242 try {
243 URL url = new URL(urlString);
244 String host = url.getHost();
245 SharedPreferences prefs = BrowserSettings.getInstance().getPreferences();
246 return prefs.getInt(host + ":color", 0);
247 } catch (MalformedURLException e) {
248 return 0;
249 }
250 }
251
252 public static int getDefaultStatusBarColor() {
253 return mDefaultStatusBarColor;
254 }
255
Sagar Dhawanca9ecfb2015-08-10 17:27:58 -0700256 // Sets the favicon for the given tab if it's in the foreground
257 // If the tab doesn't have a favicon, it sets the default favicon
258 public void showCurrentFavicon(Tab tab) {
259 int color;
260 if (tab == null) { return; }
Pankaj Garg32e1b942015-06-03 18:13:24 -0700261
Sagar Dhawanca9ecfb2015-08-10 17:27:58 -0700262 if (tab.inForeground()) {
Pankaj Garg32e1b942015-06-03 18:13:24 -0700263 if (tab.hasFavicon()) {
Sagar Dhawanca9ecfb2015-08-10 17:27:58 -0700264 color = ColorUtils.getDominantColorForBitmap(tab.getFavicon());
Pankaj Garg32e1b942015-06-03 18:13:24 -0700265 updateSiteIconColor(tab.getUrl(), color);
266 setStatusAndNavigationBarColor(mUiController.getActivity(),
267 adjustColor(color, 1, 1, 0.7f));
Sagar Dhawanca9ecfb2015-08-10 17:27:58 -0700268
269 } else {
Pankaj Garg32e1b942015-06-03 18:13:24 -0700270 color = getSiteIconColor(tab.getUrl());
271 if (color != 0) {
272 setStatusAndNavigationBarColor(mUiController.getActivity(),
273 adjustColor(color, 1, 1, 0.7f));
274 } else {
275 setStatusAndNavigationBarColor(mUiController.getActivity(),
276 mDefaultStatusBarColor);
277 }
278 }
Sagar Dhawanca9ecfb2015-08-10 17:27:58 -0700279 if (mFaviconTile != null) {
280 mFaviconTile.replaceFavicon(tab.getFavicon()); // Always set the tab's favicon
281 }
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700282 }
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());
Sagar Dhawane28023a2015-08-13 16:40:25 -0700316 bundle.putCharSequence(SiteSpecificPreferencesFragment.EXTRA_SITE_TITLE,
317 mUiController.getCurrentTab().getTitle());
Pankaj Gargdbdf5aa2015-07-16 15:22:37 -0700318 bundle.putInt(SiteSpecificPreferencesFragment.EXTRA_WEB_REFINER_ADS_INFO, ads);
319 bundle.putInt(SiteSpecificPreferencesFragment.EXTRA_WEB_REFINER_TRACKER_INFO, tracker);
320 bundle.putInt(SiteSpecificPreferencesFragment.EXTRA_WEB_REFINER_MALWARE_INFO, malware);
Pankaj Garg32e1b942015-06-03 18:13:24 -0700321
322 bundle.putParcelable(SiteSpecificPreferencesFragment.EXTRA_SECURITY_CERT,
323 SslCertificate.saveState(wv.getCertificate()));
324
Pankaj Garg96d0ccd2015-07-30 16:49:47 -0700325 Tab.SecurityState securityState = Tab.getWebViewSecurityState(
326 mUiController.getCurrentTab().getWebView());
327 if (securityState == Tab.SecurityState.SECURITY_STATE_MIXED) {
328 bundle.putBoolean(SiteSpecificPreferencesFragment.EXTRA_SECURITY_CERT_MIXED, true);
329 } else if (securityState == Tab.SecurityState.SECURITY_STATE_BAD_CERTIFICATE) {
330 bundle.putBoolean(SiteSpecificPreferencesFragment.EXTRA_SECURITY_CERT_BAD, true);
Pankaj Garg32e1b942015-06-03 18:13:24 -0700331 }
332
Pankaj Garg68faf1c2015-06-26 17:07:37 -0700333 Bitmap favicon = mUiController.getCurrentTopWebView().getFavicon();
Pankaj Garg32e1b942015-06-03 18:13:24 -0700334 if (favicon != null) {
335 ByteArrayOutputStream baos = new ByteArrayOutputStream();
Sagar Dhawanca9ecfb2015-08-10 17:27:58 -0700336 favicon.compress(Bitmap.CompressFormat.PNG, 100, baos);
Pankaj Garg32e1b942015-06-03 18:13:24 -0700337 bundle.putByteArray(SiteSpecificPreferencesFragment.EXTRA_FAVICON,
338 baos.toByteArray());
339 }
340 BrowserPreferencesPage.startPreferenceFragmentExtraForResult(
Pankaj Garg75273bb2015-08-20 11:43:49 -0700341 mUiController.getActivity(), SiteSpecificPreferencesFragment.class.getName(),
342 bundle, Controller.PREFERENCES_PAGE);
Pankaj Garg32e1b942015-06-03 18:13:24 -0700343 }
344
John Reck0f602f32011-07-07 15:38:43 -0700345 @Override
346 public void onClick(View v) {
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700347 Tab currentTab = mUiController.getCurrentTab();
Vivek Sekharae3b1792015-08-03 12:26:41 -0700348 WebView wv = currentTab.getWebView();
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700349 String url = null;
350 if (currentTab != null){
351 url = currentTab.getUrl();
352 }
Enrico Ros1f5a0952014-11-18 20:15:48 -0800353 if (mMore == v) {
354 showMenu(mMore);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700355 } else if (mFaviconTile == v) {
Vivek Sekharae3b1792015-08-03 12:26:41 -0700356 if (urlHasSitePrefs(url) && (wv != null && !wv.isShowingInterstitialPage()) ){
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700357 showSiteSpecificSettings();
358 }
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700359 } else if (mVoiceButton == v) {
360 mUiController.startVoiceRecognizer();
361 } else if (mStopButton == v) {
362 stopOrRefresh();
363 } else if (mClearButton == v) {
364 clearOrClose();
365 mUrlInput.setText("");
366 }
367 }
368
369 private static boolean urlHasSitePrefs(String url) {
370 if (TextUtils.isEmpty(url)) {
371 return false;
372 }
373
374 for (int i = 0; i < noSitePrefs.length; i++) {
375 if (url.startsWith(noSitePrefs[i])) {
376 return false;
377 }
378 }
379 return true;
380 }
381
382 private void stopOrRefresh() {
383 if (mUiController == null) return;
384 if (mTitleBar.isInLoad()) {
385 mUiController.stopLoading();
386 } else {
387 if (mUiController.getCurrentTopWebView() != null) {
388 stopEditingUrl();
389 mUiController.getCurrentTopWebView().reload();
390 }
391 }
392 }
393
394 private void clearOrClose() {
395 if (TextUtils.isEmpty(mUrlInput.getText())) {
396 // close
397 mUrlInput.clearFocus();
398 } else {
399 // clear
400 mUrlInput.setText("");
Enrico Ros1f5a0952014-11-18 20:15:48 -0800401 }
402 }
403
404 void showMenu(View anchor) {
405 Activity activity = mUiController.getActivity();
406 if (mPopupMenu == null) {
407 mPopupMenu = new PopupMenu(getContext(), anchor);
408 mPopupMenu.setOnMenuItemClickListener(this);
409 mPopupMenu.setOnDismissListener(this);
410 if (!activity.onCreateOptionsMenu(mPopupMenu.getMenu())) {
411 mPopupMenu = null;
412 return;
413 }
414 }
415 Menu menu = mPopupMenu.getMenu();
416
417 if (mUiController instanceof Controller) {
418 Controller controller = (Controller) mUiController;
419 if (controller.onPrepareOptionsMenu(menu)) {
420 mOverflowMenuShowing = true;
421 }
422 }
John Reck0f602f32011-07-07 15:38:43 -0700423 }
424
425 @Override
426 public void onFocusChange(View view, boolean hasFocus) {
427 // if losing focus and not in touch mode, leave as is
428 if (hasFocus || view.isInTouchMode() || mUrlInput.needsUpdate()) {
429 setFocusState(hasFocus);
430 }
431 if (hasFocus) {
Kevin Hart97fc28f2015-09-07 15:11:32 +0200432 Engine.warmUpChildProcessAsync(mUiController.getActivity().getApplicationContext());
John Reck0f602f32011-07-07 15:38:43 -0700433 mBaseUi.showTitleBar();
Dany Rybnikovbcd37da2015-04-20 11:43:15 +0300434 if (!BrowserSettings.getInstance().isPowerSaveModeEnabled()) {
435 //Notify about anticipated network activity
436 NetworkServices.hintUpcomingUserActivity();
437 }
John Reck0f602f32011-07-07 15:38:43 -0700438 } else if (!mUrlInput.needsUpdate()) {
439 mUrlInput.dismissDropDown();
440 mUrlInput.hideIME();
441 if (mUrlInput.getText().length() == 0) {
442 Tab currentTab = mUiController.getTabControl().getCurrentTab();
443 if (currentTab != null) {
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700444 setDisplayTitle(currentTab.getTitle(), currentTab.getUrl());
John Reck0f602f32011-07-07 15:38:43 -0700445 }
446 }
John Reck0f602f32011-07-07 15:38:43 -0700447 }
448 mUrlInput.clearNeedsUpdate();
449 }
450
451 protected void setFocusState(boolean focus) {
452 }
453
John Reck0f602f32011-07-07 15:38:43 -0700454 public boolean isEditingUrl() {
455 return mUrlInput.hasFocus();
456 }
457
458 void stopEditingUrl() {
Michael Kolb0b129122012-06-04 16:31:58 -0700459 WebView currentTopWebView = mUiController.getCurrentTopWebView();
460 if (currentTopWebView != null) {
461 currentTopWebView.requestFocus();
462 }
John Reck0f602f32011-07-07 15:38:43 -0700463 }
464
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700465 void setDisplayTitle(String title, String url) {
John Reck0f602f32011-07-07 15:38:43 -0700466 if (!isEditingUrl()) {
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700467 if (!TextUtils.isEmpty(title)) {
468 if (mTrustLevel == SiteTileView.TRUST_TRUSTED) {
469 if (!title.equals(mUrlInput.getText().toString())) {
470 mUrlInput.setText(title, false);
471 }
472 return;
473 }
474 }
475 if (!url.equals(mUrlInput.getText().toString())) {
476 mUrlInput.setText(url, false);
Michael Kolb29aab402012-05-29 17:22:35 -0700477 }
John Reck0f602f32011-07-07 15:38:43 -0700478 }
479 }
480
John Reck0f602f32011-07-07 15:38:43 -0700481 void setIncognitoMode(boolean incognito) {
482 mUrlInput.setIncognitoMode(incognito);
483 }
484
485 void clearCompletions() {
Narayan Kamathf3174a52011-11-17 14:43:32 +0000486 mUrlInput.dismissDropDown();
John Reck0f602f32011-07-07 15:38:43 -0700487 }
488
489 // UrlInputListener implementation
490
491 /**
492 * callback from suggestion dropdown
493 * user selected a suggestion
494 */
495 @Override
496 public void onAction(String text, String extra, String source) {
Michael Kolb0b129122012-06-04 16:31:58 -0700497 stopEditingUrl();
John Reck0f602f32011-07-07 15:38:43 -0700498 if (UrlInputView.TYPED.equals(source)) {
kaiyizc4ada322013-07-30 09:58:07 +0800499 String url = null;
Panos Thomas4bdb5252014-11-13 16:20:11 -0800500 boolean wap2estore = BrowserConfig.getInstance(getContext())
501 .hasFeature(BrowserConfig.Feature.WAP2ESTORE);
Vivek Sekhar5e631472014-03-31 23:59:10 -0700502 if ((wap2estore && isEstoreTypeUrl(text)) || isRtspTypeUrl(text)
503 || isMakeCallTypeUrl(text)) {
kaiyizc4ada322013-07-30 09:58:07 +0800504 url = text;
505 } else {
506 url = UrlUtils.smartUrlFilter(text, false);
507 }
508
John Reck0f602f32011-07-07 15:38:43 -0700509 Tab t = mBaseUi.getActiveTab();
510 // Only shortcut javascript URIs for now, as there is special
511 // logic in UrlHandler for other schemas
Axesh R. Ajmera6fc73692015-08-11 16:32:10 -0700512 if (url != null && t != null && url.startsWith("javascript:")) {
John Reck0f602f32011-07-07 15:38:43 -0700513 mUiController.loadUrl(t, url);
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700514 setDisplayTitle(null, text);
John Reck0f602f32011-07-07 15:38:43 -0700515 return;
516 }
kaiyizc4ada322013-07-30 09:58:07 +0800517
518 // add for carrier wap2estore feature
519 if (url != null && t != null && wap2estore && isEstoreTypeUrl(url)) {
Vivek Sekharb54614f2014-05-01 19:03:37 -0700520 if (handleEstoreTypeUrl(url)) {
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700521 setDisplayTitle(null, text);
Vivek Sekharb54614f2014-05-01 19:03:37 -0700522 return;
523 }
kaiyizc4ada322013-07-30 09:58:07 +0800524 }
kaiyiz950eca22013-08-08 11:01:28 +0800525 // add for rtsp scheme feature
526 if (url != null && t != null && isRtspTypeUrl(url)) {
527 if (handleRtspTypeUrl(url)) {
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700528 setDisplayTitle(null, text);
kaiyiz950eca22013-08-08 11:01:28 +0800529 return;
530 }
531 }
Vivek Sekhar5e631472014-03-31 23:59:10 -0700532 // add for "wtai://wp/mc;" scheme feature
533 if (url != null && t != null && isMakeCallTypeUrl(url)) {
534 if (handleMakeCallTypeUrl(url)) {
535 return;
536 }
537 }
John Reck0f602f32011-07-07 15:38:43 -0700538 }
539 Intent i = new Intent();
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700540 String action = Intent.ACTION_SEARCH;
John Reck0f602f32011-07-07 15:38:43 -0700541 i.setAction(action);
542 i.putExtra(SearchManager.QUERY, text);
543 if (extra != null) {
544 i.putExtra(SearchManager.EXTRA_DATA_KEY, extra);
545 }
546 if (source != null) {
547 Bundle appData = new Bundle();
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800548 appData.putString("source", source);
549 i.putExtra("source", appData);
John Reck0f602f32011-07-07 15:38:43 -0700550 }
551 mUiController.handleNewIntent(i);
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700552 setDisplayTitle(null, text);
John Reck0f602f32011-07-07 15:38:43 -0700553 }
554
Vivek Sekhar5e631472014-03-31 23:59:10 -0700555 private boolean isMakeCallTypeUrl(String url) {
556 String utf8Url = null;
557 try {
558 utf8Url = new String(url.getBytes("UTF-8"), "UTF-8");
559 } catch (UnsupportedEncodingException e) {
560 Log.e(TAG, "err " + e);
561 }
562 if (utf8Url != null && utf8Url.startsWith(UrlHandler.SCHEME_WTAI_MC)) {
563 return true;
564 }
565 return false;
566 }
567
568 private boolean handleMakeCallTypeUrl(String url) {
569 // wtai://wp/mc;number
570 // number=string(phone-number)
571 if (url.startsWith(UrlHandler.SCHEME_WTAI_MC)) {
572 Intent intent = new Intent(Intent.ACTION_VIEW,
573 Uri.parse(WebView.SCHEME_TEL +
574 url.substring(UrlHandler.SCHEME_WTAI_MC.length())));
575 getContext().startActivity(intent);
576 // before leaving BrowserActivity, close the empty child tab.
577 // If a new tab is created through JavaScript open to load this
578 // url, we would like to close it as we will load this url in a
579 // different Activity.
580 Tab current = mUiController.getCurrentTab();
581 if (current != null
582 && current.getWebView().copyBackForwardList().getSize() == 0) {
583 mUiController.closeCurrentTab();
584 }
585 return true;
586 }
587 return false;
588 }
589
kaiyizc4ada322013-07-30 09:58:07 +0800590 private boolean isEstoreTypeUrl(String url) {
Vivek Sekharb54614f2014-05-01 19:03:37 -0700591 if (url != null && url.startsWith("estore:")) {
kaiyizc4ada322013-07-30 09:58:07 +0800592 return true;
593 }
594 return false;
595 }
596
Vivek Sekharb54614f2014-05-01 19:03:37 -0700597 private boolean handleEstoreTypeUrl(String url) {
598 if (url.getBytes().length > 256) {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800599 Toast.makeText(getContext(), R.string.estore_url_warning, Toast.LENGTH_LONG).show();
Vivek Sekharb54614f2014-05-01 19:03:37 -0700600 return false;
kaiyizc4ada322013-07-30 09:58:07 +0800601 }
Vivek Sekharb54614f2014-05-01 19:03:37 -0700602
603 Intent intent;
604 // perform generic parsing of the URI to turn it into an Intent.
605 try {
606 intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
607 } catch (URISyntaxException ex) {
608 Log.w("Browser", "Bad URI " + url + ": " + ex.getMessage());
609 return false;
610 }
611
kaiyizc4ada322013-07-30 09:58:07 +0800612 try {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800613 getContext().startActivity(intent);
kaiyizc4ada322013-07-30 09:58:07 +0800614 } catch (ActivityNotFoundException ex) {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800615 String downloadUrl = getContext().getResources().getString(R.string.estore_homepage);
kaiyizc4ada322013-07-30 09:58:07 +0800616 mUiController.loadUrl(mBaseUi.getActiveTab(), downloadUrl);
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800617 Toast.makeText(getContext(), R.string.download_estore_app, Toast.LENGTH_LONG).show();
kaiyizc4ada322013-07-30 09:58:07 +0800618 }
Vivek Sekharb54614f2014-05-01 19:03:37 -0700619
620 return true;
kaiyizc4ada322013-07-30 09:58:07 +0800621 }
622
kaiyiz950eca22013-08-08 11:01:28 +0800623 private boolean isRtspTypeUrl(String url) {
624 String utf8Url = null;
625 try {
626 utf8Url = new String(url.getBytes("UTF-8"), "UTF-8");
627 } catch (UnsupportedEncodingException e) {
628 Log.e(TAG, "err " + e);
629 }
630 if (utf8Url != null && utf8Url.startsWith("rtsp://")) {
631 return true;
632 }
633 return false;
634 }
635
636 private boolean handleRtspTypeUrl(String url) {
637 Intent intent;
638 // perform generic parsing of the URI to turn it into an Intent.
639 try {
640 intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
641 } catch (URISyntaxException ex) {
642 Log.w("Browser", "Bad URI " + url + ": " + ex.getMessage());
643 return false;
644 }
645
646 try {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800647 getContext().startActivity(intent);
kaiyiz950eca22013-08-08 11:01:28 +0800648 } catch (ActivityNotFoundException ex) {
649 Log.w("Browser", "No resolveActivity " + url);
650 return false;
651 }
652 return true;
653 }
654
John Reck0f602f32011-07-07 15:38:43 -0700655 @Override
656 public void onDismiss() {
657 final Tab currentTab = mBaseUi.getActiveTab();
658 mBaseUi.hideTitleBar();
659 post(new Runnable() {
660 public void run() {
661 clearFocus();
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700662 if (currentTab != null) {
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700663 setDisplayTitle(currentTab.getTitle(), currentTab.getUrl());
John Reck0f602f32011-07-07 15:38:43 -0700664 }
665 }
666 });
667 }
668
669 /**
670 * callback from the suggestion dropdown
671 * copy text to input field and stay in edit mode
672 */
673 @Override
674 public void onCopySuggestion(String text) {
675 mUrlInput.setText(text, true);
John Reck0f602f32011-07-07 15:38:43 -0700676 }
677
678 public void setCurrentUrlIsBookmark(boolean isBookmark) {
679 }
680
681 @Override
682 public boolean dispatchKeyEventPreIme(KeyEvent evt) {
683 if (evt.getKeyCode() == KeyEvent.KEYCODE_BACK) {
Sagar Dhawan5a5d01f2015-07-30 17:16:21 -0700684 if (mUiController.getCurrentTab() != null &&
685 mUiController.getCurrentTab().isKeyboardShowing()){
686 stopEditingUrl();
687 return true;
688 }
John Reck0f602f32011-07-07 15:38:43 -0700689 // catch back key in order to do slightly more cleanup than usual
Michael Kolb0b129122012-06-04 16:31:58 -0700690 stopEditingUrl();
John Reck0f602f32011-07-07 15:38:43 -0700691 }
692 return super.dispatchKeyEventPreIme(evt);
693 }
694
John Reck0f602f32011-07-07 15:38:43 -0700695 /**
696 * called from the Ui when the user wants to edit
697 * @param clearInput clear the input field
698 */
Michael Kolb1f9b3562012-04-24 14:38:34 -0700699 void startEditingUrl(boolean clearInput, boolean forceIME) {
John Reck0f602f32011-07-07 15:38:43 -0700700 // editing takes preference of progress
701 setVisibility(View.VISIBLE);
John Reck0f602f32011-07-07 15:38:43 -0700702 if (clearInput) {
703 mUrlInput.setText("");
John Reck0f602f32011-07-07 15:38:43 -0700704 }
Tarun Nainaniaa586822015-08-20 14:59:33 -0700705 if (!mUrlInput.hasFocus()) {
706 mUrlInput.requestFocus();
707 }
Michael Kolb1f9b3562012-04-24 14:38:34 -0700708 if (forceIME) {
Michael Kolb4bb6fcb2012-04-13 14:25:27 -0700709 mUrlInput.showIME();
710 }
John Reck0f602f32011-07-07 15:38:43 -0700711 }
712
713 public void onProgressStarted() {
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700714 mFaviconTile.setBadgeBlockedObjectsCount(0);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700715 mFaviconTile.setTrustLevel(SiteTileView.TRUST_UNKNOWN);
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700716 mFaviconTile.setBadgeHasCertIssues(false);
Pankaj Garg96d0ccd2015-07-30 16:49:47 -0700717 setSecurityState(Tab.SecurityState.SECURITY_STATE_NOT_SECURE);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700718 mHandler.removeMessages(WEBREFINER_COUNTER_MSG);
719 mHandler.sendEmptyMessageDelayed(WEBREFINER_COUNTER_MSG,
720 WEBREFINER_COUNTER_MSG_DELAY);
721 mStopButton.setImageResource(R.drawable.ic_action_stop);
722 mStopButton.setContentDescription(getResources().
723 getString(R.string.accessibility_button_stop));
John Reck0f602f32011-07-07 15:38:43 -0700724 }
725
726 public void onProgressStopped() {
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700727 if (!isEditingUrl()) {
728 mFaviconTile.setVisibility(View.VISIBLE);
729 }
730 mStopButton.setImageResource(R.drawable.ic_action_reload);
731 mStopButton.setContentDescription(getResources().
732 getString(R.string.accessibility_button_refresh));
John Reck0f602f32011-07-07 15:38:43 -0700733 }
734
John Reck419f6b42011-08-16 16:10:51 -0700735 public void onTabDataChanged(Tab tab) {
736 }
737
Michael Kolb0b129122012-06-04 16:31:58 -0700738 public void onVoiceResult(String s) {
739 startEditingUrl(true, true);
740 onCopySuggestion(s);
741 }
742
Narayan Kamathf3174a52011-11-17 14:43:32 +0000743 @Override
744 public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
745
746 @Override
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700747 public void onTextChanged(CharSequence s, int start, int before, int count) { }
Narayan Kamathf3174a52011-11-17 14:43:32 +0000748
749 @Override
750 public void afterTextChanged(Editable s) { }
Michael Kolb0b129122012-06-04 16:31:58 -0700751
Enrico Ros1f5a0952014-11-18 20:15:48 -0800752 @Override
753 public void onStateChanged(int state) {
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700754 mVoiceButton.setVisibility(View.GONE);
Sagar Dhawan84ef4442015-07-29 12:08:10 -0700755 mClearButton.setVisibility(View.GONE);
Enrico Ros1f5a0952014-11-18 20:15:48 -0800756 switch(state) {
757 case STATE_NORMAL:
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700758 mFaviconTile.setVisibility(View.VISIBLE);
Sagar Dhawanaff56c92015-07-13 15:57:11 -0700759 mMore.setVisibility(View.VISIBLE);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700760 if (mUiController != null) {
761 Tab currentTab = mUiController.getCurrentTab();
762 if (currentTab != null){
763 if (TextUtils.isEmpty(currentTab.getUrl())) {
764 mFaviconTile.setVisibility(View.GONE);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700765 }
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700766 setDisplayTitle(currentTab.getTitle(), currentTab.getUrl());
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700767 }
768 mUiController.setWindowDimming(0.0f);
769 }
770
Enrico Ros1f5a0952014-11-18 20:15:48 -0800771 break;
772 case STATE_HIGHLIGHTED:
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700773 mFaviconTile.setVisibility(View.GONE);
Sagar Dhawan84ef4442015-07-29 12:08:10 -0700774 mClearButton.setVisibility(View.VISIBLE);
Enrico Ros1f5a0952014-11-18 20:15:48 -0800775 mMore.setVisibility(View.GONE);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700776 if (mUiController != null) {
777 mUiController.setWindowDimming(0.75f);
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700778 if (mTrustLevel == SiteTileView.TRUST_TRUSTED) {
779 Tab currentTab = mUiController.getCurrentTab();
780 if (currentTab != null) {
781 mUrlInput.setText(currentTab.getUrl(), false);
782 mUrlInput.selectAll();
783 }
784 }
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700785 }
Enrico Ros1f5a0952014-11-18 20:15:48 -0800786 break;
787 case STATE_EDITED:
Sagar Dhawan84ef4442015-07-29 12:08:10 -0700788 if (TextUtils.isEmpty(mUrlInput.getText()) &&
789 mUiController != null &&
790 mUiController.supportsVoice()) {
791 mVoiceButton.setVisibility(View.VISIBLE);
792 }
793 else {
794 mClearButton.setVisibility(View.VISIBLE);
795 }
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700796 mFaviconTile.setVisibility(View.GONE);
Enrico Ros1f5a0952014-11-18 20:15:48 -0800797 mMore.setVisibility(View.GONE);
798 break;
799 }
800 }
801
802 public boolean isMenuShowing() {
803 return mOverflowMenuShowing;
804 }
805
806
807 @Override
808 public void onDismiss(PopupMenu popupMenu) {
809 if (popupMenu == mPopupMenu) {
810 onMenuHidden();
811 }
812 }
813
814 private void onMenuHidden() {
815 mOverflowMenuShowing = false;
Enrico Ros1f5a0952014-11-18 20:15:48 -0800816 }
817
818
819 @Override
820 public boolean onMenuItemClick(MenuItem item) {
821 return mUiController.onOptionsItemSelected(item);
822 }
John Reck0f602f32011-07-07 15:38:43 -0700823}