1/*
2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2009 Holger Hans Peter Freyther
4 * Copyright (C) 2010 Collabora Ltd.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "PluginObject.h"
29
30#include "PluginTest.h"
31#include "TestObject.h"
32#include <assert.h>
33#include <memory>
34#include <stdarg.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38#include <wtf/Platform.h>
39#include <wtf/ExportMacros.h>
40
41// Helper function which takes in the plugin window object for logging to the console object.
42static void pluginLogWithWindowObject(NPObject* windowObject, NPP instance, const char* message)
43{
44 NPVariant consoleVariant;
45 if (!browser->getproperty(instance, windowObject, browser->getstringidentifier("console"), &consoleVariant)) {
46 fprintf(stderr, "Failed to retrieve console object while logging: %s\n", message);
47 return;
48 }
49
50 NPObject* consoleObject = NPVARIANT_TO_OBJECT(consoleVariant);
51
52 NPVariant messageVariant;
53 STRINGZ_TO_NPVARIANT(message, messageVariant);
54
55 NPVariant result;
56 if (!browser->invoke(instance, consoleObject, browser->getstringidentifier("log"), &messageVariant, 1, &result)) {
57 fprintf(stderr, "Failed to invoke console.log while logging: %s\n", message);
58 browser->releaseobject(consoleObject);
59 return;
60 }
61
62 browser->releasevariantvalue(&result);
63 browser->releaseobject(consoleObject);
64}
65
66void pluginLogWithArguments(NPP instance, const char* format, va_list args)
67{
68 const size_t messageBufferSize = 2048;
69 char message[messageBufferSize] = "PLUGIN: ";
70 int messageLength = sizeof("PLUGIN: ") - 1;
71 messageLength += vsnprintf(message + messageLength, messageBufferSize - 1 - messageLength, format, args);
72 message[messageLength] = '\0';
73
74 NPObject* windowObject = 0;
75 NPError error = browser->getvalue(instance, NPNVWindowNPObject, &windowObject);
76 if (error != NPERR_NO_ERROR) {
77 fprintf(stderr, "Failed to retrieve window object while logging: %s\n", message);
78 return;
79 }
80
81 pluginLogWithWindowObject(windowObject, instance, message);
82 browser->releaseobject(windowObject);
83}
84
85// Helper function to log to the console object.
86void pluginLog(NPP instance, const char* format, ...)
87{
88 va_list args;
89 va_start(args, format);
90 pluginLogWithArguments(instance, format, args);
91 va_end(args);
92}
93
94static void pluginInvalidate(NPObject*);
95static bool pluginHasProperty(NPObject*, NPIdentifier name);
96static bool pluginHasMethod(NPObject*, NPIdentifier name);
97static bool pluginGetProperty(NPObject*, NPIdentifier name, NPVariant*);
98static bool pluginSetProperty(NPObject*, NPIdentifier name, const NPVariant*);
99static bool pluginInvoke(NPObject*, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result);
100static NPObject* pluginAllocate(NPP npp, NPClass*);
101static void pluginDeallocate(NPObject*);
102
103NPNetscapeFuncs* browser;
104NPPluginFuncs* pluginFunctions;
105
106static NPClass pluginClass = {
107 NP_CLASS_STRUCT_VERSION,
108 pluginAllocate,
109 pluginDeallocate,
110 pluginInvalidate,
111 pluginHasMethod,
112 pluginInvoke,
113 0, // NPClass::invokeDefault,
114 pluginHasProperty,
115 pluginGetProperty,
116 pluginSetProperty,
117 0, // NPClass::removeProperty
118 0, // NPClass::enumerate
119 0, // NPClass::construct
120};
121
122NPClass* getPluginClass(void)
123{
124 return &pluginClass;
125}
126
127static bool identifiersInitialized = false;
128
129enum {
130 ID_PROPERTY_PROPERTY = 0,
131 ID_PROPERTY_EVENT_LOGGING,
132 ID_PROPERTY_HAS_STREAM,
133 ID_PROPERTY_TEST_OBJECT,
134 ID_PROPERTY_LOG_DESTROY,
135 ID_PROPERTY_RETURN_ERROR_FROM_NEWSTREAM,
136 ID_PROPERTY_RETURN_NEGATIVE_ONE_FROM_WRITE,
137 ID_PROPERTY_THROW_EXCEPTION_PROPERTY,
138 ID_LAST_SET_WINDOW_ARGUMENTS,
139 ID_PROPERTY_WINDOWED_PLUGIN,
140 ID_PROPERTY_TEST_OBJECT_COUNT,
141 ID_PROPERTY_DELETE_IN_GET_PROPERTY,
142 NUM_PROPERTY_IDENTIFIERS
143};
144
145static NPIdentifier pluginPropertyIdentifiers[NUM_PROPERTY_IDENTIFIERS];
146static const NPUTF8 *pluginPropertyIdentifierNames[NUM_PROPERTY_IDENTIFIERS] = {
147 "property",
148 "eventLoggingEnabled",
149 "hasStream",
150 "testObject",
151 "logDestroy",
152 "returnErrorFromNewStream",
153 "returnNegativeOneFromWrite",
154 "testThrowExceptionProperty",
155 "lastSetWindowArguments",
156 "windowedPlugin",
157 "testObjectCount",
158 "deletePluginInGetProperty"
159};
160
161enum {
162 ID_TEST_CALLBACK_METHOD = 0,
163 ID_TEST_CALLBACK_METHOD_RETURN,
164 ID_TEST_GETURL,
165 ID_TEST_DOM_ACCESS,
166 ID_TEST_GET_URL_NOTIFY,
167 ID_TEST_INVOKE_DEFAULT,
168 ID_DESTROY_STREAM,
169 ID_TEST_ENUMERATE,
170 ID_TEST_GETINTIDENTIFIER,
171 ID_TEST_GET_PROPERTY,
172 ID_TEST_HAS_PROPERTY,
173 ID_TEST_HAS_METHOD,
174 ID_TEST_EVALUATE,
175 ID_TEST_GET_PROPERTY_RETURN_VALUE,
176 ID_TEST_IDENTIFIER_TO_STRING,
177 ID_TEST_IDENTIFIER_TO_INT,
178 ID_TEST_PASS_TEST_OBJECT,
179 ID_TEST_POSTURL_FILE,
180 ID_TEST_CONSTRUCT,
181 ID_TEST_THROW_EXCEPTION_METHOD,
182 ID_TEST_FAIL_METHOD,
183 ID_TEST_CLONE_OBJECT,
184 ID_TEST_SCRIPT_OBJECT_INVOKE,
185 ID_TEST_CREATE_TEST_OBJECT,
186 ID_DESTROY_NULL_STREAM,
187 ID_TEST_RELOAD_PLUGINS_NO_PAGES,
188 ID_TEST_RELOAD_PLUGINS_AND_PAGES,
189 ID_TEST_GET_BROWSER_PROPERTY,
190 ID_TEST_SET_BROWSER_PROPERTY,
191 ID_REMEMBER,
192 ID_GET_REMEMBERED_OBJECT,
193 ID_GET_AND_FORGET_REMEMBERED_OBJECT,
194 ID_REF_COUNT,
195 ID_SET_STATUS,
196 ID_RESIZE_TO,
197 ID_NORMALIZE,
198 ID_INVALIDATE_RECT,
199 ID_OBJECTS_ARE_SAME,
200 ID_TEST_DELETE_WITHIN_INVOKE,
201 NUM_METHOD_IDENTIFIERS
202};
203
204static NPIdentifier pluginMethodIdentifiers[NUM_METHOD_IDENTIFIERS];
205static const NPUTF8 *pluginMethodIdentifierNames[NUM_METHOD_IDENTIFIERS] = {
206 "testCallback",
207 "testCallbackReturn",
208 "getURL",
209 "testDOMAccess",
210 "getURLNotify",
211 "testInvokeDefault",
212 "destroyStream",
213 "testEnumerate",
214 "testGetIntIdentifier",
215 "testGetProperty",
216 "testHasProperty",
217 "testHasMethod",
218 "testEvaluate",
219 "testGetPropertyReturnValue",
220 "testIdentifierToString",
221 "testIdentifierToInt",
222 "testPassTestObject",
223 "testPostURLFile",
224 "testConstruct",
225 "testThrowException",
226 "testFail",
227 "testCloneObject",
228 "testScriptObjectInvoke",
229 "testCreateTestObject",
230 "destroyNullStream",
231 "reloadPluginsNoPages",
232 "reloadPluginsAndPages",
233 "testGetBrowserProperty",
234 "testSetBrowserProperty",
235 "remember",
236 "getRememberedObject",
237 "getAndForgetRememberedObject",
238 "refCount",
239 "setStatus",
240 "resizeTo",
241 "normalize",
242 "invalidateRect",
243 "objectsAreSame",
244 "testDeleteWithinInvoke"
245};
246
247static NPUTF8* createCStringFromNPVariant(const NPVariant* variant)
248{
249 size_t length = NPVARIANT_TO_STRING(*variant).UTF8Length;
250 NPUTF8* result = (NPUTF8*)malloc(length + 1);
251 memcpy(result, NPVARIANT_TO_STRING(*variant).UTF8Characters, length);
252 result[length] = '\0';
253 return result;
254}
255
256static void initializeIdentifiers(void)
257{
258 browser->getstringidentifiers(pluginPropertyIdentifierNames, NUM_PROPERTY_IDENTIFIERS, pluginPropertyIdentifiers);
259 browser->getstringidentifiers(pluginMethodIdentifierNames, NUM_METHOD_IDENTIFIERS, pluginMethodIdentifiers);
260}
261
262static bool callDeletePlugin(NPObject* obj, NPIdentifier name, NPIdentifier identifierToMatch)
263{
264 if (name != identifierToMatch)
265 return false;
266
267 PluginObject* plugin = reinterpret_cast<PluginObject*>(obj);
268 NPObject* windowScriptObject;
269 browser->getvalue(plugin->npp, NPNVWindowNPObject, &windowScriptObject);
270
271 NPIdentifier callbackIdentifier = browser->getstringidentifier("deletePlugin");
272 NPVariant browserResult;
273 if (browser->invoke(plugin->npp, windowScriptObject, callbackIdentifier, 0, 0, &browserResult))
274 browser->releasevariantvalue(&browserResult);
275 return true;
276}
277
278static bool pluginHasProperty(NPObject *obj, NPIdentifier name)
279{
280 if (callDeletePlugin(obj, name, browser->getstringidentifier("deletePluginReturnTrue")))
281 return true;
282
283 if (callDeletePlugin(obj, name, browser->getstringidentifier("deletePluginReturnFalse")))
284 return false;
285
286 for (int i = 0; i < NUM_PROPERTY_IDENTIFIERS; i++)
287 if (name == pluginPropertyIdentifiers[i])
288 return true;
289 return false;
290}
291
292static bool pluginHasMethod(NPObject *obj, NPIdentifier name)
293{
294 if (callDeletePlugin(obj, name, browser->getstringidentifier("deletePluginInHasMethod")))
295 return true;
296
297 for (int i = 0; i < NUM_METHOD_IDENTIFIERS; i++)
298 if (name == pluginMethodIdentifiers[i])
299 return true;
300 return false;
301}
302
303static bool pluginGetProperty(NPObject* obj, NPIdentifier name, NPVariant* result)
304{
305 PluginObject* plugin = reinterpret_cast<PluginObject*>(obj);
306 if (name == pluginPropertyIdentifiers[ID_PROPERTY_PROPERTY]) {
307 static const char* originalString = "property";
308 char* buf = static_cast<char*>(browser->memalloc(strlen(originalString) + 1));
309 strcpy(buf, originalString);
310 STRINGZ_TO_NPVARIANT(buf, *result);
311 return true;
312 }
313 if (name == pluginPropertyIdentifiers[ID_PROPERTY_EVENT_LOGGING]) {
314 BOOLEAN_TO_NPVARIANT(plugin->eventLogging, *result);
315 return true;
316 }
317 if (name == pluginPropertyIdentifiers[ID_PROPERTY_LOG_DESTROY]) {
318 BOOLEAN_TO_NPVARIANT(plugin->logDestroy, *result);
319 return true;
320 }
321 if (name == pluginPropertyIdentifiers[ID_PROPERTY_HAS_STREAM]) {
322 BOOLEAN_TO_NPVARIANT(plugin->stream, *result);
323 return true;
324 }
325 if (name == pluginPropertyIdentifiers[ID_PROPERTY_TEST_OBJECT]) {
326 NPObject* testObject = plugin->testObject;
327 browser->retainobject(testObject);
328 OBJECT_TO_NPVARIANT(testObject, *result);
329 return true;
330 }
331 if (name == pluginPropertyIdentifiers[ID_PROPERTY_RETURN_ERROR_FROM_NEWSTREAM]) {
332 BOOLEAN_TO_NPVARIANT(plugin->returnErrorFromNewStream, *result);
333 return true;
334 }
335 if (name == pluginPropertyIdentifiers[ID_PROPERTY_RETURN_NEGATIVE_ONE_FROM_WRITE]) {
336 BOOLEAN_TO_NPVARIANT(plugin->returnNegativeOneFromWrite, *result);
337 return true;
338 }
339 if (name == pluginPropertyIdentifiers[ID_PROPERTY_THROW_EXCEPTION_PROPERTY]) {
340 browser->setexception(obj, "plugin object testThrowExceptionProperty SUCCESS");
341 return true;
342 }
343 if (name == pluginPropertyIdentifiers[ID_LAST_SET_WINDOW_ARGUMENTS]) {
344 char* buf = static_cast<char*>(browser->memalloc(256));
345 snprintf(buf, 256, "x: %d, y: %d, width: %u, height: %u, clipRect: (%u, %u, %u, %u)", (int)plugin->lastWindow.x, (int)plugin->lastWindow.y, (unsigned)plugin->lastWindow.width, (unsigned)plugin->lastWindow.height,
346 plugin->lastWindow.clipRect.left, plugin->lastWindow.clipRect.top, plugin->lastWindow.clipRect.right - plugin->lastWindow.clipRect.left, plugin->lastWindow.clipRect.bottom - plugin->lastWindow.clipRect.top);
347
348 STRINGZ_TO_NPVARIANT(buf, *result);
349 return true;
350 }
351 if (name == pluginPropertyIdentifiers[ID_PROPERTY_TEST_OBJECT_COUNT]) {
352 INT32_TO_NPVARIANT(getTestObjectCount(), *result);
353 return true;
354 }
355
356 if (name == pluginPropertyIdentifiers[ID_PROPERTY_DELETE_IN_GET_PROPERTY]) {
357 browser->retainobject(obj);
358 callDeletePlugin(obj, name, pluginPropertyIdentifiers[ID_PROPERTY_DELETE_IN_GET_PROPERTY]);
359 NPObject* testObject = plugin->testObject;
360 browser->retainobject(testObject);
361 OBJECT_TO_NPVARIANT(testObject, *result);
362 browser->releaseobject(obj);
363 return true;
364 }
365
366 return false;
367}
368
369static bool pluginSetProperty(NPObject* obj, NPIdentifier name, const NPVariant* variant)
370{
371 PluginObject* plugin = reinterpret_cast<PluginObject*>(obj);
372 if (callDeletePlugin(obj, name, browser->getstringidentifier("deletePluginReturnTrue")))
373 return true;
374
375 if (name == pluginPropertyIdentifiers[ID_PROPERTY_EVENT_LOGGING]) {
376 plugin->eventLogging = NPVARIANT_TO_BOOLEAN(*variant);
377 return true;
378 }
379 if (name == pluginPropertyIdentifiers[ID_PROPERTY_LOG_DESTROY]) {
380 plugin->logDestroy = NPVARIANT_TO_BOOLEAN(*variant);
381 return true;
382 }
383 if (name == pluginPropertyIdentifiers[ID_PROPERTY_RETURN_ERROR_FROM_NEWSTREAM]) {
384 plugin->returnErrorFromNewStream = NPVARIANT_TO_BOOLEAN(*variant);
385 return true;
386 }
387 if (name == pluginPropertyIdentifiers[ID_PROPERTY_RETURN_NEGATIVE_ONE_FROM_WRITE]) {
388 plugin->returnNegativeOneFromWrite = NPVARIANT_TO_BOOLEAN(*variant);
389 return true;
390 }
391 if (name == pluginPropertyIdentifiers[ID_PROPERTY_THROW_EXCEPTION_PROPERTY]) {
392 browser->setexception(obj, "plugin object testThrowExceptionProperty SUCCESS");
393 return true;
394 }
395 if (name == pluginPropertyIdentifiers[ID_PROPERTY_WINDOWED_PLUGIN]) {
396 browser->setvalue(plugin->npp, NPPVpluginWindowBool, (void *)NPVARIANT_TO_BOOLEAN(*variant));
397 return true;
398 }
399
400 return false;
401}
402
403static bool testDOMAccess(PluginObject* obj, const NPVariant*, uint32_t, NPVariant* result)
404{
405 // Get plug-in's DOM element
406 NPObject* elementObject;
407 if (browser->getvalue(obj->npp, NPNVPluginElementNPObject, &elementObject) == NPERR_NO_ERROR) {
408 // Get style
409 NPVariant styleVariant;
410 NPIdentifier styleIdentifier = browser->getstringidentifier("style");
411 if (browser->getproperty(obj->npp, elementObject, styleIdentifier, &styleVariant) && NPVARIANT_IS_OBJECT(styleVariant)) {
412 // Set style.border
413 NPIdentifier borderIdentifier = browser->getstringidentifier("border");
414 NPVariant borderVariant;
415 STRINGZ_TO_NPVARIANT("3px solid red", borderVariant);
416 browser->setproperty(obj->npp, NPVARIANT_TO_OBJECT(styleVariant), borderIdentifier, &borderVariant);
417 browser->releasevariantvalue(&styleVariant);
418 }
419
420 browser->releaseobject(elementObject);
421 }
422 VOID_TO_NPVARIANT(*result);
423 return true;
424}
425
426static NPIdentifier stringVariantToIdentifier(NPVariant variant)
427{
428 assert(NPVARIANT_IS_STRING(variant));
429 NPUTF8* utf8String = createCStringFromNPVariant(&variant);
430 NPIdentifier identifier = browser->getstringidentifier(utf8String);
431 free(utf8String);
432 return identifier;
433}
434
435static NPIdentifier int32VariantToIdentifier(NPVariant variant)
436{
437 assert(NPVARIANT_IS_INT32(variant));
438 int32_t integer = NPVARIANT_TO_INT32(variant);
439 return browser->getintidentifier(integer);
440}
441
442static NPIdentifier doubleVariantToIdentifier(NPVariant variant)
443{
444 assert(NPVARIANT_IS_DOUBLE(variant));
445 double value = NPVARIANT_TO_DOUBLE(variant);
446 // Sadly there is no "getdoubleidentifier"
447 int32_t integer = static_cast<int32_t>(value);
448 return browser->getintidentifier(integer);
449}
450
451static NPIdentifier variantToIdentifier(NPVariant variant)
452{
453 if (NPVARIANT_IS_STRING(variant))
454 return stringVariantToIdentifier(variant);
455 if (NPVARIANT_IS_INT32(variant))
456 return int32VariantToIdentifier(variant);
457 if (NPVARIANT_IS_DOUBLE(variant))
458 return doubleVariantToIdentifier(variant);
459 return 0;
460}
461
462static bool testIdentifierToString(PluginObject*, const NPVariant* args, uint32_t argCount, NPVariant* result)
463{
464 if (argCount != 1)
465 return true;
466 NPIdentifier identifier = variantToIdentifier(args[0]);
467 if (!identifier)
468 return true;
469 NPUTF8* utf8String = browser->utf8fromidentifier(identifier);
470 if (!utf8String)
471 return true;
472 STRINGZ_TO_NPVARIANT(utf8String, *result);
473 return true;
474}
475
476static bool testIdentifierToInt(PluginObject*, const NPVariant* args, uint32_t argCount, NPVariant* result)
477{
478 if (argCount != 1)
479 return false;
480 NPIdentifier identifier = variantToIdentifier(args[0]);
481 if (!identifier)
482 return false;
483 int32_t integer = browser->intfromidentifier(identifier);
484 INT32_TO_NPVARIANT(integer, *result);
485 return true;
486}
487
488static bool testPassTestObject(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
489{
490 if (argCount != 2 || !NPVARIANT_IS_STRING(args[0]))
491 return false;
492
493 NPObject* windowScriptObject;
494 browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject);
495
496 NPUTF8* callbackString = createCStringFromNPVariant(&args[0]);
497 NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackString);
498 free(callbackString);
499
500 NPVariant browserResult;
501 browser->invoke(obj->npp, windowScriptObject, callbackIdentifier, &args[1], 1, &browserResult);
502 browser->releasevariantvalue(&browserResult);
503
504 VOID_TO_NPVARIANT(*result);
505 return true;
506}
507
508static bool testCallback(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
509{
510 if (!argCount || !NPVARIANT_IS_STRING(args[0]))
511 return false;
512
513 NPObject* windowScriptObject;
514 browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject);
515
516 NPUTF8* callbackString = createCStringFromNPVariant(&args[0]);
517 NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackString);
518 free(callbackString);
519
520 NPVariant browserResult;
521 if (browser->invoke(obj->npp, windowScriptObject, callbackIdentifier, 0, 0, &browserResult))
522 browser->releasevariantvalue(&browserResult);
523
524 browser->releaseobject(windowScriptObject);
525
526 VOID_TO_NPVARIANT(*result);
527 return true;
528}
529
530static bool testCallbackReturn(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
531{
532 if (argCount != 1 || !NPVARIANT_IS_STRING(args[0]))
533 return false;
534
535 NPObject* windowScriptObject;
536 browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject);
537
538 NPUTF8* callbackString = createCStringFromNPVariant(&args[0]);
539 NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackString);
540 free(callbackString);
541
542 NPVariant callbackArgs[1];
543 OBJECT_TO_NPVARIANT(windowScriptObject, callbackArgs[0]);
544
545 NPVariant browserResult;
546 browser->invoke(obj->npp, windowScriptObject, callbackIdentifier,
547 callbackArgs, 1, &browserResult);
548
549 if (NPVARIANT_IS_OBJECT(browserResult))
550 OBJECT_TO_NPVARIANT(NPVARIANT_TO_OBJECT(browserResult), *result);
551 else {
552 browser->releasevariantvalue(&browserResult);
553 VOID_TO_NPVARIANT(*result);
554 }
555
556 return true;
557}
558
559static bool getURL(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
560{
561 if (argCount == 2 && NPVARIANT_IS_STRING(args[0]) && NPVARIANT_IS_STRING(args[1])) {
562 NPUTF8* urlString = createCStringFromNPVariant(&args[0]);
563 NPUTF8* targetString = createCStringFromNPVariant(&args[1]);
564 NPError npErr = browser->geturl(obj->npp, urlString, targetString);
565 free(urlString);
566 free(targetString);
567
568 INT32_TO_NPVARIANT(npErr, *result);
569 return true;
570 }
571 if (argCount == 1 && NPVARIANT_IS_STRING(args[0])) {
572 NPUTF8* urlString = createCStringFromNPVariant(&args[0]);
573 NPError npErr = browser->geturl(obj->npp, urlString, 0);
574 free(urlString);
575
576 INT32_TO_NPVARIANT(npErr, *result);
577 return true;
578 }
579 return false;
580}
581
582static bool getURLNotify(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
583{
584 if (argCount != 3 || !NPVARIANT_IS_STRING(args[0])
585 || (!NPVARIANT_IS_STRING(args[1]) && !NPVARIANT_IS_NULL(args[1]))
586 || !NPVARIANT_IS_STRING(args[2]))
587 return false;
588
589 NPUTF8* urlString = createCStringFromNPVariant(&args[0]);
590 NPUTF8* targetString = (NPVARIANT_IS_STRING(args[1]) ? createCStringFromNPVariant(&args[1]) : 0);
591 NPUTF8* callbackString = createCStringFromNPVariant(&args[2]);
592
593 NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackString);
594 browser->geturlnotify(obj->npp, urlString, targetString, callbackIdentifier);
595
596 free(urlString);
597 free(targetString);
598 free(callbackString);
599
600 VOID_TO_NPVARIANT(*result);
601 return true;
602}
603
604static bool testInvokeDefault(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
605{
606 if (!NPVARIANT_IS_OBJECT(args[0]))
607 return false;
608
609 NPObject* callback = NPVARIANT_TO_OBJECT(args[0]);
610
611 NPVariant invokeArgs[1];
612 NPVariant browserResult;
613
614 STRINGZ_TO_NPVARIANT("test", invokeArgs[0]);
615 bool retval = browser->invokeDefault(obj->npp, callback, invokeArgs, 1, &browserResult);
616
617 if (retval)
618 browser->releasevariantvalue(&browserResult);
619
620 BOOLEAN_TO_NPVARIANT(retval, *result);
621 return true;
622}
623
624static bool destroyStream(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
625{
626 NPError npError = browser->destroystream(obj->npp, obj->stream, NPRES_USER_BREAK);
627 INT32_TO_NPVARIANT(npError, *result);
628 return true;
629}
630
631static bool destroyNullStream(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
632{
633 NPError npError = browser->destroystream(obj->npp, 0, NPRES_USER_BREAK);
634 INT32_TO_NPVARIANT(npError, *result);
635 return true;
636}
637
638static bool testEnumerate(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
639{
640 if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_OBJECT(args[1]))
641 return false;
642
643 uint32_t count;
644 NPIdentifier* identifiers;
645 if (browser->enumerate(obj->npp, NPVARIANT_TO_OBJECT(args[0]), &identifiers, &count)) {
646 NPObject* outArray = NPVARIANT_TO_OBJECT(args[1]);
647 NPIdentifier pushIdentifier = browser->getstringidentifier("push");
648
649 for (uint32_t i = 0; i < count; i++) {
650 NPUTF8* string = browser->utf8fromidentifier(identifiers[i]);
651
652 if (!string)
653 continue;
654
655 NPVariant args[1];
656 STRINGZ_TO_NPVARIANT(string, args[0]);
657 NPVariant browserResult;
658 if (browser->invoke(obj->npp, outArray, pushIdentifier, args, 1, &browserResult))
659 browser->releasevariantvalue(&browserResult);
660 browser->memfree(string);
661 }
662
663 browser->memfree(identifiers);
664 }
665
666 VOID_TO_NPVARIANT(*result);
667 return true;
668}
669
670static bool testGetIntIdentifier(PluginObject*, const NPVariant* args, uint32_t argCount, NPVariant* result)
671{
672 if (argCount != 1 || !NPVARIANT_IS_DOUBLE(args[0]))
673 return false;
674
675 NPIdentifier identifier = browser->getintidentifier((int)NPVARIANT_TO_DOUBLE(args[0]));
676 INT32_TO_NPVARIANT((int32_t)(long long)identifier, *result);
677 return true;
678}
679
680static bool testGetProperty(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
681{
682 if (!argCount)
683 return false;
684
685 NPObject* object;
686 browser->getvalue(obj->npp, NPNVWindowNPObject, &object);
687
688 for (uint32_t i = 0; i < argCount; i++) {
689 assert(NPVARIANT_IS_STRING(args[i]));
690 NPUTF8* propertyString = createCStringFromNPVariant(&args[i]);
691 NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyString);
692 free(propertyString);
693
694 NPVariant variant;
695 bool retval = browser->getproperty(obj->npp, object, propertyIdentifier, &variant);
696 browser->releaseobject(object);
697
698 if (!retval)
699 break;
700
701 if (i + 1 < argCount) {
702 assert(NPVARIANT_IS_OBJECT(variant));
703 object = NPVARIANT_TO_OBJECT(variant);
704 } else {
705 *result = variant;
706 return true;
707 }
708 }
709
710 VOID_TO_NPVARIANT(*result);
711 return false;
712}
713
714static bool testHasProperty(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
715{
716 if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_STRING(args[1]))
717 return false;
718
719 NPUTF8* propertyString = createCStringFromNPVariant(&args[1]);
720 NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyString);
721 free(propertyString);
722
723 bool retval = browser->hasproperty(obj->npp, NPVARIANT_TO_OBJECT(args[0]), propertyIdentifier);
724
725 BOOLEAN_TO_NPVARIANT(retval, *result);
726 return true;
727}
728
729static bool testHasMethod(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
730{
731 if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_STRING(args[1]))
732 return false;
733
734 NPUTF8* propertyString = createCStringFromNPVariant(&args[1]);
735 NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyString);
736 free(propertyString);
737
738 bool retval = browser->hasmethod(obj->npp, NPVARIANT_TO_OBJECT(args[0]), propertyIdentifier);
739
740 BOOLEAN_TO_NPVARIANT(retval, *result);
741 return true;
742}
743
744static bool testEvaluate(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
745{
746 if (argCount != 1 || !NPVARIANT_IS_STRING(args[0]))
747 return false;
748 NPObject* windowScriptObject;
749 browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject);
750
751 NPString s = NPVARIANT_TO_STRING(args[0]);
752
753 bool retval = browser->evaluate(obj->npp, windowScriptObject, &s, result);
754 browser->releaseobject(windowScriptObject);
755 return retval;
756}
757
758static bool testGetPropertyReturnValue(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
759{
760 if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_STRING(args[1]))
761 return false;
762
763 NPUTF8* propertyString = createCStringFromNPVariant(&args[1]);
764 NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyString);
765 free(propertyString);
766
767 NPVariant variant;
768 bool retval = browser->getproperty(obj->npp, NPVARIANT_TO_OBJECT(args[0]), propertyIdentifier, &variant);
769 if (retval)
770 browser->releasevariantvalue(&variant);
771
772 BOOLEAN_TO_NPVARIANT(retval, *result);
773 return true;
774}
775
776static std::unique_ptr<char[]> toCString(const NPString& string)
777{
778 size_t length = string.UTF8Length;
779 std::unique_ptr<char[]> result(new char[length + 1]);
780 if (!result)
781 return result;
782
783 memcpy(result.get(), string.UTF8Characters, length);
784 result[length] = '\0';
785
786 return result;
787}
788
789static bool testPostURLFile(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
790{
791 if (argCount != 4 || !NPVARIANT_IS_STRING(args[0]) || !NPVARIANT_IS_STRING(args[1]) || !NPVARIANT_IS_STRING(args[2]) || !NPVARIANT_IS_STRING(args[3]))
792 return false;
793
794 NPString urlString = NPVARIANT_TO_STRING(args[0]);
795 auto url = toCString(urlString);
796
797 NPString targetString = NPVARIANT_TO_STRING(args[1]);
798 auto target = toCString(targetString);
799
800 NPString pathString = NPVARIANT_TO_STRING(args[2]);
801 auto path = toCString(pathString);
802
803 NPString contentsString = NPVARIANT_TO_STRING(args[3]);
804
805 FILE* tempFile = fopen(path.get(), "w");
806 if (!tempFile)
807 return false;
808
809 size_t count = fwrite(contentsString.UTF8Characters, contentsString.UTF8Length, 1, tempFile);
810 fclose(tempFile);
811
812 if (!count)
813 return false;
814
815 NPError error = browser->posturl(obj->npp, url.get(), target.get(), pathString.UTF8Length, path.get(), TRUE);
816
817 BOOLEAN_TO_NPVARIANT(error == NPERR_NO_ERROR, *result);
818 return true;
819}
820
821static bool testConstruct(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
822{
823 if (!argCount || !NPVARIANT_IS_OBJECT(args[0]))
824 return false;
825
826 return browser->construct(obj->npp, NPVARIANT_TO_OBJECT(args[0]), args + 1, argCount - 1, result);
827}
828
829// Invoke a script callback to get a script NPObject. Then call a method on the
830// script NPObject passing it a freshly created NPObject.
831static bool testScriptObjectInvoke(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
832{
833 if (argCount != 2 || !NPVARIANT_IS_STRING(args[0]) || !NPVARIANT_IS_STRING(args[1]))
834 return false;
835 NPObject* windowScriptObject;
836 browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject);
837
838 // Arg1 is the name of the callback
839 NPUTF8* callbackString = createCStringFromNPVariant(&args[0]);
840 NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackString);
841 free(callbackString);
842
843 // Invoke a callback that returns a script object
844 NPVariant object_result;
845 browser->invoke(obj->npp, windowScriptObject, callbackIdentifier, &args[1], 1, &object_result);
846
847 // Script object returned
848 NPObject* script_object = object_result.value.objectValue;
849
850 // Arg2 is the name of the method to be called on the script object
851 NPUTF8* object_mehod_string = createCStringFromNPVariant(&args[1]);
852 NPIdentifier object_method = browser->getstringidentifier(object_mehod_string);
853 free(object_mehod_string);
854
855 // Create a fresh NPObject to be passed as an argument
856 NPObject* object_arg = browser->createobject(obj->npp, &pluginClass);
857 NPVariant invoke_args[1];
858 OBJECT_TO_NPVARIANT(object_arg, invoke_args[0]);
859
860 // Invoke the script method
861 NPVariant object_method_result;
862 browser->invoke(obj->npp, script_object, object_method, invoke_args, 1, &object_method_result);
863
864 browser->releasevariantvalue(&object_result);
865 VOID_TO_NPVARIANT(*result);
866 if (NPVARIANT_IS_OBJECT(object_method_result)) {
867 // Now return the callbacks return value back to our caller.
868 // BUG 897451: This should be the same as the
869 // windowScriptObject, but its not (in Chrome) - or at least, it
870 // has a different refcount. This means Chrome will delete the
871 // object before returning it and the calling JS gets a garbage
872 // value. Firefox handles it fine.
873 OBJECT_TO_NPVARIANT(NPVARIANT_TO_OBJECT(object_method_result), *result);
874 } else {
875 browser->releasevariantvalue(&object_method_result);
876 VOID_TO_NPVARIANT(*result);
877 }
878
879 browser->releaseobject(object_arg);
880
881 return true;
882}
883
884// Helper function to notify the layout test controller that the test completed.
885void notifyTestCompletion(NPP npp, NPObject* object)
886{
887 NPVariant result;
888 NPString script;
889 script.UTF8Characters = "javascript:window.testRunner.notifyDone();";
890 script.UTF8Length = strlen("javascript:window.testRunner.notifyDone();");
891 browser->evaluate(npp, object, &script, &result);
892 browser->releasevariantvalue(&result);
893}
894
895bool testDocumentOpen(NPP npp)
896{
897 NPIdentifier documentId = browser->getstringidentifier("document");
898 NPIdentifier openId = browser->getstringidentifier("open");
899
900 NPObject* windowObject = 0;
901 browser->getvalue(npp, NPNVWindowNPObject, &windowObject);
902 if (!windowObject)
903 return false;
904
905 NPVariant docVariant;
906 browser->getproperty(npp, windowObject, documentId, &docVariant);
907 if (docVariant.type != NPVariantType_Object) {
908 browser->releaseobject(windowObject);
909 return false;
910 }
911
912 NPObject* documentObject = NPVARIANT_TO_OBJECT(docVariant);
913
914 NPVariant openArgs[2];
915 STRINGZ_TO_NPVARIANT("text/html", openArgs[0]);
916 STRINGZ_TO_NPVARIANT("_blank", openArgs[1]);
917
918 NPVariant result;
919 if (!browser->invoke(npp, documentObject, openId, openArgs, 2, &result)) {
920 browser->releaseobject(windowObject);
921 browser->releaseobject(documentObject);
922 return false;
923 }
924
925 browser->releaseobject(documentObject);
926
927 if (result.type != NPVariantType_Object) {
928 browser->releaseobject(windowObject);
929 browser->releasevariantvalue(&result);
930 return false;
931 }
932
933 pluginLogWithWindowObject(windowObject, npp, "PLUGIN: DOCUMENT OPEN SUCCESS");
934 notifyTestCompletion(npp, result.value.objectValue);
935 browser->releaseobject(result.value.objectValue);
936 browser->releaseobject(windowObject);
937 return true;
938}
939
940bool testWindowOpen(NPP npp)
941{
942 NPIdentifier openId = browser->getstringidentifier("open");
943
944 NPObject* windowObject = 0;
945 browser->getvalue(npp, NPNVWindowNPObject, &windowObject);
946 if (!windowObject)
947 return false;
948
949 NPVariant openArgs[2];
950 STRINGZ_TO_NPVARIANT("about:blank", openArgs[0]);
951 STRINGZ_TO_NPVARIANT("_blank", openArgs[1]);
952
953 NPVariant result;
954 if (!browser->invoke(npp, windowObject, openId, openArgs, 2, &result)) {
955 browser->releaseobject(windowObject);
956 return false;
957 }
958
959 if (result.type != NPVariantType_Object) {
960 browser->releaseobject(windowObject);
961 browser->releasevariantvalue(&result);
962 return false;
963 }
964
965 pluginLogWithWindowObject(windowObject, npp, "PLUGIN: WINDOW OPEN SUCCESS");
966 notifyTestCompletion(npp, result.value.objectValue);
967 browser->releaseobject(result.value.objectValue);
968 browser->releaseobject(windowObject);
969 return true;
970}
971
972static bool testSetStatus(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
973{
974 std::unique_ptr<char[]> message;
975 if (argCount && NPVARIANT_IS_STRING(args[0])) {
976 NPString statusString = NPVARIANT_TO_STRING(args[0]);
977 message = toCString(statusString);
978 }
979
980 browser->status(obj->npp, message.get());
981
982 return true;
983}
984
985static bool testResizeTo(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
986{
987 VOID_TO_NPVARIANT(*result);
988
989 NPObject* windowObject;
990 if (NPERR_NO_ERROR != browser->getvalue(obj->npp, NPNVWindowNPObject, &windowObject))
991 return false;
992
993 NPVariant callResult;
994 if (browser->invoke(obj->npp, windowObject, browser->getstringidentifier("resizePlugin"), args, argCount, &callResult))
995 browser->releasevariantvalue(&callResult);
996
997 // Force layout.
998 if (browser->getproperty(obj->npp, windowObject, browser->getstringidentifier("pageYOffset"), &callResult))
999 browser->releasevariantvalue(&callResult);
1000
1001 return true;
1002}
1003
1004static bool normalizeOverride(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
1005{
1006 VOID_TO_NPVARIANT(*result);
1007
1008 NPObject* windowObject;
1009 if (NPERR_NO_ERROR != browser->getvalue(obj->npp, NPNVWindowNPObject, &windowObject))
1010 return false;
1011
1012 NPVariant callResult;
1013 if (browser->invoke(obj->npp, windowObject, browser->getstringidentifier("pluginCallback"), args, argCount, &callResult))
1014 browser->releasevariantvalue(&callResult);
1015
1016 return true;
1017}
1018
1019static bool invalidateRect(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
1020{
1021 if (argCount != 4)
1022 return false;
1023
1024 NPRect rect;
1025 rect.left = static_cast<int>(NPVARIANT_TO_DOUBLE(args[0]));
1026 rect.top = static_cast<int>(NPVARIANT_TO_DOUBLE(args[1]));
1027 rect.right = static_cast<int>(NPVARIANT_TO_DOUBLE(args[2]));
1028 rect.bottom = static_cast<int>(NPVARIANT_TO_DOUBLE(args[3]));
1029
1030 browser->invalidaterect(obj->npp, &rect);
1031 return true;
1032}
1033
1034static bool objectsAreSame(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result)
1035{
1036 if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_OBJECT(args[1]))
1037 return false;
1038
1039 BOOLEAN_TO_NPVARIANT(NPVARIANT_TO_OBJECT(args[0]) == NPVARIANT_TO_OBJECT(args[1]), *result);
1040 return true;
1041}
1042
1043static bool pluginInvoke(NPObject* header, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result)
1044{
1045 PluginObject* plugin = reinterpret_cast<PluginObject*>(header);
1046 if (name == pluginMethodIdentifiers[ID_TEST_CALLBACK_METHOD])
1047 return testCallback(plugin, args, argCount, result);
1048 if (name == pluginMethodIdentifiers[ID_TEST_CALLBACK_METHOD_RETURN])
1049 return testCallbackReturn(plugin, args, argCount, result);
1050 if (name == pluginMethodIdentifiers[ID_TEST_GETURL])
1051 return getURL(plugin, args, argCount, result);
1052 if (name == pluginMethodIdentifiers[ID_TEST_DOM_ACCESS])
1053 return testDOMAccess(plugin, args, argCount, result);
1054 if (name == pluginMethodIdentifiers[ID_TEST_GET_URL_NOTIFY])
1055 return getURLNotify(plugin, args, argCount, result);
1056 if (name == pluginMethodIdentifiers[ID_TEST_INVOKE_DEFAULT])
1057 return testInvokeDefault(plugin, args, argCount, result);
1058 if (name == pluginMethodIdentifiers[ID_TEST_ENUMERATE])
1059 return testEnumerate(plugin, args, argCount, result);
1060 if (name == pluginMethodIdentifiers[ID_DESTROY_STREAM])
1061 return destroyStream(plugin, args, argCount, result);
1062 if (name == pluginMethodIdentifiers[ID_TEST_GETINTIDENTIFIER])
1063 return testGetIntIdentifier(plugin, args, argCount, result);
1064 if (name == pluginMethodIdentifiers[ID_TEST_EVALUATE])
1065 return testEvaluate(plugin, args, argCount, result);
1066 if (name == pluginMethodIdentifiers[ID_TEST_GET_PROPERTY])
1067 return testGetProperty(plugin, args, argCount, result);
1068 if (name == pluginMethodIdentifiers[ID_TEST_GET_PROPERTY_RETURN_VALUE])
1069 return testGetPropertyReturnValue(plugin, args, argCount, result);
1070 if (name == pluginMethodIdentifiers[ID_TEST_HAS_PROPERTY])
1071 return testHasProperty(plugin, args, argCount, result);
1072 if (name == pluginMethodIdentifiers[ID_TEST_HAS_METHOD])
1073 return testHasMethod(plugin, args, argCount, result);
1074 if (name == pluginMethodIdentifiers[ID_TEST_IDENTIFIER_TO_STRING])
1075 return testIdentifierToString(plugin, args, argCount, result);
1076 if (name == pluginMethodIdentifiers[ID_TEST_IDENTIFIER_TO_INT])
1077 return testIdentifierToInt(plugin, args, argCount, result);
1078 if (name == pluginMethodIdentifiers[ID_TEST_PASS_TEST_OBJECT])
1079 return testPassTestObject(plugin, args, argCount, result);
1080 if (name == pluginMethodIdentifiers[ID_TEST_POSTURL_FILE])
1081 return testPostURLFile(plugin, args, argCount, result);
1082 if (name == pluginMethodIdentifiers[ID_TEST_CONSTRUCT])
1083 return testConstruct(plugin, args, argCount, result);
1084 if (name == pluginMethodIdentifiers[ID_TEST_SCRIPT_OBJECT_INVOKE])
1085 return testScriptObjectInvoke(plugin, args, argCount, result);
1086 if (name == pluginMethodIdentifiers[ID_TEST_THROW_EXCEPTION_METHOD]) {
1087 browser->setexception(header, "plugin object testThrowException SUCCESS");
1088 return true;
1089 }
1090 if (name == pluginMethodIdentifiers[ID_TEST_FAIL_METHOD]) {
1091 NPObject* windowScriptObject;
1092 browser->getvalue(plugin->npp, NPNVWindowNPObject, &windowScriptObject);
1093 browser->invoke(plugin->npp, windowScriptObject, name, args, argCount, result);
1094 return false;
1095 }
1096 if (name == pluginMethodIdentifiers[ID_TEST_CLONE_OBJECT]) {
1097 NPObject* new_object = browser->createobject(plugin->npp, &pluginClass);
1098 assert(new_object->referenceCount == 1);
1099 OBJECT_TO_NPVARIANT(new_object, *result);
1100 return true;
1101 }
1102 if (name == pluginMethodIdentifiers[ID_TEST_CREATE_TEST_OBJECT]) {
1103 NPObject* testObject = browser->createobject(plugin->npp, getTestClass());
1104 assert(testObject->referenceCount == 1);
1105 OBJECT_TO_NPVARIANT(testObject, *result);
1106 return true;
1107 }
1108 if (name == pluginMethodIdentifiers[ID_DESTROY_NULL_STREAM])
1109 return destroyNullStream(plugin, args, argCount, result);
1110 if (name == pluginMethodIdentifiers[ID_TEST_RELOAD_PLUGINS_NO_PAGES]) {
1111 browser->reloadplugins(false);
1112 return true;
1113 }
1114 if (name == pluginMethodIdentifiers[ID_TEST_RELOAD_PLUGINS_AND_PAGES]) {
1115 browser->reloadplugins(true);
1116 return true;
1117 }
1118 if (name == pluginMethodIdentifiers[ID_TEST_GET_BROWSER_PROPERTY]) {
1119 browser->getproperty(plugin->npp, NPVARIANT_TO_OBJECT(args[0]), stringVariantToIdentifier(args[1]), result);
1120 return true;
1121 }
1122 if (name == pluginMethodIdentifiers[ID_TEST_SET_BROWSER_PROPERTY]) {
1123 browser->setproperty(plugin->npp, NPVARIANT_TO_OBJECT(args[0]), stringVariantToIdentifier(args[1]), &args[2]);
1124 return true;
1125 }
1126 if (name == pluginMethodIdentifiers[ID_REMEMBER]) {
1127 if (plugin->rememberedObject)
1128 browser->releaseobject(plugin->rememberedObject);
1129 plugin->rememberedObject = NPVARIANT_TO_OBJECT(args[0]);
1130 browser->retainobject(plugin->rememberedObject);
1131 VOID_TO_NPVARIANT(*result);
1132 return true;
1133 }
1134 if (name == pluginMethodIdentifiers[ID_GET_REMEMBERED_OBJECT]) {
1135 assert(plugin->rememberedObject);
1136 browser->retainobject(plugin->rememberedObject);
1137 OBJECT_TO_NPVARIANT(plugin->rememberedObject, *result);
1138 return true;
1139 }
1140 if (name == pluginMethodIdentifiers[ID_GET_AND_FORGET_REMEMBERED_OBJECT]) {
1141 assert(plugin->rememberedObject);
1142 OBJECT_TO_NPVARIANT(plugin->rememberedObject, *result);
1143 plugin->rememberedObject = 0;
1144 return true;
1145 }
1146 if (name == pluginMethodIdentifiers[ID_REF_COUNT]) {
1147 uint32_t refCount = NPVARIANT_TO_OBJECT(args[0])->referenceCount;
1148 INT32_TO_NPVARIANT(refCount, *result);
1149 return true;
1150 }
1151 if (name == pluginMethodIdentifiers[ID_SET_STATUS])
1152 return testSetStatus(plugin, args, argCount, result);
1153 if (name == pluginMethodIdentifiers[ID_RESIZE_TO])
1154 return testResizeTo(plugin, args, argCount, result);
1155 if (name == pluginMethodIdentifiers[ID_NORMALIZE])
1156 return normalizeOverride(plugin, args, argCount, result);
1157 if (name == pluginMethodIdentifiers[ID_INVALIDATE_RECT])
1158 return invalidateRect(plugin, args, argCount, result);
1159 if (name == pluginMethodIdentifiers[ID_OBJECTS_ARE_SAME])
1160 return objectsAreSame(plugin, args, argCount, result);
1161 if (name == pluginMethodIdentifiers[ID_TEST_DELETE_WITHIN_INVOKE]) {
1162 NPObject* newObject = browser->createobject(plugin->npp, &pluginClass);
1163 OBJECT_TO_NPVARIANT(newObject, *result);
1164 callDeletePlugin(header, name, pluginMethodIdentifiers[ID_TEST_DELETE_WITHIN_INVOKE]);
1165 return true;
1166 }
1167 return false;
1168}
1169
1170static void pluginInvalidate(NPObject* header)
1171{
1172 PluginObject* plugin = reinterpret_cast<PluginObject*>(header);
1173 plugin->testObject = 0;
1174 plugin->rememberedObject = 0;
1175}
1176
1177static NPObject *pluginAllocate(NPP npp, NPClass *theClass)
1178{
1179 PluginObject* newInstance = (PluginObject*)malloc(sizeof(PluginObject));
1180
1181 if (!identifiersInitialized) {
1182 identifiersInitialized = true;
1183 initializeIdentifiers();
1184 }
1185
1186 newInstance->pluginTest = 0;
1187 newInstance->npp = npp;
1188 newInstance->testObject = browser->createobject(npp, getTestClass());
1189 newInstance->rememberedObject = 0;
1190 newInstance->eventLogging = FALSE;
1191 newInstance->onStreamLoad = 0;
1192 newInstance->onStreamDestroy = 0;
1193 newInstance->onDestroy = 0;
1194 newInstance->onURLNotify = 0;
1195 newInstance->onSetWindow = 0;
1196 newInstance->onPaintEvent = 0;
1197 newInstance->logDestroy = FALSE;
1198 newInstance->logSetWindow = FALSE;
1199 newInstance->returnErrorFromNewStream = FALSE;
1200 newInstance->returnNegativeOneFromWrite = FALSE;
1201 newInstance->stream = 0;
1202
1203 newInstance->firstUrl = 0;
1204 newInstance->firstHeaders = 0;
1205 newInstance->lastUrl = 0;
1206 newInstance->lastHeaders = 0;
1207
1208 newInstance->testGetURLOnDestroy = FALSE;
1209 newInstance->testWindowOpen = FALSE;
1210 newInstance->testKeyboardFocusForPlugins = FALSE;
1211
1212 newInstance->mouseDownForEvaluateScript = FALSE;
1213 newInstance->evaluateScriptOnMouseDownOrKeyDown = 0;
1214
1215 return (NPObject*)newInstance;
1216}
1217
1218static void pluginDeallocate(NPObject* header)
1219{
1220 PluginObject* plugin = reinterpret_cast<PluginObject*>(header);
1221 delete plugin->pluginTest;
1222 if (plugin->testObject)
1223 browser->releaseobject(plugin->testObject);
1224 if (plugin->rememberedObject)
1225 browser->releaseobject(plugin->rememberedObject);
1226
1227 free(plugin->firstUrl);
1228 free(plugin->firstHeaders);
1229 free(plugin->lastUrl);
1230 free(plugin->lastHeaders);
1231 free(plugin);
1232}
1233
1234void handleCallback(PluginObject* object, const char *url, NPReason reason, void *notifyData)
1235{
1236 assert(object);
1237
1238 NPVariant args[2];
1239
1240 NPObject* windowScriptObject;
1241 browser->getvalue(object->npp, NPNVWindowNPObject, &windowScriptObject);
1242
1243 NPIdentifier callbackIdentifier = notifyData;
1244
1245 INT32_TO_NPVARIANT(reason, args[0]);
1246
1247 char* strHdr = 0;
1248 if (object->firstUrl && object->firstHeaders && object->lastUrl && object->lastHeaders) {
1249 // Format expected by JavaScript validator: four fields separated by \n\n:
1250 // First URL; first header block; last URL; last header block.
1251 // Note that header blocks already end with \n due to how NPStream::headers works.
1252 int len = strlen(object->firstUrl) + 2
1253 + strlen(object->firstHeaders) + 1
1254 + strlen(object->lastUrl) + 2
1255 + strlen(object->lastHeaders) + 1;
1256 strHdr = (char*)malloc(len + 1);
1257 snprintf(strHdr, len + 1, "%s\n\n%s\n%s\n\n%s\n",
1258 object->firstUrl, object->firstHeaders, object->lastUrl, object->lastHeaders);
1259 STRINGN_TO_NPVARIANT(strHdr, len, args[1]);
1260 } else
1261 NULL_TO_NPVARIANT(args[1]);
1262
1263 NPVariant browserResult;
1264 if (browser->invoke(object->npp, windowScriptObject, callbackIdentifier, args, 2, &browserResult))
1265 browser->releasevariantvalue(&browserResult);
1266
1267 free(strHdr);
1268}
1269
1270void notifyStream(PluginObject* object, const char *url, const char *headers)
1271{
1272 if (!object->firstUrl) {
1273 if (url)
1274 object->firstUrl = strdup(url);
1275 if (headers)
1276 object->firstHeaders = strdup(headers);
1277 } else {
1278 free(object->lastUrl);
1279 free(object->lastHeaders);
1280 object->lastUrl = (url ? strdup(url) : 0);
1281 object->lastHeaders = (headers ? strdup(headers) : 0);
1282 }
1283}
1284
1285void testNPRuntime(NPP npp)
1286{
1287 NPObject* windowScriptObject;
1288 browser->getvalue(npp, NPNVWindowNPObject, &windowScriptObject);
1289
1290 // Invoke
1291 NPIdentifier testNPInvoke = browser->getstringidentifier("testNPInvoke");
1292 NPVariant args[7];
1293
1294 VOID_TO_NPVARIANT(args[0]);
1295 NULL_TO_NPVARIANT(args[1]);
1296 BOOLEAN_TO_NPVARIANT(true, args[2]);
1297 INT32_TO_NPVARIANT(242, args[3]);
1298 DOUBLE_TO_NPVARIANT(242.242, args[4]);
1299 STRINGZ_TO_NPVARIANT("Hello, World", args[5]);
1300 OBJECT_TO_NPVARIANT(windowScriptObject, args[6]);
1301
1302 NPVariant result;
1303 if (browser->invoke(npp, windowScriptObject, testNPInvoke, args, 7, &result))
1304 browser->releasevariantvalue(&result);
1305
1306 browser->releaseobject(windowScriptObject);
1307}
1308