blob: eb8dc537f1d647c19ac5f235c7016ac25ec54e26 [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;
jrizzolia62318b2015-09-08 21:44:50 +020079 private View mSeparator;
Pankaj Garg66f8cef2015-07-07 17:29:03 -070080 private View mVoiceButton;
81 private ImageView mClearButton;
Enrico Ros1f5a0952014-11-18 20:15:48 -080082 private View mMore;
83 private PopupMenu mPopupMenu;
84 private boolean mOverflowMenuShowing;
Axesh R. Ajmera2e241242014-05-19 15:53:38 -070085
Pankaj Garg66f8cef2015-07-07 17:29:03 -070086 private static Bitmap mDefaultFavicon;
87
Pankaj Garg32e1b942015-06-03 18:13:24 -070088 private int mStatusBarColor;
89 private static int mDefaultStatusBarColor = -1;
90
Pankaj Garg66f8cef2015-07-07 17:29:03 -070091 private static final int WEBREFINER_COUNTER_MSG = 4242;
92 private static final int WEBREFINER_COUNTER_MSG_DELAY = 3000;
93 private Handler mHandler;
94
Pankaj Garg8d2e98f2015-08-07 10:01:49 -070095 protected int mTrustLevel = SiteTileView.TRUST_UNKNOWN;
96
Pankaj Garg66f8cef2015-07-07 17:29:03 -070097 private static final String noSitePrefs[] = {
Axesh R. Ajmera6fc73692015-08-11 16:32:10 -070098 "chrome://",
Pankaj Garg66f8cef2015-07-07 17:29:03 -070099 "about:",
100 "content:",
101 };
102
John Reck0f602f32011-07-07 15:38:43 -0700103 public NavigationBarBase(Context context) {
104 super(context);
105 }
106
107 public NavigationBarBase(Context context, AttributeSet attrs) {
108 super(context, attrs);
109 }
110
111 public NavigationBarBase(Context context, AttributeSet attrs, int defStyle) {
112 super(context, attrs, defStyle);
113 }
114
115 @Override
116 protected void onFinishInflate() {
117 super.onFinishInflate();
John Reck0f602f32011-07-07 15:38:43 -0700118 mUrlInput = (UrlInputView) findViewById(R.id.url);
119 mUrlInput.setUrlInputListener(this);
John Reck0f602f32011-07-07 15:38:43 -0700120 mUrlInput.setOnFocusChangeListener(this);
121 mUrlInput.setSelectAllOnFocus(true);
Narayan Kamathf3174a52011-11-17 14:43:32 +0000122 mUrlInput.addTextChangedListener(this);
Enrico Ros1f5a0952014-11-18 20:15:48 -0800123 mMore = findViewById(R.id.more_browser_settings);
124 mMore.setOnClickListener(this);
jrizzolia62318b2015-09-08 21:44:50 +0200125 mSeparator = findViewById(R.id.separator);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700126 mFaviconTile = (SiteTileView) findViewById(R.id.favicon_view);
127 mFaviconTile.setOnClickListener(this);
128 mVoiceButton = findViewById(R.id.voice);
129 mVoiceButton.setOnClickListener(this);
130 mClearButton = (ImageView) findViewById(R.id.clear);
131 mClearButton.setOnClickListener(this);
132 mStopButton = (ImageView) findViewById(R.id.stop);
133 mStopButton.setOnClickListener(this);
134
135 mDefaultFavicon = BitmapFactory.decodeResource(getResources(),
136 R.drawable.ic_deco_favicon_normal);
137
138 mHandler = new Handler() {
139 @Override
140 public void handleMessage(Message m) {
141 switch (m.what) {
142 case WEBREFINER_COUNTER_MSG:
143 WebView wv = mUiController.getCurrentTopWebView();
144 if (wv != null && WebRefiner.isInitialized()) {
145 int count = WebRefiner.getInstance().getBlockedURLCount(wv);
146 if (count > 0) {
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700147 mFaviconTile.setBadgeBlockedObjectsCount(count);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700148 }
149 }
150 mHandler.sendEmptyMessageDelayed(WEBREFINER_COUNTER_MSG,
151 WEBREFINER_COUNTER_MSG_DELAY);
152 break;
153 }
154 }
155 };
John Reck0f602f32011-07-07 15:38:43 -0700156 }
157
158 public void setTitleBar(TitleBar titleBar) {
159 mTitleBar = titleBar;
160 mBaseUi = mTitleBar.getUi();
161 mUiController = mTitleBar.getUiController();
Michael Kolbb2e91fd2011-07-14 13:47:29 -0700162 mUrlInput.setController(mUiController);
John Reck0f602f32011-07-07 15:38:43 -0700163 }
164
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700165 public void setSecurityState(Tab.SecurityState securityState) {
Pankaj Garg96d0ccd2015-07-30 16:49:47 -0700166 switch (securityState) {
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700167 case SECURITY_STATE_SECURE:
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700168 mTrustLevel = SiteTileView.TRUST_TRUSTED;
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700169 mFaviconTile.setBadgeHasCertIssues(false);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700170 break;
171 case SECURITY_STATE_MIXED:
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700172 mTrustLevel = SiteTileView.TRUST_UNTRUSTED;
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700173 mFaviconTile.setBadgeHasCertIssues(true);
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700174 mTitleBar.showTopControls(false);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700175 break;
176 case SECURITY_STATE_BAD_CERTIFICATE:
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700177 mTrustLevel = SiteTileView.TRUST_AVOID;
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700178 mFaviconTile.setBadgeHasCertIssues(true);
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700179 mTitleBar.showTopControls(false);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700180 break;
181 case SECURITY_STATE_NOT_SECURE:
182 default:
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700183 mTrustLevel = SiteTileView.TRUST_UNKNOWN;
John Reck0f602f32011-07-07 15:38:43 -0700184 }
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700185 mFaviconTile.setTrustLevel(mTrustLevel);
186 }
187
188 public int getTrustLevel() {
189 return mTrustLevel;
John Reck0f602f32011-07-07 15:38:43 -0700190 }
191
Pankaj Garg32e1b942015-06-03 18:13:24 -0700192 public static int adjustColor(int color, float hueMultiplier,
193 float saturationMultiplier, float valueMultiplier) {
194 float[] hsv = new float[3];
195 Color.colorToHSV(color, hsv);
196 hsv[0] *= hueMultiplier;
197 hsv[1] *= saturationMultiplier;
198 hsv[2] *= valueMultiplier;
199 return Color.HSVToColor(Color.alpha(color), hsv);
200 }
201
202 public static void setStatusAndNavigationBarColor(final Activity activity, int color) {
Sagar Dhawaneecefa32015-09-25 12:02:34 -0700203 // The flag that allows coloring is disabled in PowerSaveMode, no point in trying to color.
204 if (BrowserSettings.getInstance().isPowerSaveModeEnabled())
205 return;
jrizzolibe2afc52015-10-28 18:43:00 +0100206 // Disable colored statusbar if user asked so
207 if (! BrowserSettings.getInstance().isColoredSBEnabled())
208 return;
Pankaj Garg32e1b942015-06-03 18:13:24 -0700209 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
210 int currentColor = activity.getWindow().getStatusBarColor();
211 Integer from = currentColor;
212 Integer to = color;
213 ValueAnimator animator = ValueAnimator.ofObject(new ArgbEvaluator(), from, to);
214
215 if (mDefaultStatusBarColor == -1) {
216 mDefaultStatusBarColor = activity.getWindow().getStatusBarColor();
217 }
218
219 animator.addUpdateListener(
220 new ValueAnimator.AnimatorUpdateListener() {
221 @Override
222 public void onAnimationUpdate(ValueAnimator animation) {
223 Integer value = (Integer) animation.getAnimatedValue();
224 activity.getWindow().setStatusBarColor(value.intValue());
225 //activity.getWindow().setNavigationBarColor(value.intValue());
226 }
227 }
228 );
229 animator.start();
230 }
231 }
232
233 private void updateSiteIconColor(String urlString, int color) {
234 try {
235 URL url = new URL(urlString);
236 String host = url.getHost();
237 SharedPreferences prefs = BrowserSettings.getInstance().getPreferences();
238 int currentColor = prefs.getInt(host + ":color", 0);
239 if (currentColor != color) {
240 SharedPreferences.Editor editor = prefs.edit();
241 editor.remove(host + ":color");
242 editor.putInt(host + ":color", color);
243 editor.commit();
244 }
245 } catch (MalformedURLException e) {
246 }
247 }
248
249 public static int getSiteIconColor(String urlString) {
250 try {
251 URL url = new URL(urlString);
252 String host = url.getHost();
253 SharedPreferences prefs = BrowserSettings.getInstance().getPreferences();
254 return prefs.getInt(host + ":color", 0);
255 } catch (MalformedURLException e) {
256 return 0;
257 }
258 }
259
260 public static int getDefaultStatusBarColor() {
261 return mDefaultStatusBarColor;
262 }
263
Sagar Dhawanca9ecfb2015-08-10 17:27:58 -0700264 // Sets the favicon for the given tab if it's in the foreground
265 // If the tab doesn't have a favicon, it sets the default favicon
266 public void showCurrentFavicon(Tab tab) {
267 int color;
268 if (tab == null) { return; }
Pankaj Garg32e1b942015-06-03 18:13:24 -0700269
Sagar Dhawanca9ecfb2015-08-10 17:27:58 -0700270 if (tab.inForeground()) {
Pankaj Garg32e1b942015-06-03 18:13:24 -0700271 if (tab.hasFavicon()) {
Sagar Dhawanca9ecfb2015-08-10 17:27:58 -0700272 color = ColorUtils.getDominantColorForBitmap(tab.getFavicon());
Pankaj Garg32e1b942015-06-03 18:13:24 -0700273 updateSiteIconColor(tab.getUrl(), color);
274 setStatusAndNavigationBarColor(mUiController.getActivity(),
275 adjustColor(color, 1, 1, 0.7f));
Sagar Dhawanca9ecfb2015-08-10 17:27:58 -0700276
277 } else {
Pankaj Garg32e1b942015-06-03 18:13:24 -0700278 color = getSiteIconColor(tab.getUrl());
279 if (color != 0) {
280 setStatusAndNavigationBarColor(mUiController.getActivity(),
281 adjustColor(color, 1, 1, 0.7f));
282 } else {
283 setStatusAndNavigationBarColor(mUiController.getActivity(),
284 mDefaultStatusBarColor);
285 }
286 }
Sagar Dhawanca9ecfb2015-08-10 17:27:58 -0700287 if (mFaviconTile != null) {
288 mFaviconTile.replaceFavicon(tab.getFavicon()); // Always set the tab's favicon
289 }
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700290 }
John Reck0f602f32011-07-07 15:38:43 -0700291 }
292
Pankaj Garg32e1b942015-06-03 18:13:24 -0700293 protected void showSiteSpecificSettings() {
294 WebView wv = mUiController.getCurrentTopWebView();
Pankaj Gargdbdf5aa2015-07-16 15:22:37 -0700295 int ads = 0;
296 int tracker = 0;
297 int malware = 0;
Pankaj Garg32e1b942015-06-03 18:13:24 -0700298
Pankaj Gargdbdf5aa2015-07-16 15:22:37 -0700299 WebRefiner webRefiner = WebRefiner.getInstance();
300 if (wv != null && webRefiner != null) {
301 WebRefiner.PageInfo pageInfo = webRefiner.getPageInfo(wv);
302 if (pageInfo != null) {
303 for (WebRefiner.MatchedURLInfo urlInfo : pageInfo.mMatchedURLInfoList) {
Pankaj Gargee992032015-07-24 15:59:36 -0700304 if (urlInfo.mActionTaken == WebRefiner.MatchedURLInfo.ACTION_BLOCKED) {
305 switch (urlInfo.mMatchedFilterCategory) {
306 case WebRefiner.RuleSet.CATEGORY_ADS:
307 ads++;
308 break;
309 case WebRefiner.RuleSet.CATEGORY_TRACKERS:
310 tracker++;
311 break;
312 case WebRefiner.RuleSet.CATEGORY_MALWARE_DOMAINS:
313 malware++;
314 break;
315 }
Pankaj Gargdbdf5aa2015-07-16 15:22:37 -0700316 }
317 }
318 }
Pankaj Garg32e1b942015-06-03 18:13:24 -0700319 }
320
321 Bundle bundle = new Bundle();
322 bundle.putCharSequence(SiteSpecificPreferencesFragment.EXTRA_SITE,
323 mUiController.getCurrentTab().getUrl());
Sagar Dhawane28023a2015-08-13 16:40:25 -0700324 bundle.putCharSequence(SiteSpecificPreferencesFragment.EXTRA_SITE_TITLE,
325 mUiController.getCurrentTab().getTitle());
Pankaj Gargdbdf5aa2015-07-16 15:22:37 -0700326 bundle.putInt(SiteSpecificPreferencesFragment.EXTRA_WEB_REFINER_ADS_INFO, ads);
327 bundle.putInt(SiteSpecificPreferencesFragment.EXTRA_WEB_REFINER_TRACKER_INFO, tracker);
328 bundle.putInt(SiteSpecificPreferencesFragment.EXTRA_WEB_REFINER_MALWARE_INFO, malware);
Pankaj Garg32e1b942015-06-03 18:13:24 -0700329
330 bundle.putParcelable(SiteSpecificPreferencesFragment.EXTRA_SECURITY_CERT,
331 SslCertificate.saveState(wv.getCertificate()));
332
Pankaj Garg96d0ccd2015-07-30 16:49:47 -0700333 Tab.SecurityState securityState = Tab.getWebViewSecurityState(
334 mUiController.getCurrentTab().getWebView());
335 if (securityState == Tab.SecurityState.SECURITY_STATE_MIXED) {
336 bundle.putBoolean(SiteSpecificPreferencesFragment.EXTRA_SECURITY_CERT_MIXED, true);
337 } else if (securityState == Tab.SecurityState.SECURITY_STATE_BAD_CERTIFICATE) {
338 bundle.putBoolean(SiteSpecificPreferencesFragment.EXTRA_SECURITY_CERT_BAD, true);
Pankaj Garg32e1b942015-06-03 18:13:24 -0700339 }
340
Pankaj Garg68faf1c2015-06-26 17:07:37 -0700341 Bitmap favicon = mUiController.getCurrentTopWebView().getFavicon();
Pankaj Garg32e1b942015-06-03 18:13:24 -0700342 if (favicon != null) {
343 ByteArrayOutputStream baos = new ByteArrayOutputStream();
Sagar Dhawanca9ecfb2015-08-10 17:27:58 -0700344 favicon.compress(Bitmap.CompressFormat.PNG, 100, baos);
Pankaj Garg32e1b942015-06-03 18:13:24 -0700345 bundle.putByteArray(SiteSpecificPreferencesFragment.EXTRA_FAVICON,
346 baos.toByteArray());
347 }
348 BrowserPreferencesPage.startPreferenceFragmentExtraForResult(
Pankaj Garg75273bb2015-08-20 11:43:49 -0700349 mUiController.getActivity(), SiteSpecificPreferencesFragment.class.getName(),
350 bundle, Controller.PREFERENCES_PAGE);
Pankaj Garg32e1b942015-06-03 18:13:24 -0700351 }
352
John Reck0f602f32011-07-07 15:38:43 -0700353 @Override
354 public void onClick(View v) {
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700355 Tab currentTab = mUiController.getCurrentTab();
356 String url = null;
Sagar Dhawan20b1deb2015-10-12 11:13:18 -0700357 WebView wv = null;
358 if (currentTab != null) {
359 wv = currentTab.getWebView();
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700360 url = currentTab.getUrl();
361 }
Sagar Dhawan20b1deb2015-10-12 11:13:18 -0700362
Enrico Ros1f5a0952014-11-18 20:15:48 -0800363 if (mMore == v) {
364 showMenu(mMore);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700365 } else if (mFaviconTile == v) {
Vivek Sekharae3b1792015-08-03 12:26:41 -0700366 if (urlHasSitePrefs(url) && (wv != null && !wv.isShowingInterstitialPage()) ){
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700367 showSiteSpecificSettings();
368 }
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700369 } else if (mVoiceButton == v) {
370 mUiController.startVoiceRecognizer();
371 } else if (mStopButton == v) {
372 stopOrRefresh();
373 } else if (mClearButton == v) {
374 clearOrClose();
375 mUrlInput.setText("");
376 }
377 }
378
379 private static boolean urlHasSitePrefs(String url) {
380 if (TextUtils.isEmpty(url)) {
381 return false;
382 }
383
384 for (int i = 0; i < noSitePrefs.length; i++) {
385 if (url.startsWith(noSitePrefs[i])) {
386 return false;
387 }
388 }
389 return true;
390 }
391
392 private void stopOrRefresh() {
393 if (mUiController == null) return;
394 if (mTitleBar.isInLoad()) {
395 mUiController.stopLoading();
396 } else {
397 if (mUiController.getCurrentTopWebView() != null) {
398 stopEditingUrl();
399 mUiController.getCurrentTopWebView().reload();
400 }
401 }
402 }
403
404 private void clearOrClose() {
405 if (TextUtils.isEmpty(mUrlInput.getText())) {
406 // close
407 mUrlInput.clearFocus();
408 } else {
409 // clear
410 mUrlInput.setText("");
Enrico Ros1f5a0952014-11-18 20:15:48 -0800411 }
412 }
413
414 void showMenu(View anchor) {
415 Activity activity = mUiController.getActivity();
416 if (mPopupMenu == null) {
417 mPopupMenu = new PopupMenu(getContext(), anchor);
418 mPopupMenu.setOnMenuItemClickListener(this);
419 mPopupMenu.setOnDismissListener(this);
420 if (!activity.onCreateOptionsMenu(mPopupMenu.getMenu())) {
421 mPopupMenu = null;
422 return;
423 }
424 }
425 Menu menu = mPopupMenu.getMenu();
426
427 if (mUiController instanceof Controller) {
428 Controller controller = (Controller) mUiController;
429 if (controller.onPrepareOptionsMenu(menu)) {
430 mOverflowMenuShowing = true;
431 }
432 }
John Reck0f602f32011-07-07 15:38:43 -0700433 }
434
435 @Override
436 public void onFocusChange(View view, boolean hasFocus) {
437 // if losing focus and not in touch mode, leave as is
438 if (hasFocus || view.isInTouchMode() || mUrlInput.needsUpdate()) {
439 setFocusState(hasFocus);
440 }
441 if (hasFocus) {
442 mBaseUi.showTitleBar();
Dany Rybnikovbcd37da2015-04-20 11:43:15 +0300443 if (!BrowserSettings.getInstance().isPowerSaveModeEnabled()) {
444 //Notify about anticipated network activity
445 NetworkServices.hintUpcomingUserActivity();
446 }
John Reck0f602f32011-07-07 15:38:43 -0700447 } else if (!mUrlInput.needsUpdate()) {
448 mUrlInput.dismissDropDown();
449 mUrlInput.hideIME();
450 if (mUrlInput.getText().length() == 0) {
451 Tab currentTab = mUiController.getTabControl().getCurrentTab();
452 if (currentTab != null) {
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700453 setDisplayTitle(currentTab.getTitle(), currentTab.getUrl());
John Reck0f602f32011-07-07 15:38:43 -0700454 }
455 }
John Reck0f602f32011-07-07 15:38:43 -0700456 }
457 mUrlInput.clearNeedsUpdate();
458 }
459
460 protected void setFocusState(boolean focus) {
461 }
462
John Reck0f602f32011-07-07 15:38:43 -0700463 public boolean isEditingUrl() {
464 return mUrlInput.hasFocus();
465 }
466
467 void stopEditingUrl() {
Michael Kolb0b129122012-06-04 16:31:58 -0700468 WebView currentTopWebView = mUiController.getCurrentTopWebView();
469 if (currentTopWebView != null) {
470 currentTopWebView.requestFocus();
471 }
John Reck0f602f32011-07-07 15:38:43 -0700472 }
473
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700474 void setDisplayTitle(String title, String url) {
John Reck0f602f32011-07-07 15:38:43 -0700475 if (!isEditingUrl()) {
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700476 if (!TextUtils.isEmpty(title)) {
477 if (mTrustLevel == SiteTileView.TRUST_TRUSTED) {
478 if (!title.equals(mUrlInput.getText().toString())) {
479 mUrlInput.setText(title, false);
480 }
481 return;
482 }
483 }
484 if (!url.equals(mUrlInput.getText().toString())) {
485 mUrlInput.setText(url, false);
Michael Kolb29aab402012-05-29 17:22:35 -0700486 }
John Reck0f602f32011-07-07 15:38:43 -0700487 }
488 }
489
John Reck0f602f32011-07-07 15:38:43 -0700490 void setIncognitoMode(boolean incognito) {
491 mUrlInput.setIncognitoMode(incognito);
492 }
493
494 void clearCompletions() {
Narayan Kamathf3174a52011-11-17 14:43:32 +0000495 mUrlInput.dismissDropDown();
John Reck0f602f32011-07-07 15:38:43 -0700496 }
497
498 // UrlInputListener implementation
499
500 /**
501 * callback from suggestion dropdown
502 * user selected a suggestion
503 */
504 @Override
505 public void onAction(String text, String extra, String source) {
Michael Kolb0b129122012-06-04 16:31:58 -0700506 stopEditingUrl();
John Reck0f602f32011-07-07 15:38:43 -0700507 if (UrlInputView.TYPED.equals(source)) {
kaiyizc4ada322013-07-30 09:58:07 +0800508 String url = null;
Panos Thomas4bdb5252014-11-13 16:20:11 -0800509 boolean wap2estore = BrowserConfig.getInstance(getContext())
510 .hasFeature(BrowserConfig.Feature.WAP2ESTORE);
Vivek Sekhar5e631472014-03-31 23:59:10 -0700511 if ((wap2estore && isEstoreTypeUrl(text)) || isRtspTypeUrl(text)
512 || isMakeCallTypeUrl(text)) {
kaiyizc4ada322013-07-30 09:58:07 +0800513 url = text;
514 } else {
515 url = UrlUtils.smartUrlFilter(text, false);
516 }
517
John Reck0f602f32011-07-07 15:38:43 -0700518 Tab t = mBaseUi.getActiveTab();
519 // Only shortcut javascript URIs for now, as there is special
520 // logic in UrlHandler for other schemas
Axesh R. Ajmera6fc73692015-08-11 16:32:10 -0700521 if (url != null && t != null && url.startsWith("javascript:")) {
John Reck0f602f32011-07-07 15:38:43 -0700522 mUiController.loadUrl(t, url);
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700523 setDisplayTitle(null, text);
John Reck0f602f32011-07-07 15:38:43 -0700524 return;
525 }
kaiyizc4ada322013-07-30 09:58:07 +0800526
527 // add for carrier wap2estore feature
528 if (url != null && t != null && wap2estore && isEstoreTypeUrl(url)) {
Vivek Sekharb54614f2014-05-01 19:03:37 -0700529 if (handleEstoreTypeUrl(url)) {
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700530 setDisplayTitle(null, text);
Vivek Sekharb54614f2014-05-01 19:03:37 -0700531 return;
532 }
kaiyizc4ada322013-07-30 09:58:07 +0800533 }
kaiyiz950eca22013-08-08 11:01:28 +0800534 // add for rtsp scheme feature
535 if (url != null && t != null && isRtspTypeUrl(url)) {
536 if (handleRtspTypeUrl(url)) {
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700537 setDisplayTitle(null, text);
kaiyiz950eca22013-08-08 11:01:28 +0800538 return;
539 }
540 }
Vivek Sekhar5e631472014-03-31 23:59:10 -0700541 // add for "wtai://wp/mc;" scheme feature
542 if (url != null && t != null && isMakeCallTypeUrl(url)) {
543 if (handleMakeCallTypeUrl(url)) {
544 return;
545 }
546 }
John Reck0f602f32011-07-07 15:38:43 -0700547 }
548 Intent i = new Intent();
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700549 String action = Intent.ACTION_SEARCH;
John Reck0f602f32011-07-07 15:38:43 -0700550 i.setAction(action);
551 i.putExtra(SearchManager.QUERY, text);
552 if (extra != null) {
553 i.putExtra(SearchManager.EXTRA_DATA_KEY, extra);
554 }
555 if (source != null) {
556 Bundle appData = new Bundle();
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800557 appData.putString("source", source);
558 i.putExtra("source", appData);
John Reck0f602f32011-07-07 15:38:43 -0700559 }
560 mUiController.handleNewIntent(i);
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700561 setDisplayTitle(null, text);
John Reck0f602f32011-07-07 15:38:43 -0700562 }
563
Vivek Sekhar5e631472014-03-31 23:59:10 -0700564 private boolean isMakeCallTypeUrl(String url) {
565 String utf8Url = null;
566 try {
567 utf8Url = new String(url.getBytes("UTF-8"), "UTF-8");
568 } catch (UnsupportedEncodingException e) {
569 Log.e(TAG, "err " + e);
570 }
571 if (utf8Url != null && utf8Url.startsWith(UrlHandler.SCHEME_WTAI_MC)) {
572 return true;
573 }
574 return false;
575 }
576
577 private boolean handleMakeCallTypeUrl(String url) {
578 // wtai://wp/mc;number
579 // number=string(phone-number)
580 if (url.startsWith(UrlHandler.SCHEME_WTAI_MC)) {
581 Intent intent = new Intent(Intent.ACTION_VIEW,
582 Uri.parse(WebView.SCHEME_TEL +
Vivek Sekharcb3f7232015-12-10 20:02:46 -0800583 Uri.encode(url.substring(UrlHandler.SCHEME_WTAI_MC.length()))));
Vivek Sekhar5e631472014-03-31 23:59:10 -0700584 getContext().startActivity(intent);
585 // before leaving BrowserActivity, close the empty child tab.
586 // If a new tab is created through JavaScript open to load this
587 // url, we would like to close it as we will load this url in a
588 // different Activity.
589 Tab current = mUiController.getCurrentTab();
590 if (current != null
591 && current.getWebView().copyBackForwardList().getSize() == 0) {
592 mUiController.closeCurrentTab();
593 }
594 return true;
595 }
596 return false;
597 }
598
kaiyizc4ada322013-07-30 09:58:07 +0800599 private boolean isEstoreTypeUrl(String url) {
Vivek Sekharb54614f2014-05-01 19:03:37 -0700600 if (url != null && url.startsWith("estore:")) {
kaiyizc4ada322013-07-30 09:58:07 +0800601 return true;
602 }
603 return false;
604 }
605
Vivek Sekharb54614f2014-05-01 19:03:37 -0700606 private boolean handleEstoreTypeUrl(String url) {
607 if (url.getBytes().length > 256) {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800608 Toast.makeText(getContext(), R.string.estore_url_warning, Toast.LENGTH_LONG).show();
Vivek Sekharb54614f2014-05-01 19:03:37 -0700609 return false;
kaiyizc4ada322013-07-30 09:58:07 +0800610 }
Vivek Sekharb54614f2014-05-01 19:03:37 -0700611
612 Intent intent;
613 // perform generic parsing of the URI to turn it into an Intent.
614 try {
615 intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
616 } catch (URISyntaxException ex) {
617 Log.w("Browser", "Bad URI " + url + ": " + ex.getMessage());
618 return false;
619 }
620
kaiyizc4ada322013-07-30 09:58:07 +0800621 try {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800622 getContext().startActivity(intent);
kaiyizc4ada322013-07-30 09:58:07 +0800623 } catch (ActivityNotFoundException ex) {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800624 String downloadUrl = getContext().getResources().getString(R.string.estore_homepage);
kaiyizc4ada322013-07-30 09:58:07 +0800625 mUiController.loadUrl(mBaseUi.getActiveTab(), downloadUrl);
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800626 Toast.makeText(getContext(), R.string.download_estore_app, Toast.LENGTH_LONG).show();
kaiyizc4ada322013-07-30 09:58:07 +0800627 }
Vivek Sekharb54614f2014-05-01 19:03:37 -0700628
629 return true;
kaiyizc4ada322013-07-30 09:58:07 +0800630 }
631
kaiyiz950eca22013-08-08 11:01:28 +0800632 private boolean isRtspTypeUrl(String url) {
633 String utf8Url = null;
634 try {
635 utf8Url = new String(url.getBytes("UTF-8"), "UTF-8");
636 } catch (UnsupportedEncodingException e) {
637 Log.e(TAG, "err " + e);
638 }
639 if (utf8Url != null && utf8Url.startsWith("rtsp://")) {
640 return true;
641 }
642 return false;
643 }
644
645 private boolean handleRtspTypeUrl(String url) {
646 Intent intent;
647 // perform generic parsing of the URI to turn it into an Intent.
648 try {
649 intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
650 } catch (URISyntaxException ex) {
651 Log.w("Browser", "Bad URI " + url + ": " + ex.getMessage());
652 return false;
653 }
654
655 try {
Bijan Amirzada9b1e9882014-02-26 17:15:46 -0800656 getContext().startActivity(intent);
kaiyiz950eca22013-08-08 11:01:28 +0800657 } catch (ActivityNotFoundException ex) {
658 Log.w("Browser", "No resolveActivity " + url);
659 return false;
660 }
661 return true;
662 }
663
John Reck0f602f32011-07-07 15:38:43 -0700664 @Override
665 public void onDismiss() {
666 final Tab currentTab = mBaseUi.getActiveTab();
667 mBaseUi.hideTitleBar();
668 post(new Runnable() {
669 public void run() {
670 clearFocus();
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700671 if (currentTab != null) {
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700672 setDisplayTitle(currentTab.getTitle(), currentTab.getUrl());
John Reck0f602f32011-07-07 15:38:43 -0700673 }
674 }
675 });
676 }
677
678 /**
679 * callback from the suggestion dropdown
680 * copy text to input field and stay in edit mode
681 */
682 @Override
683 public void onCopySuggestion(String text) {
684 mUrlInput.setText(text, true);
John Reck0f602f32011-07-07 15:38:43 -0700685 }
686
687 public void setCurrentUrlIsBookmark(boolean isBookmark) {
688 }
689
690 @Override
691 public boolean dispatchKeyEventPreIme(KeyEvent evt) {
692 if (evt.getKeyCode() == KeyEvent.KEYCODE_BACK) {
Sagar Dhawan5a5d01f2015-07-30 17:16:21 -0700693 if (mUiController.getCurrentTab() != null &&
694 mUiController.getCurrentTab().isKeyboardShowing()){
695 stopEditingUrl();
696 return true;
697 }
John Reck0f602f32011-07-07 15:38:43 -0700698 // catch back key in order to do slightly more cleanup than usual
Michael Kolb0b129122012-06-04 16:31:58 -0700699 stopEditingUrl();
John Reck0f602f32011-07-07 15:38:43 -0700700 }
701 return super.dispatchKeyEventPreIme(evt);
702 }
703
John Reck0f602f32011-07-07 15:38:43 -0700704 /**
705 * called from the Ui when the user wants to edit
706 * @param clearInput clear the input field
707 */
Michael Kolb1f9b3562012-04-24 14:38:34 -0700708 void startEditingUrl(boolean clearInput, boolean forceIME) {
John Reck0f602f32011-07-07 15:38:43 -0700709 // editing takes preference of progress
710 setVisibility(View.VISIBLE);
John Reck0f602f32011-07-07 15:38:43 -0700711 if (clearInput) {
712 mUrlInput.setText("");
John Reck0f602f32011-07-07 15:38:43 -0700713 }
Tarun Nainaniaa586822015-08-20 14:59:33 -0700714 if (!mUrlInput.hasFocus()) {
715 mUrlInput.requestFocus();
716 }
Michael Kolb1f9b3562012-04-24 14:38:34 -0700717 if (forceIME) {
Michael Kolb4bb6fcb2012-04-13 14:25:27 -0700718 mUrlInput.showIME();
719 }
John Reck0f602f32011-07-07 15:38:43 -0700720 }
721
722 public void onProgressStarted() {
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700723 mFaviconTile.setBadgeBlockedObjectsCount(0);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700724 mFaviconTile.setTrustLevel(SiteTileView.TRUST_UNKNOWN);
Pankaj Garg07b2fd92015-07-15 12:07:37 -0700725 mFaviconTile.setBadgeHasCertIssues(false);
Pankaj Garg96d0ccd2015-07-30 16:49:47 -0700726 setSecurityState(Tab.SecurityState.SECURITY_STATE_NOT_SECURE);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700727 mHandler.removeMessages(WEBREFINER_COUNTER_MSG);
728 mHandler.sendEmptyMessageDelayed(WEBREFINER_COUNTER_MSG,
729 WEBREFINER_COUNTER_MSG_DELAY);
730 mStopButton.setImageResource(R.drawable.ic_action_stop);
731 mStopButton.setContentDescription(getResources().
732 getString(R.string.accessibility_button_stop));
John Reck0f602f32011-07-07 15:38:43 -0700733 }
734
735 public void onProgressStopped() {
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700736 if (!isEditingUrl()) {
737 mFaviconTile.setVisibility(View.VISIBLE);
738 }
739 mStopButton.setImageResource(R.drawable.ic_action_reload);
740 mStopButton.setContentDescription(getResources().
741 getString(R.string.accessibility_button_refresh));
John Reck0f602f32011-07-07 15:38:43 -0700742 }
743
John Reck419f6b42011-08-16 16:10:51 -0700744 public void onTabDataChanged(Tab tab) {
745 }
746
Michael Kolb0b129122012-06-04 16:31:58 -0700747 public void onVoiceResult(String s) {
748 startEditingUrl(true, true);
749 onCopySuggestion(s);
750 }
751
Narayan Kamathf3174a52011-11-17 14:43:32 +0000752 @Override
753 public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
754
755 @Override
Michael Kolb5ff5c8b2012-05-03 11:37:58 -0700756 public void onTextChanged(CharSequence s, int start, int before, int count) { }
Narayan Kamathf3174a52011-11-17 14:43:32 +0000757
758 @Override
759 public void afterTextChanged(Editable s) { }
Michael Kolb0b129122012-06-04 16:31:58 -0700760
Enrico Ros1f5a0952014-11-18 20:15:48 -0800761 @Override
762 public void onStateChanged(int state) {
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700763 mVoiceButton.setVisibility(View.GONE);
Sagar Dhawan84ef4442015-07-29 12:08:10 -0700764 mClearButton.setVisibility(View.GONE);
Enrico Ros1f5a0952014-11-18 20:15:48 -0800765 switch(state) {
766 case STATE_NORMAL:
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700767 mFaviconTile.setVisibility(View.VISIBLE);
jrizzolia62318b2015-09-08 21:44:50 +0200768 mSeparator.setVisibility(View.VISIBLE);
Sagar Dhawanaff56c92015-07-13 15:57:11 -0700769 mMore.setVisibility(View.VISIBLE);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700770 if (mUiController != null) {
771 Tab currentTab = mUiController.getCurrentTab();
772 if (currentTab != null){
773 if (TextUtils.isEmpty(currentTab.getUrl())) {
774 mFaviconTile.setVisibility(View.GONE);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700775 }
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700776 setDisplayTitle(currentTab.getTitle(), currentTab.getUrl());
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700777 }
778 mUiController.setWindowDimming(0.0f);
779 }
780
Enrico Ros1f5a0952014-11-18 20:15:48 -0800781 break;
782 case STATE_HIGHLIGHTED:
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700783 mFaviconTile.setVisibility(View.GONE);
jrizzolia62318b2015-09-08 21:44:50 +0200784 mSeparator.setVisibility(View.GONE);
Sagar Dhawan84ef4442015-07-29 12:08:10 -0700785 mClearButton.setVisibility(View.VISIBLE);
Enrico Ros1f5a0952014-11-18 20:15:48 -0800786 mMore.setVisibility(View.GONE);
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700787 if (mUiController != null) {
788 mUiController.setWindowDimming(0.75f);
Pankaj Garg8d2e98f2015-08-07 10:01:49 -0700789 if (mTrustLevel == SiteTileView.TRUST_TRUSTED) {
790 Tab currentTab = mUiController.getCurrentTab();
791 if (currentTab != null) {
792 mUrlInput.setText(currentTab.getUrl(), false);
793 mUrlInput.selectAll();
794 }
795 }
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700796 }
Enrico Ros1f5a0952014-11-18 20:15:48 -0800797 break;
798 case STATE_EDITED:
Sagar Dhawan84ef4442015-07-29 12:08:10 -0700799 if (TextUtils.isEmpty(mUrlInput.getText()) &&
800 mUiController != null &&
801 mUiController.supportsVoice()) {
802 mVoiceButton.setVisibility(View.VISIBLE);
803 }
804 else {
805 mClearButton.setVisibility(View.VISIBLE);
806 }
Pankaj Garg66f8cef2015-07-07 17:29:03 -0700807 mFaviconTile.setVisibility(View.GONE);
Enrico Ros1f5a0952014-11-18 20:15:48 -0800808 mMore.setVisibility(View.GONE);
809 break;
810 }
811 }
812
813 public boolean isMenuShowing() {
814 return mOverflowMenuShowing;
815 }
816
817
818 @Override
819 public void onDismiss(PopupMenu popupMenu) {
820 if (popupMenu == mPopupMenu) {
821 onMenuHidden();
822 }
823 }
824
825 private void onMenuHidden() {
826 mOverflowMenuShowing = false;
Enrico Ros1f5a0952014-11-18 20:15:48 -0800827 }
828
829
830 @Override
831 public boolean onMenuItemClick(MenuItem item) {
832 return mUiController.onOptionsItemSelected(item);
833 }
John Reck0f602f32011-07-07 15:38:43 -0700834}