diff --git a/media/webrtc/trunk/webrtc/modules/video_capture/android/java/org/webrtc/videoengine/VideoCaptureAndroid.java b/media/webrtc/trunk/webrtc/modules/video_capture/android/java/org/webrtc/videoengine/VideoCaptureAndroid.java index f6e3ca1da705..b9f5216a49f5 100644 --- a/media/webrtc/trunk/webrtc/modules/video_capture/android/java/org/webrtc/videoengine/VideoCaptureAndroid.java +++ b/media/webrtc/trunk/webrtc/modules/video_capture/android/java/org/webrtc/videoengine/VideoCaptureAndroid.java @@ -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; diff --git a/mobile/android/base/ANRReporter.java b/mobile/android/base/ANRReporter.java index d1fbdc703e3e..213f1fecddd3 100644 --- a/mobile/android/base/ANRReporter.java +++ b/mobile/android/base/ANRReporter.java @@ -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; diff --git a/mobile/android/base/ActivityHandlerHelper.java b/mobile/android/base/ActivityHandlerHelper.java index 70fd3e461932..5d356601b538 100644 --- a/mobile/android/base/ActivityHandlerHelper.java +++ b/mobile/android/base/ActivityHandlerHelper.java @@ -68,7 +68,7 @@ public class ActivityHandlerHelper { private int addIntentActivitiesToList(Context context, Intent intent, ArrayList items, ArrayList aIntents) { PackageManager pm = context.getPackageManager(); - List lri = pm.queryIntentActivityOptions(GeckoApp.mAppContext.getComponentName(), null, intent, 0); + List 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 diff --git a/mobile/android/base/AndroidImportPreference.java b/mobile/android/base/AndroidImportPreference.java index 045ce7fdbbeb..65923a1e5d66 100644 --- a/mobile/android/base/AndroidImportPreference.java +++ b/mobile/android/base/AndroidImportPreference.java @@ -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(); diff --git a/mobile/android/base/BrowserApp.java b/mobile/android/base/BrowserApp.java index 3033f6811361..b07b143d0930 100644 --- a/mobile/android/base/BrowserApp.java +++ b/mobile/android/base/BrowserApp.java @@ -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")) { diff --git a/mobile/android/base/BrowserToolbar.java b/mobile/android/base/BrowserToolbar.java index 289ae78e1666..be39922e02ba 100644 --- a/mobile/android/base/BrowserToolbar.java +++ b/mobile/android/base/BrowserToolbar.java @@ -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); diff --git a/mobile/android/base/BrowserToolbarLayout.java b/mobile/android/base/BrowserToolbarLayout.java index 1895e0541707..cb3e906283cf 100644 --- a/mobile/android/base/BrowserToolbarLayout.java +++ b/mobile/android/base/BrowserToolbarLayout.java @@ -39,7 +39,7 @@ public class BrowserToolbarLayout extends GeckoRelativeLayout { post(new Runnable() { @Override public void run() { - ((BrowserApp)GeckoApp.mAppContext).refreshToolbarHeight(); + ((BrowserApp)GeckoAppShell.getContext()).refreshToolbarHeight(); } }); } diff --git a/mobile/android/base/CameraVideoResultHandler.java b/mobile/android/base/CameraVideoResultHandler.java index c8f9ce8b947c..bf99e2cd5cc8 100644 --- a/mobile/android/base/CameraVideoResultHandler.java +++ b/mobile/android/base/CameraVideoResultHandler.java @@ -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, diff --git a/mobile/android/base/ContextGetter.java b/mobile/android/base/ContextGetter.java new file mode 100644 index 000000000000..5432000784a7 --- /dev/null +++ b/mobile/android/base/ContextGetter.java @@ -0,0 +1,6 @@ +package org.mozilla.gecko; +import android.content.Context; + +interface ContextGetter { + Context getContext(); +} diff --git a/mobile/android/base/Favicons.java b/mobile/android/base/Favicons.java index 0e91c8b9e336..eaf217cde3f8 100644 --- a/mobile/android/base/Favicons.java +++ b/mobile/android/base/Favicons.java @@ -51,7 +51,7 @@ public class Favicons { private LruCache mFaviconsCache; private LruCache mFailedCache; private LruCache 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 { diff --git a/mobile/android/base/FilePickerResultHandler.java b/mobile/android/base/FilePickerResultHandler.java index 75f3138115df..e515929a49ff 100644 --- a/mobile/android/base/FilePickerResultHandler.java +++ b/mobile/android/base/FilePickerResultHandler.java @@ -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]; diff --git a/mobile/android/base/FormAssistPopup.java b/mobile/android/base/FormAssistPopup.java index 187db73414ec..697125331259 100644 --- a/mobile/android/base/FormAssistPopup.java +++ b/mobile/android/base/FormAssistPopup.java @@ -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 diff --git a/mobile/android/base/GeckoAccessibility.java b/mobile/android/base/GeckoAccessibility.java index 7369a2404262..9370be5ba782 100644 --- a/mobile/android/base/GeckoAccessibility.java +++ b/mobile/android/base/GeckoAccessibility.java @@ -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); diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index 4b56299620de..118f00eb7a34 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -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 mPackageInfoCache = new ArrayList(); - - // 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 directories = new ArrayList(); - PackageManager pm = mAppContext.getPackageManager(); - List 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(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; } diff --git a/mobile/android/base/GeckoAppShell.java b/mobile/android/base/GeckoAppShell.java index ecb6258be70b..c12ae99d7d4c 100644 --- a/mobile/android/base/GeckoAppShell.java +++ b/mobile/android/base/GeckoAppShell.java @@ -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 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 list = pm.queryIntentActivities(intent, 0); return !list.isEmpty(); } static String[] getHandlersForIntent(Intent intent) { - PackageManager pm = GeckoApp.mAppContext.getPackageManager(); + PackageManager pm = getContext().getPackageManager(); List 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 mPackageInfoCache = new ArrayList(); + + // 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 directories = new ArrayList(); + PackageManager pm = getContext().getPackageManager(); + List 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) { diff --git a/mobile/android/base/GeckoEditable.java b/mobile/android/base/GeckoEditable.java index 11e559b844d7..5ec496e82b1d 100644 --- a/mobile/android/base/GeckoEditable.java +++ b/mobile/android/base/GeckoEditable.java @@ -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); diff --git a/mobile/android/base/GeckoEvent.java b/mobile/android/base/GeckoEvent.java index 01947346d51c..5cd72d74626a 100644 --- a/mobile/android/base/GeckoEvent.java +++ b/mobile/android/base/GeckoEvent.java @@ -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); diff --git a/mobile/android/base/GeckoInputConnection.java b/mobile/android/base/GeckoInputConnection.java index 3b276b30412d..628ae37a9976 100644 --- a/mobile/android/base/GeckoInputConnection.java +++ b/mobile/android/base/GeckoInputConnection.java @@ -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); } diff --git a/mobile/android/base/GeckoPreferences.java b/mobile/android/base/GeckoPreferences.java index a4f892521150..0ed1eabfa0f6 100644 --- a/mobile/android/base/GeckoPreferences.java +++ b/mobile/android/base/GeckoPreferences.java @@ -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); diff --git a/mobile/android/base/GeckoScreenOrientationListener.java b/mobile/android/base/GeckoScreenOrientationListener.java index 2187a231c93a..e4ceecad37f7 100644 --- a/mobile/android/base/GeckoScreenOrientationListener.java +++ b/mobile/android/base/GeckoScreenOrientationListener.java @@ -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(); } } diff --git a/mobile/android/base/GeckoSmsManager.java b/mobile/android/base/GeckoSmsManager.java index 8a30f73a40ef..0ab9963effeb 100644 --- a/mobile/android/base/GeckoSmsManager.java +++ b/mobile/android/base/GeckoSmsManager.java @@ -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(); - 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) { diff --git a/mobile/android/base/Makefile.in b/mobile/android/base/Makefile.in index 4c778e9e7d61..722f3d958f59 100644 --- a/mobile/android/base/Makefile.in +++ b/mobile/android/base/Makefile.in @@ -73,6 +73,7 @@ FENNEC_JAVA_FILES = \ CanvasDelegate.java \ CheckableLinearLayout.java \ ClickableWhenDisabledEditText.java \ + ContextGetter.java \ CustomEditText.java \ db/BrowserDB.java \ db/LocalBrowserDB.java \ diff --git a/mobile/android/base/SiteIdentityPopup.java b/mobile/android/base/SiteIdentityPopup.java index fa5913579550..c401e87f14a9 100644 --- a/mobile/android/base/SiteIdentityPopup.java +++ b/mobile/android/base/SiteIdentityPopup.java @@ -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); diff --git a/mobile/android/base/SuggestClient.java b/mobile/android/base/SuggestClient.java index 5955117af89e..20c90778ae40 100644 --- a/mobile/android/base/SuggestClient.java +++ b/mobile/android/base/SuggestClient.java @@ -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; diff --git a/mobile/android/base/Tabs.java b/mobile/android/base/Tabs.java index d09c267ac628..af59b448d375 100644 --- a/mobile/android/base/Tabs.java +++ b/mobile/android/base/Tabs.java @@ -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."); } diff --git a/mobile/android/base/TabsPanel.java b/mobile/android/base/TabsPanel.java index 6b8feca6193d..2d671ea6ba8c 100644 --- a/mobile/android/base/TabsPanel.java +++ b/mobile/android/base/TabsPanel.java @@ -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 { diff --git a/mobile/android/base/ThumbnailHelper.java b/mobile/android/base/ThumbnailHelper.java index 677ab101c2f9..56d09829c2e8 100644 --- a/mobile/android/base/ThumbnailHelper.java +++ b/mobile/android/base/ThumbnailHelper.java @@ -52,7 +52,7 @@ public final class ThumbnailHelper { private ThumbnailHelper() { mPendingThumbnails = new LinkedList(); - 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())); } } diff --git a/mobile/android/base/WebAppAllocator.java b/mobile/android/base/WebAppAllocator.java index 51143ed14e0c..98f38974101b 100644 --- a/mobile/android/base/WebAppAllocator.java +++ b/mobile/android/base/WebAppAllocator.java @@ -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) { diff --git a/mobile/android/base/awesomebar/AllPagesTab.java b/mobile/android/base/awesomebar/AllPagesTab.java index 037ad61b322b..4dd09a326c2a 100644 --- a/mobile/android/base/awesomebar/AllPagesTab.java +++ b/mobile/android/base/awesomebar/AllPagesTab.java @@ -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)); } diff --git a/mobile/android/base/gfx/LayerView.java b/mobile/android/base/gfx/LayerView.java index 48440acaca01..a880b1677acf 100644 --- a/mobile/android/base/gfx/LayerView.java +++ b/mobile/android/base/gfx/LayerView.java @@ -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; diff --git a/mobile/android/base/gfx/PluginLayer.java b/mobile/android/base/gfx/PluginLayer.java index 74f165b77728..2017f70149f7 100644 --- a/mobile/android/base/gfx/PluginLayer.java +++ b/mobile/android/base/gfx/PluginLayer.java @@ -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) {