2 // Copyright (C) 2010, 2011, 2012, 2014, 2016 Free Software Foundation, Inc
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 3 of the License, or
7 // (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "gnashconfig.h"
25 #if defined(HAVE_WINSOCK_H) && !defined(__OS2__)
26 # include <winsock2.h>
28 # include <sys/stat.h>
30 # include <ws2tcpip.h>
32 # include <sys/ioctl.h>
37 #include "npruntime.h"
39 #include "callbacks.h"
41 #include "pluginScriptObject.h"
43 extern NPNetscapeFuncs NPNFuncs
;
47 // NPClass of GnashPluginScriptObject
48 static NPClass GnashPluginScriptObjectClass
= {
49 NP_CLASS_STRUCT_VERSION
,
50 GnashPluginScriptObject::marshalAllocate
,
51 GnashPluginScriptObject::marshalDeallocate
,
52 GnashPluginScriptObject::marshalInvalidate
,
53 GnashPluginScriptObject::marshalHasMethod
,
54 GnashPluginScriptObject::marshalInvoke
,
55 GnashPluginScriptObject::marshalInvokeDefault
,
56 GnashPluginScriptObject::marshalHasProperty
,
57 GnashPluginScriptObject::marshalGetProperty
,
58 GnashPluginScriptObject::marshalSetProperty
,
59 GnashPluginScriptObject::marshalRemoveProperty
,
60 GnashPluginScriptObject::marshalEnumerate
,
61 GnashPluginScriptObject::marshalConstruct
65 printNPVariant(const NPVariant
*value
)
67 if (NPVARIANT_IS_DOUBLE(*value
)) {
68 double num
= NPVARIANT_TO_DOUBLE(*value
);
69 log_debug("is double, value %g", num
);
70 } else if (NPVARIANT_IS_STRING(*value
)) {
71 std::string str
= NPStringToString(NPVARIANT_TO_STRING(*value
));
72 log_debug("is string, value %s", str
);
73 } else if (NPVARIANT_IS_BOOLEAN(*value
)) {
74 bool flag
= NPVARIANT_TO_BOOLEAN(*value
);
75 log_debug("is boolean, value %d", flag
);
76 } else if (NPVARIANT_IS_INT32(*value
)) {
77 int num
= NPVARIANT_TO_INT32(*value
);
78 log_debug("is int, value %d", num
);
79 } else if (NPVARIANT_IS_NULL(*value
)) {
80 log_debug("value is null");
81 } else if (NPVARIANT_IS_VOID(*value
)) {
82 log_debug("value is void");
83 } else if (NPVARIANT_IS_OBJECT(*value
)) {
84 log_debug("value is object");
89 // The methods for GnashPluginScriptObject start here.
93 GnashPluginScriptObject::AddProperty(const std::string
&name
,
94 const std::string
&val
)
96 NPIdentifier id
= NPN_GetStringIdentifier(name
.c_str());
99 STRINGN_TO_NPVARIANT(val
.c_str(), static_cast<int>(val
.size()), strvar
);
100 SetProperty(id
, strvar
);
104 GnashPluginScriptObject::AddProperty(const std::string
&name
, double num
)
106 NPIdentifier id
= NPN_GetStringIdentifier(name
.c_str());
108 DOUBLE_TO_NPVARIANT(num
, value
);
109 SetProperty(id
, value
);
113 GnashPluginScriptObject::AddProperty(const std::string
&name
, int num
)
115 NPIdentifier id
= NPN_GetStringIdentifier(name
.c_str());
117 INT32_TO_NPVARIANT(num
, value
);
118 SetProperty(id
, value
);
121 // Sets up the property and method identifier arrays used by the browser
122 // via the hasProperty and hasMethod fuction pointers
124 GnashPluginScriptObject::initializeIdentifiers()
126 // log_debug("initializeIdentifiers");
128 // NPN_Status(nppinstance, __FUNCTION__);
130 // http://www.adobe.com/support/flash/publishexport/scriptingwithflash/scriptingwithflash_04.html
132 // We maintain an internal property for our version number, rather
133 // than asking the player.
134 AddProperty("$version", "10,1,r999");
135 // id and name appear to be the same tag, but differeing browsers access
136 // one or the other, or both.
137 // name=send_this_page_swf
138 AddProperty("name", "Hello World");
139 // id=send_this_page_swf
140 AddProperty("id", "Hello World");
142 // http://s.ytimg.com/yt/swf/watch-vfl161193.swf
143 AddProperty("src", "example");
144 AddProperty("align", "middle");
145 AddProperty("quality", "high");
146 AddProperty("bgcolor", "#FFFFFF");
147 AddProperty("allowScriptAccess", "sameDomain");
148 AddProperty("type", "application/x-shockwave-flash");
149 AddProperty("codebase", "http://www.getgnash.org");
150 AddProperty("pluginspage", "http://www.getgnash.org");
152 AddProperty("classid", "2b70f2b1-fc72-4734-bb81-4eb2a7713e49");
153 AddProperty("movie", "unknown");
154 AddProperty("width", 0);
155 AddProperty("height", 0);
156 AddProperty("vspace", 0);
157 AddProperty("hspace", 0);
158 AddProperty("class", "class unknown");
159 AddProperty("title", "title unknown");
160 AddProperty("accesskey", 0);
161 AddProperty("name", "name unknown");
162 AddProperty("tabindex", 8);
163 AddProperty("FlashVars", "flashVars unknown");
165 // Javascript and flash events
166 AddProperty("onafterupdate", "unknown");
167 AddProperty("onbeforeupdate", "unknown");
168 AddProperty("onblur", "unknown");
169 AddProperty("oncellchange", "unknown");
170 AddProperty("onclick", "unknown");
171 AddProperty("ondblClick", "unknown");
172 AddProperty("ondrag", "unknown");
173 AddProperty("ondragend", "unknown");
174 AddProperty("ondragenter", "unknown");
175 AddProperty("ondragleave", "unknown");
176 AddProperty("ondragover", "unknown");
177 AddProperty("ondrop", "unknown");
178 AddProperty("onfinish", "unknown");
179 AddProperty("onfocus", "unknown");
180 AddProperty("onhelp", "unknown");
181 AddProperty("onmousedown", "unknown");
182 AddProperty("onmouseup", "unknown");
183 AddProperty("onmouseover", "unknown");
184 AddProperty("onmousemove", "unknown");
185 AddProperty("onmouseout", "unknown");
186 AddProperty("onkeypress", "unknown");
187 AddProperty("onkeydown", "unknown");
188 AddProperty("onkeyup", "unknown");
189 AddProperty("onload", "unknown");
190 AddProperty("onlosecapture", "unknown");
191 AddProperty("onpropertychange", "unknown");
192 AddProperty("onreadystatechange", "unknown");
193 AddProperty("onrowsdelete", "unknown");
194 AddProperty("onrowenter", "unknown");
195 AddProperty("onrowexit", "unknown");
196 AddProperty("onrowsinserted", "unknown");
197 AddProperty("onstart", "");
198 AddProperty("onscroll", "unknown");
199 AddProperty("onbeforeeditfocus", "unknown");
200 AddProperty("onactivate", "unknown");
201 AddProperty("onbeforedeactivate", "unknown");
202 AddProperty("ondeactivate", "unknown");
204 // Add the default methods
205 NPIdentifier id
= NPN_GetStringIdentifier("SetVariable");
206 AddMethod(id
, SetVariableCallback
);
208 id
= NPN_GetStringIdentifier("GetVariable");
209 AddMethod(id
, GetVariableCallback
);
211 id
= NPN_GetStringIdentifier("GotoFrame");
212 AddMethod(id
, GotoFrame
);
214 id
= NPN_GetStringIdentifier("IsPlaying");
215 AddMethod(id
, IsPlaying
);
217 id
= NPN_GetStringIdentifier("LoadMovie");
218 AddMethod(id
, LoadMovie
);
220 id
= NPN_GetStringIdentifier("Pan");
223 id
= NPN_GetStringIdentifier("PercentLoaded");
224 AddMethod(id
, PercentLoaded
);
226 id
= NPN_GetStringIdentifier("Play");
229 id
= NPN_GetStringIdentifier("Rewind");
230 AddMethod(id
, Rewind
);
232 id
= NPN_GetStringIdentifier("SetZoomRect");
233 AddMethod(id
, SetZoomRect
);
235 id
= NPN_GetStringIdentifier("StopPlay");
236 AddMethod(id
, StopPlay
);
238 id
= NPN_GetStringIdentifier("Zoom");
241 id
= NPN_GetStringIdentifier("TotalFrames");
242 AddMethod(id
, TotalFrames
);
244 // id = NPN_GetStringIdentifier("TestASMethod");
245 // AddMethod(id, remoteCallback);
249 GnashPluginScriptObject::GnashPluginScriptObject()
250 : nppinstance (nullptr),
254 // log_debug(__PRETTY_FUNCTION__);
256 initializeIdentifiers();
261 GnashPluginScriptObject::GnashPluginScriptObject(NPP npp
)
266 // log_debug(__PRETTY_FUNCTION__);
268 initializeIdentifiers();
273 GnashPluginScriptObject::~GnashPluginScriptObject()
275 // log_debug(__PRETTY_FUNCTION__);
280 GnashPluginScriptObject::marshalGetNPClass()
282 // log_debug(__PRETTY_FUNCTION__);
283 return &GnashPluginScriptObjectClass
;
287 GnashPluginScriptObject::marshalAllocate (NPP npp
, NPClass */
* aClass */
)
289 // log_debug(__PRETTY_FUNCTION__);
290 return new GnashPluginScriptObject(npp
);
295 GnashPluginScriptObject::marshalDeallocate (NPObject
*npobj
)
297 // log_debug(__PRETTY_FUNCTION__);
298 delete (GnashPluginScriptObject
*)npobj
;
302 GnashPluginScriptObject::marshalInvalidate (NPObject */
* npobj */
)
304 // log_debug(__PRETTY_FUNCTION__);
309 GnashPluginScriptObject::marshalHasMethod (NPObject
*npobj
, NPIdentifier name
)
311 // log_debug(__PRETTY_FUNCTION__);
313 GnashPluginScriptObject
*gpso
= (GnashPluginScriptObject
*)npobj
;
316 log_debug("Checking for Method: ");
317 if (NPN_IdentifierIsString(name
)) {
318 log_debug("%s", NPN_UTF8FromIdentifier(name
));
320 log_debug("%d", NPN_IntFromIdentifier(name
));
324 return gpso
->HasMethod(name
);
328 GnashPluginScriptObject::marshalInvoke (NPObject
*npobj
, NPIdentifier name
,
329 const NPVariant
*args
, uint32_t argCount
,
332 GnashPluginScriptObject
*gpso
= (GnashPluginScriptObject
*)npobj
;
334 return gpso
->Invoke(npobj
, name
, args
, argCount
, result
);
338 GnashPluginScriptObject::marshalInvokeDefault (NPObject
*npobj
,
339 const NPVariant
*args
,
343 GnashPluginScriptObject
*gpso
= (GnashPluginScriptObject
*)npobj
;
345 return gpso
->InvokeDefault(args
, argCount
, result
);
349 GnashPluginScriptObject::marshalHasProperty (NPObject
*npobj
, NPIdentifier name
)
351 GnashPluginScriptObject
*gpso
= (GnashPluginScriptObject
*)npobj
;
353 return gpso
->HasProperty(name
);
357 GnashPluginScriptObject::marshalGetProperty (NPObject
*npobj
, NPIdentifier name
,
360 GnashPluginScriptObject
*gpso
= (GnashPluginScriptObject
*)npobj
;
362 return gpso
->GetProperty(name
, result
);
366 GnashPluginScriptObject::marshalSetProperty (NPObject
*npobj
, NPIdentifier name
,
367 const NPVariant
*value
)
369 GnashPluginScriptObject
*gpso
= (GnashPluginScriptObject
*)npobj
;
370 return gpso
->SetProperty(name
, *value
);
374 GnashPluginScriptObject::marshalRemoveProperty (NPObject
*npobj
, NPIdentifier name
)
376 GnashPluginScriptObject
*gpso
= (GnashPluginScriptObject
*)npobj
;
377 return gpso
->RemoveProperty(name
);
381 GnashPluginScriptObject::marshalEnumerate (NPObject
*npobj
, void***identifier
,
384 log_debug(__PRETTY_FUNCTION__
);
386 GnashPluginScriptObject
*gpso
= (GnashPluginScriptObject
*)npobj
;
387 return gpso
->Enumerate(identifier
, count
);
393 GnashPluginScriptObject::marshalConstruct (NPObject
*npobj
, const NPVariant
*data
,
394 uint32_t count
, NPVariant
*result
)
396 log_debug(__PRETTY_FUNCTION__
);
398 GnashPluginScriptObject
*gpso
= (GnashPluginScriptObject
*)npobj
;
399 return gpso
->Construct(data
, count
, result
);
405 GnashPluginScriptObject::HasProperty(NPIdentifier name
)
408 log_debug("Checking for Property \"");
409 if (NPN_IdentifierIsString(name
)) {
410 log_debug("%s\"...", NPN_UTF8FromIdentifier(name
));
412 log_debug("%d\"...", NPN_IntFromIdentifier(name
));
416 return _properties
.find(name
) != _properties
.end();
420 GnashPluginScriptObject::GetProperty(NPIdentifier name
, NPVariant
*result
)
422 if (NPN_IdentifierIsString(name
)) {
423 log_debug("Getting Property \"%s\"...", NPN_UTF8FromIdentifier(name
));
425 log_debug("Getting Property \"%d\"...", NPN_IntFromIdentifier(name
));
428 std::map
<NPIdentifier
, GnashNPVariant
>::const_iterator it
;
429 it
= _properties
.find(name
);
430 if (it
== _properties
.end()) {
434 const GnashNPVariant
& val
= it
->second
;
441 GnashPluginScriptObject::SetProperty(NPIdentifier name
, const NPVariant
& value
)
443 _properties
[name
] = value
;
449 GnashPluginScriptObject::RemoveProperty(NPIdentifier name
)
451 std::map
<NPIdentifier
, GnashNPVariant
>::iterator it
;
452 it
= _properties
.find(name
);
453 if (it
!= _properties
.end()) {
454 _properties
.erase(it
);
462 GnashPluginScriptObject::Enumerate(NPIdentifier
**/
*identifier */
, uint32_t */
* count */
)
464 log_debug(__PRETTY_FUNCTION__
);
470 GnashPluginScriptObject::Construct(const NPVariant */
* args */
, uint32_t /* argCount */,
471 NPVariant */
* result */
)
473 log_debug(__PRETTY_FUNCTION__
);
479 GnashPluginScriptObject::HasMethod(NPIdentifier name
)
482 log_debug("Checking for Method \"");
483 if (NPN_IdentifierIsString(name
)) {
484 log_debug("%s\"...", NPN_UTF8FromIdentifier(name
));
486 log_debug("%d\"...", NPN_IntFromIdentifier(name
));
490 return _methods
.find(name
) != _methods
.end();
494 GnashPluginScriptObject::Invoke(NPObject */
* npobj */
, NPIdentifier name
,
495 const NPVariant
*args
, uint32_t argCount
,
498 // log_debug(__PRETTY_FUNCTION__);
501 if (NPN_IdentifierIsString(name
)) {
502 log_debug("Invoking Method \"%s\"...", NPN_UTF8FromIdentifier(name
));
504 log_debug("Invoking Method: \"%d\"...", NPN_IntFromIdentifier(name
));
506 // log_debug("SCRIPT OBJECT invoke %s: %x", NPN_UTF8FromIdentifier(name),
510 std::map
<NPIdentifier
, NPInvokeFunctionPtr
>::iterator it
;
511 it
= _methods
.find(name
);
512 if (it
!= _methods
.end()) {
513 // log_debug("FOUND Method \"%s\"!", NPN_UTF8FromIdentifier(name));
514 NPInvokeFunctionPtr func
= it
->second
;
515 return func(this, name
, args
, argCount
, result
);
517 log_error("Couldn't find Method \"%s\"", NPN_UTF8FromIdentifier(name
));
522 // return NPN_Invoke(nppinstance, this, name, args, argCount, result);
526 GnashPluginScriptObject::InvokeDefault(const NPVariant */
* args */
,
527 uint32_t /* argCount */, NPVariant */
* result */
)
529 log_debug(__PRETTY_FUNCTION__
);
531 log_debug("Invoking Default Method \"");
532 if (NPN_IdentifierIsString(name
)) {
533 log_debug("%s\"...", NPN_UTF8FromIdentifier(name
));
535 log_debug("%d\"...", NPN_IntFromIdentifier(name
));
543 GnashPluginScriptObject::AddMethod(NPIdentifier name
, NPInvokeFunctionPtr func
)
545 // log_debug(__PRETTY_FUNCTION__);
548 if (NPN_IdentifierIsString(name
)) {
549 log_debug("Adding Method \"%s\"...", NPN_UTF8FromIdentifier(name
));
551 log_debug("Adding Method \"%d\"...", NPN_IntFromIdentifier(name
));
555 _methods
[name
] = func
;
560 // SetVariable sends a message to the player that looks like this:
561 // "Command Name Type value\n", ie... "SetVariable var1 string value1\n"
563 GnashPluginScriptObject::SetVariable(const std::string
&name
,
564 const NPVariant
& value
)
566 std::vector
<std::string
> iargs
;
567 std::string str
= plugin::ExternalInterface::makeString(name
);
568 iargs
.push_back(str
);
569 str
= plugin::ExternalInterface::convertNPVariant(&value
);
570 iargs
.push_back(str
);
571 str
= plugin::ExternalInterface::makeInvoke("SetVariable", iargs
);
573 log_debug("Trying to set a value for %s.", name
);
575 // Write the message to the Control FD.
576 size_t ret
= writePlayer(str
);
577 // Unless we wrote the same amount of data as the message contained,
578 // something went wrong.
579 if (ret
!= str
.size()) {
580 log_error("Couldn't set the variable, network problems.");
587 // GetVariable sends a message to the player that looks like this:
588 // "Command Name\n", ie... "GetVariable var1\n". Then it waits
589 // for the response with the type and value.
591 GnashPluginScriptObject::GetVariable(const std::string
&name
)
593 std::vector
<std::string
> iargs
;
594 std::string str
= plugin::ExternalInterface::makeString(name
);
595 iargs
.push_back(str
);
596 str
= plugin::ExternalInterface::makeInvoke("GetVariable", iargs
);
598 log_debug("Trying to get a value for %s.", name
);
600 size_t ret
= writePlayer(str
);
601 if (ret
!= str
.size()) {
602 // If all the browser wants is the version, we don't need to
603 // ask the standalone player for this value. YouTube at
604 // least depends on this for some pages which want this to
605 // be greater than 8.0.0. This appears to potentially be
606 // Google's way of trying to revent downloaders, as this requires
609 if (name
== "$version") {
610 STRINGN_TO_NPVARIANT("LNX 10,0,r999", 13, value
);
612 log_error("Couldn't send GetVariable request, network problems.");
613 NULL_TO_NPVARIANT(value
);
618 // Have the read function allocate the memory
619 std::string data
= readPlayer();
621 return GnashNPVariant();
624 GnashNPVariant parsed
= plugin::ExternalInterface::parseXML(this, data
);
626 printNPVariant(&parsed
.get());
632 GnashPluginScriptObject::setControlFD(int x
)
634 // log_debug("%s: %d", __FUNCTION__, x);
635 _controlfd
= x
; // FIXME: this should go away
639 GnashPluginScriptObject::getControlFD()
641 // log_debug("getControlFD: %d", controlfd);
647 GnashPluginScriptObject::setHostFD(int x
)
649 // log_debug("%s: %d", __FUNCTION__, x);
650 _hostfd
= x
; // FIXME: this should go away
654 GnashPluginScriptObject::getHostFD()
656 // log_debug("getControlFD: %d", controlfd);
662 // Write to the standalone player over the control socket
664 GnashPluginScriptObject::writePlayer(const std::string
&data
)
666 return writePlayer(_controlfd
, data
);
670 GnashPluginScriptObject::writePlayer(int fd
, const std::string
&data
)
672 // log_debug(__PRETTY_FUNCTION__);
674 // log_debug("Writing data to fd #%d:\n %s", fd, data);
677 return ::write(fd
, data
.c_str(), data
.size());
684 GnashPluginScriptObject::readPlayer()
686 return readPlayer(_hostfd
);
690 GnashPluginScriptObject::readPlayer(int fd
)
695 log_error("Invalid fd passed");
699 // Wait for some data from the player
702 pollfd pfds
[1] = { pollfd() };
704 pfds
[0].events
= POLLIN
;
706 int rv
= poll(pfds
, 1 /* arraySize */, 2000 /* ms */);
714 rv
= ioctl(fd
, FIONREAD
, &bytes
);
716 rv
= ioctlSocket(fd
, FIONREAD
, &bytes
);
719 log_error("FIONREAD ioctl failed, unable to get network buffer length");
722 log_debug("There are %d bytes in the network buffer", bytes
);
730 int ret
= ::read(fd
, buf
, bytes
);
731 if (ret
<= 0 || ret
> bytes
) {
735 return std::string(buf
, ret
);
741 } // end of gnash namespace
745 // indent-tabs-mode: nil