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-01-31 22:13:33 +00:00
|
|
|
import org.mozilla.gecko.db.BrowserDB;
|
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;
|
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;
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.DialogInterface;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.content.SharedPreferences;
|
|
|
|
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.ScrollView;
|
|
|
|
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;
|
|
|
|
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-06-10 23:44:50 +00:00
|
|
|
GeckoApplication.ApplicationLifecycleCallbacks,
|
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
|
|
|
|
}
|
|
|
|
|
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-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-01-25 04:32:12 +00:00
|
|
|
public static final String ACTION_UPDATE = "org.mozilla.gecko.UPDATE";
|
2012-03-08 18:25:44 +00:00
|
|
|
public static final String ACTION_INIT_PW = "org.mozilla.gecko.INIT_PW";
|
2012-08-21 11:20:26 +00:00
|
|
|
public static final String SAVED_STATE_TITLE = "title";
|
|
|
|
public static final String SAVED_STATE_IN_BACKGROUND = "inBackground";
|
|
|
|
|
|
|
|
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-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-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-01-28 01:28:47 +00:00
|
|
|
public static boolean sIsGeckoReady = false;
|
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 = "";
|
2011-11-30 04:58:39 +00:00
|
|
|
|
2012-04-02 20:50:03 +00:00
|
|
|
private GeckoConnectivityReceiver mConnectivityReceiver;
|
2012-04-05 00:31:19 +00:00
|
|
|
private GeckoBatteryManager mBatteryReceiver;
|
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-08-20 19:43:53 +00:00
|
|
|
private 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-06-11 22:18:40 +00:00
|
|
|
protected int mRestoreMode = GeckoAppShell.RESTORE_NONE;
|
2012-08-22 15:37:14 +00:00
|
|
|
protected boolean mInitialized = false;
|
2012-02-14 21:30:15 +00:00
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2012-01-13 19:08:39 +00:00
|
|
|
Log.w(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - start of getPluginDirectories");
|
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) {
|
|
|
|
Log.w(LOGTAG, "Ignore bad plugin");
|
|
|
|
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
|
|
|
Log.w(LOGTAG, "Loading plugin: " + serviceInfo.packageName);
|
|
|
|
|
|
|
|
|
|
|
|
// retrieve information from the plugin's manifest
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
if (pkgInfo == null) {
|
|
|
|
Log.w(LOGTAG, "Loading plugin: " + serviceInfo.packageName + ". Could not load package information.");
|
|
|
|
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;
|
|
|
|
// 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) {
|
|
|
|
Log.w(LOGTAG, "Loading plugin: " + serviceInfo.packageName + ". Does not have required permission.");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
boolean permissionOk = false;
|
|
|
|
for (String permit : permissions) {
|
|
|
|
if (PLUGIN_PERMISSION.equals(permit)) {
|
|
|
|
permissionOk = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!permissionOk) {
|
|
|
|
Log.w(LOGTAG, "Loading plugin: " + serviceInfo.packageName + ". Does not have required permission (2).");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// check to ensure the plugin is properly signed
|
|
|
|
Signature signatures[] = pkgInfo.signatures;
|
|
|
|
if (signatures == null) {
|
|
|
|
Log.w(LOGTAG, "Loading plugin: " + serviceInfo.packageName + ". Not signed.");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// determine the type of plugin from the manifest
|
|
|
|
if (serviceInfo.metaData == null) {
|
|
|
|
Log.e(LOGTAG, "The plugin '" + serviceInfo.name + "' has no type defined");
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
String [] result = directories.toArray(new String[directories.size()]);
|
2012-01-13 19:08:39 +00:00
|
|
|
Log.w(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - end of getPluginDirectories");
|
2011-11-18 18:28:17 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
|
|
|
public View getMenuPanel() {
|
|
|
|
return mMenuPanel;
|
|
|
|
}
|
|
|
|
|
|
|
|
// MenuPanel holds the scrollable Menu
|
2012-07-18 00:54:54 +00:00
|
|
|
public static class MenuPanel extends ScrollView {
|
2012-05-31 23:01:50 +00:00
|
|
|
public MenuPanel(Context context, AttributeSet attrs) {
|
|
|
|
super(context, attrs);
|
|
|
|
setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
@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);
|
|
|
|
} 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-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-06-10 23:44:50 +00:00
|
|
|
Tab tab = Tabs.getInstance().getSelectedTab();
|
|
|
|
if (tab == null)
|
|
|
|
return;
|
|
|
|
|
|
|
|
String url = tab.getURL();
|
|
|
|
if (url == null)
|
|
|
|
return;
|
|
|
|
|
|
|
|
GeckoAppShell.openUriExternal(url, "text/plain", "", "",
|
2012-07-24 23:47:59 +00:00
|
|
|
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
|
|
|
|
2012-08-21 11:20:26 +00:00
|
|
|
Log.i(LOGTAG, "onSaveInstanceState");
|
|
|
|
|
2011-11-30 03:54:07 +00:00
|
|
|
if (outState == null)
|
|
|
|
outState = new Bundle();
|
2011-12-12 18:50:35 +00:00
|
|
|
|
2012-04-16 18:56:56 +00:00
|
|
|
Tab tab = Tabs.getInstance().getSelectedTab();
|
|
|
|
if (tab != null)
|
|
|
|
outState.putString(SAVED_STATE_TITLE, tab.getDisplayTitle());
|
2012-08-21 11:20:26 +00:00
|
|
|
|
|
|
|
boolean inBackground =
|
|
|
|
((GeckoApplication)getApplication()).isApplicationInBackground();
|
|
|
|
|
|
|
|
outState.putBoolean(SAVED_STATE_IN_BACKGROUND, inBackground);
|
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) {
|
|
|
|
byte[] thumbnail = BrowserDB.getThumbnailForUrl(getContentResolver(), tab.getURL());
|
|
|
|
if (thumbnail != null)
|
|
|
|
processThumbnail(tab, null, thumbnail);
|
|
|
|
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
|
|
|
|
|
|
|
int dw = tab.getThumbnailWidth();
|
|
|
|
int dh = tab.getThumbnailHeight();
|
|
|
|
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) {
|
|
|
|
Log.e(LOGTAG, "processThumbnail: one of bitmap or compressed must be non-null!");
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2011-12-14 00:23:35 +00:00
|
|
|
void handleLocationChange(final int tabId, final String uri,
|
2012-04-23 21:35:50 +00:00
|
|
|
final String documentURI, final String contentType,
|
|
|
|
final boolean sameDocument) {
|
2011-11-18 18:28:17 +00:00
|
|
|
final Tab tab = Tabs.getInstance().getTab(tabId);
|
|
|
|
if (tab == null)
|
|
|
|
return;
|
2011-12-02 16:12:43 +00:00
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
tab.updateURL(uri);
|
2011-12-14 00:23:35 +00:00
|
|
|
tab.setDocumentURI(documentURI);
|
2011-11-18 18:28:17 +00:00
|
|
|
|
2012-07-07 05:50:07 +00:00
|
|
|
// We can get a location change event for the same document with an anchor tag
|
|
|
|
if (sameDocument)
|
|
|
|
return;
|
|
|
|
|
2012-04-23 21:35:50 +00:00
|
|
|
tab.setContentType(contentType);
|
2012-05-29 21:10:48 +00:00
|
|
|
tab.clearFavicon();
|
2012-07-12 18:09:40 +00:00
|
|
|
tab.updateTitle(null);
|
2012-05-02 16:07:58 +00:00
|
|
|
tab.updateIdentityData(null);
|
2012-06-02 18:23:45 +00:00
|
|
|
tab.setReaderEnabled(false);
|
2012-08-07 14:39:03 +00:00
|
|
|
tab.setZoomConstraints(new ZoomConstraints(true));
|
2012-01-25 00:31:33 +00:00
|
|
|
tab.setHasTouchListeners(false);
|
2012-04-23 17:29:14 +00:00
|
|
|
tab.setCheckerboardColor(Color.WHITE);
|
2011-11-18 18:28:17 +00:00
|
|
|
|
|
|
|
mMainHandler.post(new Runnable() {
|
|
|
|
public void run() {
|
2012-08-04 23:34:47 +00:00
|
|
|
Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.LOCATION_CHANGE, uri);
|
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-08-02 18:10:31 +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) {
|
|
|
|
if (faviconUrl != null) {
|
|
|
|
JSONObject args = new JSONObject();
|
|
|
|
try {
|
|
|
|
args.put("url", url);
|
|
|
|
args.put("faviconUrl", faviconUrl);
|
|
|
|
} catch (JSONException e) {
|
|
|
|
Log.e(LOGTAG, "error building json arguments");
|
|
|
|
}
|
|
|
|
|
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Reader:FaviconReturn", args.toString()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}).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-06-12 16:53:44 +00:00
|
|
|
mMainHandler.post(new Runnable() {
|
|
|
|
public void run() {
|
2012-06-11 22:18:40 +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-01-24 14:03:28 +00:00
|
|
|
public StartupMode getStartupMode() {
|
|
|
|
// This function might touch the disk and should not
|
|
|
|
// be called from UI's main thread.
|
|
|
|
|
|
|
|
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) {
|
|
|
|
Log.i(LOGTAG, "Got message: " + event);
|
|
|
|
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);
|
|
|
|
Log.i(LOGTAG, "title - " + 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");
|
|
|
|
Log.i(LOGTAG, "link rel - " + rel + ", href - " + href + ", size - " + 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");
|
|
|
|
Log.i(LOGTAG, "Log: " + msg);
|
|
|
|
} else if (event.equals("Content:LocationChange")) {
|
|
|
|
final int tabId = message.getInt("tabID");
|
|
|
|
final String uri = message.getString("uri");
|
2011-12-14 00:23:35 +00:00
|
|
|
final String documentURI = message.getString("documentURI");
|
|
|
|
final String contentType = message.getString("contentType");
|
2012-04-23 21:35:50 +00:00
|
|
|
final boolean sameDocument = message.getBoolean("sameDocument");
|
2011-11-18 18:28:17 +00:00
|
|
|
Log.i(LOGTAG, "URI - " + uri);
|
2012-04-23 21:35:50 +00:00
|
|
|
handleLocationChange(tabId, uri, documentURI, contentType, sameDocument);
|
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");
|
|
|
|
Log.i(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) {
|
|
|
|
Log.i(LOGTAG, "Got a document start");
|
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) {
|
|
|
|
Log.i(LOGTAG, "Got a document stop");
|
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")) {
|
|
|
|
sIsGeckoReady = true;
|
2012-06-13 20:28:00 +00:00
|
|
|
final Menu menu = mMenu;
|
2011-11-18 18:28:17 +00:00
|
|
|
mMainHandler.post(new Runnable() {
|
|
|
|
public void run() {
|
2012-06-13 19:58:57 +00:00
|
|
|
if (menu != null)
|
|
|
|
menu.findItem(R.id.settings).setEnabled(true);
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
});
|
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-01-23 21:47:48 +00:00
|
|
|
} else if (event.equals("CharEncoding:Data")) {
|
|
|
|
final JSONArray charsets = message.getJSONArray("charsets");
|
|
|
|
int selected = message.getInt("selected");
|
|
|
|
|
|
|
|
final int len = charsets.length();
|
|
|
|
final String[] titleArray = new String[len];
|
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
|
JSONObject charset = charsets.getJSONObject(i);
|
|
|
|
titleArray[i] = charset.getString("title");
|
|
|
|
}
|
|
|
|
|
|
|
|
final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
|
|
|
|
dialogBuilder.setSingleChoiceItems(titleArray, selected, new AlertDialog.OnClickListener() {
|
|
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
|
|
try {
|
|
|
|
JSONObject charset = charsets.getJSONObject(which);
|
2012-02-09 07:18:27 +00:00
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("CharEncoding:Set", charset.getString("code")));
|
2012-01-23 21:47:48 +00:00
|
|
|
dialog.dismiss();
|
|
|
|
} catch (JSONException e) {
|
|
|
|
Log.e(LOGTAG, "error parsing json", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
dialogBuilder.setNegativeButton(R.string.button_cancel, new AlertDialog.OnClickListener() {
|
|
|
|
public void onClick(DialogInterface dialog, int which) {
|
|
|
|
dialog.dismiss();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
mMainHandler.post(new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
dialogBuilder.show();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} else if (event.equals("CharEncoding:State")) {
|
|
|
|
final boolean visible = message.getString("visible").equals("true");
|
|
|
|
GeckoPreferences.setCharEncodingState(visible);
|
2012-06-13 20:28:00 +00:00
|
|
|
final Menu menu = mMenu;
|
2012-05-23 01:32:32 +00:00
|
|
|
mMainHandler.post(new Runnable() {
|
|
|
|
public void run() {
|
2012-06-13 19:58:57 +00:00
|
|
|
if (menu != null)
|
|
|
|
menu.findItem(R.id.char_encoding).setVisible(visible);
|
2012-05-23 01:32:32 +00:00
|
|
|
}
|
|
|
|
});
|
2012-01-25 04:32:12 +00:00
|
|
|
} else if (event.equals("Update:Restart")) {
|
|
|
|
doRestart("org.mozilla.gecko.restart_update");
|
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");
|
|
|
|
Intent intent = GeckoAppShell.getWebAppIntent(url, origin, false);
|
|
|
|
if (intent == null)
|
|
|
|
return;
|
|
|
|
Log.i(LOGTAG, "Open " + url + " (" + origin + ")");
|
|
|
|
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();
|
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() {
|
|
|
|
Log.i(LOGTAG, "Return " + mCurrentResponse);
|
|
|
|
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 {
|
|
|
|
items[i] = aPermissions.getJSONObject(i).
|
|
|
|
getString("setting");
|
|
|
|
// Make all the items checked by default
|
|
|
|
states[i] = true;
|
|
|
|
} catch (JSONException e) {
|
2012-07-23 19:04:28 +00:00
|
|
|
Log.i(LOGTAG, "JSONException", 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-04-27 17:52:21 +00:00
|
|
|
tab.setState("about:home".equals(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();
|
2011-11-18 18:28:17 +00:00
|
|
|
mMainHandler.post(new Runnable() {
|
|
|
|
public void run() {
|
2012-06-11 22:18:40 +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
|
|
|
|
|
|
|
mMainHandler.post(new Runnable() {
|
|
|
|
public void run() {
|
2012-02-29 17:09:43 +00:00
|
|
|
Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.STOP);
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
});
|
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()));
|
|
|
|
GeckoAppShell.screenshotWholePage(tab);
|
|
|
|
}
|
|
|
|
|
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-05-17 21:35:33 +00:00
|
|
|
mMainHandler.post(new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
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
|
|
|
|
mMainHandler.post(new Runnable() {
|
|
|
|
public void run() {
|
2012-08-20 19:43:53 +00:00
|
|
|
mLayerView.setVisibility(View.VISIBLE);
|
2012-06-07 02:39:36 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
FrameLayout decor = (FrameLayout)getWindow().getDecorView();
|
|
|
|
decor.removeView(mFullScreenPluginContainer);
|
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-03-07 19:19:05 +00:00
|
|
|
GeckoAppShell.registerGlobalExceptionHandler();
|
|
|
|
|
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-06-04 14:58:54 +00:00
|
|
|
|
2012-04-13 19:31:16 +00:00
|
|
|
mMainHandler = new Handler();
|
2012-01-13 19:08:39 +00:00
|
|
|
Log.w(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - onCreate");
|
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-08-21 11:20:26 +00:00
|
|
|
Log.i(LOGTAG, "Restoring from OOM");
|
2012-05-14 21:48:04 +00:00
|
|
|
mRestoreMode = GeckoAppShell.RESTORE_OOM;
|
2012-08-21 11:20:26 +00:00
|
|
|
|
|
|
|
boolean wasInBackground =
|
|
|
|
savedInstanceState.getBoolean(SAVED_STATE_IN_BACKGROUND, false);
|
|
|
|
Log.i(LOGTAG, "Was in background: " + wasInBackground);
|
|
|
|
|
|
|
|
if (!wasInBackground) {
|
|
|
|
Telemetry.HistogramAdd("OUT_OF_MEMORY_KILLED", 1);
|
|
|
|
}
|
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) {
|
|
|
|
Log.i(LOGTAG, "Crashed due to OOM last run");
|
|
|
|
Telemetry.HistogramAdd("OUT_OF_MEMORY_KILLED", 1);
|
|
|
|
}
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
((GeckoApplication)getApplication()).addApplicationLifecycleCallbacks(this);
|
2012-02-14 21:30:15 +00:00
|
|
|
}
|
|
|
|
|
2012-08-04 23:34:42 +00:00
|
|
|
void initializeChrome(String uri, Boolean isExternalURL) {
|
|
|
|
mDoorHangerPopup = new DoorHangerPopup(this, null);
|
|
|
|
}
|
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";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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-03-07 18:36:38 +00:00
|
|
|
if (ACTION_UPDATE.equals(action) || args != null && args.contains("-alert update-app")) {
|
2012-01-25 04:32:12 +00:00
|
|
|
Log.i(LOGTAG,"onCreate: Update request");
|
|
|
|
checkAndLaunchUpdate();
|
|
|
|
}
|
|
|
|
|
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-08-21 11:20:26 +00:00
|
|
|
if (mRestoreMode == GeckoAppShell.RESTORE_NONE && getProfile().shouldRestoreSession()) {
|
|
|
|
Log.i(LOGTAG, "Restoring crash");
|
2012-05-14 21:48:04 +00:00
|
|
|
mRestoreMode = GeckoAppShell.RESTORE_CRASH;
|
2012-08-21 11:20:26 +00:00
|
|
|
}
|
2012-04-23 14:47:46 +00:00
|
|
|
|
|
|
|
boolean isExternalURL = passedUri != null && !passedUri.equals("about:home");
|
2012-06-11 22:18:40 +00:00
|
|
|
initializeChrome(uri, isExternalURL);
|
2012-04-23 14:47:46 +00:00
|
|
|
|
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();
|
|
|
|
if (data != null && "http".equals(data.getScheme()) &&
|
|
|
|
isHostOnPrefetchWhitelist(data.getHost())) {
|
|
|
|
Intent copy = new Intent(intent);
|
|
|
|
copy.setAction(ACTION_LOAD);
|
|
|
|
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-03-16 16:29:37 +00:00
|
|
|
passedUri = "about:empty";
|
2012-01-10 07:50:56 +00:00
|
|
|
}
|
|
|
|
|
2012-08-01 07:51:12 +00:00
|
|
|
if (!mIsRestoringActivity) {
|
|
|
|
sGeckoThread = new GeckoThread(intent, passedUri, mRestoreMode);
|
|
|
|
}
|
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() {
|
|
|
|
Log.i(LOGTAG, "Launching from debug intent after 5s wait");
|
|
|
|
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 */);
|
|
|
|
Log.i(LOGTAG, "Intent : ACTION_DEBUG - waiting 5s before launching");
|
|
|
|
}
|
2012-01-04 05:47:48 +00:00
|
|
|
|
2012-06-13 17:52:46 +00:00
|
|
|
Tabs.registerOnTabsChangedListener(this);
|
2011-11-18 18:28:17 +00:00
|
|
|
|
|
|
|
if (cameraView == null) {
|
|
|
|
cameraView = new SurfaceView(this);
|
|
|
|
cameraView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
|
|
|
|
}
|
|
|
|
|
2012-08-20 19:43:53 +00:00
|
|
|
if (mLayerView == null) {
|
2012-08-20 19:43:53 +00:00
|
|
|
mLayerView = (LayerView) findViewById(R.id.layer_view);
|
2012-08-20 19:43:53 +00:00
|
|
|
mLayerView.createLayerClient(GeckoAppShell.getEventDispatcher());
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
|
2011-12-02 23:41:14 +00:00
|
|
|
mPluginContainer = (AbsoluteLayout) findViewById(R.id.plugin_container);
|
2012-03-06 19:56:41 +00:00
|
|
|
mFormAssistPopup = (FormAssistPopup) findViewById(R.id.form_assist_popup);
|
2012-02-14 21:30:15 +00:00
|
|
|
|
2012-01-13 19:08:39 +00:00
|
|
|
Log.w(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - UI almost up");
|
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:LocationChange");
|
|
|
|
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("CharEncoding:Data");
|
|
|
|
registerEventListener("CharEncoding:State");
|
|
|
|
registerEventListener("Update:Restart");
|
|
|
|
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");
|
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-04-05 00:31:19 +00:00
|
|
|
mBatteryReceiver = new GeckoBatteryManager();
|
|
|
|
mBatteryReceiver.registerFor(mAppContext);
|
|
|
|
|
2012-04-05 00:29:30 +00:00
|
|
|
mConnectivityReceiver = new GeckoConnectivityReceiver();
|
|
|
|
mConnectivityReceiver.registerFor(mAppContext);
|
|
|
|
|
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-08-03 01:38:45 +00:00
|
|
|
(TextSelectionHandle) findViewById(R.id.end_handle),
|
|
|
|
GeckoAppShell.getEventDispatcher());
|
2012-07-19 20:16:44 +00:00
|
|
|
|
2012-01-16 17:17:34 +00:00
|
|
|
GeckoNetworkManager.getInstance().init();
|
2012-04-05 00:29:30 +00:00
|
|
|
GeckoNetworkManager.getInstance().start();
|
|
|
|
|
|
|
|
GeckoScreenOrientationListener.getInstance().start();
|
2012-01-17 18:40:39 +00:00
|
|
|
|
2011-12-14 17:35:58 +00:00
|
|
|
final GeckoApp self = this;
|
2012-01-24 16:06:47 +00:00
|
|
|
|
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-01-13 19:08:39 +00:00
|
|
|
Log.w(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - pre checkLaunchState");
|
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
|
|
|
|
|
|
|
/*
|
|
|
|
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-07-18 00:54:54 +00:00
|
|
|
class RedirectorRunnable implements Runnable {
|
2012-01-10 07:50:56 +00:00
|
|
|
Intent mIntent;
|
|
|
|
RedirectorRunnable(Intent intent) {
|
|
|
|
mIntent = intent;
|
|
|
|
}
|
|
|
|
public void run() {
|
|
|
|
HttpURLConnection connection = null;
|
|
|
|
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
|
|
|
|
connection = (HttpURLConnection) url.openConnection();
|
|
|
|
connection.setRequestProperty("User-Agent", getUAStringForHost(url.getHost()));
|
|
|
|
connection.setInstanceFollowRedirects(false);
|
|
|
|
connection.setRequestMethod("GET");
|
|
|
|
connection.connect();
|
|
|
|
int code = connection.getResponseCode();
|
|
|
|
if (code >= 300 && code < 400) {
|
|
|
|
String location = connection.getHeaderField("Location");
|
|
|
|
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) {
|
|
|
|
Log.i(LOGTAG, "exception trying to pre-fetch redirected url", ioe);
|
|
|
|
mIntent.putExtra("prefetched", 1);
|
|
|
|
} 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 (connection != null)
|
|
|
|
connection.disconnect();
|
|
|
|
}
|
|
|
|
mMainHandler.postAtFrontOfQueue(new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
onNewIntent(mIntent);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private final String kPrefetchWhiteListArray[] = new String[] {
|
|
|
|
"t.co",
|
|
|
|
"bit.ly",
|
|
|
|
"moz.la",
|
|
|
|
"aje.me",
|
|
|
|
"facebook.com",
|
|
|
|
"goo.gl",
|
|
|
|
"tinyurl.com"
|
|
|
|
};
|
|
|
|
|
|
|
|
private final CopyOnWriteArrayList<String> kPrefetchWhiteList =
|
|
|
|
new CopyOnWriteArrayList<String>(kPrefetchWhiteListArray);
|
|
|
|
|
|
|
|
private boolean isHostOnPrefetchWhitelist(String host) {
|
|
|
|
return kPrefetchWhiteList.contains(host);
|
|
|
|
}
|
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
@Override
|
|
|
|
protected void onNewIntent(Intent intent) {
|
2012-01-13 19:08:39 +00:00
|
|
|
Log.w(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - onNewIntent");
|
2011-11-18 18:28:17 +00:00
|
|
|
|
|
|
|
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()) &&
|
|
|
|
(bundle == null || bundle.getInt("prefetched", 0) != 1) &&
|
|
|
|
isHostOnPrefetchWhitelist(data.getHost())) {
|
|
|
|
GeckoAppShell.getHandler().post(new RedirectorRunnable(intent));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2011-11-18 18:28:17 +00:00
|
|
|
final String action = intent.getAction();
|
|
|
|
|
|
|
|
if (Intent.ACTION_MAIN.equals(action)) {
|
|
|
|
Log.i(LOGTAG, "Intent : ACTION_MAIN");
|
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-06-10 23:44:50 +00:00
|
|
|
loadUrl(uri, AwesomeBar.Target.CURRENT_TAB);
|
2012-01-10 07:50:56 +00:00
|
|
|
Log.i(LOGTAG,"onNewIntent: " + uri);
|
|
|
|
}
|
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-23 08:43:08 +00:00
|
|
|
Log.i(LOGTAG,"onNewIntent: " + 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));
|
2012-06-18 17:03:03 +00:00
|
|
|
Log.i(LOGTAG,"Intent : WEBAPP (" + action + ") - " + 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
|
|
|
Log.i(LOGTAG,"Intent : BOOKMARK - " + 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-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-01-28 17:24:51 +00:00
|
|
|
String uri = intent.getDataString();
|
|
|
|
if (uri != null)
|
|
|
|
return uri;
|
|
|
|
|
|
|
|
final String action = intent.getAction();
|
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()
|
|
|
|
{
|
|
|
|
Log.i(LOGTAG, "resume");
|
2012-02-15 20:34:31 +00:00
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
// 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
|
|
|
|
|
|
|
// 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()
|
|
|
|
{
|
|
|
|
Log.i(LOGTAG, "stop");
|
|
|
|
// 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()
|
|
|
|
{
|
|
|
|
Log.i(LOGTAG, "pause");
|
|
|
|
|
|
|
|
// 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();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
super.onPause();
|
|
|
|
}
|
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
@Override
|
|
|
|
public void onRestart()
|
|
|
|
{
|
|
|
|
Log.i(LOGTAG, "restart");
|
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-01-13 19:08:39 +00:00
|
|
|
Log.w(LOGTAG, "zerdatime " + SystemClock.uptimeMillis() + " - onStart");
|
2011-11-18 18:28:17 +00:00
|
|
|
|
|
|
|
Log.i(LOGTAG, "start");
|
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()
|
|
|
|
{
|
|
|
|
Log.i(LOGTAG, "destroy");
|
|
|
|
|
|
|
|
// 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:LocationChange");
|
|
|
|
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("CharEncoding:Data");
|
|
|
|
unregisterEventListener("CharEncoding:State");
|
|
|
|
unregisterEventListener("Update:Restart");
|
|
|
|
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");
|
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-04-30 20:17:29 +00:00
|
|
|
if (mBatteryReceiver != null)
|
|
|
|
mBatteryReceiver.unregisterFor(mAppContext);
|
2012-03-08 23:48:44 +00:00
|
|
|
|
2012-04-03 18:58:01 +00:00
|
|
|
((GeckoApplication) getApplication()).removeApplicationLifecycleCallbacks(this);
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
|
2012-08-04 07:33:07 +00:00
|
|
|
private void registerEventListener(String event) {
|
|
|
|
GeckoAppShell.getEventDispatcher().registerEventListener(event, this);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void unregisterEventListener(String event) {
|
|
|
|
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
|
2011-12-21 08:03:34 +00:00
|
|
|
public void onConfigurationChanged(Configuration newConfig)
|
2011-11-18 18:28:17 +00:00
|
|
|
{
|
|
|
|
Log.i(LOGTAG, "configuration changed");
|
2011-12-07 00:44:08 +00:00
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onLowMemory()
|
|
|
|
{
|
|
|
|
Log.e(LOGTAG, "low memory");
|
|
|
|
if (checkLaunchState(LaunchState.GeckoRunning))
|
|
|
|
GeckoAppShell.onLowMemory();
|
|
|
|
super.onLowMemory();
|
2012-04-26 19:47:59 +00:00
|
|
|
GeckoAppShell.geckoEventSync();
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
|
2012-04-03 18:58:01 +00:00
|
|
|
@Override
|
|
|
|
public void onApplicationPause() {
|
|
|
|
Log.i(LOGTAG, "application paused");
|
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createPauseEvent(true));
|
2012-04-05 00:29:30 +00:00
|
|
|
|
2012-04-23 20:58:14 +00:00
|
|
|
if (mConnectivityReceiver != null)
|
|
|
|
mConnectivityReceiver.unregisterFor(mAppContext);
|
2012-04-05 00:29:30 +00:00
|
|
|
GeckoNetworkManager.getInstance().stop();
|
|
|
|
GeckoScreenOrientationListener.getInstance().stop();
|
2012-04-03 18:58:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onApplicationResume() {
|
|
|
|
Log.i(LOGTAG, "application resumed");
|
|
|
|
if (checkLaunchState(LaunchState.GeckoRunning))
|
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createResumeEvent(true));
|
2012-04-05 00:29:30 +00:00
|
|
|
|
2012-04-23 20:58:14 +00:00
|
|
|
if (mConnectivityReceiver != null)
|
|
|
|
mConnectivityReceiver.registerFor(mAppContext);
|
2012-04-05 00:29:30 +00:00
|
|
|
GeckoNetworkManager.getInstance().start();
|
|
|
|
GeckoScreenOrientationListener.getInstance().start();
|
2012-04-03 18:58:01 +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) {
|
|
|
|
Log.i(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);
|
|
|
|
Log.i(LOGTAG, intent.toString());
|
|
|
|
GeckoAppShell.killAnyZombies();
|
|
|
|
startActivity(intent);
|
|
|
|
} catch (Exception e) {
|
2012-08-22 15:37:08 +00:00
|
|
|
Log.e(LOGTAG, "error doing 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void checkAndLaunchUpdate() {
|
|
|
|
Log.i(LOGTAG, "Checking for an update");
|
|
|
|
|
|
|
|
int statusCode = 8; // UNEXPECTED_ERROR
|
|
|
|
File baseUpdateDir = null;
|
|
|
|
if (Build.VERSION.SDK_INT >= 8)
|
|
|
|
baseUpdateDir = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
|
|
|
|
else
|
|
|
|
baseUpdateDir = new File(Environment.getExternalStorageDirectory().getPath(), "download");
|
|
|
|
|
|
|
|
File updateDir = new File(new File(baseUpdateDir, "updates"),"0");
|
|
|
|
|
|
|
|
File updateFile = new File(updateDir, "update.apk");
|
|
|
|
File statusFile = new File(updateDir, "update.status");
|
|
|
|
|
|
|
|
if (!statusFile.exists() || !readUpdateStatus(statusFile).equals("pending"))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!updateFile.exists())
|
|
|
|
return;
|
|
|
|
|
|
|
|
Log.i(LOGTAG, "Update is available!");
|
|
|
|
|
|
|
|
// Launch APK
|
|
|
|
File updateFileToRun = new File(updateDir, getPackageName() + "-update.apk");
|
|
|
|
try {
|
|
|
|
if (updateFile.renameTo(updateFileToRun)) {
|
|
|
|
String amCmd = "/system/bin/am start -a android.intent.action.VIEW " +
|
|
|
|
"-n com.android.packageinstaller/.PackageInstallerActivity -d file://" +
|
|
|
|
updateFileToRun.getPath();
|
|
|
|
Log.i(LOGTAG, amCmd);
|
|
|
|
Runtime.getRuntime().exec(amCmd);
|
|
|
|
statusCode = 0; // OK
|
|
|
|
} else {
|
|
|
|
Log.i(LOGTAG, "Cannot rename the update file!");
|
|
|
|
statusCode = 7; // WRITE_ERROR
|
|
|
|
}
|
|
|
|
} catch (Exception e) {
|
|
|
|
Log.i(LOGTAG, "error launching installer to update", e);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the status file
|
|
|
|
String status = statusCode == 0 ? "succeeded\n" : "failed: "+ statusCode + "\n";
|
|
|
|
|
|
|
|
OutputStream outStream;
|
|
|
|
try {
|
|
|
|
byte[] buf = status.getBytes("UTF-8");
|
|
|
|
outStream = new FileOutputStream(statusFile);
|
|
|
|
outStream.write(buf, 0, buf.length);
|
|
|
|
outStream.close();
|
|
|
|
} catch (Exception e) {
|
|
|
|
Log.i(LOGTAG, "error writing status file", e);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (statusCode == 0)
|
|
|
|
System.exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
private String readUpdateStatus(File statusFile) {
|
|
|
|
String status = "";
|
|
|
|
try {
|
|
|
|
BufferedReader reader = new BufferedReader(new FileReader(statusFile));
|
|
|
|
status = reader.readLine();
|
|
|
|
reader.close();
|
|
|
|
} catch (Exception e) {
|
|
|
|
Log.i(LOGTAG, "error reading update status", e);
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2011-12-19 21:56:11 +00:00
|
|
|
private void checkMigrateProfile() {
|
2012-04-17 20:01:28 +00:00
|
|
|
final File profileDir = getProfile().getDir();
|
|
|
|
final long currentTime = SystemClock.uptimeMillis();
|
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() {
|
|
|
|
Log.i(LOGTAG, "Checking profile migration in: " + profileDir.getAbsolutePath());
|
|
|
|
|
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.
|
|
|
|
if (!profileMigrator.hasMigrationRun()) {
|
2012-04-19 20:07:39 +00:00
|
|
|
// Show the "Setting up Fennec" screen if this takes
|
|
|
|
// a while.
|
2012-04-19 14:41:52 +00:00
|
|
|
final SetupScreen setupScreen = new SetupScreen(app);
|
|
|
|
|
2012-04-19 20:07:39 +00:00
|
|
|
final Runnable startCallback = new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
GeckoApp.mAppContext.runOnUiThread(new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
setupScreen.show();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
final Runnable stopCallback = new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
GeckoApp.mAppContext.runOnUiThread(new Runnable() {
|
|
|
|
public void run() {
|
|
|
|
setupScreen.dismiss();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
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-04-17 20:01:28 +00:00
|
|
|
|
|
|
|
long timeDiff = SystemClock.uptimeMillis() - currentTime;
|
|
|
|
Log.i(LOGTAG, "Profile migration took " + timeDiff + " ms");
|
|
|
|
|
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();
|
|
|
|
if (profileDir != null) {
|
|
|
|
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()) {
|
|
|
|
Log.i(LOGTAG, "Checking Sync settings in: " + profileDir.getAbsolutePath());
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2011-12-08 01:52:07 +00:00
|
|
|
// If searchEngine is provided, url will be used as the search query.
|
|
|
|
// Otherwise, the url is loaded.
|
2012-06-11 22:18:40 +00:00
|
|
|
protected void loadRequest(String url, AwesomeBar.Target target, String searchEngine, boolean userEntered) {
|
2012-06-10 23:44:50 +00:00
|
|
|
Log.d(LOGTAG, target.name());
|
2011-12-08 01:52:07 +00:00
|
|
|
JSONObject args = new JSONObject();
|
|
|
|
try {
|
|
|
|
args.put("url", url);
|
|
|
|
args.put("engine", searchEngine);
|
2012-02-23 02:26:04 +00:00
|
|
|
args.put("userEntered", userEntered);
|
2011-12-08 01:52:07 +00:00
|
|
|
} catch (Exception e) {
|
|
|
|
Log.e(LOGTAG, "error building JSON arguments");
|
|
|
|
}
|
2012-06-10 23:44:50 +00:00
|
|
|
|
|
|
|
if (target == AwesomeBar.Target.NEW_TAB) {
|
2012-03-12 19:48:55 +00:00
|
|
|
Log.d(LOGTAG, "Sending message to Gecko: " + SystemClock.uptimeMillis() + " - Tab:Add");
|
2012-02-09 07:18:27 +00:00
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Tab:Add", args.toString()));
|
2011-11-18 18:28:17 +00:00
|
|
|
} else {
|
2012-02-09 07:18:27 +00:00
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Tab:Load", args.toString()));
|
2011-11-18 18:28:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-11 14:59:50 +00:00
|
|
|
public void loadUrl(String url) {
|
|
|
|
loadRequest(url, AwesomeBar.Target.CURRENT_TAB, null, false);
|
|
|
|
}
|
|
|
|
|
2012-06-10 23:44:50 +00:00
|
|
|
public void loadUrl(String url, AwesomeBar.Target target) {
|
|
|
|
loadRequest(url, target, null, false);
|
2011-12-08 01:52:07 +00:00
|
|
|
}
|
|
|
|
|
2011-12-19 18:44:52 +00:00
|
|
|
/**
|
2012-01-03 18:57:24 +00:00
|
|
|
* Open the url as a new tab, and mark the selected tab as its "parent".
|
|
|
|
* If the url is already open in a tab, the existing tab is selected.
|
2011-12-19 18:44:52 +00:00
|
|
|
* Use this for tabs opened by the browser chrome, so users can press the
|
|
|
|
* "Back" button to return to the previous tab.
|
|
|
|
*/
|
2012-01-03 18:57:24 +00:00
|
|
|
public void loadUrlInTab(String url) {
|
2012-08-09 20:52:58 +00:00
|
|
|
Tabs tabsInstance = Tabs.getInstance();
|
|
|
|
Iterable<Tab> tabs = tabsInstance.getTabsInOrder();
|
|
|
|
for (Tab tab : tabs) {
|
|
|
|
if (url.equals(tab.getURL())) {
|
|
|
|
tabsInstance.selectTab(tab.getId());
|
|
|
|
return;
|
2012-01-03 18:57:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-19 18:44:52 +00:00
|
|
|
JSONObject args = new JSONObject();
|
|
|
|
try {
|
|
|
|
args.put("url", url);
|
2012-08-09 20:52:58 +00:00
|
|
|
args.put("parentId", tabsInstance.getSelectedTab().getId());
|
2011-12-19 18:44:52 +00:00
|
|
|
} catch (Exception e) {
|
|
|
|
Log.e(LOGTAG, "error building JSON arguments");
|
|
|
|
}
|
2012-01-24 17:16:18 +00:00
|
|
|
Log.i(LOGTAG, "Sending message to Gecko: " + SystemClock.uptimeMillis() + " - Tab:Add");
|
2012-02-09 07:18:27 +00:00
|
|
|
GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("Tab:Add", args.toString()));
|
2011-12-19 18:44:52 +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; }
|
|
|
|
|
2011-11-18 18:28:17 +00:00
|
|
|
// accelerometer
|
2012-03-21 06:36:17 +00:00
|
|
|
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
|
2011-11-18 18:28:17 +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
|
|
|
}
|
|
|
|
|
|
|
|
// geolocation
|
|
|
|
public void onLocationChanged(Location location)
|
|
|
|
{
|
|
|
|
Log.w(LOGTAG, "onLocationChanged "+location);
|
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
|
|
|
|
|
|
|
private void connectGeckoLayerClient() {
|
2012-08-20 19:43:53 +00:00
|
|
|
mLayerView.getLayerClient().notifyGeckoReady();
|
2012-04-04 15:55:40 +00:00
|
|
|
|
2012-08-20 19:43:53 +00:00
|
|
|
mLayerView.getTouchEventHandler().setOnTouchListener(new ContentTouchListener() {
|
2012-07-10 21:12:53 +00:00
|
|
|
private PointF initialPoint = null;
|
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
|
|
|
|
2012-07-20 17:06:01 +00:00
|
|
|
if (super.onTouch(view, event))
|
2012-06-19 21:10:42 +00:00
|
|
|
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-07-20 17:06:01 +00:00
|
|
|
protected class ContentTouchListener implements OnInterceptTouchListener {
|
|
|
|
private boolean mIsHidingTabs = false;
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onInterceptTouchEvent(View view, MotionEvent event) {
|
|
|
|
// If the tab tray is showing, hide the tab tray and don't send the event to content.
|
|
|
|
if (event.getActionMasked() == MotionEvent.ACTION_DOWN && autoHideTabs()) {
|
|
|
|
mIsHidingTabs = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean onTouch(View view, MotionEvent event) {
|
|
|
|
if (mIsHidingTabs) {
|
|
|
|
// Keep consuming events until the gesture finishes.
|
|
|
|
int action = event.getActionMasked();
|
|
|
|
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
|
|
|
|
mIsHidingTabs = false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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-08-20 19:43:53 +00:00
|
|
|
mLayerView.setVisibility(View.INVISIBLE);
|
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)) {
|
|
|
|
loadUrl(text, AwesomeBar.Target.CURRENT_TAB);
|
|
|
|
}
|
|
|
|
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-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
|
|
|
}
|