gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] /srv/bzr/gnash/trunk r12259: migrate from branch. Error h


From: Rob Savoye
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r12259: migrate from branch. Error handling now works, and remote functions are now accessible to Javascript
Date: Fri, 18 Jun 2010 09:48:04 -0600
User-agent: Bazaar (2.0.3)

------------------------------------------------------------
revno: 12259 [merge]
committer: Rob Savoye <address@hidden>
branch nick: trunk
timestamp: Fri 2010-06-18 09:48:04 -0600
message:
  migrate from branch. Error handling now works, and remote functions are now 
accessible to Javascript
modified:
  gui/gnash.cpp
  libcore/ExternalInterface.cpp
  libcore/ExternalInterface.h
  libcore/asobj/flash/external/ExternalInterface_as.cpp
  libcore/movie_root.cpp
  libcore/movie_root.h
  plugin/npapi/callbacks.cpp
  plugin/npapi/callbacks.h
  plugin/npapi/plugin.cpp
  plugin/npapi/plugin.h
  plugin/npapi/pluginScriptObject.cpp
  plugin/npapi/pluginScriptObject.h
  plugin/npapi/scriptable-test.html
  testsuite/actionscript.all/ExternalInterface.as
=== modified file 'gui/gnash.cpp'
--- a/gui/gnash.cpp     2010-05-08 21:33:27 +0000
+++ b/gui/gnash.cpp     2010-06-15 16:45:19 +0000
@@ -141,7 +141,7 @@
             "URLs\n") 
     << _("  -P,  --param <param>     Set parameter (e.g. "
             "\"FlashVars=A=1&b=2\")\n") 
-    << _("  -F,  --fd <fd>           Filedescriptor to use for external "
+    << _("  -F,  --fd <fd>:<fd>      Filedescriptor to use for external "
             "communications\n") 
 #ifdef GNASH_FPS_DEBUG
     << _("  -f,  --debug-fps num     Print FPS every num seconds (float)\n") 

=== modified file 'libcore/ExternalInterface.cpp'
--- a/libcore/ExternalInterface.cpp     2010-06-03 19:29:37 +0000
+++ b/libcore/ExternalInterface.cpp     2010-06-15 16:52:07 +0000
@@ -469,7 +469,7 @@
         }
     }
 
-    log_debug("Argument is: %s", value.to_string());
+//    log_debug("Argument is: %s", value.to_string());
     return value;
 }
 

=== modified file 'libcore/ExternalInterface.h'
--- a/libcore/ExternalInterface.h       2010-06-08 14:25:12 +0000
+++ b/libcore/ExternalInterface.h       2010-06-15 16:52:07 +0000
@@ -35,6 +35,7 @@
 struct ObjectURI;
 class Global_as;
 class movie_root;
+class IOChannel;
 }
 
 namespace gnash {

=== modified file 'libcore/asobj/flash/external/ExternalInterface_as.cpp'
--- a/libcore/asobj/flash/external/ExternalInterface_as.cpp     2010-06-04 
13:14:31 +0000
+++ b/libcore/asobj/flash/external/ExternalInterface_as.cpp     2010-06-18 
03:29:25 +0000
@@ -36,6 +36,7 @@
 #include "smart_ptr.h" // for boost intrusive_ptr
 #include "builtin_function.h" // need builtin_function
 #include "GnashException.h" // for ActionException
+#include "URLAccessManager.h"
 #include "VM.h"
 #include "rc.h"
 #include "as_value.h"
@@ -229,11 +230,11 @@
     callMethod(&gl, NSV::PROP_AS_SET_PROP_FLAGS, &o, null, 7);
 }
 
+// This adds a function that can be called from javascript.
 as_value
 externalinterface_addCallback(const fn_call& fn)
 {
     // GNASH_REPORT_FUNCTION;
-
     movie_root& mr = getRoot(fn);
 
     if (mr.getControlFD() <= 0) {
@@ -248,35 +249,44 @@
         if (fn.arg(2).is_object()) {
             log_debug("adding callback %s", name);
             asCallback = (fn.arg(2).to_object(getGlobal(fn)));
-            mr.addExternalCallback(name, asCallback.get());
+            mr.addExternalCallback(fn.this_ptr, name, asCallback.get());
         }
-        return as_value(true);
-    }
-    
+     }
+
+    // This function doesn't actually have a return value, but we do this
+    // to quiet warnings about not returning anything, as the return
+    // value should never be checked anyway.
     return as_value(false);    
 }
 
+// This calls a Javascript function in the browser.
 as_value
 externalinterface_call(const fn_call& fn)
 {
     // GNASH_REPORT_FUNCTION;
-
     movie_root& mr = getRoot(fn);
+    as_value val;
 
     if (fn.nargs >= 2) {
         const as_value& methodName_as = fn.arg(0);
         const std::string methodName = methodName_as.to_string();
         const std::vector<as_value>& args = fn.getArgs();
         log_debug("Calling External method \"%s\"", methodName);
-        std::string result = mr.callExternalCallback(methodName, args);
-        if (result.empty()) {
-            return as_value();
+        std::string result = mr.callExternalJavascript(methodName, args);
+        if (!result.empty()) {
+            val = ExternalInterface::parseXML(result);
+            // There was an error trying to Invoke the callback
+            if (result == ExternalInterface::makeString("Error")
+                || (result == ExternalInterface::makeString("SecurityError"))) 
{
+                val.set_null();
+            }
         } else {
-            return as_value(result);
+            // We got nothing back from the Invoke, so return an error
+            val.set_null();
         }
     }
     
-    return as_value();
+    return val;
 }
 
 as_value
@@ -286,6 +296,12 @@
     
     movie_root& m = getRoot(fn);
     bool mode = false;
+
+    // If we're not running under a browser as a plugin, then just
+    // return, as ExternalInterface is only available as a plugin.
+    if (m.getHostFD() < 0) {
+        return false;
+    }
     
     switch (m.getAllowScriptAccess()) {
       case movie_root::SCRIPT_ACCESS_NEVER:
@@ -297,6 +313,7 @@
           const std::string& baseurl = m.getOriginalURL();
           const int MAXHOSTNAMELEN = 128;
           char hostname[MAXHOSTNAMELEN];
+          memset(hostname, 0, MAXHOSTNAMELEN);
           
           if (gethostname(hostname, MAXHOSTNAMELEN) != 0) {
               mode = false;
@@ -305,6 +322,10 @@
           // The hostname is empty if running the standalone Gnash from
           // a terminal, so we can assume the default of sameDomain applies.
           URL localPath(hostname, baseurl);
+          // If the URL has a file protocol, then 
+          if (URLAccessManager::allow(localPath)) {
+              return as_value(true);
+          }
           if (localPath.hostname().empty()) {
               mode = false;
           } else {

=== modified file 'libcore/movie_root.cpp'
--- a/libcore/movie_root.cpp    2010-06-12 01:40:51 +0000
+++ b/libcore/movie_root.cpp    2010-06-18 03:28:37 +0000
@@ -1617,13 +1617,14 @@
     if (invoke == 0) {
        return false;
     }
+    
     if (invoke->name.empty()) {
        return false;
     }
 
     log_debug("Processing %s call from the Browser.", invoke->name);
 
-    std::stringstream ss;
+    std::stringstream ss;       // ss is the response string
 
     // These are the default methods used by ExternalInterface
     if (invoke->name == "Quit") {
@@ -1635,8 +1636,13 @@
        // SetVariable doesn't send a response
     } else if (invoke->name == "GetVariable") {
        // GetVariable sends the value of the variable
+#if 1
        as_value val("Hello World");
        // FIXME: need to use a real value
+#else
+        as_object::SortedPropertyList props;
+        enumerateProperties(o, props);
+#endif
        ss << ExternalInterface::toXML(val);
     } else if (invoke->name == "GotoFrame") {
        // GotoFrame doesn't send a response
@@ -1670,11 +1676,13 @@
        // FIXME: need to use a real value
        ss << ExternalInterface::toXML(val);
     } else {
-       std::map<std::string, as_object *>::const_iterator it;
-       for (it=_externalCallbacks.begin(); it != _externalCallbacks.end(); 
it++) {
-           std::string method = it->first;
-           log_debug("Checking against method name: %s", method);
-       }
+        std::string result = callExternalCallback(invoke->name, invoke->args);
+        if (result == ExternalInterface::makeString("Error")) {
+            return false;
+        } else if (result == ExternalInterface::makeString("SecurityError")) {
+            return false;
+        }
+        return true;
     }
 
     if (!ss.str().empty()) {
@@ -1856,31 +1864,139 @@
     return 0;
 }
 
-// This calls a JavaScript method in the web page
+/// @example "Internal Gnash message 'addMethod'"
+///
+/// <pre>
+/// <invoke name="addMethod" returntype="xml">
+///      <arguments><string>methodname</string</arguments>
+/// </invoke>
+/// </pre>
+void
+movie_root::addExternalCallback(as_object *obj, const std::string &name,
+                                as_object *callback)
+{
+    GNASH_REPORT_FUNCTION;
+    
+    _externalCallbacks.push_back(ExternalCallback(obj, name, callback));
+
+    if (_hostfd) {
+        std::vector<as_value> fnargs;
+        fnargs.push_back(name);
+        std::string msg = ExternalInterface::makeInvoke("addMethod", fnargs);
+        
+        const size_t ret = ExternalInterface::writeBrowser(_hostfd, msg);
+        if (ret != msg.size()) {
+            log_error(_("Could not write to browser fd #%d: %s"),
+                      _hostfd, std::strerror(errno));
+        }
+    }
+}    
+
+/// This calls a JavaScript method in the web page
+///
+/// @example "ExternalInterace::call message"
+///
+/// <pre>
+/// <invoke name="methodname" returntype="xml">
+///      <arguments></arguments>
+///             ...
+///      <arguments></arguments>
+/// </invoke>
+///
+/// May return any supported type like Number or String in XML format.
+///
+/// </pre>
+std::string
+movie_root::callExternalJavascript(const std::string &name, 
+                                   const std::vector<as_value> &fnargs)
+{
+    std::string result;
+    ExternalCallbacks::const_iterator it;
+    // If the browser is connected, we send an Invoke message to the
+    // browser.
+    if (_controlfd && _hostfd) {
+        std::string msg = ExternalInterface::makeInvoke(name, fnargs);
+        
+        const size_t ret = ExternalInterface::writeBrowser(_hostfd, msg);
+        if (ret != msg.size()) {
+            log_error(_("Could not write to browser fd #%d: %s"),
+                      _hostfd, std::strerror(errno));
+        } else {
+            // Now read the response from the browser after it's exectuted
+            // the JavaScript function.
+            result = ExternalInterface::readBrowser(_controlfd);
+        }
+    }
+
+    return result;
+}
+
+// Call one of the registered callbacks, and return the result to
+// Javascript in the browser.
 std::string
 movie_root::callExternalCallback(const std::string &name, 
                                 const std::vector<as_value> &fnargs)
 {
-
-    if (_hostfd) {
-        return std::string();
-    }
-
-    std::string msg = ExternalInterface::makeInvoke(name, fnargs);
-
-    const size_t ret = ExternalInterface::writeBrowser(_hostfd, msg);
-    if (ret != msg.size()) {
-        log_error(_("Could not write to browser fd #%d: %s"),
-                 _hostfd, std::strerror(errno));
-        return std::string();
-    }
-
-    std::string result = ExternalInterface::readBrowser(_controlfd);
+    std::string result;
+    ExternalCallbacks::const_iterator it;
+    for (it=_externalCallbacks.begin(); it != _externalCallbacks.end(); it++) {
+        ExternalCallback ec = *it;
+        log_debug("Checking %s against method name: %s", name, 
ec.methodName());
+
+        // FIXME: call the AS method here!
+
+        as_value val;
+        if (name == ec.methodName()) {
+            std::string result;
+            val = ec.call(fnargs);
+        }
+        
+        if (val.is_null()) {
+            // Return an error
+            result = ExternalInterface::makeString("Error");
+        } else {
+            result = ExternalInterface::toXML(val);
+        }
+        
+        // If the browser is connected, we send an Invoke message to the
+        // browser.
+        if (_hostfd) {
+            const size_t ret = ExternalInterface::writeBrowser(_hostfd, 
result);
+            if (ret != result.size()) {
+                log_error(_("Could not write to browser fd #%d: %s"),
+                          _hostfd, std::strerror(errno));
+            }
+        }
+    }
 
     return result;
 }
 
 void
+movie_root::ExternalCallback::setReachable() const
+{
+    _caller->setReachable();
+}
+
+as_value
+movie_root::ExternalCallback::call(const std::vector<as_value>& args)
+{
+    GNASH_REPORT_FUNCTION;
+
+#if 0
+    as_environment env(VM::get());
+    fn_call::Args newargs;
+    as_function *as_func = _callback->to_function();    
+    fn_call fn(0, env, newargs);
+
+    as_func->call(fn);
+#endif
+    
+    return as_value();
+}
+
+
+void
 movie_root::cleanupDisplayList()
 {
 
@@ -2553,3 +2669,7 @@
 
 } // namespace gnash
 
+// local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:

=== modified file 'libcore/movie_root.h'
--- a/libcore/movie_root.h      2010-06-06 11:27:45 +0000
+++ b/libcore/movie_root.h      2010-06-18 03:29:09 +0000
@@ -164,8 +164,25 @@
         SimpleBuffer _buf;
         as_object* _obj;
     };
-        
     typedef std::list<LoadCallback> LoadCallbacks;
+        
+    class ExternalCallback {
+    public:
+        ExternalCallback(as_object *obj, const std::string &name,
+                         as_object *callback)
+            : _name(name),
+              _caller(obj),
+              _callback(callback)
+        {}
+        std::string &methodName() { return _name; };
+        as_value call(const std::vector<as_value>& args);
+        void setReachable() const;
+    private:
+        std::string     _name;
+        as_object       *_caller;
+        as_object       *_callback;
+    };        
+    typedef std::list<ExternalCallback> ExternalCallbacks;
 
     typedef std::bitset<key::KEYCOUNT> Keys;
 
@@ -920,15 +937,16 @@
 
     const RunResources& runResources() const { return _runResources; }
 
-    void addExternalCallback(const std::string &name, as_object *obj)
-    {
-        _externalCallbacks[name] = obj;
-    }    
+    void addExternalCallback(as_object *obj, const std::string &name,
+                             as_object *callback);
 
     bool processInvoke(ExternalInterface::invoke_t *);
 
     std::string callExternalCallback(const std::string &name, 
                                      const std::vector<as_value>& args);
+    
+    std::string callExternalJavascript(const std::string &name, 
+                                       const std::vector<as_value>& args);
 
     /// Removes a queued constructor from the execution queue
     //
@@ -1141,7 +1159,6 @@
 
     LoadCallbacks _loadCallbacks;
     
-    typedef std::map<std::string, as_object *> ExternalCallbacks;
     ExternalCallbacks _externalCallbacks;
 
     typedef std::map<int, Timer*> TimerMap;

=== modified file 'plugin/npapi/callbacks.cpp'
--- a/plugin/npapi/callbacks.cpp        2010-05-31 22:19:55 +0000
+++ b/plugin/npapi/callbacks.cpp        2010-06-18 03:27:56 +0000
@@ -170,14 +170,12 @@
 
     GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)npobj;
 
-    ExternalInterface ei;
-
     std::string varname;
     if (argCount == 1) {
-        std::string str = ei.convertNPVariant(&args[0]);
+        std::string str = ExternalInterface::convertNPVariant(&args[0]);
         std::vector<std::string> iargs;
         iargs.push_back(str);
-        str = ei.makeInvoke("GotoFrame", iargs);
+        str = ExternalInterface::makeInvoke("GotoFrame", iargs);
 
         // Write the message to the Control FD.
         size_t ret = gpso->writePlayer(str);
@@ -214,9 +212,8 @@
     GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)npobj;
 
     if (argCount == 0) {
-        ExternalInterface ei;
         std::vector<std::string> iargs;
-        std::string str = ei.makeInvoke("IsPlaying", iargs);
+        std::string str = ExternalInterface::makeInvoke("IsPlaying", iargs);
         
         // Write the message to the Control FD.
         size_t ret = gpso->writePlayer(str);
@@ -233,7 +230,7 @@
             return false;
         }
 
-        GnashNPVariant value = ei.parseXML(data);
+        GnashNPVariant value = ExternalInterface::parseXML(data);
         if (NPVARIANT_TO_BOOLEAN(value.get()) == true) {
             BOOLEAN_TO_NPVARIANT(true, *result);
         } else {
@@ -268,15 +265,14 @@
     GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)npobj;
     
     if (argCount == 2) {
-        ExternalInterface ei;
         // int layer = NPVARIANT_TO_INT32(args[0]);
         // std::string url = NPStringToString(NPVARIANT_TO_STRING(args[1]));
-        std::string str = ei.convertNPVariant(&args[0]);
+        std::string str = ExternalInterface::convertNPVariant(&args[0]);
         std::vector<std::string> iargs;
         iargs.push_back(str);
-        str = ei.convertNPVariant(&args[1]);
+        str = ExternalInterface::convertNPVariant(&args[1]);
         iargs.push_back(str);
-        str = ei.makeInvoke("LoadMovie", iargs);
+        str = ExternalInterface::makeInvoke("LoadMovie", iargs);
 
         // Write the message to the Control FD.
         size_t ret = gpso->writePlayer(str);
@@ -317,15 +313,14 @@
     GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)npobj;
 
     if (argCount == 3) {
-        ExternalInterface ei;
-        std::string str = ei.convertNPVariant(&args[0]);
+        std::string str = ExternalInterface::convertNPVariant(&args[0]);
         std::vector<std::string> iargs;
         iargs.push_back(str);
-        str = ei.convertNPVariant(&args[1]);
-        iargs.push_back(str);
-        str = ei.convertNPVariant(&args[2]);
-        iargs.push_back(str);
-        str = ei.makeInvoke("Pan", iargs);
+        str = ExternalInterface::convertNPVariant(&args[1]);
+        iargs.push_back(str);
+        str = ExternalInterface::convertNPVariant(&args[2]);
+        iargs.push_back(str);
+        str = ExternalInterface::makeInvoke("Pan", iargs);
         
         // Write the message to the Control FD.
         size_t ret = gpso->writePlayer(str);
@@ -353,13 +348,11 @@
 // Receives something like this:
 //      <number>33</number>
 bool
-PercentLoaded (NPObject *npobj, NPIdentifier /* name */, const NPVariant 
*/*args */,
-          uint32_t argCount, NPVariant *result)
+PercentLoaded (NPObject */* npobj */, NPIdentifier /* name */, const NPVariant 
*/*args */,
+               uint32_t /* argCount */, NPVariant *result)
 {   
 //    log_debug(__PRETTY_FUNCTION__);
     
-    GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)npobj;
-
 #if 1
     static int counter = 0;
 //    log_error("%s: %d ; %d\n", __FUNCTION__, gpso->getControlFD(), counter);
@@ -371,10 +364,11 @@
     }
     return true;
 #else
+    GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)npobj;
+
     if (argCount == 0) {
-        ExternalInterface ei;
         std::vector<std::string> iargs;
-        std::string str = ei.makeInvoke("PercentLoaded", iargs);
+        std::string str = ExternalInterface::makeInvoke("PercentLoaded", 
iargs);
 
         // Write the message to the Control FD.
         size_t ret = gpso->writePlayer(str);
@@ -424,9 +418,8 @@
     GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)npobj;
 
     if (argCount == 0) {
-        ExternalInterface ei;
         std::vector<std::string> iargs;
-        std::string str = ei.makeInvoke("Play", iargs);
+        std::string str = ExternalInterface::makeInvoke("Play", iargs);
 
         // Write the message to the Control FD.
         size_t ret = gpso->writePlayer(str);
@@ -463,9 +456,8 @@
     GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)npobj;
 
     if (argCount == 0) {
-        ExternalInterface ei;
         std::vector<std::string> iargs;
-        std::string str = ei.makeInvoke("Rewind", iargs);
+        std::string str = ExternalInterface::makeInvoke("Rewind", iargs);
 
         // Write the message to the Control FD.
         size_t ret = gpso->writePlayer(str);
@@ -506,17 +498,16 @@
     GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)npobj;
 
     if (argCount == 4) {
-        ExternalInterface ei;
-        std::string str = ei.convertNPVariant(&args[0]);
+        std::string str = ExternalInterface::convertNPVariant(&args[0]);
         std::vector<std::string> iargs;
         iargs.push_back(str);
-        str = ei.convertNPVariant(&args[1]);
-        iargs.push_back(str);
-        str = ei.convertNPVariant(&args[2]);
-        iargs.push_back(str);
-        str = ei.convertNPVariant(&args[3]);
-        iargs.push_back(str);
-        str = ei.makeInvoke("SetZoomRect", iargs);
+        str = ExternalInterface::convertNPVariant(&args[1]);
+        iargs.push_back(str);
+        str = ExternalInterface::convertNPVariant(&args[2]);
+        iargs.push_back(str);
+        str = ExternalInterface::convertNPVariant(&args[3]);
+        iargs.push_back(str);
+        str = ExternalInterface::makeInvoke("SetZoomRect", iargs);
 
         // Write the message to the Control FD.
         size_t ret = gpso->writePlayer(str);
@@ -552,9 +543,8 @@
     GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)npobj;
 
     if (argCount == 0) {
-        ExternalInterface ei;
         std::vector<std::string> iargs;
-        std::string str = ei.makeInvoke("StopPlay", iargs);
+        std::string str = ExternalInterface::makeInvoke("StopPlay", iargs);
 
         // Write the message to the Control FD.
         size_t ret = gpso->writePlayer(str);
@@ -593,11 +583,10 @@
     GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)npobj;
 
     if (argCount == 1) {
-        ExternalInterface ei;
-        std::string str = ei.convertNPVariant(&args[0]);
+        std::string str = ExternalInterface::convertNPVariant(&args[0]);
         std::vector<std::string> iargs;
         iargs.push_back(str);
-        str = ei.makeInvoke("Zoom", iargs);
+        str = ExternalInterface::makeInvoke("Zoom", iargs);
 
         // Write the message to the Control FD.
         size_t ret = gpso->writePlayer(str);
@@ -633,9 +622,8 @@
     GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)npobj;
 
     if (argCount == 0) {
-        ExternalInterface ei;
         std::vector<std::string> iargs;
-        std::string str = ei.makeInvoke("TotalFrames", iargs);
+        std::string str = ExternalInterface::makeInvoke("TotalFrames", iargs);
 
         // Write the message to the Control FD.
         size_t ret = gpso->writePlayer(str);
@@ -652,7 +640,7 @@
             return false;
         }
 
-        GnashNPVariant value = ei.parseXML(data);
+        GnashNPVariant value = ExternalInterface::parseXML(data);
         if (NPVARIANT_IS_INT32(value.get())) {
             value.copy(*result);
         } else {
@@ -666,6 +654,82 @@
     return false;
 }
 
+// Sends something like this:
+// <invoke name="TestASMethod" returntype="xml">
+//      <arguments>
+//              <number>123</number>
+//      </arguments>
+// </invoke>
+//
+//    Receives:
+//     An XML response of one of the standard types like Number or String.
+bool
+remoteCallback (NPObject *npobj, NPIdentifier name, const NPVariant *args,
+          uint32_t argCount, NPVariant *result)
+{   
+    // log_debug(__PRETTY_FUNCTION__);
+
+    GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)npobj;
+
+    std::string method;
+    
+#if 1
+    if (NPN_IdentifierIsString(name)) {
+        log_debug("Invoking remote Method \"%s\"...",
+                  NPN_UTF8FromIdentifier(name));
+        method = NPN_UTF8FromIdentifier(name);
+    } else {
+        log_debug("Invoking remote Method: \"%d\"...",
+                  NPN_IntFromIdentifier(name));
+    }
+#endif
+
+    // Build the argument array
+    std::vector<std::string> fnargs;
+    for (uint32_t i=0; i<argCount; ++i) {
+        std::string xml = ExternalInterface::convertNPVariant(&args[i]);
+        fnargs.push_back(xml);
+        
+    }
+    
+    std::string str = ExternalInterface::makeInvoke(method, fnargs);
+
+    // Write the message to the Control FD.
+    size_t ret = gpso->writePlayer(str);
+    // Unless we wrote the same amount of data as the message contained,
+    // something went wrong.
+    if (ret != str.size()) {
+        log_error("Couldn't invoke %s, network problems.", method);
+            return false;
+    }        
+
+    // Have the read function allocate the memory
+    std::string data = gpso->readPlayer();
+    if (data.empty()) {
+        log_error("Couldn't read a response for invoke, network problems.");
+        NULL_TO_NPVARIANT(*result);
+        return false;
+    }
+
+    std::string answer;
+    GnashNPVariant parsed = ExternalInterface::parseXML(data);
+    if (!NPVARIANT_IS_NULL(parsed.get())) {
+        answer = NPStringToString(NPVARIANT_TO_STRING(parsed.get()));
+    }
+    if (answer == "Error") {
+        NULL_TO_NPVARIANT(*result);
+    } else if (answer == "SecurityError") {
+        NULL_TO_NPVARIANT(*result);
+    } else {
+        parsed.copy(*result);
+    }
+    
+    // printNPVariant(&parsed.get());
+
+    // Returning false makes Javascript stop executing the script.
+    return true;
+}
+
 } // end of gnash namespace
 
 // local Variables:

=== modified file 'plugin/npapi/callbacks.h'
--- a/plugin/npapi/callbacks.h  2010-04-21 19:46:03 +0000
+++ b/plugin/npapi/callbacks.h  2010-06-16 20:02:01 +0000
@@ -287,6 +287,10 @@
                           const NPVariant *args, uint32_t argCount,
                           NPVariant *result);
 
+extern bool remoteCallback (NPObject *npobj, NPIdentifier name,
+                            const NPVariant *args, uint32_t argCount,
+                            NPVariant *result);
+
 #endif // GNASH_PLUGIN_CALLBACKS_H
 
 } // end of gnash namespace

=== modified file 'plugin/npapi/plugin.cpp'
--- a/plugin/npapi/plugin.cpp   2010-06-12 01:40:51 +0000
+++ b/plugin/npapi/plugin.cpp   2010-06-17 20:35:31 +0000
@@ -66,6 +66,7 @@
 #include "GnashSystemIOHeaders.h"
 #include "StringPredicates.h"
 #include "external.h"
+#include "callbacks.h"
 #include "npapi.h"
 #include "npruntime.h"
 #include "npfunctions.h"
@@ -321,6 +322,8 @@
 nsPluginInstanceBase *
 NS_NewPluginInstance(nsPluginCreateData * aCreateDataStruct)
 {
+    // gnash::log_debug(__PRETTY_FUNCTION__);
+
     if(!aCreateDataStruct) {
         return NULL;
     }
@@ -358,8 +361,11 @@
     _controlfd(-1),
     _childpid(0),
     _filefd(-1),
-    _name()
+    _name(),
+    _scriptObject(0)
 {
+    // gnash::log_debug("%s: %x", __PRETTY_FUNCTION__, (void *)this);
+
     for (size_t i=0, n=data->argc; i<n; ++i) {
         std::string name, val;
         gnash::StringNoCaseEqual noCaseCompare;
@@ -378,11 +384,14 @@
 
         _params[name] = val;
     }
-    
+
+#if 1
     if (NPNFuncs.version >= 14) { // since NPAPI start to support
         _scriptObject = (GnashPluginScriptObject *)NPNFuncs.createobject(
             _instance, GnashPluginScriptObject::marshalGetNPClass());
+        log_debug("SCRIPT OBJECT create: %x, ns: %x", (void *)_scriptObject, 
(void *)this);
     }
+#endif
     
     return;
 }
@@ -535,6 +544,7 @@
 NPError
 nsPluginInstance::GetValue(NPPVariable aVariable, void *aValue)
 {
+
     if (aVariable == NPPVpluginScriptableNPObject) {
         if (_scriptObject) {
             void **v = (void **)aValue;
@@ -545,6 +555,8 @@
         }
     }    
 
+    // log_debug("SCRIPT OBJECT getValue: %x, ns: %x", (void *)_scriptObject, 
(void *)this);
+
     return NS_PluginGetValue(aVariable, aValue);
 }
 
@@ -569,6 +581,8 @@
 nsPluginInstance::NewStream(NPMIMEType /*type*/, NPStream* stream,
                             NPBool /*seekable*/, uint16_t* /*stype*/)
 {
+    // gnash::log_debug("%s: %x", __PRETTY_FUNCTION__, (void *)this);
+
     if (_childpid) {
         // Apparently the child process has already been started for this
         // plugin instance. It is puzzling that this method gets called
@@ -639,6 +653,7 @@
 bool
 nsPluginInstance::handlePlayerRequests(GIOChannel* iochan, GIOCondition cond)
 {
+    // gnash::log_debug("%s: %d: %x", __PRETTY_FUNCTION__, __LINE__, (void 
*)this);
 
     if ( cond & G_IO_HUP ) {
         gnash::log_debug("Player control socket hang up");
@@ -658,6 +673,8 @@
     //    g_io_channel_set_flags(iochan, G_IO_FLAG_NONBLOCK, &error);
 
     size_t retries = 5;
+    gchar* request = 0;
+    gsize requestSize = 0;
     do {
         // When in non-blocking mode, we'll get several iterations of this
         // loop while waiting for data. if data never arrives, we'd be stuck
@@ -667,8 +684,8 @@
             return false;
         }
         error = 0;
-        gchar* request = 0;
-        gsize requestSize = 0;
+        request = 0;
+        requestSize = 0;
         GIOStatus status = g_io_channel_read_line(iochan, &request,
                            &requestSize, NULL, &error);
         switch (status) {
@@ -699,20 +716,21 @@
               gnash::log_error("Abnormal status!");
               return false;
         }
-
-        // process request..
-        processPlayerRequest(request, requestSize);
-        g_free(request);
-
     } while (g_io_channel_get_buffer_condition(iochan) & G_IO_IN);
 
+    // process request..
+    processPlayerRequest(request, requestSize);
+    g_free(request);
+    
     return true;
-
 }
 
 bool
 nsPluginInstance::processPlayerRequest(gchar* buf, gsize linelen)
 {
+    // gnash::log_debug(__PRETTY_FUNCTION__);
+
+   // log_debug("SCRIPT OBJECT %d: %x", __LINE__, this->getScriptObject());
 
     if ( linelen < 4 ) {
         if (buf) {
@@ -725,6 +743,10 @@
     
     ExternalInterface::invoke_t *invoke = ExternalInterface::parseInvoke(buf);
 
+    if (!invoke->name.empty()) {
+        gnash::log_debug("Requested method is: %s", invoke->name);
+    }
+    
     // The invoke message is also used for getURL. In this case there are 4
     // possible arguments.
     if (invoke) {
@@ -786,7 +808,43 @@
             
             NPN_GetURL(_instance, jsurl.str().c_str(), tgt);
             return true;
-        }
+        } else if (invoke->name == "addMethod") {
+            // Make this flash function accessible to Javascript. The
+            // actual callback lives in libcore/movie_root, but it
+            // needs to be on the list of supported remote methods so
+            // it can be called by Javascript.
+            std::string method = NPStringToString(NPVARIANT_TO_STRING(
+                                                      invoke->args[0].get()));
+            NPIdentifier id = NPN_GetStringIdentifier(method.c_str());
+            // log_debug("SCRIPT OBJECT addMethod: %x, %s", (void 
*)_scriptObject, method);
+            this->getScriptObject()->AddMethod(id, remoteCallback);
+            return true;
+        }
+        NPVariant *result = 0;
+        // This is the player invoking a method in Javascript
+        uint32_t count = 0;
+        NPVariant args;
+        if (!invoke->name.empty()) {
+            NPIdentifier id = NPN_GetStringIdentifier(invoke->name.c_str());   
   
+            gnash::log_debug("Invoking JavaScript method %s", invoke->name);
+            NPN_Invoke(_instance, _scriptObject, id, &args, count, result);
+        }
+        // We got a result from invoking the Javascript method
+        std::stringstream ss;
+        if (result) {
+            NPN_ReleaseVariantValue(result);
+            ss << ExternalInterface::convertNPVariant(result);
+        } else {
+            // Send response
+            // FIXME: "securityError" also possible, check domain
+            ss << ExternalInterface::makeString("Error");
+        }
+        size_t ret = _scriptObject->writePlayer(ss.str());
+        if (ret != ss.str().size()) {
+            log_error("Couldn't write the response to Gnash, network 
problems.");
+            return false;
+        }
+        return true;
     } else {
         gnash::log_error("Unknown player request: " + std::string(buf));
         return false;

=== modified file 'plugin/npapi/plugin.h'
--- a/plugin/npapi/plugin.h     2010-05-08 21:33:27 +0000
+++ b/plugin/npapi/plugin.h     2010-06-18 15:48:04 +0000
@@ -83,11 +83,11 @@
     /// Can the stream be written to yet ?
     int32_t WriteReady(NPStream *stream);
     int32_t Write(NPStream *stream, int32_t offset, int32_t len, void *buffer);
-#ifdef ENABLE_SCRIPTABLE
     NPObject *getScriptableObject();
     const char *getEmbedURL() const;
-#endif
-    
+
+    GnashPluginScriptObject *getScriptObject() { return _scriptObject; }; // 
FIXME: debug only!!!
+
 private:
     void startProc();
     std::vector<std::string> getCmdLine(int hostfd, int controlfd);
@@ -129,9 +129,7 @@
 
     /// Name of the plugin instance element in the dom 
     std::string                        _name;
-//#ifdef ENABLE_SCRIPTABLE
     GnashPluginScriptObject             *_scriptObject;
-//#endif
     
     std::string getCurrentPageURL() const;
 };
@@ -142,7 +140,6 @@
 //  0: no messages at all
 //  1: fatal errors (errors preventing the plugin from working as it should)
 //  2: informational messages
-//
 #define GNASH_PLUGIN_DEBUG 1
 
 // This following logging code is copied from libbase/log.h, but

=== modified file 'plugin/npapi/pluginScriptObject.cpp'
--- a/plugin/npapi/pluginScriptObject.cpp       2010-06-12 01:10:28 +0000
+++ b/plugin/npapi/pluginScriptObject.cpp       2010-06-17 21:16:54 +0000
@@ -157,7 +157,7 @@
 void
 GnashPluginScriptObject::initializeIdentifiers()
 {
-//    log_debug("initializeIdentifiers");
+    // log_debug("initializeIdentifiers");
 
 //    NPN_Status(_nppinstance, __FUNCTION__);
     
@@ -275,6 +275,8 @@
     id = NPN_GetStringIdentifier("TotalFrames");
     AddMethod(id, TotalFrames);
     
+    // id = NPN_GetStringIdentifier("TestASMethod");
+    // AddMethod(id, remoteCallback);
 };
 
 // Constructor
@@ -282,6 +284,7 @@
     : _nppinstance (0)
 {
 //    log_debug(__PRETTY_FUNCTION__);
+    
     initializeIdentifiers();
     
     _sockfds[READFD] = 0;
@@ -293,6 +296,7 @@
     : _nppinstance (npp)
 {
 //    log_debug(__PRETTY_FUNCTION__);
+    
     initializeIdentifiers();
 
     _sockfds[READFD] = 0;
@@ -373,11 +377,9 @@
                                         const NPVariant *args, uint32_t 
argCount,
                                         NPVariant *result)
 {
-    // log_debug(__PRETTY_FUNCTION__);
-    
     GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)npobj;
     
-    return gpso->Invoke(name, args, argCount, result);
+    return gpso->Invoke(npobj, name, args, argCount, result);
 }
 
 bool 
@@ -386,8 +388,6 @@
                                                uint32_t argCount,
                                                NPVariant *result)
 {
-    // log_debug(__PRETTY_FUNCTION__);
-
     GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)npobj;
     
     return gpso->InvokeDefault(args, argCount, result);
@@ -396,8 +396,6 @@
 bool 
 GnashPluginScriptObject::marshalHasProperty (NPObject *npobj, NPIdentifier 
name)
 {
-//    log_debug(__PRETTY_FUNCTION__);
-    
     GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)npobj;
 
     return gpso->HasProperty(name);
@@ -407,8 +405,6 @@
 GnashPluginScriptObject::marshalGetProperty (NPObject *npobj, NPIdentifier 
name,
                                              NPVariant *result)
 {
-//    log_debug(__PRETTY_FUNCTION__);
-
     GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)npobj;
     
     return gpso->GetProperty(name, result);    
@@ -418,8 +414,6 @@
 GnashPluginScriptObject::marshalSetProperty (NPObject *npobj, NPIdentifier 
name,
                                              const NPVariant *value)
 {
-//    log_debug(__PRETTY_FUNCTION__);
-
     GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)npobj;    
     return gpso->SetProperty(name, *value);
 }
@@ -427,8 +421,6 @@
 bool 
 GnashPluginScriptObject::marshalRemoveProperty (NPObject *npobj, NPIdentifier 
name)
 {
-//    log_debug(__PRETTY_FUNCTION__);
-
     GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)npobj;    
     return gpso->RemoveProperty(name);
 }
@@ -460,8 +452,6 @@
 bool
 GnashPluginScriptObject::HasProperty(NPIdentifier name)
 {
-//    log_debug(__PRETTY_FUNCTION__);
-
 #if 0
     log_debug("Checking for Property \"");
     if (NPN_IdentifierIsString(name)) {
@@ -477,8 +467,6 @@
 bool
 GnashPluginScriptObject::GetProperty(NPIdentifier name, NPVariant *result)
 {
-    // log_debug(__PRETTY_FUNCTION__);
-
     if (NPN_IdentifierIsString(name)) {
         log_debug("Getting Property %s\"...", NPN_UTF8FromIdentifier(name));
     } else {
@@ -500,8 +488,6 @@
 bool
 GnashPluginScriptObject::SetProperty(NPIdentifier name, const NPVariant& value)
 {
-    // log_debug(__PRETTY_FUNCTION__);
-
     _properties[name] = value;
 
     return false;
@@ -510,8 +496,6 @@
 bool
 GnashPluginScriptObject::RemoveProperty(NPIdentifier name)
 {
-    // log_debug(__PRETTY_FUNCTION__);
-
     std::map<NPIdentifier, GnashNPVariant>::iterator it;
     it = _properties.find(name);
     if (it != _properties.end()) {
@@ -542,8 +526,6 @@
 bool
 GnashPluginScriptObject::HasMethod(NPIdentifier name)
 {
-//    log_debug(__PRETTY_FUNCTION__);
-
 #if 0
     log_debug("Checking for Method \"");
     if (NPN_IdentifierIsString(name)) {
@@ -557,27 +539,35 @@
 }
 
 bool
-GnashPluginScriptObject::Invoke(NPIdentifier name, const NPVariant *args, 
uint32_t argCount, NPVariant *result)
+GnashPluginScriptObject::Invoke(NPObject */* npobj */, NPIdentifier name,
+                                const NPVariant *args, uint32_t argCount,
+                                NPVariant *result)
 {
 //    log_debug(__PRETTY_FUNCTION__);
-#if 0
-    log_debug("Invoking Method \"");
+    
+#if 1
     if (NPN_IdentifierIsString(name)) {
-        log_debug("%s\"...", NPN_UTF8FromIdentifier(name));
+        log_debug("Invoking Method \"%s\"...", NPN_UTF8FromIdentifier(name));
     } else {
-        log_debug("%d\"...", NPN_IntFromIdentifier(name));
+        log_debug("Invoking Method: \"%d\"...", NPN_IntFromIdentifier(name));
     }
+    // log_debug("SCRIPT OBJECT invoke %s: %x", NPN_UTF8FromIdentifier(name),
+    //           (void *)npobj);    
 #endif
 
     std::map<NPIdentifier, NPInvokeFunctionPtr>::iterator it;
     it = _methods.find(name);
     if (it != _methods.end()) {
-        // log_debug(" FOUND");
+        // log_debug("FOUND Method \"%s\"!", NPN_UTF8FromIdentifier(name));
         NPInvokeFunctionPtr func = it->second;
         return func(NULL, name, args, argCount, result);
+    } else {
+        log_error("Couldn't find Method \"%s\"", NPN_UTF8FromIdentifier(name));
     }
 
     return false;
+    
+//    return NPN_Invoke(_nppinstance, this, name, args, argCount, result);
 }
 
 bool
@@ -603,11 +593,10 @@
 //    log_debug(__PRETTY_FUNCTION__);
     
 #if 0
-    log_debug("Adding Method \"");
     if (NPN_IdentifierIsString(name)) {
-        log_debug("%s\"...", NPN_UTF8FromIdentifier(name));
+        log_debug("Adding Method \"%s\"...", NPN_UTF8FromIdentifier(name));
     } else {
-        log_debug("%d\"...", NPN_IntFromIdentifier(name));
+        log_debug("Adding Method \"%d\"...", NPN_IntFromIdentifier(name));
     }
 #endif
 
@@ -622,7 +611,6 @@
 GnashPluginScriptObject::SetVariable(const std::string &name,
                                      const NPVariant& value)
 {
-    log_debug(__PRETTY_FUNCTION__);
     std::vector<std::string> iargs;
     std::string str = ExternalInterface::makeString(name);
     iargs.push_back(str);
@@ -630,6 +618,8 @@
     iargs.push_back(str);
     str = ExternalInterface::makeInvoke("SetVariable", iargs);
     
+    log_debug("Trying to set a value for %s.", name);
+
     // Write the message to the Control FD.
     size_t ret = writePlayer(str);
     // Unless we wrote the same amount of data as the message contained,
@@ -648,8 +638,6 @@
 GnashNPVariant
 GnashPluginScriptObject::GetVariable(const std::string &name)
 {
-    log_debug(__PRETTY_FUNCTION__);
-
     std::vector<std::string> iargs;
     std::string str = ExternalInterface::makeString(name);
     iargs.push_back(str);
@@ -780,7 +768,7 @@
     FD_ZERO(&fdset);
     FD_SET(fd, &fdset);
     struct timeval tval;
-    tval.tv_sec = 10;
+    tval.tv_sec = 2;
     tval.tv_usec = 0;
     // log_debug("Waiting for data... ");
     if (select(fd+1, &fdset, NULL, NULL, &tval)) {
@@ -791,7 +779,6 @@
         ioctlSocket(fd, FIONREAD, &bytes);
 #endif
     }
-        
 
     // No data yet
     if (bytes == 0) {
@@ -811,8 +798,6 @@
         buf.resize(ret);
     }
 
-    std::cout << buf << std::endl;
-    
     return buf;
 }
 
@@ -827,7 +812,7 @@
         // Send a Quit message to the player before closing the pipe.
         std::vector<std::string> args;
         std::string str = ExternalInterface::makeInvoke("Quit", args);
-        size_t ret = writePlayer(fd, str);
+        writePlayer(fd, str);
     
         ::shutdown(fd, SHUT_RDWR);
         ::close(fd);

=== modified file 'plugin/npapi/pluginScriptObject.h'
--- a/plugin/npapi/pluginScriptObject.h 2010-06-01 03:10:58 +0000
+++ b/plugin/npapi/pluginScriptObject.h 2010-06-17 20:35:31 +0000
@@ -131,8 +131,10 @@
     bool checkPipe(int fd);
 
     int getReadFD()  { return _sockfds[READFD]; };
+    GIOChannel *getReadChannel()  { return _iochan[READFD]; };
     int getWriteFD() { return _sockfds[WRITEFD]; };
-    
+    GIOChannel *getWriteChannel() { return _iochan[WRITEFD]; };
+
     // Write to the standalone player over the control socket
     int writePlayer(const std::string &data);
     int writePlayer(int fd, const std::string &data);
@@ -141,19 +143,21 @@
     std::string readPlayer();
     std::string readPlayer(int fd);
     
-protected:
+    bool Invoke(NPObject *npobj, NPIdentifier name, const NPVariant *args,
+                uint32_t argCount, NPVariant *result);
     bool AddMethod(NPIdentifier name, NPInvokeFunctionPtr func);
     void AddProperty(const std::string &name, const std::string &str);
     void AddProperty(const std::string &name, double num);
     void AddProperty(const std::string &name, int num);
 
+protected:
     // Internal functions for the API
     void Deallocate();
     void Invalidate();
     bool HasMethod(NPIdentifier name);
 
-    bool Invoke(NPIdentifier name, const NPVariant *args, uint32_t argCount, 
NPVariant *result);
-    bool InvokeDefault(const NPVariant *args, uint32_t argCount, NPVariant 
*result);
+    bool InvokeDefault(const NPVariant *args, uint32_t argCount,
+                       NPVariant *result);
     bool HasProperty(NPIdentifier name);
     bool GetProperty(NPIdentifier name, NPVariant *result);
     bool SetProperty(NPIdentifier name, const NPVariant& value);
@@ -161,7 +165,7 @@
     bool Enumerate(NPIdentifier **identifier, uint32_t *count);
     bool Construct(const NPVariant *data, uint32_t argCount, NPVariant 
*result);
 
-    bool handleInvoke(GIOChannel* iochan, GIOCondition cond);
+    bool handleInvoke(GIOChannel *iochan, GIOCondition cond);
     
     /// Process a null-terminated request line
     //

=== modified file 'plugin/npapi/scriptable-test.html'
--- a/plugin/npapi/scriptable-test.html 2010-06-01 04:15:48 +0000
+++ b/plugin/npapi/scriptable-test.html 2010-06-17 20:35:31 +0000
@@ -35,11 +35,41 @@
     </div>
     <div id="content">
       
-    <embed type="application/x-shockwave-flash" width="1" height="1" 
hidden="true">
+<!-- 
+   This next test is a bit hokey, we should really trim down
+   the ExternalInterface test to one that's focused on this
+   web page. But for now, this gives us a resident player that we
+   can bounce XML messages off of.
+
+   To make this work for you, copy testsuite/Dejagnu.swf and
+   testsuite/actionsctiona.all/EsternalInterfce-v8.swf from your build
+   tree to your source tree in plugin/npapi/. You can then attach GDB
+   to the PID of gnash running, letting you debug the processing of
+   XML messages to and from the browser. For this to work the swf
+   files must be in the same directory as the html file.
+   
+<param name="allowScriptAccess" value="sameDomain" />
+-->
+<div>
+<object>
+<param name="movie" value="ExternalInterface-v8.swf"
+<param name="allowScriptAccess" value="always" />
+<embed
+src="ExternalInterface-v8.swf"
+quality="high" wmode="transparent" width="640" height="100"
+   type="application/x-shockwave-flash"
+   pluginspage="http://www.getgnash.org";>
+</embed>
+</div>
+
+<!--
+   <embed type="application/x-shockwave-flash" width="1" height="1" 
hidden="true">
+-->
 
     <ul id="test-actions">
       <li><button onclick='ShowVersion()'>Show Version</button></li>
-      <li><button onclick='ShowFoobar("barfood")'>Show Foobar</button></li>
+      <li><button onclick='TestJSMethod("foodbar")'>TestJSMethod</button></li>
+      <li><button 
onclick='TestASMethodJS("barfood")'>TestASMethodJS</button></li>
       <li><button onclick='FlashSetVariable("var1", 
"value1")'>SetVariable</button></li>
       <li><button onclick='FlashGetVariable("var1")'>GetVariable</button></li>
       <li><button onclick='FlashGotoFrame(123)'>GotoFrame</button></li>
@@ -53,7 +83,7 @@
       <li><button onclick='FlashStopPlay()'>StopPlay</button></li>
       <li><button onclick='FlashZoom(12)'>Zoom</button></li>
       <li><button onclick='FlashTotalFrames()'>TotalFrames</button></li>
-      <li><button onclick='FlashTestEIMethod()'>TestEIMethod</button></li>
+      <li><button 
onclick='FlashTestASMethod("barby")'>FlashTestASMethod</button></li>
     </ul>
 
 </div>
@@ -227,48 +257,39 @@
                   addLog(value);
         }
 
-        function FlashTestEIMethod()
+          // This gets call a javascript method
+        function TestJSMethod(msg)
+          {
+                addLog("executed TestJSMethod");
+          }
+
+        function FlashTestASMethod(msg)
         {
-                  var value = embed.TestEIMethod();
-        //          addLog("TestEIMethod() = " + value);          
+                  addLog("flashTestASMethod(): enter " + msg);
+                  var value = embed.TestASMethod(msg);
                   addLog(value);
+                  embed.SetVariable("variable1", 1.1);
+                  addLog("flashTestASMethod(): return");         
         }
 
-        function ShowFoobar(msg)
+          // This calls a method in gnash
+        function TestASMethodJS(msg)
         {
-            addLog(embed.SetVariable("foo", "bar"));
-            addLog(embed.SetVariable("fuby", 1.1));
-            addLog(embed.GetVariable("foo"));
-            if (typeof embed.showFoobar === 'function') {
-                addLog('Running embed.showFoobar("'+msg+'")');
-                addLog(embed.showFoobar(msg));
-            } else {
-                addLog("Quitting: embed.showFoobar is not a function. Tried 
running embed.showFoobar('"+msg+"')");
-            }
+            addLog("TestASMethod(): enter " + msg);
+            var value = embed.TestASMethod(msg);
+            addLog(value);
+            embed.SetVariable("variable2", 1.1);
+//            if (typeof embed.TestASMethod === 'function') {
+//                addLog('Running embed.TestASMethod("'+msg+'")');
+//                addLog(embed.TestASMethod(msg));
+//            } else {
+//                addLog("Quitting: embed.TestASMethod is not a function.");
+//            }
+//          addLog(embed.GetVariable("$version"));
+            addLog("TestASMethod(): return ");
         }
 </script>
 
-<!-- 
-   This next test is a bit hokey, we should really trim down
-   the ExternalInterface test sae to e one that's focused on this
-   web page. ut for now, this gives us a resident player that we
-   can bounce XML messages off of.
-
-   To make this work for you, copy testsuite/Dejagnu.swf and
-   testsuite/actionsctiona.all/EsternalInterfce-v8.swf from your build
-   tree to your source tree in plugin/npapi/. You can then attach GDB
-   to the PID of gnash running, letting you debug the processing of
-   XML messages to and from the browser.
--->
-<object>
-<param name="movie" value="ExternalInterface-v8.swf"
-<embed
-src="ExternalInterface-v8.swf"
-quality="high" wmode="transparent" width="320" height="240"
-   type="application/x-shockwave-flash"
-   pluginspage="http://www.getgnash.org";>
-</embed>
-
 <!--
    This causes this page to do an immediate redirect, but at least then
    we know this is working.
@@ -283,6 +304,13 @@
 </embed>
 -->
 
+<!--
+<a href="javascript:;" onclick="window.open('geturl.swf',
+       '_selfXX',
+       'width=100,height=100,location=yes,resizable=yes');
+ return false">GetURL test</a>
+-->
+
 </body>
 </html>
 

=== modified file 'testsuite/actionscript.all/ExternalInterface.as'
--- a/testsuite/actionscript.all/ExternalInterface.as   2010-06-03 15:07:12 
+0000
+++ b/testsuite/actionscript.all/ExternalInterface.as   2010-06-15 16:36:37 
+0000
@@ -22,6 +22,8 @@
 
 #include "dejagnu.as"
 
+flash.system.Security.allowDomain("localhost");
+
 ASSetPropFlags (_global, "flash", 0, 5248);
 
 #if OUTPUT_VERSION < 6
@@ -59,34 +61,38 @@
     fail("ExternalInterface::available() doesn't exist");
 }
 
-// this should always be true now that Gnash supports this class,
-// and sameDomain is the default when running standalone.
-if (EI.available == false) {
-    pass("ExternalInterface::available is correct");
-} else {
-    fail("ExternalInterface::available property isn't correct");
-}
-
 // Create a test function for the callback
-function TestEIMethod () {
-    note("TestEIMethod called!");
+function TestASMethod () {
+    note("TestASMethod called!");
 }
 
-if (EI.addCallback("TestEIMethod", null, TestEIMethod) == false) {
-    pass("ExternalInterface::addCallback(\"TestEIMethod\")");
-} else {
-    fail("ExternalInterface::addCallback(\"TestEIMethod\")");
-}
+// ExternalInterface::available is always false when run standalone,
+// and true if running under a browser and has allowable access to the
+// resource. So we can't have a test case for this property that works
+// both standalone and online Instead we do depend on it being correct
+// as the ExternalInterface::call() tests require this test case to
+// be run under a browser.
 
 // ::call() calls JavaScript functions in the browser, not in flash,
 // so we can't test it when running standalone. So this will always
-// return null.
-var foo = EI.call("TestEIMethod", null);
+// return null unless run from a browser
 
-if (EI.call("TestEIMethod", null) == null) {
-    pass("ExternalInterface::call(\"TestEIMethod\")");
+// This adds a callback that the brower can call from Javascript. This is
+// a bit of a bogus test case, as addCallback() doesn't return anything, but
+// we need to add a method anyway to test being called by Javascript.
+if (EI.addCallback("TestASMethod", null, TestASMethod) == false) {
+    pass("ExternalInterface::addCallback(\"TestASMethod\")");
 } else {
-    fail("ExternalInterface::call(\"TestEIMethod\")");
+    fail("ExternalInterface::addCallback(\"TestASMethod\")");
+}
+
+if (EI.available == true) {
+  // This test tries to invoke a Javascript method running in the browser
+  if (EI.call("TestJSMethod", "test") == null) {
+    pass("ExternalInterface::call(\"TestJSMethod\") == null");
+  } else {
+    fail("ExternalInterface::call(\"TestJSMethod\") == null");
+  }
 }
 
 // The default is false, so if we can set it to true, it worked


reply via email to

[Prev in Thread] Current Thread [Next in Thread]