blob: 248f57f24fec81fcf51d33ed8a4fb9e7920c2259 [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;
jrizzoli7324f6e2016-05-01 22:31:14 +020043import android.view.MotionEvent;
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;
Pankaj Garg32e1b942015-06-03 18:13:24 -070062import org.codeaurora.swe.WebRefiner;
Bijan Amirzada9b1e9882014-02-26 17:15:46 -080063import org.codeaurora.swe.WebView;
Pankaj Garg32e1b942015-06-03 18:13:24 -070064import org.codeaurora.swe.util.ColorUtils;
Bijan Amirzada9b1e9882014-02-26 17:15:46 -080065
John Reck42229bc2011-08-19 13:26:43 -070066public class NavigationBarBase extends LinearLayout implements
67 OnClickListener, UrlInputListener, OnFocusChangeListener,
Enrico Ros1f5a0952014-11-18 20:15:48 -080068 TextWatcher, UrlInputView.StateListener,
69 PopupMenu.OnMenuItemClickListener, PopupMenu.OnDismissListener {
John Reck0f602f32011-07-07 15:38:43 -070070
kaiyizc4ada322013-07-30 09:58:07 +080071 private final static String TAG = "NavigationBarBase";
72
John Reck0f602f32011-07-07 15:38:43 -070073 protected BaseUi mBaseUi;
74 protected TitleBar mTitleBar;
75 protected UiController mUiController;
76 protected UrlInputView mUrlInput;
Pankaj Garg66f8cef2015-07-07 17:29:03 -070077 protected ImageView mStopButton;
John Reck0f602f32011-07-07 15:38:43 -070078
Pankaj Garg66f8cef2015-07-07 17:29:03 -070079 private SiteTileView mFaviconTile;
jrizzolia62318b2015-09-08 21:44:50 +020080 private View mSeparator;
Pankaj Garg66f8cef2015-07-07 17:29:03 -070081 private View mVoiceButton;
82 private ImageView mClearButton;
Enrico Ros1f5a0952014-11-18 20:15:48 -080083 private View mMore;
84 private PopupMenu mPopupMenu;
85 private boolean mOverflowMenuShowing;
Axesh R. Ajmera2e241242014-05-19 15:53:38 -070086
Pankaj Garg66f8cef2015-07-07 17:29:03 -070087 private static Bitmap mDefaultFavicon;
88
Pankaj Garg32e1b942015-06-03 18:13:24 -070089 private int mStatusBarColor;
90 private static int mDefaultStatusBarColor = -1;
91
Pankaj Garg66f8cef2015-07-07 17:29:03 -070092 private static final int WEBREFINER_COUNTER_MSG = 4242;
93 private static final int WEBREFINER_COUNTER_MSG_DELAY = 3000;
94 private Handler mHandler;
95
Pankaj Garg8d2e98f2015-08-07 10:01:49 -070096 protected int mTrustLevel = SiteTileView.TRUST_UNKNOWN;
97
Pankaj Garg66f8cef2015-07-07 17:29:03 -070098 private static final String noSitePrefs[] = {
Axesh R. Ajmera6fc73692015-08-11 16:32:10 -070099 "chrome://",
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700100 "about:",
101 "content:",
102 };
103
John Reck0f602f32011-07-07 15:38:43 -0700104 public NavigationBarBase(Context context) {
105 super(context);
106 }
107
108 public NavigationBarBase(Context context, AttributeSet attrs) {
109 super(context, attrs);
110 }
111
112 public NavigationBarBase(Context context, AttributeSet attrs, int defStyle) {
113 super(context, attrs, defStyle);
114 }
115
116 @Override
117 protected void onFinishInflate() {
118 super.onFinishInflate();
John Reck0f602f32011-07-07 15:38:43 -0700119 mUrlInput = (UrlInputView) findViewById(R.id.url);
120 mUrlInput.setUrlInputListener(this);
John Reck0f602f32011-07-07 15:38:43 -0700121 mUrlInput.setOnFocusChangeListener(this);
122 mUrlInput.setSelectAllOnFocus(true);
Narayan Kamathf3174a52011-11-17 14:43:32 +0000123 mUrlInput.addTextChangedListener(this);
Enrico Ros1f5a0952014-11-18 20:15:48 -0800124 mMore = findViewById(R.id.more_browser_settings);
125 mMore.setOnClickListener(this);
jrizzolia62318b2015-09-08 21:44:50 +0200126 mSeparator = findViewById(R.id.separator);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700127 mFaviconTile = (SiteTileView) findViewById(R.id.favicon_view);
128 mFaviconTile.setOnClickListener(this);
129 mVoiceButton = findViewById(R.id.voice);
130 mVoiceButton.setOnClickListener(this);
131 mClearButton = (ImageView) findViewById(R.id.clear);
132 mClearButton.setOnClickListener(this);
133 mStopButton = (ImageView) findViewById(R.id.stop);
134 mStopButton.setOnClickListener(this);
135
136 mDefaultFavicon = BitmapFactory.decodeResource(getResources(),
137 R.drawable.ic_deco_favicon_normal);
138
jrizzoli7324f6e2016-05-01 22:31:14 +0200139 mMore.setOnTouchListener(new OnTouchListener() {
140 @Override
141 public boolean onTouch(View v, MotionEvent event) {
142 if (event.getAction() == MotionEvent.ACTION_DOWN) {
143 showMenu(mMore);
144 }
145 return true;
146 }
147 });
148
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700149 mHandler = new Handler() {
150 @Override
151 public void handleMessage(Message m) {
152 switch (m.what) {
153 case WEBREFINER_COUNTER_MSG:
154 WebView wv = mUiController.getCurrentTopWebView();
155 if (wv != null && WebRefiner.isInitialized()) {
156 int count = WebRefiner.getInstance().getBlockedURLCount(wv);
157 if (count > 0) {
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700158 mFaviconTile.setBadgeBlockedObjectsCount(count);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700159 }
160 }
161 mHandler.sendEmptyMessageDelayed(WEBREFINER_COUNTER_MSG,
162 WEBREFINER_COUNTER_MSG_DELAY);
163 break;
164 }
165 }
166 };
John Reck0f602f32011-07-07 15:38:43 -0700167 }
168
169 public void setTitleBar(TitleBar titleBar) {
170 mTitleBar = titleBar;
171 mBaseUi = mTitleBar.getUi();
172 mUiController = mTitleBar.getUiController();
Michael Kolbb2e91fd2011-07-14 13:47:29 -0700173 mUrlInput.setController(mUiController);
John Reck0f602f32011-07-07 15:38:43 -0700174 }
175
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700176 public void setSecurityState(Tab.SecurityState securityState) {
Pankaj Garg96d0ccd2015-07-30 16:49:47 -0700177 switch (securityState) {
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700178 case SECURITY_STATE_SECURE:
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700179 mTrustLevel = SiteTileView.TRUST_TRUSTED;
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700180 mFaviconTile.setBadgeHasCertIssues(false);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700181 break;
182 case SECURITY_STATE_MIXED:
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700183 mTrustLevel = SiteTileView.TRUST_UNTRUSTED;
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700184 mFaviconTile.setBadgeHasCertIssues(true);
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700185 mTitleBar.showTopControls(false);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700186 break;
187 case SECURITY_STATE_BAD_CERTIFICATE:
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700188 mTrustLevel = SiteTileView.TRUST_AVOID;
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700189 mFaviconTile.setBadgeHasCertIssues(true);
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700190 mTitleBar.showTopControls(false);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700191 break;
192 case SECURITY_STATE_NOT_SECURE:
193 default:
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700194 mTrustLevel = SiteTileView.TRUST_UNKNOWN;
John Reck0f602f32011-07-07 15:38:43 -0700195 }
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700196 mFaviconTile.setTrustLevel(mTrustLevel);
197 }
198
199 public int getTrustLevel() {
200 return mTrustLevel;
John Reck0f602f32011-07-07 15:38:43 -0700201 }
202
Pankaj Garg32e1b942015-06-03 18:13:24 -0700203 public static int adjustColor(int color, float hueMultiplier,
204 float saturationMultiplier, float valueMultiplier) {
205 float[] hsv = new float[3];
206 Color.colorToHSV(color, hsv);
207 hsv[0] *= hueMultiplier;
208 hsv[1] *= saturationMultiplier;
209 hsv[2] *= valueMultiplier;
210 return Color.HSVToColor(Color.alpha(color), hsv);
211 }
212
213 public static void setStatusAndNavigationBarColor(final Activity activity, int color) {
Sagar Dhawaneecefa32015-09-25 12:02:34 -0700214 // The flag that allows coloring is disabled in PowerSaveMode, no point in trying to color.
215 if (BrowserSettings.getInstance().isPowerSaveModeEnabled())
216 return;
jrizzolibe2afc52015-10-28 18:43:00 +0100217 // Disable colored statusbar if user asked so
218 if (! BrowserSettings.getInstance().isColoredSBEnabled())
219 return;
Pankaj Garg32e1b942015-06-03 18:13:24 -0700220 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
221 int currentColor = activity.getWindow().getStatusBarColor();
222 Integer from = currentColor;
223 Integer to = color;
224 ValueAnimator animator = ValueAnimator.ofObject(new ArgbEvaluator(), from, to);
225
226 if (mDefaultStatusBarColor == -1) {
227 mDefaultStatusBarColor = activity.getWindow().getStatusBarColor();
228 }
229
230 animator.addUpdateListener(
231 new ValueAnimator.AnimatorUpdateListener() {
232 @Override
233 public void onAnimationUpdate(ValueAnimator animation) {
234 Integer value = (Integer) animation.getAnimatedValue();
235 activity.getWindow().setStatusBarColor(value.intValue());
236 //activity.getWindow().setNavigationBarColor(value.intValue());
237 }
238 }
239 );
240 animator.start();
241 }
242 }
243
244 private void updateSiteIconColor(String urlString, int color) {
245 try {
246 URL url = new URL(urlString);
247 String host = url.getHost();
248 SharedPreferences prefs = BrowserSettings.getInstance().getPreferences();
249 int currentColor = prefs.getInt(host + ":color", 0);
250 if (currentColor != color) {
251 SharedPreferences.Editor editor = prefs.edit();
252 editor.remove(host + ":color");
253 editor.putInt(host + ":color", color);
254 editor.commit();
255 }
256 } catch (MalformedURLException e) {
257 }
258 }
259
260 public static int getSiteIconColor(String urlString) {
261 try {
262 URL url = new URL(urlString);
263 String host = url.getHost();
264 SharedPreferences prefs = BrowserSettings.getInstance().getPreferences();
265 return prefs.getInt(host + ":color", 0);
266 } catch (MalformedURLException e) {
267 return 0;
268 }
269 }
270
271 public static int getDefaultStatusBarColor() {
272 return mDefaultStatusBarColor;
273 }
274
Sagar Dhawanca9ecfb2015-08-10 17:27:58 -0700275 // Sets the favicon for the given tab if it's in the foreground
276 // If the tab doesn't have a favicon, it sets the default favicon
277 public void showCurrentFavicon(Tab tab) {
278 int color;
279 if (tab == null) { return; }
Pankaj Garg32e1b942015-06-03 18:13:24 -0700280
Sagar Dhawanca9ecfb2015-08-10 17:27:58 -0700281 if (tab.inForeground()) {
Pankaj Garg32e1b942015-06-03 18:13:24 -0700282 if (tab.hasFavicon()) {
Sagar Dhawanca9ecfb2015-08-10 17:27:58 -0700283 color = ColorUtils.getDominantColorForBitmap(tab.getFavicon());
Pankaj Garg32e1b942015-06-03 18:13:24 -0700284 updateSiteIconColor(tab.getUrl(), color);
285 setStatusAndNavigationBarColor(mUiController.getActivity(),
286 adjustColor(color, 1, 1, 0.7f));
Sagar Dhawanca9ecfb2015-08-10 17:27:58 -0700287
288 } else {
Pankaj Garg32e1b942015-06-03 18:13:24 -0700289 color = getSiteIconColor(tab.getUrl());
290 if (color != 0) {
291 setStatusAndNavigationBarColor(mUiController.getActivity(),
292 adjustColor(color, 1, 1, 0.7f));
293 } else {
294 setStatusAndNavigationBarColor(mUiController.getActivity(),
295 mDefaultStatusBarColor);
296 }
297 }
Sagar Dhawanca9ecfb2015-08-10 17:27:58 -0700298 if (mFaviconTile != null) {
299 mFaviconTile.replaceFavicon(tab.getFavicon()); // Always set the tab's favicon
300 }
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700301 }
John Reck0f602f32011-07-07 15:38:43 -0700302 }
303
Pankaj Garg32e1b942015-06-03 18:13:24 -0700304 protected void showSiteSpecificSettings() {
305 WebView wv = mUiController.getCurrentTopWebView();
Pankaj Gargdbdf5aa2015-07-16 15:22:37 -0700306 int ads = 0;
307 int tracker = 0;
308 int malware = 0;
Pankaj Garg32e1b942015-06-03 18:13:24 -0700309
Pankaj Gargdbdf5aa2015-07-16 15:22:37 -0700310 WebRefiner webRefiner = WebRefiner.getInstance();
311 if (wv != null && webRefiner != null) {
312 WebRefiner.PageInfo pageInfo = webRefiner.getPageInfo(wv);
313 if (pageInfo != null) {
314 for (WebRefiner.MatchedURLInfo urlInfo : pageInfo.mMatchedURLInfoList) {
Pankaj Gargee992032015-07-24 15:59:36 -0700315 if (urlInfo.mActionTaken == WebRefiner.MatchedURLInfo.ACTION_BLOCKED) {
316 switch (urlInfo.mMatchedFilterCategory) {
317 case WebRefiner.RuleSet.CATEGORY_ADS:
318 ads++;
319 break;
320 case WebRefiner.RuleSet.CATEGORY_TRACKERS:
321 tracker++;
322 break;
323 case WebRefiner.RuleSet.CATEGORY_MALWARE_DOMAINS:
324 malware++;
325 break;
326 }
Pankaj Gargdbdf5aa2015-07-16 15:22:37 -0700327 }
328 }
329 }
Pankaj Garg32e1b942015-06-03 18:13:24 -0700330 }
331
332 Bundle bundle = new Bundle();
333 bundle.putCharSequence(SiteSpecificPreferencesFragment.EXTRA_SITE,
334 mUiController.getCurrentTab().getUrl());
Sagar Dhawane28023a2015-08-13 16:40:25 -0700335 bundle.putCharSequence(SiteSpecificPreferencesFragment.EXTRA_SITE_TITLE,
336 mUiController.getCurrentTab().getTitle());
Pankaj Gargdbdf5aa2015-07-16 15:22:37 -0700337 bundle.putInt(SiteSpecificPreferencesFragment.EXTRA_WEB_REFINER_ADS_INFO, ads);
338 bundle.putInt(SiteSpecificPreferencesFragment.EXTRA_WEB_REFINER_TRACKER_INFO, tracker);
339 bundle.putInt(SiteSpecificPreferencesFragment.EXTRA_WEB_REFINER_MALWARE_INFO, malware);
Pankaj Garg32e1b942015-06-03 18:13:24 -0700340
341 bundle.putParcelable(SiteSpecificPreferencesFragment.EXTRA_SECURITY_CERT,
342 SslCertificate.saveState(wv.getCertificate()));
343
Pankaj Garg96d0ccd2015-07-30 16:49:47 -0700344 Tab.SecurityState securityState = Tab.getWebViewSecurityState(
345 mUiController.getCurrentTab().getWebView());
346 if (securityState == Tab.SecurityState.SECURITY_STATE_MIXED) {
347 bundle.putBoolean(SiteSpecificPreferencesFragment.EXTRA_SECURITY_CERT_MIXED, true);
348 } else if (securityState == Tab.SecurityState.SECURITY_STATE_BAD_CERTIFICATE) {
349 bundle.putBoolean(SiteSpecificPreferencesFragment.EXTRA_SECURITY_CERT_BAD, true);
Pankaj Garg32e1b942015-06-03 18:13:24 -0700350 }
351
Pankaj Garg68faf1c2015-06-26 17:07:37 -0700352 Bitmap favicon = mUiController.getCurrentTopWebView().getFavicon();
Pankaj Garg32e1b942015-06-03 18:13:24 -0700353 if (favicon != null) {
354 ByteArrayOutputStream baos = new ByteArrayOutputStream();
Sagar Dhawanca9ecfb2015-08-10 17:27:58 -0700355 favicon.compress(Bitmap.CompressFormat.PNG, 100, baos);
Pankaj Garg32e1b942015-06-03 18:13:24 -0700356 bundle.putByteArray(SiteSpecificPreferencesFragment.EXTRA_FAVICON,
357 baos.toByteArray());
358 }
359 BrowserPreferencesPage.startPreferenceFragmentExtraForResult(
Pankaj Garg75273bb2015-08-20 11:43:49 -0700360 mUiController.getActivity(), SiteSpecificPreferencesFragment.class.getName(),
361 bundle, Controller.PREFERENCES_PAGE);
Pankaj Garg32e1b942015-06-03 18:13:24 -0700362 }
363
John Reck0f602f32011-07-07 15:38:43 -0700364 @Override
365 public void onClick(View v) {
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700366 Tab currentTab = mUiController.getCurrentTab();
367 String url = null;
Sagar Dhawan20b1deb2015-10-12 11:13:18 -0700368 WebView wv = null;
369 if (currentTab != null) {
370 wv = currentTab.getWebView();
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700371 url = currentTab.getUrl();
372 }
Sagar Dhawan20b1deb2015-10-12 11:13:18 -0700373
jrizzoli7324f6e2016-05-01 22:31:14 +0200374 if (mFaviconTile == v) {
375 if (urlHasSitePrefs(url) && (wv != null && !wv.isShowingInterstitialPage())) {
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700376 showSiteSpecificSettings();
377 }
jrizzoli7324f6e2016-05-01 22:31:14 +0200378 } else if (mMore == v) {
379 showMenu(mMore);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700380 } else if (mVoiceButton == v) {
381 mUiController.startVoiceRecognizer();
382 } else if (mStopButton == v) {
383 stopOrRefresh();
384 } else if (mClearButton == v) {
385 clearOrClose();
386 mUrlInput.setText("");
387 }
388 }
389
390 private static boolean urlHasSitePrefs(String url) {
391 if (TextUtils.isEmpty(url)) {
392 return false;
393 }
394
395 for (int i = 0; i < noSitePrefs.length; i++) {
396 if (url.startsWith(noSitePrefs[i])) {
397 return false;
398 }
399 }
400 return true;
401 }
402
403 private void stopOrRefresh() {
404 if (mUiController == null) return;
405 if (mTitleBar.isInLoad()) {
406 mUiController.stopLoading();
407 } else {
408 if (mUiController.getCurrentTopWebView() != null) {
409 stopEditingUrl();
410 mUiController.getCurrentTopWebView().reload();
411 }
412 }
413 }
414
415 private void clearOrClose() {
416 if (TextUtils.isEmpty(mUrlInput.getText())) {
417 // close
418 mUrlInput.clearFocus();
419 } else {
420 // clear
421 mUrlInput.setText("");
Enrico Ros1f5a0952014-11-18 20:15:48 -0800422 }
423 }
424
425 void showMenu(View anchor) {
426 Activity activity = mUiController.getActivity();
427 if (mPopupMenu == null) {
428 mPopupMenu = new PopupMenu(getContext(), anchor);
429 mPopupMenu.setOnMenuItemClickListener(this);
430 mPopupMenu.setOnDismissListener(this);
431 if (!activity.onCreateOptionsMenu(mPopupMenu.getMenu())) {
432 mPopupMenu = null;
433 return;
434 }
435 }
436 Menu menu = mPopupMenu.getMenu();
437
438 if (mUiController instanceof Controller) {
439 Controller controller = (Controller) mUiController;
440 if (controller.onPrepareOptionsMenu(menu)) {
441 mOverflowMenuShowing = true;
442 }
443 }
John Reck0f602f32011-07-07 15:38:43 -0700444 }
445
446 @Override
447 public void onFocusChange(View view, boolean hasFocus) {
448 // if losing focus and not in touch mode, leave as is
449 if (hasFocus || view.isInTouchMode() || mUrlInput.needsUpdate()) {
450 setFocusState(hasFocus);
451 }
452 if (hasFocus) {
453 mBaseUi.showTitleBar();
Dany Rybnikovbcd37da2015-04-20 11:43:15 +0300454 if (!BrowserSettings.getInstance().isPowerSaveModeEnabled()) {
455 //Notify about anticipated network activity
456 NetworkServices.hintUpcomingUserActivity();
457 }
John Reck0f602f32011-07-07 15:38:43 -0700458 } else if (!mUrlInput.needsUpdate()) {
459 mUrlInput.dismissDropDown();
460 mUrlInput.hideIME();
461 if (mUrlInput.getText().length() == 0) {
462 Tab currentTab = mUiController.getTabControl().getCurrentTab();
463 if (currentTab != null) {
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700464 setDisplayTitle(currentTab.getTitle(), currentTab.getUrl());
John Reck0f602f32011-07-07 15:38:43 -0700465 }
466 }
John Reck0f602f32011-07-07 15:38:43 -0700467 }
468 mUrlInput.clearNeedsUpdate();
469 }
470
471 protected void setFocusState(boolean focus) {
472 }
473
John Reck0f602f32011-07-07 15:38:43 -0700474 public boolean isEditingUrl() {
475 return mUrlInput.hasFocus();
476 }
477
478 void stopEditingUrl() {
Michael Kolb0b129122012-06-04 16:31:58 -0700479 WebView currentTopWebView = mUiController.getCurrentTopWebView();
480 if (currentTopWebView != null) {
481 currentTopWebView.requestFocus();
482 }
John Reck0f602f32011-07-07 15:38:43 -0700483 }
484
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700485 void setDisplayTitle(String title, String url) {
John Reck0f602f32011-07-07 15:38:43 -0700486 if (!isEditingUrl()) {
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700487 if (!TextUtils.isEmpty(title)) {
488 if (mTrustLevel == SiteTileView.TRUST_TRUSTED) {
489 if (!title.equals(mUrlInput.getText().toString())) {
490 mUrlInput.setText(title, false);
491 }
492 return;
493 }
494 }
495 if (!url.equals(mUrlInput.getText().toString())) {
496 mUrlInput.setText(url, false);
Michael Kolb29aab402012-05-29 17:22:35 -0700497 }
John Reck0f602f32011-07-07 15:38:43 -0700498 }
499 }
500
John Reck0f602f32011-07-07 15:38:43 -0700501 void setIncognitoMode(boolean incognito) {
502 mUrlInput.setIncognitoMode(incognito);
503 }
504
505 void clearCompletions() {
Narayan Kamathf3174a52011-11-17 14:43:32 +0000506 mUrlInput.dismissDropDown();
John Reck0f602f32011-07-07 15:38:43 -0700507 }
508
509 // UrlInputListener implementation
510
511 /**
512 * callback from suggestion dropdown
513 * user selected a suggestion
514 */
515 @Override
516 public void onAction(String text, String extra, String source) {
Michael Kolb0b129122012-06-04 16:31:58 -0700517 stopEditingUrl();
John Reck0f602f32011-07-07 15:38:43 -0700518 if (UrlInputView.TYPED.equals(source)) {
kaiyizc4ada322013-07-30 09:58:07 +0800519 String url = null;
Panos Thomas4bdb5252014-11-13 16:20:11 -0800520 boolean wap2estore = BrowserConfig.getInstance(getContext())
521 .hasFeature(BrowserConfig.Feature.WAP2ESTORE);
Vivek Sekhar5e631472014-03-31 23:59:10 -0700522 if ((wap2estore && isEstoreTypeUrl(text)) || isRtspTypeUrl(text)
523 || isMakeCallTypeUrl(text)) {
kaiyizc4ada322013-07-30 09:58:07 +0800524 url = text;
525 } else {
526 url = UrlUtils.smartUrlFilter(text, false);
527 }
528
John Reck0f602f32011-07-07 15:38:43 -0700529 Tab t = mBaseUi.getActiveTab();
530 // Only shortcut javascript URIs for now, as there is special
531 // logic in UrlHandler for other schemas
Axesh R. Ajmera6fc73692015-08-11 16:32:10 -0700532 if (url != null && t != null && url.startsWith("javascript:")) {
John Reck0f602f32011-07-07 15:38:43 -0700533 mUiController.loadUrl(t, url);
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700534 setDisplayTitle(null, text);
John Reck0f602f32011-07-07 15:38:43 -0700535 return;
536 }
kaiyizc4ada322013-07-30 09:58:07 +0800537
538 // add for carrier wap2estore feature
539 if (url != null && t != null && wap2estore && isEstoreTypeUrl(url)) {
Vivek Sekharb54614f2014-05-01 19:03:37 -0700540 if (handleEstoreTypeUrl(url)) {
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700541 setDisplayTitle(null, text);
Vivek Sekharb54614f2014-05-01 19:03:37 -0700542 return;
543 }
kaiyizc4ada322013-07-30 09:58:07 +0800544 }
kaiyiz950eca22013-08-08 11:01:28 +0800545 // add for rtsp scheme feature
546 if (url != null && t != null && isRtspTypeUrl(url)) {
547 if (handleRtspTypeUrl(url)) {
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700548 setDisplayTitle(null, text);
kaiyiz950eca22013-08-08 11:01:28 +0800549 return;
550 }
551 }
Vivek Sekhar5e631472014-03-31 23:59:10 -0700552 // add for "wtai://wp/mc;" scheme feature
553 if (url != null && t != null && isMakeCallTypeUrl(url)) {
554 if (handleMakeCallTypeUrl(url)) {
555 return;
556 }
557 }
John Reck0f602f32011-07-07 15:38:43 -0700558 }
559 Intent i = new Intent();
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700560 String action = Intent.ACTION_SEARCH;
John Reck0f602f32011-07-07 15:38:43 -0700561 i.setAction(action);
562 i.putExtra(SearchManager.QUERY, text);
563 if (extra != null) {
564 i.putExtra(SearchManager.EXTRA_DATA_KEY, extra);
565 }
566 if (source != null) {
567 Bundle appData = new Bundle();
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800568 appData.putString("source", source);
569 i.putExtra("source", appData);
John Reck0f602f32011-07-07 15:38:43 -0700570 }
571 mUiController.handleNewIntent(i);
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700572 setDisplayTitle(null, text);
John Reck0f602f32011-07-07 15:38:43 -0700573 }
574
Vivek Sekhar5e631472014-03-31 23:59:10 -0700575 private boolean isMakeCallTypeUrl(String url) {
576 String utf8Url = null;
577 try {
578 utf8Url = new String(url.getBytes("UTF-8"), "UTF-8");
579 } catch (UnsupportedEncodingException e) {
580 Log.e(TAG, "err " + e);
581 }
582 if (utf8Url != null && utf8Url.startsWith(UrlHandler.SCHEME_WTAI_MC)) {
583 return true;
584 }
585 return false;
586 }
587
588 private boolean handleMakeCallTypeUrl(String url) {
589 // wtai://wp/mc;number
590 // number=string(phone-number)
591 if (url.startsWith(UrlHandler.SCHEME_WTAI_MC)) {
592 Intent intent = new Intent(Intent.ACTION_VIEW,
593 Uri.parse(WebView.SCHEME_TEL +
Vivek Sekharcb3f7232015-12-10 20:02:46 -0800594 Uri.encode(url.substring(UrlHandler.SCHEME_WTAI_MC.length()))));
Vivek Sekhar5e631472014-03-31 23:59:10 -0700595 getContext().startActivity(intent);
596 // before leaving BrowserActivity, close the empty child tab.
597 // If a new tab is created through JavaScript open to load this
598 // url, we would like to close it as we will load this url in a
599 // different Activity.
600 Tab current = mUiController.getCurrentTab();
601 if (current != null
602 && current.getWebView().copyBackForwardList().getSize() == 0) {
603 mUiController.closeCurrentTab();
604 }
605 return true;
606 }
607 return false;
608 }
609
kaiyizc4ada322013-07-30 09:58:07 +0800610 private boolean isEstoreTypeUrl(String url) {
Vivek Sekharb54614f2014-05-01 19:03:37 -0700611 if (url != null && url.startsWith("estore:")) {
kaiyizc4ada322013-07-30 09:58:07 +0800612 return true;
613 }
614 return false;
615 }
616
Vivek Sekharb54614f2014-05-01 19:03:37 -0700617 private boolean handleEstoreTypeUrl(String url) {
618 if (url.getBytes().length > 256) {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800619 Toast.makeText(getContext(), R.string.estore_url_warning, Toast.LENGTH_LONG).show();
Vivek Sekharb54614f2014-05-01 19:03:37 -0700620 return false;
kaiyizc4ada322013-07-30 09:58:07 +0800621 }
Vivek Sekharb54614f2014-05-01 19:03:37 -0700622
623 Intent intent;
624 // perform generic parsing of the URI to turn it into an Intent.
625 try {
626 intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
627 } catch (URISyntaxException ex) {
628 Log.w("Browser", "Bad URI " + url + ": " + ex.getMessage());
629 return false;
630 }
631
kaiyizc4ada322013-07-30 09:58:07 +0800632 try {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800633 getContext().startActivity(intent);
kaiyizc4ada322013-07-30 09:58:07 +0800634 } catch (ActivityNotFoundException ex) {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800635 String downloadUrl = getContext().getResources().getString(R.string.estore_homepage);
kaiyizc4ada322013-07-30 09:58:07 +0800636 mUiController.loadUrl(mBaseUi.getActiveTab(), downloadUrl);
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800637 Toast.makeText(getContext(), R.string.download_estore_app, Toast.LENGTH_LONG).show();
kaiyizc4ada322013-07-30 09:58:07 +0800638 }
Vivek Sekharb54614f2014-05-01 19:03:37 -0700639
640 return true;
kaiyizc4ada322013-07-30 09:58:07 +0800641 }
642
kaiyiz950eca22013-08-08 11:01:28 +0800643 private boolean isRtspTypeUrl(String url) {
644 String utf8Url = null;
645 try {
646 utf8Url = new String(url.getBytes("UTF-8"), "UTF-8");
647 } catch (UnsupportedEncodingException e) {
648 Log.e(TAG, "err " + e);
649 }
650 if (utf8Url != null && utf8Url.startsWith("rtsp://")) {
651 return true;
652 }
653 return false;
654 }
655
656 private boolean handleRtspTypeUrl(String url) {
657 Intent intent;
658 // perform generic parsing of the URI to turn it into an Intent.
659 try {
660 intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
661 } catch (URISyntaxException ex) {
662 Log.w("Browser", "Bad URI " + url + ": " + ex.getMessage());
663 return false;
664 }
665
666 try {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800667 getContext().startActivity(intent);
kaiyiz950eca22013-08-08 11:01:28 +0800668 } catch (ActivityNotFoundException ex) {
669 Log.w("Browser", "No resolveActivity " + url);
670 return false;
671 }
672 return true;
673 }
674
John Reck0f602f32011-07-07 15:38:43 -0700675 @Override
676 public void onDismiss() {
677 final Tab currentTab = mBaseUi.getActiveTab();
678 mBaseUi.hideTitleBar();
679 post(new Runnable() {
680 public void run() {
681 clearFocus();
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700682 if (currentTab != null) {
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700683 setDisplayTitle(currentTab.getTitle(), currentTab.getUrl());
John Reck0f602f32011-07-07 15:38:43 -0700684 }
685 }
686 });
687 }
688
689 /**
690 * callback from the suggestion dropdown
691 * copy text to input field and stay in edit mode
692 */
693 @Override
694 public void onCopySuggestion(String text) {
695 mUrlInput.setText(text, true);
John Reck0f602f32011-07-07 15:38:43 -0700696 }
697
698 public void setCurrentUrlIsBookmark(boolean isBookmark) {
699 }
700
701 @Override
702 public boolean dispatchKeyEventPreIme(KeyEvent evt) {
703 if (evt.getKeyCode() == KeyEvent.KEYCODE_BACK) {
Sagar Dhawan5a5d01f2015-07-30 17:16:21 -0700704 if (mUiController.getCurrentTab() != null &&
705 mUiController.getCurrentTab().isKeyboardShowing()){
706 stopEditingUrl();
707 return true;
708 }
John Reck0f602f32011-07-07 15:38:43 -0700709 // catch back key in order to do slightly more cleanup than usual
Michael Kolb0b129122012-06-04 16:31:58 -0700710 stopEditingUrl();
John Reck0f602f32011-07-07 15:38:43 -0700711 }
712 return super.dispatchKeyEventPreIme(evt);
713 }
714
John Reck0f602f32011-07-07 15:38:43 -0700715 /**
716 * called from the Ui when the user wants to edit
717 * @param clearInput clear the input field
718 */
Michael Kolb1f9b3562012-04-24 14:38:34 -0700719 void startEditingUrl(boolean clearInput, boolean forceIME) {
John Reck0f602f32011-07-07 15:38:43 -0700720 // editing takes preference of progress
721 setVisibility(View.VISIBLE);
John Reck0f602f32011-07-07 15:38:43 -0700722 if (clearInput) {
723 mUrlInput.setText("");
John Reck0f602f32011-07-07 15:38:43 -0700724 }
Tarun Nainaniaa586822015-08-20 14:59:33 -0700725 if (!mUrlInput.hasFocus()) {
726 mUrlInput.requestFocus();
727 }
Michael Kolb1f9b3562012-04-24 14:38:34 -0700728 if (forceIME) {
Michael Kolb4bb6fcb2012-04-13 14:25:27 -0700729 mUrlInput.showIME();
730 }
John Reck0f602f32011-07-07 15:38:43 -0700731 }
732
733 public void onProgressStarted() {
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700734 mFaviconTile.setBadgeBlockedObjectsCount(0);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700735 mFaviconTile.setTrustLevel(SiteTileView.TRUST_UNKNOWN);
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700736 mFaviconTile.setBadgeHasCertIssues(false);
Pankaj Garg96d0ccd2015-07-30 16:49:47 -0700737 setSecurityState(Tab.SecurityState.SECURITY_STATE_NOT_SECURE);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700738 mHandler.removeMessages(WEBREFINER_COUNTER_MSG);
739 mHandler.sendEmptyMessageDelayed(WEBREFINER_COUNTER_MSG,
740 WEBREFINER_COUNTER_MSG_DELAY);
jrizzoli3f57be02016-01-24 21:06:30 +0100741 mStopButton.setImageResource(R.drawable.ic_action_stop_inverted);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700742 mStopButton.setContentDescription(getResources().
743 getString(R.string.accessibility_button_stop));
John Reck0f602f32011-07-07 15:38:43 -0700744 }
745
746 public void onProgressStopped() {
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700747 if (!isEditingUrl()) {
748 mFaviconTile.setVisibility(View.VISIBLE);
749 }
jrizzoli3f57be02016-01-24 21:06:30 +0100750 mStopButton.setImageResource(R.drawable.ic_action_reload_inverted);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700751 mStopButton.setContentDescription(getResources().
752 getString(R.string.accessibility_button_refresh));
John Reck0f602f32011-07-07 15:38:43 -0700753 }
754
John Reck419f6b42011-08-16 16:10:51 -0700755 public void onTabDataChanged(Tab tab) {
756 }
757
Michael Kolb0b129122012-06-04 16:31:58 -0700758 public void onVoiceResult(String s) {
759 startEditingUrl(true, true);
760 onCopySuggestion(s);
761 }
762
Narayan Kamathf3174a52011-11-17 14:43:32 +0000763 @Override
764 public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
765
766 @Override
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700767 public void onTextChanged(CharSequence s, int start, int before, int count) { }
Narayan Kamathf3174a52011-11-17 14:43:32 +0000768
769 @Override
770 public void afterTextChanged(Editable s) { }
Michael Kolb0b129122012-06-04 16:31:58 -0700771
Enrico Ros1f5a0952014-11-18 20:15:48 -0800772 @Override
773 public void onStateChanged(int state) {
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700774 mVoiceButton.setVisibility(View.GONE);
Sagar Dhawan84ef4442015-07-29 12:08:10 -0700775 mClearButton.setVisibility(View.GONE);
Enrico Ros1f5a0952014-11-18 20:15:48 -0800776 switch(state) {
777 case STATE_NORMAL:
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700778 mFaviconTile.setVisibility(View.VISIBLE);
jrizzolia62318b2015-09-08 21:44:50 +0200779 mSeparator.setVisibility(View.VISIBLE);
Sagar Dhawanaff56c92015-07-13 15:57:11 -0700780 mMore.setVisibility(View.VISIBLE);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700781 if (mUiController != null) {
782 Tab currentTab = mUiController.getCurrentTab();
783 if (currentTab != null){
784 if (TextUtils.isEmpty(currentTab.getUrl())) {
785 mFaviconTile.setVisibility(View.GONE);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700786 }
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700787 setDisplayTitle(currentTab.getTitle(), currentTab.getUrl());
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700788 }
789 mUiController.setWindowDimming(0.0f);
790 }
791
Enrico Ros1f5a0952014-11-18 20:15:48 -0800792 break;
793 case STATE_HIGHLIGHTED:
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700794 mFaviconTile.setVisibility(View.GONE);
jrizzolia62318b2015-09-08 21:44:50 +0200795 mSeparator.setVisibility(View.GONE);
Sagar Dhawan84ef4442015-07-29 12:08:10 -0700796 mClearButton.setVisibility(View.VISIBLE);
Enrico Ros1f5a0952014-11-18 20:15:48 -0800797 mMore.setVisibility(View.GONE);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700798 if (mUiController != null) {
799 mUiController.setWindowDimming(0.75f);
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700800 if (mTrustLevel == SiteTileView.TRUST_TRUSTED) {
801 Tab currentTab = mUiController.getCurrentTab();
802 if (currentTab != null) {
803 mUrlInput.setText(currentTab.getUrl(), false);
804 mUrlInput.selectAll();
805 }
806 }
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700807 }
Enrico Ros1f5a0952014-11-18 20:15:48 -0800808 break;
809 case STATE_EDITED:
Sagar Dhawan84ef4442015-07-29 12:08:10 -0700810 if (TextUtils.isEmpty(mUrlInput.getText()) &&
811 mUiController != null &&
812 mUiController.supportsVoice()) {
813 mVoiceButton.setVisibility(View.VISIBLE);
814 }
815 else {
816 mClearButton.setVisibility(View.VISIBLE);
817 }
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700818 mFaviconTile.setVisibility(View.GONE);
Enrico Ros1f5a0952014-11-18 20:15:48 -0800819 mMore.setVisibility(View.GONE);
820 break;
821 }
822 }
823
824 public boolean isMenuShowing() {
825 return mOverflowMenuShowing;
826 }
827
828
829 @Override
830 public void onDismiss(PopupMenu popupMenu) {
831 if (popupMenu == mPopupMenu) {
832 onMenuHidden();
833 }
834 }
835
836 private void onMenuHidden() {
837 mOverflowMenuShowing = false;
Enrico Ros1f5a0952014-11-18 20:15:48 -0800838 }
839
840
841 @Override
842 public boolean onMenuItemClick(MenuItem item) {
843 return mUiController.onOptionsItemSelected(item);
844 }
John Reck0f602f32011-07-07 15:38:43 -0700845}