[Top][All Lists]
[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 (®ex_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 (®ex_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 (®ex_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 (®ex_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:
- [Gnash-commit] /srv/bzr/gnash/trunk r12207: merge from branch all ExternalInterface refactoring.,
Rob Savoye <=