Bug 778468 - Part 8: Add EventDispatcher to remove gfx dependency on GeckoAppShell event registration. r=blassey

This commit is contained in:
Chris Peterson 2012-08-02 15:12:35 -07:00
parent f7f07c0f74
commit 8b01b458f6
5 changed files with 127 additions and 84 deletions

View File

@ -1654,7 +1654,7 @@ abstract public class GeckoApp
}
if (mLayerClient == null) {
mLayerClient = new GeckoLayerClient(this);
mLayerClient = new GeckoLayerClient(this, GeckoAppShell.getEventDispatcher());
mLayerClient.setView((LayerView)findViewById(R.id.layer_view));
}

View File

@ -14,12 +14,10 @@ import org.mozilla.gecko.gfx.LayerView;
import org.mozilla.gecko.gfx.RectUtils;
import org.mozilla.gecko.gfx.ScreenshotLayer;
import org.mozilla.gecko.mozglue.DirectBufferAllocator;
import org.mozilla.gecko.util.EventDispatcher;
import org.mozilla.gecko.util.FloatUtils;
import org.mozilla.gecko.util.GeckoBackgroundThread;
import org.mozilla.gecko.util.GeckoEventListener;
import org.mozilla.gecko.util.GeckoEventResponder;
import org.json.JSONObject;
import android.app.Activity;
import android.app.ActivityManager;
@ -98,11 +96,9 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Queue;
import java.util.StringTokenizer;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.SynchronousQueue;
@ -146,8 +142,7 @@ public class GeckoAppShell
private static Boolean sNSSLibsLoaded = false;
private static Boolean sLibsSetup = false;
private static File sGREDir = null;
private static Map<String, CopyOnWriteArrayList<GeckoEventListener>> mEventListeners
= new HashMap<String, CopyOnWriteArrayList<GeckoEventListener>>();
private static final EventDispatcher sEventDispatcher = new EventDispatcher();
/* Is the value in sVibrationEndTime valid? */
private static boolean sVibrationMaybePlaying = false;
@ -1921,17 +1916,11 @@ public class GeckoAppShell
* This method is referenced by Robocop via reflection.
*/
public static void registerGeckoEventListener(String event, GeckoEventListener listener) {
synchronized (mEventListeners) {
CopyOnWriteArrayList<GeckoEventListener> listeners = mEventListeners.get(event);
if (listeners == null) {
// create a CopyOnWriteArrayList so that we can modify it
// concurrently with iterating through it in handleGeckoMessage.
// Otherwise we could end up throwing a ConcurrentModificationException.
listeners = new CopyOnWriteArrayList<GeckoEventListener>();
}
listeners.add(listener);
mEventListeners.put(event, listeners);
}
sEventDispatcher.registerEventListener(event, listener);
}
static EventDispatcher getEventDispatcher() {
return sEventDispatcher;
}
static SynchronousQueue<Date> sTracerQueue = new SynchronousQueue<Date>();
@ -1962,16 +1951,7 @@ public class GeckoAppShell
* This method is referenced by Robocop via reflection.
*/
public static void unregisterGeckoEventListener(String event, GeckoEventListener listener) {
synchronized (mEventListeners) {
CopyOnWriteArrayList<GeckoEventListener> listeners = mEventListeners.get(event);
if (listeners == null) {
return;
}
listeners.remove(listener);
if (listeners.size() == 0) {
mEventListeners.remove(event);
}
}
sEventDispatcher.unregisterEventListener(event, listener);
}
/*
@ -1982,45 +1962,7 @@ public class GeckoAppShell
}
public static String handleGeckoMessage(String message) {
//
// {"gecko": {
// "type": "value",
// "event_specific": "value",
// ....
try {
JSONObject json = new JSONObject(message);
final JSONObject geckoObject = json.getJSONObject("gecko");
String type = geckoObject.getString("type");
CopyOnWriteArrayList<GeckoEventListener> listeners;
synchronized (mEventListeners) {
listeners = mEventListeners.get(type);
}
if (listeners == null)
return "";
String response = null;
for (GeckoEventListener listener : listeners) {
listener.handleMessage(type, geckoObject);
if (listener instanceof GeckoEventResponder) {
String newResponse = ((GeckoEventResponder)listener).getResponse();
if (response != null && newResponse != null) {
Log.e(LOGTAG, "Received two responses for message of type " + type);
}
response = newResponse;
}
}
if (response != null)
return response;
} catch (Exception e) {
Log.e(LOGTAG, "handleGeckoMessage throws " + e, e);
}
return "";
return sEventDispatcher.dispatchEvent(message);
}
public static void disableBatteryNotifications() {

View File

@ -30,6 +30,7 @@ UTIL_JAVA_FILES := \
GeckoJarReader.java \
INIParser.java \
INISection.java \
util/EventDispatcher.java \
util/FloatUtils.java \
$(NULL)

View File

@ -9,11 +9,11 @@ import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.GeckoEvent;
import org.mozilla.gecko.Tab;
import org.mozilla.gecko.Tabs;
import org.mozilla.gecko.util.GeckoEventResponder;
import org.mozilla.gecko.ZoomConstraints;
import org.mozilla.gecko.ui.PanZoomController;
import org.mozilla.gecko.ui.PanZoomTarget;
import org.mozilla.gecko.ui.SimpleScaleGestureDetector;
import org.mozilla.gecko.util.EventDispatcher;
import org.mozilla.gecko.util.GeckoEventResponder;
import org.json.JSONArray;
import org.json.JSONException;
@ -26,7 +26,6 @@ import android.graphics.RectF;
import android.os.SystemClock;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.GestureDetector;
import java.util.HashMap;
import java.util.Map;
@ -39,6 +38,7 @@ public class GeckoLayerClient
private LayerRenderer mLayerRenderer;
private boolean mLayerRendererInitialized;
private final EventDispatcher mEventDispatcher;
private Context mContext;
private IntSize mScreenSize;
private IntSize mWindowSize;
@ -102,9 +102,10 @@ public class GeckoLayerClient
private final PanZoomController mPanZoomController;
private LayerView mView;
public GeckoLayerClient(Context context) {
public GeckoLayerClient(Context context, EventDispatcher eventDispatcher) {
// we can fill these in with dummy values because they are always written
// to before being read
mEventDispatcher = eventDispatcher;
mContext = context;
mScreenSize = new IntSize(0, 0);
mWindowSize = new IntSize(0, 0);
@ -112,7 +113,6 @@ public class GeckoLayerClient
mRecordDrawTimes = true;
mDrawTimingQueue = new DrawTimingQueue();
mCurrentViewTransform = new ViewTransform(0, 0, 1);
mCompositorCreated = false;
mForceRedraw = true;
@ -137,11 +137,11 @@ public class GeckoLayerClient
mRootLayer = new VirtualLayer(new IntSize(mView.getWidth(), mView.getHeight()));
mLayerRenderer = new LayerRenderer(mView);
GeckoAppShell.registerGeckoEventListener("Viewport:Update", this);
GeckoAppShell.registerGeckoEventListener("Viewport:PageSize", this);
GeckoAppShell.registerGeckoEventListener("Viewport:CalculateDisplayPort", this);
GeckoAppShell.registerGeckoEventListener("Checkerboard:Toggle", this);
GeckoAppShell.registerGeckoEventListener("Preferences:Data", this);
registerEventListener("Viewport:Update");
registerEventListener("Viewport:PageSize");
registerEventListener("Viewport:CalculateDisplayPort");
registerEventListener("Checkerboard:Toggle");
registerEventListener("Preferences:Data");
mView.setListener(this);
mView.setLayerRenderer(mLayerRenderer);
@ -156,11 +156,19 @@ public class GeckoLayerClient
public void destroy() {
mPanZoomController.destroy();
GeckoAppShell.unregisterGeckoEventListener("Viewport:Update", this);
GeckoAppShell.unregisterGeckoEventListener("Viewport:PageSize", this);
GeckoAppShell.unregisterGeckoEventListener("Viewport:CalculateDisplayPort", this);
GeckoAppShell.unregisterGeckoEventListener("Checkerboard:Toggle", this);
GeckoAppShell.unregisterGeckoEventListener("Preferences:Data", this);
unregisterEventListener("Viewport:Update");
unregisterEventListener("Viewport:PageSize");
unregisterEventListener("Viewport:CalculateDisplayPort");
unregisterEventListener("Checkerboard:Toggle");
unregisterEventListener("Preferences:Data");
}
private void registerEventListener(String event) {
mEventDispatcher.registerEventListener(event, this);
}
private void unregisterEventListener(String event) {
mEventDispatcher.unregisterEventListener(event, this);
}
/**
@ -384,7 +392,7 @@ public class GeckoLayerClient
// right batch of prefs, since other java code may also have sent requests
// for prefs.
if (DisplayPortCalculator.setStrategy(prefValues) && PluginLayer.setUsePlaceholder(prefValues)) {
GeckoAppShell.unregisterGeckoEventListener("Preferences:Data", this);
unregisterEventListener("Preferences:Data");
}
}
} catch (JSONException e) {

View File

@ -0,0 +1,92 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.gecko.util;
import org.json.JSONObject;
import android.util.Log;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
public final class EventDispatcher {
private static final String LOGTAG = "EventDispatcher";
private final Map<String, CopyOnWriteArrayList<GeckoEventListener>> mEventListeners
= new HashMap<String, CopyOnWriteArrayList<GeckoEventListener>>();
public void registerEventListener(String event, GeckoEventListener listener) {
synchronized (mEventListeners) {
CopyOnWriteArrayList<GeckoEventListener> listeners = mEventListeners.get(event);
if (listeners == null) {
// create a CopyOnWriteArrayList so that we can modify it
// concurrently with iterating through it in handleGeckoMessage.
// Otherwise we could end up throwing a ConcurrentModificationException.
listeners = new CopyOnWriteArrayList<GeckoEventListener>();
} else if (listeners.contains(listener)) {
Log.w(LOGTAG, "EventListener already registered for event \"" + event + "\"",
new IllegalArgumentException());
}
listeners.add(listener);
mEventListeners.put(event, listeners);
}
}
public void unregisterEventListener(String event, GeckoEventListener listener) {
synchronized (mEventListeners) {
CopyOnWriteArrayList<GeckoEventListener> listeners = mEventListeners.get(event);
if (listeners == null) {
return;
}
listeners.remove(listener);
if (listeners.size() == 0) {
mEventListeners.remove(event);
}
}
}
public String dispatchEvent(String message) {
//
// {"gecko": {
// "type": "value",
// "event_specific": "value",
// ....
try {
JSONObject json = new JSONObject(message);
final JSONObject geckoObject = json.getJSONObject("gecko");
String type = geckoObject.getString("type");
CopyOnWriteArrayList<GeckoEventListener> listeners;
synchronized (mEventListeners) {
listeners = mEventListeners.get(type);
}
if (listeners == null)
return "";
String response = null;
for (GeckoEventListener listener : listeners) {
listener.handleMessage(type, geckoObject);
if (listener instanceof GeckoEventResponder) {
String newResponse = ((GeckoEventResponder)listener).getResponse();
if (response != null && newResponse != null) {
Log.e(LOGTAG, "Received two responses for message of type " + type);
}
response = newResponse;
}
}
if (response != null)
return response;
} catch (Exception e) {
Log.e(LOGTAG, "handleGeckoMessage throws " + e, e);
}
return "";
}
}