bug 867517 - Gecko-based WebView for Android, refactor patch r=mfinkle

This commit is contained in:
Brad Lassey 2013-05-24 12:21:01 -04:00
parent b6bcc5c7f7
commit 2eb791ed73
34 changed files with 555 additions and 419 deletions

View File

@ -73,13 +73,13 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback {
captureAndroid.camera = null;
captureAndroid.context = 0;
GeckoApp.mAppContext.cameraView.getHolder().
GeckoAppShell.getGeckoInterface().getCameraView().getHolder().
removeCallback(captureAndroid);
ThreadUtils.getUiHandler().post(new Runnable() {
@Override
public void run() {
try {
GeckoApp.mAppContext.disableCameraView();
GeckoAppShell.getGeckoInterface().disableCameraView();
} catch (Exception e) {
Log.e(TAG,
"VideoCaptureAndroid disableCameraView exception: " +
@ -99,12 +99,12 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback {
currentDevice = in_device;
try {
GeckoApp.mAppContext.cameraView.getHolder().addCallback(this);
GeckoAppShell.getGeckoInterface().getCameraView().getHolder().addCallback(this);
ThreadUtils.getUiHandler().post(new Runnable() {
@Override
public void run() {
try {
GeckoApp.mAppContext.enableCameraView();
GeckoAppShell.getGeckoInterface().enableCameraView();
} catch (Exception e) {
Log.e(TAG,
"VideoCaptureAndroid enableCameraView exception: "
@ -122,7 +122,7 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = GeckoApp.mAppContext.getWindowManager().getDefaultDisplay().getRotation();
int rotation = GeckoAppShell.getGeckoInterface().getActivity().getWindowManager().getDefaultDisplay().getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;

View File

@ -181,10 +181,10 @@ public final class ANRReporter extends BroadcastReceiver
}
private static File getPingFile() {
if (GeckoApp.mAppContext == null) {
if (GeckoAppShell.getContext() == null) {
return null;
}
GeckoProfile profile = GeckoApp.mAppContext.getProfile();
GeckoProfile profile = GeckoAppShell.getGeckoInterface().getProfile();
if (profile == null) {
return null;
}
@ -263,9 +263,9 @@ public final class ANRReporter extends BroadcastReceiver
private static long getTotalMem() {
if (Build.VERSION.SDK_INT >= 16 && GeckoApp.mAppContext != null) {
if (Build.VERSION.SDK_INT >= 16 && GeckoAppShell.getContext() != null) {
ActivityManager am = (ActivityManager)
GeckoApp.mAppContext.getSystemService(Context.ACTIVITY_SERVICE);
GeckoAppShell.getContext().getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
am.getMemoryInfo(mi);
mi.totalMem /= 1024L * 1024L;

View File

@ -68,7 +68,7 @@ public class ActivityHandlerHelper {
private int addIntentActivitiesToList(Context context, Intent intent, ArrayList<Prompt.PromptListItem> items, ArrayList<Intent> aIntents) {
PackageManager pm = context.getPackageManager();
List<ResolveInfo> lri = pm.queryIntentActivityOptions(GeckoApp.mAppContext.getComponentName(), null, intent, 0);
List<ResolveInfo> lri = pm.queryIntentActivityOptions(GeckoAppShell.getGeckoInterface().getActivity().getComponentName(), null, intent, 0);
if (lri == null) {
return 0;
@ -163,7 +163,7 @@ public class ActivityHandlerHelper {
return intents.get(0);
}
final PromptService ps = GeckoApp.mAppContext.getPromptService();
final PromptService ps = GeckoAppShell.getGeckoInterface().getPromptService();
final String title = getFilePickerTitle(context, aMimeType);
// Runnable has to be called to show an intent-like

View File

@ -76,7 +76,7 @@ class AndroidImportPreference extends MultiChoicePreference {
final Runnable stopCallback = new Runnable() {
@Override
public void run() {
GeckoApp.mAppContext.runOnUiThread(new Runnable() {
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
dialog.dismiss();

View File

@ -957,7 +957,7 @@ abstract public class BrowserApp extends GeckoApp
// Display notification for Mozilla data reporting, if data should be collected.
if (AppConstants.MOZ_DATA_REPORTING) {
DataReportingNotification.checkAndNotifyPolicy(BrowserApp.mAppContext);
DataReportingNotification.checkAndNotifyPolicy(GeckoAppShell.getContext());
}
} else if (event.equals("Telemetry:Gather")) {

View File

@ -1178,7 +1178,7 @@ public class BrowserToolbar implements Tabs.OnTabsChangedListener,
if (!mHasSoftMenuButton)
return false;
GeckoApp.mAppContext.invalidateOptionsMenu();
GeckoAppShell.getGeckoInterface().invalidateOptionsMenu();
if (mMenuPopup != null && !mMenuPopup.isShowing())
mMenuPopup.showAsDropDown(mMenu);

View File

@ -39,7 +39,7 @@ public class BrowserToolbarLayout extends GeckoRelativeLayout {
post(new Runnable() {
@Override
public void run() {
((BrowserApp)GeckoApp.mAppContext).refreshToolbarHeight();
((BrowserApp)GeckoAppShell.getContext()).refreshToolbarHeight();
}
});
}

View File

@ -30,7 +30,7 @@ class CameraVideoResultHandler implements ActivityResultHandler {
return;
}
Cursor cursor = GeckoApp.mAppContext.managedQuery(data.getData(),
Cursor cursor = GeckoAppShell.getGeckoInterface().getActivity().managedQuery(data.getData(),
new String[] { MediaStore.Video.Media.DATA },
null,
null,

View File

@ -0,0 +1,6 @@
package org.mozilla.gecko;
import android.content.Context;
interface ContextGetter {
Context getContext();
}

View File

@ -51,7 +51,7 @@ public class Favicons {
private LruCache<String, Bitmap> mFaviconsCache;
private LruCache<String, Long> mFailedCache;
private LruCache<String, Integer> mColorCache;
private static final String USER_AGENT = GeckoApp.mAppContext.getDefaultUAString();
private static final String USER_AGENT = GeckoAppShell.getGeckoInterface().getDefaultUAString();
private AndroidHttpClient mHttpClient;
public interface OnFaviconLoadedListener {

View File

@ -40,7 +40,7 @@ abstract class FilePickerResultHandler implements ActivityResultHandler {
return path == null ? "" : path;
}
try {
ContentResolver cr = GeckoApp.mAppContext.getContentResolver();
ContentResolver cr = GeckoAppShell.getContext().getContentResolver();
Cursor cursor = cr.query(uri, new String[] { OpenableColumns.DISPLAY_NAME },
null, null, null);
String name = null;
@ -63,7 +63,7 @@ abstract class FilePickerResultHandler implements ActivityResultHandler {
fileExt = name.substring(period);
fileName = name.substring(0, period);
}
File file = File.createTempFile(fileName, fileExt, GeckoLoader.getGREDir(GeckoApp.mAppContext));
File file = File.createTempFile(fileName, fileExt, GeckoLoader.getGREDir(GeckoAppShell.getContext()));
FileOutputStream fos = new FileOutputStream(file);
InputStream is = cr.openInputStream(uri);
byte[] buf = new byte[4096];

View File

@ -188,7 +188,7 @@ public class FormAssistPopup extends RelativeLayout implements GeckoEventListene
private void positionAndShowPopup(JSONObject rect, boolean isAutoComplete) {
// Don't show the form assist popup when using fullscreen VKB
InputMethodManager imm =
(InputMethodManager) GeckoApp.mAppContext.getSystemService(Context.INPUT_METHOD_SERVICE);
(InputMethodManager) GeckoAppShell.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm.isFullscreenMode())
return;
@ -205,7 +205,7 @@ public class FormAssistPopup extends RelativeLayout implements GeckoEventListene
sValidationMessageHeight = (int) (res.getDimension(R.dimen.validation_message_height));
}
ImmutableViewportMetrics viewportMetrics = GeckoApp.mAppContext.getLayerView().getViewportMetrics();
ImmutableViewportMetrics viewportMetrics = GeckoAppShell.getGeckoInterface().getLayerView().getViewportMetrics();
float zoom = viewportMetrics.zoomFactor;
// These values correspond to the input box for which we want to

View File

@ -120,10 +120,10 @@ public class GeckoAccessibility {
private static void sendDirectAccessibilityEvent(int eventType, JSONObject message) {
final AccessibilityEvent accEvent = AccessibilityEvent.obtain(eventType);
accEvent.setClassName(GeckoAccessibility.class.getName());
accEvent.setPackageName(GeckoApp.mAppContext.getPackageName());
accEvent.setPackageName(GeckoAppShell.getContext().getPackageName());
populateEventFromJSON(accEvent, message);
AccessibilityManager accessibilityManager =
(AccessibilityManager) GeckoApp.mAppContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
(AccessibilityManager) GeckoAppShell.getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
try {
accessibilityManager.sendAccessibilityEvent(accEvent);
} catch (IllegalStateException e) {
@ -153,7 +153,7 @@ public class GeckoAccessibility {
} else {
// In Jelly Bean we populate an AccessibilityNodeInfo with the minimal amount of data to have
// it work with TalkBack.
final LayerView view = GeckoApp.mAppContext.getLayerView();
final LayerView view = GeckoAppShell.getGeckoInterface().getLayerView();
if (view == null)
return;
@ -275,7 +275,7 @@ public class GeckoAccessibility {
info.setParent(host);
info.setSource(host, virtualDescendantId);
info.setVisibleToUser(true);
info.setPackageName(GeckoApp.mAppContext.getPackageName());
info.setPackageName(GeckoAppShell.getContext().getPackageName());
info.setClassName(host.getClass().getName());
info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);

View File

@ -41,13 +41,6 @@ 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;
@ -112,10 +105,10 @@ import java.util.regex.Pattern;
abstract public class GeckoApp
extends GeckoActivity
implements GeckoEventListener, SensorEventListener, LocationListener,
implements GeckoEventListener, SensorEventListener, LocationListener,
Tabs.OnTabsChangedListener, GeckoEventResponder,
GeckoMenu.Callback, GeckoMenu.MenuPresenter,
TouchEventInterceptor
TouchEventInterceptor, ContextGetter, GeckoAppShell.GeckoInterface
{
private static final String LOGTAG = "GeckoApp";
@ -147,7 +140,7 @@ abstract public class GeckoApp
protected RelativeLayout mGeckoLayout;
public View getView() { return mGeckoLayout; }
public SurfaceView cameraView;
public static GeckoApp mAppContext;
private static GeckoApp sAppContext;
protected MenuPanel mMenuPanel;
protected Menu mMenu;
private static GeckoThread sGeckoThread;
@ -204,6 +197,30 @@ abstract public class GeckoApp
void focusChrome() { }
public Context getContext() {
return sAppContext;
}
public Activity getActivity() {
return this;
}
public LocationListener getLocationListener() {
return this;
}
public SensorEventListener getSensorEventListener() {
return this;
}
public SurfaceView getCameraView() {
return cameraView;
}
public FormAssistPopup getFormAssistPopup() {
return mFormAssistPopup;
}
@Override
public void onTabChanged(Tab tab, Tabs.TabEvents msg, Object data) {
// When a tab is closed, it is always unselected first.
@ -241,206 +258,6 @@ abstract public class GeckoApp
public void refreshChrome() { }
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>();
// Returns null if plugins are blocked on the device.
String[] getPluginDirectories() {
// 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)");
return null;
}
}
} catch (IOException ex) {
// nothing
} finally {
try {
if (vreader != null) {
vreader.close();
}
} catch (IOException ex) {
// nothing
}
}
}
ArrayList<String> directories = new ArrayList<String>();
PackageManager pm = mAppContext.getPackageManager();
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, "Ignoring bad plugin.");
continue;
}
// 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;
}
// 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, "Not 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, "Not 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, "Not 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, "Not 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 defined type.");
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);
}
}
return directories.toArray(new String[directories.size()]);
}
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;
}
Class<?> getPluginClass(String packageName, String className)
throws NameNotFoundException, ClassNotFoundException {
Context pluginContext = mAppContext.createPackageContext(packageName,
Context.CONTEXT_INCLUDE_CODE |
Context.CONTEXT_IGNORE_SECURITY);
ClassLoader pluginCL = pluginContext.getClassLoader();
return pluginCL.loadClass(className);
}
@Override
public void invalidateOptionsMenu() {
if (mMenu == null)
@ -464,7 +281,7 @@ abstract public class GeckoApp
@Override
public MenuInflater getMenuInflater() {
if (Build.VERSION.SDK_INT >= 11)
return new GeckoMenuInflater(mAppContext);
return new GeckoMenuInflater(sAppContext);
else
return super.getMenuInflater();
}
@ -504,7 +321,7 @@ abstract public class GeckoApp
public View onCreatePanelView(int featureId) {
if (Build.VERSION.SDK_INT >= 11 && featureId == Window.FEATURE_OPTIONS_PANEL) {
if (mMenuPanel == null) {
mMenuPanel = new MenuPanel(mAppContext, null);
mMenuPanel = new MenuPanel(this, null);
} else {
// Prepare the panel everytime before showing the menu.
onPreparePanel(featureId, mMenuPanel, mMenu);
@ -523,7 +340,7 @@ abstract public class GeckoApp
mMenuPanel = (MenuPanel) onCreatePanelView(featureId);
}
GeckoMenu gMenu = new GeckoMenu(mAppContext, null);
GeckoMenu gMenu = new GeckoMenu(this, null);
gMenu.setCallback(this);
gMenu.setMenuPresenter(this);
menu = gMenu;
@ -724,14 +541,15 @@ abstract public class GeckoApp
} else if (event.equals("Bookmark:Insert")) {
final String url = message.getString("url");
final String title = message.getString("title");
final Context context = this;
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(GeckoApp.mAppContext, R.string.bookmark_added, Toast.LENGTH_SHORT).show();
Toast.makeText(context, R.string.bookmark_added, Toast.LENGTH_SHORT).show();
ThreadUtils.postToBackgroundThread(new Runnable() {
@Override
public void run() {
BrowserDB.addBookmark(GeckoApp.mAppContext.getContentResolver(), title, url);
BrowserDB.addBookmark(GeckoApp.sAppContext.getContentResolver(), title, url);
}
});
}
@ -906,7 +724,7 @@ abstract public class GeckoApp
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(mAppContext, resId, duration).show();
Toast.makeText(sAppContext, resId, duration).show();
}
});
}
@ -917,9 +735,9 @@ abstract public class GeckoApp
public void run() {
Toast toast;
if (duration.equals("long"))
toast = Toast.makeText(mAppContext, message, Toast.LENGTH_LONG);
toast = Toast.makeText(sAppContext, message, Toast.LENGTH_LONG);
else
toast = Toast.makeText(mAppContext, message, Toast.LENGTH_SHORT);
toast = Toast.makeText(sAppContext, message, Toast.LENGTH_SHORT);
toast.show();
}
});
@ -953,7 +771,7 @@ abstract public class GeckoApp
mFullScreenPluginView = view;
}
void addPluginView(final View view, final Rect rect, final boolean isFullScreen) {
public void addPluginView(final View view, final Rect rect, final boolean isFullScreen) {
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
@ -1010,7 +828,7 @@ abstract public class GeckoApp
setFullScreen(false);
}
void removePluginView(final View view, final boolean isFullScreen) {
public void removePluginView(final View view, final boolean isFullScreen) {
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
@ -1031,21 +849,21 @@ abstract public class GeckoApp
}
private void setImageAsWallpaper(final String aSrc) {
final String progText = mAppContext.getString(R.string.wallpaper_progress);
final String successText = mAppContext.getString(R.string.wallpaper_success);
final String failureText = mAppContext.getString(R.string.wallpaper_fail);
final String progText = sAppContext.getString(R.string.wallpaper_progress);
final String successText = sAppContext.getString(R.string.wallpaper_success);
final String failureText = sAppContext.getString(R.string.wallpaper_fail);
final String fileName = aSrc.substring(aSrc.lastIndexOf("/") + 1);
final PendingIntent emptyIntent = PendingIntent.getActivity(mAppContext, 0, new Intent(), 0);
final AlertNotification notification = new AlertNotification(mAppContext, fileName.hashCode(),
final PendingIntent emptyIntent = PendingIntent.getActivity(sAppContext, 0, new Intent(), 0);
final AlertNotification notification = new AlertNotification(sAppContext, fileName.hashCode(),
R.drawable.alert_download, fileName, progText, System.currentTimeMillis(), null);
notification.setLatestEventInfo(mAppContext, fileName, progText, emptyIntent );
notification.setLatestEventInfo(sAppContext, fileName, progText, emptyIntent );
notification.flags |= Notification.FLAG_ONGOING_EVENT;
notification.show();
new UiAsyncTask<Void, Void, Boolean>(ThreadUtils.getBackgroundHandler()) {
@Override
protected Boolean doInBackground(Void... params) {
WallpaperManager mgr = WallpaperManager.getInstance(mAppContext);
WallpaperManager mgr = WallpaperManager.getInstance(sAppContext);
if (mgr == null) {
return false;
}
@ -1163,10 +981,10 @@ abstract public class GeckoApp
notification.flags |= Notification.FLAG_AUTO_CANCEL;
if(!success) {
notification.tickerText = failureText;
notification.setLatestEventInfo(mAppContext, fileName, failureText, emptyIntent);
notification.setLatestEventInfo(sAppContext, fileName, failureText, emptyIntent);
} else {
notification.tickerText = successText;
notification.setLatestEventInfo(mAppContext, fileName, successText, emptyIntent);
notification.setLatestEventInfo(sAppContext, fileName, successText, emptyIntent);
}
notification.show();
}
@ -1305,7 +1123,9 @@ abstract public class GeckoApp
BrowserDB.initialize(getProfile().getName());
((GeckoApplication)getApplication()).initialize();
mAppContext = this;
sAppContext = this;
GeckoAppShell.setContextGetter(this);
GeckoAppShell.setGeckoInterface(this);
ThreadUtils.setUiThread(Thread.currentThread(), new Handler());
Tabs.getInstance().attachToActivity(this);
@ -1378,7 +1198,7 @@ abstract public class GeckoApp
@Override
public void run() {
SharedPreferences prefs =
GeckoApp.mAppContext.getSharedPreferences(PREFS_NAME, 0);
GeckoApp.sAppContext.getSharedPreferences(PREFS_NAME, 0);
boolean wasOOM = prefs.getBoolean(PREFS_OOM_EXCEPTION, false);
boolean wasStopped = prefs.getBoolean(PREFS_WAS_STOPPED, true);
@ -1399,7 +1219,7 @@ abstract public class GeckoApp
final String profilePath = getProfile().getDir().getAbsolutePath();
final EventDispatcher dispatcher = GeckoAppShell.getEventDispatcher();
Log.i(LOGTAG, "Creating BrowserHealthRecorder.");
mHealthRecorder = new BrowserHealthRecorder(GeckoApp.mAppContext, profilePath, dispatcher);
mHealthRecorder = new BrowserHealthRecorder(sAppContext, profilePath, dispatcher);
}
});
@ -1610,7 +1430,7 @@ abstract public class GeckoApp
// Record our launch time for the announcements service
// to use in assessing inactivity.
final Context context = GeckoApp.mAppContext;
final Context context = GeckoApp.sAppContext;
AnnouncementsBroadcastService.recordLastLaunch(context);
// Kick off our background service to fetch product announcements.
@ -1718,7 +1538,7 @@ abstract public class GeckoApp
return RESTORE_OOM;
}
final SharedPreferences prefs = GeckoApp.mAppContext.getSharedPreferences(PREFS_NAME, 0);
final SharedPreferences prefs = GeckoApp.sAppContext.getSharedPreferences(PREFS_NAME, 0);
// We record crashes in the crash reporter. If sessionstore.js
// exists, but we didn't flag a crash in the crash reporter, we
@ -1920,7 +1740,7 @@ abstract public class GeckoApp
@Override
public void run() {
SharedPreferences prefs =
GeckoApp.mAppContext.getSharedPreferences(GeckoApp.PREFS_NAME, 0);
GeckoApp.sAppContext.getSharedPreferences(GeckoApp.PREFS_NAME, 0);
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(GeckoApp.PREFS_WAS_STOPPED, false);
editor.commit();
@ -1948,7 +1768,7 @@ abstract public class GeckoApp
@Override
public void run() {
SharedPreferences prefs =
GeckoApp.mAppContext.getSharedPreferences(GeckoApp.PREFS_NAME, 0);
GeckoApp.sAppContext.getSharedPreferences(GeckoApp.PREFS_NAME, 0);
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(GeckoApp.PREFS_WAS_STOPPED, true);
editor.commit();
@ -1967,7 +1787,7 @@ abstract public class GeckoApp
@Override
public void run() {
SharedPreferences prefs =
GeckoApp.mAppContext.getSharedPreferences(GeckoApp.PREFS_NAME, 0);
GeckoApp.sAppContext.getSharedPreferences(GeckoApp.PREFS_NAME, 0);
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(GeckoApp.PREFS_WAS_STOPPED, false);
editor.commit();
@ -2059,7 +1879,7 @@ abstract public class GeckoApp
// Get a temporary directory, may return null
public static File getTempDirectory() {
File dir = mAppContext.getExternalFilesDir("temp");
File dir = sAppContext.getExternalFilesDir("temp");
return dir;
}
@ -2164,7 +1984,7 @@ abstract public class GeckoApp
final File profileDir = getProfile().getDir();
if (profileDir != null) {
final GeckoApp app = GeckoApp.mAppContext;
final GeckoApp app = GeckoApp.sAppContext;
ThreadUtils.postToBackgroundThread(new Runnable() {
@Override
@ -2187,7 +2007,7 @@ abstract public class GeckoApp
final Runnable startCallback = new Runnable() {
@Override
public void run() {
GeckoApp.mAppContext.runOnUiThread(new Runnable() {
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
setupScreenHolder[0] = new SetupScreen(app);
@ -2200,7 +2020,7 @@ abstract public class GeckoApp
final Runnable stopCallback = new Runnable() {
@Override
public void run() {
GeckoApp.mAppContext.runOnUiThread(new Runnable() {
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
SetupScreen screen = setupScreenHolder[0];
@ -2230,7 +2050,7 @@ abstract public class GeckoApp
private void checkMigrateSync() {
final File profileDir = getProfile().getDir();
if (!GeckoApp.sIsUsingCustomProfile && profileDir != null) {
final GeckoApp app = GeckoApp.mAppContext;
final GeckoApp app = GeckoApp.sAppContext;
ProfileMigrator profileMigrator = new ProfileMigrator(app);
if (!profileMigrator.hasSyncMigrated()) {
profileMigrator.launchSyncPrefs();
@ -2238,7 +2058,7 @@ abstract public class GeckoApp
}
}
PromptService getPromptService() {
public PromptService getPromptService() {
return mPromptService;
}

View File

@ -16,6 +16,7 @@ import org.mozilla.gecko.util.GeckoEventListener;
import org.mozilla.gecko.util.HardwareUtils;
import org.mozilla.gecko.util.ThreadUtils;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
@ -24,8 +25,13 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
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.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@ -39,8 +45,10 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.hardware.SensorEventListener;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.media.MediaScannerConnection;
import android.media.MediaScannerConnection.MediaScannerConnectionClient;
@ -61,9 +69,11 @@ import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.HapticFeedbackConstants;
import android.view.Surface;
import android.view.SurfaceView;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.webkit.MimeTypeMap;
import android.widget.AbsoluteLayout;
import android.widget.Toast;
import java.io.BufferedReader;
@ -82,6 +92,7 @@ import java.net.ProxySelector;
import java.net.URI;
import java.net.URL;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
@ -186,7 +197,7 @@ public class GeckoAppShell
if (e instanceof OutOfMemoryError) {
SharedPreferences prefs =
GeckoApp.mAppContext.getSharedPreferences(GeckoApp.PREFS_NAME, 0);
getContext().getSharedPreferences(GeckoApp.PREFS_NAME, 0);
SharedPreferences.Editor editor = prefs.edit();
editor.putBoolean(GeckoApp.PREFS_OOM_EXCEPTION, true);
editor.commit();
@ -260,6 +271,16 @@ public class GeckoAppShell
}
}
private static LayerView sLayerView;
public static void setLayerView(LayerView lv) {
sLayerView = lv;
}
public static LayerView getLayerView() {
return sLayerView;
}
public static void runGecko(String apkPath, String args, String url, String type) {
Looper.prepare();
@ -267,7 +288,11 @@ public class GeckoAppShell
GeckoAppShell.nativeInit();
// Tell Gecko where the target byte buffer is for rendering
GeckoAppShell.setLayerClient(GeckoApp.mAppContext.getLayerView().getLayerClient());
if (getGeckoInterface() != null)
sLayerView = getGeckoInterface().getLayerView();
if (sLayerView != null)
GeckoAppShell.setLayerClient(sLayerView.getLayerClient());
// First argument is the .apk path
String combinedArgs = apkPath + " -greomni " + apkPath;
@ -278,10 +303,10 @@ public class GeckoAppShell
if (type != null)
combinedArgs += " " + type;
DisplayMetrics metrics = GeckoApp.mAppContext.getResources().getDisplayMetrics();
DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
combinedArgs += " -width " + metrics.widthPixels + " -height " + metrics.heightPixels;
GeckoApp.mAppContext.runOnUiThread(new Runnable() {
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
geckoLoaded();
@ -427,7 +452,7 @@ public class GeckoAppShell
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
LocationManager lm = getLocationManager(GeckoApp.mAppContext);
LocationManager lm = getLocationManager(getContext());
if (lm == null) {
return;
}
@ -435,7 +460,7 @@ public class GeckoAppShell
if (enable) {
Location lastKnownLocation = getLastKnownLocation(lm);
if (lastKnownLocation != null) {
GeckoApp.mAppContext.onLocationChanged(lastKnownLocation);
getGeckoInterface().getLocationListener().onLocationChanged(lastKnownLocation);
}
Criteria criteria = new Criteria();
@ -457,9 +482,9 @@ public class GeckoAppShell
return;
Looper l = Looper.getMainLooper();
lm.requestLocationUpdates(provider, 100, (float).5, GeckoApp.mAppContext, l);
lm.requestLocationUpdates(provider, 100, (float).5, getGeckoInterface().getLocationListener(), l);
} else {
lm.removeUpdates(GeckoApp.mAppContext);
lm.removeUpdates(getGeckoInterface().getLocationListener());
}
}
});
@ -483,50 +508,53 @@ public class GeckoAppShell
}
public static void enableSensor(int aSensortype) {
GeckoInterface gi = getGeckoInterface();
if (gi == null)
return;
SensorManager sm = (SensorManager)
GeckoApp.mAppContext.getSystemService(Context.SENSOR_SERVICE);
getContext().getSystemService(Context.SENSOR_SERVICE);
switch(aSensortype) {
case GeckoHalDefines.SENSOR_ORIENTATION:
if(gOrientationSensor == null)
gOrientationSensor = sm.getDefaultSensor(Sensor.TYPE_ORIENTATION);
if (gOrientationSensor != null)
sm.registerListener(GeckoApp.mAppContext, gOrientationSensor, sDefaultSensorHint);
if (gOrientationSensor != null)
sm.registerListener(gi.getSensorEventListener(), gOrientationSensor, sDefaultSensorHint);
break;
case GeckoHalDefines.SENSOR_ACCELERATION:
if(gAccelerometerSensor == null)
gAccelerometerSensor = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if (gAccelerometerSensor != null)
sm.registerListener(GeckoApp.mAppContext, gAccelerometerSensor, sDefaultSensorHint);
sm.registerListener(gi.getSensorEventListener(), gAccelerometerSensor, sDefaultSensorHint);
break;
case GeckoHalDefines.SENSOR_PROXIMITY:
if(gProximitySensor == null)
if(gProximitySensor == null )
gProximitySensor = sm.getDefaultSensor(Sensor.TYPE_PROXIMITY);
if (gProximitySensor != null)
sm.registerListener(GeckoApp.mAppContext, gProximitySensor, SensorManager.SENSOR_DELAY_NORMAL);
sm.registerListener(gi.getSensorEventListener(), gProximitySensor, SensorManager.SENSOR_DELAY_NORMAL);
break;
case GeckoHalDefines.SENSOR_LIGHT:
if(gLightSensor == null)
gLightSensor = sm.getDefaultSensor(Sensor.TYPE_LIGHT);
if (gLightSensor != null)
sm.registerListener(GeckoApp.mAppContext, gLightSensor, SensorManager.SENSOR_DELAY_NORMAL);
sm.registerListener(gi.getSensorEventListener(), gLightSensor, SensorManager.SENSOR_DELAY_NORMAL);
break;
case GeckoHalDefines.SENSOR_LINEAR_ACCELERATION:
if(gLinearAccelerometerSensor == null)
gLinearAccelerometerSensor = sm.getDefaultSensor(10 /* API Level 9 - TYPE_LINEAR_ACCELERATION */);
if (gLinearAccelerometerSensor != null)
sm.registerListener(GeckoApp.mAppContext, gLinearAccelerometerSensor, sDefaultSensorHint);
sm.registerListener(gi.getSensorEventListener(), gLinearAccelerometerSensor, sDefaultSensorHint);
break;
case GeckoHalDefines.SENSOR_GYROSCOPE:
if(gGyroscopeSensor == null)
gGyroscopeSensor = sm.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
if (gGyroscopeSensor != null)
sm.registerListener(GeckoApp.mAppContext, gGyroscopeSensor, sDefaultSensorHint);
sm.registerListener(gi.getSensorEventListener(), gGyroscopeSensor, sDefaultSensorHint);
break;
default:
Log.w(LOGTAG, "Error! Can't enable unknown SENSOR type " + aSensortype);
@ -534,38 +562,42 @@ public class GeckoAppShell
}
public static void disableSensor(int aSensortype) {
GeckoInterface gi = getGeckoInterface();
if (gi == null)
return;
SensorManager sm = (SensorManager)
GeckoApp.mAppContext.getSystemService(Context.SENSOR_SERVICE);
getContext().getSystemService(Context.SENSOR_SERVICE);
switch (aSensortype) {
case GeckoHalDefines.SENSOR_ORIENTATION:
if (gOrientationSensor != null)
sm.unregisterListener(GeckoApp.mAppContext, gOrientationSensor);
sm.unregisterListener(gi.getSensorEventListener(), gOrientationSensor);
break;
case GeckoHalDefines.SENSOR_ACCELERATION:
if (gAccelerometerSensor != null)
sm.unregisterListener(GeckoApp.mAppContext, gAccelerometerSensor);
sm.unregisterListener(gi.getSensorEventListener(), gAccelerometerSensor);
break;
case GeckoHalDefines.SENSOR_PROXIMITY:
if (gProximitySensor != null)
sm.unregisterListener(GeckoApp.mAppContext, gProximitySensor);
sm.unregisterListener(gi.getSensorEventListener(), gProximitySensor);
break;
case GeckoHalDefines.SENSOR_LIGHT:
if (gLightSensor != null)
sm.unregisterListener(GeckoApp.mAppContext, gLightSensor);
sm.unregisterListener(gi.getSensorEventListener(), gLightSensor);
break;
case GeckoHalDefines.SENSOR_LINEAR_ACCELERATION:
if (gLinearAccelerometerSensor != null)
sm.unregisterListener(GeckoApp.mAppContext, gLinearAccelerometerSensor);
sm.unregisterListener(gi.getSensorEventListener(), gLinearAccelerometerSensor);
break;
case GeckoHalDefines.SENSOR_GYROSCOPE:
if (gGyroscopeSensor != null)
sm.unregisterListener(GeckoApp.mAppContext, gGyroscopeSensor);
sm.unregisterListener(gi.getSensorEventListener(), gGyroscopeSensor);
break;
default:
Log.w(LOGTAG, "Error! Can't disable unknown SENSOR type " + aSensortype);
@ -573,7 +605,8 @@ public class GeckoAppShell
}
public static void moveTaskToBack() {
GeckoApp.mAppContext.moveTaskToBack(true);
if (getGeckoInterface() != null)
getGeckoInterface().getActivity().moveTaskToBack(true);
}
public static void returnIMEQueryResult(String result, int selectionStart, int selectionLength) {
@ -584,10 +617,12 @@ public class GeckoAppShell
static void onXreExit() {
// The launch state can only be Launched or GeckoRunning at this point
GeckoThread.setLaunchState(GeckoThread.LaunchState.GeckoExiting);
if (gRestartScheduled) {
GeckoApp.mAppContext.doRestart();
} else {
GeckoApp.mAppContext.finish();
if (getGeckoInterface() != null) {
if (gRestartScheduled) {
getGeckoInterface().doRestart();
} else {
getGeckoInterface().getActivity().finish();
}
}
Log.d(LOGTAG, "Killing via System.exit()");
@ -599,13 +634,13 @@ public class GeckoAppShell
}
public static File preInstallWebApp(String aTitle, String aURI, String aUniqueURI) {
int index = WebAppAllocator.getInstance(GeckoApp.mAppContext).findAndAllocateIndex(aUniqueURI, aTitle, (String) null);
GeckoProfile profile = GeckoProfile.get(GeckoApp.mAppContext, "webapp" + index);
int index = WebAppAllocator.getInstance(getContext()).findAndAllocateIndex(aUniqueURI, aTitle, (String) null);
GeckoProfile profile = GeckoProfile.get(getContext(), "webapp" + index);
return profile.getDir();
}
public static void postInstallWebApp(String aTitle, String aURI, String aUniqueURI, String aIconURL) {
WebAppAllocator allocator = WebAppAllocator.getInstance(GeckoApp.mAppContext);
WebAppAllocator allocator = WebAppAllocator.getInstance(getContext());
int index = allocator.getIndexForApp(aUniqueURI);
assert index != -1 && aIconURL != null;
allocator.updateAppAllocation(aUniqueURI, index, BitmapUtils.getBitmapFromDataURI(aIconURL));
@ -615,9 +650,9 @@ public class GeckoAppShell
public static Intent getWebAppIntent(String aURI, String aUniqueURI, String aTitle, Bitmap aIcon) {
int index;
if (aIcon != null && !TextUtils.isEmpty(aTitle))
index = WebAppAllocator.getInstance(GeckoApp.mAppContext).findAndAllocateIndex(aUniqueURI, aTitle, aIcon);
index = WebAppAllocator.getInstance(getContext()).findAndAllocateIndex(aUniqueURI, aTitle, aIcon);
else
index = WebAppAllocator.getInstance(GeckoApp.mAppContext).getIndexForApp(aUniqueURI);
index = WebAppAllocator.getInstance(getContext()).getIndexForApp(aUniqueURI);
if (index == -1)
return null;
@ -684,7 +719,7 @@ public class GeckoAppShell
intent.putExtra("duplicate", false);
intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
GeckoApp.mAppContext.sendBroadcast(intent);
getContext().sendBroadcast(intent);
}
});
}
@ -700,7 +735,7 @@ public class GeckoAppShell
// the intent to be launched by the shortcut
Intent shortcutIntent;
if (aType.equalsIgnoreCase(SHORTCUT_TYPE_WEBAPP)) {
int index = WebAppAllocator.getInstance(GeckoApp.mAppContext).getIndexForApp(aUniqueURI);
int index = WebAppAllocator.getInstance(getContext()).getIndexForApp(aUniqueURI);
shortcutIntent = getWebAppIntent(aURI, aUniqueURI, "", null);
if (shortcutIntent == null)
return;
@ -720,7 +755,7 @@ public class GeckoAppShell
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, aURI);
intent.setAction("com.android.launcher.action.UNINSTALL_SHORTCUT");
GeckoApp.mAppContext.sendBroadcast(intent);
getContext().sendBroadcast(intent);
}
});
}
@ -732,17 +767,17 @@ public class GeckoAppShell
ThreadUtils.postToBackgroundThread(new Runnable() {
@Override
public void run() {
int index = WebAppAllocator.getInstance(GeckoApp.mAppContext).releaseIndexForApp(uniqueURI);
int index = WebAppAllocator.getInstance(getContext()).releaseIndexForApp(uniqueURI);
// if -1, nothing to do; we didn't think it was installed anyway
if (index == -1)
return;
// kill the app if it's running
String targetProcessName = GeckoApp.mAppContext.getPackageName();
String targetProcessName = getContext().getPackageName();
targetProcessName = targetProcessName + ":" + targetProcessName + ".WebApp" + index;
ActivityManager am = (ActivityManager) GeckoApp.mAppContext.getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager am = (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningAppProcessInfo> procs = am.getRunningAppProcesses();
if (procs != null) {
for (ActivityManager.RunningAppProcessInfo proc : procs) {
@ -754,14 +789,14 @@ public class GeckoAppShell
}
// then nuke the profile
GeckoProfile.removeProfile(GeckoApp.mAppContext, "webapp" + index);
GeckoProfile.removeProfile(getContext(), "webapp" + index);
}
});
}
static public int getPreferredIconSize() {
if (android.os.Build.VERSION.SDK_INT >= 11) {
ActivityManager am = (ActivityManager)GeckoApp.mAppContext.getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager am = (ActivityManager)getContext().getSystemService(Context.ACTIVITY_SERVICE);
return am.getLauncherLargeIconSize();
} else {
switch (getDpi()) {
@ -807,12 +842,12 @@ public class GeckoAppShell
}
// draw the overlay
Bitmap overlay = BitmapUtils.decodeResource(GeckoApp.mAppContext, R.drawable.home_bg);
Bitmap overlay = BitmapUtils.decodeResource(getContext(), R.drawable.home_bg);
canvas.drawBitmap(overlay, null, new Rect(0, 0, size, size), null);
// draw the favicon
if (aSource == null)
aSource = BitmapUtils.decodeResource(GeckoApp.mAppContext, R.drawable.home_star);
aSource = BitmapUtils.decodeResource(getContext(), R.drawable.home_star);
// by default, we scale the icon to this size
int sWidth = insetSize / 2;
@ -848,20 +883,20 @@ public class GeckoAppShell
// aURL may contain the whole URL or just the protocol
Uri uri = aURL.indexOf(':') >= 0 ? Uri.parse(aURL) : new Uri.Builder().scheme(aURL).build();
Intent intent = getOpenURIIntent(GeckoApp.mAppContext, uri.toString(), "",
Intent intent = getOpenURIIntent(getContext(), uri.toString(), "",
TextUtils.isEmpty(aAction) ? Intent.ACTION_VIEW : aAction, "");
return getHandlersForIntent(intent);
}
static boolean hasHandlersForIntent(Intent intent) {
PackageManager pm = GeckoApp.mAppContext.getPackageManager();
PackageManager pm = getContext().getPackageManager();
List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
return !list.isEmpty();
}
static String[] getHandlersForIntent(Intent intent) {
PackageManager pm = GeckoApp.mAppContext.getPackageManager();
PackageManager pm = getContext().getPackageManager();
List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
int numAttr = 4;
String[] ret = new String[list.size() * numAttr];
@ -985,14 +1020,14 @@ public class GeckoAppShell
} finally {
safeStreamClose(os);
}
GeckoApp.mAppContext.startActivity(Intent.createChooser(intent,
GeckoApp.mAppContext.getResources().getString(R.string.share_title)));
getContext().startActivity(Intent.createChooser(intent,
getContext().getResources().getString(R.string.share_title)));
}
// Don't fail silently, tell the user that we weren't able to share the image
private static final void showImageShareFailureToast() {
Toast toast = Toast.makeText(GeckoApp.mAppContext,
GeckoApp.mAppContext.getResources().getString(R.string.share_image_failed),
Toast toast = Toast.makeText(getContext(),
getContext().getResources().getString(R.string.share_image_failed),
Toast.LENGTH_SHORT);
toast.show();
}
@ -1029,7 +1064,7 @@ public class GeckoAppShell
String className,
String action,
String title) {
final Context context = GeckoApp.mAppContext;
final Context context = getContext();
final Intent intent = getOpenURIIntent(context, targetURI,
mimeType, action, title);
@ -1184,7 +1219,7 @@ public class GeckoAppShell
* on a thread with a looper, so this function requires a looper is
* present on the thread. */
private static String getClipboardTextImpl() {
Context context = GeckoApp.mAppContext;
Context context = getContext();
if (android.os.Build.VERSION.SDK_INT >= 11) {
android.content.ClipboardManager cm = (android.content.ClipboardManager)context.getSystemService(Context.CLIPBOARD_SERVICE);
if (cm.hasPrimaryClip()) {
@ -1238,7 +1273,7 @@ public class GeckoAppShell
ThreadUtils.postToBackgroundThread(new Runnable() {
@Override
public void run() {
Context context = GeckoApp.mAppContext;
Context context = getContext();
if (android.os.Build.VERSION.SDK_INT >= 11) {
android.content.ClipboardManager cm = (android.content.ClipboardManager)
context.getSystemService(Context.CLIPBOARD_SERVICE);
@ -1270,7 +1305,7 @@ public class GeckoAppShell
"- name = '" + aAlertName + "'");
// The intent to launch when the user clicks the expanded notification
String app = GeckoApp.mAppContext.getClass().getName();
String app = getContext().getClass().getName();
Intent notificationIntent = new Intent(GeckoApp.ACTION_ALERT_CALLBACK);
notificationIntent.setClassName(AppConstants.ANDROID_PACKAGE_NAME, app);
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@ -1285,7 +1320,7 @@ public class GeckoAppShell
.build();
notificationIntent.setData(dataUri);
PendingIntent contentIntent = PendingIntent.getActivity(
GeckoApp.mAppContext, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
getContext(), 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
mAlertCookies.put(aAlertName, aAlertCookie);
callObserver(aAlertName, "alertshow", aAlertCookie);
@ -1338,29 +1373,34 @@ public class GeckoAppShell
public static int getDpi() {
if (sDensityDpi == 0) {
sDensityDpi = GeckoApp.mAppContext.getResources().getDisplayMetrics().densityDpi;
sDensityDpi = getContext().getResources().getDisplayMetrics().densityDpi;
}
return sDensityDpi;
}
public static void setFullScreen(boolean fullscreen) {
GeckoApp.mAppContext.setFullScreen(fullscreen);
if (getGeckoInterface() != null)
getGeckoInterface().setFullScreen(fullscreen);
}
public static String showFilePickerForExtensions(String aExtensions) {
return sActivityHelper.showFilePicker(GeckoApp.mAppContext, getMimeTypeFromExtensions(aExtensions));
if (getGeckoInterface() != null)
return sActivityHelper.showFilePicker(getGeckoInterface().getActivity(), getMimeTypeFromExtensions(aExtensions));
return "";
}
public static String showFilePickerForMimeType(String aMimeType) {
return sActivityHelper.showFilePicker(GeckoApp.mAppContext, aMimeType);
if (getGeckoInterface() != null)
return sActivityHelper.showFilePicker(getGeckoInterface().getActivity(), aMimeType);
return "";
}
public static void performHapticFeedback(boolean aIsLongPress) {
// Don't perform haptic feedback if a vibration is currently playing,
// because the haptic feedback will nuke the vibration.
if (!sVibrationMaybePlaying || System.nanoTime() >= sVibrationEndTime) {
LayerView layerView = GeckoApp.mAppContext.getLayerView();
LayerView layerView = getLayerView();
layerView.performHapticFeedback(aIsLongPress ?
HapticFeedbackConstants.LONG_PRESS :
HapticFeedbackConstants.VIRTUAL_KEY);
@ -1368,7 +1408,7 @@ public class GeckoAppShell
}
private static Vibrator vibrator() {
LayerView layerView = GeckoApp.mAppContext.getLayerView();
LayerView layerView = getLayerView();
return (Vibrator) layerView.getContext().getSystemService(Context.VIBRATOR_SERVICE);
}
@ -1400,12 +1440,12 @@ public class GeckoAppShell
public static void showInputMethodPicker() {
InputMethodManager imm = (InputMethodManager)
GeckoApp.mAppContext.getSystemService(Context.INPUT_METHOD_SERVICE);
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showInputMethodPicker();
}
public static void setKeepScreenOn(final boolean on) {
GeckoApp.mAppContext.runOnUiThread(new Runnable() {
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
// TODO
@ -1417,7 +1457,7 @@ public class GeckoAppShell
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
LayerView view = GeckoApp.mAppContext.getLayerView();
LayerView view = getLayerView();
PanZoomController controller = (view == null ? null : view.getPanZoomController());
if (controller != null) {
controller.notifyDefaultActionPrevented(defaultPrevented);
@ -1428,7 +1468,7 @@ public class GeckoAppShell
public static boolean isNetworkLinkUp() {
ConnectivityManager cm = (ConnectivityManager)
GeckoApp.mAppContext.getSystemService(Context.CONNECTIVITY_SERVICE);
getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
if (info == null || !info.isConnected())
return false;
@ -1437,7 +1477,7 @@ public class GeckoAppShell
public static boolean isNetworkLinkKnown() {
ConnectivityManager cm = (ConnectivityManager)
GeckoApp.mAppContext.getSystemService(Context.CONNECTIVITY_SERVICE);
getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
if (cm.getActiveNetworkInfo() == null)
return false;
return true;
@ -1452,8 +1492,8 @@ public class GeckoAppShell
//We're not using this, not need to save it (see bug 635342)
SharedPreferences settings =
GeckoApp.mAppContext.getPreferences(Activity.MODE_PRIVATE);
settings.edit().putString(GeckoApp.mAppContext.getPackageName() + ".locale",
getContext().getPreferences(Activity.MODE_PRIVATE);
settings.edit().putString(getContext().getPackageName() + ".locale",
localeCode).commit();
Locale locale;
int index;
@ -1467,7 +1507,7 @@ public class GeckoAppShell
}
Locale.setDefault(locale);
Resources res = GeckoApp.mAppContext.getBaseContext().getResources();
Resources res = getContext().getBaseContext().getResources();
Configuration config = res.getConfiguration();
config.locale = locale;
res.updateConfiguration(config, res.getDisplayMetrics());
@ -1494,7 +1534,7 @@ public class GeckoAppShell
int[] result = new int[attrsAppearance.length];
final ContextThemeWrapper contextThemeWrapper =
new ContextThemeWrapper(GeckoApp.mAppContext, android.R.style.TextAppearance);
new ContextThemeWrapper(getContext(), android.R.style.TextAppearance);
final TypedArray appearance = contextThemeWrapper.getTheme().obtainStyledAttributes(attrsAppearance);
@ -1625,7 +1665,7 @@ public class GeckoAppShell
int nameColumn = -1;
try {
String filter = GeckoProfile.get(GeckoApp.mAppContext).getDir().toString();
String filter = GeckoProfile.get(getContext()).getDir().toString();
Log.i(LOGTAG, "[OPENFILE] Filter: " + filter);
// run lsof and parse its output
@ -1666,7 +1706,7 @@ public class GeckoAppShell
}
public static void scanMedia(String aFile, String aMimeType) {
Context context = GeckoApp.mAppContext;
Context context = getContext();
GeckoMediaScannerClient.startScan(context, aFile, aMimeType);
}
@ -1678,7 +1718,7 @@ public class GeckoAppShell
if (aExt != null && aExt.length() > 1 && aExt.charAt(0) == '.')
aExt = aExt.substring(1);
PackageManager pm = GeckoApp.mAppContext.getPackageManager();
PackageManager pm = getContext().getPackageManager();
Drawable icon = getDrawableForExtension(pm, aExt);
if (icon == null) {
// Use a generic icon
@ -1726,7 +1766,7 @@ public class GeckoAppShell
public static boolean getShowPasswordSetting() {
try {
int showPassword =
Settings.System.getInt(GeckoApp.mAppContext.getContentResolver(),
Settings.System.getInt(getContext().getContentResolver(),
Settings.System.TEXT_SHOW_PASSWORD, 1);
return (showPassword > 0);
}
@ -1739,18 +1779,221 @@ public class GeckoAppShell
int x, int y,
int w, int h,
boolean isFullScreen) {
GeckoApp.mAppContext.addPluginView(view, new Rect(x, y, x + w, y + h), isFullScreen);
if (getGeckoInterface() != null)
getGeckoInterface().addPluginView(view, new Rect(x, y, x + w, y + h), isFullScreen);
}
public static void removePluginView(View view, boolean isFullScreen) {
GeckoApp.mAppContext.removePluginView(view, isFullScreen);
if (getGeckoInterface() != null)
getGeckoInterface().removePluginView(view, isFullScreen);
}
/**
* A plugin that wish to be loaded in the WebView must provide this permission
* in their AndroidManifest.xml.
*/
public static final String PLUGIN_ACTION = "android.webkit.PLUGIN";
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";
static public ArrayList<PackageInfo> mPackageInfoCache = new ArrayList<PackageInfo>();
// Returns null if plugins are blocked on the device.
static String[] getPluginDirectories() {
// 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)");
return null;
}
}
} catch (IOException ex) {
// nothing
} finally {
try {
if (vreader != null) {
vreader.close();
}
} catch (IOException ex) {
// nothing
}
}
}
ArrayList<String> directories = new ArrayList<String>();
PackageManager pm = getContext().getPackageManager();
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, "Ignoring bad plugin.");
continue;
}
// 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;
}
// 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, "Not 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, "Not 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, "Not 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, "Not 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 defined type.");
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);
}
}
return directories.toArray(new String[directories.size()]);
}
static 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;
}
static Class<?> getPluginClass(String packageName, String className)
throws NameNotFoundException, ClassNotFoundException {
Context pluginContext = getContext().createPackageContext(packageName,
Context.CONTEXT_INCLUDE_CODE |
Context.CONTEXT_IGNORE_SECURITY);
ClassLoader pluginCL = pluginContext.getClassLoader();
return pluginCL.loadClass(className);
}
public static Class<?> loadPluginClass(String className, String libName) {
if (getGeckoInterface() == null)
return null;
try {
final String packageName = GeckoApp.mAppContext.getPluginPackage(libName);
final String packageName = getPluginPackage(libName);
final int contextFlags = Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY;
final Context pluginContext = GeckoApp.mAppContext.createPackageContext(packageName, contextFlags);
final Context pluginContext = getContext().createPackageContext(packageName, contextFlags);
return pluginContext.getClassLoader().loadClass(className);
} catch (java.lang.ClassNotFoundException cnfe) {
Log.w(LOGTAG, "Couldn't find plugin class " + className, cnfe);
@ -1761,8 +2004,48 @@ public class GeckoAppShell
}
}
private static ContextGetter sContextGetter;
public static Context getContext() {
return GeckoApp.mAppContext;
return sContextGetter.getContext();
}
public static void setContextGetter(ContextGetter cg) {
sContextGetter = cg;
}
public interface GeckoInterface {
public GeckoProfile getProfile();
public LayerView getLayerView();
public PromptService getPromptService();
public Activity getActivity();
public String getDefaultUAString();
public LocationListener getLocationListener();
public SensorEventListener getSensorEventListener();
public void doRestart();
public void setFullScreen(boolean fullscreen);
public void addPluginView(View view, final Rect rect, final boolean isFullScreen);
public void removePluginView(final View view, final boolean isFullScreen);
public void enableCameraView();
public void disableCameraView();
public SurfaceView getCameraView();
public void notifyWakeLockChanged(String topic, String state);
public FormAssistPopup getFormAssistPopup();
public boolean areTabsShown();
public AbsoluteLayout getPluginContainer();
public void notifyCheckUpdateResult(String result);
public boolean hasTabsSideBar();
public void invalidateOptionsMenu();
};
private static GeckoInterface sGeckoInterface;
public static GeckoInterface getGeckoInterface() {
return sGeckoInterface;
}
public static void setGeckoInterface(GeckoInterface aGeckoInterface) {
sGeckoInterface = aGeckoInterface;
}
public static android.hardware.Camera sCamera = null;
@ -1777,7 +2060,8 @@ public class GeckoAppShell
@Override
public void run() {
try {
GeckoApp.mAppContext.enableCameraView();
if (getGeckoInterface() != null)
getGeckoInterface().enableCameraView();
} catch (Exception e) {}
}
});
@ -1833,7 +2117,8 @@ public class GeckoAppShell
}
try {
sCamera.setPreviewDisplay(GeckoApp.mAppContext.cameraView.getHolder());
if (getGeckoInterface() != null)
sCamera.setPreviewDisplay(getGeckoInterface().getCameraView().getHolder());
} catch(IOException e) {
Log.w(LOGTAG, "Error setPreviewDisplay:", e);
} catch(RuntimeException e) {
@ -1869,7 +2154,8 @@ public class GeckoAppShell
@Override
public void run() {
try {
GeckoApp.mAppContext.disableCameraView();
if (getGeckoInterface() != null)
getGeckoInterface().disableCameraView();
} catch (Exception e) {}
}
});
@ -2013,7 +2299,7 @@ public class GeckoAppShell
}
public static void viewSizeChanged() {
LayerView v = GeckoApp.mAppContext.getLayerView();
LayerView v = getLayerView();
if (v != null && v.isIMEEnabled()) {
sendEventToGecko(GeckoEvent.createBroadcastEvent(
"ScrollTo:FocusedInput", ""));
@ -2192,13 +2478,15 @@ public class GeckoAppShell
/* Called by JNI from AndroidBridge */
public static void showFilePickerAsync(String aMimeType, long id) {
if (!sActivityHelper.showFilePicker(GeckoApp.mAppContext, aMimeType, new AsyncResultHandler(id))) {
GeckoAppShell.notifyFilePickerResult("", id);
}
if (getGeckoInterface() != null)
if (!sActivityHelper.showFilePicker(getGeckoInterface().getActivity(), aMimeType, new AsyncResultHandler(id))) {
GeckoAppShell.notifyFilePickerResult("", id);
}
}
public static void notifyWakeLockChanged(String topic, String state) {
GeckoApp.mAppContext.notifyWakeLockChanged(topic, state);
if (getGeckoInterface() != null)
getGeckoInterface().notifyWakeLockChanged(topic, state);
}
public static String getGfxInfoData() {
@ -2223,9 +2511,12 @@ public class GeckoAppShell
GeckoAppShell.killAnyZombies();
// Then force unlock this profile
GeckoProfile profile = GeckoApp.mAppContext.getProfile();
File lock = profile.getFile(".parentlock");
return lock.exists() && lock.delete();
if (getGeckoInterface() != null) {
GeckoProfile profile = getGeckoInterface().getProfile();
File lock = profile.getFile(".parentlock");
return lock.exists() && lock.delete();
}
return false;
}
public static String getProxyForURI(String spec, String scheme, String host, int port) {

View File

@ -346,7 +346,7 @@ final class GeckoEditable
Editable.class.getClassLoader(),
PROXY_INTERFACES, this);
LayerView v = GeckoApp.mAppContext.getLayerView();
LayerView v = GeckoAppShell.getLayerView();
mListener = GeckoInputConnection.create(v, this);
mIcRunHandler = mIcPostHandler = ThreadUtils.getUiHandler();
@ -775,7 +775,7 @@ final class GeckoEditable
// Set InputConnectionHandler in notifyIMEContext because
// GeckoInputConnection.notifyIMEContext calls restartInput() which will invoke
// InputConnectionHandler.onCreateInputConnection
LayerView v = GeckoApp.mAppContext.getLayerView();
LayerView v = GeckoAppShell.getLayerView();
if (v != null) {
mListener = GeckoInputConnection.create(v, GeckoEditable.this);
v.setInputConnectionHandler((InputConnectionHandler)mListener);

View File

@ -311,7 +311,7 @@ public class GeckoEvent {
event.mPoints = new Point[1];
PointF geckoPoint = new PointF(pt.x, pt.y);
geckoPoint = GeckoApp.mAppContext.getLayerView().convertViewPointToLayerPoint(geckoPoint);
geckoPoint = GeckoAppShell.getGeckoInterface().getLayerView().convertViewPointToLayerPoint(geckoPoint);
if (geckoPoint == null) {
// This could happen if Gecko isn't ready yet.
@ -384,7 +384,7 @@ public class GeckoEvent {
try {
PointF geckoPoint = new PointF(event.getX(eventIndex), event.getY(eventIndex));
if (!keepInViewCoordinates) {
geckoPoint = GeckoApp.mAppContext.getLayerView().convertViewPointToLayerPoint(geckoPoint);
geckoPoint = GeckoAppShell.getLayerView().convertViewPointToLayerPoint(geckoPoint);
}
mPoints[index] = new Point(Math.round(geckoPoint.x), Math.round(geckoPoint.y));
@ -415,7 +415,7 @@ public class GeckoEvent {
}
} else {
float size = event.getSize(eventIndex);
Resources resources = GeckoApp.mAppContext.getResources();
Resources resources = GeckoAppShell.getContext().getResources();
DisplayMetrics displaymetrics = resources.getDisplayMetrics();
size = size*Math.min(displaymetrics.heightPixels, displaymetrics.widthPixels);
mPointRadii[index] = new Point((int)size,(int)size);

View File

@ -327,7 +327,7 @@ class GeckoInputConnection
}
private static View getView() {
return GeckoApp.mAppContext.getLayerView();
return GeckoAppShell.getLayerView();
}
private static InputMethodManager getInputMethodManager() {
@ -609,8 +609,8 @@ class GeckoInputConnection
outAttrs.actionLabel = mIMEActionHint;
}
GeckoApp app = GeckoApp.mAppContext;
DisplayMetrics metrics = app.getResources().getDisplayMetrics();
Context context = GeckoAppShell.getContext();
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
if (Math.min(metrics.widthPixels, metrics.heightPixels) > INLINE_IME_MIN_DISPLAY_SIZE) {
// prevent showing full-screen keyboard only when the screen is tall enough
// to show some reasonable amount of the page (see bug 752709)
@ -625,14 +625,14 @@ class GeckoInputConnection
}
String prevInputMethod = mCurrentInputMethod;
mCurrentInputMethod = InputMethods.getCurrentInputMethod(app);
mCurrentInputMethod = InputMethods.getCurrentInputMethod(context);
if (DEBUG) {
Log.d(LOGTAG, "IME: CurrentInputMethod=" + mCurrentInputMethod);
}
// If the user has changed IMEs, then notify input method observers.
if (!mCurrentInputMethod.equals(prevInputMethod)) {
FormAssistPopup popup = app.mFormAssistPopup;
if (!mCurrentInputMethod.equals(prevInputMethod) && GeckoAppShell.getGeckoInterface() != null) {
FormAssistPopup popup = GeckoAppShell.getGeckoInterface().getFormAssistPopup();
if (popup != null) {
popup.onInputMethodChanged(mCurrentInputMethod);
}

View File

@ -351,9 +351,9 @@ public class GeckoPreferences
} else if (PREFS_ANNOUNCEMENTS_ENABLED.equals(prefName)) {
// Send a broadcast intent to the product announcements service, either to start or
// to stop the repeated background checks.
broadcastAnnouncementsPref(GeckoApp.mAppContext, ((Boolean) newValue).booleanValue());
broadcastAnnouncementsPref(GeckoAppShell.getContext(), ((Boolean) newValue).booleanValue());
} else if (PREFS_UPDATER_AUTODOWNLOAD.equals(prefName)) {
org.mozilla.gecko.updater.UpdateServiceHelper.registerForUpdates(GeckoApp.mAppContext, (String) newValue);
org.mozilla.gecko.updater.UpdateServiceHelper.registerForUpdates(GeckoAppShell.getContext(), (String) newValue);
} else if (PREFS_HEALTHREPORT_UPLOAD_ENABLED.equals(prefName)) {
// Healthreport pref only lives in Android. Do not persist to Gecko.
return true;
@ -377,7 +377,7 @@ public class GeckoPreferences
}
private EditText getTextBox(int aHintText) {
EditText input = new EditText(GeckoApp.mAppContext);
EditText input = new EditText(GeckoAppShell.getContext());
int inputtype = InputType.TYPE_CLASS_TEXT;
inputtype |= InputType.TYPE_TEXT_VARIATION_PASSWORD | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
input.setInputType(inputtype);

View File

@ -13,6 +13,8 @@ import android.view.Surface;
import java.util.Arrays;
import java.util.List;
import android.app.Activity;
public class GeckoScreenOrientationListener {
private static final String LOGTAG = "GeckoScreenOrientationListener";
@ -51,7 +53,7 @@ public class GeckoScreenOrientationListener {
private static final String DEFAULT_ORIENTATION_PREF = "app.orientation.default";
private GeckoScreenOrientationListener() {
mListener = new OrientationEventListenerImpl(GeckoApp.mAppContext);
mListener = new OrientationEventListenerImpl(GeckoAppShell.getContext());
PrefsHelper.getPref(DEFAULT_ORIENTATION_PREF, new PrefsHelper.PrefHandlerBase() {
@Override public void prefValue(String pref, String value) {
@ -141,7 +143,11 @@ public class GeckoScreenOrientationListener {
}
private void updateScreenOrientation() {
int rotation = GeckoApp.mAppContext.getWindowManager().getDefaultDisplay().getRotation();
Context context = GeckoAppShell.getContext();
int rotation = mDefaultOrientation;
if (context instanceof Activity) {
rotation = ((Activity)context).getWindowManager().getDefaultDisplay().getRotation();
}
short previousOrientation = mOrientation;
if (rotation == Surface.ROTATION_0) {
@ -192,16 +198,18 @@ public class GeckoScreenOrientationListener {
Log.e(LOGTAG, "Unexpected value received! (" + aOrientation + ")");
return;
}
GeckoApp.mAppContext.setRequestedOrientation(orientation);
if (GeckoAppShell.getContext() instanceof Activity)
((Activity)GeckoAppShell.getContext()).setRequestedOrientation(orientation);
updateScreenOrientation();
}
public void unlockScreenOrientation() {
if (GeckoApp.mAppContext.getRequestedOrientation() == mDefaultOrientation)
return;
if (!(GeckoAppShell.getContext() instanceof Activity))
return;
if (((Activity)GeckoAppShell.getContext()).getRequestedOrientation() == mDefaultOrientation)
return;
GeckoApp.mAppContext.setRequestedOrientation(mDefaultOrientation);
((Activity)GeckoAppShell.getContext()).setRequestedOrientation(mDefaultOrientation);
updateScreenOrientation();
}
}

View File

@ -362,7 +362,7 @@ public class GeckoSmsManager
smsFilter.addAction(GeckoSmsManager.ACTION_SMS_SENT);
smsFilter.addAction(GeckoSmsManager.ACTION_SMS_DELIVERED);
GeckoApp.mAppContext.registerReceiver(this, smsFilter);
GeckoAppShell.getContext().registerReceiver(this, smsFilter);
}
@Override
@ -523,12 +523,12 @@ public class GeckoSmsManager
* generated by GetPendingIntentUID().
*/
PendingIntent sentPendingIntent =
PendingIntent.getBroadcast(GeckoApp.mAppContext,
PendingIntent.getBroadcast(GeckoAppShell.getContext(),
PendingIntentUID.generate(), sentIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
PendingIntent deliveredPendingIntent =
PendingIntent.getBroadcast(GeckoApp.mAppContext,
PendingIntent.getBroadcast(GeckoAppShell.getContext(),
PendingIntentUID.generate(), deliveredIntent,
PendingIntent.FLAG_CANCEL_CURRENT);
@ -549,13 +549,13 @@ public class GeckoSmsManager
for (int i=0; i<parts.size(); ++i) {
sentPendingIntents.add(
PendingIntent.getBroadcast(GeckoApp.mAppContext,
PendingIntent.getBroadcast(GeckoAppShell.getContext(),
PendingIntentUID.generate(), sentIntent,
PendingIntent.FLAG_CANCEL_CURRENT)
);
deliveredPendingIntents.add(
PendingIntent.getBroadcast(GeckoApp.mAppContext,
PendingIntent.getBroadcast(GeckoAppShell.getContext(),
PendingIntentUID.generate(), deliveredIntent,
PendingIntent.FLAG_CANCEL_CURRENT)
);
@ -584,7 +584,7 @@ public class GeckoSmsManager
// Always 'PENDING' because we always request status report.
values.put("status", kInternalDeliveryStatusPending);
ContentResolver cr = GeckoApp.mAppContext.getContentResolver();
ContentResolver cr = GeckoAppShell.getContext().getContentResolver();
Uri uri = cr.insert(kSmsSentContentUri, values);
long id = ContentUris.parseId(uri);
@ -621,7 +621,7 @@ public class GeckoSmsManager
Cursor cursor = null;
try {
ContentResolver cr = GeckoApp.mAppContext.getContentResolver();
ContentResolver cr = GeckoAppShell.getContext().getContentResolver();
Uri message = ContentUris.withAppendedId(kSmsContentUri, mMessageId);
cursor = cr.query(message, kRequiredMessageRows, null, null, null);
@ -704,7 +704,7 @@ public class GeckoSmsManager
@Override
public void run() {
try {
ContentResolver cr = GeckoApp.mAppContext.getContentResolver();
ContentResolver cr = GeckoAppShell.getContext().getContentResolver();
Uri message = ContentUris.withAppendedId(kSmsContentUri, mMessageId);
int count = cr.delete(message, null, null);
@ -795,7 +795,7 @@ public class GeckoSmsManager
restrictionText += " AND " + restrictions.get(i);
}
ContentResolver cr = GeckoApp.mAppContext.getContentResolver();
ContentResolver cr = GeckoAppShell.getContext().getContentResolver();
cursor = cr.query(kSmsContentUri, kRequiredMessageRows, restrictionText, null,
mReverse ? "date DESC" : "date ASC");
@ -920,7 +920,7 @@ public class GeckoSmsManager
@Override
public void stop() {
GeckoApp.mAppContext.unregisterReceiver(this);
GeckoAppShell.getContext().unregisterReceiver(this);
}
@Override

View File

@ -11,10 +11,13 @@ import org.mozilla.gecko.util.GeckoEventListener;
import org.json.JSONObject;
import android.content.Intent;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.SystemClock;
import android.util.Log;
import android.app.Activity;
import java.util.Locale;
@ -51,22 +54,28 @@ public class GeckoThread extends Thread implements GeckoEventListener {
Locale.setDefault(locale);
}
GeckoApp app = GeckoApp.mAppContext;
String resourcePath = app.getApplication().getPackageResourcePath();
Context app = GeckoAppShell.getContext();
String resourcePath = "";
Resources res = null;
String[] pluginDirs = null;
try {
pluginDirs = app.getPluginDirectories();
pluginDirs = GeckoAppShell.getPluginDirectories();
} catch (Exception e) {
Log.w(LOGTAG, "Caught exception getting plugin dirs.", e);
}
GeckoLoader.setupGeckoEnvironment(app, pluginDirs, GeckoProfile.get(app).getFilesDir().getPath());
if (app instanceof Activity) {
Activity activity = (Activity)app;
resourcePath = activity.getApplication().getPackageResourcePath();
res = activity.getBaseContext().getResources();
GeckoLoader.setupGeckoEnvironment(activity, pluginDirs, GeckoProfile.get(app).getFilesDir().getPath());
}
GeckoLoader.loadSQLiteLibs(app, resourcePath);
GeckoLoader.loadNSSLibs(app, resourcePath);
GeckoLoader.loadGeckoLibs(app, resourcePath);
Locale.setDefault(locale);
Resources res = app.getBaseContext().getResources();
Configuration config = res.getConfiguration();
config.locale = locale;
res.updateConfiguration(config, res.getDisplayMetrics());
@ -85,7 +94,7 @@ public class GeckoThread extends Thread implements GeckoEventListener {
}
private String addCustomProfileArg(String args) {
String profile = GeckoApp.sIsUsingCustomProfile ? "" : (" -P " + GeckoApp.mAppContext.getProfile().getName());
String profile = GeckoAppShell.getGeckoInterface() == null || GeckoApp.sIsUsingCustomProfile ? "" : (" -P " + GeckoAppShell.getGeckoInterface().getProfile().getName());
return (args != null ? args : "") + profile;
}

View File

@ -17,8 +17,8 @@ public class GeckoUpdateReceiver extends BroadcastReceiver
public void onReceive(Context context, Intent intent) {
if (UpdateServiceHelper.ACTION_CHECK_UPDATE_RESULT.equals(intent.getAction())) {
String result = intent.getStringExtra("result");
if (GeckoApp.mAppContext != null && result != null) {
GeckoApp.mAppContext.notifyCheckUpdateResult(result);
if (GeckoAppShell.getGeckoInterface() != null && result != null) {
GeckoAppShell.getGeckoInterface().notifyCheckUpdateResult(result);
}
}
}

View File

@ -51,7 +51,7 @@ class GlobalHistory {
// the cache was wiped away, repopulate it
Log.w(LOGTAG, "Rebuilding visited link set...");
visitedSet = new HashSet<String>();
Cursor c = BrowserDB.getAllVisitedHistory(GeckoApp.mAppContext.getContentResolver());
Cursor c = BrowserDB.getAllVisitedHistory(GeckoAppShell.getContext().getContentResolver());
if (c.moveToFirst()) {
do {
visitedSet.add(c.getString(0));
@ -120,7 +120,7 @@ class GlobalHistory {
if (!canAddURI(uri))
return;
BrowserDB.updateVisitedHistory(GeckoApp.mAppContext.getContentResolver(), uri);
BrowserDB.updateVisitedHistory(GeckoAppShell.getContext().getContentResolver(), uri);
addToGeckoOnly(uri);
}
@ -128,7 +128,7 @@ class GlobalHistory {
if (!canAddURI(uri))
return;
BrowserDB.updateHistoryTitle(GeckoApp.mAppContext.getContentResolver(), uri, title);
BrowserDB.updateHistoryTitle(GeckoAppShell.getContext().getContentResolver(), uri, title);
}
public void checkUriVisited(final String uri) {

View File

@ -73,6 +73,7 @@ FENNEC_JAVA_FILES = \
CanvasDelegate.java \
CheckableLinearLayout.java \
ClickableWhenDisabledEditText.java \
ContextGetter.java \
CustomEditText.java \
db/BrowserDB.java \
db/LocalBrowserDB.java \

View File

@ -48,9 +48,9 @@ public class SiteIdentityPopup extends PopupWindow {
private int mYOffset;
private SiteIdentityPopup() {
super(GeckoApp.mAppContext);
super(GeckoAppShell.getContext());
mResources = GeckoApp.mAppContext.getResources();
mResources = GeckoAppShell.getContext().getResources();
mYOffset = mResources.getDimensionPixelSize(R.dimen.menu_popup_offset);
mInflated = false;
setAnimationStyle(R.style.PopupAnimation);
@ -73,7 +73,7 @@ public class SiteIdentityPopup extends PopupWindow {
setWindowLayoutMode(HardwareUtils.isTablet() ? LayoutParams.WRAP_CONTENT : LayoutParams.FILL_PARENT,
LayoutParams.WRAP_CONTENT);
LayoutInflater inflater = LayoutInflater.from(GeckoApp.mAppContext);
LayoutInflater inflater = LayoutInflater.from(GeckoAppShell.getContext());
RelativeLayout layout = (RelativeLayout) inflater.inflate(R.layout.site_identity_popup, null);
setContentView(layout);

View File

@ -25,7 +25,7 @@ import java.util.ArrayList;
*/
public class SuggestClient {
private static final String LOGTAG = "GeckoSuggestClient";
private static final String USER_AGENT = GeckoApp.mAppContext.getDefaultUAString();
private static final String USER_AGENT = GeckoAppShell.getGeckoInterface().getDefaultUAString();
private final Context mContext;
private final int mTimeout;

View File

@ -15,6 +15,7 @@ import org.json.JSONObject;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.OnAccountsUpdateListener;
import android.app.Activity;
import android.content.ContentResolver;
import android.database.ContentObserver;
import android.graphics.Color;
@ -63,7 +64,7 @@ public class Tabs implements GeckoEventListener {
private static AtomicInteger sTabId = new AtomicInteger(0);
private volatile boolean mInitialTabsAdded;
private GeckoApp mActivity;
private Activity mActivity;
private ContentObserver mContentObserver;
private final Runnable mPersistTabsRunnable = new Runnable() {
@ -99,7 +100,7 @@ public class Tabs implements GeckoEventListener {
registerEventListener("DesktopMode:Changed");
}
public synchronized void attachToActivity(GeckoApp activity) {
public synchronized void attachToActivity(Activity activity) {
if (mActivity == activity) {
return;
}
@ -130,7 +131,7 @@ public class Tabs implements GeckoEventListener {
// detached; however, we have lifecycle issues with GeckoApp and Tabs that
// requires us to keep it around (see
// https://bugzilla.mozilla.org/show_bug.cgi?id=844407).
public synchronized void detachFromActivity(GeckoApp activity) {
public synchronized void detachFromActivity(Activity activity) {
ThreadUtils.getBackgroundHandler().removeCallbacks(mPersistTabsRunnable);
if (mContentObserver != null) {
@ -357,7 +358,7 @@ public class Tabs implements GeckoEventListener {
* @return the current GeckoApp instance, or throws if
* we aren't correctly initialized.
*/
private synchronized GeckoApp getActivity() {
private synchronized android.app.Activity getActivity() {
if (mActivity == null) {
throw new IllegalStateException("Tabs not initialized with a GeckoApp instance.");
}

View File

@ -217,7 +217,7 @@ public class TabsPanel extends LinearLayout
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (!GeckoApp.mAppContext.hasTabsSideBar()) {
if (!GeckoAppShell.getGeckoInterface().hasTabsSideBar()) {
int heightSpec = MeasureSpec.makeMeasureSpec(getTabContainerHeight(TabsListContainer.this), MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightSpec);
} else {

View File

@ -52,7 +52,7 @@ public final class ThumbnailHelper {
private ThumbnailHelper() {
mPendingThumbnails = new LinkedList<Tab>();
mPendingWidth = new AtomicInteger((int)GeckoApp.mAppContext.getResources().getDimension(R.dimen.tab_thumbnail_width));
mPendingWidth = new AtomicInteger((int)GeckoAppShell.getContext().getResources().getDimension(R.dimen.tab_thumbnail_width));
mWidth = -1;
mHeight = -1;
}
@ -66,7 +66,7 @@ public final class ThumbnailHelper {
if (tab.getState() == Tab.STATE_DELAYED) {
String url = tab.getURL();
if (url != null) {
byte[] thumbnail = BrowserDB.getThumbnailForUrl(GeckoApp.mAppContext.getContentResolver(), url);
byte[] thumbnail = BrowserDB.getThumbnailForUrl(GeckoAppShell.getContext().getContentResolver(), url);
if (thumbnail != null) {
setTabThumbnail(tab, null, thumbnail);
}
@ -198,6 +198,6 @@ public final class ThumbnailHelper {
}
private boolean shouldUpdateThumbnail(Tab tab) {
return (Tabs.getInstance().isSelectedTab(tab) || GeckoApp.mAppContext.areTabsShown());
return (Tabs.getInstance().isSelectedTab(tab) || (GeckoAppShell.getGeckoInterface() != null && GeckoAppShell.getGeckoInterface().areTabsShown()));
}
}

View File

@ -21,7 +21,7 @@ public class WebAppAllocator {
protected static GeckoApp sContext = null;
protected static WebAppAllocator sInstance = null;
public static WebAppAllocator getInstance() {
return getInstance(GeckoApp.mAppContext);
return getInstance(GeckoAppShell.getContext());
}
public static synchronized WebAppAllocator getInstance(Context cx) {

View File

@ -657,7 +657,7 @@ public class AllPagesTab extends AwesomeBarTab implements GeckoEventListener {
// should be safe to assume that null means non-private.
Tab tab = Tabs.getInstance().getSelectedTab();
if (tab == null || !tab.isPrivate())
mSuggestClient = new SuggestClient(GeckoApp.mAppContext, suggestTemplate, SUGGESTION_TIMEOUT, SUGGESTION_MAX);
mSuggestClient = new SuggestClient(getView().getContext(), suggestTemplate, SUGGESTION_TIMEOUT, SUGGESTION_MAX);
} else {
searchEngines.add(new SearchEngine(name, identifier, icon));
}

View File

@ -6,7 +6,7 @@
package org.mozilla.gecko.gfx;
import org.mozilla.gecko.GeckoAccessibility;
import org.mozilla.gecko.GeckoApp;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.R;
import org.mozilla.gecko.TouchEventInterceptor;
import org.mozilla.gecko.ZoomConstraints;
@ -450,7 +450,7 @@ public class LayerView extends FrameLayout {
/** This function is invoked by Gecko (compositor thread) via JNI; be careful when modifying signature. */
public static GLController registerCxxCompositor() {
try {
LayerView layerView = GeckoApp.mAppContext.getLayerView();
LayerView layerView = GeckoAppShell.getLayerView();
GLController controller = layerView.getGLController();
controller.compositorCreated();
return controller;

View File

@ -4,7 +4,7 @@
package org.mozilla.gecko.gfx;
import org.mozilla.gecko.GeckoApp;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.util.FloatUtils;
import org.mozilla.gecko.util.ThreadUtils;
@ -39,7 +39,7 @@ public class PluginLayer extends TileLayer {
super(new BufferedCairoImage(null, 0, 0, 0), TileLayer.PaintMode.NORMAL);
mView = view;
mContainer = GeckoApp.mAppContext.getPluginContainer();
mContainer = GeckoAppShell.getGeckoInterface().getPluginContainer();
mView.setWillNotDraw(false);
if (mView instanceof SurfaceView) {