gnash-commit
[Top][All Lists]
Advanced

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

[Gnash-commit] /srv/bzr/gnash/trunk r12207: merge from branch all Extern


From: Rob Savoye
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r12207: merge from branch all ExternalInterface refactoring.
Date: Wed, 02 Jun 2010 08:18:20 -0600
User-agent: Bazaar (2.0.3)

------------------------------------------------------------
revno: 12207 [merge]
committer: Rob Savoye <address@hidden>
branch nick: trunk
timestamp: Wed 2010-06-02 08:18:20 -0600
message:
  merge from branch all ExternalInterface refactoring.
added:
  libcore/ExternalInterface.cpp
  libcore/ExternalInterface.h
  plugin/npapi/geturl.as
  plugin/npapi/gshell.cpp
modified:
  configure.ac
  gui/Player.cpp
  libcore/Makefile.am
  libcore/asobj/flash/external/ExternalInterface_as.cpp
  libcore/asobj/flash/external/ExternalInterface_as.h
  libcore/movie_root.cpp
  libcore/movie_root.h
  plugin/npapi/Makefile.am
  plugin/npapi/callbacks.cpp
  plugin/npapi/external.cpp
  plugin/npapi/external.h
  plugin/npapi/mozilla-sdk/npn_gate.cpp
  plugin/npapi/plugin.cpp
  plugin/npapi/pluginScriptObject.cpp
  plugin/npapi/pluginScriptObject.h
  plugin/npapi/scriptable-test.html
  plugin/npapi/test.cpp
  testsuite/actionscript.all/ExternalInterface.as
  testsuite/misc-haxe.all/classes.all/system/System_as.hx
=== modified file 'configure.ac'
--- a/configure.ac      2010-05-19 18:02:36 +0000
+++ b/configure.ac      2010-06-02 14:18:20 +0000
@@ -283,19 +283,6 @@
     AC_DEFINE(ENABLE_AVM2, [1], [Enable AVM2 code])
 fi
 
-AC_ARG_ENABLE(scriptable,
-  AC_HELP_STRING([--enable-scriptable], [Enable support for AS3]),
-  [case "${enableval}" in
-    yes) scriptable=yes ;;
-    no)  scriptable=no ;;
-    *)   AC_MSG_ERROR([bad value ${enableval} for enable-scriptable option]) ;;
-  esac], scriptable=yes
-)
-AM_CONDITIONAL(SCRIPTABLE, [test x"$scriptable" = xyes])
-if test x$scriptable = xyes; then
-    AC_DEFINE(ENABLE_SCRIPTABLE, [1], [Enable scriptable code in plugin])
-fi
-
 dnl This option is only used if you want Gnash to interwork with 
 dnl the Adobe player using the LocalConnection class.
 dnl lckey=0xdd3adabd

=== modified file 'gui/Player.cpp'
--- a/gui/Player.cpp    2010-05-21 01:26:20 +0000
+++ b/gui/Player.cpp    2010-06-01 02:31:30 +0000
@@ -47,6 +47,7 @@
 #include "noseek_fd_adapter.h"
 #include "VM.h"
 #include "SystemClock.h"
+#include "ExternalInterface.h"
 
 #ifdef USE_FFMPEG
 # include "MediaHandlerFfmpeg.h"
@@ -445,7 +446,7 @@
     
     if (_controlfd != -1) {
         root.setControlFD(_controlfd);        
-        _gui->setFDCallback(_controlfd, boost::bind(&Gui::quit, 
boost::ref(_gui)));
+//        _gui->setFDCallback(_controlfd, boost::bind(&Gui::quit, 
boost::ref(_gui)));
     }
 
     _gui->setStage(&root);
@@ -690,7 +691,10 @@
     if (hostfd != -1) {
         //log_debug("user-provided host requests fd is %d", hostfd);
         std::stringstream request;
-        request << "INVOKE " << command << ":" << args << std::endl;
+       std::vector<as_value> fnargs;
+       fnargs.push_back(as_value(command));
+       fnargs.push_back(as_value(args));
+       request << ExternalInterface::makeInvoke("fsCommand", fnargs);
 
         std::string requestString = request.str();
         const char* cmd = requestString.c_str();

=== added file 'libcore/ExternalInterface.cpp'
--- a/libcore/ExternalInterface.cpp     1970-01-01 00:00:00 +0000
+++ b/libcore/ExternalInterface.cpp     2010-06-01 03:48:36 +0000
@@ -0,0 +1,725 @@
+// ExternalInterface.cpp:  ActionScript "ExternalInterface" support
+//
+//   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+//   Foundation, Inc
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include <map>
+#include <vector>
+#include <sstream>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <boost/algorithm/string/erase.hpp>
+#include <boost/shared_ptr.hpp>
+#include <algorithm>
+
+#include "StringPredicates.h"
+#include "Relay.h" // for inheritance
+#include "ExternalInterface.h"
+#include "as_object.h" // for inheritance
+#include "fn_call.h"
+#include "Global_as.h"
+#include "smart_ptr.h" // for boost intrusive_ptr
+#include "builtin_function.h" // need builtin_function
+#include "GnashException.h" // for ActionException
+#include "VM.h"
+#include "rc.h"
+#include "as_value.h"
+#include "as_object.h"
+#include "xml/XMLDocument_as.h"
+#include "Array_as.h"
+#include "namedStrings.h"
+#include "Global_as.h"
+#include "Globals.h"
+#include "PropertyList.h"
+#include "movie_root.h"
+#include "log.h"
+
+using namespace std;
+
+namespace gnash {
+
+/// Class used to serialize properties of an object to a buffer
+class PropsSerializer : public AbstractPropertyVisitor
+{
+
+public:
+    
+    PropsSerializer(VM& vm)
+        : _st(vm.getStringTable()),
+          _error(false)
+        { /* do nothing */}
+    
+    bool success() const { return !_error; }
+
+    bool accept(const ObjectURI& uri, const as_value& val) {
+        if (_error) return true;
+
+        const string_table::key key = getName(uri);
+
+        if (key == NSV::PROP_uuPROTOuu || key == NSV::PROP_CONSTRUCTOR) {
+            log_debug(" skip serialization of specially-named property %s",
+                      _st.value(key));
+            return true;
+        }
+
+        // write property name
+        const std::string& id = _st.value(key);
+
+//        log_debug(" serializing property %s", id);
+        
+        _xml << "<property id=\"" << id << "\">";
+        _xml << ExternalInterface::toXML(val);
+        _xml << "</property>";
+
+        _noprops.push_back(val);
+            
+        return true;
+    }
+
+    std::string getXML() { return _xml.str(); };
+    std::vector<as_value> getArgs() { return _noprops; };
+    
+private:
+    string_table&       _st;
+    mutable bool        _error;
+    std::stringstream   _xml;
+    std::vector<as_value>   _noprops;
+};
+
+#if 0
+class ExternalExecutor: public movie_root::AbstractExternalCallback {
+public:
+       void notify()
+       {
+           log_debug(_("external_callback()"));
+       }
+};
+#endif
+
+/// Convert an AS object to an XML string.
+std::string
+ExternalInterface::objectToXML(as_object *obj)
+{
+    // GNASH_REPORT_FUNCTION;
+    
+    std::stringstream ss;
+
+    if (obj == 0) {
+        //log_error("Need a valid AS Object!");
+        return ss.str();
+    }
+
+    VM& vm = getVM(*obj);
+    
+    ss << "<object>";
+    
+    // Get all the properties
+    PropsSerializer props(vm);
+    obj->visitProperties<IsEnumerable>(props);
+    if (!props.success()) {
+        log_error("Could not serialize object");
+        return false;
+    } else {
+        std::vector<as_value> properties = props.getArgs();
+    }
+    ss << "</object>";
+    
+    return ss.str();
+}
+
+/// Convert an AS object to an XML string.
+std::string
+ExternalInterface::arrayToXML(as_object *obj)
+{
+    // GNASH_REPORT_FUNCTION;
+    std::stringstream ss;
+    if (obj == 0) {
+        //log_error("Need a valid AS Object!");
+        return ss.str();
+    }
+
+    VM& vm = getVM(*obj);    
+    
+    ss << "<array>";
+    PropsSerializer props(vm);
+    obj->visitProperties<IsEnumerable>(props);
+    if (!props.success()) {
+        log_error("Could not serialize object");
+        return false;
+    }
+    ss << props.getXML();
+    
+    ss << "</array>";
+    
+    return ss.str();
+}
+
+/// Convert an AS object to an XML string.
+std::string
+ExternalInterface::toXML(const as_value &val)
+{
+    // GNASH_REPORT_FUNCTION;
+    
+    std::stringstream ss;
+    
+    if (val.is_string()) {
+        ss << "<string>" << val.to_string() << "</string>";
+    } else if (val.is_number()) {
+        ss << "<number>" << val.to_string() << "</number>";
+    } else if (val.is_undefined()) {
+        ss << "<undefined/>";
+    } else if (val.is_null()) {
+        ss << "<null/>";
+        // Exception isn't listed in any docs, but we'll use it for
+        // marshallExceptions.
+    } else if (val.is_exception()) {
+        ss << "<exception>" << val.to_string()<< "</exception>";
+    } else if (val.is_bool()) {
+        ss << (val.to_bool() ? "<true/>" : "<false/>");
+        // Function also isn't listed, but it's the only other type
+        // supported by as_value, so leaving it out doesn't seem right.
+    } else if (val.is_function()) {
+        ss << "<function>" << val.to_string() << "</function>";
+    } else if (val.is_object()) {
+//        as_object *obj = (as_object *)&val;
+//         ss << "<object></object>";
+    } else {
+        log_error("Can't convert unknown type %d", val.to_string());
+    }
+
+    return ss.str();
+}
+
+/// Convert an XML string to an AS object.
+as_value
+ExternalInterface::toAS(Global_as& /*gl*/, const std::string &xml)
+{
+    // GNASH_REPORT_FUNCTION;
+
+    std::string::size_type start = 0;
+    std::string::size_type end;
+    std::string tag;
+    as_value val;
+    
+    // Look for the ending > in the first part of the data for the tag
+    end = xml.find(">");
+    if (end != std::string::npos) {
+        end++;                  // go past the > character
+        tag = xml.substr(start, end);
+        // Look for the easy ones first
+        if (tag == "<null/>") {
+            val.set_null();
+        } else if (tag == "<void/>") {
+            val.set_null();     // FIXME: we need a void type in as_value
+        } else if (tag == "<true/>") {
+            val.set_bool(true);
+        } else if (tag == "<false/>") {
+            val.set_bool(false);
+        } else if (tag == "<number>") {
+            start = end;
+            end = xml.find("</number>");
+            std::string str = xml.substr(start, end-start);
+            if (str.find(".") != std::string::npos) {
+                double num = strtod(str.c_str(), NULL);
+                val.set_double(num);
+            } else {
+                int num = strtol(str.c_str(), NULL, 0);
+                val.set_double(num);
+            }
+        } else if (tag == "<string>") {
+            start = end;
+            end = xml.find("</string>");
+            std::string str = xml.substr(start, end-start);
+            int length = str.size();;
+            char *data = new char[length+1];
+            std::copy(str.begin(), str.end(), data);
+            data[length] = 0;  // terminate the new string or bad things happen
+            // When an NPVariant becomes a string object, it *does not* make a 
copy.
+            // Instead it stores the pointer (and length) we just allocated.
+            val.set_string(data);
+            // as_value copies the string, so we don't need data anymore
+            delete[] data;
+        } else if (tag == "<array>") {
+            start = end;
+            end = xml.find("</array");
+            std::string str = xml.substr(start, end-start);
+            log_unimpl("array processing for ExternalInterface");
+        } else if (tag == "<object>") {
+            start = end;
+            end = xml.find("</object");
+            std::string str = xml.substr(start, end-start);
+            log_unimpl("object processing for ExternalInterface");
+        }
+    }
+
+    return val;
+}
+
+as_value
+ExternalInterface::argumentsToXML(std::vector<as_value> &args)
+{
+    // GNASH_REPORT_FUNCTION;
+
+    std::vector<as_value>::iterator it;
+    std::stringstream ss;
+
+    ss << "<arguments>";
+    for (it=args.begin(); it != args.end(); it++) {
+        as_value val = *it;
+        ss << toXML(val);
+    }
+    ss << "</arguments>";
+    
+    return as_value(ss.str());
+}
+
+std::map<std::string, as_value>
+ExternalInterface::propertiesToAS(Global_as& gl, std::string &xml)
+{
+    // GNASH_REPORT_FUNCTION;
+    std::map<std::string, as_value> props;
+
+    std::string::size_type start = 0;
+    std::string::size_type end;
+
+    std::string id;
+    start = xml.find(" id=");
+    while (start != std::string::npos) {
+        // Extract the id from the property tag
+        start++;
+        end = xml.find(">", start) - 1;
+        id = xml.substr(start, end-start);
+        id.erase(0, 4);
+
+        // Extract the data
+        start = end + 2;
+        end = xml.find("</property>", start) ;
+        std::string data = xml.substr(start, end-start);
+        props[id] = toAS(gl, data);
+        start = xml.find(" id=", end);
+    }
+
+    return props;
+}
+
+as_value
+ExternalInterface::objectToAS(Global_as& /*gl*/, const std::string &/*xml*/)
+{
+    // GNASH_REPORT_FUNCTION;
+
+    return as_value();
+}
+
+boost::shared_ptr<ExternalInterface::invoke_t>
+ExternalInterface::ExternalEventCheck(int fd)
+{
+//    GNASH_REPORT_FUNCTION;
+    
+    boost::shared_ptr<ExternalInterface::invoke_t> error;
+
+    if (fd > 0) {
+        fd_set fdset;
+        FD_ZERO(&fdset);
+        FD_SET(fd, &fdset);
+        struct timeval tval;
+        tval.tv_sec  = 0;
+        tval.tv_usec = 100;
+        errno = 0;
+        int ret = ::select(fd+1, &fdset, NULL, NULL, &tval);
+        if (ret == 0) {
+//            log_debug ("The pipe for fd #%d timed out waiting to read", fd);
+            return error;
+        } else if (ret == 1) {
+            log_debug ("The pipe for fd #%d is ready", fd);
+        } else {
+            log_error("The pipe has this error: %s", strerror(errno));
+            return error;
+        }
+
+        int bytes = 0;
+#ifndef _WIN32
+        ioctl(fd, FIONREAD, &bytes);
+#else
+        ioctlSocket(fd, FIONREAD, &bytes);
+#endif
+        log_debug("There are %d bytes in the network buffer", bytes);
+
+        char *buf = new char[bytes+1];
+        // Since we know how bytes are in the network buffer, allocate
+        // some memory to read the data.
+        // terminate incase we want to treat the data like a string.
+        buf[bytes+1] = 0;
+        ret = ::read(fd, buf, bytes);
+        if (ret) {
+            return parseInvoke(buf);
+        }
+    }
+
+    return error;
+}
+
+// Parse the XML Invoke message, which looks like this:
+//
+// <invoke name="LoadMovie" returntype="xml">
+//      <arguments>
+//              <number>2</number>
+//              <string>bogus</string>
+//      </arguments>
+// </invoke>
+//
+boost::shared_ptr<ExternalInterface::invoke_t>
+ExternalInterface::parseInvoke(const std::string &xml)
+{
+    //    GNASH_REPORT_FUNCTION;
+
+    boost::shared_ptr<ExternalInterface::invoke_t> invoke;
+    if (xml.empty()) {
+        return invoke;
+    }
+    
+    invoke.reset(new ExternalInterface::invoke_t);
+    string::size_type start = 0;
+    string::size_type end;
+    string tag;
+
+    // Look for the ending > in the first part of the data for the tag
+    end = xml.find(">");
+    if (end != std::string::npos) {
+        end++;                  // go past the > character
+        tag = xml.substr(start, end);
+        // Look for the easy ones first
+        if (tag.substr(0, 7) == "<invoke") {
+            // extract the name of the method to invoke
+            start = tag.find("name=") + 5;
+            end   = tag.find(" ", start);
+            invoke->name  = tag.substr(start, end-start);
+            // Ignore any quote characters around the string
+            boost::erase_first(invoke->name, "\"");
+            boost::erase_last(invoke->name, "\"");
+
+            // extract the return type of the method
+            start = tag.find("returntype=") + 11;
+            end   = tag.find(">", start);
+            invoke->type  = tag.substr(start, end-start);
+            // Ignore any quote characters around the string
+            boost::erase_first(invoke->type, "\"");
+            boost::erase_last(invoke->type, "\"");
+
+            // extract the arguments to the method
+            start = xml.find("<arguments>");
+            end   = xml.find("</invoke");
+            tag   = xml.substr(start, end-start);
+            invoke->args = ExternalInterface::parseArguments(tag);
+        }
+    }
+
+    return invoke;
+}
+
+as_value
+ExternalInterface::parseXML(const std::string &xml)
+{
+    //    GNASH_REPORT_FUNCTION;
+
+    if (xml.empty()) {
+        return as_value();
+    }
+
+    std::string::size_type start = 0;
+    std::string::size_type end;
+    std::string tag;
+    as_value value;
+
+    // Look for the ending > in the first part of the data for the tag
+    end = xml.find(">");
+    if (end != std::string::npos) {
+        end++;                  // go past the > character
+        tag = xml.substr(start, end);
+        // Look for the easy ones first
+        if (tag == "<null/>") {
+            value.set_null();
+        } else if (tag == "<void/>") {
+            value.set_undefined();
+        } else if (tag == "<true/>") {
+            value.set_bool(true);
+        } else if (tag == "<false/>") {
+            value.set_bool(false);
+        } else if (tag == "<number>") {
+            start = end;
+            end = xml.find("</number>");
+            std::string str = xml.substr(start, end-start);
+            double num = strtod(str.c_str(), NULL);
+            value.set_double(num);
+        } else if (tag == "<string>") {
+            start = end;
+            end = xml.find("</string>");
+            std::string str = xml.substr(start, end-start);
+            value.set_string(str);
+        }
+    }
+
+    log_debug("Argument is: %s", value.to_string());
+    return value;
+}
+
+std::vector<as_value>
+ExternalInterface::parseArguments(const std::string &xml)
+{
+    // GNASH_REPORT_FUNCTION;
+
+    std::vector<as_value> args;
+    std::string::size_type start = 0;
+    std::string::size_type end;
+
+    std::string name;
+    std::string data = xml;
+    std::string tag = "<arguments>";
+    start = data.find(tag);
+    if (start != std::string::npos) {
+        data.erase(0, tag.size());
+    }
+    while (!data.empty()) {
+        // Extract the data
+        start = data.find("<", 1); // start past the opening <
+        end = data.find(">", start) + 1;
+        std::string sub = data.substr(0, end);
+        if (data == "</arguments>") {
+            break;
+        }
+        args.push_back(parseXML(sub));
+        data.erase(0, end);
+    }
+
+    return args;
+}
+
+// Create an Invoke message for the standalone Gnash
+std::string
+ExternalInterface::makeInvoke (const std::string &method,
+                               const std::vector<as_value> &args)
+{
+    std::stringstream ss;
+    std::vector<as_value>::const_iterator it;
+
+    ss << "<invoke name=\"" << method << "\" returntype=\"xml\">";
+    ss << "<arguments>";
+    for (it=args.begin(); it != args.end(); ++it) {
+        ss << ExternalInterface::toXML(*it);
+    }
+    
+    ss << "</arguments>";
+    ss << "</invoke>";
+
+    // Add a CR on the end so the output is more readable on the other
+    // end. XL should be ignoring the CR anyway.
+    ss << std::endl;
+    
+    return ss.str();
+}
+
+std::string
+ExternalInterface::makeNull ()
+{
+    std::stringstream ss;
+    
+    ss << "<null/>";
+    
+    return ss.str();
+}
+
+std::string
+ExternalInterface::makeTrue ()
+{
+    std::stringstream ss;
+
+    ss << "<true/>";
+    
+    return ss.str();
+}
+
+std::string
+ExternalInterface::makeFalse ()
+{
+    std::stringstream ss;
+    
+    ss << "<false/>";
+
+    return ss.str();
+}
+
+std::string
+ExternalInterface::makeString (const std::string &str)
+{
+    std::stringstream ss;
+
+    ss << "<string>" << str << "</string>";
+    
+    return ss.str();
+}
+
+
+std::string
+ExternalInterface::makeProperty (const std::string &id, double num)
+{
+    std::stringstream ss;
+    ss << num;
+    return makeProperty(id, ss.str());
+}
+
+std::string
+ExternalInterface::makeProperty (const std::string &id, int num)
+{
+    std::stringstream ss;
+    ss << num;
+    return makeProperty(id, ss.str());
+}
+
+std::string
+ExternalInterface::makeProperty (const std::string &id, const std::string 
&data)
+{
+    std::stringstream ss;
+
+    ss << "<property id=\"" << id << "\">" << data << "</property>";
+    
+    return ss.str();
+}
+
+std::string
+ExternalInterface::makeNumber (double num)
+{
+    std::stringstream ss;
+
+    ss << "<number>" << num << "</number>";
+    
+    return ss.str();
+}
+
+std::string
+ExternalInterface::makeNumber (int num)
+{
+    std::stringstream ss;
+
+    ss << "<number>" << num << "</number>";
+    
+    return ss.str();
+}
+
+std::string
+ExternalInterface::makeNumber (unsigned int num)
+{
+    std::stringstream ss;
+    
+    ss << "<number>" << num << "</number>";
+
+    return ss.str();
+}
+
+std::string
+ExternalInterface::makeArray (std::vector<std::string> &args)
+{
+    std::stringstream ss;
+    std::vector<std::string>::iterator it;
+    int index = 0;
+    
+    ss << "<array>";
+    for (it=args.begin(); it != args.end(); ++it) {
+        ss << "<property id=\"" << index << "\">" << *it << "</property>";
+        index++;
+    }
+    
+    ss << "</array>";
+    
+    return ss.str();
+}
+
+std::string
+ExternalInterface::makeObject (std::map<std::string, std::string> &args)
+{
+    std::stringstream ss;
+    std::map<std::string, std::string>::iterator it;
+
+    ss << "<object>";
+    for (it = args.begin(); it != args.end(); ++it) {
+        ss << "<property id=\"" << it->first << "\">" << it->second << 
"</property>";
+    }
+    ss << "</object>";
+    
+    return ss.str();
+}
+
+size_t
+ExternalInterface::writeBrowser(int fd, const std::string &data)
+{
+    if (fd > 0) {
+        return ::write(fd, data.c_str(), data.size());
+    }
+
+    return -1;
+}
+
+std::string
+ExternalInterface::readBrowser(int fd)
+{
+    std::string empty;
+    // Wait for some data from the player
+    int bytes = 0;
+    fd_set fdset;
+    FD_ZERO(&fdset);
+    FD_SET(fd, &fdset);
+    struct timeval tval;
+    tval.tv_sec = 10;
+    tval.tv_usec = 0;
+    // log_debug("Waiting for data... ");
+    if (select(fd+1, &fdset, NULL, NULL, &tval)) {
+        // log_debug("There is data in the network");
+#ifndef _WIN32
+        ioctl(fd, FIONREAD, &bytes);
+#else
+        ioctlSocket(fd, FIONREAD, &bytes);
+#endif
+    }  
+
+    // No data yet
+    if (bytes == 0) {
+        return empty;
+    }
+
+    log_debug("There are %d bytes in the network buffer", bytes);
+
+    std::string buf(bytes, '\0');
+
+    int ret = ::read(fd, &buf[0], bytes);
+    if (ret <= 0) {
+        return empty;
+    }
+
+    if (ret < bytes) {
+        buf.resize(ret);
+    }
+
+    std::cout << buf << std::endl;
+    
+    return buf;
+}
+
+} // end of gnash namespace
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:

=== added file 'libcore/ExternalInterface.h'
--- a/libcore/ExternalInterface.h       1970-01-01 00:00:00 +0000
+++ b/libcore/ExternalInterface.h       2010-06-01 02:34:36 +0000
@@ -0,0 +1,123 @@
+// ExternalInterface.h:  ActionScript "ExternalInterface" support
+//
+//   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
+//   Foundation, Inc
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#ifndef GNASH_ASOBJ_EXTERNALINTERFACE_H
+#define GNASH_ASOBJ_EXTERNALINTERFACE_H
+
+#include <string>
+#include <vector>
+#include <map>
+#include <boost/shared_ptr.hpp>
+
+namespace gnash {
+
+class as_object;
+class as_value;
+class ObjectURI;
+class Global_as;
+class movie_root;
+}
+
+namespace gnash {
+
+struct ExternalInterface
+{
+    typedef struct {
+        std::string name;
+        std::string type;
+        std::vector<as_value> args;
+    } invoke_t;
+
+    // Some of these appear to be undocumented helper functions of this class
+    // that while probably designed to be used internally, get used
+    // by ActionScript coders.
+
+    /// Convert an AS object to an XML string.
+    static std::string toXML(const as_value &obj);
+    
+    /// Convert an XML string to an AS value.
+    static as_value toAS(Global_as& as, const std::string &xml);
+
+    /// Convert an XML string of properties to a data structure.
+    static std::map<std::string, as_value> propertiesToAS(Global_as& gl,
+                                                   std::string &xml);
+    
+    static as_value argumentsToXML(std::vector<as_value> &args);
+//    as_value argumentsToAS();
+    
+    static std::string objectToXML(as_object *obj);
+    static as_value objectToAS(Global_as& gl, const std::string &xml);
+//  std::string objectToJS(as_object &obj);
+//  as_value toJS(const std::string &xml);;
+    
+    static std::string arrayToXML(as_object *obj);
+
+//  static std::string arrayToJS();
+//  static as_value arrayToAS();
+
+//  static std::string jsQuoteString();
+//  static void initJS();
+//  static bool evalJS();
+    
+//  static callOut"));
+//  static callIn"));
+
+    static std::string escapeXML(as_object &obj);
+    static std::string unescapeXML(as_object &obj);
+
+    static as_value parseXML(const std::string &xml);
+    static std::vector<as_value> parseArguments(const std::string &xml);
+
+    // Parse the XML Invoke message.
+    static boost::shared_ptr<invoke_t> parseInvoke(const std::string &str);
+    // Check for data from the browser and parse it.
+    static boost::shared_ptr<invoke_t> ExternalEventCheck(int fd);
+
+    // These methods are for constructing Invoke messages.
+    // Create an Invoke message for the standalone Gnash
+    static std::string makeInvoke (const std::string &method,
+                                   const std::vector<as_value> &args);
+    
+    static std::string makeNull ();
+    static std::string makeTrue ();
+    static std::string makeFalse ();
+    static std::string makeString (const std::string &str);
+    static std::string makeProperty (const std::string &str, const std::string 
&data);
+    static std::string makeProperty (const std::string &str, double num);
+    static std::string makeProperty (const std::string &str, int num);
+    static std::string makeNumber (double num);
+    static std::string makeNumber (int num);
+    static std::string makeNumber (unsigned int num);
+    static std::string makeArray (std::vector<std::string> &args);
+    static std::string makeObject (std::map<std::string, std::string> &args);
+
+    static size_t writeBrowser(int fd, const std::string &xml);
+    static std::string readBrowser(int fd);
+};
+
+} // end of gnash namespace
+
+// __GNASH_ASOBJ_EXTERNALINTERFACE_H__
+#endif
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:

=== modified file 'libcore/Makefile.am'
--- a/libcore/Makefile.am       2010-03-24 23:11:52 +0000
+++ b/libcore/Makefile.am       2010-05-29 16:06:49 +0000
@@ -85,6 +85,7 @@
         GradientBevelFilter.cpp \
         parser/filter_factory.cpp \
        InteractiveObject.cpp \
+       ExternalInterface.cpp \
        SWFMatrix.cpp \
        SWFMovie.cpp \
        movie_root.cpp \
@@ -176,6 +177,7 @@
        SWFMovie.h \
        SWFStream.h \
        MovieLibrary.h \
+       ExternalInterface.h \
        swf/tag_loaders.h \
        swf/DefaultTagLoaders.h \
        swf/VideoFrameTag.h \

=== modified file 'libcore/asobj/flash/external/ExternalInterface_as.cpp'
--- a/libcore/asobj/flash/external/ExternalInterface_as.cpp     2010-05-25 
19:03:26 +0000
+++ b/libcore/asobj/flash/external/ExternalInterface_as.cpp     2010-06-02 
14:18:20 +0000
@@ -26,9 +26,9 @@
 #include <boost/algorithm/string/erase.hpp>
 #include <algorithm>
 
+#include "ExternalInterface.h"
+#include "ExternalInterface_as.h"
 #include "StringPredicates.h"
-#include "Relay.h" // for inheritance
-#include "ExternalInterface_as.h"
 #include "as_object.h" // for inheritance
 #include "fn_call.h"
 #include "Global_as.h"
@@ -116,7 +116,7 @@
 //        log_debug(" serializing property %s", id);
         
         _xml << "<property id=\"" << id << "\">";
-        _xml << ExternalInterface_as::toXML(val);
+        _xml << ExternalInterface::toXML(val);
         _xml << "</property>";
 
         _noprops.push_back(val);
@@ -140,6 +140,7 @@
 //    GNASH_REPORT_FUNCTION;
 
     where.init_destructive_property(uri, externalInterfaceConstructor, 0);
+
 }
 
 namespace {
@@ -147,7 +148,7 @@
 void
 attachExternalInterfaceStaticInterface(as_object& o)
 {    
-    GNASH_REPORT_FUNCTION;
+    // GNASH_REPORT_FUNCTION;
     
     const int swf7Flags = PropFlags::dontDelete | PropFlags::dontEnum
         | PropFlags::readOnly | PropFlags::onlySWF7Up;
@@ -215,28 +216,24 @@
 as_value
 externalinterface_addCallback(const fn_call& fn)
 {
-    GNASH_REPORT_FUNCTION;
+    // GNASH_REPORT_FUNCTION;
 
     movie_root& mr = getRoot(fn);
+
     if (mr.getControlFD() <= 0) {
         log_debug("ExternalInterface not accessible when running standalone.");
         return as_value(false);
     }
 
-    ExternalInterface_as* ptr = ensure<ThisIsNative<ExternalInterface_as> 
>(fn);
-
-    // MovieClip *mc = mr.getLevel(1);
-    // string_table& st = getStringTable(fn);    
-
     if (fn.nargs > 1) {
         const as_value& name_as = fn.arg(0);
         std::string name = name_as.to_string();
         boost::intrusive_ptr<as_object> asCallback;
-        if (fn.arg(1).is_object()) {
-            asCallback = (fn.arg(1).to_object(getGlobal(fn)));
-            ptr->addCallback(name, asCallback.get());
+        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());
         }
-        ptr->addRootCallback(mr);
         return as_value(true);
     }
     
@@ -246,22 +243,21 @@
 as_value
 externalinterface_call(const fn_call& fn)
 {
-    GNASH_REPORT_FUNCTION;
-
-    ExternalInterface_as* ptr = ensure<ThisIsNative<ExternalInterface_as> 
>(fn);
-    
+    // GNASH_REPORT_FUNCTION;
+
+    movie_root& mr = getRoot(fn);
+
     if (fn.nargs >= 2) {
         const as_value& methodName_as = fn.arg(0);
-        std::string methodName = methodName_as.to_string();
-        // boost::intrusive_ptr<as_object> asCallback;
-        // if (fn.arg(1).is_object()) {
-        //     asCallback = (fn.arg(1).to_object(getGlobal(fn)));
-        // }
-        
-//      const std::vector<as_value>& args = fn.getArgs();
-//      as_object *asCallback = ptr.getCallback(methodName);
+        const std::string methodName = methodName_as.to_string();
+        const std::vector<as_value>& args = fn.getArgs();
         log_debug("Calling External method \"%s\"", methodName);
-//      ptr.call(asCallback.get(), methodName, args, 2);
+        std::string result = mr.callExternalCallback(methodName, args);
+        if (result.empty()) {
+            return as_value();
+        } else {
+            return as_value(result);
+        }
     }
     
     return as_value();
@@ -321,13 +317,11 @@
 {
 //    GNASH_REPORT_FUNCTION;
     
-    ExternalInterface_as* ptr = ensure<ThisIsNative<ExternalInterface_as> 
>(fn);
-
-    // No, don't pass exceptions up to the browser
+    movie_root& m = getRoot(fn);
     if (fn.nargs) {
-        ptr->setMarshallExceptions(fn.arg(0).to_bool());
+        m.setMarshallExceptions(fn.arg(0).to_bool());
     } else {
-        return as_value(false);
+        return as_value(m.getMarshallExceptions());
     }
     
     return as_value(true);
@@ -336,7 +330,7 @@
 as_value
 externalinterface_objectID(const fn_call& fn)
 {
-    GNASH_REPORT_FUNCTION;
+    // GNASH_REPORT_FUNCTION;
 
     movie_root& mr = getRoot(fn);
     MovieClip *mc = mr.getLevel(0);
@@ -414,7 +408,7 @@
                 args.push_back(fn.arg(i));
             }
         }
-        return ExternalInterface_as::argumentsToXML(args);
+        return ExternalInterface::argumentsToXML(args);
     }
     
     return as_value();
@@ -424,12 +418,13 @@
 externalinterface_uArgumentsToAS(const fn_call& /*fn*/)
 {
     // GNASH_REPORT_FUNCTION;
-    
-    // std::string str(fn.arg(0).to_string());
-    // ExternalInterface_as &ptr = (ExternalInterface_as &)(fn);
-    // if (fn.nargs > 0) {
-    //     return ptr->argumentsToAS();
-    // }
+    LOG_ONCE( log_unimpl (__FUNCTION__) );
+#if 0
+    std::string str(fn.arg(0).to_string());
+    if (fn.nargs > 0) {
+        return ExternalInterface::argumentsToAS();
+    }
+#endif
 
     return as_value();
 }
@@ -437,7 +432,7 @@
 as_value
 externalinterface_uAddCallback(const fn_call& /*fn*/)
 {
-    GNASH_REPORT_FUNCTION;
+    // GNASH_REPORT_FUNCTION;
     
     LOG_ONCE( log_unimpl (__FUNCTION__) );
     return as_value();
@@ -466,7 +461,7 @@
     
     if (fn.nargs == 1) {
         as_object *obj = fn.arg(0).to_object(getGlobal(fn));
-        std::string str = ExternalInterface_as::arrayToXML(obj);
+        std::string str = ExternalInterface::arrayToXML(obj);
         return as_value(str);
     }
     
@@ -526,7 +521,7 @@
 {
 //    GNASH_REPORT_FUNCTION;
     if (fn.nargs == 1) {
-        return ExternalInterface_as::objectToAS(getGlobal(fn), 
fn.arg(0).to_string());
+        return ExternalInterface::objectToAS(getGlobal(fn), 
fn.arg(0).to_string());
     }
     
     return as_value();
@@ -547,7 +542,7 @@
     if (fn.nargs == 1) {
         if (!fn.arg(0).is_null() && !fn.arg(0).is_undefined()) {
             as_object *obj = fn.arg(0).to_object(getGlobal(fn));
-            std::string str = ExternalInterface_as::objectToXML(obj);
+            std::string str = ExternalInterface::objectToXML(obj);
             return as_value(str);
         } else {
             return as_value("<object></object>");
@@ -571,7 +566,7 @@
 
     if (fn.nargs == 1) {
         as_value val = fn.arg(0);
-        std::string str = ExternalInterface_as::toXML(val);
+        std::string str = ExternalInterface::toXML(val);
         return as_value(str);
     }
     
@@ -584,7 +579,7 @@
 //    GNASH_REPORT_FUNCTION;
     
     if (fn.nargs == 1) {
-        as_value val = ExternalInterface_as::toAS(getGlobal(fn), 
fn.arg(0).to_string());
+        as_value val = ExternalInterface::toAS(getGlobal(fn), 
fn.arg(0).to_string());
         return val;
     }
     
@@ -621,542 +616,6 @@
 
 } // end of anonymous namespace used for callbacks
 
-// namespace gnash {
-
-ExternalInterface_as::ExternalInterface_as(as_object* /*owner*/)
-    :  _fd(-1),
-       _marshallExceptions(false)
-{
-    GNASH_REPORT_FUNCTION;
-}
-
-ExternalInterface_as::~ExternalInterface_as()
-{
-//    GNASH_REPORT_FUNCTION;
-//    LOG_ONCE( log_unimpl (__FUNCTION__) );
-}
-
-// The ActionScript 3.0 version of this method does not accept the
-// instance parameter. The method parameter is replaced by a closure
-// parameter, which can take a reference to a function, a class
-// method, or a method of a particular class instance. In addition, if
-// the calling code cannot access the closure reference for security
-// reasons, a SecurityError exception is thrown.
-bool
-ExternalInterface_as::addCallback(const std::string &name, as_object *method)
-{
-    log_debug(__PRETTY_FUNCTION__);
-
-    if (method) {
-        _methods[name] = method;
-    }
-
-    return true;
-}
-
-bool
-ExternalInterface_as::addRootCallback(movie_root &mr)
-{
-    log_debug(__PRETTY_FUNCTION__);
-
-    //_root = &mr;
-    
-#if 0
-    if (_methods.size() == 1) {
-        // Register callback so we can send the data on the next advance.
-        mr.registerExternalCallback(&externalUpdate);
-    }
-#endif
-    
-    return true;
-}
-
-bool
-ExternalInterface_as::call(as_object */*asCallback*/, const std::string& name,
-                           const std::vector<as_value>& /*args*/, size_t 
/*firstArg*/)
-{
-    GNASH_REPORT_FUNCTION;
-
-    // log_debug("Calling External method \"%s\"", name);
-
-    // as_object *method = getCallback(name);
-
-    
-    // call(asCallback, name, args, firstArg);
-
-    // startAdvanceTimer();
-    
-    return false;
-}
-
-/// Convert an AS object to an XML string.
-std::string
-ExternalInterface_as::objectToXML(as_object *obj)
-{
-    // GNASH_REPORT_FUNCTION;
-    
-    std::stringstream ss;
-
-    if (obj == 0) {
-        //log_error("Need a valid AS Object!");
-        return ss.str();
-    }
-
-    VM& vm = getVM(*obj);
-    
-    ss << "<object>";
-    
-    // Get all the properties
-    PropsSerializer props(vm);
-    obj->visitProperties<IsEnumerable>(props);
-    if (!props.success()) {
-        log_error("Could not serialize object");
-        return false;
-    } else {
-        std::vector<as_value> properties = props.getArgs();
-    }
-    ss << "</object>";
-    
-    return ss.str();
-}
-
-/// Convert an AS object to an XML string.
-std::string
-ExternalInterface_as::arrayToXML(as_object *obj)
-{
-    // GNASH_REPORT_FUNCTION;
-    std::stringstream ss;
-    if (obj == 0) {
-        //log_error("Need a valid AS Object!");
-        return ss.str();
-    }
-
-    VM& vm = getVM(*obj);    
-    
-    ss << "<array>";
-    PropsSerializer props(vm);
-    obj->visitProperties<IsEnumerable>(props);
-    if (!props.success()) {
-        log_error("Could not serialize object");
-        return false;
-    }
-    ss << props.getXML();
-    
-    ss << "</array>";
-    
-    return ss.str();
-}
-
-/// Convert an AS object to an XML string.
-std::string
-ExternalInterface_as::toXML(const as_value &val)
-{
-    // GNASH_REPORT_FUNCTION;
-    
-    std::stringstream ss;
-    
-    if (val.is_string()) {
-        ss << "<string>" << val.to_string() << "</string>";
-    } else if (val.is_number()) {
-        ss << "<number>" << val.to_string() << "</number>";
-    } else if (val.is_undefined()) {
-        ss << "<undefined/>";
-    } else if (val.is_null()) {
-        ss << "<null/>";
-        // Exception isn't listed in any docs, but we'll use it for
-        // marshallExceptions.
-    } else if (val.is_exception()) {
-        ss << "<exception>" << val.to_string()<< "</exception>";
-    } else if (val.is_bool()) {
-        ss << (val.to_bool() ? "<true/>" : "<false/>");
-        // Function also isn't listed, but it's the only other type
-        // supported by as_value, so leaving it out doesn't seem right.
-    } else if (val.is_function()) {
-        ss << "<function>" << val.to_string() << "</function>";
-    } else if (val.is_object()) {
-//        as_object *obj = (as_object *)&val;
-//         ss << "<object></object>";
-    } else {
-        log_error("Can't convert unknown type %d", val.to_string());
-    }
-
-    return ss.str();
-}
-
-/// Convert an XML string to an AS object.
-as_value
-ExternalInterface_as::toAS(Global_as& /*gl*/, const std::string &xml)
-{
-    // GNASH_REPORT_FUNCTION;
-
-    std::string::size_type start = 0;
-    std::string::size_type end;
-    std::string tag;
-    as_value val;
-    
-    // Look for the ending > in the first part of the data for the tag
-    end = xml.find(">");
-    if (end != std::string::npos) {
-        end++;                  // go past the > character
-        tag = xml.substr(start, end);
-        // Look for the easy ones first
-        if (tag == "<null/>") {
-            val.set_null();
-        } else if (tag == "<void/>") {
-            val.set_null();     // FIXME: we need a void type in as_value
-        } else if (tag == "<true/>") {
-            val.set_bool(true);
-        } else if (tag == "<false/>") {
-            val.set_bool(false);
-        } else if (tag == "<number>") {
-            start = end;
-            end = xml.find("</number>");
-            std::string str = xml.substr(start, end-start);
-            if (str.find(".") != std::string::npos) {
-                double num = strtod(str.c_str(), NULL);
-                val.set_double(num);
-            } else {
-                int num = strtol(str.c_str(), NULL, 0);
-                val.set_double(num);
-            }
-        } else if (tag == "<string>") {
-            start = end;
-            end = xml.find("</string>");
-            std::string str = xml.substr(start, end-start);
-            int length = str.size();;
-            char *data = new char[length+1];
-            std::copy(str.begin(), str.end(), data);
-            data[length] = 0;  // terminate the new string or bad things happen
-            // When an NPVariant becomes a string object, it *does not* make a 
copy.
-            // Instead it stores the pointer (and length) we just allocated.
-            val.set_string(data);
-        } else if (tag == "<array>") {
-            start = end;
-            end = xml.find("</array");
-            std::string str = xml.substr(start, end-start);
-            // std::map<std::string, NPVariant *> props = parseProperties(str);
-            // std::map<std::string, NPVariant *>::iterator it;
-            // for (it=props.begin(); it != props.end(); ++it) {
-            //     // NPIdentifier id = 
NPN_GetStringIdentifier(it->first.c_str());
-            //     // NPVariant *value = it->second;
-            // }
-            // as_object *obj = new as_object(gl);
-        } else if (tag == "<object>") {
-            start = end;
-            end = xml.find("</object");
-            std::string str = xml.substr(start, end-start);
-            // std::map<std::string, as_value> props = parseProperties(str);
-            // std::map<std::string, NPVariant *>::iterator it;
-            // for (it=props.begin(); it != props.end(); ++it) {
-            //     // NPIdentifier id = 
NPN_GetStringIdentifier(it->first.c_str());
-            //     // NPVariant *value = it->second;
-            // }
-            // as_object *obj = val.to_object();
-            // val.set_as_object(obj); 
-            // as_object *obj = new as_object(gl);
-        }
-    }
-
-    return val;
-}
-
-as_value
-ExternalInterface_as::argumentsToXML(std::vector<as_value> &args)
-{
-    // GNASH_REPORT_FUNCTION;
-
-    std::vector<as_value>::iterator it;
-    std::stringstream ss;
-
-    ss << "<arguments>";
-    for (it=args.begin(); it != args.end(); it++) {
-        as_value val = *it;
-        ss << toXML(val);
-    }
-    ss << "</arguments>";
-    
-    return as_value(ss.str());
-}
-
-std::map<std::string, as_value>
-ExternalInterface_as::propertiesToAS(Global_as& gl, std::string &xml)
-{
-    // GNASH_REPORT_FUNCTION;
-    std::map<std::string, as_value> props;
-
-    std::string::size_type start = 0;
-    std::string::size_type end;
-
-    std::string id;
-    start = xml.find(" id=");
-    while (start != std::string::npos) {
-        // Extract the id from the property tag
-        start++;
-        end = xml.find(">", start) - 1;
-        id = xml.substr(start, end-start);
-        id.erase(0, 4);
-
-        // Extract the data
-        start = end + 2;
-        end = xml.find("</property>", start) ;
-        std::string data = xml.substr(start, end-start);
-        props[id] = toAS(gl, data);
-        start = xml.find(" id=", end);
-    }
-
-    return props;
-}
-
-as_value
-ExternalInterface_as::objectToAS(Global_as& /*gl*/, const std::string &/*xml*/)
-{
-    // GNASH_REPORT_FUNCTION;
-
-    return as_value();
-}
-
-#if 0
-ExternalInterface_as &
-ExternalInterface_as::Instance()
-{
-    // TODO: this is a temporary hack to allow ExternalInterface to work as an
-    // ActiveRelay without changing the way ActiveRelay works.
-    // ExternalInterface shouldn't use ActiveRelay, neither should it need
-    // any of these singletons or statics.
-    static as_object* o = 0;
-    if (!o) {
-        o = new as_object(*VM::get().getGlobal());
-        VM::get().addStatic(o);
-    }
-    static ExternalInterface_as ei(o);
-    
-    return ei;
-}
-#endif
-
-#if 0
-void
-ExternalInterface_as::setReachable() const
-{
-    log_debug(__PRETTY_FUNCTION__);
-
-    std::map<std::string, as_object *>::const_iterator it;
-    for (it=_methods.begin(); it != _methods.end(); ++it) {
-        it->second->setReachable();
-    }
-}
-
-bool
-ExternalInterface_as::advance()
-{
-    log_debug(__PRETTY_FUNCTION__);
-    
-    return false;
-}
-#endif
-
-as_object *
-ExternalInterface_as::getCallback(const std::string &name)
-{
-    log_debug(__PRETTY_FUNCTION__);
-    
-    std::map<std::string, as_object *>::const_iterator it;
-    it = _methods.find(name);
-    if (it != _methods.end()) {
-        log_debug("Found External Method \"%s\"", it->first);
-        return it->second;
-    }
-
-    return 0;
-}
-
-void
-ExternalInterface_as::update()
-{
-    log_debug(__PRETTY_FUNCTION__);
-    
-    if (_fd > 0) {
-        fd_set fdset;
-        FD_ZERO(&fdset);
-        FD_SET(_fd, &fdset);
-        struct timeval tval;
-        tval.tv_sec  = 0;
-        tval.tv_usec = 100;
-        errno = 0;
-        int ret = ::select(_fd+1, &fdset, NULL, NULL, &tval);
-        if (ret == 0) {
-//            log_debug ("The pipe for fd #%d timed out waiting to read", _fd);
-            return;
-        } else if (ret == 1) {
-            log_debug ("The pipe for fd #%d is ready", _fd);
-        } else {
-            log_error("The pipe has this error: %s", strerror(errno));
-            return;
-        }
-
-        int bytes = 0;
-#ifndef _WIN32
-        ioctl(_fd, FIONREAD, &bytes);
-#else
-        ioctlSocket(_fd, FIONREAD, &bytes);
-#endif
-        log_debug("There are %d bytes in the network buffer", bytes);
-
-        char *buf = new char[bytes+1];
-        // Since we know how bytes are in the network buffer, allocate
-        // some memory to read the data.
-        // terminate incase we want to treat the data like a string.
-        buf[bytes+1] = 0;
-        ret = ::read(_fd, buf, bytes);
-        if (ret) {
-            processInvoke(buf);
-        }
-    }
-}
-
-// Parse the XML Invoke message, which looks like this:
-//
-// <invoke name="LoadMovie" returntype="xml">
-//      <arguments>
-//              <number>2</number>
-//              <string>bogus</string>
-//      </arguments>
-// </invoke>
-//
-void
-ExternalInterface_as::processInvoke(const std::string &xml)
-{
-    GNASH_REPORT_FUNCTION;
-
-    if (xml.empty()) {
-        return;
-    }
-    
-    std::vector<as_value> args;
-    string::size_type start = 0;
-    string::size_type end;
-    string tag;
-    string name;
-
-    // Look for the ending > in the first part of the data for the tag
-    end = xml.find(">");
-    if (end != std::string::npos) {
-        end++;                  // go past the > character
-        tag = xml.substr(start, end);
-        // Look for the easy ones first
-        if (tag.substr(0, 7) == "<invoke") {
-            // extract the name of the method to invoke
-            start = tag.find("name=") + 5;
-            end   = tag.find(" ", start);
-            name  = tag.substr(start, end-start);
-            // Ignore any quote characters around the string
-            boost::erase_first(name, "\"");
-            boost::erase_last(name, "\"");
-
-#if 0
-            // extract the return type of the method
-            start = tag.find("returntype=") + 11;
-            end   = tag.find(">", start);
-            invoke->type  = tag.substr(start, end-start);
-            // Ignore any quote characters around the string
-            boost::erase_first(invoke->type, "\"");
-            boost::erase_last(invoke->type, "\"");
-#endif
-            // extract the arguments to the method
-            start = xml.find("<arguments>");
-            end   = xml.find("</invoke");
-            tag   = xml.substr(start, end-start);
-            args = parseArguments(tag);
-        }
-    }
-
-    // call(as_object* callback, const std::string& name,
-    std::map<std::string, as_object *>::const_iterator it;
-    for (it=_methods.begin(); it != _methods.end(); it++) {
-        log_debug("Method name %s", it->first);
-        if (name == it->first) {
-            // call(it->second, args, 0);
-        }
-    }    
-}
-
-as_value
-ExternalInterface_as::parseXML(const std::string &xml)
-{
-    GNASH_REPORT_FUNCTION;
-
-    if (xml.empty()) {
-        return as_value();
-    }
-
-    std::string::size_type start = 0;
-    std::string::size_type end;
-    std::string tag;
-    as_value value;
-
-    // Look for the ending > in the first part of the data for the tag
-    end = xml.find(">");
-    if (end != std::string::npos) {
-        end++;                  // go past the > character
-        tag = xml.substr(start, end);
-        // Look for the easy ones first
-        if (tag == "<null/>") {
-            value.set_null();
-        } else if (tag == "<void/>") {
-            value.set_undefined();
-        } else if (tag == "<true/>") {
-            value.set_bool(true);
-        } else if (tag == "<false/>") {
-            value.set_bool(false);
-        } else if (tag == "<number>") {
-            start = end;
-            end = xml.find("</number>");
-            std::string str = xml.substr(start, end-start);
-            double num = strtod(str.c_str(), NULL);
-            value.set_double(num);
-        } else if (tag == "<string>") {
-            start = end;
-            end = xml.find("</string>");
-            std::string str = xml.substr(start, end-start);
-            value.set_string(str);
-        }
-    }
-
-    log_debug("Argument is: %s", value.to_string());
-    return value;
-}
-
-std::vector<as_value>
-ExternalInterface_as::parseArguments(const std::string &xml)
-{
-    GNASH_REPORT_FUNCTION;
-
-    std::vector<as_value> args;
-    std::string::size_type start = 0;
-    std::string::size_type end;
-
-    std::string name;
-    std::string data = xml;
-    std::string tag = "<arguments>";
-    start = data.find(tag);
-    if (start != std::string::npos) {
-        data.erase(0, tag.size());
-    }
-    while (!data.empty()) {
-        // Extract the data
-        start = data.find("<", 1); // start past the opening <
-        end = data.find(">", start) + 1;
-        std::string sub = data.substr(0, end);
-        if (data == "</arguments>") {
-            break;
-        }
-        args.push_back(parseXML(sub));
-        data.erase(0, end);
-    }
-
-    return args;
-}
-
 } // end of gnash namespace
 
 // local Variables:

=== modified file 'libcore/asobj/flash/external/ExternalInterface_as.h'
--- a/libcore/asobj/flash/external/ExternalInterface_as.h       2010-05-25 
00:25:45 +0000
+++ b/libcore/asobj/flash/external/ExternalInterface_as.h       2010-06-01 
03:49:45 +0000
@@ -41,80 +41,10 @@
 public:
     ExternalInterface_as(as_object* owner);
     ~ExternalInterface_as();
-
-    // This is a flag that specifies whether exceptions in ActionScript
-    // should be propogated to JavaScript in the browser.
-    void setMarshallExceptions(bool x) { _marshallExceptions = x; };
-    bool getMarshallExceptions() { return _marshallExceptions; };
-    
-    /// Add an ActionScript function as a callback by JavaScript
-    // in the browser.
-    bool addCallback(const std::string &name, as_object *method);
-
-    ///
-    bool addRootCallback(movie_root &mr);    
-
-    // These appear to be undocumented helper functions of this class
-    // that while propably designed to be used internally, get used
-    // by ActionScript coders.
-
-    /// Convert an AS object to an XML string.
-    static std::string toXML(const as_value &obj);
-    
-    /// Convert an XML string to an AS value.
-    static as_value toAS(Global_as& as, const std::string &xml);
-
-    /// Convert an XML string of properties to a data structure.
-    static std::map<std::string, as_value> propertiesToAS(Global_as& gl,
-                                                   std::string &xml);
-    
-    static as_value argumentsToXML(std::vector<as_value> &args);
-//    as_value argumentsToAS();
-    
-    static std::string objectToXML(as_object *obj);
-    static as_value objectToAS(Global_as& gl, const std::string &xml);
-//  std::string objectToJS(as_object &obj);
-//  as_value toJS(const std::string &xml);;
-    
-    static std::string arrayToXML(as_object *obj);
-
-//  std::string arrayToJS();
-//  as_value arrayToAS();
-
-//  std::string jsQuoteString();
-//  void initJS();
-//  bool evalJS();
-    
-//  callOut"));
-//  callIn"));
-
-    static std::string escapeXML(as_object &obj);
-    static std::string unescapeXML(as_object &obj);
-
-    /// Call a callback if it's registered already.
-    bool call(as_object* callback, const std::string& name,
-              const std::vector<as_value>& args, size_t firstArg);
-    
-    // These are our implementations of ActiveRelay methods.
-    // virtual bool advance() = 0;
-    // virtual void setReachable() const = 0;
-    
-    virtual void update();
-
-    // Parse the XML Invoke message.
-    void processInvoke(const std::string &str);
-
-    void setFD(int x) { _fd = x; };
-
-    as_object *getCallback(const std::string &name);
-
-    as_value parseXML(const std::string &xml);
-    std::vector<as_value> parseArguments(const std::string &xml);
     
 private:
     int                 _fd;
     std::map<std::string, as_object *> _methods;
-    bool               _marshallExceptions;
 };
 
 /// Initialize the global ExternalInterface class

=== modified file 'libcore/movie_root.cpp'
--- a/libcore/movie_root.cpp    2010-05-25 19:03:26 +0000
+++ b/libcore/movie_root.cpp    2010-06-02 14:18:20 +0000
@@ -40,11 +40,16 @@
 #include "IOChannel.h"
 #include "RunResources.h"
 #include "Renderer.h"
+#include "ExternalInterface.h"
 
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <boost/algorithm/string/erase.hpp>
 #include <boost/algorithm/string/replace.hpp>
 #include <utility>
 #include <iostream>
 #include <string>
+#include <sstream>
 #include <map>
 #include <bitset>
 #include <typeinfo>
@@ -136,6 +141,7 @@
     _quality(QUALITY_HIGH),
     _alignMode(0),
     _allowScriptAccess(SCRIPT_ACCESS_SAME_DOMAIN),
+    _marshallExceptions(false),
     _showMenu(true),
     _scaleMode(SCALEMODE_SHOWALL),
     _displayState(DISPLAYSTATE_NORMAL),
@@ -612,7 +618,7 @@
 
     processActionQueue();
 
-    return false; // should return true if needs update ...
+    return false; // should return true if needs updatee ...
 }
 
 
@@ -1574,9 +1580,109 @@
                 std::mem_fun_ref(&movie_root::LoadCallback::processLoad));
     }
 
+    // _controlfd is set when running as a child process of a hosting
+    // application. If it is set, we have to check the socket connection
+    // for XML messages.
+    if (_controlfd) {
+       boost::shared_ptr<ExternalInterface::invoke_t> invoke = 
+           ExternalInterface::ExternalEventCheck(_controlfd);
+       if (invoke) {
+           if (processInvoke(invoke.get()) == false) {
+               if (!invoke->name.empty()) {
+                   log_error("Couldn't process ExternalInterface Call %s",
+                             invoke->name);
+               }
+           }
+       }       
+    }
+    
     processActionQueue();
 }
 
+bool
+movie_root::processInvoke(ExternalInterface::invoke_t *invoke)
+{
+    GNASH_REPORT_FUNCTION;
+
+    if (invoke == 0) {
+       return false;
+    }
+    if (invoke->name.empty()) {
+       return false;
+    }
+
+    log_debug("Processing %s call from the Browser.", invoke->name);
+
+    std::stringstream ss;
+
+    // These are the default methods used by ExternalInterface
+    if (invoke->name == "Quit") {
+       // The browser is telling us to quit.
+       // FIXME: This is probably not the right way to exit, but it
+       // beats turning into a zombie and eating cpu cycles.
+       exit(0);
+    } else if (invoke->name == "SetVariable") {
+       // SetVariable doesn't send a response
+    } else if (invoke->name == "GetVariable") {
+       // GetVariable sends the value of the variable
+       as_value val("Hello World");
+       // FIXME: need to use a real value
+       ss << ExternalInterface::toXML(val);
+    } else if (invoke->name == "GotoFrame") {
+       // GotoFrame doesn't send a response
+    } else if (invoke->name == "IsPlaying") {
+       // IsPlaying sends true or false
+       as_value val(true);
+       // FIXME: need to use a real value
+       ss << ExternalInterface::toXML(val);    
+    } else if (invoke->name == "LoadMovie") {
+       // LoadMovie doesn't send a response
+    } else if (invoke->name == "Pan") {
+       // Pan doesn't send a response
+    } else if (invoke->name == "PercentLoaded") {
+       // PercentLoaded sends the percentage
+       as_value val(100);
+       // FIXME: need to use a real value
+       ss << ExternalInterface::toXML(val);    
+    } else if (invoke->name == "Play") {
+       // Play doesn't send a response
+    } else if (invoke->name == "Rewind") {
+       // Rewind doesn't send a response
+    } else if (invoke->name == "SetZoomRect") {
+       // SetZoomRect doesn't send a response
+    } else if (invoke->name == "StopPlay") {
+       // StopPlay doesn't send a response
+    } else if (invoke->name == "Zoom") {
+       // Zoom doesn't send a response
+    } else if (invoke->name == "TotalFrames") {
+       // TotalFrames sends the number of frames in the movie
+       as_value val(100);
+       // 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);
+       }
+    }
+
+    if (!ss.str().empty()) {
+       if (_hostfd) {
+           log_debug(_("Attempt to write response to ExternalInterface 
requests fd %d"), _hostfd);
+           int ret = write(_hostfd, ss.str().c_str(), ss.str().size());
+           if (ret == -1) {
+               log_error(_("Could not write to user-provided host requests "
+                           "fd %d: %s"), _hostfd, std::strerror(errno));
+           }
+       }
+    } else {
+       log_debug("No response needed for %s request", invoke->name);
+    }
+
+    return true;
+}
+
 void
 movie_root::executeTimers()
 {
@@ -1740,6 +1846,33 @@
     return 0;
 }
 
+// This calls a JavaScript method in the web page
+std::string
+movie_root::callExternalCallback(const std::string &name, 
+                                const std::vector<as_value> &fnargs)
+{
+    std::string empty;
+
+    if (_hostfd) {
+       return empty;
+    }
+
+    std::vector<std::string> args;
+    std::vector<as_value>::const_iterator it;
+    std::string msg = ExternalInterface::makeInvoke(name, fnargs);
+
+    int 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);
+
+    return result;
+}
+
 void
 movie_root::cleanupDisplayList()
 {
@@ -1999,23 +2132,27 @@
     size_t len = requestString.length();
     // TODO: should mutex-protect this ?
     // NOTE: we are assuming the hostfd is set in blocking mode here..
-    log_debug(_("Attempt to write geturl requests fd %d"), _hostfd);
-
-    int ret = write(_hostfd, requestString.c_str(), len);
-    if (ret == -1) {
-        log_error(_("Could not write to user-provided host requests "
-                    "fd %d: %s"), _hostfd, std::strerror(errno));
+
+    log_debug(_("Attempt to write geturl requests fd #%d"), _hostfd);
+
+    std::vector<as_value> fnargs;
+    fnargs.push_back(as_value(urlstr));
+    if (!target.empty()) {
+       fnargs.push_back(as_value(target));
     }
-    if (static_cast<size_t>(ret) < len) {
-        log_error(_("Could only write %d bytes over %d required to "
-                    "user-provided host requests fd %d"),
-                    ret, len, _hostfd);
+    std::string msg = ExternalInterface::makeInvoke("getURL", fnargs);
+
+    size_t ret = ExternalInterface::writeBrowser(_hostfd, msg);
+    if (ret < msg.size()) {
+        log_error(_("Could only write %d bytes to fd #%d"),
+                 ret, _hostfd);
     }
 
     // The request string ends with newline, and we don't want to log that
+#if 0
     requestString.resize(requestString.size() - 1);
     log_debug(_("Sent request '%s' to host fd %d"), requestString, _hostfd);
-
+#endif
 }
 
 void

=== modified file 'libcore/movie_root.h'
--- a/libcore/movie_root.h      2010-05-25 19:03:26 +0000
+++ b/libcore/movie_root.h      2010-06-02 14:18:20 +0000
@@ -80,6 +80,7 @@
 #include "MovieClip.h"
 #include "SimpleBuffer.h" // for LoadCallback
 #include "MovieLoader.h"
+#include "ExternalInterface.h"
 
 #ifdef USE_SWFTREE
 # include "tree.hh"
@@ -585,9 +586,11 @@
     /// Sets the flag to allow interfacing with JavaScript in the browser.
     /// This is disabled by default, but enabled for ExternalInterface.
     void setAllowScriptAccess(AllowScriptAccessMode mode);
+    
     /// Gets the current Access Mode for ExternalInterface.
     AllowScriptAccessMode getAllowScriptAccess();
 
+
     typedef std::pair<StageHorizontalAlign, StageVerticalAlign> StageAlign;
 
     /// Returns the current alignment of the stage (left/right/centre, top/
@@ -602,6 +605,11 @@
     /// current gui
     void setShowMenuState( bool state );
 
+    // This is a flag that specifies whether exceptions in ActionScript
+    // should be propogated to JavaScript in the browser.
+    void setMarshallExceptions(bool x) { _marshallExceptions = x; };
+    bool getMarshallExceptions() { return _marshallExceptions; };
+    
     /// Sets the Stage object's align mode.
     void setStageScaleMode(ScaleMode sm);
     
@@ -785,11 +793,13 @@
     {
         return _hostfd;
     }
+
     int getControlFD() const
     {
         return _controlfd;
     }
 
+
     /// Abstract base class for FS handlers
     class AbstractFsCallback {
     public:
@@ -814,7 +824,7 @@
     /// Call this to notify FS commands
     DSOEXPORT void handleFsCommand(const std::string& cmd,
             const std::string& arg) const;
-
+    
     /// Abstract base class for hosting app handler
     class AbstractIfaceCallback
     {
@@ -910,6 +920,16 @@
 
     const RunResources& runResources() const { return _runResources; }
 
+    void addExternalCallback(const std::string &name, as_object *obj)
+    {
+        _externalCallbacks[name] = obj;
+    }    
+
+    bool processInvoke(ExternalInterface::invoke_t *);
+
+    std::string callExternalCallback(const std::string &name, 
+                                     const std::vector<as_value>& args);
+
 private:
 
     /// Set the root movie, replacing the current one if any.
@@ -1044,7 +1064,7 @@
     /// An invalidated stage will trigger complete redraw
     //
     /// So, this method should return true everytime a complete
-    /// redraw is needed. This is tipically only needed when
+    /// redraw is needed. This is typically only needed when
     /// the background changes.
     ///
     /// See setInvalidated() and clearInvalidated().
@@ -1112,9 +1132,11 @@
     ObjectCallbacks _objectCallbacks;
 
     LoadCallbacks _loadCallbacks;
+    
+    typedef std::map<std::string, as_object *> ExternalCallbacks;
+    ExternalCallbacks _externalCallbacks;
 
     typedef std::map<int, Timer*> TimerMap;
-
     TimerMap _intervalTimers;
     unsigned int _lastTimerId;
 
@@ -1171,6 +1193,7 @@
     Quality            _quality;
     std::bitset<4u>    _alignMode;
     AllowScriptAccessMode _allowScriptAccess;
+    bool               _marshallExceptions;
     bool               _showMenu;
     ScaleMode          _scaleMode;
     DisplayState       _displayState;

=== modified file 'plugin/npapi/Makefile.am'
--- a/plugin/npapi/Makefile.am  2010-04-22 16:22:57 +0000
+++ b/plugin/npapi/Makefile.am  2010-06-02 14:18:20 +0000
@@ -67,7 +67,6 @@
        $(NULL)
 
 # Scriptable plugin support
-if SCRIPTABLE
 check_PROGRAMS = test
 test_LDADD  = \
        $(GLIB_LIBS) \
@@ -86,8 +85,6 @@
 check:
        ./test
 
-endif
-
 if PLUGIN_LINK_UNDEFINED
 libgnashplugin_la_LDFLAGS = -avoid-version -L$(plugindir)
 else

=== modified file 'plugin/npapi/callbacks.cpp'
--- a/plugin/npapi/callbacks.cpp        2010-04-22 16:22:57 +0000
+++ b/plugin/npapi/callbacks.cpp        2010-05-31 22:19:55 +0000
@@ -180,7 +180,7 @@
         str = ei.makeInvoke("GotoFrame", iargs);
 
         // Write the message to the Control FD.
-        size_t ret = gpso->writePlayer(gpso->getControlFD(), str);
+        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()) {
@@ -219,7 +219,7 @@
         std::string str = ei.makeInvoke("IsPlaying", iargs);
         
         // Write the message to the Control FD.
-        size_t ret = gpso->writePlayer(gpso->getControlFD(), str);
+        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()) {
@@ -227,7 +227,7 @@
             BOOLEAN_TO_NPVARIANT(false, *result);
             return false;
         }        
-        std::string data = gpso->readPlayer(gpso->getControlFD());
+        std::string data = gpso->readPlayer();
         if (data.empty()) {
             BOOLEAN_TO_NPVARIANT(false, *result);
             return false;
@@ -279,13 +279,13 @@
         str = ei.makeInvoke("LoadMovie", iargs);
 
         // Write the message to the Control FD.
-        size_t ret = gpso->writePlayer(gpso->getControlFD(), str);
+        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 load the movie, network problems.");
             return false;
-        }        
+        }
         // gpso->LoadMovie();
         BOOLEAN_TO_NPVARIANT(true, *result);
         return true;
@@ -328,7 +328,7 @@
         str = ei.makeInvoke("Pan", iargs);
         
         // Write the message to the Control FD.
-        size_t ret = gpso->writePlayer(gpso->getControlFD(), str);
+        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()) {
@@ -377,7 +377,7 @@
         std::string str = ei.makeInvoke("PercentLoaded", iargs);
 
         // Write the message to the Control FD.
-        size_t ret = gpso->writePlayer(gpso->getControlFD(), str);
+        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()) {
@@ -385,7 +385,7 @@
             BOOLEAN_TO_NPVARIANT(false, *result);
             return false;
         }        
-        std::string data = gpso->readPlayer(gpso->getControlFD());
+        std::string data = gpso->readPlayer();
         if (data.empty()) {
             BOOLEAN_TO_NPVARIANT(false, *result);
             return false;
@@ -429,7 +429,7 @@
         std::string str = ei.makeInvoke("Play", iargs);
 
         // Write the message to the Control FD.
-        size_t ret = gpso->writePlayer(gpso->getControlFD(), str);
+        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()) {
@@ -468,7 +468,7 @@
         std::string str = ei.makeInvoke("Rewind", iargs);
 
         // Write the message to the Control FD.
-        size_t ret = gpso->writePlayer(gpso->getControlFD(), str);
+        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()) {
@@ -519,7 +519,7 @@
         str = ei.makeInvoke("SetZoomRect", iargs);
 
         // Write the message to the Control FD.
-        size_t ret = gpso->writePlayer(gpso->getControlFD(), str);
+        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()) {
@@ -557,7 +557,7 @@
         std::string str = ei.makeInvoke("StopPlay", iargs);
 
         // Write the message to the Control FD.
-        size_t ret = gpso->writePlayer(gpso->getControlFD(), str);
+        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()) {
@@ -600,7 +600,7 @@
         str = ei.makeInvoke("Zoom", iargs);
 
         // Write the message to the Control FD.
-        size_t ret = gpso->writePlayer(gpso->getControlFD(), str);
+        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()) {
@@ -638,7 +638,7 @@
         std::string str = ei.makeInvoke("TotalFrames", iargs);
 
         // Write the message to the Control FD.
-        size_t ret = gpso->writePlayer(gpso->getControlFD(), str);
+        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()) {
@@ -646,7 +646,7 @@
             BOOLEAN_TO_NPVARIANT(false, *result);
             return false;
         }        
-        std::string data = gpso->readPlayer(gpso->getControlFD());
+        std::string data = gpso->readPlayer();
         if (data.empty()) {
             BOOLEAN_TO_NPVARIANT(false, *result);
             return false;

=== modified file 'plugin/npapi/external.cpp'
--- a/plugin/npapi/external.cpp 2010-04-22 16:22:57 +0000
+++ b/plugin/npapi/external.cpp 2010-06-01 03:09:00 +0000
@@ -36,14 +36,6 @@
 
 namespace gnash {
 
-ExternalInterface::ExternalInterface ()
-{
-}
-
-ExternalInterface::~ExternalInterface ()
-{
-}
-
 // Create an Invoke message for the standalone Gnash
 std::string
 ExternalInterface::makeInvoke (const std::string &method,

=== modified file 'plugin/npapi/external.h'
--- a/plugin/npapi/external.h   2010-04-22 16:22:57 +0000
+++ b/plugin/npapi/external.h   2010-06-01 02:57:20 +0000
@@ -35,40 +35,36 @@
 
 namespace gnash {
 
-class ExternalInterface
+struct ExternalInterface
 {
-public:
     typedef struct {
         std::string name;
         std::string type;
         std::vector<GnashNPVariant> args;
     } invoke_t;
     
-    ExternalInterface ();
-    ~ExternalInterface ();
-    
     // Create an Invoke message for the standalone Gnash
-    std::string makeInvoke (const std::string &method, 
std::vector<std::string> args);
-    
-    std::string makeNull ();
-    std::string makeTrue ();
-    std::string makeFalse ();
-    std::string makeString (const std::string &str);
-    std::string makeProperty (const std::string &str, const std::string &data);
-    std::string makeProperty (const std::string &str, double num);
-    std::string makeProperty (const std::string &str, int num);
-    std::string makeNumber (double num);
-    std::string makeNumber (int num);
-    std::string makeNumber (unsigned int num);
-    std::string makeArray (std::vector<std::string> &args);
-    std::string makeObject (std::map<std::string, std::string> &args);
-    
-    GnashNPVariant parseXML(const std::string &xml);
-    invoke_t *parseInvoke(const std::string &xml);
-    
-    std::map<std::string, GnashNPVariant> parseProperties(const std::string 
&xml);
-    std::vector<GnashNPVariant> parseArguments(const std::string &xml);
-    std::string convertNPVariant (const NPVariant *npv);
+    static std::string makeInvoke (const std::string &method, 
std::vector<std::string> args);
+    
+    static std::string makeNull ();
+    static std::string makeTrue ();
+    static std::string makeFalse ();
+    static std::string makeString (const std::string &str);
+    static std::string makeProperty (const std::string &str, const std::string 
&data);
+    static std::string makeProperty (const std::string &str, double num);
+    static std::string makeProperty (const std::string &str, int num);
+    static std::string makeNumber (double num);
+    static std::string makeNumber (int num);
+    static std::string makeNumber (unsigned int num);
+    static std::string makeArray (std::vector<std::string> &args);
+    static std::string makeObject (std::map<std::string, std::string> &args);
+    
+    static GnashNPVariant parseXML(const std::string &xml);
+    static invoke_t *parseInvoke(const std::string &xml);
+    
+    static std::map<std::string, GnashNPVariant> parseProperties(const 
std::string &xml);
+    static std::vector<GnashNPVariant> parseArguments(const std::string &xml);
+    static std::string convertNPVariant (const NPVariant *npv);
 };
 
 }

=== added file 'plugin/npapi/geturl.as'
--- a/plugin/npapi/geturl.as    1970-01-01 00:00:00 +0000
+++ b/plugin/npapi/geturl.as    2010-05-29 16:06:24 +0000
@@ -0,0 +1,1 @@
+getURL("http://www.gnashdev.org";);

=== added file 'plugin/npapi/gshell.cpp'
--- a/plugin/npapi/gshell.cpp   1970-01-01 00:00:00 +0000
+++ b/plugin/npapi/gshell.cpp   2010-05-31 22:24:29 +0000
@@ -0,0 +1,527 @@
+// 
+//   Copyright (C) 2010 Free Software Foundation, Inc
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should hxave received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//
+
+#include <iostream>
+#include <string>
+#include <cstdlib>
+#include <vector>
+#include <map>
+#include <cassert>
+
+#include "npapi.h"
+#include "npruntime.h"
+#include "npfunctions.h"
+#include "plugin.h"
+#include "pluginbase.h"
+#include <regex.h>
+
+#include "external.h"
+#include "dsodefs.h" // DSOEXPORT
+
+#ifdef _WIN32
+#undef DLL_EXPORT
+#define LIBLTDL_DLL_IMPORT 1
+#endif
+
+#include <sys/param.h>
+#include <ltdl.h>
+
+using namespace gnash; 
+using namespace std; 
+
+typedef NPError NP_InitializePtr (NPNetscapeFuncs* aNPNFuncs,
+                                  NPPluginFuncs* aNPPFuncs);
+
+extern NPError NS_PluginGetValue(NPPVariable aVariable, void *aValue);
+
+// This is a global variable commonly used by plugins to access
+// the browser's function table. Since we aren't using a browser
+// we have to populate this ourselves.
+NPNetscapeFuncs *
+populateNPFuncs(NPNetscapeFuncs *aNPNFuncs)
+{
+    aNPNFuncs->size = 45;       // this is the count of entries
+    aNPNFuncs->version = 1.9;
+
+    aNPNFuncs->geturl = NPN_GetURL;
+    aNPNFuncs->posturl = NPN_PostURL;
+    aNPNFuncs->requestread = NPN_RequestRead;
+    aNPNFuncs->newstream = NPN_NewStream;
+    aNPNFuncs->write = NPN_Write;
+    aNPNFuncs->destroystream = NPN_DestroyStream;
+    aNPNFuncs->status = NPN_Status;
+    aNPNFuncs->uagent = NPN_UserAgent;
+    aNPNFuncs->memalloc = NPN_MemAlloc;
+    aNPNFuncs->memfree = NPN_MemFree;
+    aNPNFuncs->memflush = NPN_MemFlush;
+    aNPNFuncs->reloadplugins = NPN_ReloadPlugins;
+    aNPNFuncs->getJavaEnv = 0;    // NPN_GetJavaEnv;
+    aNPNFuncs->getJavaPeer = 0;   //NPN_GetJavaPeer;
+    aNPNFuncs->geturlnotify = NPN_GetURLNotify;
+    aNPNFuncs->posturlnotify = NPN_PostURLNotify;
+    aNPNFuncs->getvalue = NPN_GetValue;
+    aNPNFuncs->setvalue = NPN_SetValue;
+    aNPNFuncs->invalidaterect = NPN_InvalidateRect;
+    aNPNFuncs->invalidateregion = NPN_InvalidateRegion;
+    aNPNFuncs->forceredraw = 0;    // NPN_ForceDraw;
+    aNPNFuncs->getstringidentifier = NPN_GetStringIdentifier;
+    aNPNFuncs->getstringidentifiers = NPN_GetStringIdentifiers;
+    aNPNFuncs->getintidentifier = NPN_GetIntIdentifier;
+    aNPNFuncs->identifierisstring = NPN_IdentifierIsString;
+    aNPNFuncs->utf8fromidentifier = NPN_UTF8FromIdentifier;
+    aNPNFuncs->intfromidentifier = NPN_IntFromIdentifier;
+    aNPNFuncs->createobject = NPN_CreateObject;
+    aNPNFuncs->retainobject = NPN_RetainObject;
+    aNPNFuncs->releaseobject = NPN_ReleaseObject;
+    aNPNFuncs->invoke = NPN_Invoke;
+    aNPNFuncs->invokeDefault = NPN_InvokeDefault;
+    aNPNFuncs->evaluate = NPN_Evaluate;
+    aNPNFuncs->getproperty = NPN_GetProperty;
+    aNPNFuncs->setproperty = NPN_SetProperty;
+    aNPNFuncs->removeproperty = NPN_RemoveProperty;
+    aNPNFuncs->hasproperty = NPN_HasProperty;
+    aNPNFuncs->hasmethod = NPN_HasMethod;
+    aNPNFuncs->releasevariantvalue = NPN_ReleaseVariantValue;
+    aNPNFuncs->setexception = NPN_SetException;
+    // aaNPNFuncs->pushpopupsenabledstate = NPN_PushPopupsEnabledState;
+    // aaNPNFuncs->poppopupsenabledstate = NPN_PopPopupsEnabledState;
+    aNPNFuncs->enumerate = NPN_Enumerate;
+    aNPNFuncs->pluginthreadasynccall = NPN_PluginThreadAsyncCall;
+    aNPNFuncs->construct = NPN_Construct;
+    // aNPNFuncs->getvalueforurl = NPN_GetValueForURL;
+    // aNPNFuncs->setvalueforurl = NPN_SetValueForURL;
+
+    return aNPNFuncs;
+}
+
+int
+main(int argc, char *argv[])
+{
+    // Initialize libtool's dynamic library loader
+    int errors = lt_dlinit ();
+    if (errors) {
+        cerr << "ERROR: Couldn't initialize ltdl: " << lt_dlerror() << endl;
+    }    
+
+    // load a plugin in the current directory
+    string plugindir = ".";
+
+    // 
+    char dir[MAXPATHLEN];
+    getcwd(dir, MAXPATHLEN);
+    plugindir += ":";
+    plugindir += dir;
+    plugindir += "/.libs/";
+//    plugindir += "/plugin/npapo/.libs";
+    
+    lt_dlsetsearchpath(plugindir.c_str());
+
+    string filespec = "libgnashplugin.so";
+    lt_dlhandle handle;
+    handle = lt_dlopenext (filespec.c_str());
+    
+    if (handle == NULL) {
+        cerr << lt_dlerror() << endl;
+        return false;
+    }
+    // Make this module unloadable
+    lt_dlmakeresident(handle);    
+
+    // Get the init function
+    lt_ptr run = NULL;
+    string symbol = "NP_Initialize"; // NS_PluginInitialize instead ?
+    run  = lt_dlsym (handle, symbol.c_str());
+    
+    if (run == NULL) {
+        cout << "Couldn't find symbol: " << symbol << endl;
+        return NULL;
+    } else {
+        cout << "Found symbol " << symbol << " @ " << hex << run << endl;
+    }
+    
+    // this gets populated by the browser
+    NPNetscapeFuncs aNPNFuncs;
+    populateNPFuncs(&aNPNFuncs);
+
+    // this gets populated by the plugin
+    //NPPluginFuncs *aNPPFuncs;
+    nsPluginCreateData ds;
+
+    // NPPFuncs.newp(NPMIMEType, 0, 0, 1, 0, "foo", 0);
+    // nsPluginInstanceBase * plugin = NS_NewPluginInstance(&ds);
+    
+    NPPluginFuncs *aNPPFuncs = 0;
+    // Execute the plugin's initialization function
+    NP_InitializePtr *ptr = (NP_InitializePtr *)run;
+    NPError error = ptr(&aNPNFuncs, aNPPFuncs);
+    //    cout << getPluginDescription() << endl;
+
+    char *str = 0;
+    NPP_GetValue(0, NPPVpluginDescriptionString, str);
+    if (str) {
+        cerr << str << endl;
+    }
+
+    bool bo = false;
+    NPN_GetValue(0, NPNVSupportsXEmbedBool, &bo);
+    cerr << bo << endl;    
+}
+
+// We have to implement these two memory allocation functions as
+// they're used in the code we're testing.
+void *
+NPN_MemAlloc(uint32_t size)
+{
+  void * rv = NULL;
+  rv = malloc(size);
+  return rv;
+}
+
+void
+NPN_MemFree(void* ptr)
+{
+  assert(ptr);
+  free(ptr);
+}
+
+uint32_t
+NPN_MemFlush(uint32_t size)
+{
+    return size;
+}
+
+NPUTF8 *
+NPN_UTF8FromIdentifier(NPIdentifier identifier)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+int32_t
+NPN_IntFromIdentifier(NPIdentifier identifier)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+// These are just stubs to get the test case to link standalone.
+NPIdentifier
+NPN_GetStringIdentifier(const NPUTF8 *name)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+NPError
+NPP_GetValue(NPP instance, NPPVariable aVariable, void *aValue)
+{
+    if (NPPFuncs.getvalue) {
+        return NPPFuncs.getvalue(instance, aVariable, aValue);
+    }
+    return NPERR_GENERIC_ERROR;
+}
+
+NPError
+NPN_GetURLNotify(NPP instance, const char* url,
+                 const char* target, void* notifyData)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+NPError
+NPN_PostURLNotify(NPP instance, const char* url,
+                  const char* target, uint32_t len,
+                  const char* buf, NPBool file,
+                  void* notifyData)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+bool
+NPN_Invoke(NPP npp, NPObject *npobj, NPIdentifier methodName,
+           const NPVariant *args, uint32_t argCount, NPVariant *result)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+bool
+NPN_InvokeDefault(NPP npp, NPObject *npobj, const NPVariant *args,
+                  uint32_t argCount, NPVariant *result)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+bool
+NPN_Evaluate(NPP npp, NPObject *npobj, NPString *script,
+             NPVariant *result)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+bool
+NPN_GetProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName,
+                NPVariant *result)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+bool
+NPN_HasProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+bool
+NPN_HasMethod(NPP npp, NPObject *npobj, NPIdentifier methodName)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+NPError
+NPN_GetValue(NPP instance, NPNVariable aVariable, void *aValue)
+{
+    if (NPPFuncs.getvalue) {
+        return NPNFuncs.getvalue(instance, aVariable, aValue);
+    }
+    return NPERR_GENERIC_ERROR;
+}
+
+NPError
+NPN_SetValue(NPP instance, NPPVariable aVariable, void *aValue)
+{
+    if (NPPFuncs.setvalue) {
+        return NPNFuncs.setvalue(instance, aVariable, aValue);
+    }
+    return NPERR_GENERIC_ERROR;
+}
+
+void
+NPN_InvalidateRect(NPP instance, NPRect *invalidRect)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+void
+NPN_InvalidateRegion(NPP instance, NPRegion invalidRegion)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+void
+NPN_ReloadPlugins(NPBool reloadPages)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+NPError
+NPN_GetURL(NPP instance, const char* url, const char* target)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+NPError
+NP_LOADDS NPN_PostURL(NPP instance, const char* url,
+                      const char* target, uint32_t len,
+                      const char* buf, NPBool file)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+NPError
+NPN_RequestRead(NPStream* stream, NPByteRange* rangeList)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+NPError
+NPN_NewStream(NPP instance, NPMIMEType type, const char* target,
+              NPStream** stream)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+void
+NPN_Status(NPP instance, const char* message)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+const char *
+NPN_UserAgent(NPP instance)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+int32_t
+NPN_Write(NPP instance, NPStream* stream, int32_t len, void* buffer)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+NPError
+NPN_DestroyStream(NPP instance, NPStream* stream, NPReason reason)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+void
+NS_PluginShutdown()
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+char*
+NPP_GetMIMEDescription(void)
+{
+    char *x = 0;
+    return x;
+}
+
+void
+NS_DestroyPluginInstance(nsPluginInstanceBase *aPlugin)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+std::map<NPIdentifier, NPVariant *> _properties;
+std::map<NPIdentifier,  NPInvokeFunctionPtr> _methods;
+
+// Implement minimal properties handling
+bool
+NPN_SetProperty(NPP npp, NPObject* obj, NPIdentifier name,
+                     const NPVariant *value)
+{
+    _properties[name] = const_cast<NPVariant *>(value);
+}
+
+bool
+NPN_GetProperty(NPP npp, NPObject* obj, NPIdentifier name,
+                     const NPVariant *value)
+{
+    return _properties[name];
+}
+
+bool
+NPN_RemoveProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+bool
+NPN_HasProperty(NPP npp, NPObject* obj, NPIdentifier name,
+                     const NPVariant *value)
+{
+    std::map<NPIdentifier, NPVariant *>::iterator it;
+    it = _properties.find(name);
+    if (it != _properties.end()) {
+        return true;
+    }
+}
+
+
+void
+NPN_SetException(NPObject *npobj, const NPUTF8 *message)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+void
+NPN_PluginThreadAsyncCall(NPP plugin, void (*func)(void *), void *userData)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+bool
+NPN_Enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier,
+              uint32_t *count)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+bool
+NPN_Construct(NPP npp, NPObject *npobj, const NPVariant *args,
+              uint32_t argCount, NPVariant *result)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+void
+NPN_ReleaseVariantValue(NPVariant *variant)
+{
+    switch(variant->type) {
+        case NPVariantType_String:
+        {
+            
NPN_MemFree(const_cast<NPUTF8*>(NPVARIANT_TO_STRING(*variant).UTF8Characters));
+            break;
+        }
+        case NPVariantType_Object:
+        {
+            NPObject* obj = NPVARIANT_TO_OBJECT(*variant);
+            if (obj) {
+                NPN_ReleaseObject(obj);
+            }
+            break;
+        }
+        default:
+        {}
+    }
+ 
+    NULL_TO_NPVARIANT(*variant);
+}
+
+NPObject *
+NPN_CreateObject(NPP npp, NPClass *aClass)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+void
+NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount,
+                         NPIdentifier *identifiers)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+NPIdentifier
+NPN_GetIntIdentifier(int32_t intid)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+bool
+NPN_IdentifierIsString(NPIdentifier identifier)
+{
+    cerr << "UNIMPLEMENTED: " << __PRETTY_FUNCTION__ << endl;
+}
+
+NPObject*
+NPN_RetainObject(NPObject *obj)
+{
+    assert(obj); ++obj->referenceCount; return obj;
+}
+
+void
+NPN_ReleaseObject(NPObject *npobj)
+{
+    assert(npobj);
+    --npobj->referenceCount;
+    if (npobj->referenceCount == 0) {
+        NPN_MemFree(npobj);
+    }
+}
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:

=== modified file 'plugin/npapi/mozilla-sdk/npn_gate.cpp'
--- a/plugin/npapi/mozilla-sdk/npn_gate.cpp     2010-05-27 19:11:10 +0000
+++ b/plugin/npapi/mozilla-sdk/npn_gate.cpp     2010-06-02 14:18:20 +0000
@@ -42,6 +42,8 @@
 #include "npapi.h"
 #include "npfunctions.h"
 
+#include "plugin.h"
+
 #ifndef HIBYTE
 #define HIBYTE(x) ((((uint32_t)(x)) & 0xff00) >> 8)
 #endif
@@ -181,13 +183,19 @@
 
 NPError NPN_GetValue(NPP instance, NPNVariable variable, void *value)
 {
-  NPError rv = NPNFuncs.getvalue(instance, variable, value);
+  NPError rv = NPERR_GENERIC_ERROR;
+  if (NPNFuncs.getvalue) {
+    rv = NPNFuncs.getvalue(instance, variable, value);
+  }
   return rv;
 }
 
 NPError NPN_SetValue(NPP instance, NPPVariable variable, void *value)
 {
-  NPError rv = NPNFuncs.setvalue(instance, variable, value);
+  NPError rv = NPERR_GENERIC_ERROR;
+  if (NPNFuncs.setvalue) {
+    rv = NPNFuncs.setvalue(instance, variable, value);
+  }
   return rv;
 }
 

=== modified file 'plugin/npapi/plugin.cpp'
--- a/plugin/npapi/plugin.cpp   2010-05-27 23:23:21 +0000
+++ b/plugin/npapi/plugin.cpp   2010-06-02 14:18:20 +0000
@@ -62,16 +62,14 @@
   <br>\
   Compatible Shockwave Flash "FLASH_VERSION
 
-// Defining this flag disables the pipe to the standalone player, as well
-// as prevents the standalone Gnash player from being exec'd. Instead it
-// makes a network connection to localhost:1111 so the developer can use
-// Netcat (nc) to send and receive messages to test the interface.
-// #define NETTEST 1
-#undef NETTEST
-
 #include "plugin.h" 
 #include "GnashSystemIOHeaders.h"
 #include "StringPredicates.h"
+#include "external.h"
+#include "npapi.h"
+#include "npruntime.h"
+#include "npfunctions.h"
+#include "GnashNPVariant.h"
 
 #include <boost/tokenizer.hpp>
 #include <boost/algorithm/string/join.hpp>
@@ -101,6 +99,7 @@
 #include "pluginScriptObject.h"
 
 extern NPNetscapeFuncs NPNFuncs;
+extern NPPluginFuncs NPPFuncs;
 
 namespace gnash {
 NPBool plugInitialized = FALSE;
@@ -144,6 +143,8 @@
 NPError
 NS_PluginInitialize()
 {
+    // gnash::log_debug(__PRETTY_FUNCTION__);
+
     if ( gnash::plugInitialized ) {
         gnash::log_debug("NS_PluginInitialize called, but ignored (we already 
initialized)");
         return NPERR_NO_ERROR;
@@ -249,6 +250,7 @@
 void
 NS_PluginShutdown()
 {
+    // gnash::log_debug(__PRETTY_FUNCTION__);
 #if 0
     if (!plugInitialized) {
         gnash::log_debug("Plugin already shut down");
@@ -267,6 +269,7 @@
 NPError
 NS_PluginGetValue(NPPVariable aVariable, void *aValue)
 {
+    // gnash::log_debug(__PRETTY_FUNCTION__);
     NPError err = NPERR_NO_ERROR;
 
     switch (aVariable) {
@@ -321,6 +324,7 @@
 nsPluginInstanceBase *
 NS_NewPluginInstance(nsPluginCreateData * aCreateDataStruct)
 {
+    // gnash::log_debug(__PRETTY_FUNCTION__);
     if(!aCreateDataStruct) {
         return NULL;
     }
@@ -378,36 +382,11 @@
 
         _params[name] = val;
     }
-
-    _scriptObject = (GnashPluginScriptObject 
*)NPNFuncs.createobject(_instance, 
GnashPluginScriptObject::marshalGetNPClass());
-
-#if defined(NETTEST)
-    // This is a network testing node switch. This is only used for testing the
-    // interface between the player and the plugin.
-    struct sockaddr_in  sock_in;
-    memset(&sock_in, 0, sizeof(struct sockaddr_in));
-    sock_in.sin_family = AF_INET;
-    sock_in.sin_port = ntohs(1111);
-    const struct hostent *hent = ::gethostbyname("localhost");
-    if (hent > 0) {
-        ::memcpy(&sock_in.sin_addr, hent->h_addr, hent->h_length);
-    }
-    struct protoent     *proto;
-    proto = ::getprotobyname("TCP");
-    int sockfd = ::socket(PF_INET, SOCK_STREAM, proto->p_proto);
-    if (sockfd > 0) {
-        int ret = ::connect(sockfd, 
-                            reinterpret_cast<struct sockaddr *>(&sock_in),
-                            sizeof(sock_in));
-        if (ret == 0) {
-            gnash::log_debug("Connected to debug server on fd #%d", sockfd);
-            _controlfd = sockfd;
-            _scriptObject->setControlFD(_controlfd);
-        } else {
-            gnash::log_debug("Couldn't connect to debug server: %s", 
strerror(errno));
-        }
-    }
-#endif
+    
+    if (NPNFuncs.version >= 14) { // since NPAPI start to support
+        _scriptObject = (GnashPluginScriptObject *)NPNFuncs.createobject(
+            _instance, GnashPluginScriptObject::marshalGetNPClass());
+    }
     
     return;
 }
@@ -458,7 +437,6 @@
             usleep(1000);
             cleanup_childpid(pid);
         } else {
-
             gnash::log_debug("Child process exited with status %d", status);
         }
     }
@@ -509,14 +487,12 @@
     }
 
     if (_controlfd != -1) {
+        _scriptObject->closePipe(_controlfd);
         if (close(_controlfd) != 0) {
             gnash::log_error("Gnash plugin failed to close the control 
socket!");
         }
     }
 
-// #ifdef ENABLE_SCRIPTABLE
-//     _scriptObject->closePipe();
-// #endif
 
 }
 /// \brief Set the window to be used to render in
@@ -667,8 +643,10 @@
 bool
 nsPluginInstance::handlePlayerRequests(GIOChannel* iochan, GIOCondition cond)
 {
+    gnash::log_debug(__PRETTY_FUNCTION__);
+
     if ( cond & G_IO_HUP ) {
-        gnash::log_debug("Player request channel hang up");
+        gnash::log_debug("Player control socket hang up");
         // Returning false here will cause the "watch" to be removed. This 
watch
         // is the only reference held to the GIOChannel, so it will be
         // destroyed. We must make sure we don't attempt to destroy it again.
@@ -681,26 +659,36 @@
     gnash::log_debug("Checking player requests on fd #%d",
               g_io_channel_unix_get_fd(iochan));
 
+    GError* error = 0;
+    //    g_io_channel_set_flags(iochan, G_IO_FLAG_NONBLOCK, &error);
+
+    size_t retries = 5;
     do {
-        GError* error = 0;
+        // 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
+        // looping here forever, so this is our escape from that loop.
+        if (retries-- <= 0) {
+            gnash::log_error("Too many attempts to read from the player!");
+            return false;
+        }
+        error = 0;
         gchar* request = 0;
         gsize requestSize = 0;
         GIOStatus status = g_io_channel_read_line(iochan, &request,
                            &requestSize, NULL, &error);
         switch (status) {
           case G_IO_STATUS_ERROR:
-              gnash::log_error(std::string("Error reading request line: ")
-                               + error->message);
+              gnash::log_error("error reading request line: %s",
+                               error->message);
               g_error_free(error);
               return false;
           case G_IO_STATUS_EOF:
-              gnash::log_error(std::string("EOF (error: ") + error->message);
+              gnash::log_error("EOF (error: %s", error->message);
               g_error_free(error);
               return false;
           case G_IO_STATUS_AGAIN:
-              gnash::log_error(std::string("Read again(error: ")
-                               + error->message);
-              break;
+              gnash::log_debug("read again: nonblocking mode set ");
+              continue;
           case G_IO_STATUS_NORMAL:
               // process request
               // Get rid of the newline on the end if there is one. The string
@@ -730,94 +718,84 @@
 bool
 nsPluginInstance::processPlayerRequest(gchar* buf, gsize linelen)
 {
+    gnash::log_debug(__PRETTY_FUNCTION__);
+
     if ( linelen < 4 ) {
-        gnash::log_error(std::string("Invalid player request (too short): ") + 
 buf);
+        if (buf) {
+            gnash::log_error("Invalid player request (too short): %s", buf);
+        } else {
+            gnash::log_error("Invalid player request (too short): %d bytes", 
linelen);
+        }
         return false;
     }
-
-    if ( ! std::strncmp(buf, "GET ", 4) ) {
-        char* target = buf + 4;
-        if ( ! *target ) {
-            gnash::log_error("No target found after GET request");
-            return false;
-        }
-        char* url = target;
-        while (*url && *url != ':') ++url;
-        if ( *url ) {
-            *url='\0';
-            ++url;
-        } else {
-            gnash::log_error("No colon found after GETURL target string");
-            return false;
-        }
-
-        gnash::log_debug("Asked to get URL '%s' in target %s", url, target);
-        NPN_GetURL(_instance, url, target);
-        return true;
-
-    } else if ( ! std::strncmp(buf, "INVOKE ", 7) ) {
-        char* command = buf + 7;
-        if ( ! *command ) {
-            gnash::log_error("No command found after INVOKE request");
-            return false;
-        }
-        char* arg = command;
-        while (*arg && *arg != ':') ++arg;
-        if ( *arg ) {
-            *arg='\0';
-            ++arg;
-        } else {
-            gnash::log_error("No colon found after INVOKE command string");
-            return false;
-        }
-
-        std::string name = _name; 
-
-        std::stringstream jsurl;
-        jsurl << "javascript:" << name << "_DoFSCommand('" << command << "','" 
<< arg <<"')";
-
-        // TODO: check if _self is a good target for this
-        static const char* tgt = "_self";
-
-        gnash::log_debug("Calling NPN_GetURL(" + jsurl.str() + ", '" + 
std::string(tgt) + "');");
-
-        NPN_GetURL(_instance, jsurl.str().c_str(), tgt);
-        return true;
-    }  else if ( ! strncmp(buf, "POST ", 5)) {
-        char* target = buf + 5;
-        if (! *target) return false;
-        
-        char* postdata = target;
-        while (*postdata && *postdata != ':') ++postdata;
-        if ( *postdata ) {
-            *postdata='\0';
-            ++postdata;
-        }
-        else
-        {
-            gnash::log_error("No colon found after getURL postdata string");
-            return false;
-        }
-        
-        char* url = postdata;
-        while (*url && *url != '$') ++url;
-        if (*url) {
-            *url='\0';
-            ++url;
-        } else {
-            gnash::log_error("No $ character found after getURL target 
string");
-            return false;
-        }
-        
-
-        NPN_PostURL(_instance, url, target, std::strlen(postdata),
-                postdata, false);
-
-        return true;
+    
+    ExternalInterface::invoke_t *invoke = ExternalInterface::parseInvoke(buf);
+
+    if (invoke) {
+        if (invoke->name == "getURL") {
+            // gnash::log_debug("Got a getURL() request: %", 
invoke->args[0].get());
+
+            std::string url = 
NPStringToString(NPVARIANT_TO_STRING(invoke->args[0].get()));
+            std::string target;
+            if (invoke->args.size() == 2) {
+                target = 
NPStringToString(NPVARIANT_TO_STRING(invoke->args[1].get()));
+            }
+            
+            gnash::log_debug("Asked to getURL '%s' in target %s", url, target);
+            NPN_GetURL(_instance, url.c_str(), target.c_str());
+            return true;
+        } else if (invoke->name == "fsCommand") {
+            std::string command = 
NPStringToString(NPVARIANT_TO_STRING(invoke->args[0].get()));
+            std::string arg = 
NPStringToString(NPVARIANT_TO_STRING(invoke->args[1].get()));            
+            std::string name = _name; 
+            std::stringstream jsurl;
+            jsurl << "javascript:" << name << "_DoFSCommand('" << command << 
"','" << arg <<"')";
+            
+            // TODO: check if _self is a good target for this
+            static const char* tgt = "_self";
+            
+            gnash::log_debug("Calling NPN_GetURL(%s, %s)",
+                             jsurl.str(), tgt);
+            
+            NPN_GetURL(_instance, jsurl.str().c_str(), tgt);
+            return true;
+#if 0
+        }  else if ( ! strncmp(buf, "POST ", 5)) {
+            char* target = buf + 5;
+            if (! *target) return false;
+            
+            char* postdata = target;
+            while (*postdata && *postdata != ':') ++postdata;
+            if ( *postdata ) {
+                *postdata='\0';
+                ++postdata;
+            } else {
+                gnash::log_error("No colon found after getURL postdata 
string");
+                return false;
+            }
+        
+            char* url = postdata;
+            while (*url && *url != '$') ++url;
+            if (*url) {
+                *url='\0';
+                ++url;
+            } else {
+                gnash::log_error("No $ character found after getURL target 
string");
+                return false;
+            }
+            
+            NPN_PostURL(_instance, url, target, std::strlen(postdata),
+                        postdata, false);
+            
+            return true;
+#endif
+        }
     } else {
         gnash::log_error("Unknown player request: " + std::string(buf));
         return false;
     }
+
+    return false;
 }
 
 std::string
@@ -1065,6 +1043,7 @@
     }
 
     _scriptObject->setControlFD(p2c_controlpipe[1]);
+    _scriptObject->setHostFD(c2p_pipe[0]);
     
     // Setup the command line for starting Gnash
 

=== modified file 'plugin/npapi/pluginScriptObject.cpp'
--- a/plugin/npapi/pluginScriptObject.cpp       2010-05-25 19:03:26 +0000
+++ b/plugin/npapi/pluginScriptObject.cpp       2010-06-02 14:18:20 +0000
@@ -74,6 +74,14 @@
     GnashPluginScriptObject::marshalConstruct
 };
 
+/// The HostFD is the file descriptor for the socket connection
+/// to the standalone player. This is used by this plugin when reading
+/// messages from the standalone player.
+static int hostfd = -1;
+
+/// The ControlFD is the file descriptor for the socket connection
+/// to the standalone player. This is used when writing to the
+/// standalone player from this plugin.
 static int controlfd = -1;
 
 bool
@@ -615,18 +623,15 @@
                                      const NPVariant& value)
 {
     log_debug(__PRETTY_FUNCTION__);
-
-    ExternalInterface ei;
-    
     std::vector<std::string> iargs;
-    std::string str = ei.makeString(name);
-    iargs.push_back(str);
-    str = ei.convertNPVariant(&value);
-    iargs.push_back(str);
-    str = ei.makeInvoke("SetVariable", iargs);
+    std::string str = ExternalInterface::makeString(name);
+    iargs.push_back(str);
+    str = ExternalInterface::convertNPVariant(&value);
+    iargs.push_back(str);
+    str = ExternalInterface::makeInvoke("SetVariable", iargs);
     
     // Write the message to the Control FD.
-    size_t ret = writePlayer(controlfd, str);
+    size_t ret = writePlayer(str);
     // Unless we wrote the same amount of data as the message contained,
     // something went wrong.
     if (ret != str.size()) {
@@ -645,47 +650,42 @@
 {
     log_debug(__PRETTY_FUNCTION__);
 
-    ExternalInterface ei;
     std::vector<std::string> iargs;
-    std::string str = ei.makeString(name);
+    std::string str = ExternalInterface::makeString(name);
     iargs.push_back(str);
-    str = ei.makeInvoke("GetVariable", iargs);
+    str = ExternalInterface::makeInvoke("GetVariable", iargs);
 
     log_debug("Trying to get a value for %s.", name);
     
-    NPVariant value;
-    NULL_TO_NPVARIANT(value);
-    
-    if (name == "$version") {
+    size_t ret = writePlayer(str);
+    if (ret != str.size()) {
         // If all the browser wants is the version, we don't need to
         // ask the standalone player for this value. YouTube at
         // least depends on this for some pages which want this to
         // be greater than 8.0.0. This appears to potentially be
         // Google's way of trying to revent downloaders, as this requires
         // plugin support.
-        STRINGN_TO_NPVARIANT("LNX 10,0,r999", 13, value);
-        return value;
-    } else {
-        size_t ret = writePlayer(controlfd, str);
-        if (ret != str.size()) {
+        NPVariant value;
+        if (name == "$version") {
+            STRINGN_TO_NPVARIANT("LNX 10,0,r999", 13, value);
+        } else {
             log_error("Couldn't send GetVariable request, network problems.");
             NULL_TO_NPVARIANT(value);
-            return value;
-        }
-
-        // Have the read function allocate the memory
-        std::string data = readPlayer(controlfd);
-        if (data.empty()) {
-            return GnashNPVariant();
-        }
-        
-        GnashNPVariant parsed = ei.parseXML(data);
-        
-        printNPVariant(&parsed.get());
-        
-        return parsed;
-    }
-    return value;
+        }
+        return value;
+    }
+
+    // Have the read function allocate the memory
+    std::string data = readPlayer();
+    if (data.empty()) {
+        return GnashNPVariant();
+    }
+
+    GnashNPVariant parsed = ExternalInterface::parseXML(data);
+
+    printNPVariant(&parsed.get());
+    
+    return parsed;
 }
 
 void
@@ -711,9 +711,38 @@
     return controlfd;
 };
 
+void
+GnashPluginScriptObject::setHostFD(int x)
+{
+//    log_debug("%s: %d", __FUNCTION__, x);
+#if 0
+    if (_iochan == 0) {
+        _iochan[WRITEFD] = g_io_channel_unix_new(x);
+    }
+#endif
+    hostfd = x;              // FIXME: this should go away
+}
+
+int
+GnashPluginScriptObject::getHostFD()
+{
+// log_debug("getControlFD: %d", controlfd);
+
+#if 0
+    return g_io_channel_unix_get_fd (_iochan);
+#endif    
+    return hostfd;
+};
+
 
 // Write to the standalone player over the control socket
 int
+GnashPluginScriptObject::writePlayer(const std::string &data)
+{
+    return writePlayer(controlfd, data);
+}
+
+int
 GnashPluginScriptObject::writePlayer(int fd, const std::string &data)
 {
 //    log_debug(__PRETTY_FUNCTION__);
@@ -728,6 +757,12 @@
 }
 
 std::string
+GnashPluginScriptObject::readPlayer()
+{
+    return readPlayer(hostfd);
+}
+
+std::string
 GnashPluginScriptObject::readPlayer(int fd)
 {
 //    log_debug(__PRETTY_FUNCTION__);
@@ -789,6 +824,11 @@
 //     log_debug(__FUNCTION__);
     
     if (fd > 0) {
+        // 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);
+    
         ::shutdown(fd, SHUT_RDWR);
         ::close(fd);
     }
@@ -956,7 +996,7 @@
     log_debug(__PRETTY_FUNCTION__);
     
     if ( cond & G_IO_HUP ) {
-        log_debug("Player request channel hang up");
+        log_debug("Player control channel hang up");
         // Returning false here will cause the "watch" to be removed. This 
watch
         // is the only reference held to the GIOChannel, so it will be
         // destroyed. We must make sure we don't attempt to destroy it again.
@@ -1008,6 +1048,14 @@
 }
 
 bool
+GnashPluginScriptObject::processPlayerRequest(gchar */* buf */, gsize /* len 
*/)
+{
+    log_debug(__PRETTY_FUNCTION__);
+
+    return false;
+}
+
+bool
 GnashPluginScriptObject::handleInvokeWrapper(GIOChannel *iochan,
                                              GIOCondition cond,
                                              GnashPluginScriptObject* plugin)

=== modified file 'plugin/npapi/pluginScriptObject.h'
--- a/plugin/npapi/pluginScriptObject.h 2010-05-08 21:33:27 +0000
+++ b/plugin/npapi/pluginScriptObject.h 2010-06-01 03:10:58 +0000
@@ -91,11 +91,18 @@
     /// Scripting API support. This is where all the protocol support
     /// lives.
 
-    //  The ControlFD is the file descriptor for the socket connection
-    // to the standalone player.
+    /// The ControlFD is the file descriptor for the socket connection
+    /// to the standalone player. This is used when writing to the
+    /// standalone player from this plugin.
     void setControlFD(int x);
     int getControlFD();
 
+    /// The HostFD is the file descriptor for the socket connection
+    /// to the standalone player. This is used by this plugin when reading
+    /// messages from the standalone player.
+    void setHostFD(int x);
+    int getHostFD();
+
     /// Set a variable in the standalone player
     ///
     /// @param name the name of the variable to set
@@ -127,9 +134,11 @@
     int getWriteFD() { return _sockfds[WRITEFD]; };
     
     // Write to the standalone player over the control socket
+    int writePlayer(const std::string &data);
     int writePlayer(int fd, const std::string &data);
     
     // Read the standalone player over the control socket
+    std::string readPlayer();
     std::string readPlayer(int fd);
     
 protected:
@@ -167,7 +176,6 @@
     /// @return true if the request was processed, false otherwise (bogus 
request..)
     ///
     bool processPlayerRequest(gchar* buf, gsize len);
-
 private:
     static bool handleInvokeWrapper(GIOChannel* iochan, GIOCondition cond,
                                      GnashPluginScriptObject* plugin);

=== modified file 'plugin/npapi/scriptable-test.html'
--- a/plugin/npapi/scriptable-test.html 2010-04-19 15:38:17 +0000
+++ b/plugin/npapi/scriptable-test.html 2010-06-01 04:15:48 +0000
@@ -53,6 +53,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>
     </ul>
 
 </div>
@@ -226,6 +227,13 @@
                   addLog(value);
         }
 
+        function FlashTestEIMethod()
+        {
+                  var value = embed.TestEIMethod();
+        //          addLog("TestEIMethod() = " + value);          
+                  addLog(value);
+        }
+
         function ShowFoobar(msg)
         {
             addLog(embed.SetVariable("foo", "bar"));
@@ -240,6 +248,40 @@
         }
 </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.
+<br>
+<object>
+<param name="movie" value="geturl.swf"
+<embed
+src="geturl.swf"
+quality="high" wmode="transparent" width="320" height="240"
+   type="application/x-shockwave-flash"
+   pluginspage="http://www.getgnash.org";>
+</embed>
+-->
 
 </body>
 </html>

=== modified file 'plugin/npapi/test.cpp'
--- a/plugin/npapi/test.cpp     2010-04-22 16:22:57 +0000
+++ b/plugin/npapi/test.cpp     2010-06-01 03:11:31 +0000
@@ -42,11 +42,10 @@
 {
     using namespace gnash; 
 
-    ExternalInterface ei;
     NPVariant *value =  (NPVariant *)NPN_MemAlloc(sizeof(NPVariant));
 
     BOOLEAN_TO_NPVARIANT(true, *value);
-    std::string str = ei.convertNPVariant(value);
+    std::string str = ExternalInterface::convertNPVariant(value);
     if (str == "<true/>") {
         runtest.pass("convertNPVariant(true)");
     } else {
@@ -54,7 +53,7 @@
     }
     
     BOOLEAN_TO_NPVARIANT(false, *value);
-    str = ei.convertNPVariant(value);
+    str = ExternalInterface::convertNPVariant(value);
     if (str == "<false/>") {
         runtest.pass("convertNPVariant(false)");
     } else {
@@ -62,7 +61,7 @@
     }
 
     NULL_TO_NPVARIANT(*value);
-    str = ei.convertNPVariant(value);
+    str = ExternalInterface::convertNPVariant(value);
     if (str == "<null/>") {
         runtest.pass("convertNPVariant(null)");
     } else {
@@ -70,7 +69,7 @@
     }
 
     VOID_TO_NPVARIANT(*value);
-    str = ei.convertNPVariant(value);
+    str = ExternalInterface::convertNPVariant(value);
     if (str == "<void/>") {
         runtest.pass("convertNPVariant(void)");
     } else {
@@ -78,7 +77,7 @@
     }
 
     DOUBLE_TO_NPVARIANT(123.456, *value);
-    str = ei.convertNPVariant(value);
+    str = ExternalInterface::convertNPVariant(value);
     if (str == "<number>123.456</number>") {
         runtest.pass("convertNPVariant(double)");
     } else {
@@ -86,7 +85,7 @@
     }    
 
     INT32_TO_NPVARIANT(78, *value);
-    str = ei.convertNPVariant(value);
+    str = ExternalInterface::convertNPVariant(value);
     if (str == "<number>78</number>") {
         runtest.pass("convertNPVariant(int32)");
     } else {
@@ -94,14 +93,14 @@
     }
     
     STRINGZ_TO_NPVARIANT("Hello World!", *value);
-    str = ei.convertNPVariant(value);
+    str = ExternalInterface::convertNPVariant(value);
     if (str == "<string>Hello World!</string>") {
         runtest.pass("convertNPVariant(string)");
     } else {
         runtest.fail("convertNPVariant(string)");
     }
     
-    str = ei.makeProperty("hi", "Hello World!");
+    str = ExternalInterface::makeProperty("hi", "Hello World!");
     if (str == "<property id=\"hi\">Hello World!</property>") {
         runtest.pass("ExternalInterface::makeProperty()");
     } else {
@@ -110,7 +109,7 @@
     
 #if 0
     ARRAY_TO_NPVARIANT(*value);
-    str = ei.convertNPVariant(value);
+    str = ExternalInterface::convertNPVariant(value);
     if (str == "<array></array>") {
         runtest.pass("convertNPVariant(array)");
     } else {
@@ -119,9 +118,9 @@
 #endif
 
     NPObject *obj =  (NPObject *)NPN_MemAlloc(sizeof(NPObject));
-    std::string prop1 = ei.makeString("foobar");
-    std::string prop2 = ei.makeNumber(12.34);
-    std::string prop3 = ei.makeNumber(56);
+    std::string prop1 = ExternalInterface::makeString("foobar");
+    std::string prop2 = ExternalInterface::makeNumber(12.34);
+    std::string prop3 = ExternalInterface::makeNumber(56);
     std::vector<std::string> aargs;
     aargs.push_back(prop1);
     aargs.push_back(prop2);
@@ -129,7 +128,7 @@
     
     regex_t regex_pat;
     regcomp (&regex_pat, "<array><property 
id=\"0\"><string>foobar</string></property><property 
id=\"1\"><number>12.34</number></property><property 
id=\"2\"><number>56</number></property></array>", REG_NOSUB|REG_NEWLINE);
-    str = ei.makeArray(aargs);
+    str = ExternalInterface::makeArray(aargs);
     if (regexec (&regex_pat, reinterpret_cast<const char*>(str.c_str()), 0, 
(regmatch_t *)0, 0)) {    
         runtest.fail("ExternalInterface::makeArray()");
     } else {
@@ -141,7 +140,7 @@
     margs["test2"] = prop2;
     margs["test3"] = prop3;
     
-    str = ei.makeObject(margs);
+    str = ExternalInterface::makeObject(margs);
     std::string xml = "<object><property 
id=\"test1\"><string>foobar</string></property><property 
id=\"test2\"><number>12.34</number></property><property 
id=\"test3\"><number>56</number></property></object>";
     
     regcomp (&regex_pat, xml.c_str(), REG_NOSUB|REG_NEWLINE);
@@ -157,7 +156,7 @@
     // Parsing tests
     //
     xml = "<string>Hello World!</string>";
-    GnashNPVariant np = ei.parseXML(xml);
+    GnashNPVariant np = ExternalInterface::parseXML(xml);
     std::string data = NPStringToString(NPVARIANT_TO_STRING(np.get()));
     if (NPVARIANT_IS_STRING(np.get()) &&
         (data == "Hello World!")) {
@@ -167,7 +166,7 @@
     }
 
     xml = "<number>123.456</number>";
-    np = ei.parseXML(xml);
+    np = ExternalInterface::parseXML(xml);
     double num = NPVARIANT_TO_DOUBLE(np.get());
     if (NPVARIANT_IS_DOUBLE(np.get()) &&
         (num == 123.456)) {
@@ -177,7 +176,7 @@
     }
 
     xml = "<number>78</number>";
-    np = ei.parseXML(xml);
+    np = ExternalInterface::parseXML(xml);
     int inum = NPVARIANT_TO_INT32(np.get());
     if (NPVARIANT_IS_INT32(np.get()) &&
         (inum == 78)) {
@@ -187,7 +186,7 @@
     }
 
     xml = "<true/>";
-    np = ei.parseXML(xml);
+    np = ExternalInterface::parseXML(xml);
     bool flag = NPVARIANT_TO_BOOLEAN(np.get());
     if (NPVARIANT_IS_BOOLEAN(np.get()) &&
         (flag == true)) {
@@ -197,7 +196,7 @@
     }
 
     xml = "<false/>";
-    np = ei.parseXML(xml);
+    np = ExternalInterface::parseXML(xml);
     flag = NPVARIANT_TO_BOOLEAN(np.get());
     if (NPVARIANT_IS_BOOLEAN(np.get()) &&
         (flag == false)) {
@@ -207,7 +206,7 @@
     }
 
     xml = "<null/>";
-    np = ei.parseXML(xml);
+    np = ExternalInterface::parseXML(xml);
     if (NPVARIANT_IS_NULL(np.get())) {
         runtest.pass("ExternalInterface::parseXML(null)");
     } else {
@@ -215,7 +214,7 @@
     }
 
     xml = "<void/>";
-    np = ei.parseXML(xml);
+    np = ExternalInterface::parseXML(xml);
     if (NPVARIANT_IS_VOID(np.get())) {
         runtest.pass("ExternalInterface::parseXML(void)");
     } else {
@@ -223,7 +222,7 @@
     }
 
     xml = "<property id=\"0\"><string>foobar</string></property><property 
id=\"1\"><number>12.34</number></property><property 
id=\"2\"><number>56</number></property>";
-    std::map<std::string, GnashNPVariant> props = ei.parseProperties(xml);
+    std::map<std::string, GnashNPVariant> props = 
ExternalInterface::parseProperties(xml);
     np = props["0"];
     data = NPStringToString(NPVARIANT_TO_STRING(np.get()));
     if ((props.size() == 3) && (data == "foobar")) {
@@ -233,7 +232,7 @@
     }
     
     xml = "<object><property 
id=\"test1\"><string>foobar</string></property><property 
id=\"test2\"><number>12.34</number></property><property 
id=\"test3\"><number>56</number></property></object>";
-    np = ei.parseXML(xml);
+    np = ExternalInterface::parseXML(xml);
     if (NPVARIANT_IS_OBJECT(np.get())) {
         runtest.pass("ExternalInterface::parseXML(object)");
     } else {
@@ -241,12 +240,12 @@
     }
     
     std::vector<std::string> iargs;
-    str = ei.makeString("barfoo");
+    str = ExternalInterface::makeString("barfoo");
     iargs.push_back(str);
-    str = ei.makeNumber(135.78);
+    str = ExternalInterface::makeNumber(135.78);
     iargs.push_back(str);
     
-    str = ei.makeInvoke("barbyfoo", iargs);
+    str = ExternalInterface::makeInvoke("barbyfoo", iargs);
     xml = "<invoke name=\"barbyfoo\" 
returntype=\"xml\"><arguments><string>barfoo</string><number>135.78</number></arguments></invoke>";
 //    std::cout << str << std::endl;
     regcomp (&regex_pat, xml.c_str(), REG_NOSUB|REG_NEWLINE);
@@ -257,7 +256,7 @@
     }
     
     xml = 
"<arguments><string>barfoo</string><number>135.78</number><number>89</number></arguments>";
-    std::vector<GnashNPVariant> arguments = ei.parseArguments(xml);
+    std::vector<GnashNPVariant> arguments = 
ExternalInterface::parseArguments(xml);
     np = arguments[0];
     str = NPStringToString(NPVARIANT_TO_STRING(np.get()));
     double dub = NPVARIANT_TO_DOUBLE(arguments[1].get());
@@ -271,7 +270,7 @@
 
     // Parse an invoke message
     xml = "<invoke name=\"barbyfoo\" 
returntype=\"xml\"><arguments><string>barfoo</string><number>135.78</number></arguments></invoke>";
-    ExternalInterface::invoke_t *invoke = ei.parseInvoke(xml);
+    ExternalInterface::invoke_t *invoke = ExternalInterface::parseInvoke(xml);
     str = NPStringToString(NPVARIANT_TO_STRING(invoke->args[0].get()));
     if ((invoke->name == "barbyfoo") && (invoke->type == "xml")
         && (NPVARIANT_IS_STRING(invoke->args[0].get()))
@@ -287,21 +286,24 @@
 
 // We have to implement these two memory allocation functions as
 // they're used in the code we're testing.
-void* NPN_MemAlloc(uint32_t size)
+void *
+NPN_MemAlloc(uint32_t size)
 {
   void * rv = NULL;
   rv = malloc(size);
   return rv;
 }
 
-void NPN_MemFree(void* ptr)
+void
+NPN_MemFree(void* ptr)
 {
   assert(ptr);
   free(ptr);
 }
 
 // These are just stubs to get the test case to link standalone.
-NPIdentifier NPN_GetStringIdentifier(const NPUTF8 *name)
+NPIdentifier
+NPN_GetStringIdentifier(const NPUTF8 *name)
 {
 }
 
@@ -338,19 +340,22 @@
 }
 
 // Implement minimal properties handling
-bool NPN_SetProperty(NPP npp, NPObject* obj, NPIdentifier name,
+bool
+NPN_SetProperty(NPP npp, NPObject* obj, NPIdentifier name,
                      const NPVariant *value)
 {
     _properties[name] = const_cast<NPVariant *>(value);
 }
 
-bool NPN_GetProperty(NPP npp, NPObject* obj, NPIdentifier name,
+bool
+NPN_GetProperty(NPP npp, NPObject* obj, NPIdentifier name,
                      const NPVariant *value)
 {
     return _properties[name];
 }
 
-bool NPN_HasProperty(NPP npp, NPObject* obj, NPIdentifier name,
+bool
+NPN_HasProperty(NPP npp, NPObject* obj, NPIdentifier name,
                      const NPVariant *value)
 {
     std::map<NPIdentifier, NPVariant *>::iterator it;

=== modified file 'testsuite/actionscript.all/ExternalInterface.as'
--- a/testsuite/actionscript.all/ExternalInterface.as   2010-05-25 19:03:26 
+0000
+++ b/testsuite/actionscript.all/ExternalInterface.as   2010-06-02 14:18:20 
+0000
@@ -78,6 +78,9 @@
     fail("ExternalInterface::addCallback(\"TestEIMethod\")");
 }
 
+// ::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);
 
 if (EI.call("TestEIMethod", null) == null) {

=== modified file 'testsuite/misc-haxe.all/classes.all/system/System_as.hx'
--- a/testsuite/misc-haxe.all/classes.all/system/System_as.hx   2010-01-01 
17:48:26 +0000
+++ b/testsuite/misc-haxe.all/classes.all/system/System_as.hx   2010-06-02 
14:18:20 +0000
@@ -694,7 +694,7 @@
 if (Std.string(untyped __typeof__(p.download)) == 'function') {
        DejaGnu.xpass("Type of p.download is 'function'.");
 } else {
-       DejaGnu.xfail("Type of p.donwload should be 'functoin', is "+untyped 
__typeof__(p.download));
+       DejaGnu.xfail("Type of p.donwload should be 'function', is "+untyped 
__typeof__(p.download));
 }
 if (Std.string(untyped __typeof__(p.launch)) == 'function') {
        DejaGnu.xpass("Type of p.launch is 'function'.");
@@ -747,6 +747,6 @@
 
 // local Variables:
 // mode: C++
-// indent-tabs-mode: t
+// indent-tabs-mode: nil
 // End:
 


reply via email to

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