Backed out 2 changesets (bug 967325) for rc4 failures

Backed out changeset 5db7e8e8bd6c (bug 967325)
Backed out changeset bbd7ca6452ff (bug 967325)
This commit is contained in:
Wes Kocher 2014-08-11 16:31:15 -07:00
parent 9f7525e1fa
commit a891b9fc9e
7 changed files with 1 additions and 406 deletions

View File

@ -44,12 +44,8 @@ import org.mozilla.gecko.mozglue.RobocopTarget;
import org.mozilla.gecko.mozglue.generatorannotations.OptionalGeneratedParameter;
import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
import org.mozilla.gecko.prompts.PromptService;
import org.mozilla.gecko.util.EventCallback;
import org.mozilla.gecko.util.GeckoRequest;
import org.mozilla.gecko.util.HardwareUtils;
import org.mozilla.gecko.util.NativeEventListener;
import org.mozilla.gecko.util.NativeJSContainer;
import org.mozilla.gecko.util.NativeJSObject;
import org.mozilla.gecko.util.ProxySelector;
import org.mozilla.gecko.util.ThreadUtils;
@ -163,8 +159,6 @@ public class GeckoAppShell
private static Sensor gProximitySensor;
private static Sensor gLightSensor;
private static final String GECKOREQUEST_RESPONSE_KEY = "response";
/*
* Keep in sync with constants found here:
* http://mxr.mozilla.org/mozilla-central/source/uriloader/base/nsIWebProgressListener.idl
@ -411,36 +405,6 @@ public class GeckoAppShell
PENDING_EVENTS.add(e);
}
/**
* Sends an asynchronous request to Gecko.
*
* The response data will be passed to {@link GeckoRequest#onResponse(NativeJSObject)} if the
* request succeeds; otherwise, {@link GeckoRequest#onError()} will fire.
*
* This method follows the same queuing conditions as {@link #sendEventToGecko(GeckoEvent)}.
* It can be called from any thread. The GeckoRequest callbacks will be executed on the Gecko thread.
*
* @param request The request to dispatch. Cannot be null.
*/
@RobocopTarget
public static void sendRequestToGecko(final GeckoRequest request) {
final String responseMessage = "Gecko:Request" + request.getId();
EventDispatcher.getInstance().registerGeckoThreadListener(new NativeEventListener() {
@Override
public void handleMessage(String event, NativeJSObject message, EventCallback callback) {
EventDispatcher.getInstance().unregisterGeckoThreadListener(this, event);
if (!message.has(GECKOREQUEST_RESPONSE_KEY)) {
request.onError();
return;
}
request.onResponse(message.getObject(GECKOREQUEST_RESPONSE_KEY));
}
}, responseMessage);
sendEventToGecko(GeckoEvent.createBroadcastEvent(request.getName(), request.getData()));
}
// Tell the Gecko event loop that an event is available.
public static native void notifyGeckoOfEvent(GeckoEvent event);

View File

@ -63,7 +63,6 @@ gujar.sources += [
'util/GeckoBackgroundThread.java',
'util/GeckoEventListener.java',
'util/GeckoJarReader.java',
'util/GeckoRequest.java',
'util/HardwareUtils.java',
'util/INIParser.java',
'util/INISection.java',

View File

@ -122,7 +122,6 @@ skip-if = android_version == "10"
skip-if = android_version == "10"
[testAppMenuPathways]
[testEventDispatcher]
[testGeckoRequest]
[testInputConnection]
# disabled on Android 2.3; bug 1025968
skip-if = android_version == "10"

View File

@ -1,135 +0,0 @@
package org.mozilla.gecko.tests;
import java.util.concurrent.atomic.AtomicBoolean;
import com.jayway.android.robotium.solo.Condition;
import org.mozilla.gecko.GeckoAppShell;
import org.mozilla.gecko.tests.helpers.AssertionHelper;
import org.mozilla.gecko.tests.helpers.GeckoHelper;
import org.mozilla.gecko.tests.helpers.JavascriptBridge;
import org.mozilla.gecko.tests.helpers.NavigationHelper;
import org.mozilla.gecko.tests.helpers.WaitHelper;
import org.mozilla.gecko.util.GeckoRequest;
import org.mozilla.gecko.util.NativeJSObject;
/**
* Tests sending and receiving Gecko requests using the GeckoRequest API.
*/
public class testGeckoRequest extends UITest {
private static final String TEST_JS = "testGeckoRequest.js";
private static final int MAX_WAIT_MS = 1000;
private static final String REQUEST_EVENT = "Robocop:GeckoRequest";
private static final String REQUEST_EXCEPTION_EVENT = "Robocop:GeckoRequestException";
private JavascriptBridge js;
@Override
public void setUp() throws Exception {
super.setUp();
js = new JavascriptBridge(this);
}
@Override
public void tearDown() throws Exception {
js.disconnect();
super.tearDown();
}
public void testGeckoRequest() {
GeckoHelper.blockForReady();
NavigationHelper.enterAndLoadUrl(StringHelper.ROBOCOP_JS_HARNESS_URL + "?path=" + TEST_JS);
// Register a listener for this request.
js.syncCall("add_request_listener", REQUEST_EVENT);
// Make sure we receive the expected response.
checkFooRequest();
// Try registering a second listener for this request, which should fail.
js.syncCall("add_second_request_listener", REQUEST_EVENT);
// Unregister the listener for this request.
js.syncCall("remove_request_listener", REQUEST_EVENT);
// Make sure we don't receive a response after removing the listener.
checkUnregisteredRequest();
// Check that we still receive a response for listeners that throw.
js.syncCall("add_exception_listener", REQUEST_EXCEPTION_EVENT);
checkExceptionRequest();
js.syncCall("remove_request_listener", REQUEST_EXCEPTION_EVENT);
js.syncCall("finish_test");
}
private void checkFooRequest() {
final AtomicBoolean responseReceived = new AtomicBoolean(false);
final String data = "foo";
GeckoAppShell.sendRequestToGecko(new GeckoRequest(REQUEST_EVENT, data) {
@Override
public void onResponse(NativeJSObject nativeJSObject) {
// Ensure we receive the expected response from Gecko.
final String result = nativeJSObject.getString("result");
AssertionHelper.fAssertEquals("Sent and received request data", data + "bar", result);
responseReceived.set(true);
}
});
WaitHelper.waitFor("Received response for registered listener", new Condition() {
@Override
public boolean isSatisfied() {
return responseReceived.get();
}
}, MAX_WAIT_MS);
}
private void checkExceptionRequest() {
final AtomicBoolean responseReceived = new AtomicBoolean(false);
final AtomicBoolean errorReceived = new AtomicBoolean(false);
GeckoAppShell.sendRequestToGecko(new GeckoRequest(REQUEST_EXCEPTION_EVENT, null) {
@Override
public void onResponse(NativeJSObject nativeJSObject) {
responseReceived.set(true);
}
@Override
public void onError() {
errorReceived.set(true);
}
});
WaitHelper.waitFor("Received error for listener with exception", new Condition() {
@Override
public boolean isSatisfied() {
return errorReceived.get();
}
}, MAX_WAIT_MS);
AssertionHelper.fAssertTrue("onResponse not called for listener with exception", !responseReceived.get());
}
private void checkUnregisteredRequest() {
final AtomicBoolean responseReceived = new AtomicBoolean(false);
GeckoAppShell.sendRequestToGecko(new GeckoRequest(REQUEST_EVENT, null) {
@Override
public void onResponse(NativeJSObject nativeJSObject) {
responseReceived.set(true);
}
});
// This check makes sure that we do *not* receive a response for an unregistered listener,
// meaning waitForCondition() should always time out.
getSolo().waitForCondition(new Condition() {
@Override
public boolean isSatisfied() {
return responseReceived.get();
}
}, MAX_WAIT_MS);
AssertionHelper.fAssertTrue("Did not receive response for unregistered listener", !responseReceived.get());
}
}

View File

@ -1,40 +0,0 @@
Components.utils.import("resource://gre/modules/Messaging.jsm");
let java = new JavaBridge(this);
do_register_cleanup(() => {
java.disconnect();
});
do_test_pending();
function add_request_listener(message) {
RequestService.addListener(function (data) {
return { result: data + "bar" };
}, message);
}
function add_exception_listener(message) {
RequestService.addListener(function (data) {
throw "error!";
}, message);
}
function add_second_request_listener(message) {
let exceptionCaught = false;
try {
RequestService.addListener(() => {}, message);
} catch (e) {
exceptionCaught = true;
}
do_check_true(exceptionCaught);
}
function remove_request_listener(message) {
RequestService.removeListener(message);
}
function finish_test() {
do_test_finished();
}

View File

@ -1,91 +0,0 @@
package org.mozilla.gecko.util;
import java.util.concurrent.atomic.AtomicInteger;
import org.json.JSONException;
import org.json.JSONObject;
import org.mozilla.gecko.mozglue.RobocopTarget;
import android.util.Log;
public abstract class GeckoRequest {
private static final String LOGTAG = "GeckoRequest";
private static final AtomicInteger currentId = new AtomicInteger(0);
private final int id = currentId.getAndIncrement();
private final String name;
private final String data;
/**
* Creates a request that can be dispatched using
* {@link GeckoAppShell#sendRequestToGecko(GeckoRequest)}.
*
* @param name The name of the event associated with this request, which must have a
* Gecko-side listener registered to respond to this request.
* @param data Data to send with this request, which can be any object serializeable by
* {@link JSONObject#put(String, Object)}.
*/
@RobocopTarget
public GeckoRequest(String name, Object data) {
this.name = name;
final JSONObject message = new JSONObject();
try {
message.put("id", id);
message.put("data", data);
} catch (JSONException e) {
Log.e(LOGTAG, "JSON error", e);
}
this.data = message.toString();
}
/**
* Gets the ID for this request.
*
* @return The request ID
*/
public int getId() {
return id;
}
/**
* Gets the event name associated with this request.
*
* @return The name of the event sent to Gecko
*/
public String getName() {
return name;
}
/**
* Gets the stringified data associated with this request.
*
* @return The data being sent with the request
*/
public String getData() {
return data;
}
/**
* Callback executed when the request succeeds.
*
* @param nativeJSObject The response data from Gecko
*/
@RobocopTarget
public abstract void onResponse(NativeJSObject nativeJSObject);
/**
* Callback executed when the request fails.
*
* In general, this should not be overridden since there's no way to differentiate between
* expected errors and logic errors in JS. If the Gecko-side request handler wants to send a
* recoverable error to Java, it should include any error data in the response object that the
* {@link #onResponse(NativeJSObject)} callback can handle as necessary.
*
* @throws RuntimeException
*/
@RobocopTarget
public void onError() {
throw new RuntimeException("Unhandled error for GeckoRequest: " + name);
}
}

View File

@ -7,9 +7,8 @@ const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Task.jsm");
this.EXPORTED_SYMBOLS = ["sendMessageToJava", "RequestService"];
this.EXPORTED_SYMBOLS = ["sendMessageToJava"];
XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
"@mozilla.org/uuid-generator;1",
@ -43,103 +42,3 @@ function sendMessageToJava(aMessage, aCallback) {
return Services.androidBridge.handleGeckoMessage(aMessage);
}
let RequestService = {
/**
* Add a listener for the given message.
*
* Only one request listener can be registered for a given message.
*
* Example usage:
* RequestService.addListener({
* // aMessage is the message name.
* // aData is data sent from Java with the request.
* // The return value is used to respond to the request. The return
* // type *must* be an instance of Object.
* onRequest: function (aMessage, aData) {
* if (aData == "foo") {
* return { response: "bar" };
* }
* return {};
* }
* }, "Demo:Request");
*
* The listener may also be a generator function, useful for performing a
* task asynchronously. For example:
* RequestService.addListener({
* onRequest: function* (aMessage, aData) {
* let deferred = Promise.defer();
* setTimeout(deferred.resolve, 2000);
* yield deferred.resolve;
* return { response: "bar" };
* }
* }, "Demo:Request");
*
* @param aListener Listener object with an onRequest function (see example
* usage above).
* @param aMessage Event name that this listener should observe.
*/
addListener: function (aListener, aMessage) {
requestHandler.addListener(aListener, aMessage);
},
/**
* Removes a listener for a given message.
*
* @param aMessage The event to stop listening for.
*/
removeListener: function (aMessage) {
requestHandler.removeListener(aMessage);
},
};
let requestHandler = {
_listeners: {},
addListener: function (aListener, aMessage) {
if (aMessage in this._listeners) {
throw new Error("Error in addListener: A listener already exists for message " + aMessage);
}
if (typeof aListener !== "function") {
throw new Error("Error in addListener: Listener must be a function for message " + aMessage);
}
this._listeners[aMessage] = aListener;
Services.obs.addObserver(this, aMessage, false);
},
removeListener: function (aMessage) {
if (!(aMessage in this._listeners)) {
throw new Error("Error in removeListener: There is no listener for message " + aMessage);
}
delete this._listeners[aMessage];
Services.obs.removeObserver(this, aMessage);
},
observe: Task.async(function* (aSubject, aTopic, aData) {
let wrapper = JSON.parse(aData);
let listener = this._listeners[aTopic];
// A null response indicates an error. If an error occurs in the callback
// below, the response will remain null, and Java will fire onError for
// this request.
let response = null;
try {
let result = yield listener(wrapper.data);
if (typeof result !== "object" || result === null) {
throw new Error("Gecko request listener did not return an object");
}
response = result;
} catch (e) {
Cu.reportError(e);
}
sendMessageToJava({
type: "Gecko:Request" + wrapper.id,
response: response
});
})
};