Ben Bucksch wrote:
Mark Finkle wrote, On 02.10.2014 22:02:
I finally got around to working on ways for the Java embedding/host
application to inject JavaScript into the GeckoView context [1].
Coupled with injecting scripts is a mechanism to communicate between
the JavaScript in GeckoView and the Java in the host application.
Dang!
For the SWT embedding and a customer of mine, Neil Rashbrook was
working on the exact same thing. Neil, can you please attach and
describe your patch and compare the approaches?
Up to XULRunner 10, SWT was using JS_EvaluateUCScriptForPrincipals. SWT
doesn't seem to support XULRunner 17, but for XULRunner 24 the
conditions for invoking JS_EvaluateUCScriptForPrincipals changed and SWT
didn't adapt to them correctly (despite having a comment to the
contrary, they used an AutoCompartment instead of an nsContextPusher).
As such SWT didn't correctly invoke script on XULRunner 24.
Having identified the problem it was reasonably simple to switch the SWT
glue library from AutoCompartment to nsContextPusher to resolve the
problem with XULRunner 24, however this doesn't help with XULRunner 31
which exports far fewer symbols, and requires mucking around with
JS::Handle because of its rooting garbage collector. (This is
particularly difficult because SWT doesn't want to include the SDK
headers, so you have to make stub copies of all the necessary declarations.)
Looking into various ways of invoking scripts I decided the simplest way
would be for SWT to inject a <script> node into the DOM of the window in
which it wanted the script to execute, which is what I implemented in
the attached patch. This bypasses the problematic part of the SWT glue
library completely, although of course a sufficiently assiduous page
would notice the brief existence of the <script> node (it is removed
after the script executes).
Having fixed the rest of SWT* to work with XULRunner 31 I was pleased to
find that this code transparently works with XULRunner 31.
*Apart from some other JSObject hackery which is something I still need
to look into; again my preference would be to find a solution that is as
version-agnostic as possible.
.../common/org/eclipse/swt/browser/Mozilla.java | 111 +++++++++++++++------
.../swt/internal/mozilla/nsIDOMDocument.java | 8 ++
.../eclipse/swt/internal/mozilla/nsIDOMNode.java | 8 ++
3 files changed, 94 insertions(+), 33 deletions(-)
diff --git a/bundles/org.eclipse.swt/Eclipse SWT
Mozilla/common/org/eclipse/swt/browser/Mozilla.java
b/bundles/org.eclipse.swt/Eclipse SWT
Mozilla/common/org/eclipse/swt/browser/Mozilla.java
index 267df39..c38a251 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT
Mozilla/common/org/eclipse/swt/browser/Mozilla.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT
Mozilla/common/org/eclipse/swt/browser/Mozilla.java
@@ -1400,6 +1400,80 @@ public boolean execute (String script) {
*/
delegate.removeWindowSubclass ();
+ long /*int*/[] result = new long /*int*/[1];
+ /*
+ * As of mozilla 1.9 executing javascript via the javascript: protocol no
+ * longer happens synchronously. As a result, the result of executing JS
+ * is not returned to the java side when expected by the client. The
+ * workaround for version 24 is to inject a script element into the DOM,
+ * which then executes synchronously.
+ */
+ if (MozillaVersion.CheckVersion (MozillaVersion.VERSION_XR24)) {
+ result[0] = 0;
+ int rc = webBrowser.QueryInterface (IIDStore.GetIID
(nsIInterfaceRequestor.class), result);
+ if (rc != XPCOM.NS_OK) error (rc);
+ if (result[0] == 0) error (XPCOM.NS_NOINTERFACE);
+ nsIInterfaceRequestor interfaceRequestor = new
nsIInterfaceRequestor (result[0]);
+
+ result[0] = 0;
+ rc = interfaceRequestor.GetInterface (IIDStore.GetIID
(nsIDOMDocument.class), result);
+ interfaceRequestor.Release ();
+ if (rc != XPCOM.NS_OK) error (rc);
+ if (result[0] == 0) error (XPCOM.NS_NOINTERFACE);
+ nsIDOMDocument domDocument = new nsIDOMDocument (result[0]);
+ nsIDOMNode documentElement = null, scriptElement = null,
textNode = null;
+
+ try {
+ result[0] = 0;
+ rc = domDocument.GetDocumentElement (result);
+ if (rc != XPCOM.NS_OK) error (rc);
+ if (result[0] == 0) error (XPCOM.NS_ERROR_NULL_POINTER);
+ documentElement = new nsIDOMNode (result[0]);
+
+ result[0] = 0;
+ nsEmbedString scriptTag = new nsEmbedString ("script");
+ rc = domDocument.CreateElement (scriptTag, result);
+ scriptTag.dispose ();
+ if (rc != XPCOM.NS_OK) error (rc);
+ if (result[0] == 0) error (XPCOM.NS_ERROR_NULL_POINTER);
+ scriptElement = new nsIDOMNode (result[0]);
+
+ result[0] = 0;
+ nsEmbedString data = new nsEmbedString (script);
+ rc = domDocument.CreateTextNode (data, result);
+ data.dispose ();
+ if (rc != XPCOM.NS_OK) error (rc);
+ if (result[0] == 0) error (XPCOM.NS_ERROR_NULL_POINTER);
+ textNode = new nsIDOMNode (result[0]);
+
+ result[0] = 0;
+ rc = scriptElement.AppendChild (textNode, result);
+ if (rc != XPCOM.NS_OK) error (rc);
+ if (result[0] == 0) error (XPCOM.NS_ERROR_NULL_POINTER);
+ new nsISupports (result[0]).Release ();
+
+ rc = documentElement.AppendChild (scriptElement,
result);
+ if (rc != XPCOM.NS_OK) error (rc);
+ if (result[0] == 0) error (XPCOM.NS_ERROR_NULL_POINTER);
+ new nsISupports (result[0]).Release ();
+
+ rc = documentElement.RemoveChild (scriptElement,
result);
+ if (rc != XPCOM.NS_OK) error (rc);
+ if (result[0] == 0) error (XPCOM.NS_ERROR_NULL_POINTER);
+ new nsISupports (result[0]).Release ();
+
+ return true;
+ } finally {
+ if (textNode != null)
+ textNode.Release ();
+ if (scriptElement != null)
+ scriptElement.Release ();
+ if (documentElement != null)
+ documentElement.Release ();
+ domDocument.Release ();
+ }
+ }
+
/*
* As of mozilla 1.9 executing javascript via the javascript: protocol no
* longer happens synchronously. As a result, the result of executing JS
@@ -1407,7 +1481,6 @@ public boolean execute (String script) {
* workaround is to invoke the javascript handler directly via C++,
which is
* exposed as of mozilla 1.9.
*/
- long /*int*/[] result = new long /*int*/[1];
if (MozillaVersion.CheckVersion (MozillaVersion.VERSION_XR1_9)) {
int rc = XPCOM.NS_GetServiceManager (result);
if (rc != XPCOM.NS_OK) error (rc);
@@ -1439,20 +1512,11 @@ public boolean execute (String script) {
if (rc == XPCOM.NS_OK && result[0] != 0) {
long /*int*/ scriptGlobalObject =
result[0];
result[0] = 0;
- if (MozillaVersion.CheckVersion
(MozillaVersion.VERSION_XR24)) { /* >= 24.x */
- rc =
(int/*64*/)XPCOM.nsIScriptGlobalObject24_EnsureScriptEnvironment
(scriptGlobalObject);
- } else {
- rc =
(int/*64*/)XPCOM.nsIScriptGlobalObject_EnsureScriptEnvironment
(scriptGlobalObject, 2); /* nsIProgrammingLanguage.JAVASCRIPT */
- }
+ rc =
(int/*64*/)XPCOM.nsIScriptGlobalObject_EnsureScriptEnvironment
(scriptGlobalObject, 2); /* nsIProgrammingLanguage.JAVASCRIPT */
if (rc != XPCOM.NS_OK) {
new nsISupports
(scriptGlobalObject).Release ();
} else {
- long /*int*/ scriptContext;
- if (MozillaVersion.CheckVersion
(MozillaVersion.VERSION_XR24)) { /* >= 24.x */
- scriptContext =
XPCOM.nsIScriptGlobalObject24_GetScriptContext (scriptGlobalObject);
- } else {
- scriptContext =
XPCOM.nsIScriptGlobalObject_GetScriptContext (scriptGlobalObject, 2); /*
nsIProgrammingLanguage.JAVASCRIPT */
- }
+ long /*int*/ scriptContext =
XPCOM.nsIScriptGlobalObject_GetScriptContext (scriptGlobalObject, 2); /*
nsIProgrammingLanguage.JAVASCRIPT */
if (scriptContext != 0) {
/* ensure that the
received nsIScriptContext implements the expected interface */
@@ -1462,12 +1526,7 @@ public boolean execute (String script) {
new nsISupports
(result[0]).Release ();
result[0] = 0;
- long /*int*/
jsContext;
- if
(MozillaVersion.CheckVersion (MozillaVersion.VERSION_XR24)) { /* >= 24.x */
-
jsContext = XPCOM.nsIScriptContext24_GetNativeContext (scriptContext);
- } else {
-
jsContext = XPCOM.nsIScriptContext_GetNativeContext (scriptContext);
- }
+ long /*int*/
jsContext = XPCOM.nsIScriptContext_GetNativeContext (scriptContext);
if (jsContext
!= 0) {
int
length = script.length ();
char[]
scriptChars = new char[length];
@@ -1480,22 +1539,8 @@ public boolean execute (String script) {
result[0] = 0;
}
byte[]
jsLibPath = getJSLibPathBytes ();
- long
/*int*/ globalJSObject;
- if
(MozillaVersion.CheckVersion (MozillaVersion.VERSION_XR24)) { /* >= 24.x */
-
globalJSObject = XPCOM.nsIScriptGlobalObject24_GetGlobalJSObject
(scriptGlobalObject);
- } else {
-
globalJSObject = XPCOM.JS_GetGlobalObject (jsLibPath, jsContext);
- }
+ long
/*int*/ globalJSObject = XPCOM.JS_GetGlobalObject (jsLibPath, jsContext);
if
(globalJSObject != 0) {
-
if (MozillaVersion.CheckVersion (MozillaVersion.VERSION_XR24)) { /* >= 24.x */
-
boolean success = XPCOM.JS_EvaluateUCScriptForPrincipals24 (jsLibPath,
jsContext, globalJSObject, principals, scriptChars, length, urlbytes, 0, 0) !=
0;
-
// should principals be Release()d too?
-
new nsISupports (scriptGlobalObject).Release ();
-
principal.Release ();
-
serviceManager.Release ();
-
return success;
-
}
-
/* 1.9.x - 10.x */
aContractID = MozillaDelegate.wcsToMbcs (null,
XPCOM.NS_CONTEXTSTACK_CONTRACTID, true);
rc = serviceManager.GetServiceByContractID (aContractID, IIDStore.GetIID
(nsIJSContextStack.class), result);
if (rc == XPCOM.NS_OK && result[0] != 0) {
diff --git a/bundles/org.eclipse.swt/Eclipse SWT
Mozilla/common/org/eclipse/swt/internal/mozilla/nsIDOMDocument.java
b/bundles/org.eclipse.swt/Eclipse SWT
Mozilla/common/org/eclipse/swt/internal/mozilla/nsIDOMDocument.java
index d1736d3..5e1619e 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT
Mozilla/common/org/eclipse/swt/internal/mozilla/nsIDOMDocument.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT
Mozilla/common/org/eclipse/swt/internal/mozilla/nsIDOMDocument.java
@@ -49,4 +49,12 @@ public class nsIDOMDocument extends nsIDOMNode {
public int GetDocumentElement(long /*int*/[] aDocumentElement) {
return XPCOM.VtblCall(nsIDOMNode.LAST_METHOD_ID + 3,
getAddress(), aDocumentElement);
}
+
+ public int CreateElement(nsEmbedString tagName, long /*int*/[]
aElement) {
+ return XPCOM.VtblCall(nsIDOMNode.LAST_METHOD_ID + 4,
getAddress(), tagName.getAddress(), aElement);
+ }
+
+ public int CreateTextNode(nsEmbedString data, long /*int*/[] aText) {
+ return XPCOM.VtblCall(nsIDOMNode.LAST_METHOD_ID + 6,
getAddress(), data.getAddress(), aText);
+ }
}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT
Mozilla/common/org/eclipse/swt/internal/mozilla/nsIDOMNode.java
b/bundles/org.eclipse.swt/Eclipse SWT
Mozilla/common/org/eclipse/swt/internal/mozilla/nsIDOMNode.java
index 4757984..7928bce 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT
Mozilla/common/org/eclipse/swt/internal/mozilla/nsIDOMNode.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT
Mozilla/common/org/eclipse/swt/internal/mozilla/nsIDOMNode.java
@@ -46,6 +46,14 @@ public class nsIDOMNode extends nsISupports {
super(address);
}
+ public int RemoveChild(nsIDOMNode aChild, long /*int*/[] aReturned) {
+ return XPCOM.VtblCall(nsISupports.LAST_METHOD_ID + 15,
getAddress(), aChild.getAddress(), aReturned);
+ }
+
+ public int AppendChild(nsIDOMNode aChild, long /*int*/[] aReturned) {
+ return XPCOM.VtblCall(nsISupports.LAST_METHOD_ID + 16,
getAddress(), aChild.getAddress(), aReturned);
+ }
+
public static final int ELEMENT_NODE = 1;
public static final int ATTRIBUTE_NODE = 2;
public static final int TEXT_NODE = 3;
_______________________________________________
mobile-firefox-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/mobile-firefox-dev