mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
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:
parent
9f7525e1fa
commit
a891b9fc9e
@ -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);
|
||||
|
||||
|
@ -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',
|
||||
|
@ -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"
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
||||
});
|
||||
})
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user