/WebVox/src/com/marvin/webvox/BrowserActivity.java
Java | 1668 lines | 1094 code | 158 blank | 416 comment | 277 complexity | 7061e778ccf953fd7c2ebe0b8df697e4 MD5 | raw file
Possible License(s): GPL-3.0, Apache-2.0
- /*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package com.marvin.webvox;
- import com.marvin.webvox.R;
- //import com.google.android.googleapps.IGoogleLoginService;
- //import com.google.android.googlelogin.GoogleLoginServiceConstants;
- import android.app.Activity;
- import android.app.AlertDialog;
- import android.app.ProgressDialog;
- import android.app.SearchManager;
- import android.content.ActivityNotFoundException;
- import android.content.BroadcastReceiver;
- import android.content.ComponentName;
- import android.content.ContentResolver;
- import android.content.ContentUris;
- import android.content.ContentValues;
- import android.content.Context;
- import android.content.DialogInterface;
- import android.content.Intent;
- import android.content.IntentFilter;
- import android.content.ServiceConnection;
- import android.content.DialogInterface.OnCancelListener;
- import android.content.pm.PackageInfo;
- import android.content.pm.PackageManager;
- import android.content.pm.ResolveInfo;
- import android.content.res.AssetManager;
- import android.content.res.Configuration;
- import android.content.res.Resources;
- import android.database.Cursor;
- import android.database.sqlite.SQLiteDatabase;
- import android.database.sqlite.SQLiteException;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.Canvas;
- import android.graphics.DrawFilter;
- import android.graphics.Paint;
- import android.graphics.PaintFlagsDrawFilter;
- import android.graphics.Picture;
- import android.graphics.PixelFormat;
- import android.graphics.Rect;
- import android.graphics.drawable.Drawable;
- import android.hardware.SensorListener;
- import android.hardware.SensorManager;
- import android.net.ConnectivityManager;
- import android.net.NetworkInfo;
- import android.net.Uri;
- //import android.net.WebAddress;
- //import android.net.http.EventHandler;
- import android.net.http.SslCertificate;
- //import android.net.http.SslError;
- import android.os.AsyncTask;
- import android.os.Bundle;
- import android.os.Debug;
- import android.os.Environment;
- import android.os.Handler;
- import android.os.IBinder;
- import android.os.Message;
- import android.os.PowerManager;
- import android.os.Process;
- import android.os.RemoteException;
- //import android.os.ServiceManager;
- import android.os.SystemClock;
- import android.provider.Browser;
- import android.provider.ContactsContract;
- import android.provider.ContactsContract.Intents.Insert;
- //import android.provider.Downloads;
- import android.provider.MediaStore;
- //import android.text.IClipboard;
- import android.speech.tts.TextToSpeech;
- import android.text.TextUtils;
- import android.text.format.DateFormat;
- //import android.text.util.Regex;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.ContextMenu;
- import android.view.Gravity;
- import android.view.KeyEvent;
- import android.view.LayoutInflater;
- import android.view.Menu;
- import android.view.MenuInflater;
- import android.view.MenuItem;
- import android.view.View;
- import android.view.ViewGroup;
- import android.view.Window;
- import android.view.WindowManager;
- import android.view.ContextMenu.ContextMenuInfo;
- import android.view.MenuItem.OnMenuItemClickListener;
- import android.view.animation.AlphaAnimation;
- import android.view.animation.Animation;
- import android.view.animation.AnimationSet;
- import android.view.animation.DecelerateInterpolator;
- import android.view.animation.ScaleAnimation;
- import android.view.animation.TranslateAnimation;
- import android.webkit.CookieManager;
- import android.webkit.CookieSyncManager;
- import android.webkit.DownloadListener;
- import android.webkit.GeolocationPermissions;
- import android.webkit.HttpAuthHandler;
- //import android.webkit.PluginManager;
- import android.webkit.SslErrorHandler;
- import android.webkit.URLUtil;
- //import android.webkit.ValueCallback;
- import android.webkit.WebChromeClient;
- //import android.webkit.WebChromeClient.CustomViewCallback;
- import android.webkit.WebHistoryItem;
- import android.webkit.WebIconDatabase;
- import android.webkit.WebStorage;
- import android.webkit.WebView;
- import android.webkit.WebViewClient;
- import android.widget.EditText;
- import android.widget.FrameLayout;
- import android.widget.LinearLayout;
- import android.widget.TextView;
- import android.widget.Toast;
- import java.io.BufferedOutputStream;
- import java.io.ByteArrayOutputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.net.MalformedURLException;
- import java.net.URI;
- import java.net.URISyntaxException;
- import java.net.URL;
- import java.net.URLEncoder;
- import java.text.ParseException;
- import java.util.Date;
- import java.util.Enumeration;
- import java.util.HashMap;
- import java.util.LinkedList;
- import java.util.List;
- import java.util.Vector;
- import java.util.regex.Matcher;
- import java.util.regex.Pattern;
- import java.util.zip.ZipEntry;
- import java.util.zip.ZipFile;
- public class BrowserActivity extends Activity
- implements View.OnCreateContextMenuListener,
- DownloadListener {
- /* Define some aliases to make these debugging flags easier to refer to.
- * This file imports android.provider.Browser, so we can't just refer to "Browser.DEBUG".
- */
- private final static boolean DEBUG = com.marvin.webvox.Browser.DEBUG;
- private final static boolean LOGV_ENABLED = com.marvin.webvox.Browser.LOGV_ENABLED;
- private final static boolean LOGD_ENABLED = com.marvin.webvox.Browser.LOGD_ENABLED;
- // private IGoogleLoginService mGls = null;
- private ServiceConnection mGlsConnection = null;
- private SensorManager mSensorManager = null;
- // These are single-character shortcuts for searching popular sources.
- private static final int SHORTCUT_INVALID = 0;
- private static final int SHORTCUT_GOOGLE_SEARCH = 1;
- private static final int SHORTCUT_WIKIPEDIA_SEARCH = 2;
- private static final int SHORTCUT_DICTIONARY_SEARCH = 3;
- private static final int SHORTCUT_GOOGLE_MOBILE_LOCAL_SEARCH = 4;
- /* Whitelisted webpages
- private static HashSet<String> sWhiteList;
- static {
- sWhiteList = new HashSet<String>();
- sWhiteList.add("cnn.com/");
- sWhiteList.add("espn.go.com/");
- sWhiteList.add("nytimes.com/");
- sWhiteList.add("engadget.com/");
- sWhiteList.add("yahoo.com/");
- sWhiteList.add("msn.com/");
- sWhiteList.add("amazon.com/");
- sWhiteList.add("consumerist.com/");
- sWhiteList.add("google.com/m/news");
- }
- */
- private void setupHomePage() {
- final Runnable getAccount = new Runnable() {
- public void run() {
- // Lower priority
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- // get the default home page
- String homepage = mSettings.getHomePage();
- try {
- // if (mGls == null) return;
- if (!homepage.startsWith("http://www.google.")) return;
- if (homepage.indexOf('?') == -1) return;
- // String hostedUser = mGls.getAccount(GoogleLoginServiceConstants.PREFER_HOSTED);
- // String googleUser = mGls.getAccount(GoogleLoginServiceConstants.REQUIRE_GOOGLE);
- // three cases:
- //
- // hostedUser == googleUser
- // The device has only a google account
- //
- // hostedUser != googleUser
- // The device has a hosted account and a google account
- //
- // hostedUser != null, googleUser == null
- // The device has only a hosted account (so far)
- // developers might have no accounts at all
- // if (hostedUser == null) return;
- // if (googleUser == null || !hostedUser.equals(googleUser)) {
- // String domain = hostedUser.substring(hostedUser.lastIndexOf('@')+1);
- // homepage = homepage.replace("?", "/a/" + domain + "?");
- // }
- // } catch (RemoteException ignore) {
- // Login service died; carry on
- } catch (RuntimeException ignore) {
- // Login service died; carry on
- } finally {
- finish(homepage);
- }
- }
- private void finish(final String homepage) {
- mHandler.post(new Runnable() {
- public void run() {
- mSettings.setHomePage(BrowserActivity.this, homepage);
- resumeAfterCredentials();
- // as this is running in a separate thread,
- // BrowserActivity's onDestroy() may have been called,
- // which also calls unbindService().
- if (mGlsConnection != null) {
- // we no longer need to keep GLS open
- unbindService(mGlsConnection);
- mGlsConnection = null;
- }
- } });
- } };
- final boolean[] done = { false };
- // Open a connection to the Google Login Service. The first
- // time the connection is established, set up the homepage depending on
- // the account in a background thread.
- mGlsConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- // mGls = IGoogleLoginService.Stub.asInterface(service);
- if (done[0] == false) {
- done[0] = true;
- Thread account = new Thread(getAccount);
- account.setName("GLSAccount");
- account.start();
- }
- }
- public void onServiceDisconnected(ComponentName className) {
- // mGls = null;
- }
- };
- // bindService(GoogleLoginServiceConstants.SERVICE_INTENT,
- // mGlsConnection, Context.BIND_AUTO_CREATE);
- }
- private static class ClearThumbnails extends AsyncTask<File, Void, Void> {
- @Override
- public Void doInBackground(File... files) {
- if (files != null) {
- for (File f : files) {
- if (!f.delete()) {
- Log.e(LOGTAG, f.getPath() + " was not deleted");
- }
- }
- }
- return null;
- }
- }
- /**
- * This layout holds everything you see below the status bar, including the
- * error console, the custom view container, and the webviews.
- */
- private FrameLayout mBrowserFrameLayout;
- @Override public void onCreate(Bundle icicle) {
- mTts = new TextToSpeech(this, null);
- scriptdb = new ScriptDatabase(this);
- scriptdb.onUpgrade(scriptdb.getWritableDatabase(), -10, 10);
-
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, this + " onStart");
- }
- super.onCreate(icicle);
- // test the browser in OpenGL
- // requestWindowFeature(Window.FEATURE_OPENGL);
- setDefaultKeyMode(DEFAULT_KEYS_SEARCH_LOCAL);
- mResolver = getContentResolver();
- // If this was a web search request, pass it on to the default web
- // search provider and finish this activity.
- if (handleWebSearchIntent(getIntent())) {
- finish();
- return;
- }
- //
- // start MASF proxy service
- //
- //Intent proxyServiceIntent = new Intent();
- //proxyServiceIntent.setComponent
- // (new ComponentName(
- // "com.android.masfproxyservice",
- // "com.android.masfproxyservice.MasfProxyService"));
- //startService(proxyServiceIntent, null);
- mSecLockIcon = Resources.getSystem().getDrawable(
- android.R.drawable.ic_secure);
- mMixLockIcon = Resources.getSystem().getDrawable(
- android.R.drawable.ic_partial_secure);
- // FrameLayout frameLayout = (FrameLayout) getWindow().getDecorView()
- // .findViewById(com.android.internal.R.id.content);
-
-
- mBrowserFrameLayout = (FrameLayout) LayoutInflater.from(this)
- .inflate(R.layout.custom_screen, null);
- mContentView = (FrameLayout) mBrowserFrameLayout.findViewById(
- R.id.main_content);
- mErrorConsoleContainer = (LinearLayout) mBrowserFrameLayout
- .findViewById(R.id.error_console);
- mCustomViewContainer = (FrameLayout) mBrowserFrameLayout
- .findViewById(R.id.fullscreen_custom_content);
- //frameLayout.addView(mBrowserFrameLayout, COVER_SCREEN_PARAMS);
-
- setContentView(mBrowserFrameLayout);
-
- mTitleBar = new TitleBar(this);
- // Create the tab control and our initial tab
- mTabControl = new TabControl(this);
- // Open the icon database and retain all the bookmark urls for favicons
- retainIconsOnStartup();
- // Keep a settings instance handy.
- mSettings = BrowserSettings.getInstance();
- mSettings.setTabControl(mTabControl);
- mSettings.loadFromDb(this);
- PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
- mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Browser");
- /* enables registration for changes in network status from
- http stack */
- mNetworkStateChangedFilter = new IntentFilter();
- mNetworkStateChangedFilter.addAction(
- ConnectivityManager.CONNECTIVITY_ACTION);
- mNetworkStateIntentReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(
- ConnectivityManager.CONNECTIVITY_ACTION)) {
- boolean noConnectivity = intent.getBooleanExtra(
- ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
- onNetworkToggle(!noConnectivity);
- }
- }
- };
- IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
- filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
- filter.addDataScheme("package");
- mPackageInstallationReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- final String packageName = intent.getData()
- .getSchemeSpecificPart();
- final boolean replacing = intent.getBooleanExtra(
- Intent.EXTRA_REPLACING, false);
- if (Intent.ACTION_PACKAGE_REMOVED.equals(action) && replacing) {
- // if it is replacing, refreshPlugins() when adding
- return;
- }
- PackageManager pm = BrowserActivity.this.getPackageManager();
- PackageInfo pkgInfo = null;
- try {
- pkgInfo = pm.getPackageInfo(packageName,
- PackageManager.GET_PERMISSIONS);
- } catch (PackageManager.NameNotFoundException e) {
- return;
- }
- if (pkgInfo != null) {
- String permissions[] = pkgInfo.requestedPermissions;
- if (permissions == null) {
- return;
- }
- boolean permissionOk = false;
- /*
- for (String permit : permissions) {
- if (PluginManager.PLUGIN_PERMISSION.equals(permit)) {
- permissionOk = true;
- break;
- }
- }
- if (permissionOk) {
- PluginManager.getInstance(BrowserActivity.this)
- .refreshPlugins(
- Intent.ACTION_PACKAGE_ADDED
- .equals(action));
- }
- */
- }
- }
- };
- registerReceiver(mPackageInstallationReceiver, filter);
- if (!mTabControl.restoreState(icicle)) {
- // clear up the thumbnail directory if we can't restore the state as
- // none of the files in the directory are referenced any more.
- new ClearThumbnails().execute(
- mTabControl.getThumbnailDir().listFiles());
- // there is no quit on Android. But if we can't restore the state,
- // we can treat it as a new Browser, remove the old session cookies.
- CookieManager.getInstance().removeSessionCookie();
- final Intent intent = getIntent();
- final Bundle extra = intent.getExtras();
- // Create an initial tab.
- // If the intent is ACTION_VIEW and data is not null, the Browser is
- // invoked to view the content by another application. In this case,
- // the tab will be close when exit.
- UrlData urlData = getUrlDataFromIntent(intent);
- final TabControl.Tab t = mTabControl.createNewTab(
- Intent.ACTION_VIEW.equals(intent.getAction()) &&
- intent.getData() != null,
- intent.getStringExtra(Browser.EXTRA_APPLICATION_ID), urlData.mUrl);
- mTabControl.setCurrentTab(t);
- attachTabToContentView(t);
- WebView webView = t.getWebView();
- if (extra != null) {
- int scale = extra.getInt(Browser.INITIAL_ZOOM_LEVEL, 0);
- if (scale > 0 && scale <= 1000) {
- webView.setInitialScale(scale);
- }
- }
- // If we are not restoring from an icicle, then there is a high
- // likely hood this is the first run. So, check to see if the
- // homepage needs to be configured and copy any plugins from our
- // asset directory to the data partition.
- if ((extra == null || !extra.getBoolean("testing"))
- && !mSettings.isLoginInitialized()) {
- setupHomePage();
- }
- if (urlData.isEmpty()) {
- if (mSettings.isLoginInitialized()) {
- webView.loadUrl(mSettings.getHomePage());
- } else {
- waitForCredentials();
- }
- } else {
- if (extra != null) {
- // urlData.setPostData(extra
- // .getByteArray(Browser.EXTRA_POST_DATA));
- }
- urlData.loadIn(webView);
- }
- } else {
- // TabControl.restoreState() will create a new tab even if
- // restoring the state fails.
- attachTabToContentView(mTabControl.getCurrentTab());
- }
- // Read JavaScript flags if it exists.
- String jsFlags = mSettings.getJsFlags();
- if (jsFlags.trim().length() != 0) {
- // mTabControl.getCurrentWebView().setJsFlags(jsFlags);
- }
- }
- @Override
- protected void onNewIntent(Intent intent) {
- TabControl.Tab current = mTabControl.getCurrentTab();
- // When a tab is closed on exit, the current tab index is set to -1.
- // Reset before proceed as Browser requires the current tab to be set.
- if (current == null) {
- // Try to reset the tab in case the index was incorrect.
- current = mTabControl.getTab(0);
- if (current == null) {
- // No tabs at all so just ignore this intent.
- return;
- }
- mTabControl.setCurrentTab(current);
- attachTabToContentView(current);
- resetTitleAndIcon(current.getWebView());
- }
- final String action = intent.getAction();
- final int flags = intent.getFlags();
- if (Intent.ACTION_MAIN.equals(action) ||
- (flags & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) {
- // just resume the browser
- return;
- }
- if (Intent.ACTION_VIEW.equals(action)
- || Intent.ACTION_SEARCH.equals(action)
- || MediaStore.INTENT_ACTION_MEDIA_SEARCH.equals(action)
- || Intent.ACTION_WEB_SEARCH.equals(action)) {
- // If this was a search request (e.g. search query directly typed into the address bar),
- // pass it on to the default web search provider.
- if (handleWebSearchIntent(intent)) {
- return;
- }
- UrlData urlData = getUrlDataFromIntent(intent);
- if (urlData.isEmpty()) {
- urlData = new UrlData(mSettings.getHomePage());
- }
- // urlData.setPostData(intent
- // .getByteArrayExtra(Browser.EXTRA_POST_DATA));
- final String appId = intent
- .getStringExtra(Browser.EXTRA_APPLICATION_ID);
- if (Intent.ACTION_VIEW.equals(action)
- && !getPackageName().equals(appId)
- && (flags & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
- TabControl.Tab appTab = mTabControl.getTabFromId(appId);
- if (appTab != null) {
- Log.i(LOGTAG, "Reusing tab for " + appId);
- // Dismiss the subwindow if applicable.
- dismissSubWindow(appTab);
- // Since we might kill the WebView, remove it from the
- // content view first.
- removeTabFromContentView(appTab);
- // Recreate the main WebView after destroying the old one.
- // If the WebView has the same original url and is on that
- // page, it can be reused.
- boolean needsLoad =
- mTabControl.recreateWebView(appTab, urlData.mUrl);
- if (current != appTab) {
- switchToTab(mTabControl.getTabIndex(appTab));
- if (needsLoad) {
- urlData.loadIn(appTab.getWebView());
- }
- } else {
- // If the tab was the current tab, we have to attach
- // it to the view system again.
- attachTabToContentView(appTab);
- if (needsLoad) {
- urlData.loadIn(appTab.getWebView());
- }
- }
- return;
- } else {
- // No matching application tab, try to find a regular tab
- // with a matching url.
- appTab = mTabControl.findUnusedTabWithUrl(urlData.mUrl);
- if (appTab != null) {
- if (current != appTab) {
- switchToTab(mTabControl.getTabIndex(appTab));
- }
- // Otherwise, we are already viewing the correct tab.
- } else {
- // if FLAG_ACTIVITY_BROUGHT_TO_FRONT flag is on, the url
- // will be opened in a new tab unless we have reached
- // MAX_TABS. Then the url will be opened in the current
- // tab. If a new tab is created, it will have "true" for
- // exit on close.
- openTabAndShow(urlData, true, appId);
- }
- }
- } else {
- if ("about:debug".equals(urlData.mUrl)) {
- mSettings.toggleDebugSettings();
- return;
- }
- // Get rid of the subwindow if it exists
- dismissSubWindow(current);
- urlData.loadIn(current.getWebView());
- }
- }
- }
- private int parseUrlShortcut(String url) {
- if (url == null) return SHORTCUT_INVALID;
- // FIXME: quick search, need to be customized by setting
- if (url.length() > 2 && url.charAt(1) == ' ') {
- switch (url.charAt(0)) {
- case 'g': return SHORTCUT_GOOGLE_SEARCH;
- case 'w': return SHORTCUT_WIKIPEDIA_SEARCH;
- case 'd': return SHORTCUT_DICTIONARY_SEARCH;
- case 'l': return SHORTCUT_GOOGLE_MOBILE_LOCAL_SEARCH;
- }
- }
- return SHORTCUT_INVALID;
- }
- /**
- * Launches the default web search activity with the query parameters if the given intent's data
- * are identified as plain search terms and not URLs/shortcuts.
- * @return true if the intent was handled and web search activity was launched, false if not.
- */
- private boolean handleWebSearchIntent(Intent intent) {
- if (intent == null) return false;
- String url = null;
- final String action = intent.getAction();
- if (Intent.ACTION_VIEW.equals(action)) {
- Uri data = intent.getData();
- if (data != null) url = data.toString();
- } else if (Intent.ACTION_SEARCH.equals(action)
- || MediaStore.INTENT_ACTION_MEDIA_SEARCH.equals(action)
- || Intent.ACTION_WEB_SEARCH.equals(action)) {
- url = intent.getStringExtra(SearchManager.QUERY);
- }
- return handleWebSearchRequest(url, intent.getBundleExtra(SearchManager.APP_DATA),
- intent.getStringExtra(SearchManager.EXTRA_DATA_KEY));
- }
- /**
- * Launches the default web search activity with the query parameters if the given url string
- * was identified as plain search terms and not URL/shortcut.
- * @return true if the request was handled and web search activity was launched, false if not.
- */
- private boolean handleWebSearchRequest(String inUrl, Bundle appData, String extraData) {
- if (inUrl == null) return false;
- // In general, we shouldn't modify URL from Intent.
- // But currently, we get the user-typed URL from search box as well.
- String url = fixUrl(inUrl).trim();
- // URLs and site specific search shortcuts are handled by the regular flow of control, so
- // return early.
- // if (Regex.WEB_URL_PATTERN.matcher(url).matches() ||
- if ( ACCEPTED_URI_SCHEMA.matcher(url).matches()
- || parseUrlShortcut(url) != SHORTCUT_INVALID) {
- return false;
- }
- Browser.updateVisitedHistory(mResolver, url, false);
- Browser.addSearchUrl(mResolver, url);
- Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
- intent.addCategory(Intent.CATEGORY_DEFAULT);
- intent.putExtra(SearchManager.QUERY, url);
- if (appData != null) {
- intent.putExtra(SearchManager.APP_DATA, appData);
- }
- if (extraData != null) {
- intent.putExtra(SearchManager.EXTRA_DATA_KEY, extraData);
- }
- intent.putExtra(Browser.EXTRA_APPLICATION_ID, getPackageName());
- startActivity(intent);
- return true;
- }
- private UrlData getUrlDataFromIntent(Intent intent) {
- String url = null;
- if (intent != null) {
- final String action = intent.getAction();
- if (Intent.ACTION_VIEW.equals(action)) {
- url = smartUrlFilter(intent.getData());
- if (url != null && url.startsWith("content:")) {
- /* Append mimetype so webview knows how to display */
- String mimeType = intent.resolveType(getContentResolver());
- if (mimeType != null) {
- url += "?" + mimeType;
- }
- }
- // if ("inline:".equals(url)) {
- // return new InlinedUrlData(
- // intent.getStringExtra(Browser.EXTRA_INLINE_CONTENT),
- // intent.getType(),
- // intent.getStringExtra(Browser.EXTRA_INLINE_ENCODING),
- // intent.getStringExtra(Browser.EXTRA_INLINE_FAILURL));
- // }
- } else if (Intent.ACTION_SEARCH.equals(action)
- || MediaStore.INTENT_ACTION_MEDIA_SEARCH.equals(action)
- || Intent.ACTION_WEB_SEARCH.equals(action)) {
- url = intent.getStringExtra(SearchManager.QUERY);
- if (url != null) {
- mLastEnteredUrl = url;
- // Don't add Urls, just search terms.
- // Urls will get added when the page is loaded.
- // if (!Regex.WEB_URL_PATTERN.matcher(url).matches()) {
- // Browser.updateVisitedHistory(mResolver, url, false);
- // }
- // In general, we shouldn't modify URL from Intent.
- // But currently, we get the user-typed URL from search box as well.
- url = fixUrl(url);
- url = smartUrlFilter(url);
- String searchSource = "&source=android-" + GOOGLE_SEARCH_SOURCE_SUGGEST + "&";
- if (url.contains(searchSource)) {
- String source = null;
- final Bundle appData = intent.getBundleExtra(SearchManager.APP_DATA);
- // if (appData != null) {
- // source = appData.getString(SearchManager.SOURCE);
- // }
- if (TextUtils.isEmpty(source)) {
- source = GOOGLE_SEARCH_SOURCE_UNKNOWN;
- }
- url = url.replace(searchSource, "&source=android-"+source+"&");
- }
- }
- }
- }
- return new UrlData(url);
- }
- /* package */ static String fixUrl(String inUrl) {
- // FIXME: Converting the url to lower case
- // duplicates functionality in smartUrlFilter().
- // However, changing all current callers of fixUrl to
- // call smartUrlFilter in addition may have unwanted
- // consequences, and is deferred for now.
- int colon = inUrl.indexOf(':');
- boolean allLower = true;
- for (int index = 0; index < colon; index++) {
- char ch = inUrl.charAt(index);
- if (!Character.isLetter(ch)) {
- break;
- }
- allLower &= Character.isLowerCase(ch);
- if (index == colon - 1 && !allLower) {
- inUrl = inUrl.substring(0, colon).toLowerCase()
- + inUrl.substring(colon);
- }
- }
- if (inUrl.startsWith("http://") || inUrl.startsWith("https://"))
- return inUrl;
- if (inUrl.startsWith("http:") ||
- inUrl.startsWith("https:")) {
- if (inUrl.startsWith("http:/") || inUrl.startsWith("https:/")) {
- inUrl = inUrl.replaceFirst("/", "//");
- } else inUrl = inUrl.replaceFirst(":", "://");
- }
- return inUrl;
- }
- /**
- * Looking for the pattern like this
- *
- * *
- * * *
- * *** * *******
- * * *
- * * *
- * *
- */
- private final SensorListener mSensorListener = new SensorListener() {
- private long mLastGestureTime;
- private float[] mPrev = new float[3];
- private float[] mPrevDiff = new float[3];
- private float[] mDiff = new float[3];
- private float[] mRevertDiff = new float[3];
- public void onSensorChanged(int sensor, float[] values) {
- boolean show = false;
- float[] diff = new float[3];
- for (int i = 0; i < 3; i++) {
- diff[i] = values[i] - mPrev[i];
- if (Math.abs(diff[i]) > 1) {
- show = true;
- }
- if ((diff[i] > 1.0 && mDiff[i] < 0.2)
- || (diff[i] < -1.0 && mDiff[i] > -0.2)) {
- // start track when there is a big move, or revert
- mRevertDiff[i] = mDiff[i];
- mDiff[i] = 0;
- } else if (diff[i] > -0.2 && diff[i] < 0.2) {
- // reset when it is flat
- mDiff[i] = mRevertDiff[i] = 0;
- }
- mDiff[i] += diff[i];
- mPrevDiff[i] = diff[i];
- mPrev[i] = values[i];
- }
- if (false) {
- // only shows if we think the delta is big enough, in an attempt
- // to detect "serious" moves left/right or up/down
- Log.d("BrowserSensorHack", "sensorChanged " + sensor + " ("
- + values[0] + ", " + values[1] + ", " + values[2] + ")"
- + " diff(" + diff[0] + " " + diff[1] + " " + diff[2]
- + ")");
- Log.d("BrowserSensorHack", " mDiff(" + mDiff[0] + " "
- + mDiff[1] + " " + mDiff[2] + ")" + " mRevertDiff("
- + mRevertDiff[0] + " " + mRevertDiff[1] + " "
- + mRevertDiff[2] + ")");
- }
- long now = android.os.SystemClock.uptimeMillis();
- if (now - mLastGestureTime > 1000) {
- mLastGestureTime = 0;
- float y = mDiff[1];
- float z = mDiff[2];
- float ay = Math.abs(y);
- float az = Math.abs(z);
- float ry = mRevertDiff[1];
- float rz = mRevertDiff[2];
- float ary = Math.abs(ry);
- float arz = Math.abs(rz);
- boolean gestY = ay > 2.5f && ary > 1.0f && ay > ary;
- boolean gestZ = az > 3.5f && arz > 1.0f && az > arz;
- if ((gestY || gestZ) && !(gestY && gestZ)) {
- WebView view = mTabControl.getCurrentWebView();
- if (view != null) {
- if (gestZ) {
- if (z < 0) {
- view.zoomOut();
- } else {
- view.zoomIn();
- }
- } else {
- view.flingScroll(0, Math.round(y * 100));
- }
- }
- mLastGestureTime = now;
- }
- }
- }
- public void onAccuracyChanged(int sensor, int accuracy) {
- // TODO Auto-generated method stub
- }
- };
- @Override protected void onResume() {
- super.onResume();
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "BrowserActivity.onResume: this=" + this);
- }
- if (!mActivityInPause) {
- Log.e(LOGTAG, "BrowserActivity is already resumed.");
- return;
- }
- mTabControl.resumeCurrentTab();
- mActivityInPause = false;
- resumeWebViewTimers();
- if (mWakeLock.isHeld()) {
- mHandler.removeMessages(RELEASE_WAKELOCK);
- mWakeLock.release();
- }
- if (mCredsDlg != null) {
- if (!mHandler.hasMessages(CANCEL_CREDS_REQUEST)) {
- // In case credential request never comes back
- mHandler.sendEmptyMessageDelayed(CANCEL_CREDS_REQUEST, 6000);
- }
- }
- registerReceiver(mNetworkStateIntentReceiver,
- mNetworkStateChangedFilter);
- WebView.enablePlatformNotifications();
- if (mSettings.doFlick()) {
- if (mSensorManager == null) {
- mSensorManager = (SensorManager) getSystemService(
- Context.SENSOR_SERVICE);
- }
- mSensorManager.registerListener(mSensorListener,
- SensorManager.SENSOR_ACCELEROMETER,
- SensorManager.SENSOR_DELAY_FASTEST);
- } else {
- mSensorManager = null;
- }
- }
- /**
- * Since the actual title bar is embedded in the WebView, and removing it
- * would change its appearance, create a temporary title bar to go at
- * the top of the screen while the menu is open.
- */
- private TitleBar mFakeTitleBar;
- /**
- * Holder for the fake title bar. It will have a foreground shadow, as well
- * as a white background, so the fake title bar looks like the real one.
- */
- private ViewGroup mFakeTitleBarHolder;
- /**
- * Layout parameters for the fake title bar within mFakeTitleBarHolder
- */
- private FrameLayout.LayoutParams mFakeTitleBarParams
- = new FrameLayout.LayoutParams(
- ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
- /**
- * Keeps track of whether the options menu is open. This is important in
- * determining whether to show or hide the title bar overlay.
- */
- private boolean mOptionsMenuOpen;
- /**
- * Only meaningful when mOptionsMenuOpen is true. This variable keeps track
- * of whether the configuration has changed. The first onMenuOpened call
- * after a configuration change is simply a reopening of the same menu
- * (i.e. mIconView did not change).
- */
- private boolean mConfigChanged;
- /**
- * Whether or not the options menu is in its smaller, icon menu form. When
- * true, we want the title bar overlay to be up. When false, we do not.
- * Only meaningful if mOptionsMenuOpen is true.
- */
- private boolean mIconView;
- @Override
- public boolean onMenuOpened(int featureId, Menu menu) {
- if (Window.FEATURE_OPTIONS_PANEL == featureId) {
- if (mOptionsMenuOpen) {
- if (mConfigChanged) {
- // We do not need to make any changes to the state of the
- // title bar, since the only thing that happened was a
- // change in orientation
- mConfigChanged = false;
- } else {
- if (mIconView) {
- // Switching the menu to expanded view, so hide the
- // title bar.
- hideFakeTitleBar();
- mIconView = false;
- } else {
- // Switching the menu back to icon view, so show the
- // title bar once again.
- showFakeTitleBar();
- mIconView = true;
- }
- }
- } else {
- // The options menu is closed, so open it, and show the title
- showFakeTitleBar();
- mOptionsMenuOpen = true;
- mConfigChanged = false;
- mIconView = true;
- }
- }
- return true;
- }
- /**
- * Special class used exclusively for the shadow drawn underneath the fake
- * title bar. The shadow does not need to be drawn if the WebView
- * underneath is scrolled to the top, because it will draw directly on top
- * of the embedded shadow.
- */
- private static class Shadow extends View {
- private WebView mWebView;
- public Shadow(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
- public void setWebView(WebView view) {
- mWebView = view;
- }
- @Override
- public void draw(Canvas canvas) {
- // In general onDraw is the method to override, but we care about
- // whether or not the background gets drawn, which happens in draw()
- if (mWebView == null || mWebView.getScrollY() > getHeight()) {
- super.draw(canvas);
- }
- // Need to invalidate so that if the scroll position changes, we
- // still draw as appropriate.
- invalidate();
- }
- }
- private void showFakeTitleBar() {
- final View decor = getWindow().peekDecorView();
- if (mFakeTitleBar == null && mActiveTabsPage == null
- && !mActivityInPause && decor != null
- && decor.getWindowToken() != null) {
- Rect visRect = new Rect();
- if (!mBrowserFrameLayout.getGlobalVisibleRect(visRect)) {
- if (LOGD_ENABLED) {
- Log.d(LOGTAG, "showFakeTitleBar visRect failed");
- }
- return;
- }
- final WebView webView = getTopWindow();
- mFakeTitleBar = new TitleBar(this);
- mFakeTitleBar.setTitleAndUrl(null, webView.getUrl());
- mFakeTitleBar.setProgress(webView.getProgress());
- mFakeTitleBar.setFavicon(webView.getFavicon());
- updateLockIconToLatest();
- WindowManager manager
- = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
- // Add the title bar to the window manager so it can receive touches
- // while the menu is up
- WindowManager.LayoutParams params
- = new WindowManager.LayoutParams(
- ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT,
- WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
- PixelFormat.TRANSLUCENT);
- params.gravity = Gravity.TOP;
- WebView mainView = mTabControl.getCurrentWebView();
- boolean atTop = mainView != null && mainView.getScrollY() == 0;
- params.windowAnimations = atTop ? 0 : R.style.TitleBar;
- // XXX : Without providing an offset, the fake title bar will be
- // placed underneath the status bar. Use the global visible rect
- // of mBrowserFrameLayout to determine the bottom of the status bar
- params.y = visRect.top;
- // Add a holder for the title bar. It also holds a shadow to show
- // below the title bar.
- if (mFakeTitleBarHolder == null) {
- mFakeTitleBarHolder = (ViewGroup) LayoutInflater.from(this)
- .inflate(R.layout.title_bar_bg, null);
- }
- Shadow shadow = (Shadow) mFakeTitleBarHolder.findViewById(
- R.id.shadow);
- shadow.setWebView(mainView);
- mFakeTitleBarHolder.addView(mFakeTitleBar, 0, mFakeTitleBarParams);
- manager.addView(mFakeTitleBarHolder, params);
- }
- }
- @Override
- public void onOptionsMenuClosed(Menu menu) {
- mOptionsMenuOpen = false;
- if (!mInLoad) {
- hideFakeTitleBar();
- } else if (!mIconView) {
- // The page is currently loading, and we are in expanded mode, so
- // we were not showing the menu. Show it once again. It will be
- // removed when the page finishes.
- showFakeTitleBar();
- }
- }
- private void hideFakeTitleBar() {
- if (mFakeTitleBar == null) return;
- WindowManager.LayoutParams params = (WindowManager.LayoutParams)
- mFakeTitleBarHolder.getLayoutParams();
- WebView mainView = mTabControl.getCurrentWebView();
- // Although we decided whether or not to animate based on the current
- // scroll position, the scroll position may have changed since the
- // fake title bar was displayed. Make sure it has the appropriate
- // animation/lack thereof before removing.
- params.windowAnimations = mainView != null && mainView.getScrollY() == 0
- ? 0 : R.style.TitleBar;
- WindowManager manager
- = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
- manager.updateViewLayout(mFakeTitleBarHolder, params);
- mFakeTitleBarHolder.removeView(mFakeTitleBar);
- manager.removeView(mFakeTitleBarHolder);
- mFakeTitleBar = null;
- }
- /**
- * Special method for the fake title bar to call when displaying its context
- * menu, since it is in its own Window, and its parent does not show a
- * context menu.
- */
- /* package */ void showTitleBarContextMenu() {
- if (null == mTitleBar.getParent()) {
- return;
- }
- openContextMenu(mTitleBar);
- }
- /**
- * onSaveInstanceState(Bundle map)
- * onSaveInstanceState is called right before onStop(). The map contains
- * the saved state.
- */
- @Override protected void onSaveInstanceState(Bundle outState) {
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "BrowserActivity.onSaveInstanceState: this=" + this);
- }
- // the default implementation requires each view to have an id. As the
- // browser handles the state itself and it doesn't use id for the views,
- // don't call the default implementation. Otherwise it will trigger the
- // warning like this, "couldn't save which view has focus because the
- // focused view XXX has no id".
- // Save all the tabs
- mTabControl.saveState(outState);
- }
- @Override protected void onPause() {
- super.onPause();
- if (mActivityInPause) {
- Log.e(LOGTAG, "BrowserActivity is already paused.");
- return;
- }
- mTabControl.pauseCurrentTab();
- mActivityInPause = true;
- if (mTabControl.getCurrentIndex() >= 0 && !pauseWebViewTimers()) {
- mWakeLock.acquire();
- mHandler.sendMessageDelayed(mHandler
- .obtainMessage(RELEASE_WAKELOCK), WAKELOCK_TIMEOUT);
- }
- // Clear the credentials toast if it is up
- if (mCredsDlg != null && mCredsDlg.isShowing()) {
- mCredsDlg.dismiss();
- }
- mCredsDlg = null;
- // FIXME: This removes the active tabs page and resets the menu to
- // MAIN_MENU. A better solution might be to do this work in onNewIntent
- // but then we would need to save it in onSaveInstanceState and restore
- // it in onCreate/onRestoreInstanceState
- if (mActiveTabsPage != null) {
- removeActiveTabPage(true);
- }
- cancelStopToast();
- // unregister network state listener
- unregisterReceiver(mNetworkStateIntentReceiver);
- WebView.disablePlatformNotifications();
- if (mSensorManager != null) {
- mSensorManager.unregisterListener(mSensorListener);
- }
- }
- @Override protected void onDestroy() {
- if (LOGV_ENABLED) {
- Log.v(LOGTAG, "BrowserActivity.onDestroy: this=" + this);
- }
- super.onDestroy();
- if (mTabControl == null) return;
- // Remove the current tab and sub window
- TabControl.Tab t = mTabControl.getCurrentTab();
- if (t != null) {
- dismissSubWindow(t);
- removeTabFromContentView(t);
- }
- // Destroy all the tabs
- mTabControl.destroy();
- WebIconDatabase.getInstance().close();
- if (mGlsConnection != null) {
- unbindService(mGlsConnection);
- mGlsConnection = null;
- }
- //
- // stop MASF proxy service
- //
- //Intent proxyServiceIntent = new Intent();
- //proxyServiceIntent.setComponent
- // (new ComponentName(
- // "com.android.masfproxyservice",
- // "com.android.masfproxyservice.MasfProxyService"));
- //stopService(proxyServiceIntent);
- unregisterReceiver(mPackageInstallationReceiver);
- }
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- mConfigChanged = true;
- super.onConfigurationChanged(newConfig);
- if (mPageInfoDialog != null) {
- mPageInfoDialog.dismiss();
- showPageInfo(
- mPageInfoView,
- mPageInfoFromShowSSLCertificateOnError.booleanValue());
- }
- if (mSSLCertificateDialog != null) {
- mSSLCertificateDialog.dismiss();
- showSSLCertificate(
- mSSLCertificateView);
- }
- /*
- if (mSSLCertificateOnErrorDialog != null) {
- mSSLCertificateOnErrorDialog.dismiss();
- showSSLCertificateOnError(
- mSSLCertificateOnErrorView,
- mSSLCertificateOnErrorHandler,
- mSSLCertificateOnErrorError);
- }
- */
- if (mHttpAuthenticationDialog != null) {
- String title = "";
- // String title = ((TextView) mHttpAuthenticationDialog
- // .findViewById(com.android.internal.R.id.alertTitle)).getText()
- // .toString();
- String name = ((TextView) mHttpAuthenticationDialog
- .findViewById(R.id.username_edit)).getText().toString();
- String password = ((TextView) mHttpAuthenticationDialog
- .findViewById(R.id.password_edit)).getText().toString();
- int focusId = mHttpAuthenticationDialog.getCurrentFocus()
- .getId();
- mHttpAuthenticationDialog.dismiss();
- showHttpAuthentication(mHttpAuthHandler, null, null, title,
- name, password, focusId);
- }
- if (mFindDialog != null && mFindDialog.isShowing()) {
- mFindDialog.onConfigurationChanged(newConfig);
- }
- }
- @Override public void onLowMemory() {
- super.onLowMemory();
- mTabControl.freeMemory();
- }
- private boolean resumeWebViewTimers() {
- if ((!mActivityInPause && !mPageStarted) ||
- (mActivityInPause && mPageStarted)) {
- CookieSyncManager.getInstance().startSync();
- WebView w = mTabControl.getCurrentWebView();
- if (w != null) {
- w.resumeTimers();
- }
- return true;
- } else {
- return false;
- }
- }
- private boolean pauseWebViewTimers() {
- if (mActivityInPause && !mPageStarted) {
- CookieSyncManager.getInstance().stopSync();
- WebView w = mTabControl.getCurrentWebView();
- if (w != null) {
- w.pauseTimers();
- }
- return true;
- } else {
- return false;
- }
- }
- // FIXME: Do we want to call this when loading google for the first time?
- /*
- * This function is called when we are launching for the first time. We
- * are waiting for the login credentials before loading Google home
- * pages. This way the user will be logged in straight away.
- */
- private void waitForCredentials() {
- // Show a toast
- mCredsDlg = new ProgressDialog(this);
- mCredsDlg.setIndeterminate(true);
- mCredsDlg.setMessage(getText(R.string.retrieving_creds_dlg_msg));
- // If the user cancels the operation, then cancel the Google
- // Credentials request.
- mCredsDlg.setCancelMessage(mHandler.obtainMessage(CANCEL_CREDS_REQUEST));
- mCredsDlg.show();
- // We set a timeout for the retrieval of credentials in onResume()
- // as that is when we have freed up some CPU time to get
- // the login credentials.
- }
- /*
- * If we have received the credentials or we have timed out and we are
- * showing the credentials dialog, then it is time to move on.
- */
- private void resumeAfterCredentials() {
- if (mCredsDlg == null) {
- return;
- }
- // Clear the toast
- if (mCredsDlg.isShowing()) {
- mCredsDlg.dismiss();
- }
- mCredsDlg = null;
- // Clear any pending timeout
- mHandler.removeMessages(CANCEL_CREDS_REQUEST);
- // Load the page
- WebView w = mTabControl.getCurrentWebView();
- if (w != null) {
- w.loadUrl(mSettings.getHomePage());
- }
- // Update the settings, need to do this last as it can take a moment
- // to persist the settings. In the mean time we could be loading
- // content.
- mSettings.setLoginInitialized(this);
- }
- // Open the icon database and retain all the icons for visited sites.
- private void retainIconsOnStartup() {
- /*
- final WebIconDatabase db = WebIconDatabase.getInstance();
- db.open(getDir("icons", 0).getPath());
- try {
- Cursor c = Browser.getAllBookmarks(mResolver);
- if (!c.moveToFirst()) {
- c.deactivate();
- return;
- }
- int urlIndex = c.getColumnIndex(Browser.BookmarkColumns.URL);
- do {
- String url = c.getString(urlIndex);
- db.retainIconForPageUrl(url);
- } while (c.moveToNext());
- c.deactivate();
- } catch (IllegalStateException e) {
- Log.e(LOGTAG, "retainIconsOnStartup", e);
- }
- */
- }
- // Helper method for getting the top window.
- WebView getTopWindow() {
- return mTabControl.getCurrentTopWebView();
- }
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.browser, menu);
- mMenu = menu;
- updateInLoadMenuItems();
- return true;
- }
- /**
- * As the menu can be open when loading state changes
- * we must manually update the state of the stop/reload menu
- * item
- */
- private void updateInLoadMenuItems() {
- if (mMenu == null) {
- return;
- }
- MenuItem src = mInLoad ?
- mMenu.findItem(R.id.stop_menu_id):
- mMenu.findItem(R.id.reload_menu_id);
- MenuItem dest = mMenu.findItem(R.id.stop_reload_menu_id);
- dest.setIcon(src.getIcon());
- dest.setTitle(src.getTitle());
- }
- @Override
- public boolean onContextItemSelected(MenuItem item) {
- // chording is not an issue with context menus, but we use the same
- // options selector, so set mCanChord to true so we can access them.
- mCanChord = true;
- int id = item.getItemId();
- switch (id) {
- // For the context menu from the title bar
- case R.id.title_bar_share_page_url:
- case R.id.title_bar_copy_page_url:
- WebView mainView = mTabControl.getCurrentWebView();
- if (null == mainView) {
- return false;
- }
- if (id == R.id.title_bar_share_page_url) {
- Browser.sendString(this, mainView.getUrl());
- } else {
- copy(mainView.getUrl());
- }
- break;
- // -- Browser context menu
- case R.id.open_context_menu_id:
- case R.id.open_newtab_context_menu_id:
- case R.id.bookmark_context_menu_id:
- case R.id.save_link_context_menu_id:
- case R.id.share_link_context_menu_id:
- case R.id.copy_link_context_menu_id:
- final WebView webView = getTopWindow();
- if (null == webView) {
- return false;
- }
- final HashMap hrefMap = new HashMap();
- hrefMap.put("webview", webView);
- final Message msg = mHandler.obtainMessage(
- FOCUS_NODE_HREF, id, 0, hrefMap);
- webView.requestFocusNodeHref(msg);
- break;
- default:
- // For other context menus
- return onOptionsItemSelected(item);
- }
- mCanChord = false;
- return true;
- }
- private Bundle createGoogleSearchSourceBundle(String source) {
- Bundle bundle = new Bundle();
- // bundle.putString(SearchManager.SOURCE, source);
- return bundle;
- }
- /**
- * Overriding this to insert a local information bundle
- */
- @Override
- public boolean onSearchRequested() {
- if (mOptionsMenuOpen) closeOptionsMenu();
- String url = (getTopWindow() == null) ? null : getTopWindow().getUrl();
- startSearch(mSettings.getHomePage().equals(url) ? null : url, true,
- createGoogleSearchSourceBundle(GOOGLE_SEARCH_SOURCE_SEARCHKEY), false);
- return true;
- }
- @Override
- public void startSearch(String initialQuery, boolean selectInitialQuery,
- Bundle appSearchData, boolean globalSearch) {
- if (appSearchData == null) {
- appSearchData = createGoogleSearchSourceBundle(GOOGLE_SEARCH_SOURCE_TYPE);
- }
- super.startSearch(initialQuery, selectInitialQuery, appSearchData, globalSearch);
- }
- /**
- * Switch tabs. Called by the TitleBarSet when sliding the title bar
- * results in changing tabs.
- * @param index Index of the tab to change to, as defined by
- * mTabControl.getTabIndex(Tab t).
- * @return boolean True if we successfully switched to a different tab. If
- * the indexth tab is null, or if that tab is the same as
- * the current one, return false.
- */
- /* package */ boolean switchToTab(int index) {
- TabControl.Tab tab = mTabControl.getTab(index);
- TabControl.Tab currentTab = mTabControl.getCurrentTab();
- if (tab == null || tab == currentTab) {
- return false;
- }
- if (currentTab != null) {
- // currentTab may be null if it was just removed. In that case,
- // we do not need to remove it
- removeTabFromContentView(currentTab);
- }
- mTabControl.setCurrentTab(tab);
- attachTabToContentView(tab);
- resetTitleIconAndProgress();
- updateLockIconToLatest();
- return true;
- }
- /* package */ TabControl.Tab openTabToHomePage() {
- return openTabAndShow(mSettings.getHomePage(), false, null);
- }
- /* package */ void closeCurrentWindow() {
- final TabControl.Tab current = mTabControl.getCurrentTab();
- if (mTabControl.getTabCount() == 1) {
- // This is the last tab. Open a new one, with the home
- // page and close the current one.
- TabControl.Tab newTab = openTabToHomePage();
- closeTab(current);
- return;
- }
- final TabControl.Tab parent = current.getParentTab();
- int indexToShow = -1;
- if (parent != null) {
- indexToShow = mTabControl.getTabIndex(parent);
- } else {
- final int currentIndex = mTabControl.getCurrentIndex();
- // Try to move to the tab to the right
- indexToShow = currentIndex + 1;
- if (indexToShow > mTabControl.getTabCount() - 1) {
- // Try to move to the tab to the left
- indexToShow = currentIndex - 1;
- }
- }
- if (switchToTab(indexToShow)) {
- // Close window
- closeTab(current);
- }
- }
- private ActiveTabsPage mActiveTabsPage;
- /**
- * Remove the active tabs page.
- * @param needToAttach If true, the active tabs page did not attach a tab
- * to the content view, so we need to do that here.
- */
- /* package */ void removeActiveTabPage(boolean needToAttach) {
- mContentView.removeView(mActiveTabsPage);
- mActiveTabsPage = null;
- mMenuState = R.id.MAIN_MENU;
- if (needToAttach) {
- attachTabToContentView(mTabControl.getCurrentTab());
- }
- getTopWindow().requestFocus();
- }
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (!mCanChord) {
- // The user has already fired a shortcut with this hold down of the
- // menu key.
- return false;
- }
- if (null == getTopWindow()) {
- return false;
- }
- if (mMenuIsDown) {
- // The shortcut action consumes the MENU. Even if it is still down,
- // it won't trigger the next shortcut action. In the case of the
- // shortcut action triggering a new activity, like Bookmarks, we
- // won't get onKeyUp for MENU. So it is important to reset it here.
- mMenuIsDown = false;
- }
- switch (item.getItemId()) {
- // -- Main menu
- case R.id.new_tab_menu_id:
- openTabToHomePage();
- break;
- case R.id.goto_menu_id:
- onSearchRequested();
- break;
- case R.id.bookmarks_menu_id:
- bookmarksOrHistoryPicker(false);
- break;
- case R.id.active_tabs_menu_id:
- mActiveTabsPage = new ActiveTabsPage(this, mTabControl);
- removeTabFromContentView(mTabControl.getCurrentTab());
- hideFakeTitleBar();
- mContentView.addView(mActiveTabsPage, COVER_SCREEN_PARAMS);
- mActiveTabsPage.requestFocus();
- mMenuState = EMPTY_MENU;
- break;
- case R.id.add_bookmark_menu_id:
- Intent i = new Intent(BrowserActivity.this,
- AddBookmarkPage.class);
- WebView w = getTopWindow();
- i.putExtra("url", w.getUrl());
- i.putExtra("title", w.getTitle());
- // i.putExtra("touch_icon_url", w.getTouchIconUrl());
- i.putExtra("thumbnail", createScreenshot(w));
- startActivity(i);
- break;
- case R.id.stop_reload_menu_id:
- if (mInLoad) {
- stopLoading();
- } else {
- getTopWindow().reload();
- }
- break;
- case R.id.back_menu_id:
- getTopWindow().goBack();
- break;
- case R.id.forward_menu_id:
- getTopWindow().goForward();
- break;
- case R.id.close_menu_id:
- // Close the subwindow if it exists.
- if (mTabControl.getCurrentSubWindow() != null) {
- dismissSubWindow(mTabControl.getCurrentTab());
- break;
- }
- closeCurrentWindow();
- break;
- case R.id.homepage_menu_id:
- TabControl.Tab current = mTabControl.getCurrentTab();
- if (current != null) {
- dismissSubWindow(current);
- current.getWebView().loadUrl(mSettings.getHomePage());
- }
- break;
- case R.id.preferences_menu_id:
- Intent intent = new Intent(this,
- BrowserPreferencesPage.class);
- startActivityForResult(intent, PREFERENCES_PAGE);
- break;
-
- case R.id.scripts_menu_id:
- Intent scriptsIntent = new Intent(this,
- ScriptListActivity.class);
- startActivity(scriptsIntent);
- break;
- case R.id.find_menu_id:
- if (null == mFindDialog) {
- mFindDialog = new FindDialog(this);
- }
- mFindDialog.setWebView(getTopWindow());
- mFindDialog.show();
- mMenuState = EMPTY_MENU;
- break;
- case R.id.select_text_id:
- // getTopWindow().emulateShiftHeld();
- break;
- case R.id.page_info_menu_id:
- showPageInfo(mTabControl.getCurrentTab(), false);
- break;
- case R.id.classic_history_menu_id:
- bookmarksOrHistoryPicker(true);
- break;
- case R.id.share_page_menu_id:
- // Browser.sendString(this, getTopWindow().getUrl(),
- // getText(R.string.choosertitle_sharevia).toString());
- break;
- case R.id.dump_nav_menu_id:
- getTopWindow().debugDump();
- break;
- case R.id.zoom_in_menu_id:
- getTopWindow().zoomIn();
- break;
- case R.id.zoom_out_menu_id:
- getTopWindow().zoomOut();
- break;
- case R.id.view_downloads_menu_id:
- viewDownloads(null);
- break;
- case R.id.window_one_menu_id:
- case R.id.window_two_menu_id:
- case R.id.window_three_menu_id:
- case R.id.window_four_menu_id:
- case R.id.window_five_menu_id:
-