2011-11-18 18:28:17 +00:00
|
|
|
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
2012-05-21 11:12:37 +00:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2011-11-18 18:28:17 +00:00
|
|
|
|
|
|
|
package org.mozilla.gecko;
|
|
|
|
|
2012-10-30 20:27:33 +00:00
|
|
|
import org.mozilla.gecko.background.announcements.AnnouncementsBroadcastService;
|
2012-01-31 22:13:33 +00:00
|
|
|
import org.mozilla.gecko.db.BrowserDB;
|
2012-10-20 00:36:21 +00:00
|
|
|
import org.mozilla.gecko.db.BrowserContract;
|
2012-01-31 14:40:58 +00:00
|
|
|
import org.mozilla.gecko.gfx.Layer;
|
2011-11-18 18:28:17 +00:00
|
|
|
import org.mozilla.gecko.gfx.LayerView;
|
2012-04-27 20:04:47 +00:00
|
|
|
import org.mozilla.gecko.gfx.PluginLayer;
|
2012-07-10 21:12:53 +00:00
|
|
|
import org.mozilla.gecko.gfx.PointUtils;
|
|
|
|
import org.mozilla.gecko.ui.PanZoomController;
|
2012-08-02 18:10:31 +00:00
|
|
|
import org.mozilla.gecko.util.GeckoAsyncTask;
|
2012-08-21 11:20:26 +00:00
|
|
|
import org.mozilla.gecko.util.GeckoBackgroundThread;
|
2012-08-03 00:13:40 +00:00
|
|
|
import org.mozilla.gecko.util.GeckoEventListener;
|
2012-08-07 21:48:13 +00:00
|
|
|
import org.mozilla.gecko.util.GeckoEventResponder;
|
2012-08-20 22:29:22 +00:00
|
|
|
import org.mozilla.gecko.GeckoAccessibility;
|
2012-08-31 13:31:29 +00:00
|
|
|
import org.mozilla.gecko.updater.UpdateServiceHelper;
|
|
|
|
import org.mozilla.gecko.updater.UpdateService;
|
2011-11-18 18:28:17 +00:00
|
|
|
|
2012-07-28 00:54:28 +00:00
|
|
|
import org.json.JSONArray;
|
|
|
|
import org.json.JSONException;
|
|
|
|
import org.json.JSONObject;
|
2011-11-18 18:28:17 +00:00
|
|
|
|
2012-07-28 00:54:28 +00:00
|
|
|
import android.app.Activity;
|
|
|
|
import android.app.AlertDialog;
|
2012-09-19 17:37:35 +00:00
|
|
|
import android.content.ComponentName;
|
2012-07-28 00:54:28 +00:00
|
|
|
import android.content.Context;
|
|
|
|
import android.content.DialogInterface;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.content.SharedPreferences;
|
2012-09-19 17:37:35 +00:00
|
|
|
import android.content.pm.ActivityInfo;
|
2012-07-28 00:54:28 +00:00
|
|
|
import android.content.pm.ApplicationInfo;
|
|
|
|
import android.content.pm.PackageInfo;
|
|
|
|
import android.content.pm.PackageManager;
|
|
|
|
import android.content.pm.PackageManager.NameNotFoundException;
|
|
|
|
import android.content.pm.ResolveInfo;
|
|
|
|
import android.content.pm.ServiceInfo;
|
|
|
|
import android.content.pm.Signature;
|
|
|
|
import android.content.res.Configuration;
|
|
|
|
import android.graphics.Bitmap;
|
|
|
|
import android.graphics.BitmapFactory;
|
|
|
|
import android.graphics.Color;
|
|
|
|
import android.graphics.PointF;
|
|
|
|
import android.graphics.Rect;
|
2011-11-18 18:28:17 +00:00
|
|
|
import android.graphics.drawable.BitmapDrawable;
|
2012-07-28 00:54:28 +00:00
|
|
|
import android.hardware.Sensor;
|
|
|
|
import android.hardware.SensorEvent;
|
|
|
|
import android.hardware.SensorEventListener;
|
|
|
|
import android.location.Location;
|
|
|
|
import android.location.LocationListener;
|
|
|
|
import android.net.Uri;
|
|
|
|
import android.os.Build;
|
|
|
|
import android.os.Bundle;
|
|
|
|
import android.os.Environment;
|
|
|
|
import android.os.Handler;
|
|
|
|
import android.os.PowerManager;
|
|
|
|
import android.os.StrictMode;
|
|
|
|
import android.os.SystemClock;
|
|
|
|
import android.text.TextUtils;
|
2012-07-28 00:53:54 +00:00
|
|
|
import android.util.AttributeSet;
|
|
|
|
import android.util.DisplayMetrics;
|
|
|
|
import android.util.Log;
|
|
|
|
import android.util.SparseBooleanArray;
|
2012-07-28 00:54:28 +00:00
|
|
|
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.MotionEvent;
|
|
|
|
import android.view.SurfaceHolder;
|
|
|
|
import android.view.SurfaceView;
|
|
|
|
import android.view.View;
|
|
|
|
import android.view.ViewConfiguration;
|
|
|
|
import android.view.ViewGroup;
|
|
|
|
import android.view.Window;
|
|
|
|
import android.view.WindowManager;
|
2012-08-20 22:29:22 +00:00
|
|
|
|
2012-04-27 17:35:47 +00:00
|
|
|
import android.view.accessibility.AccessibilityEvent;
|
2012-07-28 00:53:54 +00:00
|
|
|
import android.view.accessibility.AccessibilityManager;
|
2012-07-28 00:54:28 +00:00
|
|
|
import android.widget.AbsoluteLayout;
|
|
|
|
import android.widget.FrameLayout;
|
|
|
|
import android.widget.LinearLayout;
|
|
|
|
import android.widget.ListView;
|
|
|
|
import android.widget.RelativeLayout;
|
|
|
|
import android.widget.TextView;
|
|
|
|
import android.widget.Toast;
|
2012-07-28 00:53:54 +00:00
|
|
|
|
|
|
|
import java.io.BufferedReader;
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
|
|
import java.io.File;
|
|
|
|
import java.io.FileOutputStream;
|
|
|
|
import java.io.FileReader;
|
|
|
|
import java.io.IOException;
|
|
|
|
import java.io.OutputStream;
|
|
|
|
import java.lang.reflect.Method;
|
|
|
|
import java.net.HttpURLConnection;
|
|
|
|
import java.net.URL;
|
|
|
|
import java.nio.ByteBuffer;
|
|
|
|
import java.util.ArrayList;
|
2012-09-19 17:38:29 +00:00
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.Comparator;
|
2012-07-28 00:53:54 +00:00
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.Iterator;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Map;
|
|
|
|
import java.util.Set;
|
|
|
|
import java.util.concurrent.CopyOnWriteArrayList;
|
|
|
|
import java.util.regex.Matcher;
|
|
|
|
import java.util.regex.Pattern;
|
2011-11-18 18:28:17 +00:00
|
|
|
|
|
|
|
abstract public class GeckoApp
|
2012-04-03 18:58:01 +00:00
|
|
|
extends GeckoActivity
|
|
|
|
implements GeckoEventListener, SensorEventListener, LocationListener,
|
2012-08-06 16:30:12 +00:00
|
|
|
Tabs.OnTabsChangedListener, GeckoEventResponder
|
2012-06-11 22:18:40 +00:00
|
|
|
{
|
2011-11-18 18:28:17 +00:00
|
|
|
private static final String LOGTAG = "GeckoApp";
|
|
|
|
|
2012-01-24 14:03:28 +00:00
|
|
|
public static enum StartupMode {
|
|
|
|
NORMAL,
|
|
|
|
NEW_VERSION,
|
|
|
|
NEW_PROFILE
|
|
|
|
}
|
|
|
|
|
2012-10-01 20:57:03 +00:00
|
|
|
private static enum StartupAction {
|
|
|
|
NORMAL, /* normal application start */
|
|
|
|
URL, /* launched with a passed URL */
|
|
|
|
PREFETCH, /* launched with a passed URL that we prefetch */
|
|
|
|
REDIRECTOR /* launched with a passed URL in our redirect list */
|
|
|
|
}
|
|
|
|
|
2011-11-30 03:54:07 +00:00
|
|
|
public static final String ACTION_ALERT_CLICK = "org.mozilla.gecko.ACTION_ALERT_CLICK";
|
|
|
|
public static final String ACTION_ALERT_CLEAR = "org.mozilla.gecko.ACTION_ALERT_CLEAR";
|
2012-08-22 15:37:08 +00:00
|
|
|
public static final String ACTION_ALERT_CALLBACK = "org.mozilla.gecko.ACTION_ALERT_CALLBACK";
|
2012-10-11 17:10:49 +00:00
|
|
|
public static final String ACTION_ANNOUNCEMENTS_PREF = "org.mozilla.gecko.ANNOUNCEMENTS_PREF";
|
2012-06-18 17:03:03 +00:00
|
|
|
public static final String ACTION_WEBAPP_PREFIX = "org.mozilla.gecko.WEBAPP";
|
2011-11-30 03:54:07 +00:00
|
|
|
public static final String ACTION_DEBUG = "org.mozilla.gecko.DEBUG";
|
|
|
|
public static final String ACTION_BOOKMARK = "org.mozilla.gecko.BOOKMARK";
|
2012-01-10 07:50:56 +00:00
|
|
|
public static final String ACTION_LOAD = "org.mozilla.gecko.LOAD";
|
2012-03-08 18:25:44 +00:00
|
|
|
public static final String ACTION_INIT_PW = "org.mozilla.gecko.INIT_PW";
|
2012-10-19 18:15:06 +00:00
|
|
|
public static final String ACTION_WIDGET = "org.mozilla.gecko.WIDGET";
|
2012-08-21 11:20:26 +00:00
|
|
|
public static final String SAVED_STATE_IN_BACKGROUND = "inBackground";
|
2012-10-09 18:26:33 +00:00
|
|
|
public static final String SAVED_STATE_PRIVATE_SESSION = "privateSession";
|
2012-08-21 11:20:26 +00:00
|
|
|
|
|
|
|
public static final String PREFS_NAME = "GeckoApp";
|
|
|
|
public static final String PREFS_OOM_EXCEPTION = "OOMException";
|
|
|
|
public static final String PREFS_WAS_STOPPED = "wasStopped";
|
2011-11-18 18:28:17 +00:00
|
|
|
|
2012-10-29 23:34:29 +00:00
|
|
|
static public final int RESTORE_NONE = 0;
|
|
|
|
static public final int RESTORE_OOM = 1;
|
|
|
|
static public final int RESTORE_CRASH = 2;
|
|
|
|
|
2012-01-24 14:03:28 +00:00
|
|
|
StartupMode mStartupMode = null;
|
2012-06-13 05:47:52 +00:00
|
|
|
protected LinearLayout mMainLayout;
|
|
|
|
protected RelativeLayout mGeckoLayout;
|
2012-06-11 22:18:40 +00:00
|
|
|
public View getView() { return mGeckoLayout; }
|
2012-07-13 14:17:03 +00:00
|
|
|
public SurfaceView cameraView;
|
2011-11-18 18:28:17 +00:00
|
|
|
public static GeckoApp mAppContext;
|
2012-07-13 14:17:03 +00:00
|
|
|
public boolean mDOMFullScreen = false;
|
2012-09-19 17:35:35 +00:00
|
|
|
protected MenuPresenter mMenuPresenter;
|
2012-06-11 22:18:40 +00:00
|
|
|
protected MenuPanel mMenuPanel;
|
2012-06-13 20:28:00 +00:00
|
|
|
protected Menu mMenu;
|
2012-06-29 22:49:48 +00:00
|
|
|
private static GeckoThread sGeckoThread;
|
2012-04-13 19:31:16 +00:00
|
|
|
public Handler mMainHandler;
|
2012-02-26 04:22:40 +00:00
|
|
|
private GeckoProfile mProfile;
|
2012-06-15 03:12:06 +00:00
|
|
|
public static int mOrientation;
|
2012-07-13 14:20:34 +00:00
|
|
|
private boolean mIsRestoringActivity;
|
2012-08-06 16:30:12 +00:00
|
|
|
private String mCurrentResponse = "";
|
2012-09-29 02:52:11 +00:00
|
|
|
public static boolean sIsUsingCustomProfile = false;
|
2011-11-30 04:58:39 +00:00
|
|
|
|
2012-06-13 21:12:15 +00:00
|
|
|
private PromptService mPromptService;
|
2012-07-18 10:03:14 +00:00
|
|
|
private Favicons mFavicons;
|
2012-07-19 20:16:44 +00:00
|
|
|
private TextSelection mTextSelection;
|
2011-11-22 20:48:22 +00:00
|
|
|
|
2012-07-28 06:31:54 +00:00
|
|
|
protected DoorHangerPopup mDoorHangerPopup;
|
|
|
|
protected FormAssistPopup mFormAssistPopup;
|
|
|
|
protected TabsPanel mTabsPanel;
|
2011-11-22 20:48:22 +00:00
|
|
|
|
2012-10-12 11:57:07 +00:00
|
|
|
protected LayerView mLayerView;
|
2012-07-13 14:17:03 +00:00
|
|
|
private AbsoluteLayout mPluginContainer;
|
2011-11-18 18:28:17 +00:00
|
|
|
|
2012-06-07 02:39:36 +00:00
|
|
|
private FullScreenHolder mFullScreenPluginContainer;
|
2012-05-30 16:10:49 +00:00
|
|
|
private View mFullScreenPluginView;
|
|
|
|
|
2012-06-07 02:39:01 +00:00
|
|
|
private HashMap<String, PowerManager.WakeLock> mWakeLocks = new HashMap<String, PowerManager.WakeLock>();
|
|
|
|
|
2012-10-29 23:34:29 +00:00
|
|
|
protected int mRestoreMode = RESTORE_NONE;
|
2012-08-22 15:37:14 +00:00
|
|
|
protected boolean mInitialized = false;
|
2012-10-01 20:57:00 +00:00
|
|
|
protected Telemetry.Timer mAboutHomeStartupTimer;
|
|
|
|
private Telemetry.Timer mJavaUiStartupTimer;
|
|
|
|
private Telemetry.Timer mGeckoReadyStartupTimer;
|
2012-02-14 21:30:15 +00:00
|
|
|
|
2012-10-09 18:26:33 +00:00
|
|
|
private String mPrivateBrowsingSession;
|
|
|
|
|
2011-11-22 06:56:55 +00:00
|
|
|
public enum LaunchState {Launching, WaitForDebugger,
|
2011-11-18 18:28:17 +00:00
|
|
|
Launched, GeckoRunning, GeckoExiting};
|
|
|
|
private static LaunchState sLaunchState = LaunchState.Launching;
|
|
|
|
|
2012-06-18 17:03:03 +00:00
|
|
|
abstract public int getLayout();
|
2012-07-23 20:08:48 +00:00
|
|
|
abstract public boolean hasTabsSideBar();
|
2012-06-18 17:03:03 +00:00
|
|
|
abstract protected String getDefaultProfileName();
|
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
public static boolean checkLaunchState(LaunchState checkState) {
|
|
|
|
synchronized(sLaunchState) {
|
|
|
|
return sLaunchState == checkState;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void setLaunchState(LaunchState setState) {
|
|
|
|
synchronized(sLaunchState) {
|
|
|
|
sLaunchState = setState;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// if mLaunchState is equal to checkState this sets mLaunchState to setState
|
|
|
|
// and return true. Otherwise we return false.
|
|
|
|
static boolean checkAndSetLaunchState(LaunchState checkState, LaunchState setState) {
|
|
|
|
synchronized(sLaunchState) {
|
|
|
|
if (sLaunchState != checkState)
|
|
|
|
return false;
|
|
|
|
sLaunchState = setState;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-11 22:18:40 +00:00
|
|
|
void toggleChrome(final Boolean aShow) { }
|
|
|
|
|
|
|
|
void focusChrome() { }
|
|
|
|
|
|
|
|
public void onTabChanged(Tab tab, Tabs.TabEvents msg, Object data) {
|
2012-07-06 18:19:19 +00:00
|
|
|
// When a tab is closed, it is always unselected first.
|
|
|
|
// When a tab is unselected, another tab is always selected first.
|
2012-06-11 22:18:40 +00:00
|
|
|
switch(msg) {
|
2012-07-06 18:19:19 +00:00
|
|
|
case UNSELECTED:
|
|
|
|
hidePlugins(tab);
|
|
|
|
break;
|
|
|
|
|
2012-06-11 22:18:40 +00:00
|
|
|
case LOCATION_CHANGE:
|
2012-07-06 18:19:19 +00:00
|
|
|
// We only care about location change for the selected tab.
|
|
|
|
if (!Tabs.getInstance().isSelectedTab(tab))
|
|
|
|
break;
|
|
|
|
// Fall through...
|
|
|
|
case SELECTED:
|
|
|
|
invalidateOptionsMenu();
|
2012-06-11 22:18:40 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void refreshChrome() { }
|
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
public static final String PLUGIN_ACTION = "android.webkit.PLUGIN";
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A plugin that wish to be loaded in the WebView must provide this permission
|
|
|
|
* in their AndroidManifest.xml.
|
|
|
|
*/
|
|
|
|
public static final String PLUGIN_PERMISSION = "android.webkit.permission.PLUGIN";
|
|
|
|
|
|
|
|
private static final String PLUGIN_SYSTEM_LIB = "/system/lib/plugins/";
|
|
|
|
|
|
|
|
private static final String PLUGIN_TYPE = "type";
|
|
|
|
private static final String TYPE_NATIVE = "native";
|
|
|
|
public ArrayList<PackageInfo> mPackageInfoCache = new ArrayList<PackageInfo>();
|
|
|
|
|
2012-07-26 04:44:11 +00:00
|
|
|
// Returns null if plugins are blocked on the device.
|
2011-11-18 18:28:17 +00:00
|
|
|
String[] getPluginDirectories() {
|
2012-05-03 21:14:05 +00:00
|
|
|
|
2012-06-05 18:52:48 +00:00
|
|
|
// An awful hack to detect Tegra devices. Easiest way to do it without spinning up a EGL context.
|
|
|
|
boolean isTegra = (new File("/system/lib/hw/gralloc.tegra.so")).exists();
|
|
|
|
if (isTegra) {
|
|
|
|
// disable Flash on Tegra ICS with CM9 and other custom firmware (bug 736421)
|
|
|
|
File vfile = new File("/proc/version");
|
|
|
|
FileReader vreader = null;
|
|
|
|
try {
|
|
|
|
if (vfile.canRead()) {
|
|
|
|
vreader = new FileReader(vfile);
|
|
|
|
String version = new BufferedReader(vreader).readLine();
|
|
|
|
if (version.indexOf("CM9") != -1 ||
|
|
|
|
version.indexOf("cyanogen") != -1 ||
|
|
|
|
version.indexOf("Nova") != -1)
|
|
|
|
{
|
|
|
|
Log.w(LOGTAG, "Blocking plugins because of Tegra 2 + unofficial ICS bug (bug 736421)");
|
2012-07-26 04:44:11 +00:00
|
|
|
return null;
|
2012-06-05 18:52:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (IOException ex) {
|
|
|
|
// nothing
|
|
|
|
} finally {
|
|
|
|
try {
|
|
|
|
if (vreader != null) {
|
|
|
|
vreader.close();
|
|
|
|
}
|
|
|
|
} catch (IOException ex) {
|
|
|
|
// nothing
|
|
|
|
}
|
|
|
|
}
|
2012-05-03 21:14:05 +00:00
|
|
|
}
|
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
ArrayList<String> directories = new ArrayList<String>();
|
2012-01-24 17:16:48 +00:00
|
|
|
PackageManager pm = mAppContext.getPackageManager();
|
2011-11-18 18:28:17 +00:00
|
|
|
List<ResolveInfo> plugins = pm.queryIntentServices(new Intent(PLUGIN_ACTION),
|
|
|
|
PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
|
|
|
|
|
|
|
|
synchronized(mPackageInfoCache) {
|
|
|
|
|
|
|
|
// clear the list of existing packageInfo objects
|
|
|
|
mPackageInfoCache.clear();
|
|
|
|
|
|
|
|
|
|
|
|
for (ResolveInfo info : plugins) {
|
|
|
|
|
|
|
|
// retrieve the plugin's service information
|
|
|
|
ServiceInfo serviceInfo = info.serviceInfo;
|
|
|
|
if (serviceInfo == null) {
|
2012-10-23 16:45:40 +00:00
|
|
|
Log.w(LOGTAG, "Ignoring bad plugin.");
|
2011-11-18 18:28:17 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2011-11-24 11:29:15 +00:00
|
|
|
// Blacklist HTC's flash lite.
|
|
|
|
// See bug #704516 - We're not quite sure what Flash Lite does,
|
|
|
|
// but loading it causes Flash to give errors and fail to draw.
|
|
|
|
if (serviceInfo.packageName.equals("com.htc.flashliteplugin")) {
|
|
|
|
Log.w(LOGTAG, "Skipping HTC's flash lite plugin");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
|
2012-10-23 16:45:40 +00:00
|
|
|
// Retrieve information from the plugin's manifest.
|
2011-11-18 18:28:17 +00:00
|
|
|
PackageInfo pkgInfo;
|
|
|
|
try {
|
|
|
|
pkgInfo = pm.getPackageInfo(serviceInfo.packageName,
|
|
|
|
PackageManager.GET_PERMISSIONS
|
|
|
|
| PackageManager.GET_SIGNATURES);
|
|
|
|
} catch (Exception e) {
|
|
|
|
Log.w(LOGTAG, "Can't find plugin: " + serviceInfo.packageName);
|
|
|
|
continue;
|
|
|
|
}
|
2012-10-23 16:45:40 +00:00
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
if (pkgInfo == null) {
|
2012-10-23 16:45:40 +00:00
|
|
|
Log.w(LOGTAG, "Not loading plugin: " + serviceInfo.packageName + ". Could not load package information.");
|
2011-11-18 18:28:17 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* find the location of the plugin's shared library. The default
|
|
|
|
* is to assume the app is either a user installed app or an
|
|
|
|
* updated system app. In both of these cases the library is
|
|
|
|
* stored in the app's data directory.
|
|
|
|
*/
|
|
|
|
String directory = pkgInfo.applicationInfo.dataDir + "/lib";
|
|
|
|
final int appFlags = pkgInfo.applicationInfo.flags;
|
|
|
|
final int updatedSystemFlags = ApplicationInfo.FLAG_SYSTEM |
|
|
|
|
ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
|
2012-10-23 16:45:40 +00:00
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
// preloaded system app with no user updates
|
|
|
|
if ((appFlags & updatedSystemFlags) == ApplicationInfo.FLAG_SYSTEM) {
|
|
|
|
directory = PLUGIN_SYSTEM_LIB + pkgInfo.packageName;
|
|
|
|
}
|
|
|
|
|
|
|
|
// check if the plugin has the required permissions
|
|
|
|
String permissions[] = pkgInfo.requestedPermissions;
|
|
|
|
if (permissions == null) {
|
2012-10-23 16:45:40 +00:00
|
|
|
Log.w(LOGTAG, "Not loading plugin: " + serviceInfo.packageName + ". Does not have required permission.");
|
2011-11-18 18:28:17 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
boolean permissionOk = false;
|
|
|
|
for (String permit : permissions) {
|
|
|
|
if (PLUGIN_PERMISSION.equals(permit)) {
|
|
|
|
permissionOk = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!permissionOk) {
|
2012-10-23 16:45:40 +00:00
|
|
|
Log.w(LOGTAG, "Not loading plugin: " + serviceInfo.packageName + ". Does not have required permission (2).");
|
2011-11-18 18:28:17 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// check to ensure the plugin is properly signed
|
|
|
|
Signature signatures[] = pkgInfo.signatures;
|
|
|
|
if (signatures == null) {
|
2012-10-23 16:45:40 +00:00
|
|
|
Log.w(LOGTAG, "Not loading plugin: " + serviceInfo.packageName + ". Not signed.");
|
2011-11-18 18:28:17 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// determine the type of plugin from the manifest
|
|
|
|
if (serviceInfo.metaData == null) {
|
2012-10-23 16:45:40 +00:00
|
|
|
Log.e(LOGTAG, "The plugin '" + serviceInfo.name + "' has no defined type.");
|
2011-11-18 18:28:17 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
String pluginType = serviceInfo.metaData.getString(PLUGIN_TYPE);
|
|
|
|
if (!TYPE_NATIVE.equals(pluginType)) {
|
|
|
|
Log.e(LOGTAG, "Unrecognized plugin type: " + pluginType);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
Class<?> cls = getPluginClass(serviceInfo.packageName, serviceInfo.name);
|
|
|
|
|
|
|
|
//TODO implement any requirements of the plugin class here!
|
|
|
|
boolean classFound = true;
|
|
|
|
|
|
|
|
if (!classFound) {
|
|
|
|
Log.e(LOGTAG, "The plugin's class' " + serviceInfo.name + "' does not extend the appropriate class.");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
} catch (NameNotFoundException e) {
|
|
|
|
Log.e(LOGTAG, "Can't find plugin: " + serviceInfo.packageName);
|
|
|
|
continue;
|
|
|
|
} catch (ClassNotFoundException e) {
|
|
|
|
Log.e(LOGTAG, "Can't find plugin's class: " + serviceInfo.name);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if all checks have passed then make the plugin available
|
|
|
|
mPackageInfoCache.add(pkgInfo);
|
|
|
|
directories.add(directory);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-23 16:45:40 +00:00
|
|
|
return directories.toArray(new String[directories.size()]);
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
String getPluginPackage(String pluginLib) {
|
|
|
|
|
|
|
|
if (pluginLib == null || pluginLib.length() == 0) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
synchronized(mPackageInfoCache) {
|
|
|
|
for (PackageInfo pkgInfo : mPackageInfoCache) {
|
|
|
|
if (pluginLib.contains(pkgInfo.packageName)) {
|
|
|
|
return pkgInfo.packageName;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2012-07-18 10:03:14 +00:00
|
|
|
synchronized Favicons getFavicons() {
|
|
|
|
if (mFavicons == null)
|
|
|
|
mFavicons = new Favicons(this);
|
|
|
|
|
|
|
|
return mFavicons;
|
|
|
|
}
|
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
Class<?> getPluginClass(String packageName, String className)
|
|
|
|
throws NameNotFoundException, ClassNotFoundException {
|
2012-01-24 17:16:48 +00:00
|
|
|
Context pluginContext = mAppContext.createPackageContext(packageName,
|
2011-11-18 18:28:17 +00:00
|
|
|
Context.CONTEXT_INCLUDE_CODE |
|
|
|
|
Context.CONTEXT_IGNORE_SECURITY);
|
|
|
|
ClassLoader pluginCL = pluginContext.getClassLoader();
|
|
|
|
return pluginCL.loadClass(className);
|
|
|
|
}
|
|
|
|
|
2012-05-25 19:47:51 +00:00
|
|
|
@Override
|
|
|
|
public void invalidateOptionsMenu() {
|
2012-06-13 20:28:00 +00:00
|
|
|
if (mMenu == null)
|
2012-05-25 19:47:51 +00:00
|
|
|
return;
|
|
|
|
|
2012-06-13 20:28:00 +00:00
|
|
|
onPrepareOptionsMenu(mMenu);
|
2012-05-25 19:47:51 +00:00
|
|
|
|
|
|
|
if (Build.VERSION.SDK_INT >= 11)
|
|
|
|
super.invalidateOptionsMenu();
|
|
|
|
}
|
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
@Override
|
2012-07-27 06:52:41 +00:00
|
|
|
public boolean onCreateOptionsMenu(Menu menu) {
|
2012-06-13 20:28:00 +00:00
|
|
|
mMenu = menu;
|
2012-05-31 23:01:50 +00:00
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
MenuInflater inflater = getMenuInflater();
|
2012-07-27 06:52:41 +00:00
|
|
|
inflater.inflate(R.menu.gecko_app_menu, mMenu);
|
2011-11-18 18:28:17 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-05-31 23:01:50 +00:00
|
|
|
@Override
|
|
|
|
public MenuInflater getMenuInflater() {
|
|
|
|
if (Build.VERSION.SDK_INT >= 11)
|
|
|
|
return new GeckoMenuInflater(mAppContext);
|
|
|
|
else
|
|
|
|
return super.getMenuInflater();
|
|
|
|
}
|
|
|
|
|
2012-09-19 17:35:35 +00:00
|
|
|
public MenuPanel getMenuPanel() {
|
2012-05-31 23:01:50 +00:00
|
|
|
return mMenuPanel;
|
|
|
|
}
|
|
|
|
|
2012-09-19 17:35:35 +00:00
|
|
|
public MenuPresenter getMenuPresenter() {
|
|
|
|
return mMenuPresenter;
|
|
|
|
}
|
|
|
|
|
2012-05-31 23:01:50 +00:00
|
|
|
// MenuPanel holds the scrollable Menu
|
2012-09-19 17:32:01 +00:00
|
|
|
public static class MenuPanel extends LinearLayout {
|
2012-05-31 23:01:50 +00:00
|
|
|
public MenuPanel(Context context, AttributeSet attrs) {
|
|
|
|
super(context, attrs);
|
2012-09-19 17:32:01 +00:00
|
|
|
setLayoutParams(new ViewGroup.LayoutParams((int) context.getResources().getDimension(R.dimen.menu_item_row_width),
|
2012-05-31 23:01:50 +00:00
|
|
|
ViewGroup.LayoutParams.WRAP_CONTENT));
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
2012-07-25 04:32:39 +00:00
|
|
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
2012-05-31 23:01:50 +00:00
|
|
|
|
|
|
|
// heightPixels changes during rotation.
|
2012-08-01 21:56:26 +00:00
|
|
|
DisplayMetrics metrics = GeckoApp.mAppContext.getResources().getDisplayMetrics();
|
2012-07-25 04:32:39 +00:00
|
|
|
int restrictedHeightSpec = MeasureSpec.makeMeasureSpec((int) (0.75 * metrics.heightPixels), MeasureSpec.AT_MOST);
|
2012-05-31 23:01:50 +00:00
|
|
|
|
|
|
|
super.onMeasure(widthMeasureSpec, restrictedHeightSpec);
|
|
|
|
}
|
2012-07-13 06:09:58 +00:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean dispatchPopulateAccessibilityEvent (AccessibilityEvent event) {
|
2012-07-15 22:17:42 +00:00
|
|
|
if (Build.VERSION.SDK_INT >= 14) // Build.VERSION_CODES.ICE_CREAM_SANDWICH
|
|
|
|
onPopulateAccessibilityEvent(event);
|
2012-07-13 06:09:58 +00:00
|
|
|
return true;
|
|
|
|
}
|
2012-05-31 23:01:50 +00:00
|
|
|
}
|
|
|
|
|
2012-09-19 17:35:35 +00:00
|
|
|
// MenuPresenter takes care of proper animation and inflation.
|
|
|
|
public class MenuPresenter {
|
|
|
|
GeckoApp mActivity;
|
|
|
|
|
|
|
|
public MenuPresenter(GeckoApp activity) {
|
|
|
|
mActivity = activity;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void show(GeckoMenu menu) {
|
|
|
|
MenuPanel panel = mActivity.getMenuPanel();
|
|
|
|
panel.removeAllViews();
|
|
|
|
panel.addView(menu);
|
|
|
|
|
|
|
|
mActivity.openOptionsMenu();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void onOptionsMenuClosed() {
|
|
|
|
MenuPanel panel = mActivity.getMenuPanel();
|
|
|
|
panel.removeAllViews();
|
|
|
|
panel.addView((GeckoMenu) mMenu);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-31 23:01:50 +00:00
|
|
|
@Override
|
|
|
|
public View onCreatePanelView(int featureId) {
|
|
|
|
if (Build.VERSION.SDK_INT >= 11 && featureId == Window.FEATURE_OPTIONS_PANEL) {
|
|
|
|
if (mMenuPanel == null) {
|
|
|
|
mMenuPanel = new MenuPanel(mAppContext, null);
|
2012-09-19 17:35:35 +00:00
|
|
|
mMenuPresenter = new MenuPresenter(this);
|
2012-05-31 23:01:50 +00:00
|
|
|
} else {
|
|
|
|
// Prepare the panel everytime before showing the menu.
|
2012-06-13 20:28:00 +00:00
|
|
|
onPreparePanel(featureId, mMenuPanel, mMenu);
|
2012-05-31 23:01:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return mMenuPanel;
|
|
|
|
}
|
|
|
|
|
|
|
|
return super.onCreatePanelView(featureId);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onCreatePanelMenu(int featureId, Menu menu) {
|
|
|
|
if (Build.VERSION.SDK_INT >= 11 && featureId == Window.FEATURE_OPTIONS_PANEL) {
|
|
|
|
if (mMenuPanel == null) {
|
|
|
|
mMenuPanel = (MenuPanel) onCreatePanelView(featureId);
|
|
|
|
}
|
|
|
|
|
|
|
|
GeckoMenu gMenu = new GeckoMenu(mAppContext, null);
|
|
|
|
menu = gMenu;
|
|
|
|
mMenuPanel.addView(gMenu);
|
|
|
|
|
|
|
|
return onCreateOptionsMenu(menu);
|
|
|
|
}
|
|
|
|
|
|
|
|
return super.onCreatePanelMenu(featureId, menu);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onPreparePanel(int featureId, View view, Menu menu) {
|
|
|
|
if (Build.VERSION.SDK_INT >= 11 && featureId == Window.FEATURE_OPTIONS_PANEL)
|
|
|
|
return onPrepareOptionsMenu(menu);
|
|
|
|
|
|
|
|
return super.onPreparePanel(featureId, view, menu);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onMenuOpened(int featureId, Menu menu) {
|
|
|
|
if (Build.VERSION.SDK_INT >= 11 && featureId == Window.FEATURE_OPTIONS_PANEL) {
|
2012-06-13 20:28:00 +00:00
|
|
|
if (mMenu == null) {
|
2012-05-31 23:01:50 +00:00
|
|
|
onCreatePanelMenu(featureId, menu);
|
2012-06-13 20:28:00 +00:00
|
|
|
onPreparePanel(featureId, mMenuPanel, mMenu);
|
2012-05-31 23:01:50 +00:00
|
|
|
}
|
|
|
|
|
2012-06-05 17:24:52 +00:00
|
|
|
// Scroll custom menu to the top
|
|
|
|
if (mMenuPanel != null)
|
|
|
|
mMenuPanel.scrollTo(0, 0);
|
|
|
|
|
2012-05-31 23:01:50 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return super.onMenuOpened(featureId, menu);
|
|
|
|
}
|
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
@Override
|
|
|
|
public boolean onOptionsItemSelected(MenuItem item) {
|
|
|
|
switch (item.getItemId()) {
|
|
|
|
case R.id.quit:
|
2011-11-24 07:04:26 +00:00
|
|
|
synchronized(sLaunchState) {
|
|
|
|
if (sLaunchState == LaunchState.GeckoRunning)
|
|
|
|
GeckoAppShell.notifyGeckoOfEvent(
|
2012-02-09 07:18:27 +00:00
|
|
|
GeckoEvent.createBroadcastEvent("Browser:Quit", null));
|
2011-11-24 07:04:26 +00:00
|
|
|
else
|
|
|
|
System.exit(0);
|
|
|
|
sLaunchState = LaunchState.GeckoExiting;
|
|
|
|
}
|
2011-11-18 18:28:17 +00:00
|
|
|
return true;
|
2011-11-18 22:49:15 +00:00
|
|
|
default:
|
|
|
|
return super.onOptionsItemSelected(item);
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
}
|
2012-09-19 17:35:35 +00:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onOptionsMenuClosed(Menu menu) {
|
|
|
|
if (Build.VERSION.SDK_INT >= 11)
|
|
|
|
mMenuPresenter.onOptionsMenuClosed();
|
|
|
|
}
|
2012-07-25 04:30:46 +00:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
|
|
|
// Custom Menu should be opened when hardware menu key is pressed.
|
|
|
|
if (Build.VERSION.SDK_INT >= 11 && keyCode == KeyEvent.KEYCODE_MENU) {
|
|
|
|
openOptionsMenu();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return super.onKeyDown(keyCode, event);
|
|
|
|
}
|
2011-11-18 18:28:17 +00:00
|
|
|
|
2012-07-27 06:52:41 +00:00
|
|
|
protected void shareCurrentUrl() {
|
2012-09-19 17:37:35 +00:00
|
|
|
Tab tab = Tabs.getInstance().getSelectedTab();
|
|
|
|
if (tab == null)
|
2012-06-10 23:44:50 +00:00
|
|
|
return;
|
|
|
|
|
2012-09-19 17:37:35 +00:00
|
|
|
String url = tab.getURL();
|
|
|
|
if (url == null)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (ReaderModeUtils.isAboutReader(url))
|
|
|
|
url = ReaderModeUtils.getUrlFromAboutReader(url);
|
|
|
|
|
|
|
|
if (Build.VERSION.SDK_INT >= 11) {
|
|
|
|
final Intent shareIntent = new Intent(Intent.ACTION_SEND);
|
|
|
|
shareIntent.putExtra(Intent.EXTRA_TEXT, url);
|
|
|
|
shareIntent.putExtra(Intent.EXTRA_SUBJECT, tab.getDisplayTitle());
|
|
|
|
shareIntent.setType("text/plain");
|
|
|
|
|
|
|
|
PackageManager pm = getPackageManager();
|
|
|
|
List<ResolveInfo> activities = pm.queryIntentActivities(shareIntent, 0);
|
2012-09-19 17:38:29 +00:00
|
|
|
Collections.sort(activities, new Comparator<ResolveInfo>() {
|
|
|
|
@Override
|
|
|
|
public int compare(ResolveInfo one, ResolveInfo two) {
|
|
|
|
return one.preferredOrder - two.preferredOrder;
|
|
|
|
}
|
2012-09-19 17:37:35 +00:00
|
|
|
|
2012-09-19 17:38:29 +00:00
|
|
|
@Override
|
|
|
|
public boolean equals(Object info) {
|
|
|
|
return this.equals(info);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
GeckoSubMenu menu = new GeckoSubMenu(mAppContext, null);
|
2012-09-19 17:37:35 +00:00
|
|
|
for (ResolveInfo activity : activities) {
|
|
|
|
final ActivityInfo activityInfo = activity.activityInfo;
|
|
|
|
|
|
|
|
MenuItem item = menu.add(activity.loadLabel(pm));
|
|
|
|
item.setIcon(activity.loadIcon(pm));
|
|
|
|
item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
|
|
|
@Override
|
|
|
|
public boolean onMenuItemClick(MenuItem item) {
|
|
|
|
shareIntent.setComponent(new ComponentName(activityInfo.packageName, activityInfo.name));
|
|
|
|
startActivity(shareIntent);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2012-09-11 17:51:44 +00:00
|
|
|
|
2012-09-19 17:37:35 +00:00
|
|
|
mMenuPresenter.show(menu);
|
|
|
|
} else {
|
|
|
|
GeckoAppShell.openUriExternal(url, "text/plain", "", "",
|
|
|
|
Intent.ACTION_SEND, tab.getDisplayTitle());
|
|
|
|
}
|
2012-06-10 23:44:50 +00:00
|
|
|
}
|
|
|
|
|
2011-11-30 03:54:07 +00:00
|
|
|
protected void onSaveInstanceState(Bundle outState) {
|
|
|
|
super.onSaveInstanceState(outState);
|
2011-12-12 18:50:35 +00:00
|
|
|
|
2011-11-30 03:54:07 +00:00
|
|
|
if (outState == null)
|
|
|
|
outState = new Bundle();
|
2011-12-12 18:50:35 +00:00
|
|
|
|
2012-08-21 11:20:26 +00:00
|
|
|
boolean inBackground =
|
|
|
|
((GeckoApplication)getApplication()).isApplicationInBackground();
|
|
|
|
|
|
|
|
outState.putBoolean(SAVED_STATE_IN_BACKGROUND, inBackground);
|
2012-10-09 18:26:33 +00:00
|
|
|
outState.putString(SAVED_STATE_PRIVATE_SESSION, mPrivateBrowsingSession);
|
2012-03-14 22:48:22 +00:00
|
|
|
}
|
2011-11-30 03:54:07 +00:00
|
|
|
|
2012-08-07 14:39:04 +00:00
|
|
|
void getAndProcessThumbnailForTab(final Tab tab) {
|
2012-05-03 23:29:59 +00:00
|
|
|
if ("about:home".equals(tab.getURL())) {
|
|
|
|
tab.updateThumbnail(null);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-08-07 14:39:04 +00:00
|
|
|
if (tab.getState() == Tab.STATE_DELAYED) {
|
2012-10-29 23:34:29 +00:00
|
|
|
if (tab.getURL() != null) {
|
|
|
|
byte[] thumbnail = BrowserDB.getThumbnailForUrl(getContentResolver(), tab.getURL());
|
|
|
|
if (thumbnail != null)
|
|
|
|
processThumbnail(tab, null, thumbnail);
|
|
|
|
}
|
2012-08-07 14:39:04 +00:00
|
|
|
return;
|
Backout d2ee4c12c0b3 (bug 777351), 5aa6f94160dd (bug 777351), b47c470168fc (bug 777351), 5fb303ba52f7 (bug 777351), be81e4c3d928 (bug 777351), abc5b9a922dc (bug 777075), 8f1fc980f1f1 (bug 777075), 0b194a7f47d4 (bug 777075), d10df9bfef60 (bug 777075), 65393fe32cce (bug 777075), b52dc1df2fde (bug 777075), 8aeda525c094 (bug 777075) for Android native R1 failures on a CLOSED TREE
2012-08-01 17:42:05 +00:00
|
|
|
}
|
2012-08-07 14:39:04 +00:00
|
|
|
|
2012-10-15 18:11:43 +00:00
|
|
|
int dw = Tabs.getThumbnailWidth();
|
|
|
|
int dh = Tabs.getThumbnailHeight();
|
2012-08-07 14:39:04 +00:00
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createScreenshotEvent(tab.getId(), 0, 0, 0, 0, 0, 0, dw, dh, dw, dh, ScreenshotHandler.SCREENSHOT_THUMBNAIL, tab.getThumbnailBuffer()));
|
2012-01-17 03:23:04 +00:00
|
|
|
}
|
2012-06-19 20:37:57 +00:00
|
|
|
|
|
|
|
void handleThumbnailData(Tab tab, ByteBuffer data) {
|
|
|
|
if (shouldUpdateThumbnail(tab)) {
|
|
|
|
Bitmap b = tab.getThumbnailBitmap();
|
|
|
|
b.copyPixelsFromBuffer(data);
|
|
|
|
processThumbnail(tab, b, null);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-13 18:10:13 +00:00
|
|
|
void processThumbnail(Tab thumbnailTab, Bitmap bitmap, byte[] compressed) {
|
2012-01-17 03:23:04 +00:00
|
|
|
try {
|
2012-08-14 00:01:31 +00:00
|
|
|
if (bitmap == null) {
|
|
|
|
if (compressed == null) {
|
2012-10-23 16:45:40 +00:00
|
|
|
Log.w(LOGTAG, "processThumbnail: one of bitmap or compressed must be non-null!");
|
2012-08-14 00:01:31 +00:00
|
|
|
return;
|
|
|
|
}
|
2012-01-17 03:23:04 +00:00
|
|
|
bitmap = BitmapFactory.decodeByteArray(compressed, 0, compressed.length);
|
2012-08-14 00:01:31 +00:00
|
|
|
}
|
2012-01-17 03:23:04 +00:00
|
|
|
thumbnailTab.updateThumbnail(bitmap);
|
|
|
|
} catch (OutOfMemoryError ome) {
|
|
|
|
Log.w(LOGTAG, "decoding byte array ran out of memory", ome);
|
|
|
|
}
|
2012-01-13 18:10:13 +00:00
|
|
|
}
|
2011-11-18 18:28:17 +00:00
|
|
|
|
2012-06-19 20:37:57 +00:00
|
|
|
private boolean shouldUpdateThumbnail(Tab tab) {
|
2012-07-09 18:04:49 +00:00
|
|
|
return (Tabs.getInstance().isSelectedTab(tab) || areTabsShown());
|
2012-06-19 20:37:57 +00:00
|
|
|
}
|
|
|
|
|
2012-07-28 06:31:54 +00:00
|
|
|
public void hideFormAssistPopup() {
|
|
|
|
if (mFormAssistPopup != null)
|
|
|
|
mFormAssistPopup.hide();
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
|
2012-05-02 16:07:58 +00:00
|
|
|
void handleSecurityChange(final int tabId, final JSONObject identityData) {
|
2011-11-18 18:28:17 +00:00
|
|
|
final Tab tab = Tabs.getInstance().getTab(tabId);
|
|
|
|
if (tab == null)
|
|
|
|
return;
|
|
|
|
|
2012-05-02 16:07:58 +00:00
|
|
|
tab.updateIdentityData(identityData);
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
|
2012-06-02 18:23:45 +00:00
|
|
|
void handleReaderEnabled(final int tabId) {
|
|
|
|
final Tab tab = Tabs.getInstance().getTab(tabId);
|
|
|
|
if (tab == null)
|
|
|
|
return;
|
|
|
|
|
|
|
|
tab.setReaderEnabled(true);
|
|
|
|
}
|
|
|
|
|
2012-07-26 22:08:50 +00:00
|
|
|
void handleFaviconRequest(final String url) {
|
2012-10-08 08:54:23 +00:00
|
|
|
(new GeckoAsyncTask<Void, Void, String>(mAppContext, GeckoAppShell.getHandler()) {
|
2012-07-26 22:08:50 +00:00
|
|
|
@Override
|
|
|
|
public String doInBackground(Void... params) {
|
|
|
|
return getFavicons().getFaviconUrlForPageUrl(url);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onPostExecute(String faviconUrl) {
|
2012-08-31 15:36:38 +00:00
|
|
|
JSONObject args = new JSONObject();
|
|
|
|
|
2012-07-26 22:08:50 +00:00
|
|
|
if (faviconUrl != null) {
|
|
|
|
try {
|
|
|
|
args.put("url", url);
|
|
|
|
args.put("faviconUrl", faviconUrl);
|
|
|
|
} catch (JSONException e) {
|
2012-10-23 16:45:40 +00:00
|
|
|
Log.w(LOGTAG, "Error building JSON favicon arguments.", e);
|
2012-07-26 22:08:50 +00:00
|
|
|
}
|
|
|
|
}
|
2012-08-31 15:36:38 +00:00
|
|
|
|
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Reader:FaviconReturn", args.toString()));
|
2012-07-26 22:08:50 +00:00
|
|
|
}
|
|
|
|
}).execute();
|
|
|
|
}
|
|
|
|
|
2011-12-16 19:32:32 +00:00
|
|
|
void handleLoadError(final int tabId, final String uri, final String title) {
|
|
|
|
final Tab tab = Tabs.getInstance().getTab(tabId);
|
|
|
|
if (tab == null)
|
|
|
|
return;
|
2012-06-12 16:53:44 +00:00
|
|
|
|
2012-06-11 22:18:40 +00:00
|
|
|
// When a load error occurs, the URLBar can get corrupt so we reset it
|
2012-10-25 16:57:06 +00:00
|
|
|
Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.LOAD_ERROR);
|
2012-05-02 20:55:27 +00:00
|
|
|
}
|
|
|
|
|
2012-06-11 22:18:40 +00:00
|
|
|
void handlePageShow(final int tabId) { }
|
2012-02-14 17:50:55 +00:00
|
|
|
|
2012-07-06 16:22:57 +00:00
|
|
|
void handleClearHistory() {
|
|
|
|
BrowserDB.clearHistory(getContentResolver());
|
2012-07-18 10:03:14 +00:00
|
|
|
getFavicons().clearFavicons();
|
2012-07-06 16:22:57 +00:00
|
|
|
}
|
2012-04-04 19:29:31 +00:00
|
|
|
|
2012-10-23 16:45:40 +00:00
|
|
|
/**
|
|
|
|
* This function might perform synchronous IO. Don't call it
|
|
|
|
* from the main thread.
|
|
|
|
*/
|
2012-01-24 14:03:28 +00:00
|
|
|
public StartupMode getStartupMode() {
|
|
|
|
|
|
|
|
synchronized(this) {
|
|
|
|
if (mStartupMode != null)
|
|
|
|
return mStartupMode;
|
|
|
|
|
|
|
|
String packageName = getPackageName();
|
|
|
|
SharedPreferences settings = getPreferences(Activity.MODE_PRIVATE);
|
|
|
|
|
|
|
|
// This key should be profile-dependent. For now, we're simply hardcoding
|
|
|
|
// the "default" profile here.
|
2012-06-11 22:18:40 +00:00
|
|
|
String profileName = getDefaultProfileName();
|
|
|
|
if (profileName == null)
|
|
|
|
profileName = "default";
|
|
|
|
String keyName = packageName + "." + profileName + ".startup_version";
|
2012-01-24 14:03:28 +00:00
|
|
|
String appVersion = null;
|
|
|
|
|
|
|
|
try {
|
|
|
|
PackageInfo pkgInfo = getPackageManager().getPackageInfo(packageName, 0);
|
|
|
|
appVersion = pkgInfo.versionName;
|
|
|
|
} catch(NameNotFoundException nnfe) {
|
|
|
|
// If, for some reason, we can't fetch the app version
|
|
|
|
// we fallback to NORMAL startup mode.
|
|
|
|
mStartupMode = StartupMode.NORMAL;
|
|
|
|
return mStartupMode;
|
|
|
|
}
|
|
|
|
|
|
|
|
String startupVersion = settings.getString(keyName, null);
|
|
|
|
if (startupVersion == null) {
|
|
|
|
mStartupMode = StartupMode.NEW_PROFILE;
|
|
|
|
} else {
|
|
|
|
if (startupVersion.equals(appVersion))
|
|
|
|
mStartupMode = StartupMode.NORMAL;
|
|
|
|
else
|
|
|
|
mStartupMode = StartupMode.NEW_VERSION;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mStartupMode != StartupMode.NORMAL)
|
|
|
|
settings.edit().putString(keyName, appVersion).commit();
|
|
|
|
|
|
|
|
Log.i(LOGTAG, "Startup mode: " + mStartupMode);
|
|
|
|
|
|
|
|
return mStartupMode;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-11 22:18:40 +00:00
|
|
|
void addTab() { }
|
2012-06-10 23:44:50 +00:00
|
|
|
|
2012-06-11 22:18:40 +00:00
|
|
|
public void showLocalTabs() { }
|
2012-06-10 23:44:50 +00:00
|
|
|
|
2012-06-11 22:18:40 +00:00
|
|
|
public void showRemoteTabs() { }
|
2012-06-08 04:47:22 +00:00
|
|
|
|
2012-06-11 22:18:40 +00:00
|
|
|
private void showTabs(TabsPanel.Panel panel) { }
|
2012-06-10 23:44:50 +00:00
|
|
|
|
2012-06-11 22:18:40 +00:00
|
|
|
public void hideTabs() { }
|
2012-06-10 23:44:50 +00:00
|
|
|
|
2012-06-19 20:37:57 +00:00
|
|
|
/**
|
|
|
|
* Close the tab UI indirectly (not as the result of a direct user
|
|
|
|
* action). This does not force the UI to close; for example in Firefox
|
|
|
|
* tablet mode it will remain open unless the user explicitly closes it.
|
|
|
|
*
|
|
|
|
* @return True if the tab UI was hidden.
|
|
|
|
*/
|
|
|
|
public boolean autoHideTabs() { return false; }
|
|
|
|
|
2012-06-11 22:18:40 +00:00
|
|
|
public boolean areTabsShown() { return false; }
|
2012-06-10 23:44:50 +00:00
|
|
|
|
2012-07-12 22:03:09 +00:00
|
|
|
public boolean hasPermanentMenuKey() {
|
2012-07-23 20:08:48 +00:00
|
|
|
boolean hasMenu = true;
|
2012-07-12 22:03:09 +00:00
|
|
|
|
|
|
|
if (Build.VERSION.SDK_INT >= 11)
|
2012-07-23 20:08:48 +00:00
|
|
|
hasMenu = false;
|
2012-07-12 22:03:09 +00:00
|
|
|
|
2012-07-23 20:08:48 +00:00
|
|
|
if (Build.VERSION.SDK_INT >= 14)
|
|
|
|
hasMenu = ViewConfiguration.get(GeckoApp.mAppContext).hasPermanentMenuKey();
|
2012-07-12 22:03:09 +00:00
|
|
|
|
|
|
|
return hasMenu;
|
|
|
|
}
|
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
public void handleMessage(String event, JSONObject message) {
|
|
|
|
try {
|
2012-07-27 06:53:48 +00:00
|
|
|
if (event.equals("Toast:Show")) {
|
2011-11-18 18:28:17 +00:00
|
|
|
final String msg = message.getString("message");
|
|
|
|
final String duration = message.getString("duration");
|
|
|
|
handleShowToast(msg, duration);
|
|
|
|
} else if (event.equals("DOMContentLoaded")) {
|
|
|
|
final int tabId = message.getInt("tabID");
|
2012-02-29 00:17:58 +00:00
|
|
|
final String backgroundColor = message.getString("bgColor");
|
2012-05-02 20:55:27 +00:00
|
|
|
handleContentLoaded(tabId);
|
2012-04-23 17:29:14 +00:00
|
|
|
Tab tab = Tabs.getInstance().getTab(tabId);
|
|
|
|
if (backgroundColor != null) {
|
|
|
|
tab.setCheckerboardColor(backgroundColor);
|
|
|
|
} else {
|
|
|
|
// Default to white if no color is given
|
|
|
|
tab.setCheckerboardColor(Color.WHITE);
|
2012-02-29 00:17:58 +00:00
|
|
|
}
|
2012-04-23 17:29:14 +00:00
|
|
|
|
2012-08-20 19:43:53 +00:00
|
|
|
// Sync up the layer view and the tab if the tab is
|
2012-04-23 17:29:14 +00:00
|
|
|
// currently displayed.
|
2012-08-20 19:43:53 +00:00
|
|
|
LayerView layerView = mLayerView;
|
|
|
|
if (layerView != null && Tabs.getInstance().isSelectedTab(tab)) {
|
|
|
|
layerView.setCheckerboardColor(tab.getCheckerboardColor());
|
2012-04-23 17:29:14 +00:00
|
|
|
}
|
2011-11-18 18:28:17 +00:00
|
|
|
} else if (event.equals("DOMTitleChanged")) {
|
|
|
|
final int tabId = message.getInt("tabID");
|
|
|
|
final String title = message.getString("title");
|
|
|
|
handleTitleChanged(tabId, title);
|
|
|
|
} else if (event.equals("DOMLinkAdded")) {
|
|
|
|
final int tabId = message.getInt("tabID");
|
|
|
|
final String rel = message.getString("rel");
|
|
|
|
final String href = message.getString("href");
|
2012-05-29 21:10:48 +00:00
|
|
|
final int size = message.getInt("size");
|
|
|
|
handleLinkAdded(tabId, rel, href, size);
|
2011-12-30 19:48:21 +00:00
|
|
|
} else if (event.equals("DOMWindowClose")) {
|
|
|
|
final int tabId = message.getInt("tabID");
|
|
|
|
handleWindowClose(tabId);
|
2011-11-18 18:28:17 +00:00
|
|
|
} else if (event.equals("log")) {
|
|
|
|
// generic log listener
|
|
|
|
final String msg = message.getString("msg");
|
2012-10-23 16:45:40 +00:00
|
|
|
Log.d(LOGTAG, "Log: " + msg);
|
2011-11-18 18:28:17 +00:00
|
|
|
} else if (event.equals("Content:SecurityChange")) {
|
|
|
|
final int tabId = message.getInt("tabID");
|
2012-05-02 16:07:58 +00:00
|
|
|
final JSONObject identity = message.getJSONObject("identity");
|
|
|
|
Log.i(LOGTAG, "Security Mode - " + identity.getString("mode"));
|
|
|
|
handleSecurityChange(tabId, identity);
|
2012-06-02 18:23:45 +00:00
|
|
|
} else if (event.equals("Content:ReaderEnabled")) {
|
|
|
|
final int tabId = message.getInt("tabID");
|
|
|
|
handleReaderEnabled(tabId);
|
2012-07-26 22:08:50 +00:00
|
|
|
} else if (event.equals("Reader:FaviconRequest")) {
|
|
|
|
final String url = message.getString("url");
|
|
|
|
handleFaviconRequest(url);
|
2012-08-07 14:23:20 +00:00
|
|
|
} else if (event.equals("Reader:GoToReadingList")) {
|
|
|
|
showReadingList();
|
2011-11-18 18:28:17 +00:00
|
|
|
} else if (event.equals("Content:StateChange")) {
|
|
|
|
final int tabId = message.getInt("tabID");
|
2012-04-23 14:34:14 +00:00
|
|
|
final String uri = message.getString("uri");
|
2012-03-07 21:58:31 +00:00
|
|
|
final boolean success = message.getBoolean("success");
|
2011-11-18 18:28:17 +00:00
|
|
|
int state = message.getInt("state");
|
2012-10-23 16:45:40 +00:00
|
|
|
Log.d(LOGTAG, "State - " + state);
|
2011-12-21 21:34:02 +00:00
|
|
|
if ((state & GeckoAppShell.WPL_STATE_IS_NETWORK) != 0) {
|
2011-11-18 18:28:17 +00:00
|
|
|
if ((state & GeckoAppShell.WPL_STATE_START) != 0) {
|
2012-10-23 16:45:40 +00:00
|
|
|
Log.d(LOGTAG, "Got a document start event.");
|
2012-01-19 19:44:16 +00:00
|
|
|
final boolean showProgress = message.getBoolean("showProgress");
|
2012-04-23 14:34:14 +00:00
|
|
|
handleDocumentStart(tabId, showProgress, uri);
|
2011-11-18 18:28:17 +00:00
|
|
|
} else if ((state & GeckoAppShell.WPL_STATE_STOP) != 0) {
|
2012-10-23 16:45:40 +00:00
|
|
|
Log.d(LOGTAG, "Got a document stop event.");
|
2012-06-19 19:03:00 +00:00
|
|
|
handleDocumentStop(tabId, success);
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
}
|
2011-12-16 19:32:32 +00:00
|
|
|
} else if (event.equals("Content:LoadError")) {
|
|
|
|
final int tabId = message.getInt("tabID");
|
|
|
|
final String uri = message.getString("uri");
|
|
|
|
final String title = message.getString("title");
|
|
|
|
handleLoadError(tabId, uri, title);
|
2012-05-02 20:55:27 +00:00
|
|
|
} else if (event.equals("Content:PageShow")) {
|
|
|
|
final int tabId = message.getInt("tabID");
|
|
|
|
handlePageShow(tabId);
|
2011-12-02 01:27:11 +00:00
|
|
|
} else if (event.equals("Gecko:Ready")) {
|
2012-10-01 20:57:00 +00:00
|
|
|
mGeckoReadyStartupTimer.stop();
|
2011-11-24 07:04:26 +00:00
|
|
|
setLaunchState(GeckoApp.LaunchState.GeckoRunning);
|
|
|
|
GeckoAppShell.sendPendingEventsToGecko();
|
2012-03-14 22:48:22 +00:00
|
|
|
connectGeckoLayerClient();
|
2011-11-18 18:28:17 +00:00
|
|
|
} else if (event.equals("ToggleChrome:Hide")) {
|
2012-06-11 22:18:40 +00:00
|
|
|
toggleChrome(false);
|
2011-11-18 18:28:17 +00:00
|
|
|
} else if (event.equals("ToggleChrome:Show")) {
|
2012-06-11 22:18:40 +00:00
|
|
|
toggleChrome(true);
|
2012-03-08 00:24:38 +00:00
|
|
|
} else if (event.equals("ToggleChrome:Focus")) {
|
2012-06-11 22:18:40 +00:00
|
|
|
focusChrome();
|
2012-01-26 17:17:33 +00:00
|
|
|
} else if (event.equals("DOMFullScreen:Start")) {
|
|
|
|
mDOMFullScreen = true;
|
|
|
|
} else if (event.equals("DOMFullScreen:Stop")) {
|
|
|
|
mDOMFullScreen = false;
|
2011-12-17 21:50:09 +00:00
|
|
|
} else if (event.equals("Permissions:Data")) {
|
|
|
|
String host = message.getString("host");
|
|
|
|
JSONArray permissions = message.getJSONArray("permissions");
|
|
|
|
showSiteSettingsDialog(host, permissions);
|
2012-05-18 15:24:27 +00:00
|
|
|
} else if (event.equals("Tab:ViewportMetadata")) {
|
|
|
|
int tabId = message.getInt("tabID");
|
|
|
|
Tab tab = Tabs.getInstance().getTab(tabId);
|
|
|
|
if (tab == null)
|
|
|
|
return;
|
2012-08-07 14:39:03 +00:00
|
|
|
tab.setZoomConstraints(new ZoomConstraints(message));
|
2012-08-20 19:43:53 +00:00
|
|
|
// Sync up the layer view and the tab if the tab is currently displayed.
|
|
|
|
LayerView layerView = mLayerView;
|
|
|
|
if (layerView != null && Tabs.getInstance().isSelectedTab(tab)) {
|
|
|
|
layerView.setZoomConstraints(tab.getZoomConstraints());
|
2012-05-18 15:24:27 +00:00
|
|
|
}
|
2012-01-31 04:47:23 +00:00
|
|
|
} else if (event.equals("Tab:HasTouchListener")) {
|
|
|
|
int tabId = message.getInt("tabID");
|
2012-05-23 01:32:32 +00:00
|
|
|
final Tab tab = Tabs.getInstance().getTab(tabId);
|
2012-01-31 04:47:23 +00:00
|
|
|
tab.setHasTouchListeners(true);
|
2012-05-23 01:32:32 +00:00
|
|
|
mMainHandler.post(new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
if (Tabs.getInstance().isSelectedTab(tab))
|
2012-08-20 19:43:53 +00:00
|
|
|
mLayerView.getTouchEventHandler().setWaitForTouchListeners(true);
|
2012-05-23 01:32:32 +00:00
|
|
|
}
|
|
|
|
});
|
2012-02-14 17:50:55 +00:00
|
|
|
} else if (event.equals("Session:StatePurged")) {
|
2012-06-11 22:18:40 +00:00
|
|
|
onStatePurged();
|
2012-02-22 05:11:50 +00:00
|
|
|
} else if (event.equals("Bookmark:Insert")) {
|
|
|
|
final String url = message.getString("url");
|
|
|
|
final String title = message.getString("title");
|
|
|
|
mMainHandler.post(new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
Toast.makeText(GeckoApp.mAppContext, R.string.bookmark_added, Toast.LENGTH_SHORT).show();
|
|
|
|
GeckoAppShell.getHandler().post(new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
BrowserDB.addBookmark(GeckoApp.mAppContext.getContentResolver(), title, url);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
2012-03-09 23:06:50 +00:00
|
|
|
} else if (event.equals("Accessibility:Event")) {
|
2012-08-20 22:29:22 +00:00
|
|
|
GeckoAccessibility.sendAccessibilityEvent(message);
|
2012-05-10 17:33:12 +00:00
|
|
|
} else if (event.equals("Accessibility:Ready")) {
|
2012-08-20 22:29:22 +00:00
|
|
|
GeckoAccessibility.updateAccessibilitySettings();
|
2012-06-06 20:52:14 +00:00
|
|
|
} else if (event.equals("Shortcut:Remove")) {
|
|
|
|
final String url = message.getString("url");
|
2012-06-18 17:03:03 +00:00
|
|
|
final String origin = message.getString("origin");
|
2012-06-06 20:52:14 +00:00
|
|
|
final String title = message.getString("title");
|
2012-06-06 21:45:41 +00:00
|
|
|
final String type = message.getString("shortcutType");
|
2012-06-18 17:03:03 +00:00
|
|
|
GeckoAppShell.removeShortcut(title, url, origin, type);
|
|
|
|
} else if (event.equals("WebApps:Open")) {
|
|
|
|
String url = message.getString("uri");
|
|
|
|
String origin = message.getString("origin");
|
2012-09-19 17:24:26 +00:00
|
|
|
Intent intent = GeckoAppShell.getWebAppIntent(url, origin, "", null);
|
2012-06-18 17:03:03 +00:00
|
|
|
if (intent == null)
|
|
|
|
return;
|
|
|
|
startActivity(intent);
|
|
|
|
} else if (event.equals("WebApps:Install")) {
|
|
|
|
String name = message.getString("name");
|
|
|
|
String launchPath = message.getString("launchPath");
|
|
|
|
String iconURL = message.getString("iconURL");
|
|
|
|
String uniqueURI = message.getString("uniqueURI");
|
2012-08-06 16:30:12 +00:00
|
|
|
|
|
|
|
// installWebapp will return a File object pointing to the profile directory of the webapp
|
|
|
|
mCurrentResponse = GeckoAppShell.installWebApp(name, launchPath, uniqueURI, iconURL).toString();
|
2012-06-18 17:03:03 +00:00
|
|
|
} else if (event.equals("WebApps:Uninstall")) {
|
|
|
|
String uniqueURI = message.getString("uniqueURI");
|
|
|
|
GeckoAppShell.uninstallWebApp(uniqueURI);
|
2012-06-22 19:53:40 +00:00
|
|
|
} else if (event.equals("DesktopMode:Changed")) {
|
|
|
|
int tabId = message.getInt("tabId");
|
|
|
|
boolean desktopMode = message.getBoolean("desktopMode");
|
|
|
|
final Tab tab = Tabs.getInstance().getTab(tabId);
|
|
|
|
if (tab == null)
|
|
|
|
return;
|
|
|
|
|
|
|
|
tab.setDesktopMode(desktopMode);
|
|
|
|
mMainHandler.post(new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
if (tab == Tabs.getInstance().getSelectedTab())
|
|
|
|
invalidateOptionsMenu();
|
|
|
|
}
|
|
|
|
});
|
2012-06-27 16:14:16 +00:00
|
|
|
} else if (event.equals("Share:Text")) {
|
|
|
|
String text = message.getString("text");
|
|
|
|
GeckoAppShell.openUriExternal(text, "text/plain", "", "", Intent.ACTION_SEND, "");
|
2012-07-10 21:25:15 +00:00
|
|
|
} else if (event.equals("Share:Image")) {
|
|
|
|
String src = message.getString("url");
|
|
|
|
String type = message.getString("mime");
|
|
|
|
GeckoAppShell.shareImage(src, type);
|
2012-07-06 16:22:57 +00:00
|
|
|
} else if (event.equals("Sanitize:ClearHistory")) {
|
|
|
|
handleClearHistory();
|
2012-08-31 13:31:29 +00:00
|
|
|
} else if (event.equals("Update:Check")) {
|
|
|
|
startService(new Intent(UpdateServiceHelper.ACTION_CHECK_FOR_UPDATE, null, this, UpdateService.class));
|
2012-10-09 18:26:33 +00:00
|
|
|
} else if (event.equals("PrivateBrowsing:Data")) {
|
|
|
|
// null strings return "null" (http://code.google.com/p/android/issues/detail?id=13830)
|
|
|
|
if (message.isNull("session")) {
|
|
|
|
mPrivateBrowsingSession = null;
|
|
|
|
} else {
|
|
|
|
mPrivateBrowsingSession = message.getString("session");
|
|
|
|
}
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
2011-11-23 19:07:29 +00:00
|
|
|
} catch (Exception e) {
|
|
|
|
Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-06 16:30:12 +00:00
|
|
|
public String getResponse() {
|
|
|
|
String res = mCurrentResponse;
|
|
|
|
mCurrentResponse = "";
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2012-06-11 22:18:40 +00:00
|
|
|
void onStatePurged() { }
|
2011-11-29 06:38:35 +00:00
|
|
|
|
2011-12-17 21:50:09 +00:00
|
|
|
/**
|
|
|
|
* @param aPermissions
|
|
|
|
* Array of JSON objects to represent site permissions.
|
|
|
|
* Example: { type: "offline-app", setting: "Store Offline Data: Allow" }
|
|
|
|
*/
|
|
|
|
private void showSiteSettingsDialog(String aHost, JSONArray aPermissions) {
|
|
|
|
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
|
|
|
|
|
|
|
View customTitleView = getLayoutInflater().inflate(R.layout.site_setting_title, null);
|
|
|
|
((TextView) customTitleView.findViewById(R.id.title)).setText(R.string.site_settings_title);
|
|
|
|
((TextView) customTitleView.findViewById(R.id.host)).setText(aHost);
|
|
|
|
builder.setCustomTitle(customTitleView);
|
|
|
|
|
|
|
|
// If there are no permissions to clear, show the user a message about that.
|
|
|
|
// In the future, we want to disable the menu item if there are no permissions to clear.
|
|
|
|
if (aPermissions.length() == 0) {
|
|
|
|
builder.setMessage(R.string.site_settings_no_settings);
|
|
|
|
} else {
|
|
|
|
// Eventually we should use a list adapter and custom checkable list items
|
|
|
|
// to make a two-line UI to match the mock-ups
|
|
|
|
CharSequence[] items = new CharSequence[aPermissions.length()];
|
|
|
|
boolean[] states = new boolean[aPermissions.length()];
|
|
|
|
for (int i = 0; i < aPermissions.length(); i++) {
|
|
|
|
try {
|
2012-10-23 16:45:40 +00:00
|
|
|
items[i] = aPermissions.getJSONObject(i).getString("setting");
|
|
|
|
// Make all the items checked by default.
|
2011-12-17 21:50:09 +00:00
|
|
|
states[i] = true;
|
|
|
|
} catch (JSONException e) {
|
2012-10-23 16:45:40 +00:00
|
|
|
Log.w(LOGTAG, "Exception populating settings items.", e);
|
2011-12-17 21:50:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
builder.setMultiChoiceItems(items, states, new DialogInterface.OnMultiChoiceClickListener(){
|
|
|
|
public void onClick(DialogInterface dialog, int item, boolean state) {
|
|
|
|
// Do nothing
|
|
|
|
}
|
|
|
|
});
|
|
|
|
builder.setPositiveButton(R.string.site_settings_clear, new DialogInterface.OnClickListener() {
|
|
|
|
public void onClick(DialogInterface dialog, int id) {
|
|
|
|
ListView listView = ((AlertDialog) dialog).getListView();
|
|
|
|
SparseBooleanArray checkedItemPositions = listView.getCheckedItemPositions();
|
|
|
|
|
|
|
|
// An array of the indices of the permissions we want to clear
|
|
|
|
JSONArray permissionsToClear = new JSONArray();
|
|
|
|
for (int i = 0; i < checkedItemPositions.size(); i++) {
|
|
|
|
boolean checked = checkedItemPositions.get(i);
|
|
|
|
if (checked)
|
|
|
|
permissionsToClear.put(i);
|
|
|
|
}
|
2012-02-09 07:18:27 +00:00
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Permissions:Clear", permissionsToClear.toString()));
|
2011-12-17 21:50:09 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
builder.setNegativeButton(R.string.site_settings_cancel, new DialogInterface.OnClickListener(){
|
|
|
|
public void onClick(DialogInterface dialog, int id) {
|
|
|
|
dialog.cancel();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
mMainHandler.post(new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
builder.create().show();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2012-04-23 14:34:14 +00:00
|
|
|
void handleDocumentStart(int tabId, final boolean showProgress, String uri) {
|
2011-11-18 18:28:17 +00:00
|
|
|
final Tab tab = Tabs.getInstance().getTab(tabId);
|
|
|
|
if (tab == null)
|
|
|
|
return;
|
|
|
|
|
2012-09-11 17:51:44 +00:00
|
|
|
tab.setState(shouldShowProgress(uri) ? Tab.STATE_SUCCESS : Tab.STATE_LOADING);
|
2012-05-02 16:07:58 +00:00
|
|
|
tab.updateIdentityData(null);
|
2012-06-02 18:23:45 +00:00
|
|
|
tab.setReaderEnabled(false);
|
2012-04-24 19:13:36 +00:00
|
|
|
if (Tabs.getInstance().isSelectedTab(tab))
|
2012-08-20 19:43:53 +00:00
|
|
|
mLayerView.getRenderer().resetCheckerboard();
|
2012-10-25 16:57:06 +00:00
|
|
|
Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.START, showProgress);
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
|
2012-06-19 19:03:00 +00:00
|
|
|
void handleDocumentStop(int tabId, boolean success) {
|
2011-11-18 18:28:17 +00:00
|
|
|
final Tab tab = Tabs.getInstance().getTab(tabId);
|
|
|
|
if (tab == null)
|
|
|
|
return;
|
|
|
|
|
2012-03-07 21:58:31 +00:00
|
|
|
tab.setState(success ? Tab.STATE_SUCCESS : Tab.STATE_ERROR);
|
2011-11-18 18:28:17 +00:00
|
|
|
|
2012-10-25 16:57:06 +00:00
|
|
|
Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.STOP);
|
2012-06-19 19:03:00 +00:00
|
|
|
|
|
|
|
final String oldURL = tab.getURL();
|
2012-04-04 00:08:28 +00:00
|
|
|
GeckoAppShell.getHandler().postDelayed(new Runnable() {
|
|
|
|
public void run() {
|
2012-06-27 06:18:02 +00:00
|
|
|
// tab.getURL() may return null
|
|
|
|
if (!TextUtils.equals(oldURL, tab.getURL()))
|
2012-05-07 23:54:52 +00:00
|
|
|
return;
|
|
|
|
|
2012-04-04 00:08:28 +00:00
|
|
|
getAndProcessThumbnailForTab(tab);
|
2012-04-24 19:13:36 +00:00
|
|
|
if (Tabs.getInstance().isSelectedTab(tab)) {
|
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createStartPaintListentingEvent(tab.getId()));
|
2012-09-19 21:15:55 +00:00
|
|
|
ScreenshotHandler.screenshotWholePage(tab);
|
2012-04-24 19:13:36 +00:00
|
|
|
}
|
|
|
|
|
2012-04-04 00:08:28 +00:00
|
|
|
}
|
|
|
|
}, 500);
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
|
2012-07-28 06:31:54 +00:00
|
|
|
public void showToast(final int resId, final int duration) {
|
|
|
|
mMainHandler.post(new Runnable() {
|
|
|
|
public void run() {
|
2012-08-07 14:23:20 +00:00
|
|
|
Toast.makeText(mAppContext, resId, duration).show();
|
2012-07-28 06:31:54 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
void handleShowToast(final String message, final String duration) {
|
|
|
|
mMainHandler.post(new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
Toast toast;
|
|
|
|
if (duration.equals("long"))
|
|
|
|
toast = Toast.makeText(mAppContext, message, Toast.LENGTH_LONG);
|
|
|
|
else
|
|
|
|
toast = Toast.makeText(mAppContext, message, Toast.LENGTH_SHORT);
|
|
|
|
toast.show();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2012-05-02 20:55:27 +00:00
|
|
|
void handleContentLoaded(int tabId) {
|
2011-11-18 18:28:17 +00:00
|
|
|
final Tab tab = Tabs.getInstance().getTab(tabId);
|
|
|
|
if (tab == null)
|
|
|
|
return;
|
|
|
|
|
2012-10-25 16:57:06 +00:00
|
|
|
Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.LOADED);
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void handleTitleChanged(int tabId, String title) {
|
|
|
|
final Tab tab = Tabs.getInstance().getTab(tabId);
|
|
|
|
if (tab == null)
|
|
|
|
return;
|
|
|
|
|
|
|
|
tab.updateTitle(title);
|
|
|
|
}
|
|
|
|
|
2012-05-29 21:10:48 +00:00
|
|
|
void handleLinkAdded(final int tabId, String rel, final String href, int size) {
|
|
|
|
if (rel.indexOf("[icon]") == -1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
final Tab tab = Tabs.getInstance().getTab(tabId);
|
|
|
|
if (tab == null)
|
|
|
|
return;
|
|
|
|
|
|
|
|
tab.updateFaviconURL(href, size);
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
|
2011-12-30 19:48:21 +00:00
|
|
|
void handleWindowClose(final int tabId) {
|
|
|
|
Tabs tabs = Tabs.getInstance();
|
|
|
|
Tab tab = tabs.getTab(tabId);
|
|
|
|
tabs.closeTab(tab);
|
|
|
|
}
|
|
|
|
|
2012-06-07 02:39:36 +00:00
|
|
|
private void addFullScreenPluginView(View view) {
|
2012-05-30 16:10:49 +00:00
|
|
|
if (mFullScreenPluginView != null) {
|
|
|
|
Log.w(LOGTAG, "Already have a fullscreen plugin view");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
setFullScreen(true);
|
|
|
|
|
|
|
|
view.setWillNotDraw(false);
|
|
|
|
if (view instanceof SurfaceView) {
|
|
|
|
((SurfaceView) view).setZOrderOnTop(true);
|
|
|
|
}
|
|
|
|
|
2012-06-07 02:39:36 +00:00
|
|
|
mFullScreenPluginContainer = new FullScreenHolder(this);
|
|
|
|
|
|
|
|
FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
|
2012-07-31 22:26:29 +00:00
|
|
|
ViewGroup.LayoutParams.FILL_PARENT,
|
|
|
|
ViewGroup.LayoutParams.FILL_PARENT,
|
2012-06-07 02:39:36 +00:00
|
|
|
Gravity.CENTER);
|
|
|
|
mFullScreenPluginContainer.addView(view, layoutParams);
|
|
|
|
|
|
|
|
|
|
|
|
FrameLayout decor = (FrameLayout)getWindow().getDecorView();
|
|
|
|
decor.addView(mFullScreenPluginContainer, layoutParams);
|
|
|
|
|
2012-05-30 16:10:49 +00:00
|
|
|
mFullScreenPluginView = view;
|
|
|
|
}
|
|
|
|
|
2012-06-07 02:39:36 +00:00
|
|
|
void addPluginView(final View view, final Rect rect, final boolean isFullScreen) {
|
2011-11-18 18:28:17 +00:00
|
|
|
mMainHandler.post(new Runnable() {
|
|
|
|
public void run() {
|
2012-01-31 14:30:47 +00:00
|
|
|
Tabs tabs = Tabs.getInstance();
|
|
|
|
Tab tab = tabs.getSelectedTab();
|
|
|
|
|
2012-05-30 16:10:49 +00:00
|
|
|
if (isFullScreen) {
|
2012-06-07 02:39:36 +00:00
|
|
|
addFullScreenPluginView(view);
|
2012-05-30 16:10:49 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-04-27 20:04:47 +00:00
|
|
|
PluginLayer layer = (PluginLayer) tab.getPluginLayer(view);
|
|
|
|
if (layer == null) {
|
2012-08-20 19:43:53 +00:00
|
|
|
layer = new PluginLayer(view, rect, mLayerView.getRenderer().getMaxTextureSize());
|
2012-04-27 20:04:47 +00:00
|
|
|
tab.addPluginLayer(view, layer);
|
2011-11-18 18:28:17 +00:00
|
|
|
} else {
|
2012-04-27 20:04:47 +00:00
|
|
|
layer.reset(rect);
|
|
|
|
layer.setVisible(true);
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
2012-05-11 14:54:51 +00:00
|
|
|
|
2012-08-20 19:43:53 +00:00
|
|
|
mLayerView.addLayer(layer);
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2012-05-30 16:10:49 +00:00
|
|
|
private void removeFullScreenPluginView(View view) {
|
|
|
|
if (mFullScreenPluginView == null) {
|
|
|
|
Log.w(LOGTAG, "Don't have a fullscreen plugin view");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mFullScreenPluginView != view) {
|
|
|
|
Log.w(LOGTAG, "Passed view is not the current full screen view");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-06-07 02:39:36 +00:00
|
|
|
mFullScreenPluginContainer.removeView(mFullScreenPluginView);
|
2012-05-30 16:10:49 +00:00
|
|
|
|
2012-06-07 02:39:36 +00:00
|
|
|
// We need do do this on the next iteration in order to avoid
|
|
|
|
// a deadlock, see comment below in FullScreenHolder
|
2012-10-22 14:51:29 +00:00
|
|
|
mMainHandler.post(new Runnable() {
|
2012-06-07 02:39:36 +00:00
|
|
|
public void run() {
|
2012-10-22 14:51:29 +00:00
|
|
|
mLayerView.show();
|
2012-06-07 02:39:36 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
FrameLayout decor = (FrameLayout)getWindow().getDecorView();
|
|
|
|
decor.removeView(mFullScreenPluginContainer);
|
2012-10-22 14:51:29 +00:00
|
|
|
|
2012-05-30 16:10:49 +00:00
|
|
|
mFullScreenPluginView = null;
|
2012-06-07 02:39:36 +00:00
|
|
|
|
|
|
|
GeckoScreenOrientationListener.getInstance().unlockScreenOrientation();
|
|
|
|
setFullScreen(false);
|
2012-05-30 16:10:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void removePluginView(final View view, final boolean isFullScreen) {
|
2011-11-18 18:28:17 +00:00
|
|
|
mMainHandler.post(new Runnable() {
|
|
|
|
public void run() {
|
2012-04-27 20:04:47 +00:00
|
|
|
Tabs tabs = Tabs.getInstance();
|
|
|
|
Tab tab = tabs.getSelectedTab();
|
2012-01-31 14:30:47 +00:00
|
|
|
|
2012-05-30 16:10:49 +00:00
|
|
|
if (isFullScreen) {
|
|
|
|
removeFullScreenPluginView(view);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-04-27 20:04:47 +00:00
|
|
|
PluginLayer layer = (PluginLayer) tab.removePluginLayer(view);
|
|
|
|
if (layer != null) {
|
|
|
|
layer.destroy();
|
|
|
|
}
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2012-01-31 14:40:58 +00:00
|
|
|
|
|
|
|
private void hidePluginLayer(Layer layer) {
|
2012-08-20 19:43:53 +00:00
|
|
|
LayerView layerView = mLayerView;
|
2012-01-31 14:40:58 +00:00
|
|
|
layerView.removeLayer(layer);
|
|
|
|
layerView.requestRender();
|
|
|
|
}
|
|
|
|
|
|
|
|
private void showPluginLayer(Layer layer) {
|
2012-08-20 19:43:53 +00:00
|
|
|
LayerView layerView = mLayerView;
|
2012-01-31 14:40:58 +00:00
|
|
|
layerView.addLayer(layer);
|
|
|
|
layerView.requestRender();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void requestRender() {
|
2012-08-20 19:43:53 +00:00
|
|
|
mLayerView.requestRender();
|
2012-01-31 14:40:58 +00:00
|
|
|
}
|
2012-04-27 20:04:47 +00:00
|
|
|
|
|
|
|
public void hidePlugins(Tab tab) {
|
|
|
|
for (Layer layer : tab.getPluginLayers()) {
|
|
|
|
if (layer instanceof PluginLayer) {
|
|
|
|
((PluginLayer) layer).setVisible(false);
|
2012-01-31 14:40:58 +00:00
|
|
|
}
|
|
|
|
|
2012-04-27 20:04:47 +00:00
|
|
|
hidePluginLayer(layer);
|
2012-01-31 14:40:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
requestRender();
|
2012-01-31 14:30:47 +00:00
|
|
|
}
|
|
|
|
|
2012-04-27 20:04:47 +00:00
|
|
|
public void showPlugins() {
|
2012-01-31 14:30:47 +00:00
|
|
|
Tabs tabs = Tabs.getInstance();
|
|
|
|
Tab tab = tabs.getSelectedTab();
|
|
|
|
|
2012-04-27 20:04:47 +00:00
|
|
|
showPlugins(tab);
|
2012-01-31 14:30:47 +00:00
|
|
|
}
|
|
|
|
|
2012-04-27 20:04:47 +00:00
|
|
|
public void showPlugins(Tab tab) {
|
|
|
|
for (Layer layer : tab.getPluginLayers()) {
|
|
|
|
showPluginLayer(layer);
|
2011-11-18 18:28:17 +00:00
|
|
|
|
2012-04-27 20:04:47 +00:00
|
|
|
if (layer instanceof PluginLayer) {
|
|
|
|
((PluginLayer) layer).setVisible(true);
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
}
|
2012-04-27 20:04:47 +00:00
|
|
|
|
|
|
|
requestRender();
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void setFullScreen(final boolean fullscreen) {
|
|
|
|
mMainHandler.post(new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
// Hide/show the system notification bar
|
2012-02-16 00:14:02 +00:00
|
|
|
Window window = getWindow();
|
|
|
|
window.setFlags(fullscreen ?
|
|
|
|
WindowManager.LayoutParams.FLAG_FULLSCREEN : 0,
|
|
|
|
WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
|
|
|
|
2012-02-16 22:22:27 +00:00
|
|
|
if (Build.VERSION.SDK_INT >= 11)
|
|
|
|
window.getDecorView().setSystemUiVisibility(fullscreen ? 1 : 0);
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2012-05-24 22:22:47 +00:00
|
|
|
public boolean isTablet() {
|
2012-07-09 20:24:45 +00:00
|
|
|
int screenLayout = getResources().getConfiguration().screenLayout;
|
2012-07-23 19:55:07 +00:00
|
|
|
return (Build.VERSION.SDK_INT >= 11 &&
|
2012-07-23 20:08:48 +00:00
|
|
|
(((screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE) ||
|
|
|
|
((screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE)));
|
2012-05-24 22:22:47 +00:00
|
|
|
}
|
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
/** Called when the activity is first created. */
|
|
|
|
@Override
|
|
|
|
public void onCreate(Bundle savedInstanceState)
|
|
|
|
{
|
2012-10-01 18:22:18 +00:00
|
|
|
GeckoAppShell.registerGlobalExceptionHandler();
|
2012-10-01 15:15:28 +00:00
|
|
|
|
2012-10-01 20:57:00 +00:00
|
|
|
// The clock starts...now. Better hurry!
|
|
|
|
mJavaUiStartupTimer = new Telemetry.Timer("FENNEC_STARTUP_TIME_JAVAUI");
|
|
|
|
mAboutHomeStartupTimer = new Telemetry.Timer("FENNEC_STARTUP_TIME_ABOUTHOME");
|
|
|
|
mGeckoReadyStartupTimer = new Telemetry.Timer("FENNEC_STARTUP_TIME_GECKOREADY");
|
|
|
|
|
|
|
|
((GeckoApplication)getApplication()).initialize();
|
|
|
|
|
2012-01-28 01:28:30 +00:00
|
|
|
mAppContext = this;
|
2012-07-28 06:31:54 +00:00
|
|
|
Tabs.getInstance().attachToActivity(this);
|
2012-01-28 01:28:30 +00:00
|
|
|
|
2012-05-16 22:28:28 +00:00
|
|
|
// Check to see if the activity is restarted after configuration change.
|
|
|
|
if (getLastNonConfigurationInstance() != null) {
|
|
|
|
// Restart the application as a safe way to handle the configuration change.
|
|
|
|
doRestart();
|
|
|
|
System.exit(0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-12-13 01:15:38 +00:00
|
|
|
// StrictMode is set by defaults resource flag |enableStrictMode|.
|
|
|
|
if (getResources().getBoolean(R.bool.enableStrictMode)) {
|
|
|
|
enableStrictMode();
|
|
|
|
}
|
2011-12-13 01:15:23 +00:00
|
|
|
|
2012-03-08 18:25:44 +00:00
|
|
|
GeckoAppShell.loadMozGlue();
|
2012-08-01 07:51:12 +00:00
|
|
|
if (sGeckoThread != null) {
|
2012-07-13 14:20:34 +00:00
|
|
|
// this happens when the GeckoApp activity is destroyed by android
|
|
|
|
// without killing the entire application (see bug 769269)
|
|
|
|
mIsRestoringActivity = true;
|
2012-10-09 15:59:44 +00:00
|
|
|
Telemetry.HistogramAdd("FENNEC_RESTORING_ACTIVITY", 1);
|
2012-07-13 14:20:34 +00:00
|
|
|
}
|
2012-06-04 14:58:54 +00:00
|
|
|
|
2012-04-13 19:31:16 +00:00
|
|
|
mMainHandler = new Handler();
|
2012-01-04 05:47:48 +00:00
|
|
|
|
2012-03-23 19:00:17 +00:00
|
|
|
LayoutInflater.from(this).setFactory(GeckoViewsFactory.getInstance());
|
|
|
|
|
2012-02-14 21:30:15 +00:00
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
|
|
|
|
mOrientation = getResources().getConfiguration().orientation;
|
|
|
|
|
2012-06-18 17:03:03 +00:00
|
|
|
setContentView(getLayout());
|
2012-02-14 21:30:15 +00:00
|
|
|
|
|
|
|
// setup gecko layout
|
|
|
|
mGeckoLayout = (RelativeLayout) findViewById(R.id.gecko_layout);
|
|
|
|
mMainLayout = (LinearLayout) findViewById(R.id.main_layout);
|
|
|
|
|
2012-06-10 23:44:50 +00:00
|
|
|
// setup tabs panel
|
|
|
|
mTabsPanel = (TabsPanel) findViewById(R.id.tabs_panel);
|
|
|
|
|
2012-08-21 11:20:26 +00:00
|
|
|
// check if the last run was exited due to a normal kill while
|
|
|
|
// we were in the background, or a more harsh kill while we were
|
|
|
|
// active
|
2012-04-16 18:56:56 +00:00
|
|
|
if (savedInstanceState != null) {
|
2012-10-29 23:34:29 +00:00
|
|
|
mRestoreMode = RESTORE_OOM;
|
2012-08-21 11:20:26 +00:00
|
|
|
|
|
|
|
boolean wasInBackground =
|
|
|
|
savedInstanceState.getBoolean(SAVED_STATE_IN_BACKGROUND, false);
|
|
|
|
|
2012-10-09 15:59:42 +00:00
|
|
|
// Don't log OOM-kills if only one activity was destroyed. (For example
|
|
|
|
// from "Don't keep activities" on ICS)
|
|
|
|
if (!wasInBackground && !mIsRestoringActivity) {
|
2012-10-09 15:59:44 +00:00
|
|
|
Telemetry.HistogramAdd("FENNEC_WAS_KILLED", 1);
|
2012-08-21 11:20:26 +00:00
|
|
|
}
|
2012-10-09 18:26:33 +00:00
|
|
|
|
|
|
|
mPrivateBrowsingSession = savedInstanceState.getString(SAVED_STATE_PRIVATE_SESSION);
|
2012-04-16 18:56:56 +00:00
|
|
|
}
|
|
|
|
|
2012-08-21 11:20:26 +00:00
|
|
|
GeckoBackgroundThread.getHandler().post(new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
SharedPreferences prefs =
|
|
|
|
GeckoApp.mAppContext.getSharedPreferences(PREFS_NAME, 0);
|
|
|
|
|
|
|
|
boolean wasOOM = prefs.getBoolean(PREFS_OOM_EXCEPTION, false);
|
|
|
|
boolean wasStopped = prefs.getBoolean(PREFS_WAS_STOPPED, true);
|
|
|
|
if (wasOOM || !wasStopped) {
|
2012-10-09 15:59:44 +00:00
|
|
|
Telemetry.HistogramAdd("FENNEC_WAS_KILLED", 1);
|
2012-08-21 11:20:26 +00:00
|
|
|
}
|
|
|
|
SharedPreferences.Editor editor = prefs.edit();
|
|
|
|
editor.putBoolean(GeckoApp.PREFS_OOM_EXCEPTION, false);
|
|
|
|
|
|
|
|
// put a flag to check if we got a normal onSaveInstaceState
|
|
|
|
// on exit, or if we were suddenly killed (crash or native OOM)
|
|
|
|
editor.putBoolean(GeckoApp.PREFS_WAS_STOPPED, false);
|
|
|
|
editor.commit();
|
|
|
|
}
|
|
|
|
});
|
2012-02-14 21:30:15 +00:00
|
|
|
}
|
|
|
|
|
2012-10-15 17:40:16 +00:00
|
|
|
protected void initializeChrome(String uri, Boolean isExternalURL) {
|
2012-08-04 23:34:42 +00:00
|
|
|
mDoorHangerPopup = new DoorHangerPopup(this, null);
|
2012-10-25 16:55:19 +00:00
|
|
|
mPluginContainer = (AbsoluteLayout) findViewById(R.id.plugin_container);
|
|
|
|
mFormAssistPopup = (FormAssistPopup) findViewById(R.id.form_assist_popup);
|
|
|
|
|
|
|
|
if (cameraView == null) {
|
|
|
|
cameraView = new SurfaceView(this);
|
|
|
|
cameraView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mLayerView == null) {
|
|
|
|
LayerView layerView = (LayerView) findViewById(R.id.layer_view);
|
|
|
|
layerView.initializeView(GeckoAppShell.getEventDispatcher());
|
|
|
|
mLayerView = layerView;
|
|
|
|
}
|
2012-08-04 23:34:42 +00:00
|
|
|
}
|
2012-06-11 22:18:40 +00:00
|
|
|
|
2012-02-14 21:30:15 +00:00
|
|
|
private void initialize() {
|
|
|
|
mInitialized = true;
|
|
|
|
|
2012-05-25 19:47:51 +00:00
|
|
|
invalidateOptionsMenu();
|
2012-05-24 22:47:49 +00:00
|
|
|
|
2012-01-04 05:47:48 +00:00
|
|
|
Intent intent = getIntent();
|
2012-03-07 18:36:38 +00:00
|
|
|
String action = intent.getAction();
|
2012-01-05 01:28:04 +00:00
|
|
|
String args = intent.getStringExtra("args");
|
2012-06-29 22:34:15 +00:00
|
|
|
|
|
|
|
String profileName = null;
|
|
|
|
String profilePath = null;
|
|
|
|
if (args != null) {
|
|
|
|
if (args.contains("-P")) {
|
|
|
|
Pattern p = Pattern.compile("(?:-P\\s*)(\\w*)(\\s*)");
|
|
|
|
Matcher m = p.matcher(args);
|
|
|
|
if (m.find()) {
|
|
|
|
profileName = m.group(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (args.contains("-profile")) {
|
|
|
|
Pattern p = Pattern.compile("(?:-profile\\s*)(\\S*)(\\s*)");
|
|
|
|
Matcher m = p.matcher(args);
|
|
|
|
if (m.find()) {
|
|
|
|
profilePath = m.group(1);
|
|
|
|
}
|
|
|
|
if (profileName == null) {
|
|
|
|
profileName = getDefaultProfileName();
|
|
|
|
if (profileName == null)
|
|
|
|
profileName = "default";
|
|
|
|
}
|
2012-09-29 02:52:11 +00:00
|
|
|
GeckoApp.sIsUsingCustomProfile = true;
|
2012-06-29 22:34:15 +00:00
|
|
|
}
|
|
|
|
if (profileName != null || profilePath != null) {
|
|
|
|
mProfile = GeckoProfile.get(this, profileName, profilePath);
|
2012-01-05 01:28:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-15 16:02:11 +00:00
|
|
|
BrowserDB.initialize(getProfile().getName());
|
|
|
|
|
2012-01-28 01:33:02 +00:00
|
|
|
String passedUri = null;
|
2012-01-28 17:24:51 +00:00
|
|
|
String uri = getURIFromIntent(intent);
|
2012-04-16 18:56:56 +00:00
|
|
|
if (uri != null && uri.length() > 0) {
|
|
|
|
passedUri = uri;
|
|
|
|
}
|
2011-12-12 17:57:04 +00:00
|
|
|
|
2012-10-29 23:34:29 +00:00
|
|
|
if (mRestoreMode == RESTORE_NONE && getProfile().shouldRestoreSession()) {
|
|
|
|
mRestoreMode = RESTORE_CRASH;
|
2012-08-21 11:20:26 +00:00
|
|
|
}
|
2012-04-23 14:47:46 +00:00
|
|
|
|
2012-10-29 23:34:29 +00:00
|
|
|
final boolean isExternalURL = passedUri != null && !passedUri.equals("about:home");
|
2012-10-01 20:57:03 +00:00
|
|
|
StartupAction startupAction;
|
|
|
|
if (isExternalURL) {
|
|
|
|
startupAction = StartupAction.URL;
|
|
|
|
} else {
|
|
|
|
startupAction = StartupAction.NORMAL;
|
|
|
|
}
|
|
|
|
|
2012-04-17 20:01:28 +00:00
|
|
|
// Start migrating as early as possible, can do this in
|
|
|
|
// parallel with Gecko load.
|
|
|
|
checkMigrateProfile();
|
|
|
|
|
2012-01-10 07:50:56 +00:00
|
|
|
Uri data = intent.getData();
|
2012-08-28 00:11:42 +00:00
|
|
|
if (data != null && "http".equals(data.getScheme())) {
|
2012-01-10 07:50:56 +00:00
|
|
|
Intent copy = new Intent(intent);
|
|
|
|
copy.setAction(ACTION_LOAD);
|
2012-08-28 00:11:42 +00:00
|
|
|
if (isHostOnRedirectWhitelist(data.getHost())) {
|
2012-10-01 20:57:03 +00:00
|
|
|
startupAction = StartupAction.REDIRECTOR;
|
2012-08-28 00:11:42 +00:00
|
|
|
GeckoAppShell.getHandler().post(new RedirectorRunnable(copy));
|
|
|
|
// We're going to handle this uri with the redirector, so setting
|
|
|
|
// the action to MAIN and clearing the uri data prevents us from
|
|
|
|
// loading it twice
|
|
|
|
intent.setAction(Intent.ACTION_MAIN);
|
|
|
|
intent.setData(null);
|
2012-10-15 17:40:16 +00:00
|
|
|
passedUri = null;
|
2012-08-28 00:11:42 +00:00
|
|
|
} else {
|
2012-10-01 20:57:03 +00:00
|
|
|
startupAction = StartupAction.PREFETCH;
|
2012-08-28 00:11:42 +00:00
|
|
|
GeckoAppShell.getHandler().post(new PrefetchRunnable(copy));
|
|
|
|
}
|
2012-01-10 07:50:56 +00:00
|
|
|
}
|
|
|
|
|
2012-10-22 19:37:50 +00:00
|
|
|
Tabs.registerOnTabsChangedListener(this);
|
|
|
|
|
2012-10-29 23:34:29 +00:00
|
|
|
// If we are doing a restore, read the session data and send it to Gecko
|
2012-10-29 23:34:29 +00:00
|
|
|
if (mRestoreMode != RESTORE_NONE) {
|
2012-10-29 23:34:29 +00:00
|
|
|
try {
|
|
|
|
String sessionString = getProfile().readSessionFile(false);
|
|
|
|
if (sessionString == null) {
|
|
|
|
throw new IOException("could not read from session file");
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we are doing an OOM restore, parse the session data and
|
|
|
|
// stub the restored tabs immediately. This allows the UI to be
|
|
|
|
// updated before Gecko has restored.
|
2012-10-29 23:34:29 +00:00
|
|
|
if (mRestoreMode == RESTORE_OOM) {
|
2012-10-29 23:34:29 +00:00
|
|
|
final JSONArray tabs = new JSONArray();
|
|
|
|
SessionParser parser = new SessionParser() {
|
|
|
|
@Override
|
|
|
|
public void onTabRead(SessionTab sessionTab) {
|
|
|
|
JSONObject tabObject = sessionTab.getTabObject();
|
|
|
|
|
|
|
|
int flags = Tabs.LOADURL_NEW_TAB;
|
|
|
|
flags |= ((isExternalURL || !sessionTab.isSelected()) ? Tabs.LOADURL_DELAY_LOAD : 0);
|
|
|
|
flags |= (tabObject.optBoolean("desktopMode") ? Tabs.LOADURL_DESKTOP : 0);
|
2012-10-29 23:34:29 +00:00
|
|
|
flags |= (tabObject.optBoolean("isPrivate") ? Tabs.LOADURL_PRIVATE : 0);
|
2012-10-29 23:34:29 +00:00
|
|
|
|
|
|
|
Tab tab = Tabs.getInstance().loadUrl(sessionTab.getSelectedUrl(), flags);
|
|
|
|
tab.updateTitle(sessionTab.getSelectedTitle());
|
|
|
|
|
|
|
|
try {
|
|
|
|
tabObject.put("tabId", tab.getId());
|
|
|
|
} catch (JSONException e) {
|
|
|
|
Log.e(LOGTAG, "JSON error", e);
|
|
|
|
}
|
|
|
|
tabs.put(tabObject);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
parser.parse(sessionString);
|
2012-10-29 23:34:29 +00:00
|
|
|
if (mPrivateBrowsingSession != null) {
|
|
|
|
parser.parse(mPrivateBrowsingSession);
|
|
|
|
}
|
2012-10-29 23:34:29 +00:00
|
|
|
|
|
|
|
if (tabs.length() > 0) {
|
|
|
|
sessionString = new JSONObject().put("windows", new JSONArray().put(new JSONObject().put("tabs", tabs))).toString();
|
|
|
|
} else {
|
|
|
|
throw new Exception("No tabs could be read from session file");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
JSONObject restoreData = new JSONObject();
|
2012-10-29 23:34:29 +00:00
|
|
|
restoreData.put("restoringOOM", mRestoreMode == RESTORE_OOM);
|
2012-10-29 23:34:29 +00:00
|
|
|
restoreData.put("sessionString", sessionString);
|
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Session:Restore", restoreData.toString()));
|
|
|
|
} catch (Exception e) {
|
|
|
|
// If restore failed, do a normal startup
|
|
|
|
Log.e(LOGTAG, "An error occurred during restore", e);
|
2012-10-29 23:34:29 +00:00
|
|
|
mRestoreMode = RESTORE_NONE;
|
2012-10-29 23:34:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move the session file if it exists
|
2012-10-29 23:34:29 +00:00
|
|
|
if (mRestoreMode != RESTORE_OOM) {
|
2012-10-29 23:34:29 +00:00
|
|
|
getProfile().moveSessionFile();
|
|
|
|
}
|
|
|
|
|
2012-10-15 17:40:16 +00:00
|
|
|
initializeChrome(passedUri, isExternalURL);
|
|
|
|
|
2012-10-29 23:34:29 +00:00
|
|
|
// Show telemetry door hanger if we aren't restoring a session
|
2012-10-29 23:34:29 +00:00
|
|
|
if (mRestoreMode == RESTORE_NONE) {
|
2012-10-15 17:40:16 +00:00
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Telemetry:Prompt", null));
|
|
|
|
}
|
|
|
|
|
2012-10-01 20:57:03 +00:00
|
|
|
Telemetry.HistogramAdd("FENNEC_STARTUP_GECKOAPP_ACTION", startupAction.ordinal());
|
|
|
|
|
2012-08-01 07:51:12 +00:00
|
|
|
if (!mIsRestoringActivity) {
|
2012-10-29 23:34:29 +00:00
|
|
|
sGeckoThread = new GeckoThread(intent, passedUri);
|
2012-08-01 07:51:12 +00:00
|
|
|
}
|
2012-03-07 18:36:38 +00:00
|
|
|
if (!ACTION_DEBUG.equals(action) &&
|
|
|
|
checkAndSetLaunchState(LaunchState.Launching, LaunchState.Launched)) {
|
2012-08-01 07:51:12 +00:00
|
|
|
sGeckoThread.start();
|
2012-03-07 18:36:38 +00:00
|
|
|
} else if (ACTION_DEBUG.equals(action) &&
|
|
|
|
checkAndSetLaunchState(LaunchState.Launching, LaunchState.WaitForDebugger)) {
|
|
|
|
mMainHandler.postDelayed(new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
setLaunchState(LaunchState.Launching);
|
2012-08-01 07:51:12 +00:00
|
|
|
sGeckoThread.start();
|
2012-03-07 18:36:38 +00:00
|
|
|
}
|
|
|
|
}, 1000 * 5 /* 5 seconds */);
|
|
|
|
}
|
2012-01-04 05:47:48 +00:00
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
//register for events
|
2012-08-04 07:33:07 +00:00
|
|
|
registerEventListener("DOMContentLoaded");
|
|
|
|
registerEventListener("DOMTitleChanged");
|
|
|
|
registerEventListener("DOMLinkAdded");
|
|
|
|
registerEventListener("DOMWindowClose");
|
|
|
|
registerEventListener("log");
|
|
|
|
registerEventListener("Content:SecurityChange");
|
|
|
|
registerEventListener("Content:ReaderEnabled");
|
|
|
|
registerEventListener("Content:StateChange");
|
|
|
|
registerEventListener("Content:LoadError");
|
|
|
|
registerEventListener("Content:PageShow");
|
|
|
|
registerEventListener("Reader:FaviconRequest");
|
|
|
|
registerEventListener("Reader:GoToReadingList");
|
|
|
|
registerEventListener("onCameraCapture");
|
|
|
|
registerEventListener("Menu:Add");
|
|
|
|
registerEventListener("Menu:Remove");
|
|
|
|
registerEventListener("Gecko:Ready");
|
|
|
|
registerEventListener("Toast:Show");
|
|
|
|
registerEventListener("DOMFullScreen:Start");
|
|
|
|
registerEventListener("DOMFullScreen:Stop");
|
|
|
|
registerEventListener("ToggleChrome:Hide");
|
|
|
|
registerEventListener("ToggleChrome:Show");
|
|
|
|
registerEventListener("ToggleChrome:Focus");
|
|
|
|
registerEventListener("Permissions:Data");
|
|
|
|
registerEventListener("Tab:HasTouchListener");
|
|
|
|
registerEventListener("Tab:ViewportMetadata");
|
|
|
|
registerEventListener("Session:StatePurged");
|
|
|
|
registerEventListener("Bookmark:Insert");
|
|
|
|
registerEventListener("Accessibility:Event");
|
|
|
|
registerEventListener("Accessibility:Ready");
|
|
|
|
registerEventListener("Shortcut:Remove");
|
|
|
|
registerEventListener("WebApps:Open");
|
|
|
|
registerEventListener("WebApps:Install");
|
|
|
|
registerEventListener("WebApps:Uninstall");
|
|
|
|
registerEventListener("DesktopMode:Changed");
|
|
|
|
registerEventListener("Share:Text");
|
|
|
|
registerEventListener("Share:Image");
|
|
|
|
registerEventListener("Sanitize:ClearHistory");
|
2012-08-31 13:31:29 +00:00
|
|
|
registerEventListener("Update:Check");
|
2012-10-09 18:26:33 +00:00
|
|
|
registerEventListener("PrivateBrowsing:Data");
|
2011-11-18 18:28:17 +00:00
|
|
|
|
2012-01-17 18:38:04 +00:00
|
|
|
if (SmsManager.getInstance() != null) {
|
2012-01-24 16:06:47 +00:00
|
|
|
SmsManager.getInstance().start();
|
2012-01-17 18:38:04 +00:00
|
|
|
}
|
2012-01-17 18:52:17 +00:00
|
|
|
|
2012-06-13 21:12:15 +00:00
|
|
|
mPromptService = new PromptService();
|
|
|
|
|
2012-07-19 20:16:44 +00:00
|
|
|
mTextSelection = new TextSelection((TextSelectionHandle) findViewById(R.id.start_handle),
|
2012-09-21 17:56:41 +00:00
|
|
|
(TextSelectionHandle) findViewById(R.id.middle_handle),
|
2012-08-03 01:38:45 +00:00
|
|
|
(TextSelectionHandle) findViewById(R.id.end_handle),
|
|
|
|
GeckoAppShell.getEventDispatcher());
|
2012-07-19 20:16:44 +00:00
|
|
|
|
2012-10-15 13:56:42 +00:00
|
|
|
PrefsHelper.getPref("app.update.autodownload", new PrefsHelper.PrefHandlerBase() {
|
|
|
|
@Override public void prefValue(String pref, String value) {
|
|
|
|
UpdateServiceHelper.registerForUpdates(GeckoApp.this, value);
|
|
|
|
}
|
|
|
|
});
|
2012-08-31 13:31:29 +00:00
|
|
|
|
2011-12-14 17:35:58 +00:00
|
|
|
final GeckoApp self = this;
|
2012-01-24 16:06:47 +00:00
|
|
|
|
2012-10-01 20:57:00 +00:00
|
|
|
// End of the startup of our Java App
|
|
|
|
mJavaUiStartupTimer.stop();
|
|
|
|
|
2012-01-03 18:50:44 +00:00
|
|
|
GeckoAppShell.getHandler().postDelayed(new Runnable() {
|
2011-12-14 17:35:58 +00:00
|
|
|
public void run() {
|
2012-04-17 20:01:28 +00:00
|
|
|
// Sync settings need Gecko to be loaded, so
|
|
|
|
// no hurry in starting this.
|
|
|
|
checkMigrateSync();
|
2011-12-14 17:35:58 +00:00
|
|
|
|
2012-10-30 20:27:33 +00:00
|
|
|
// Record our launch time for the announcements service
|
|
|
|
// to use in assessing inactivity.
|
|
|
|
final Context context = GeckoApp.mAppContext;
|
|
|
|
AnnouncementsBroadcastService.recordLastLaunch(context);
|
|
|
|
|
2012-10-11 17:10:49 +00:00
|
|
|
// Kick off our background service to fetch product announcements.
|
|
|
|
// We do this by invoking the broadcast receiver, which uses the
|
|
|
|
// system alarm infrastructure to perform tasks at intervals.
|
2012-10-30 20:27:33 +00:00
|
|
|
GeckoPreferences.broadcastAnnouncementsPref(context);
|
2012-10-11 17:10:49 +00:00
|
|
|
|
2011-12-14 17:35:58 +00:00
|
|
|
/*
|
|
|
|
XXXX see bug 635342
|
|
|
|
We want to disable this code if possible. It is about 145ms in runtime
|
|
|
|
SharedPreferences settings = getPreferences(Activity.MODE_PRIVATE);
|
|
|
|
String localeCode = settings.getString(getPackageName() + ".locale", "");
|
|
|
|
if (localeCode != null && localeCode.length() > 0)
|
|
|
|
GeckoAppShell.setSelectedLocale(localeCode);
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!checkLaunchState(LaunchState.Launched)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}, 50);
|
2012-07-13 14:20:34 +00:00
|
|
|
|
|
|
|
if (mIsRestoringActivity) {
|
|
|
|
setLaunchState(GeckoApp.LaunchState.GeckoRunning);
|
|
|
|
Tab selectedTab = Tabs.getInstance().getSelectedTab();
|
|
|
|
if (selectedTab != null)
|
|
|
|
Tabs.getInstance().selectTab(selectedTab.getId());
|
|
|
|
connectGeckoLayerClient();
|
2012-08-20 19:43:53 +00:00
|
|
|
GeckoAppShell.setLayerClient(mLayerView.getLayerClient());
|
2012-07-13 14:20:34 +00:00
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Viewport:Flush", null));
|
|
|
|
}
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
|
2012-02-26 04:22:40 +00:00
|
|
|
public GeckoProfile getProfile() {
|
|
|
|
// fall back to default profile if we didn't load a specific one
|
|
|
|
if (mProfile == null) {
|
|
|
|
mProfile = GeckoProfile.get(this);
|
|
|
|
}
|
|
|
|
return mProfile;
|
|
|
|
}
|
|
|
|
|
2011-12-13 01:15:23 +00:00
|
|
|
/**
|
|
|
|
* Enable Android StrictMode checks (for supported OS versions).
|
|
|
|
* http://developer.android.com/reference/android/os/StrictMode.html
|
|
|
|
*/
|
2012-08-14 21:13:52 +00:00
|
|
|
private void enableStrictMode()
|
|
|
|
{
|
|
|
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) {
|
2011-12-13 01:15:23 +00:00
|
|
|
return;
|
2012-08-14 21:13:52 +00:00
|
|
|
}
|
2011-12-13 01:15:23 +00:00
|
|
|
|
2012-08-14 21:13:52 +00:00
|
|
|
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
|
|
|
|
.detectAll()
|
|
|
|
.penaltyLog()
|
|
|
|
.build());
|
2011-12-13 01:15:23 +00:00
|
|
|
|
|
|
|
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
|
|
|
|
.detectAll()
|
|
|
|
.penaltyLog()
|
|
|
|
.build());
|
|
|
|
}
|
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
public void enableCameraView() {
|
|
|
|
// Some phones (eg. nexus S) need at least a 8x16 preview size
|
|
|
|
mMainLayout.addView(cameraView, new AbsoluteLayout.LayoutParams(8, 16, 0, 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
public void disableCameraView() {
|
|
|
|
mMainLayout.removeView(cameraView);
|
|
|
|
}
|
|
|
|
|
2012-01-10 07:50:56 +00:00
|
|
|
abstract public String getDefaultUAString();
|
|
|
|
abstract public String getUAStringForHost(String host);
|
|
|
|
|
2012-08-28 00:11:42 +00:00
|
|
|
class PrefetchRunnable implements Runnable {
|
2012-01-10 07:50:56 +00:00
|
|
|
Intent mIntent;
|
2012-08-28 00:11:42 +00:00
|
|
|
protected HttpURLConnection mConnection = null;
|
|
|
|
PrefetchRunnable(Intent intent) {
|
2012-01-10 07:50:56 +00:00
|
|
|
mIntent = intent;
|
|
|
|
}
|
2012-08-28 00:11:42 +00:00
|
|
|
|
|
|
|
private void afterLoad() { }
|
|
|
|
|
2012-01-10 07:50:56 +00:00
|
|
|
public void run() {
|
|
|
|
try {
|
|
|
|
// this class should only be initialized with an intent with non-null data
|
|
|
|
URL url = new URL(mIntent.getData().toString());
|
|
|
|
// data url should have an http scheme
|
2012-08-28 00:11:42 +00:00
|
|
|
mConnection = (HttpURLConnection) url.openConnection();
|
|
|
|
mConnection.setRequestProperty("User-Agent", getUAStringForHost(url.getHost()));
|
|
|
|
mConnection.setInstanceFollowRedirects(false);
|
|
|
|
mConnection.setRequestMethod("GET");
|
|
|
|
mConnection.connect();
|
|
|
|
afterLoad();
|
|
|
|
} catch (Exception e) {
|
|
|
|
Log.w(LOGTAG, "unexpected exception, passing url directly to Gecko but we should explicitly catch this", e);
|
|
|
|
mIntent.putExtra("prefetched", 1);
|
|
|
|
} finally {
|
|
|
|
if (mConnection != null)
|
|
|
|
mConnection.disconnect();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class RedirectorRunnable extends PrefetchRunnable {
|
|
|
|
RedirectorRunnable(Intent intent) {
|
|
|
|
super(intent);
|
|
|
|
}
|
|
|
|
private void afterLoad() {
|
|
|
|
try {
|
|
|
|
int code = mConnection.getResponseCode();
|
2012-01-10 07:50:56 +00:00
|
|
|
if (code >= 300 && code < 400) {
|
2012-08-28 00:11:42 +00:00
|
|
|
String location = mConnection.getHeaderField("Location");
|
2012-01-10 07:50:56 +00:00
|
|
|
Uri data;
|
|
|
|
if (location != null &&
|
|
|
|
(data = Uri.parse(location)) != null &&
|
|
|
|
!"about".equals(data.getScheme()) &&
|
|
|
|
!"chrome".equals(data.getScheme())) {
|
|
|
|
mIntent.setData(data);
|
|
|
|
} else {
|
|
|
|
mIntent.putExtra("prefetched", 1);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
mIntent.putExtra("prefetched", 1);
|
|
|
|
}
|
|
|
|
} catch (IOException ioe) {
|
2012-10-23 16:45:40 +00:00
|
|
|
Log.w(LOGTAG, "Exception trying to pre-fetch redirected URL.", ioe);
|
2012-01-10 07:50:56 +00:00
|
|
|
mIntent.putExtra("prefetched", 1);
|
|
|
|
}
|
2012-08-28 00:11:42 +00:00
|
|
|
}
|
|
|
|
public void run() {
|
|
|
|
super.run();
|
|
|
|
|
2012-01-10 07:50:56 +00:00
|
|
|
mMainHandler.postAtFrontOfQueue(new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
onNewIntent(mIntent);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-28 00:11:42 +00:00
|
|
|
private final String kRedirectWhiteListArray[] = new String[] {
|
2012-01-10 07:50:56 +00:00
|
|
|
"t.co",
|
|
|
|
"bit.ly",
|
|
|
|
"moz.la",
|
|
|
|
"aje.me",
|
|
|
|
"facebook.com",
|
|
|
|
"goo.gl",
|
|
|
|
"tinyurl.com"
|
|
|
|
};
|
|
|
|
|
2012-08-28 00:11:42 +00:00
|
|
|
private final CopyOnWriteArrayList<String> kRedirectWhiteList =
|
|
|
|
new CopyOnWriteArrayList<String>(kRedirectWhiteListArray);
|
2012-01-10 07:50:56 +00:00
|
|
|
|
2012-08-28 00:11:42 +00:00
|
|
|
private boolean isHostOnRedirectWhitelist(String host) {
|
|
|
|
return kRedirectWhiteList.contains(host);
|
2012-01-10 07:50:56 +00:00
|
|
|
}
|
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
@Override
|
|
|
|
protected void onNewIntent(Intent intent) {
|
|
|
|
if (checkLaunchState(LaunchState.GeckoExiting)) {
|
|
|
|
// We're exiting and shouldn't try to do anything else just incase
|
|
|
|
// we're hung for some reason we'll force the process to exit
|
|
|
|
System.exit(0);
|
|
|
|
return;
|
|
|
|
}
|
2012-01-10 07:50:56 +00:00
|
|
|
|
2012-02-29 23:56:53 +00:00
|
|
|
// if we were previously OOM killed, we can end up here when launching
|
|
|
|
// from external shortcuts, so set this as the intent for initialization
|
|
|
|
if (!mInitialized) {
|
|
|
|
setIntent(intent);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-03-08 01:59:27 +00:00
|
|
|
// don't perform any actions if launching from recent apps
|
|
|
|
if ((intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0)
|
|
|
|
return;
|
|
|
|
|
2012-01-10 07:50:56 +00:00
|
|
|
if (checkLaunchState(LaunchState.Launched)) {
|
|
|
|
Uri data = intent.getData();
|
|
|
|
Bundle bundle = intent.getExtras();
|
|
|
|
// if the intent has data (i.e. a URI to be opened) and the scheme
|
|
|
|
// is either http, we'll prefetch it, which means warming
|
|
|
|
// up the radio and DNS cache by connecting and parsing the redirect
|
|
|
|
// if the return code is between 300 and 400
|
|
|
|
if (data != null &&
|
|
|
|
"http".equals(data.getScheme()) &&
|
2012-08-28 00:11:42 +00:00
|
|
|
(bundle == null || bundle.getInt("prefetched", 0) != 1)) {
|
|
|
|
if (isHostOnRedirectWhitelist(data.getHost())) {
|
|
|
|
GeckoAppShell.getHandler().post(new RedirectorRunnable(intent));
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
GeckoAppShell.getHandler().post(new PrefetchRunnable(intent));
|
|
|
|
}
|
2012-01-10 07:50:56 +00:00
|
|
|
}
|
|
|
|
}
|
2011-11-18 18:28:17 +00:00
|
|
|
final String action = intent.getAction();
|
|
|
|
|
|
|
|
if (Intent.ACTION_MAIN.equals(action)) {
|
2012-04-14 02:45:25 +00:00
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createURILoadEvent(""));
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
2012-01-10 07:50:56 +00:00
|
|
|
else if (ACTION_LOAD.equals(action)) {
|
|
|
|
String uri = intent.getDataString();
|
2012-10-05 21:51:18 +00:00
|
|
|
Tabs.getInstance().loadUrl(uri);
|
2012-01-10 07:50:56 +00:00
|
|
|
}
|
2011-11-18 18:28:17 +00:00
|
|
|
else if (Intent.ACTION_VIEW.equals(action)) {
|
|
|
|
String uri = intent.getDataString();
|
2012-04-14 02:45:25 +00:00
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createURILoadEvent(uri));
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
2012-06-18 17:03:03 +00:00
|
|
|
else if (action != null && action.startsWith(ACTION_WEBAPP_PREFIX)) {
|
2012-01-28 17:24:51 +00:00
|
|
|
String uri = getURIFromIntent(intent);
|
2012-04-14 02:45:25 +00:00
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createWebappLoadEvent(uri));
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
else if (ACTION_BOOKMARK.equals(action)) {
|
2012-01-28 17:24:51 +00:00
|
|
|
String uri = getURIFromIntent(intent);
|
2012-04-14 02:45:25 +00:00
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createBookmarkLoadEvent(uri));
|
2012-01-28 17:24:51 +00:00
|
|
|
}
|
2012-10-04 23:57:39 +00:00
|
|
|
else if (Intent.ACTION_SEARCH.equals(action)) {
|
|
|
|
String uri = getURIFromIntent(intent);
|
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createURILoadEvent(uri));
|
|
|
|
}
|
2012-08-22 15:37:08 +00:00
|
|
|
else if (ACTION_ALERT_CALLBACK.equals(action)) {
|
|
|
|
String alertName = "";
|
|
|
|
String alertCookie = "";
|
|
|
|
Uri data = intent.getData();
|
|
|
|
if (data != null) {
|
|
|
|
alertName = data.getQueryParameter("name");
|
|
|
|
if (alertName == null)
|
|
|
|
alertName = "";
|
|
|
|
alertCookie = data.getQueryParameter("cookie");
|
|
|
|
if (alertCookie == null)
|
|
|
|
alertCookie = "";
|
|
|
|
}
|
|
|
|
handleNotification(ACTION_ALERT_CALLBACK, alertName, alertCookie);
|
|
|
|
}
|
2012-10-19 18:15:06 +00:00
|
|
|
else if (ACTION_WIDGET.equals(action)) {
|
|
|
|
addTab();
|
|
|
|
}
|
2012-01-28 17:24:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Handles getting a uri from and intent in a way that is backwards
|
|
|
|
* compatable with our previous implementations
|
|
|
|
*/
|
2012-08-22 15:37:14 +00:00
|
|
|
protected String getURIFromIntent(Intent intent) {
|
2012-08-29 15:51:34 +00:00
|
|
|
final String action = intent.getAction();
|
|
|
|
if (ACTION_ALERT_CALLBACK.equals(action))
|
|
|
|
return null;
|
|
|
|
|
2012-01-28 17:24:51 +00:00
|
|
|
String uri = intent.getDataString();
|
|
|
|
if (uri != null)
|
|
|
|
return uri;
|
|
|
|
|
2012-06-28 13:42:32 +00:00
|
|
|
if ((action != null && action.startsWith(ACTION_WEBAPP_PREFIX)) || ACTION_BOOKMARK.equals(action)) {
|
2012-01-28 17:24:51 +00:00
|
|
|
uri = intent.getStringExtra("args");
|
|
|
|
if (uri != null && uri.startsWith("--url=")) {
|
|
|
|
uri.replace("--url=", "");
|
|
|
|
}
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
2012-01-28 17:24:51 +00:00
|
|
|
return uri;
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onResume()
|
|
|
|
{
|
|
|
|
// After an onPause, the activity is back in the foreground.
|
|
|
|
// Undo whatever we did in onPause.
|
|
|
|
super.onResume();
|
|
|
|
|
2012-05-07 23:17:08 +00:00
|
|
|
SiteIdentityPopup.getInstance().dismiss();
|
2012-05-02 16:07:58 +00:00
|
|
|
|
2012-01-30 23:10:16 +00:00
|
|
|
int newOrientation = getResources().getConfiguration().orientation;
|
|
|
|
|
|
|
|
if (mOrientation != newOrientation) {
|
|
|
|
mOrientation = newOrientation;
|
2012-06-11 22:18:40 +00:00
|
|
|
refreshChrome();
|
2012-01-30 23:10:16 +00:00
|
|
|
}
|
2012-06-13 19:22:52 +00:00
|
|
|
|
2012-09-14 15:19:40 +00:00
|
|
|
GeckoScreenOrientationListener.getInstance().start();
|
|
|
|
|
2012-06-13 19:22:52 +00:00
|
|
|
// User may have enabled/disabled accessibility.
|
2012-08-20 22:29:22 +00:00
|
|
|
GeckoAccessibility.updateAccessibilitySettings();
|
2012-08-21 11:20:26 +00:00
|
|
|
|
|
|
|
GeckoBackgroundThread.getHandler().post(new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
SharedPreferences prefs =
|
|
|
|
GeckoApp.mAppContext.getSharedPreferences(GeckoApp.PREFS_NAME, 0);
|
|
|
|
SharedPreferences.Editor editor = prefs.edit();
|
|
|
|
editor.putBoolean(GeckoApp.PREFS_WAS_STOPPED, false);
|
|
|
|
editor.commit();
|
|
|
|
}
|
|
|
|
});
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
|
2012-04-13 19:31:16 +00:00
|
|
|
@Override
|
|
|
|
public void onWindowFocusChanged(boolean hasFocus) {
|
|
|
|
super.onWindowFocusChanged(hasFocus);
|
|
|
|
|
|
|
|
if (!mInitialized && hasFocus)
|
|
|
|
initialize();
|
|
|
|
}
|
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
@Override
|
|
|
|
public void onStop()
|
|
|
|
{
|
|
|
|
// We're about to be stopped, potentially in preparation for
|
|
|
|
// being destroyed. We're killable after this point -- as I
|
|
|
|
// understand it, in extreme cases the process can be terminated
|
|
|
|
// without going through onDestroy.
|
|
|
|
//
|
|
|
|
// We might also get an onRestart after this; not sure what
|
|
|
|
// that would mean for Gecko if we were to kill it here.
|
|
|
|
// Instead, what we should do here is save prefs, session,
|
|
|
|
// etc., and generally mark the profile as 'clean', and then
|
|
|
|
// dirty it again if we get an onResume.
|
|
|
|
|
2012-04-03 18:58:01 +00:00
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createStoppingEvent(isApplicationInBackground()));
|
2011-11-18 18:28:17 +00:00
|
|
|
super.onStop();
|
|
|
|
}
|
|
|
|
|
2012-08-21 11:20:26 +00:00
|
|
|
@Override
|
|
|
|
public void onPause()
|
|
|
|
{
|
|
|
|
// In some way it's sad that Android will trigger StrictMode warnings
|
|
|
|
// here as the whole point is to save to disk while the activity is not
|
|
|
|
// interacting with the user.
|
|
|
|
GeckoBackgroundThread.getHandler().post(new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
SharedPreferences prefs =
|
|
|
|
GeckoApp.mAppContext.getSharedPreferences(GeckoApp.PREFS_NAME, 0);
|
|
|
|
SharedPreferences.Editor editor = prefs.edit();
|
|
|
|
editor.putBoolean(GeckoApp.PREFS_WAS_STOPPED, true);
|
|
|
|
editor.commit();
|
2012-10-20 00:36:21 +00:00
|
|
|
|
|
|
|
BrowserDB.expireHistory(getContentResolver(),
|
|
|
|
BrowserContract.ExpirePriority.NORMAL);
|
2012-08-21 11:20:26 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2012-09-14 15:19:40 +00:00
|
|
|
GeckoScreenOrientationListener.getInstance().stop();
|
|
|
|
|
2012-08-21 11:20:26 +00:00
|
|
|
super.onPause();
|
|
|
|
}
|
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
@Override
|
|
|
|
public void onRestart()
|
|
|
|
{
|
2012-08-21 11:20:26 +00:00
|
|
|
GeckoBackgroundThread.getHandler().post(new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
SharedPreferences prefs =
|
|
|
|
GeckoApp.mAppContext.getSharedPreferences(GeckoApp.PREFS_NAME, 0);
|
|
|
|
SharedPreferences.Editor editor = prefs.edit();
|
|
|
|
editor.putBoolean(GeckoApp.PREFS_WAS_STOPPED, false);
|
|
|
|
editor.commit();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
super.onRestart();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onStart()
|
|
|
|
{
|
2012-04-03 18:58:01 +00:00
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createStartEvent(isApplicationInBackground()));
|
2011-11-18 18:28:17 +00:00
|
|
|
super.onStart();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onDestroy()
|
|
|
|
{
|
|
|
|
// Tell Gecko to shutting down; we'll end up calling System.exit()
|
|
|
|
// in onXreExit.
|
|
|
|
if (isFinishing())
|
2012-02-09 07:18:27 +00:00
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createShutdownEvent());
|
2012-08-04 07:33:07 +00:00
|
|
|
|
|
|
|
unregisterEventListener("DOMContentLoaded");
|
|
|
|
unregisterEventListener("DOMTitleChanged");
|
|
|
|
unregisterEventListener("DOMLinkAdded");
|
|
|
|
unregisterEventListener("DOMWindowClose");
|
|
|
|
unregisterEventListener("log");
|
|
|
|
unregisterEventListener("Content:SecurityChange");
|
|
|
|
unregisterEventListener("Content:ReaderEnabled");
|
|
|
|
unregisterEventListener("Content:StateChange");
|
|
|
|
unregisterEventListener("Content:LoadError");
|
|
|
|
unregisterEventListener("Content:PageShow");
|
|
|
|
unregisterEventListener("Reader:FaviconRequest");
|
|
|
|
unregisterEventListener("Reader:GoToReadingList");
|
|
|
|
unregisterEventListener("onCameraCapture");
|
|
|
|
unregisterEventListener("Menu:Add");
|
|
|
|
unregisterEventListener("Menu:Remove");
|
|
|
|
unregisterEventListener("Gecko:Ready");
|
|
|
|
unregisterEventListener("Toast:Show");
|
|
|
|
unregisterEventListener("DOMFullScreen:Start");
|
|
|
|
unregisterEventListener("DOMFullScreen:Stop");
|
|
|
|
unregisterEventListener("ToggleChrome:Hide");
|
|
|
|
unregisterEventListener("ToggleChrome:Show");
|
|
|
|
unregisterEventListener("ToggleChrome:Focus");
|
|
|
|
unregisterEventListener("Permissions:Data");
|
|
|
|
unregisterEventListener("Tab:HasTouchListener");
|
|
|
|
unregisterEventListener("Tab:ViewportMetadata");
|
|
|
|
unregisterEventListener("Session:StatePurged");
|
|
|
|
unregisterEventListener("Bookmark:Insert");
|
|
|
|
unregisterEventListener("Accessibility:Event");
|
|
|
|
unregisterEventListener("Accessibility:Ready");
|
|
|
|
unregisterEventListener("Shortcut:Remove");
|
|
|
|
unregisterEventListener("WebApps:Open");
|
|
|
|
unregisterEventListener("WebApps:Install");
|
|
|
|
unregisterEventListener("WebApps:Uninstall");
|
|
|
|
unregisterEventListener("DesktopMode:Changed");
|
|
|
|
unregisterEventListener("Share:Text");
|
|
|
|
unregisterEventListener("Share:Image");
|
|
|
|
unregisterEventListener("Sanitize:ClearHistory");
|
2012-08-31 13:31:29 +00:00
|
|
|
unregisterEventListener("Update:Check");
|
2012-10-09 18:26:33 +00:00
|
|
|
unregisterEventListener("PrivateBrowsing:Data");
|
2011-11-18 18:28:17 +00:00
|
|
|
|
2012-07-10 21:25:15 +00:00
|
|
|
deleteTempFiles();
|
|
|
|
|
2012-08-20 19:43:53 +00:00
|
|
|
if (mLayerView != null)
|
|
|
|
mLayerView.destroy();
|
2012-08-04 23:34:42 +00:00
|
|
|
if (mDoorHangerPopup != null)
|
|
|
|
mDoorHangerPopup.destroy();
|
2012-07-13 14:17:03 +00:00
|
|
|
if (mFormAssistPopup != null)
|
|
|
|
mFormAssistPopup.destroy();
|
|
|
|
if (mPromptService != null)
|
|
|
|
mPromptService.destroy();
|
2012-07-19 20:16:44 +00:00
|
|
|
if (mTextSelection != null)
|
|
|
|
mTextSelection.destroy();
|
2012-07-13 14:17:03 +00:00
|
|
|
|
2012-07-18 17:11:26 +00:00
|
|
|
GeckoAppShell.getHandler().post(new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
if (mFavicons != null)
|
|
|
|
mFavicons.close();
|
|
|
|
}
|
|
|
|
});
|
2011-11-18 18:28:17 +00:00
|
|
|
|
2012-01-17 18:38:04 +00:00
|
|
|
if (SmsManager.getInstance() != null) {
|
2012-01-24 16:06:47 +00:00
|
|
|
SmsManager.getInstance().stop();
|
|
|
|
if (isFinishing())
|
|
|
|
SmsManager.getInstance().shutdown();
|
2012-01-17 18:38:04 +00:00
|
|
|
}
|
2012-01-17 18:52:17 +00:00
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
super.onDestroy();
|
2011-11-22 20:48:22 +00:00
|
|
|
|
2012-08-27 20:44:27 +00:00
|
|
|
Tabs.unregisterOnTabsChangedListener(this);
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
|
2012-08-27 04:33:11 +00:00
|
|
|
protected void registerEventListener(String event) {
|
2012-08-04 07:33:07 +00:00
|
|
|
GeckoAppShell.getEventDispatcher().registerEventListener(event, this);
|
|
|
|
}
|
|
|
|
|
2012-08-27 04:33:11 +00:00
|
|
|
protected void unregisterEventListener(String event) {
|
2012-08-04 07:33:07 +00:00
|
|
|
GeckoAppShell.getEventDispatcher().unregisterEventListener(event, this);
|
|
|
|
}
|
|
|
|
|
2012-07-19 21:36:48 +00:00
|
|
|
// Get a temporary directory, may return null
|
2012-07-10 21:25:15 +00:00
|
|
|
public static File getTempDirectory() {
|
2012-07-11 02:55:38 +00:00
|
|
|
File dir = mAppContext.getExternalFilesDir("temp");
|
2012-07-10 21:25:15 +00:00
|
|
|
return dir;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete any files in our temporary directory
|
|
|
|
public static void deleteTempFiles() {
|
2012-07-19 21:36:48 +00:00
|
|
|
File dir = getTempDirectory();
|
|
|
|
if (dir == null)
|
|
|
|
return;
|
|
|
|
File[] files = dir.listFiles();
|
2012-07-10 21:25:15 +00:00
|
|
|
if (files == null)
|
|
|
|
return;
|
|
|
|
for (File file : files) {
|
|
|
|
file.delete();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-29 06:38:35 +00:00
|
|
|
@Override
|
|
|
|
public void onContentChanged() {
|
|
|
|
super.onContentChanged();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
@Override
|
2012-10-23 16:45:40 +00:00
|
|
|
public void onConfigurationChanged(Configuration newConfig) {
|
2011-11-18 18:28:17 +00:00
|
|
|
super.onConfigurationChanged(newConfig);
|
2011-12-21 08:03:34 +00:00
|
|
|
|
|
|
|
if (mOrientation != newConfig.orientation) {
|
|
|
|
mOrientation = newConfig.orientation;
|
2012-06-15 03:12:06 +00:00
|
|
|
if (mFormAssistPopup != null)
|
|
|
|
mFormAssistPopup.hide();
|
2012-05-07 23:17:08 +00:00
|
|
|
SiteIdentityPopup.getInstance().dismiss();
|
2012-06-11 22:18:40 +00:00
|
|
|
refreshChrome();
|
2011-12-21 08:03:34 +00:00
|
|
|
}
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
|
2012-05-16 22:28:28 +00:00
|
|
|
@Override
|
|
|
|
public Object onRetainNonConfigurationInstance() {
|
|
|
|
// Send a non-null value so that we can restart the application,
|
|
|
|
// when activity restarts due to configuration change.
|
|
|
|
return new Boolean(true);
|
|
|
|
}
|
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
abstract public String getPackageName();
|
|
|
|
abstract public String getContentProcessName();
|
|
|
|
|
|
|
|
public void addEnvToIntent(Intent intent) {
|
|
|
|
Map<String,String> envMap = System.getenv();
|
|
|
|
Set<Map.Entry<String,String>> envSet = envMap.entrySet();
|
|
|
|
Iterator<Map.Entry<String,String>> envIter = envSet.iterator();
|
|
|
|
int c = 0;
|
|
|
|
while (envIter.hasNext()) {
|
|
|
|
Map.Entry<String,String> entry = envIter.next();
|
|
|
|
intent.putExtra("env" + c, entry.getKey() + "="
|
|
|
|
+ entry.getValue());
|
|
|
|
c++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void doRestart() {
|
2012-01-25 04:32:12 +00:00
|
|
|
doRestart("org.mozilla.gecko.restart");
|
|
|
|
}
|
|
|
|
|
|
|
|
public void doRestart(String action) {
|
2012-10-23 16:45:40 +00:00
|
|
|
Log.d(LOGTAG, "doRestart(\"" + action + "\")");
|
2011-11-18 18:28:17 +00:00
|
|
|
try {
|
|
|
|
Intent intent = new Intent(action);
|
|
|
|
intent.setClassName(getPackageName(),
|
|
|
|
getPackageName() + ".Restarter");
|
|
|
|
/* TODO: addEnvToIntent(intent); */
|
|
|
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
|
|
|
|
Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
|
2012-10-23 16:45:40 +00:00
|
|
|
Log.d(LOGTAG, "Restart intent: " + intent.toString());
|
2011-11-18 18:28:17 +00:00
|
|
|
GeckoAppShell.killAnyZombies();
|
|
|
|
startActivity(intent);
|
|
|
|
} catch (Exception e) {
|
2012-10-23 16:45:40 +00:00
|
|
|
Log.e(LOGTAG, "Error effecting restart.", e);
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
finish();
|
|
|
|
// Give the restart process time to start before we die
|
|
|
|
GeckoAppShell.waitForAnotherGeckoProc();
|
|
|
|
}
|
|
|
|
|
|
|
|
public void handleNotification(String action, String alertName, String alertCookie) {
|
|
|
|
GeckoAppShell.handleNotification(action, alertName, alertCookie);
|
|
|
|
}
|
|
|
|
|
2011-12-19 21:56:11 +00:00
|
|
|
private void checkMigrateProfile() {
|
2012-04-17 20:01:28 +00:00
|
|
|
final File profileDir = getProfile().getDir();
|
2012-02-10 22:01:44 +00:00
|
|
|
|
2011-12-19 21:56:11 +00:00
|
|
|
if (profileDir != null) {
|
2012-01-19 20:19:56 +00:00
|
|
|
final GeckoApp app = GeckoApp.mAppContext;
|
2012-04-04 19:29:31 +00:00
|
|
|
|
2012-04-19 14:41:52 +00:00
|
|
|
GeckoAppShell.getHandler().post(new Runnable() {
|
|
|
|
public void run() {
|
2012-05-08 22:51:07 +00:00
|
|
|
ProfileMigrator profileMigrator = new ProfileMigrator(app);
|
2012-04-04 19:29:31 +00:00
|
|
|
|
2012-04-19 14:41:52 +00:00
|
|
|
// Do a migration run on the first start after an upgrade.
|
2012-09-29 02:52:11 +00:00
|
|
|
if (!GeckoApp.sIsUsingCustomProfile &&
|
|
|
|
!profileMigrator.hasMigrationRun()) {
|
2012-04-19 20:07:39 +00:00
|
|
|
// Show the "Setting up Fennec" screen if this takes
|
|
|
|
// a while.
|
2012-10-23 14:55:16 +00:00
|
|
|
|
|
|
|
// Create a "final" holder for the setup screen so that we can
|
|
|
|
// create it in startCallback and still find a reference to it
|
|
|
|
// in stopCallback. (We must create it on the UI thread to fix
|
|
|
|
// bug 788216). Note that synchronization is not a problem here
|
|
|
|
// since it is only ever touched on the UI thread.
|
|
|
|
final SetupScreen[] setupScreenHolder = new SetupScreen[1];
|
2012-04-19 14:41:52 +00:00
|
|
|
|
2012-04-19 20:07:39 +00:00
|
|
|
final Runnable startCallback = new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
GeckoApp.mAppContext.runOnUiThread(new Runnable() {
|
|
|
|
public void run() {
|
2012-10-23 14:55:16 +00:00
|
|
|
setupScreenHolder[0] = new SetupScreen(app);
|
|
|
|
setupScreenHolder[0].show();
|
2012-04-19 20:07:39 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
final Runnable stopCallback = new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
GeckoApp.mAppContext.runOnUiThread(new Runnable() {
|
|
|
|
public void run() {
|
2012-10-23 14:55:16 +00:00
|
|
|
SetupScreen screen = setupScreenHolder[0];
|
|
|
|
// screen will never be null if this code runs, but
|
|
|
|
// stranger things have happened...
|
|
|
|
if (screen != null) {
|
|
|
|
screen.dismiss();
|
|
|
|
}
|
2012-04-19 20:07:39 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
2012-04-04 19:29:31 +00:00
|
|
|
|
2012-04-19 20:07:39 +00:00
|
|
|
profileMigrator.setLongOperationCallbacks(startCallback,
|
|
|
|
stopCallback);
|
2012-05-08 22:51:07 +00:00
|
|
|
profileMigrator.launchPlaces(profileDir);
|
2012-06-11 22:18:40 +00:00
|
|
|
finishProfileMigration();
|
2012-04-17 20:01:28 +00:00
|
|
|
}
|
2012-04-19 14:41:52 +00:00
|
|
|
}}
|
|
|
|
);
|
2012-04-17 20:01:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-11 22:18:40 +00:00
|
|
|
protected void finishProfileMigration() {
|
|
|
|
}
|
|
|
|
|
2012-04-17 20:01:28 +00:00
|
|
|
private void checkMigrateSync() {
|
|
|
|
final File profileDir = getProfile().getDir();
|
2012-09-29 02:52:11 +00:00
|
|
|
if (!GeckoApp.sIsUsingCustomProfile && profileDir != null) {
|
2012-04-17 20:01:28 +00:00
|
|
|
final GeckoApp app = GeckoApp.mAppContext;
|
2012-05-08 22:51:07 +00:00
|
|
|
ProfileMigrator profileMigrator = new ProfileMigrator(app);
|
2012-04-17 20:01:28 +00:00
|
|
|
if (!profileMigrator.hasSyncMigrated()) {
|
|
|
|
profileMigrator.launchSyncPrefs();
|
2012-04-04 19:29:31 +00:00
|
|
|
}
|
2011-12-19 21:56:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-13 18:07:43 +00:00
|
|
|
PromptService getPromptService() {
|
|
|
|
return mPromptService;
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onSearchRequested() {
|
2012-06-10 23:44:50 +00:00
|
|
|
return showAwesomebar(AwesomeBar.Target.CURRENT_TAB);
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
|
2012-06-10 23:44:50 +00:00
|
|
|
public boolean showAwesomebar(AwesomeBar.Target aTarget) {
|
|
|
|
return showAwesomebar(aTarget, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean showAwesomebar(AwesomeBar.Target aTarget, String aUrl) {
|
2011-11-18 18:28:17 +00:00
|
|
|
Intent intent = new Intent(getBaseContext(), AwesomeBar.class);
|
|
|
|
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_NO_HISTORY);
|
2012-06-10 23:44:50 +00:00
|
|
|
intent.putExtra(AwesomeBar.TARGET_KEY, aTarget.name());
|
2011-11-18 18:28:17 +00:00
|
|
|
|
2012-06-10 23:44:50 +00:00
|
|
|
// if we were passed in a url, show it
|
|
|
|
if (aUrl != null && !TextUtils.isEmpty(aUrl)) {
|
|
|
|
intent.putExtra(AwesomeBar.CURRENT_URL_KEY, aUrl);
|
|
|
|
} else if (aTarget == AwesomeBar.Target.CURRENT_TAB) {
|
|
|
|
// otherwise, if we're editing the current tab, show its url
|
2011-11-18 18:28:17 +00:00
|
|
|
Tab tab = Tabs.getInstance().getSelectedTab();
|
|
|
|
if (tab != null) {
|
2012-06-10 23:44:50 +00:00
|
|
|
|
|
|
|
aUrl = tab.getURL();
|
|
|
|
if (aUrl != null) {
|
|
|
|
intent.putExtra(AwesomeBar.CURRENT_URL_KEY, aUrl);
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
2012-06-10 23:44:50 +00:00
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
}
|
2012-06-10 23:44:50 +00:00
|
|
|
|
2012-07-13 18:08:19 +00:00
|
|
|
int requestCode = GeckoAppShell.sActivityHelper.makeRequestCodeForAwesomebar();
|
2012-07-13 18:07:43 +00:00
|
|
|
startActivityForResult(intent, requestCode);
|
2011-11-18 18:28:17 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-08-07 14:23:20 +00:00
|
|
|
public void showReadingList() {
|
|
|
|
Intent intent = new Intent(getBaseContext(), AwesomeBar.class);
|
|
|
|
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_NO_HISTORY);
|
|
|
|
intent.putExtra(AwesomeBar.TARGET_KEY, AwesomeBar.Target.CURRENT_TAB.toString());
|
|
|
|
intent.putExtra(AwesomeBar.READING_LIST_KEY, true);
|
|
|
|
|
|
|
|
int requestCode = GeckoAppShell.sActivityHelper.makeRequestCodeForAwesomebar();
|
|
|
|
startActivityForResult(intent, requestCode);
|
|
|
|
}
|
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
@Override
|
|
|
|
public void onBackPressed() {
|
2012-06-19 20:37:57 +00:00
|
|
|
if (autoHideTabs()) {
|
2012-06-10 23:44:50 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-08-09 20:53:00 +00:00
|
|
|
if (mDoorHangerPopup != null && mDoorHangerPopup.isShowing()) {
|
2011-11-18 18:28:17 +00:00
|
|
|
mDoorHangerPopup.dismiss();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-05-30 16:10:49 +00:00
|
|
|
if (mFullScreenPluginView != null) {
|
2012-06-11 17:50:59 +00:00
|
|
|
GeckoAppShell.onFullScreenPluginHidden(mFullScreenPluginView);
|
|
|
|
removeFullScreenPluginView(mFullScreenPluginView);
|
2012-05-30 16:10:49 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-05-07 23:17:08 +00:00
|
|
|
SiteIdentityPopup identityPopup = SiteIdentityPopup.getInstance();
|
|
|
|
if (identityPopup.isShowing()) {
|
|
|
|
identityPopup.dismiss();
|
2012-05-02 16:07:58 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-01-26 17:17:33 +00:00
|
|
|
if (mDOMFullScreen) {
|
2012-02-09 07:18:27 +00:00
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("FullScreen:Exit", null));
|
2011-11-18 18:28:17 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-12-19 18:44:52 +00:00
|
|
|
Tabs tabs = Tabs.getInstance();
|
|
|
|
Tab tab = tabs.getSelectedTab();
|
|
|
|
if (tab == null) {
|
2011-11-18 18:28:17 +00:00
|
|
|
moveTaskToBack(true);
|
2011-12-19 18:44:52 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tab.doBack())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (tab.isExternal()) {
|
|
|
|
moveTaskToBack(true);
|
|
|
|
tabs.closeTab(tab);
|
|
|
|
return;
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
2011-12-19 18:44:52 +00:00
|
|
|
|
|
|
|
int parentId = tab.getParentId();
|
|
|
|
Tab parent = tabs.getTab(parentId);
|
|
|
|
if (parent != null) {
|
|
|
|
// The back button should always return to the parent (not a sibling).
|
|
|
|
tabs.closeTab(tab, parent);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
moveTaskToBack(true);
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2012-07-13 18:07:43 +00:00
|
|
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
2012-07-13 18:08:19 +00:00
|
|
|
if (!GeckoAppShell.sActivityHelper.handleActivityResult(requestCode, resultCode, data)) {
|
2012-04-05 05:50:06 +00:00
|
|
|
super.onActivityResult(requestCode, resultCode, data);
|
2012-07-13 18:07:43 +00:00
|
|
|
}
|
2012-04-05 05:50:06 +00:00
|
|
|
}
|
|
|
|
|
2012-08-20 19:43:53 +00:00
|
|
|
public LayerView getLayerView() {
|
|
|
|
return mLayerView;
|
|
|
|
}
|
|
|
|
|
2012-04-27 20:04:47 +00:00
|
|
|
public AbsoluteLayout getPluginContainer() { return mPluginContainer; }
|
|
|
|
|
2012-10-23 16:45:40 +00:00
|
|
|
// Accelerometer.
|
|
|
|
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
|
|
|
}
|
2011-11-18 18:28:17 +00:00
|
|
|
|
2012-10-23 16:45:40 +00:00
|
|
|
public void onSensorChanged(SensorEvent event) {
|
2012-02-09 07:18:27 +00:00
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createSensorEvent(event));
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
|
2012-10-23 16:45:40 +00:00
|
|
|
// Geolocation.
|
|
|
|
public void onLocationChanged(Location location) {
|
|
|
|
// No logging here: user-identifying information.
|
2012-03-09 06:16:25 +00:00
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createLocationEvent(location));
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void onProviderDisabled(String provider)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
public void onProviderEnabled(String provider)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
public void onStatusChanged(String provider, int status, Bundle extras)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2012-06-07 02:39:01 +00:00
|
|
|
// Called when a Gecko Hal WakeLock is changed
|
|
|
|
public void notifyWakeLockChanged(String topic, String state) {
|
|
|
|
PowerManager.WakeLock wl = mWakeLocks.get(topic);
|
|
|
|
if (state.equals("locked-foreground") && wl == null) {
|
|
|
|
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
|
|
|
wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, topic);
|
|
|
|
wl.acquire();
|
|
|
|
mWakeLocks.put(topic, wl);
|
|
|
|
} else if (!state.equals("locked-foreground") && wl != null) {
|
|
|
|
wl.release();
|
|
|
|
mWakeLocks.remove(topic);
|
|
|
|
}
|
|
|
|
}
|
2011-11-18 18:28:17 +00:00
|
|
|
|
2012-08-31 13:31:29 +00:00
|
|
|
public void notifyCheckUpdateResult(boolean result) {
|
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Update:CheckResult", result ? "true" : "false"));
|
|
|
|
}
|
|
|
|
|
2012-09-12 20:36:36 +00:00
|
|
|
protected void connectGeckoLayerClient() {
|
2012-08-20 19:43:53 +00:00
|
|
|
mLayerView.getLayerClient().notifyGeckoReady();
|
2012-04-04 15:55:40 +00:00
|
|
|
|
2012-10-12 23:23:20 +00:00
|
|
|
mLayerView.getTouchEventHandler().setOnTouchListener(new OnInterceptTouchListener() {
|
2012-07-10 21:12:53 +00:00
|
|
|
private PointF initialPoint = null;
|
2012-07-20 17:06:01 +00:00
|
|
|
|
2012-10-12 23:23:20 +00:00
|
|
|
@Override
|
|
|
|
public boolean onInterceptTouchEvent(View view, MotionEvent event) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2012-07-20 17:06:01 +00:00
|
|
|
@Override
|
2012-04-04 15:55:40 +00:00
|
|
|
public boolean onTouch(View view, MotionEvent event) {
|
|
|
|
if (event == null)
|
|
|
|
return true;
|
2012-07-10 21:12:53 +00:00
|
|
|
|
|
|
|
int action = event.getAction();
|
|
|
|
PointF point = new PointF(event.getX(), event.getY());
|
|
|
|
if ((action & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) {
|
|
|
|
initialPoint = point;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (initialPoint != null && (action & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_MOVE) {
|
|
|
|
if (PointUtils.subtract(point, initialPoint).length() < PanZoomController.PAN_THRESHOLD) {
|
|
|
|
// Don't send the touchmove event if if the users finger hasn't move far
|
|
|
|
// Necessary for Google Maps to work correctlly. See bug 771099.
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
initialPoint = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-04 15:55:40 +00:00
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createMotionEvent(event));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
});
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
2012-05-02 11:15:07 +00:00
|
|
|
|
2012-10-12 23:23:20 +00:00
|
|
|
public static class MainLayout extends LinearLayout {
|
|
|
|
private OnInterceptTouchListener mOnInterceptTouchListener;
|
|
|
|
|
|
|
|
public MainLayout(Context context, AttributeSet attrs) {
|
|
|
|
super(context, attrs);
|
|
|
|
mOnInterceptTouchListener = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setOnInterceptTouchListener(OnInterceptTouchListener listener) {
|
|
|
|
mOnInterceptTouchListener = listener;
|
|
|
|
}
|
2012-07-20 17:06:01 +00:00
|
|
|
|
|
|
|
@Override
|
2012-10-12 23:23:20 +00:00
|
|
|
public boolean onInterceptTouchEvent(MotionEvent event) {
|
|
|
|
if (mOnInterceptTouchListener != null && mOnInterceptTouchListener.onInterceptTouchEvent(this, event))
|
2012-07-20 17:06:01 +00:00
|
|
|
return true;
|
2012-10-12 23:23:20 +00:00
|
|
|
return super.onInterceptTouchEvent(event);
|
2012-07-20 17:06:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2012-10-12 23:23:20 +00:00
|
|
|
public boolean onTouchEvent(MotionEvent event) {
|
|
|
|
if (mOnInterceptTouchListener != null && mOnInterceptTouchListener.onTouch(this, event))
|
2012-07-20 17:06:01 +00:00
|
|
|
return true;
|
2012-10-12 23:23:20 +00:00
|
|
|
return super.onTouchEvent(event);
|
2012-07-20 17:06:01 +00:00
|
|
|
}
|
2012-10-15 15:18:30 +00:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void setDrawingCacheEnabled(boolean enabled) {
|
|
|
|
// Instead of setting drawing cache in the view itself, we simply
|
|
|
|
// enable drawing caching on its children. This is mainly used in
|
|
|
|
// animations (see PropertyAnimator)
|
|
|
|
super.setChildrenDrawnWithCacheEnabled(enabled);
|
|
|
|
}
|
2012-07-20 17:06:01 +00:00
|
|
|
}
|
|
|
|
|
2012-05-02 11:15:07 +00:00
|
|
|
public boolean linkerExtract() {
|
|
|
|
return false;
|
|
|
|
}
|
2012-06-07 02:39:36 +00:00
|
|
|
|
2012-07-18 00:54:54 +00:00
|
|
|
private class FullScreenHolder extends FrameLayout {
|
|
|
|
|
2012-06-07 02:39:36 +00:00
|
|
|
public FullScreenHolder(Context ctx) {
|
|
|
|
super(ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void addView(View view, int index) {
|
|
|
|
/**
|
|
|
|
* This normally gets called when Flash adds a separate SurfaceView
|
|
|
|
* for the video. It is unhappy if we have the LayerView underneath
|
|
|
|
* it for some reason so we need to hide that. Hiding the LayerView causes
|
|
|
|
* its surface to be destroyed, which causes a pause composition
|
|
|
|
* event to be sent to Gecko. We synchronously wait for that to be
|
|
|
|
* processed. Simultaneously, however, Flash is waiting on a mutex so
|
|
|
|
* the post() below is an attempt to avoid a deadlock.
|
|
|
|
*/
|
|
|
|
super.addView(view, index);
|
|
|
|
|
|
|
|
mMainHandler.post(new Runnable() {
|
|
|
|
public void run() {
|
2012-10-22 14:51:29 +00:00
|
|
|
mLayerView.hide();
|
2012-06-07 02:39:36 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The methods below are simply copied from what Android WebKit does.
|
|
|
|
* It wasn't ever called in my testing, but might as well
|
|
|
|
* keep it in case it is for some reason. The methods
|
|
|
|
* all return true because we don't want any events
|
|
|
|
* leaking out from the fullscreen view.
|
|
|
|
*/
|
|
|
|
@Override
|
|
|
|
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
|
|
|
if (event.isSystem()) {
|
|
|
|
return super.onKeyDown(keyCode, event);
|
|
|
|
}
|
|
|
|
mFullScreenPluginView.onKeyDown(keyCode, event);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
|
|
|
if (event.isSystem()) {
|
|
|
|
return super.onKeyUp(keyCode, event);
|
|
|
|
}
|
|
|
|
mFullScreenPluginView.onKeyUp(keyCode, event);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onTouchEvent(MotionEvent event) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onTrackballEvent(MotionEvent event) {
|
|
|
|
mFullScreenPluginView.onTrackballEvent(event);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2012-06-10 23:44:50 +00:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onContextItemSelected(MenuItem item) {
|
|
|
|
switch(item.getItemId()) {
|
|
|
|
case R.id.pasteandgo: {
|
|
|
|
String text = GeckoAppShell.getClipboardText();
|
|
|
|
if (text != null && !TextUtils.isEmpty(text)) {
|
2012-10-05 21:51:18 +00:00
|
|
|
Tabs.getInstance().loadUrl(text);
|
2012-06-10 23:44:50 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2012-08-20 17:28:36 +00:00
|
|
|
case R.id.site_settings: {
|
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Permissions:Get", null));
|
|
|
|
return true;
|
|
|
|
}
|
2012-06-10 23:44:50 +00:00
|
|
|
case R.id.paste: {
|
|
|
|
String text = GeckoAppShell.getClipboardText();
|
|
|
|
if (text != null && !TextUtils.isEmpty(text)) {
|
|
|
|
showAwesomebar(AwesomeBar.Target.CURRENT_TAB, text);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case R.id.share: {
|
|
|
|
shareCurrentUrl();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case R.id.copyurl: {
|
|
|
|
Tab tab = Tabs.getInstance().getSelectedTab();
|
|
|
|
if (tab != null) {
|
|
|
|
String url = tab.getURL();
|
|
|
|
if (url != null) {
|
|
|
|
GeckoAppShell.setClipboardText(url);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
case R.id.add_to_launcher: {
|
|
|
|
Tab tab = Tabs.getInstance().getSelectedTab();
|
|
|
|
if (tab != null) {
|
|
|
|
String url = tab.getURL();
|
2012-07-24 23:47:59 +00:00
|
|
|
String title = tab.getDisplayTitle();
|
2012-06-10 23:44:50 +00:00
|
|
|
BitmapDrawable favicon = (BitmapDrawable)(tab.getFavicon());
|
|
|
|
if (url != null && title != null) {
|
2012-06-18 17:03:03 +00:00
|
|
|
GeckoAppShell.createShortcut(title, url, url, favicon == null ? null : favicon.getBitmap(), "");
|
2012-06-10 23:44:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2012-06-15 22:34:22 +00:00
|
|
|
|
2012-09-11 17:51:44 +00:00
|
|
|
public static boolean shouldShowProgress(String url) {
|
|
|
|
return "about:home".equals(url) || ReaderModeUtils.isAboutReader(url);
|
|
|
|
}
|
|
|
|
|
2012-06-29 22:49:48 +00:00
|
|
|
public static void assertOnUiThread() {
|
|
|
|
Thread uiThread = mAppContext.getMainLooper().getThread();
|
|
|
|
assertOnThread(uiThread);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void assertOnGeckoThread() {
|
|
|
|
assertOnThread(sGeckoThread);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void assertOnThread(Thread expectedThread) {
|
|
|
|
Thread currentThread = Thread.currentThread();
|
|
|
|
long currentThreadId = currentThread.getId();
|
|
|
|
long expectedThreadId = expectedThread.getId();
|
|
|
|
|
|
|
|
if (currentThreadId != expectedThreadId) {
|
|
|
|
throw new IllegalThreadStateException("Expected thread " + expectedThreadId + " (\""
|
|
|
|
+ expectedThread.getName()
|
|
|
|
+ "\"), but running on thread " + currentThreadId
|
|
|
|
+ " (\"" + currentThread.getName() + ")");
|
|
|
|
}
|
|
|
|
}
|
2012-05-02 20:55:27 +00:00
|
|
|
}
|