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

Reply via email to