[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] /srv/bzr/gnash/trunk r12162: partial scriptable support.
From: |
Rob Savoye |
Subject: |
[Gnash-commit] /srv/bzr/gnash/trunk r12162: partial scriptable support. fixes Go Upgrade YouTube problem. |
Date: |
Mon, 19 Apr 2010 17:46:40 -0600 |
User-agent: |
Bazaar (2.0.3) |
------------------------------------------------------------
revno: 12162 [merge]
committer: Rob Savoye <address@hidden>
branch nick: trunk
timestamp: Mon 2010-04-19 17:46:40 -0600
message:
partial scriptable support. fixes Go Upgrade YouTube problem.
modified:
configure.ac
gui/Player.cpp
gui/gnash.cpp
libcore/movie_root.cpp
plugin/npapi/callbacks.cpp
plugin/npapi/external.cpp
plugin/npapi/external.h
plugin/npapi/plugin.cpp
plugin/npapi/plugin.h
plugin/npapi/pluginScriptObject.cpp
plugin/npapi/pluginScriptObject.h
plugin/npapi/scriptable-test.html
plugin/npapi/test.cpp
=== modified file 'configure.ac'
--- a/configure.ac 2010-04-10 20:59:49 +0000
+++ b/configure.ac 2010-04-16 22:07:49 +0000
@@ -289,7 +289,7 @@
yes) scriptable=yes ;;
no) scriptable=no ;;
*) AC_MSG_ERROR([bad value ${enableval} for enable-scriptable option]) ;;
- esac], scriptable=no
+ esac], scriptable=yes
)
AM_CONDITIONAL(SCRIPTABLE, [test x"$scriptable" = xyes])
if test x$scriptable = xyes; then
=== modified file 'gui/Player.cpp'
--- a/gui/Player.cpp 2010-03-16 18:04:59 +0000
+++ b/gui/Player.cpp 2010-04-17 00:32:12 +0000
@@ -329,8 +329,11 @@
}
// Set _root._url (either explicit of from infile)
- if (!url.empty()) _url = url;
- else _url = infile;
+ if (!url.empty()) {
+ _url = url;
+ } else {
+ _url = infile;
+ }
// Parse player parameters. These are not passed to the SWF, but rather
// control stage properties etc.
@@ -417,7 +420,9 @@
root.registerFSCommandCallback(_callbacksHandler.get());
// Set host requests fd (if any)
- if ( _hostfd != -1 ) root.setHostFD(_hostfd);
+ if ( _hostfd != -1 ) {
+ root.setHostFD(_hostfd);
+ }
if (_controlfd != -1) {
_gui->setFDCallback(_controlfd, boost::bind(&Gui::quit,
boost::ref(_gui)));
@@ -433,7 +438,9 @@
// because the gui window should be properly set up by this point.
RcInitFile& rcfile = RcInitFile::getDefaultInstance();
- if (rcfile.startStopped()) _gui->stop();
+ if (rcfile.startStopped()) {
+ _gui->stop();
+ }
// Start loader thread
// NOTE: the loader thread might (in IMPORT tag parsing)
=== modified file 'gui/gnash.cpp'
--- a/gui/gnash.cpp 2010-04-05 19:54:56 +0000
+++ b/gui/gnash.cpp 2010-04-19 22:58:02 +0000
@@ -26,6 +26,9 @@
#include <iostream>
#include <ios>
#include <boost/format.hpp>
+#include <cstdlib>
+#include <sys/types.h>
+#include <fcntl.h>
#ifdef ENABLE_NLS
# include <clocale>
#endif
@@ -118,7 +121,7 @@
<< _(" 1 enable rendering, disable sound\n")
<< _(" 2 enable sound, disable rendering\n")
<< _(" 3 enable rendering and sound
(default)\n")
- // Only list the renderes that were configured in for this build
+ // Only list the renderers that were configured in for this build
<< _(" -R, --Renderer <")
#ifdef RENDERER_OPENGL
<< _(" opengl")
@@ -140,8 +143,6 @@
"\"FlashVars=A=1&b=2\")\n")
<< _(" -F, --fd <fd> Filedescriptor to use for external "
"communications\n")
- << _(" -G, --controlfd <fd> File descriptor for external application"
- " control\n")
#ifdef GNASH_FPS_DEBUG
<< _(" -f, --debug-fps num Print FPS every num seconds (float)\n")
#endif // def GNASH_FPS_DEBUG
@@ -235,8 +236,7 @@
{ 'g', "debugger", Arg_parser::no },
{ 'V', "version", Arg_parser::no },
{ 'f', "debug-fps", Arg_parser::yes },
- { 'F', "fd", Arg_parser::yes },
- { 'G', "controlfd", Arg_parser::yes },
+ { 'F', "fifo", Arg_parser::yes },
{ 'A', "dump", Arg_parser::yes },
{ 259, "screenshot", Arg_parser::yes },
{ 260, "screenshot-file", Arg_parser::yes },
@@ -322,26 +322,31 @@
break;
case 'F':
{
- const int fd = parser.argument<long>(i);
- if (fd < 1) {
- cerr << boost::format(_("Invalid host communication "
- "filedescriptor %d\n")) % fd << endl;
- exit(EXIT_FAILURE);
- }
- player.setHostFD ( fd );
- break;
- }
- case 'G':
- {
- const int fd = parser.argument<long>(i);
- if (fd < 1) {
- cerr << boost::format(_("Invalid host communication "
- "filedescriptor %d\n")) % fd << endl;
- exit(EXIT_FAILURE);
- }
- player.setControlFD ( fd );
- break;
- }
+ const std::string& fds = parser.argument(i);
+ fds.find(":");
+ int hostfd = 0, controlfd = 0;
+ hostfd = strtol(fds.substr(0, fds.find(":")).c_str(),
NULL, 0);
+ std::string csub = fds.substr(fds.find(":")+1, fds.size());
+ controlfd = strtol(csub.c_str(), 0, 0);
+ gnash::log_debug(_("Host FD #%d, Control FD #%d\n"),
+ hostfd, controlfd);
+ if (hostfd < 0) {
+ cerr << boost::format(_("Invalid host communication "
+ "filedescriptor %d\n"))
+ % hostfd << endl;
+ exit(EXIT_FAILURE);
+ }
+ player.setHostFD (hostfd);
+
+ if (controlfd < 1) {
+ cerr << boost::format(_("Invalid control communication
"
+ "filedescriptor %d\n")) % controlfd <<
endl;
+// exit(EXIT_FAILURE);
+ controlfd = hostfd + 1;
+ }
+ player.setControlFD (controlfd);
+ }
+ break;
case 'j':
widthGiven = true;
player.setWidth(parser.argument<long>(i));
=== modified file 'libcore/movie_root.cpp'
--- a/libcore/movie_root.cpp 2010-04-16 14:44:15 +0000
+++ b/libcore/movie_root.cpp 2010-04-19 23:10:08 +0000
@@ -1968,35 +1968,9 @@
/// with complex urlOpenerFormats like:
/// firefox -remote 'openurl(%u)'
///
- ///
- /// NOTE: this escaping implementation is far from optimal, but
- /// I felt pretty in rush to fix the arbitrary command
- /// execution... we'll optimize if needed
- ///
- std::string safeurl = url.str();
- boost::replace_all(safeurl, "\\", "\\\\"); // escape backslashes
first
- boost::replace_all(safeurl, "'", "\\'"); // then single quotes
- boost::replace_all(safeurl, "\"", "\\\""); // double quotes
- boost::replace_all(safeurl, ";", "\\;"); // colons
- boost::replace_all(safeurl, " ", "\\ "); // spaces
- boost::replace_all(safeurl, ">", "\\>"); // output redirection
- boost::replace_all(safeurl, "<", "\\<"); // input redirection
- boost::replace_all(safeurl, "&", "\\&"); // background (sic)
- boost::replace_all(safeurl, "\n", "\\n"); // newline
- boost::replace_all(safeurl, "\r", "\\r"); // return
- boost::replace_all(safeurl, "\t", "\\t"); // tab
- boost::replace_all(safeurl, "|", "\\|"); // pipe
- boost::replace_all(safeurl, "`", "\\`"); // backtick
-
- boost::replace_all(safeurl, "(", "\\("); // subshell :'(
- boost::replace_all(safeurl, ")", "\\)"); //
- boost::replace_all(safeurl, "}", "\\}"); //
- boost::replace_all(safeurl, "{", "\\{"); //
-
- boost::replace_all(safeurl, "$", "\\$"); // variable expansions
-
+ std::string safeurl = url.encode(urlstr);
boost::replace_all(command, "%u", safeurl);
-
+
log_debug (_("Launching URL: %s"), command);
std::system(command.c_str());
return;
=== modified file 'plugin/npapi/callbacks.cpp'
--- a/plugin/npapi/callbacks.cpp 2010-04-15 20:13:21 +0000
+++ b/plugin/npapi/callbacks.cpp 2010-04-17 02:44:32 +0000
@@ -141,7 +141,7 @@
varname = NPVARIANT_TO_STRING(args[0]).UTF8Characters;
value = gpso->GetVariable(varname);
if (value == 0) {
- NPVARIANT_IS_NULL(*result);
+ NULL_TO_NPVARIANT(*result);
} else {
if (NPVARIANT_IS_DOUBLE(*value)) {
double num = NPVARIANT_TO_DOUBLE(*value);
@@ -382,7 +382,7 @@
GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)npobj;
-#if 0
+#if 1
static int counter = 0;
// log_error("%s: %d ; %d\n", __FUNCTION__, gpso->getControlFD(), counter);
INT32_TO_NPVARIANT(counter, *result);
=== modified file 'plugin/npapi/external.cpp'
--- a/plugin/npapi/external.cpp 2010-04-15 20:19:54 +0000
+++ b/plugin/npapi/external.cpp 2010-04-19 23:03:36 +0000
@@ -30,7 +30,9 @@
#include "npapi.h"
#include "npruntime.h"
#include "external.h"
+#include "plugin.h"
+#include <boost/algorithm/string/erase.hpp>
ExternalInterface::ExternalInterface ()
{
@@ -184,7 +186,6 @@
{
std::stringstream ss;
std::map<std::string, std::string>::iterator it;
- int index = 0;
ss << "<object>";
for (it = args.begin(); it != args.end(); ++it) {
@@ -195,9 +196,64 @@
return ss.str();
}
+// An invoke looks like this:
+// <invoke name=\"foobar\" returntype=\"xml\">
+// <arguments>
+// <string>barfoo</string>
+// <number>135.78</number>
+// </arguments>
+// </invoke>
+ExternalInterface::invoke_t *
+ExternalInterface::parseInvoke(const std::string &xml)
+{
+ if (xml.empty()) {
+ return 0;
+ }
+
+ ExternalInterface::invoke_t *invoke = new invoke_t;
+
+ std::string::size_type start = 0;
+ std::string::size_type end;
+ std::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 = parseArguments(tag);
+ }
+ }
+
+ return invoke;
+}
+
NPVariant *
ExternalInterface::parseXML(const std::string &xml)
{
+
NPVariant *value = (NPVariant *)NPN_MemAlloc(sizeof(NPVariant));
NULL_TO_NPVARIANT(*value);
=== modified file 'plugin/npapi/external.h'
--- a/plugin/npapi/external.h 2010-04-15 20:19:54 +0000
+++ b/plugin/npapi/external.h 2010-04-18 00:32:42 +0000
@@ -34,6 +34,12 @@
class ExternalInterface
{
public:
+ typedef struct {
+ std::string name;
+ std::string type;
+ std::vector<NPVariant *> args;
+ } invoke_t;
+
ExternalInterface ();
~ExternalInterface ();
@@ -54,6 +60,8 @@
std::string makeObject (std::map<std::string, std::string> &args);
NPVariant *parseXML(const std::string &xml);
+ invoke_t *parseInvoke(const std::string &xml);
+
std::map<std::string, NPVariant *> parseProperties(const std::string &xml);
std::vector<NPVariant *> parseArguments(const std::string &xml);
std::string convertNPVariant (const NPVariant *npv);
=== modified file 'plugin/npapi/plugin.cpp'
--- a/plugin/npapi/plugin.cpp 2010-04-15 20:19:54 +0000
+++ b/plugin/npapi/plugin.cpp 2010-04-19 23:01:59 +0000
@@ -62,8 +62,6 @@
<br>\
Compatible Shockwave Flash "FLASH_VERSION
-//#define WRITE_FILE
-
// 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
@@ -361,7 +359,7 @@
}
#ifdef ENABLE_SCRIPTABLE
- _scriptObject = NPNFuncs.createobject(_instance,
GnashPluginScriptObject::marshalGetNPClass());
+ _scriptObject = (GnashPluginScriptObject
*)NPNFuncs.createobject(_instance,
GnashPluginScriptObject::marshalGetNPClass());
#endif
#if defined(ENABLE_SCRIPTABLE) && defined(NETTEST)
// This is a network testing node switch. This is only used for testing the
@@ -384,8 +382,7 @@
if (ret == 0) {
log_debug("Connected to debug server on fd #%d", sockfd);
_controlfd = sockfd;
- GnashPluginScriptObject *gpso = (GnashPluginScriptObject
*)_scriptObject;
- gpso->setControlFD(_controlfd);
+ _scriptObject->setControlFD(_controlfd);
} else {
log_debug("Couldn't connect to debug server: %s", strerror(errno));
}
@@ -421,7 +418,7 @@
/// \brief Destructor
nsPluginInstance::~nsPluginInstance()
{
- log_debug("plugin instance destruction");
+// log_debug("plugin instance destruction");
if ( _ichanWatchId ) {
g_source_remove(_ichanWatchId);
@@ -496,6 +493,11 @@
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
///
@@ -556,7 +558,7 @@
return NS_PluginGetValue(aVariable, aValue);
}
-#if 1
+#if 0
// FIXME: debugging stuff, will be gone soon after I figure how this works
void myfunc(void */* param */)
{
@@ -602,27 +604,6 @@
log_debug("The full URL is %s", _swf_url);
-#ifdef WRITE_FILE
- size_t start, end;
- std::string fname;
- end = _swf_url.find(".swf", 0) + 4;
- start = _swf_url.rfind("/", end) + 1;
- fname = "/tmp/";
- fname += _swf_url.substr(start, end - start);
-
- log_debug("The Flash movie name is: %s", fname);
-
- _filefd = open(fname.c_str(),
- O_CREAT | O_WRONLY,
- S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
-
- if (_filefd < 0) {
- _filefd = open(fname.c_str(),
- O_TRUNC | O_WRONLY,
- S_IRUSR | S_IRGRP | S_IROTH);
- }
-#endif
-
if (!_swf_url.empty() && _window) {
startProc();
}
@@ -643,16 +624,6 @@
}
}
-#ifdef WRITE_FILE
- if (_filefd != -1) {
- if (close(_filefd) == -1) {
- perror("closing _filefd");
- } else {
- _filefd = -1;
- }
- }
-#endif
-
return NPERR_NO_ERROR;
}
@@ -675,9 +646,6 @@
nsPluginInstance::Write(NPStream* /*stream*/, int32_t /*offset*/, int32_t len,
void* buffer)
{
-#ifdef WRITE_FILE
- write(_filefd, buffer, len);
-#endif
int written = write(_streamfd, buffer, len);
return written;
}
@@ -686,12 +654,16 @@
nsPluginInstance::handlePlayerRequestsWrapper(GIOChannel* iochan,
GIOCondition cond, nsPluginInstance* plugin)
{
+ log_trace(__PRETTY_FUNCTION__);
+
return plugin->handlePlayerRequests(iochan, cond);
}
bool
nsPluginInstance::handlePlayerRequests(GIOChannel* iochan, GIOCondition cond)
{
+ log_trace(__PRETTY_FUNCTION__);
+
if ( cond & G_IO_HUP ) {
log_debug("Player request channel hang up");
// Returning false here will cause the "watch" to be removed. This
watch
@@ -703,15 +675,15 @@
assert(cond & G_IO_IN);
- log_debug("Checking player requests on fd #%d",
g_io_channel_unix_get_fd(iochan));
+ log_debug("Checking player requests on fd #%d",
+ g_io_channel_unix_get_fd(iochan));
do {
GError* error=NULL;
gchar* request;
gsize requestSize=0;
GIOStatus status = g_io_channel_read_line(iochan, &request,
- &requestSize, NULL, &error);
-
+ &requestSize, NULL, &error);
switch ( status ) {
case G_IO_STATUS_ERROR:
log_error(std::string("Error reading request line: ") +
error->message);
@@ -769,8 +741,7 @@
return false;
}
- log_debug("Asked to get URL '%s''", url);
- log_debug("In target '%s'", target);
+ log_debug("Asked to get URL '%s' in target %s", url, target);
NPN_GetURL(_instance, url, target);
return true;
@@ -943,17 +914,20 @@
}
std::stringstream pars;
- pars << "-x " << _window // X window ID to render into
- << " -j " << _width // Width of window
- << " -k " << _height // Height of window
- << " -F " << hostfd // Socket to send commands to
- << " -G " << controlfd; // Socket determining lifespan
- {
- std::string pars_str = pars.str();
- typedef boost::char_separator<char> char_sep;
- boost::tokenizer<char_sep> tok(pars_str, char_sep(" "));
- arg_vec.insert(arg_vec.end(), tok.begin(), tok.end());
+ pars << "-x " << _window // X window ID to render into
+ << " -j " << _width // Width of window
+ << " -k " << _height; // Height of window
+#if GNASH_PLUGIN_DEBUG > 1
+ pars << " -vv ";
+#endif
+ if ((hostfd > 0) && (controlfd)) {
+ pars << " -F " << hostfd // Socket to send commands to
+ << ":" << controlfd; // Socket determining lifespan
}
+ std::string pars_str = pars.str();
+ typedef boost::char_separator<char> char_sep;
+ boost::tokenizer<char_sep> tok(pars_str, char_sep(" "));
+ arg_vec.insert(arg_vec.end(), tok.begin(), tok.end());
for (std::map<std::string,std::string>::const_iterator it =
_params.begin(),
itEnd = _params.end(); it != itEnd; ++it) {
@@ -1020,8 +994,6 @@
{
// 0 For reading, 1 for writing.
int p2c_pipe[2];
- int c2p_pipe[2];
- int p2c_controlpipe[2];
int ret = pipe(p2c_pipe);
if (ret == -1) {
@@ -1030,12 +1002,15 @@
}
_streamfd = p2c_pipe[1];
+#if 0
+ int c2p_pipe[2];
ret = pipe(c2p_pipe);
if (ret == -1) {
log_error("ERROR: child to parent pipe() failed: " +
std::string(std::strerror(errno)));
}
+ int p2c_controlpipe[2];
ret = pipe(p2c_controlpipe);
if (ret == -1) {
log_error("ERROR: parent to child pipe() failed: " +
@@ -1043,20 +1018,22 @@
}
_controlfd = p2c_controlpipe[1];
+#endif
#ifdef ENABLE_SCRIPTABLE
- GnashPluginScriptObject *gpso = (GnashPluginScriptObject *)_scriptObject;
+ _scriptObject->createPipe();
+// _controlfd = _scriptObject->getReadFD();
+// _scriptObject->checkPipe();
#ifdef NETTEST
- gpso->setControlFD(_controlfd);
+ _scriptObject->setControlFD(_controlfd);
#endif
#endif
- /*
- Setup the command line for starting Gnash
- */
-
- std::vector<std::string> arg_vec = getCmdLine(c2p_pipe[1],
- p2c_controlpipe[0]);
+ // Setup the command line for starting Gnash
+
+ std::vector<std::string> arg_vec = getCmdLine(_scriptObject->getReadFD(),
+ _scriptObject->getWriteFD());
+
if (arg_vec.empty()) {
log_error("Failed to obtain command line parameters.");
return;
@@ -1068,9 +1045,7 @@
std::mem_fun_ref(&std::string::c_str));
args.push_back(0);
- /*
- Argument List prepared, now fork(), close file descriptors and execv()
- */
+ // Argument List prepared, now fork(), close file descriptors and execv()
_childpid = fork();
@@ -1089,7 +1064,7 @@
log_error("ERROR: p2c_pipe[0] close() failed: " +
std::string(strerror(errno)));
}
-
+#if 0
// we want to read from c2p pipe, so close write-fd1
ret = close (c2p_pipe[1]);
if (ret == -1) {
@@ -1098,15 +1073,10 @@
}
ret = close (p2c_controlpipe[0]); // close read descriptor
+#endif
log_debug("Forked successfully, child process PID is %d" , _childpid);
-
- GIOChannel* ichan = g_io_channel_unix_new(c2p_pipe[0]);
- g_io_channel_set_close_on_unref(ichan, true);
- _ichanWatchId = g_io_add_watch(ichan,
- (GIOCondition)(G_IO_IN|G_IO_HUP),
- (GIOFunc)handlePlayerRequestsWrapper,
this);
- g_io_channel_unref(ichan);
+
return;
}
@@ -1126,7 +1096,7 @@
// Close all of the browser's file descriptors that we just inherited
// (including p2c_pipe[0] that we just dup'd to fd 0), but obviously
// not the file descriptors that we want the child to use.
- int dontclose[] = {c2p_pipe[1], p2c_controlpipe[0]};
+ int dontclose[] = {_scriptObject->getReadFD(),
_scriptObject->getWriteFD()};
close_fds(dontclose);
// Start the desired executable and go away.
@@ -1208,13 +1178,27 @@
std::cerr << "ERROR: " << fmt.str() << std::endl;
}
+#if GNASH_PLUGIN_DEBUG > 1
void
processLog_debug(const boost::format& fmt)
{
-#if GNASH_PLUGIN_DEBUG > 1
std::cout << "DEBUG: " << fmt.str() << std::endl;
+}
+
+void
+processLog_trace(const boost::format& fmt)
+{
+ std::cout << "TRACE: " << fmt.str() << std::endl;
+}
+#else
+void
+processLog_debug(const boost::format& fmt)
+{ /* do nothing */ }
+
+void
+processLog_trace(const boost::format& fmt)
+{ /* do nothing */ }
#endif
-}
// Local Variables:
// mode: C++
=== modified file 'plugin/npapi/plugin.h'
--- a/plugin/npapi/plugin.h 2010-04-15 20:19:54 +0000
+++ b/plugin/npapi/plugin.h 2010-04-19 23:46:40 +0000
@@ -35,7 +35,7 @@
#endif
#ifndef HAVE_PRETTY_FUNCTION
- #define __PRETTY_FUNCTION__ __FUNCTION__
+# define __PRETTY_FUNCTION__ __FUNCTION__
#endif
/* Xlib/Xt stuff */
@@ -54,6 +54,7 @@
#include <boost/preprocessor/seq/for_each.hpp>
#include "pluginbase.h"
+#include "pluginScriptObject.h"
extern NPBool plugInitialized;
@@ -71,10 +72,13 @@
NPError GetValue(NPPVariable variable, void *value);
NPError SetWindow(NPWindow *aWindow);
+ /// Open a new stream. THis is called every time there is swf content.
NPError NewStream(NPMIMEType type, NPStream *stream, NPBool seekable,
uint16_t *stype);
+ /// Destroy the stream
NPError DestroyStream(NPStream * stream, NPError reason);
+ /// Can the stream be written to yet ?
int32_t WriteReady(NPStream *stream);
int32_t Write(NPStream *stream, int32_t offset, int32_t len, void *buffer);
#ifdef ENABLE_SCRIPTABLE
@@ -85,7 +89,6 @@
private:
void startProc();
std::vector<std::string> getCmdLine(int hostfd, int controlfd);
-
static bool handlePlayerRequestsWrapper(GIOChannel* iochan, GIOCondition
cond, nsPluginInstance* plugin);
bool handlePlayerRequests(GIOChannel* iochan, GIOCondition cond);
@@ -124,7 +127,7 @@
/// Name of the plugin instance element in the dom
std::string _name;
#ifdef ENABLE_SCRIPTABLE
- NPObject *_scriptObject;
+ GnashPluginScriptObject *_scriptObject;
#endif
const char* getCurrentPageURL() const;
@@ -145,6 +148,7 @@
// memory footprint down.
DSOEXPORT void processLog_error(const boost::format& fmt);
DSOEXPORT void processLog_debug(const boost::format& fmt);
+DSOEXPORT void processLog_trace(const boost::format& fmt);
/// This heap of steaming preprocessor code magically converts
/// printf-style statements into boost::format messages using templates.
@@ -161,10 +165,10 @@
/// This is a sequence of different log message types to be used in
/// the code. Append the name to log_ to call the function, e.g.
/// log_error, log_unimpl.
-#define LOG_TYPES (error) (debug)
+#define LOG_TYPES (error) (debug) (trace)
/// The preprocessor generates templates with 1..ARG_NUMBER
/// arguments.
-#define ARG_NUMBER 2
+#define ARG_NUMBER 4
#define LOG_TEMPLATES(z, n, data)\
template<BOOST_PP_ENUM_PARAMS(BOOST_PP_INC(n), typename T)>\
inline void log_##data(BOOST_PP_REPEAT(BOOST_PP_INC(n), TOKENIZE_ARGS, t)) \
=== modified file 'plugin/npapi/pluginScriptObject.cpp'
--- a/plugin/npapi/pluginScriptObject.cpp 2010-04-15 20:19:54 +0000
+++ b/plugin/npapi/pluginScriptObject.cpp 2010-04-19 23:03:02 +0000
@@ -28,6 +28,10 @@
#include <fcntl.h>
#include <cstring>
#include <cstdlib>
+#include <cstdio>
+#include <cerrno>
+#include <sys/types.h>
+#include <unistd.h>
#if defined(HAVE_WINSOCK_H) && !defined(__OS2__)
# include <winsock2.h>
# include <windows.h>
@@ -35,9 +39,12 @@
# include <io.h>
# include <ws2tcpip.h>
#else
+# include <sys/un.h>
# include <sys/ioctl.h>
# include <unistd.h>
# include <sys/select.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
#endif
#include "npapi.h"
#include "npruntime.h"
@@ -221,59 +228,46 @@
AddProperty("onbeforedeactivate", "unknown");
AddProperty("ondeactivate", "unknown");
-#if 0
- for (int i = 0; i < NUM_METHOD_IDENTIFIERS; i++) {
- SetProperty(pluginMethodIdentifiers[i], value);
- }
-
- // fill the method identifier array
- NPNFuncs.getstringidentifiers(pluginMethodIdentifierNames,
- NUM_METHOD_IDENTIFIERS,
- pluginMethodIdentifiers);
-#endif
-// NPIdentifier id = NPN_GetStringIdentifier("showFoobar");
-// NPInvokeFunctionPtr func = testfunc;
-// AddMethod(id, func);
-
- NPIdentifier id = NPN_GetStringIdentifier("SetVariable");
- AddMethod(id, SetVariableCallback);
-
- id = NPN_GetStringIdentifier("GetVariable");
- AddMethod(id, GetVariableCallback);
-
- id = NPN_GetStringIdentifier("GotoFrame");
- AddMethod(id, GotoFrame);
-
- id = NPN_GetStringIdentifier("IsPlaying");
- AddMethod(id, IsPlaying);
-
- id = NPN_GetStringIdentifier("LoadMovie");
- AddMethod(id, LoadMovie);
-
- id = NPN_GetStringIdentifier("Pan");
- AddMethod(id, Pan);
-
- id = NPN_GetStringIdentifier("PercentLoaded");
- AddMethod(id, PercentLoaded);
-
- id = NPN_GetStringIdentifier("Play");
- AddMethod(id, Play);
-
- id = NPN_GetStringIdentifier("Rewind");
- AddMethod(id, Rewind);
-
- id = NPN_GetStringIdentifier("SetZoomRect");
- AddMethod(id, SetZoomRect);
-
- id = NPN_GetStringIdentifier("StopPlay");
- AddMethod(id, StopPlay);
-
- id = NPN_GetStringIdentifier("Zoom");
- AddMethod(id, Zoom);
-
- id = NPN_GetStringIdentifier("TotalFrames");
- AddMethod(id, TotalFrames);
-
+ // Add the default methods
+ NPIdentifier id = NPN_GetStringIdentifier("SetVariable");
+ AddMethod(id, SetVariableCallback);
+
+ id = NPN_GetStringIdentifier("GetVariable");
+ AddMethod(id, GetVariableCallback);
+
+ id = NPN_GetStringIdentifier("GotoFrame");
+ AddMethod(id, GotoFrame);
+
+ id = NPN_GetStringIdentifier("IsPlaying");
+ AddMethod(id, IsPlaying);
+
+ id = NPN_GetStringIdentifier("LoadMovie");
+ AddMethod(id, LoadMovie);
+
+ id = NPN_GetStringIdentifier("Pan");
+ AddMethod(id, Pan);
+
+ id = NPN_GetStringIdentifier("PercentLoaded");
+ AddMethod(id, PercentLoaded);
+
+ id = NPN_GetStringIdentifier("Play");
+ AddMethod(id, Play);
+
+ id = NPN_GetStringIdentifier("Rewind");
+ AddMethod(id, Rewind);
+
+ id = NPN_GetStringIdentifier("SetZoomRect");
+ AddMethod(id, SetZoomRect);
+
+ id = NPN_GetStringIdentifier("StopPlay");
+ AddMethod(id, StopPlay);
+
+ id = NPN_GetStringIdentifier("Zoom");
+ AddMethod(id, Zoom);
+
+ id = NPN_GetStringIdentifier("TotalFrames");
+ AddMethod(id, TotalFrames);
+
};
// Constructor
@@ -282,6 +276,9 @@
{
// log_debug(__PRETTY_FUNCTION__);
initializeIdentifiers();
+
+ _sockfds[READFD] = 0;
+ _sockfds[WRITEFD] = 0;
}
// Constructor
@@ -290,27 +287,31 @@
{
// log_debug(__PRETTY_FUNCTION__);
initializeIdentifiers();
+
+ _sockfds[READFD] = 0;
+ _sockfds[WRITEFD] = 0;
}
// Destructor
GnashPluginScriptObject::~GnashPluginScriptObject()
{
- // log_debug(__PRETTY_FUNCTION__);
- // do nothing
+// log_debug(__PRETTY_FUNCTION__);
+// Should be automatically shutdown by GIO
+// closePipe();
}
// Marshal Functions
NPClass *
GnashPluginScriptObject::marshalGetNPClass()
{
- // log_debug(__PRETTY_FUNCTION__);
+// log_debug(__PRETTY_FUNCTION__);
return &GnashPluginScriptObjectClass;
}
NPObject *
GnashPluginScriptObject::marshalAllocate (NPP npp, NPClass */* aClass */)
{
- log_debug(__PRETTY_FUNCTION__);
+// log_debug(__PRETTY_FUNCTION__);
#if 0
GnashPluginScriptObject *npobj = reinterpret_cast<GnashPluginScriptObject
*>
(NPN_MemAlloc(sizeof(GnashPluginScriptObject)));
@@ -325,7 +326,7 @@
void
GnashPluginScriptObject::marshalDeallocate (NPObject *npobj)
{
- log_debug(__PRETTY_FUNCTION__);
+// log_debug(__PRETTY_FUNCTION__);
#if 0
NPN_MemFree(reinterpret_cast<void *>(npobj));
#else
@@ -336,7 +337,7 @@
void
GnashPluginScriptObject::marshalInvalidate (NPObject */* npobj */)
{
- log_debug(__PRETTY_FUNCTION__);
+// log_debug(__PRETTY_FUNCTION__);
// gpso->Invalidate();
}
@@ -692,14 +693,27 @@
iargs.push_back(str);
str = ei.makeInvoke("GetVariable", iargs);
+ log_debug("Trying to get a value for %s.", name);
+
+ NPVariant *value = 0;
size_t ret = writePlayer(controlfd, str);
if (ret != str.size()) {
- log_error("Couldn't send GetVariable request, network problems.");
- return false;
+ // 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.
+ if (name == "$version") {
+ value = (NPVariant *)NPN_MemAlloc(sizeof(NPVariant));
+ STRINGZ_TO_NPVARIANT(strdup("LNX 10,0,r999"), *value);
+ } else {
+ log_error("Couldn't send GetVariable request, network problems.");
+ }
+ return value;
}
// Have the read function allocate the memory
- NPVariant *value = 0;
const char *data = 0;
char *ptr = 0;
ptr = const_cast<char *>(data);
@@ -724,24 +738,37 @@
GnashPluginScriptObject::setControlFD(int x)
{
// log_debug("%s: %d", __FUNCTION__, x);
-
- controlfd = x;
+#if 0
+ if (_iochan == 0) {
+ _iochan[WRITEFD] = g_io_channel_unix_new(x);
+ }
+#endif
+ controlfd = x; // FIXME: this should go away
}
int
GnashPluginScriptObject::getControlFD()
{
- log_debug("getControlFD: %d", controlfd);
-
+// log_debug("getControlFD: %d", controlfd);
+
+#if 0
+ return g_io_channel_unix_get_fd (_iochan);
+#endif
return controlfd;
};
// Write to the standalone player over the control socket
int
+GnashPluginScriptObject::writePlayer(const std::string &data)
+{
+ return writePlayer(_sockfds[WRITEFD], data);
+}
+
+int
GnashPluginScriptObject::writePlayer(int fd, const std::string &data)
{
- log_debug(__PRETTY_FUNCTION__);
+// log_debug(__PRETTY_FUNCTION__);
// log_debug("Writing data: %s", data);
@@ -753,9 +780,15 @@
}
int
+GnashPluginScriptObject::writePlayer(const char *data, size_t length)
+{
+ return writePlayer(_sockfds[WRITEFD], data, length);
+}
+
+int
GnashPluginScriptObject::writePlayer(int fd, const char *data, size_t length)
{
- log_debug(__PRETTY_FUNCTION__);
+ // log_debug(__PRETTY_FUNCTION__);
if (fd > 2) {
return ::write(fd, data, length);
@@ -768,13 +801,27 @@
// Read the standalone player over the control socket
int
-GnashPluginScriptObject::readPlayer(int /* fd */, const std::string &/* data
*/)
-{
-// log_debug(__PRETTY_FUNCTION__);
-
-// return readPlayer(fd, data.c_str(), data.size());
-
- return -1;
+GnashPluginScriptObject::readPlayer(const std::string &data)
+{
+// log_debug(__PRETTY_FUNCTION__);
+
+ const char *ptr = data.c_str();
+ return readPlayer(_sockfds[READFD], &ptr, data.size());
+}
+
+int
+GnashPluginScriptObject::readPlayer(int fd, const std::string &data)
+{
+// log_debug(__PRETTY_FUNCTION__);
+
+ const char *ptr = data.c_str();
+ return readPlayer(fd, &ptr, data.size());
+}
+
+int
+GnashPluginScriptObject::readPlayer(const char **data, size_t length)
+{
+ return readPlayer(_sockfds[READFD], data, length);
}
int
@@ -791,7 +838,7 @@
struct timeval tval;
tval.tv_sec = 10;
tval.tv_usec = 0;
- log_debug("Waiting for data... ");
+ // log_debug("Waiting for data... ");
if (select(fd+1, &fdset, NULL, NULL, &tval)) {
// log_debug("There is data in the network");
#ifndef _WIN32
@@ -804,11 +851,11 @@
}
- log_debug("There are %d bytes in the network buffer", bytes);
// No data yet
if (bytes == 0) {
return 0;
}
+ log_debug("There are %d bytes in the network buffer", bytes);
char *buf = 0;
if (*data == 0) {
@@ -823,11 +870,222 @@
if (ret == bytes) {
*data = buf;
}
+
+ std::cout << buf << std::endl;
return ret;
}
return 0;
-}
+}
+
+
+// Close the socket
+bool
+GnashPluginScriptObject::closePipe(int fd)
+{
+// log_debug(__FUNCTION__);
+
+ if (fd > 0) {
+ ::shutdown(fd, SHUT_RDWR);
+ ::close(fd);
+ }
+
+ return true;
+}
+
+// Create a socket so we can talk to the player.
+bool
+GnashPluginScriptObject::createPipe()
+{
+ log_trace(__PRETTY_FUNCTION__);
+
+ if ((_sockfds[READFD] == 0) && (_sockfds[WRITEFD] == 0)) {
+ int ret = socketpair(AF_UNIX, SOCK_STREAM, 0, _sockfds);
+
+ if (ret == 0) {
+ // Set up the Glib IO Channel for reading from the plugin
+// log_debug("Read fd for socketpair is: %d", _sockfds[READFD]);
+
+ _iochan[READFD] = g_io_channel_unix_new(_sockfds[READFD]);
+ g_io_channel_set_close_on_unref(_iochan[READFD], true);
+ _watchid = g_io_add_watch(_iochan[READFD],
+ (GIOCondition)(G_IO_IN|G_IO_HUP),
+ (GIOFunc)handleInvokeWrapper, this);
+
+ // Set up the Glib IO Channel for writing to the plugin
+// log_debug("Write fd for socketpair is: %d", _sockfds[WRITEFD]);
+ _iochan[WRITEFD] = g_io_channel_unix_new(_sockfds[WRITEFD]);
+ g_io_channel_set_close_on_unref(_iochan[WRITEFD], true);
+ return true;
+ }
+ }
+
+#if 0
+ std::stringstream ss;
+ static int count = 0;
+ ss << "/tmp/gnash-" << getpid() << count++;
+
+ return createPipe(ss.str());
+#endif
+
+ return false;
+}
+
+#if 0
+bool
+GnashPluginScriptObject::createPipe(const std::string &name)
+{
+ log_debug(__PRETTY_FUNCTION__);
+
+ mode_t mode = S_IRUSR|S_IWUSR;
+ if (!name.empty()) {
+ int ret = mkfifo(name.c_str(), mode);
+ if (ret == 0) {
+ _sockfd = ::open(name.c_str(), O_RDWR|O_NONBLOCK, mode);
+ if (_sockfd < 0) {
+ log_error("Couldn't open the pipe: \"%s\"", strerror(errno));
+ }
+ } else {
+ log_error("Couldn't create fifo: s\n", strerror(errno));
+ }
+ }
+
+ _pipename = name;
+
+ return false;
+}
+#endif
+
+
+// Close the socketpair
+bool
+GnashPluginScriptObject::closePipe()
+{
+// log_debug(__FUNCTION__);
+
+ bool ret = closePipe(_sockfds[READFD]);
+ if (ret) {
+ ret = closePipe(_sockfds[WRITEFD]);
+ } else {
+ return false;
+ }
+
+ GError *error;
+ GIOStatus rstatus = g_io_channel_shutdown(_iochan[READFD], true, &error);
+ GIOStatus wstatus = g_io_channel_shutdown(_iochan[WRITEFD], true, &error);
+ if ((rstatus == G_IO_STATUS_NORMAL)
+ && (wstatus == G_IO_STATUS_NORMAL)) {
+ return true;
+ } else {
+ return false;
+ }
+
+ return false;
+}
+
+// Check the pipe to see if it's ready, ie... is gnash connected yet ?
+bool
+GnashPluginScriptObject::checkPipe()
+{
+ return checkPipe(_sockfds[WRITEFD]);
+}
+
+bool
+GnashPluginScriptObject::checkPipe(int fd)
+{
+// log_debug(__PRETTY_FUNCTION__);
+
+ fd_set fdset;
+
+ if (fd > 2) {
+ 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 false;
+ } else if (ret == 1) {
+ log_debug ("The pipe for #fd is ready", fd);
+ controlfd = fd;
+ return true;
+ } else {
+ log_error("The pipe has this error: %s", strerror(errno));
+ }
+ }
+
+ return false;
+}
+
+bool
+GnashPluginScriptObject::handleInvoke(GIOChannel *iochan, GIOCondition cond)
+{
+ log_trace(__PRETTY_FUNCTION__);
+
+ if ( cond & G_IO_HUP ) {
+ log_debug("Player request 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.
+ _watchid = 0;
+ return false;
+ }
+
+ assert(cond & G_IO_IN);
+
+ log_debug("Checking player requests on fd #%d",
+ g_io_channel_unix_get_fd(iochan));
+
+ do {
+ GError* error=NULL;
+ gchar* request;
+ gsize requestSize=0;
+ GIOStatus status = g_io_channel_read_line(iochan, &request,
+ &requestSize, NULL, &error);
+
+ switch ( status ) {
+ case G_IO_STATUS_ERROR:
+ log_error("Error reading request line: %s", error->message);
+
+ g_error_free(error);
+ return false;
+ case G_IO_STATUS_EOF:
+ log_error("EOF (error: %s", error->message);
+ return false;
+ case G_IO_STATUS_AGAIN:
+ log_error("Read again(error: %s", error->message);
+ break;
+ case G_IO_STATUS_NORMAL:
+ // process request
+ log_debug("Normal read: %s" + std::string(request));
+ break;
+ default:
+ log_error("Abnormal status!");
+ return false;
+
+ }
+
+ // process request..
+ processPlayerRequest(request, requestSize);
+ g_free(request);
+
+ } while (g_io_channel_get_buffer_condition(iochan) & G_IO_IN);
+
+ return true;
+}
+
+bool
+GnashPluginScriptObject::handleInvokeWrapper(GIOChannel *iochan,
+ GIOCondition cond,
+ GnashPluginScriptObject* plugin)
+{
+ log_trace(__PRETTY_FUNCTION__);
+
+ return plugin->handleInvoke(iochan, cond);
+}
// local Variables:
// mode: C++
=== modified file 'plugin/npapi/pluginScriptObject.h'
--- a/plugin/npapi/pluginScriptObject.h 2010-04-15 20:19:54 +0000
+++ b/plugin/npapi/pluginScriptObject.h 2010-04-18 00:35:41 +0000
@@ -16,9 +16,7 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
-#ifdef HAVE_CONFIG_H
-#include "gnashconfig.h"
-#endif
+#include <glib.h>
// Test:
// Use browser to open plugin/scriptable-test.html.
@@ -44,6 +42,9 @@
#include "npapi.h"
#include "npruntime.h"
+#define READFD 0
+#define WRITEFD 1
+
class GnashPluginScriptObject : public NPObject
{
public:
@@ -102,12 +103,30 @@
/// @return the value as returned by the standalone player
NPVariant *GetVariable(const std::string &name);
+ // Create a socketpair so we can talk to the player.
+ bool createPipe();
+
+ // Close the socket
+ bool closePipe();
+ bool closePipe(int fd);
+
+ // Check the pipe to see if it's ready, ie... is gnash connected yet ?
+ bool checkPipe();
+ bool checkPipe(int fd);
+
+ int getReadFD() { return _sockfds[READFD]; };
+ int getWriteFD() { return _sockfds[WRITEFD]; };
+
// Write to the standalone player over the control socket
+ int writePlayer(const char *data, size_t length);
int writePlayer(int fd, const char *data, size_t length);
+ int writePlayer(const std::string &data);
int writePlayer(int fd, const std::string &data);
// Read the standalone player over the control socket
+ int readPlayer(const char **data, size_t length);
int readPlayer(int fd, const char **data, size_t length);
+ int readPlayer(const std::string &data);
int readPlayer(int fd, const std::string &data);
protected:
@@ -130,20 +149,41 @@
bool Enumerate(NPIdentifier **identifier, uint32_t *count);
bool Construct(const NPVariant *data, uint32_t argCount, NPVariant
*result);
+ bool handleInvoke(GIOChannel* iochan, GIOCondition cond);
+ /// Process a null-terminated request line
+ //
+ /// @param buf
+ /// The single request.
+ /// Caller is responsible for memory management, but give us
+ /// permission to modify the string.
+ ///
+ /// @param len
+ /// Lenght of buffer.
+ ///
+ /// @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);
+
void initializeIdentifiers();
void setInstance(NPP inst) { _nppinstance = inst; };
// _nppinstance->pdata should be the nsPluginInstance once NPP_New() is
finished.
- NPP _nppinstance;
-
+ NPP _nppinstance;
std::map<NPIdentifier, NPVariant *> _properties;
std::map<NPIdentifier, NPInvokeFunctionPtr> _methods;
- // int _control;
+ // 0 for reading, 1 for writing
+ int _sockfds[2];
+ GIOChannel *_iochan[2];
+ // ID to watch the read channel from the player
+ int _watchid;
};
-#endif /* GNASH_PLUGIN_SCRIPT_OBJECT_H */
+#endif // GNASH_PLUGIN_SCRIPT_OBJECT_H
// local Variables:
// mode: C++
=== modified file 'plugin/npapi/scriptable-test.html'
--- a/plugin/npapi/scriptable-test.html 2010-04-15 20:19:54 +0000
+++ b/plugin/npapi/scriptable-test.html 2010-04-19 15:38:17 +0000
@@ -1,282 +1,245 @@
<html>
<head>
- <title>Scriptable Plugin Test</title>
+ <title>Gnash: Scriptable Plugin Test</title>
+ <style type="text/css" media="screen">
+ body, * {font-family:sans-serif;}
+ h1 {text-align:center;}
+ #content {}
+ #test-actions {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+ }
+ p {font-family: monospace;}
+ #log {
+ font-family: monospace;
+ width: 800px;
+ float:right;
+ }
+ #log p {
+ margin: 0;
+ border-bottom:1px solid gray;
+ }
+ #log h2 a {
+ font-style: italic;
+ font-weight:normal;
+ font-size:12px;
+ }
+ </style>
</head>
<body>
-
- <center>
- <h1> Scriptable Plugin </h1>
- </center>
-
- <br><br>
-
- <center>
-
- <embed type="application/x-shockwave-flash" width=1 height=1
hidden="true"><br>
+ <h1>Scriptable Plugin testbed</h1>
+ <div id="log">
+ <h2>Log <a href="#" onclick="clearLog(); return false;">Clear</a></h2>
- <script>
+ </div>
+ <div id="content">
+
+ <embed type="application/x-shockwave-flash" width="1" height="1"
hidden="true">
+
+ <ul id="test-actions">
+ <li><button onclick='ShowVersion()'>Show Version</button></li>
+ <li><button onclick='ShowFoobar("barfood")'>Show Foobar</button></li>
+ <li><button onclick='FlashSetVariable("var1",
"value1")'>SetVariable</button></li>
+ <li><button onclick='FlashGetVariable("var1")'>GetVariable</button></li>
+ <li><button onclick='FlashGotoFrame(123)'>GotoFrame</button></li>
+ <li><button onclick='FlashIsPlaying()'>IsPlaying</button></li>
+ <li><button onclick='FlashLoadMovie(2, "bogus")'>LoadMovie</button></li>
+ <li><button onclick='FlashPan(1, 2, 0)'>Pan</button></li>
+ <li><button onclick='FlashPercentLoaded()'>PercentLoaded</button></li>
+ <li><button onclick='FlashPlay()'>Play</button></li>
+ <li><button onclick='FlashRewind()'>Rewind</button></li>
+ <li><button onclick='FlashSetZoomRect(1, 2, 3,
4)'>SetZoomRect</button></li>
+ <li><button onclick='FlashStopPlay()'>StopPlay</button></li>
+ <li><button onclick='FlashZoom(12)'>Zoom</button></li>
+ <li><button onclick='FlashTotalFrames()'>TotalFrames</button></li>
+ </ul>
+
+</div>
+
+ <script type="text/javascript">
var embed = document.embeds[0];
-
- function ShowVersion()
- {
- document.write("Codebase = = " + embed.codebase + "<br>");
- document.write("Classid = " + embed.classid + "<br>");
- document.write("Pluginspage = " + embed.pluginspage + "<br>");
- document.write("Src = " + embed.src + "<br>");
- document.write("BG Color = " + embed.bgcolor + "<br>");
- document.write("Quality = " + embed.quality + "<br>");
- document.write("movie = " + embed.movie + "<br>");
- // document.write("onafterupdate = " + embed.onafterupdate + "<br>");
- // document.write("onbeforeupdate = " + embed.onbeforeupdate +
"<br>");
- // document.write("onblur = " + embed.onblur + "<br>");
- // document.write("oncellchange = " + embed.oncellchange + "<br>");
- // document.write("onclick = " + embed.onclick + "<br>");
- // document.write("ondblClick = " + embed.ondblClick + "<br>");
- // document.write("ondrag = " + embed.ondrag + "<br>");
- // document.write("ondragend = " + embed.ondragend + "<br>");
- // document.write("ondragenter = " + embed.ondragenter + "<br>");
- // document.write("ondragleave = " + embed.ondragleave + "<br>");
- // document.write("ondragover = " + embed.ondragover + "<br>");
- // document.write("ondrop = " + embed.ondrop + "<br>");
- // document.write("onfinish = " + embed.onfinish + "<br>");
- // document.write("onfocus = " + embed.onfocus + "<br>");
- // document.write("onhelp = " + embed.onhelp + "<br>");
- // document.write("onmousedown = " + embed.onmousedown + "<br>");
- // document.write("onmouseup = " + embed.onmouseup + "<br>");
- // document.write("onmouseover = " + embed.onmouseover + "<br>");
- // document.write("onmousemove = " + embed.onmousemove + "<br>");
- // document.write("onmouseout = " + embed.onmouseout + "<br>");
- // document.write("onkeypress = " + embed.onkeypress + "<br>");
- // document.write("onkeydown = " + embed.onkeydown + "<br>");
- // document.write("onkeyup = " + embed.onkeyup + "<br>");
- // document.write("onload = " + embed.onload + "<br>");
- // document.write("onlosecapture = " + embed.onlosecapture + "<br>");
- // document.write("onpropertychange = " + embed.onpropertychange +
"<br>");
- // document.write("onreadystatechange = " + embed.onreadystatechange
+ "<br>");
- // document.write("onrowsdelete = " + embed.onrowsdelete + "<br>");
- // document.write("onrowenter = " + embed.onrowenter + "<br>");
- // document.write("onrowexit = " + embed.onrowexit + "<br>");
- // document.write("onrowsinserted = " + embed.onrowsinserted +
"<br>");
- // document.write("onstart = " + embed.onstart + "<br>");
- // document.write("onscroll = " + embed.onscroll + "<br>");
- // document.write("onbeforeeditfocus = " + embed.onbeforeeditfocus +
"<br>");
- // document.write("onactivate = " + embed.onactivate) + "<br>";
- // document.write("onbeforedeactivate = " + embed.onbeforedeactivate
+ "<br>");
- // document.write("ondeactivate = " + embed.ondeactivate + "<br>");
- document.write("type = " + embed.type + "<br>");
- document.write("id = " + embed.id + "<br>");
- document.write("width = " + embed.width + "<br>");
- document.write("height = " + embed.height + "<br>");
- document.write("align = " + embed.align + "<br>");
- document.write("vspace", + embed.vspace + "<br>");
- document.write("hspace = " + embed.hspace + "<br>");
- document.write("class = " + embed.class + "<br>");
- document.write("title = " + embed.title + "<br>");
- document.write("accesskey = " + embed.accesskey + "<br>");
- document.write("name = " + embed.name + "<br>");
- document.write("tabindex = " + embed.tabindex + "<br>");
- document.write("FlashVars = " + embed.FlashVars + "<br>");
-
- alert(embed.version);
-}
-
-function FlashSetVariable(name, value)
-{
- embed.SetVariable(name, value);
-// alert("FlashSetVariable");
-}
-
-function FlashGetVariable(name)
-{
- var value = embed.GetVariable(name);
-// document.write("Got Variable = " + value + "<br>");
- alert(value);
-}
-
-function FlashGotoFrame(num)
-{
- embed.GotoFrame(num);
-// document.write("GotoFrame<br>");
-// alert(value);
-}
-
-function FlashIsPlaying()
-{
- var value = embed.IsPlaying();
-// document.write("IsPlaying() = " + value + "<br>");
- alert(value);
-}
-
-function FlashLoadMovie(layer, name)
-{
- embed.LoadMovie(layer, name);
-// document.write("LoadMovie()<br>");
-// alert("FlashLoadMovie");
-}
-
-function FlashPan(x, y, mode)
-{
- embed.Pan(x, y, mode);
-// document.write("Pan()<br>");
-// alert("FlashPan");
-}
-
-function FlashPercentLoaded()
-{
- var value = embed.PercentLoaded();
-// document.write("PercentLoaded() = " + value + "<br>");
- alert(value);
-}
-
-function FlashPlay()
-{
- embed.Play();
-// document.write("Play()<br>");
-// alert("FlashPlay");
-}
-
-function FlashRewind()
-{
- embed.Rewind();
-// document.write("Rewind()<br>");
-// alert("FlashRewind");
-}
-
-function FlashSetZoomRect(left, top, right, bottom)
-{
- embed.SetZoomRect(left, top, right, bottom);
-// document.write("SetZoomRect()<br>");
-// alert("FlashSetZoomRect");
-}
-
-function FlashStopPlay()
-{
- embed.StopPlay();
-// document.write("StopPlay()<br>");
-// alert("FlashStopPlay");
-}
-
-function FlashZoom(zoom)
-{
- embed.Zoom(zoom);
-// document.write("Zoom()<br>");
-// alert("FlashZoom");
-}
-
-function FlashTotalFrames()
-{
- var value = embed.TotalFrames();
-// document.write("TotalFrames() = " + value + "<br>");
- alert(value);
-}
-
-function ShowFoobar(msg)
-{
- document.write(embed.SetVariable("foo", "bar") + "<br>");
- document.write(embed.SetVariable("fuby", 1.1) + "<br>");
- document.write(embed.GetVariable("foo") + "<br>");
-
- alert(embed.showFoobar(msg));
-}
+ function clearLog() {
+ var log = document.getElementById("log");
+ log.innerHTML = '<h2>Log <a href="#" onclick="clearLog(); return
false;">Clear</a></h2>';
+ }
+ function addLog(str) {
+ var p = document.createElement("P");
+ p.innerHTML = str;
+ var log = document.getElementById("log");
+ log.appendChild(p);
+ }
+
+ function ShowVersion() {
+ var v = '';
+ v += "Codebase = " + embed.codebase + "<br>";
+ v += "Classid = " + embed.classid + "<br>";
+ v += "Plugins page = " + embed.pluginspage + "<br>";
+ v += "Src = " + embed["src"] + "<br>";
+ v += "BG Color = " + embed.bgcolor + "<br>";
+ v += "Quality = " + embed.quality + "<br>";
+ v += "movie = " + embed.movie + "<br>";
+ // v += "onafterupdate = " + embed.onafterupdate + "<br>";
+ // v += "onbeforeupdate = " + embed.onbeforeupdate + "<br>";
+ // v += "onblur = " + embed.onblur + "<br>";
+ // v += "oncellchange = " + embed.oncellchange + "<br>";
+ // v += "onclick = " + embed.onclick + "<br>";
+ // v += "ondblClick = " + embed.ondblClick + "<br>";
+ // v += "ondrag = " + embed.ondrag + "<br>";
+ // v += "ondragend = " + embed.ondragend + "<br>";
+ // v += "ondragenter = " + embed.ondragenter + "<br>";
+ // v += "ondragleave = " + embed.ondragleave + "<br>";
+ // v += "ondragover = " + embed.ondragover + "<br>";
+ // v += "ondrop = " + embed.ondrop + "<br>";
+ // v += "onfinish = " + embed.onfinish + "<br>";
+ // v += "onfocus = " + embed.onfocus + "<br>";
+ // v += "onhelp = " + embed.onhelp + "<br>";
+ // v += "onmousedown = " + embed.onmousedown + "<br>";
+ // v += "onmouseup = " + embed.onmouseup + "<br>";
+ // v += "onmouseover = " + embed.onmouseover + "<br>";
+ // v += "onmousemove = " + embed.onmousemove + "<br>";
+ // v += "onmouseout = " + embed.onmouseout + "<br>";
+ // v += "onkeypress = " + embed.onkeypress + "<br>";
+ // v += "onkeydown = " + embed.onkeydown + "<br>";
+ // v += "onkeyup = " + embed.onkeyup + "<br>";
+ // v += "onload = " + embed.onload + "<br>";
+ // v += "onlosecapture = " + embed.onlosecapture + "<br>";
+ // v += "onpropertychange = " + embed.onpropertychange + "<br>";
+ // v += "onreadystatechange = " + embed.onreadystatechange +
"<br>";
+ // v += "onrowsdelete = " + embed.onrowsdelete + "<br>";
+ // v += "onrowenter = " + embed.onrowenter + "<br>";
+ // v += "onrowexit = " + embed.onrowexit + "<br>";
+ // v += "onrowsinserted = " + embed.onrowsinserted + "<br>";
+ // v += "onstart = " + embed.onstart + "<br>";
+ // v += "onscroll = " + embed.onscroll + "<br>";
+ // v += "onbeforeeditfocus = " + embed.onbeforeeditfocus +
"<br>";
+ // v += "onactivate = " + embed.onactivate + "<br>";
+ // v += "onbeforedeactivate = " + embed.onbeforedeactivate +
"<br>";
+ // v += "ondeactivate = " + embed.ondeactivate + "<br>";
+
+ v += "type = " + embed.type + "<br>";
+ v += "id = " + embed.id + "<br>";
+ v += "width = " + embed.width + "<br>";
+ v += "height = " + embed.height + "<br>";
+ v += "align = " + embed.align + "<br>";
+ v += "vspace = " + embed.vspace + "<br>";
+ v += "hspace = " + embed.hspace + "<br>";
+ v += "class = " + embed["class"] + "<br>";
+ v += "title = " + embed.title + "<br>";
+ v += "accesskey = " + embed.accesskey + "<br>";
+ v += "name = " + embed.name + "<br>";
+ v += "tabindex = " + embed.tabindex + "<br>";
+ v += "FlashVars = " + embed.FlashVars + "<br>";
+
+ addLog('Found version is:' + embed.version);
+ addLog(v);
+
+ }
+
+ function FlashSetVariable(name, value)
+ {
+ embed.SetVariable(name, value);
+ // addLog("FlashSetVariable");
+ }
+
+ function FlashGetVariable(name)
+ {
+ var value = embed.GetVariable(name);
+ // addLog("Got Variable = " + value);
+ addLog(value);
+ }
+
+ function FlashGotoFrame(num)
+ {
+ embed.GotoFrame(num);
+ // addLog("GotoFrame<br>");
+ // addLog(value);
+ }
+
+ function FlashIsPlaying()
+ {
+ var value = embed.IsPlaying();
+ // addLog("IsPlaying() = " + value);
+ addLog(value);
+ }
+
+ function FlashLoadMovie(layer, name)
+ {
+ embed.LoadMovie(layer, name);
+ // addLog("LoadMovie()<br>");
+ // addLog("FlashLoadMovie");
+ }
+
+ function FlashPan(x, y, mode)
+ {
+ embed.Pan(x, y, mode);
+ // addLog("Pan()<br>");
+ // addLog("FlashPan");
+ }
+
+ function FlashPercentLoaded()
+ {
+ var value = embed.PercentLoaded();
+ // addLog("PercentLoaded() = " + value);
+ addLog(value);
+ }
+
+ function FlashPlay()
+ {
+ embed.Play();
+ // addLog("Play()<br>");
+ // addLog("FlashPlay");
+ }
+
+ function FlashRewind()
+ {
+ embed.Rewind();
+ // addLog("Rewind()<br>");
+ // addLog("FlashRewind");
+ }
+
+ function FlashSetZoomRect(left, top, right, bottom)
+ {
+ embed.SetZoomRect(left, top, right, bottom);
+ // addLog("SetZoomRect()<br>");
+ // addLog("FlashSetZoomRect");
+ }
+
+ function FlashStopPlay()
+ {
+ embed.StopPlay();
+ // addLog("StopPlay()<br>");
+ // addLog("FlashStopPlay");
+ }
+
+ function FlashZoom(zoom)
+ {
+ embed.Zoom(zoom);
+ // addLog("Zoom()<br>");
+ // addLog("FlashZoom");
+ }
+
+ function FlashTotalFrames()
+ {
+ var value = embed.TotalFrames();
+ // addLog("TotalFrames() = " + value);
+ addLog(value);
+ }
+
+ function ShowFoobar(msg)
+ {
+ addLog(embed.SetVariable("foo", "bar"));
+ addLog(embed.SetVariable("fuby", 1.1));
+ addLog(embed.GetVariable("foo"));
+ if (typeof embed.showFoobar === 'function') {
+ addLog('Running embed.showFoobar("'+msg+'")');
+ addLog(embed.showFoobar(msg));
+ } else {
+ addLog("Quitting: embed.showFoobar is not a function. Tried
running embed.showFoobar('"+msg+"')");
+ }
+ }
</script>
-<br>
-<form name="form1">
-<input type=button value="Show Version" onclick='ShowVersion()'>
-</form>
-<br>
-
-<form name="form2">
-<input type=button value="Show Foobar" onclick='ShowFoobar("barfood")'>
-</form>
-
-</center>
-
-<div id="main">
-<table>
- <tr><td>
- <form name="form3">
- <input type=button value="SetVariable"
onclick='FlashSetVariable("var1", "value1")'>
- </form>
- </td>
-
- <td>
- <form name="form4">
- <input type=button value="GetVariable"
onclick='FlashGetVariable("var1")'>
- </form>
- </td>
-
- <td>
- <form name="form5">
- <input type=button value="GotoFrame" onclick='FlashGotoFrame(123)'>
- </form>
- </td>
-
- <td>
- <form name="form6">
- <input type=button value="IsPlaying" onclick='FlashIsPlaying()'>
- </form>
- </td>
-
- <td>
- <form name="form7">
- <input type=button value="LoadMovie" onclick='FlashLoadMovie(2,
"bogus")'>
- </form>
- </td>
-
- <td>
- <form name="form8">
- <input type=button value="Pan" onclick='FlashPan(1, 2, 0)'>
- </form>
-
- </td>
-
- <td>
- <form name="form9">
- <input type=button value="PercentLoaded"
onclick='FlashPercentLoaded()'>
- </form>
- </td>
-
- </tr><tr>
-
- <td>
- <form name="form10">
- <input type=button value="Play" onclick='FlashPlay()'>
- </form>
- </td>
-
- <td>
- <form name="form11">
- <input type=button value="Rewind" onclick='FlashRewind()'>
- </form>
- </td>
-
- <td>
- <form name="form12">
- <input type=button value="SetZoomRect" onclick='FlashSetZoomRect(1, 2,
3, 4)'>
- </form>
-
- </td>
-
- <td>
- <form name="form13">
- <input type=button value="StopPlay" onclick='FlashStopPlay()'>
- </form>
- </td>
-
- <td>
- <form name="form14">
- <input type=button value="Zoom" onclick='FlashZoom(12)'>
- </form>
- </td>
-
- <td>
- <form name="form15">
- <input type=button value="TotalFrames" onclick='FlashTotalFrames()'>
- </form>
- </td></tr>
-</table>
-</div>
</body>
</html>
=== modified file 'plugin/npapi/test.cpp'
--- a/plugin/npapi/test.cpp 2010-04-15 20:19:54 +0000
+++ b/plugin/npapi/test.cpp 2010-04-18 00:32:42 +0000
@@ -265,6 +265,21 @@
} else {
runtest.fail("ExternalInterface::parseArguments()");
}
+
+ // 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);
+ str = NPVARIANT_TO_STRING(*invoke->args[0]).UTF8Characters;
+ if ((invoke->name == "barbyfoo") && (invoke->type == "xml")
+ && (NPVARIANT_IS_STRING(*invoke->args[0]))
+ && (str == "barfoo")
+ && (NPVARIANT_IS_DOUBLE(*invoke->args[1]))
+ && (NPVARIANT_TO_DOUBLE(*invoke->args[1]) == 135.78)
+ ) {
+ runtest.pass("ExternalInterface::parseInvoke()");
+ } else {
+ runtest.fail("ExternalInterface::parseInvoke()");
+ }
}
// We have to implement these two memory allocation functions as
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] /srv/bzr/gnash/trunk r12162: partial scriptable support. fixes Go Upgrade YouTube problem.,
Rob Savoye <=