1//
2//   Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
3//
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 2 of the License, or
7// (at your option) any later version.
8//
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.
13//
14// You should have received a copy of the GNU General Public License
15//
16// along with this program; if not, write to the Free Software
17// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18//
19// Test case for ExternalInterface ActionScript class
20// compile this test case with Ming makeswf, and then
21// execute it like this gnash -1 -r 0 -v out.swf
22
23#include "check.as"
24
25flash.system.Security.allowDomain("localhost");
26
27ASSetPropFlags (_global, "flash", 0, 5248);
28EI = flash.external.ExternalInterface;
29
30#if OUTPUT_VERSION < 6 // {
31
32check_equals(typeof(EI), 'undefined');
33
34#else // OUTPUT_VERSION >= 6 }{
35
36check_equals(typeof(EI), 'function');
37check(EI.hasOwnProperty('addCallback'));
38check(EI.hasOwnProperty("_argumentsToAS"));
39check(EI.hasOwnProperty("_argumentsToXML"));
40check(EI.hasOwnProperty("_arrayToAS"));
41check(EI.hasOwnProperty("_arrayToJS"));
42check(EI.hasOwnProperty("_arrayToXML"));
43check(EI.hasOwnProperty('available'));
44check(EI.hasOwnProperty('call'));
45check(EI.hasOwnProperty("_callIn"));
46check(EI.hasOwnProperty("_callOut"));
47check(EI.hasOwnProperty("_escapeXML"));
48check(EI.hasOwnProperty("_evalJS"));
49check(EI.hasOwnProperty("_initJS"));
50check(EI.hasOwnProperty("_jsQuoteString"));
51check(EI.hasOwnProperty("_objectID"));
52check(EI.hasOwnProperty("_objectToAS"));
53check(EI.hasOwnProperty("_objectToJS"));
54check(EI.hasOwnProperty("_objectToXML"));
55check(EI.hasOwnProperty("_toAS"));
56check(EI.hasOwnProperty("_toJS"));
57check(EI.hasOwnProperty("_toXML"));
58check(EI.hasOwnProperty("_unescapeXML"));
59check(EI.hasOwnProperty("prototype"));
60check(!EI.hasOwnProperty("marshallExceptions"));
61check(!EI.hasOwnProperty("objectID"));
62// Empty prototype...
63var s = ''; for (var i in EI.prototype) s += i; check_equals(s, '');
64
65#if OUTPUT_VERSION < 8 // {
66
67xcheck_equals(typeof(EI.addCallback), 'undefined');
68xcheck_equals(typeof(EI._argumentsToAS), 'undefined');
69xcheck_equals(typeof(EI._argumentsToXML), 'undefined');
70xcheck_equals(typeof(EI._arrayToAS), 'undefined');
71xcheck_equals(typeof(EI._arrayToJS), 'undefined');
72xcheck_equals(typeof(EI._arrayToXML), 'undefined');
73check_equals(typeof(EI.available), 'undefined');
74check_equals(typeof(EI.call), 'function');
75xcheck_equals(typeof(EI._callIn), 'undefined');
76check_equals(typeof(EI._callOut), 'undefined');
77check_equals(typeof(EI._escapeXML), 'undefined');
78check_equals(typeof(EI._evalJS), 'undefined');
79check_equals(typeof(EI._initJS), 'undefined');
80check_equals(typeof(EI._jsQuoteString), 'undefined');
81check_equals(typeof(EI._objectID), 'undefined');
82xcheck_equals(typeof(EI._objectToAS), 'undefined');
83xcheck_equals(typeof(EI._objectToJS), 'undefined');
84xcheck_equals(typeof(EI._objectToXML), 'undefined');
85xcheck_equals(typeof(EI._toAS), 'undefined');
86xcheck_equals(typeof(EI._toJS), 'undefined');
87xcheck_equals(typeof(EI._toXML), 'undefined');
88check_equals(typeof(EI._unescapeXML), 'undefined');
89
90#else //  OUTPUT_VERSION >= 8  }{
91
92check_equals(typeof(EI.addCallback), 'function');
93check_equals(typeof(EI._argumentsToAS), 'function');
94check_equals(typeof(EI._argumentsToXML), 'function');
95check_equals(typeof(EI._arrayToAS), 'function');
96check_equals(typeof(EI._arrayToJS), 'function');
97check_equals(typeof(EI._arrayToXML), 'function');
98check_equals(typeof(EI.available), 'boolean');
99check_equals(typeof(EI.call), 'function');
100check_equals(typeof(EI._callIn), 'function');
101check_equals(typeof(EI._callOut), 'function');
102check_equals(typeof(EI._escapeXML), 'function');
103check_equals(typeof(EI._evalJS), 'function');
104check_equals(typeof(EI._initJS), 'function');
105check_equals(typeof(EI._jsQuoteString), 'function');
106check_equals(typeof(EI._objectID), 'function');
107check_equals(typeof(EI._objectToAS), 'function');
108check_equals(typeof(EI._objectToJS), 'function');
109check_equals(typeof(EI._objectToXML), 'function');
110check_equals(typeof(EI._toAS), 'function');
111check_equals(typeof(EI._toJS), 'function');
112check_equals(typeof(EI._toXML), 'function');
113check_equals(typeof(EI._unescapeXML), 'function');
114
115// Create a test function for the callback
116function TestASMethod (msg) {
117    note("TestASMethod called! " + msg);
118    return "I am here!";
119}
120
121// ExternalInterface::available is always false when run standalone,
122// and true if running under a browser and has allowable access to the
123// resource. So we can't have a test case for this property that works
124// both standalone and online Instead we do depend on it being correct
125// as the ExternalInterface::call() tests require this test case to
126// be run under a browser.
127
128// ::call() calls JavaScript functions in the browser, not in flash,
129// so we can't test it when running standalone. So this will always
130// return null unless run from a browser
131
132// This adds a callback that the brower can call from Javascript. This is
133// a bit of a bogus test case, as addCallback() doesn't return anything, but
134// we need to add a method anyway to test being called by Javascript.
135ret = EI.addCallback("TestASMethod", null, TestASMethod);
136check_equals(typeof(ret), 'boolean');
137check_equals(ret, EI.available); // returns true if available...
138ret = EI.call("TestJSMethod", "test");
139if ( EI.available ) {
140    check_equals(typeof(ret), 'undefined');
141} else {
142    check_equals(typeof(ret), 'null');
143}
144
145// A native class
146nc = Mouse;
147
148// Try instantiating.
149r = new EI;
150// You get an object
151check_equals(typeof(r), 'object');
152check(r instanceOf EI);
153
154// All methods are class statics, not inherited
155check_equals(typeof(r.addCallback), 'undefined');
156check_equals(typeof(r._argumentsToAS), 'undefined');
157check_equals(typeof(r._argumentsToXML), 'undefined');
158check_equals(typeof(r._arrayToAS), 'undefined');
159check_equals(typeof(r._arrayToJS), 'undefined');
160check_equals(typeof(r._arrayToXML), 'undefined');
161check_equals(typeof(r.available), 'undefined');
162check_equals(typeof(r.call), 'undefined');
163check_equals(typeof(r._callIn), 'undefined');
164check_equals(typeof(r._callOut), 'undefined');
165check_equals(typeof(r._escapeXML), 'undefined');
166check_equals(typeof(r._evalJS), 'undefined');
167check_equals(typeof(r._initJS), 'undefined');
168check_equals(typeof(r._jsQuoteString), 'undefined');
169check_equals(typeof(r._objectID), 'undefined');
170check_equals(typeof(r._objectToAS), 'undefined');
171check_equals(typeof(r._objectToJS), 'undefined');
172check_equals(typeof(r._objectToXML), 'undefined');
173check_equals(typeof(r._toAS), 'undefined');
174check_equals(typeof(r._toJS), 'undefined');
175check_equals(typeof(r._toXML), 'undefined');
176check_equals(typeof(r._unescapeXML), 'undefined');
177
178xml = EI._objectToXML(nc);
179check_equals (xml, '<object></object>');
180
181// An object
182o = { a: 1, b: "string" };
183
184xml = EI._objectToXML(o);
185check_equals (xml, '<object><property id="a"><number>1</number></property><property id="b"><string>string</string></property></object>');
186
187xml = EI._objectToXML(o, 1, 2, 3);
188check_equals (xml, '<object><property id="a"><number>1</number></property><property id="b"><string>string</string></property></object>');
189
190// An object with an object reference
191
192o = { o: o };
193xml = EI._objectToXML(o);
194check_equals (xml, '<object><property id="o"><object><property id="a"><number>1</number></property><property id="b"><string>string</string></property></object></property></object>');
195
196// An object with circular references
197// (the proprietary player hangs here, we jus don't want to segfault)
198// oc = {};
199// oc.cr = oc;
200// xml = EI._objectToXML(oc);
201// check_equals (xml, '');
202
203// An undefined
204
205xml = EI._objectToXML(undefined);
206check_equals (xml, '<object></object>');
207
208xml = EI._objectToXML(null);
209check_equals (xml, '<object></object>');
210
211xml = EI._objectToXML(6);
212check_equals (xml, '<object></object>');
213
214xml = EI._objectToXML();
215check_equals (xml, '<object></object>');
216
217// An Array
218anArray = [ 12, "tr", 1 ];
219anArray.length = 4;
220
221xml = EI._arrayToXML(anArray);
222check_equals (xml,
223'<array><property id="0"><number>12</number></property><property id="1"><string>tr</string></property><property id="2"><number>1</number></property><property id="3"><undefined/></property></array>'
224);
225
226xml = EI._argumentsToXML(anArray);
227check_equals (xml,
228'<arguments><string>tr</string><number>1</number><undefined/></arguments>'
229);
230xml = EI._argumentsToXML();
231check_equals (xml, '<arguments></arguments>');
232xml = EI._argumentsToXML(['single']);
233check_equals (xml, '<arguments></arguments>');
234xml = EI._argumentsToXML('one');
235check_equals (xml, '<arguments><undefined/><undefined/></arguments>');
236xml = EI._argumentsToXML(1,2,3);
237check_equals (xml, '<arguments></arguments>');
238
239// It uses the length property...
240str = "hi";
241ret = flash.external.ExternalInterface._arrayToXML(str);
242check_equals(ret, '<array><property id="0"><undefined/></property><property id="1"><undefined/></property></array>');
243
244// xml = EI._toXML(o);
245// if (xml == '<object><property id="a"><number>1</number></property><property id="b"><string>string</string></property></object>') {
246//     pass("ExternalInterface::_toXML(object)");
247// } else {
248//     fail("ExternalInterface::_toXML(object)");
249// }
250
251// xml = EI._toXML("Hello World!");
252// if (xml == "<string>Hello World!</string>") {
253//     pass("ExternalInterface::_toXML(string)");
254// } else {
255//     fail("ExternalInterface::_toXML(string)");
256// }
257
258xml = EI._toXML(123.456);
259check_equals (xml , "<number>123.456</number>");
260
261// A native object
262no = new XML;
263
264xml = EI._objectToXML(no);
265xcheck_equals (xml, '<object><property id="namespaceURI"><null/></property><property id="localName"><null/></property><property id="prefix"><null/></property><property id="previousSibling"><null/></property><property id="parentNode"><null/></property><property id="nodeValue"><null/></property><property id="nodeType"><number>1</number></property><property id="nodeName"><null/></property><property id="nextSibling"><null/></property><property id="lastChild"><null/></property><property id="firstChild"><null/></property><property id="childNodes"><array></array></property><property id="attributes"><null/></property><property id="getPrefixForNamespace"><null/></property><property id="getNamespaceForPrefix"><null/></property><property id="toString"><null/></property><property id="hasChildNodes"><null/></property><property id="appendChild"><null/></property><property id="insertBefore"><null/></property><property id="removeNode"><null/></property><property id="cloneNode"><null/></property><property id="xmlDecl"><undefined/></property><property id="status"><number>0</number></property><property id="loaded"><undefined/></property><property id="ignoreWhite"><false/></property><property id="docTypeDecl"><undefined/></property><property id="contentType"><string>application/x-www-form-urlencoded</string></property><property id="addRequestHeader"><null/></property><property id="getBytesTotal"><null/></property><property id="getBytesLoaded"><null/></property><property id="onData"><null/></property><property id="onLoad"><null/></property><property id="sendAndLoad"><null/></property><property id="send"><null/></property><property id="load"><null/></property><property id="parseXML"><null/></property><property id="createTextNode"><null/></property><property id="createElement"><null/></property></object>');
266
267// xcheck_equals(EI._objectToJS(o), '({a:1,b:"string"})');
268
269// xcheck_equals(EI._objectToAS(no).toString(), '[object Object]');
270
271// check_equals(EI._objectID(o), null);
272
273// escape / unescape
274rin = "& ß+ü < << <>''\"";
275rout = "&amp; ß+ü &lt; &lt;&lt; &lt;&gt;&apos;&apos;&quot;";
276ret = EI._escapeXML(rin);
277check_equals(ret, rout);
278
279// It doesn't escape html entities.
280rin = "&amp; ß+ü &nbsp; &lt; &lt;&lt; &lt;&gt;&apos;&apos;&quot;";
281rout = "& ß+ü .. < << <>''\"";
282ret  = EI._unescapeXML(rin);
283// This test will until fail until we can figure out the best way to
284// match the converted strings. Testing in GDB show the result is correct,
285// so this is mainly a test case problem.
286xcheck_equals (ret, "& ß+ü &nbsp; < << <>''\"");
287
288// This isn't how _toAS works:
289val = EI._toAS("<number>34.56</number>");
290check_equals (typeof(val), 'undefined');
291
292val = EI._toAS("<string>Hello World!</string>");
293check_equals (typeof(val), 'undefined');
294
295val = EI._toAS("<null/>");
296check_equals (typeof(val), 'undefined');
297
298val = EI._toAS("<true/>");
299check_equals (typeof(val), 'undefined');
300
301val = EI._toAS("<false/>");
302check_equals (typeof(val), 'undefined');
303
304// This is how it works:
305// Note that it's really designed for XMLNodes, but it's quite happy with
306// the faked nodes we're giving it here.
307
308o = {};
309o.nodeName = "false";
310check_equals(EI._toAS(o), false);
311
312o = {};
313o.nodeName = "true";
314check_equals(EI._toAS(o), true);
315
316o = {};
317o.nodeName = "number";
318check_equals(EI._toAS(o).toString(), "NaN");
319o.firstChild = new String("45");
320check_equals(EI._toAS(o), 45);
321
322e = {};
323e.toString = function() { return "23"; };
324o.firstChild = e;
325check_equals(EI._toAS(o), 23);
326
327// This way doesn't work.
328o = {};
329o.nodeName = "boolean";
330check_equals(EI._toAS(o), undefined);
331o.firstChild = new String("false");
332check_equals(EI._toAS(o), undefined);
333
334o = {};
335o.nodeName = "null";
336check_equals(EI._toAS(o), null);
337
338o = {};
339o.nodeName = "class";
340o.firstChild = new String("foo");
341check_equals(EI._toAS(o), undefined);
342
343o.firstChild = new String("Date");
344check_equals(typeof(EI._toAS(o)), "function");
345
346val = EI._objectToAS('<object><property id="b"><string>string</string></property><property id="a"><number>1</number></property></object>');
347xcheck_equals (typeOf(val), 'object');
348
349// Check what happens with addCallback
350
351// It doesn't add the callback as a member of ExternalInterface.
352o = {};
353EI.addCallback("func1", o);
354check_equals(EI.func1, undefined);
355
356#endif  // version > 7 }
357
358#endif // OUTPUT_VERSION >= 6 }
359
360
361#if OUTPUT_VERSION < 6 // {
362	check_totals(1);
363#elif OUTPUT_VERSION < 8 // }{
364	check_totals(49);
365#else // SWF8+ }{
366	check_totals(112);
367# endif // }
368
369