1/* 2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. 3 * Copyright (C) 2009 Holger Hans Peter Freyther 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include "PluginObject.h" 28 29#include "TestObject.h" 30#include <assert.h> 31#include <stdarg.h> 32#include <stdio.h> 33 34#include <string.h> 35#include <stdlib.h> 36 37// Helper function which takes in the plugin window object for logging to the console object. 38static void pluginLogWithWindowObject(NPObject* windowObject, NPP instance, const char* message) 39{ 40 NPVariant consoleVariant; 41 if (!browser->getproperty(instance, windowObject, browser->getstringidentifier("console"), &consoleVariant)) { 42 fprintf(stderr, "Failed to retrieve console object while logging: %s\n", message); 43 return; 44 } 45 46 NPObject* consoleObject = NPVARIANT_TO_OBJECT(consoleVariant); 47 48 NPVariant messageVariant; 49 STRINGZ_TO_NPVARIANT(message, messageVariant); 50 51 NPVariant result; 52 if (!browser->invoke(instance, consoleObject, browser->getstringidentifier("log"), &messageVariant, 1, &result)) { 53 fprintf(stderr, "Failed to invoke console.log while logging: %s\n", message); 54 browser->releaseobject(consoleObject); 55 return; 56 } 57 58 browser->releasevariantvalue(&result); 59 browser->releaseobject(consoleObject); 60} 61 62// Helper function which takes in the plugin window object for logging to the console object. This function supports variable 63// arguments. 64static void pluginLogWithWindowObjectVariableArgs(NPObject* windowObject, NPP instance, const char* format, ...) 65{ 66 va_list args; 67 va_start(args, format); 68 char message[2048] = "PLUGIN: "; 69 vsprintf(message + strlen(message), format, args); 70 va_end(args); 71 72 pluginLogWithWindowObject(windowObject, instance, message); 73} 74 75// Helper function to log to the console object. 76void pluginLog(NPP instance, const char* format, ...) 77{ 78 va_list args; 79 va_start(args, format); 80 char message[2048] = "PLUGIN: "; 81 vsprintf(message + strlen(message), format, args); 82 va_end(args); 83 84 NPObject* windowObject = 0; 85 NPError error = browser->getvalue(instance, NPNVWindowNPObject, &windowObject); 86 if (error != NPERR_NO_ERROR) { 87 fprintf(stderr, "Failed to retrieve window object while logging: %s\n", message); 88 return; 89 } 90 91 pluginLogWithWindowObject(windowObject, instance, message); 92 browser->releaseobject(windowObject); 93} 94 95static void pluginInvalidate(NPObject*); 96static bool pluginHasProperty(NPObject*, NPIdentifier name); 97static bool pluginHasMethod(NPObject*, NPIdentifier name); 98static bool pluginGetProperty(NPObject*, NPIdentifier name, NPVariant*); 99static bool pluginSetProperty(NPObject*, NPIdentifier name, const NPVariant*); 100static bool pluginInvoke(NPObject*, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result); 101static bool pluginInvokeDefault(NPObject*, const NPVariant* args, uint32_t argCount, NPVariant* result); 102static NPObject* pluginAllocate(NPP npp, NPClass*); 103static void pluginDeallocate(NPObject*); 104 105NPNetscapeFuncs* browser; 106 107static NPClass pluginClass = { 108 NP_CLASS_STRUCT_VERSION, 109 pluginAllocate, 110 pluginDeallocate, 111 pluginInvalidate, 112 pluginHasMethod, 113 pluginInvoke, 114 pluginInvokeDefault, 115 pluginHasProperty, 116 pluginGetProperty, 117 pluginSetProperty, 118}; 119 120NPClass *getPluginClass(void) 121{ 122 return &pluginClass; 123} 124 125static bool identifiersInitialized = false; 126 127enum { 128 ID_PROPERTY_PROPERTY = 0, 129 ID_PROPERTY_EVENT_LOGGING, 130 ID_PROPERTY_HAS_STREAM, 131 ID_PROPERTY_TEST_OBJECT, 132 ID_PROPERTY_LOG_DESTROY, 133 ID_PROPERTY_RETURN_ERROR_FROM_NEWSTREAM, 134 ID_PROPERTY_PRIVATE_BROWSING_ENABLED, 135 ID_PROPERTY_CACHED_PRIVATE_BROWSING_ENABLED, 136 ID_PROPERTY_THROW_EXCEPTION_PROPERTY, 137 NUM_PROPERTY_IDENTIFIERS 138}; 139 140static NPIdentifier pluginPropertyIdentifiers[NUM_PROPERTY_IDENTIFIERS]; 141static const NPUTF8 *pluginPropertyIdentifierNames[NUM_PROPERTY_IDENTIFIERS] = { 142 "property", 143 "eventLoggingEnabled", 144 "hasStream", 145 "testObject", 146 "logDestroy", 147 "returnErrorFromNewStream", 148 "privateBrowsingEnabled", 149 "cachedPrivateBrowsingEnabled", 150 "testThrowExceptionProperty" 151}; 152 153enum { 154 ID_TEST_CALLBACK_METHOD = 0, 155 ID_TEST_GETURL, 156 ID_REMOVE_DEFAULT_METHOD, 157 ID_TEST_DOM_ACCESS, 158 ID_TEST_GET_URL_NOTIFY, 159 ID_TEST_INVOKE_DEFAULT, 160 ID_DESTROY_STREAM, 161 ID_TEST_ENUMERATE, 162 ID_TEST_GETINTIDENTIFIER, 163 ID_TEST_GET_PROPERTY, 164 ID_TEST_HAS_PROPERTY, 165 ID_TEST_HAS_METHOD, 166 ID_TEST_EVALUATE, 167 ID_TEST_GET_PROPERTY_RETURN_VALUE, 168 ID_TEST_IDENTIFIER_TO_STRING, 169 ID_TEST_IDENTIFIER_TO_INT, 170 ID_TEST_POSTURL_FILE, 171 ID_TEST_CONSTRUCT, 172 ID_TEST_THROW_EXCEPTION_METHOD, 173 ID_TEST_FAIL_METHOD, 174 ID_DESTROY_NULL_STREAM, 175 ID_TEST_RELOAD_PLUGINS_NO_PAGES, 176 ID_TEST_RELOAD_PLUGINS_AND_PAGES, 177 ID_TEST_GET_BROWSER_PROPERTY, 178 ID_TEST_SET_BROWSER_PROPERTY, 179 NUM_METHOD_IDENTIFIERS 180}; 181 182static NPIdentifier pluginMethodIdentifiers[NUM_METHOD_IDENTIFIERS]; 183static const NPUTF8 *pluginMethodIdentifierNames[NUM_METHOD_IDENTIFIERS] = { 184 "testCallback", 185 "getURL", 186 "removeDefaultMethod", 187 "testDOMAccess", 188 "getURLNotify", 189 "testInvokeDefault", 190 "destroyStream", 191 "testEnumerate", 192 "testGetIntIdentifier", 193 "testGetProperty", 194 "testHasProperty", 195 "testHasMethod", 196 "testEvaluate", 197 "testGetPropertyReturnValue", 198 "testIdentifierToString", 199 "testIdentifierToInt", 200 "testPostURLFile", 201 "testConstruct", 202 "testThrowException", 203 "testFail", 204 "destroyNullStream", 205 "reloadPluginsNoPages", 206 "reloadPluginsAndPages", 207 "testGetBrowserProperty", 208 "testSetBrowserProperty" 209}; 210 211static NPUTF8* createCStringFromNPVariant(const NPVariant* variant) 212{ 213 size_t length = NPVARIANT_TO_STRING(*variant).UTF8Length; 214 NPUTF8* result = (NPUTF8*)malloc(length + 1); 215 memcpy(result, NPVARIANT_TO_STRING(*variant).UTF8Characters, length); 216 result[length] = '\0'; 217 return result; 218} 219 220static void initializeIdentifiers(void) 221{ 222 browser->getstringidentifiers(pluginPropertyIdentifierNames, NUM_PROPERTY_IDENTIFIERS, pluginPropertyIdentifiers); 223 browser->getstringidentifiers(pluginMethodIdentifierNames, NUM_METHOD_IDENTIFIERS, pluginMethodIdentifiers); 224} 225 226static bool pluginHasProperty(NPObject *obj, NPIdentifier name) 227{ 228 for (int i = 0; i < NUM_PROPERTY_IDENTIFIERS; i++) 229 if (name == pluginPropertyIdentifiers[i]) 230 return true; 231 return false; 232} 233 234static bool pluginHasMethod(NPObject *obj, NPIdentifier name) 235{ 236 for (int i = 0; i < NUM_METHOD_IDENTIFIERS; i++) 237 if (name == pluginMethodIdentifiers[i]) 238 return true; 239 return false; 240} 241 242static bool pluginGetProperty(NPObject* obj, NPIdentifier name, NPVariant* result) 243{ 244 PluginObject* plugin = reinterpret_cast<PluginObject*>(obj); 245 if (name == pluginPropertyIdentifiers[ID_PROPERTY_PROPERTY]) { 246 STRINGZ_TO_NPVARIANT("property", *result); 247 return true; 248 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_EVENT_LOGGING]) { 249 BOOLEAN_TO_NPVARIANT(plugin->eventLogging, *result); 250 return true; 251 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_LOG_DESTROY]) { 252 BOOLEAN_TO_NPVARIANT(plugin->logDestroy, *result); 253 return true; 254 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_HAS_STREAM]) { 255 BOOLEAN_TO_NPVARIANT(plugin->stream != 0, *result); 256 return true; 257 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_TEST_OBJECT]) { 258 NPObject* testObject = plugin->testObject; 259 browser->retainobject(testObject); 260 OBJECT_TO_NPVARIANT(testObject, *result); 261 return true; 262 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_RETURN_ERROR_FROM_NEWSTREAM]) { 263 BOOLEAN_TO_NPVARIANT(plugin->returnErrorFromNewStream, *result); 264 return true; 265 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_PRIVATE_BROWSING_ENABLED]) { 266 NPBool privateBrowsingEnabled = FALSE; 267 browser->getvalue(plugin->npp, NPNVprivateModeBool, &privateBrowsingEnabled); 268 BOOLEAN_TO_NPVARIANT(privateBrowsingEnabled, *result); 269 return true; 270 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_CACHED_PRIVATE_BROWSING_ENABLED]) { 271 BOOLEAN_TO_NPVARIANT(plugin->cachedPrivateBrowsingMode, *result); 272 return true; 273 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_THROW_EXCEPTION_PROPERTY]) { 274 browser->setexception(obj, "plugin object testThrowExceptionProperty SUCCESS"); 275 return true; 276 } 277 return false; 278} 279 280static bool pluginSetProperty(NPObject* obj, NPIdentifier name, const NPVariant* variant) 281{ 282 PluginObject* plugin = reinterpret_cast<PluginObject*>(obj); 283 if (name == pluginPropertyIdentifiers[ID_PROPERTY_EVENT_LOGGING]) { 284 plugin->eventLogging = NPVARIANT_TO_BOOLEAN(*variant); 285 return true; 286 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_LOG_DESTROY]) { 287 plugin->logDestroy = NPVARIANT_TO_BOOLEAN(*variant); 288 return true; 289 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_RETURN_ERROR_FROM_NEWSTREAM]) { 290 plugin->returnErrorFromNewStream = NPVARIANT_TO_BOOLEAN(*variant); 291 return true; 292 } else if (name == pluginPropertyIdentifiers[ID_PROPERTY_THROW_EXCEPTION_PROPERTY]) { 293 browser->setexception(obj, "plugin object testThrowExceptionProperty SUCCESS"); 294 return true; 295 } 296 297 return false; 298} 299 300static bool testDOMAccess(PluginObject* obj, const NPVariant*, uint32_t, NPVariant* result) 301{ 302 // Get plug-in's DOM element 303 NPObject* elementObject; 304 if (browser->getvalue(obj->npp, NPNVPluginElementNPObject, &elementObject) == NPERR_NO_ERROR) { 305 // Get style 306 NPVariant styleVariant; 307 NPIdentifier styleIdentifier = browser->getstringidentifier("style"); 308 if (browser->getproperty(obj->npp, elementObject, styleIdentifier, &styleVariant) && NPVARIANT_IS_OBJECT(styleVariant)) { 309 // Set style.border 310 NPIdentifier borderIdentifier = browser->getstringidentifier("border"); 311 NPVariant borderVariant; 312 STRINGZ_TO_NPVARIANT("3px solid red", borderVariant); 313 browser->setproperty(obj->npp, NPVARIANT_TO_OBJECT(styleVariant), borderIdentifier, &borderVariant); 314 browser->releasevariantvalue(&styleVariant); 315 } 316 317 browser->releaseobject(elementObject); 318 } 319 VOID_TO_NPVARIANT(*result); 320 return true; 321} 322 323static NPIdentifier stringVariantToIdentifier(NPVariant variant) 324{ 325 assert(NPVARIANT_IS_STRING(variant)); 326 NPUTF8* utf8String = createCStringFromNPVariant(&variant); 327 NPIdentifier identifier = browser->getstringidentifier(utf8String); 328 free(utf8String); 329 return identifier; 330} 331 332static NPIdentifier int32VariantToIdentifier(NPVariant variant) 333{ 334 assert(NPVARIANT_IS_INT32(variant)); 335 int32 integer = NPVARIANT_TO_INT32(variant); 336 return browser->getintidentifier(integer); 337} 338 339static NPIdentifier doubleVariantToIdentifier(NPVariant variant) 340{ 341 assert(NPVARIANT_IS_DOUBLE(variant)); 342 double value = NPVARIANT_TO_DOUBLE(variant); 343 // Sadly there is no "getdoubleidentifier" 344 int32 integer = static_cast<int32>(value); 345 return browser->getintidentifier(integer); 346} 347 348static NPIdentifier variantToIdentifier(NPVariant variant) 349{ 350 if (NPVARIANT_IS_STRING(variant)) 351 return stringVariantToIdentifier(variant); 352 else if (NPVARIANT_IS_INT32(variant)) 353 return int32VariantToIdentifier(variant); 354 else if (NPVARIANT_IS_DOUBLE(variant)) 355 return doubleVariantToIdentifier(variant); 356 return 0; 357} 358 359static bool testIdentifierToString(PluginObject*, const NPVariant* args, uint32_t argCount, NPVariant* result) 360{ 361 if (argCount != 1) 362 return true; 363 NPIdentifier identifier = variantToIdentifier(args[0]); 364 if (!identifier) 365 return true; 366 NPUTF8* utf8String = browser->utf8fromidentifier(identifier); 367 if (!utf8String) 368 return true; 369 STRINGZ_TO_NPVARIANT(utf8String, *result); 370 return true; 371} 372 373static bool testIdentifierToInt(PluginObject*, const NPVariant* args, uint32_t argCount, NPVariant* result) 374{ 375 if (argCount != 1) 376 return false; 377 NPIdentifier identifier = variantToIdentifier(args[0]); 378 if (!identifier) 379 return false; 380 int32 integer = browser->intfromidentifier(identifier); 381 INT32_TO_NPVARIANT(integer, *result); 382 return true; 383} 384 385static bool testCallback(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result) 386{ 387 if (argCount == 0 || !NPVARIANT_IS_STRING(args[0])) 388 return false; 389 390 NPObject* windowScriptObject; 391 browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject); 392 393 NPUTF8* callbackString = createCStringFromNPVariant(&args[0]); 394 NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackString); 395 free(callbackString); 396 397 NPVariant browserResult; 398 browser->invoke(obj->npp, windowScriptObject, callbackIdentifier, 0, 0, &browserResult); 399 browser->releasevariantvalue(&browserResult); 400 401 browser->releaseobject(windowScriptObject); 402 403 VOID_TO_NPVARIANT(*result); 404 return true; 405} 406 407static bool getURL(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result) 408{ 409 if (argCount == 2 && NPVARIANT_IS_STRING(args[0]) && NPVARIANT_IS_STRING(args[1])) { 410 NPUTF8* urlString = createCStringFromNPVariant(&args[0]); 411 NPUTF8* targetString = createCStringFromNPVariant(&args[1]); 412 NPError npErr = browser->geturl(obj->npp, urlString, targetString); 413 free(urlString); 414 free(targetString); 415 416 INT32_TO_NPVARIANT(npErr, *result); 417 return true; 418 } else if (argCount == 1 && NPVARIANT_IS_STRING(args[0])) { 419 NPUTF8* urlString = createCStringFromNPVariant(&args[0]); 420 NPError npErr = browser->geturl(obj->npp, urlString, 0); 421 free(urlString); 422 423 INT32_TO_NPVARIANT(npErr, *result); 424 return true; 425 } 426 return false; 427} 428 429static bool removeDefaultMethod(PluginObject*, const NPVariant* args, uint32_t argCount, NPVariant* result) 430{ 431 pluginClass.invokeDefault = 0; 432 VOID_TO_NPVARIANT(*result); 433 return true; 434} 435 436static bool getURLNotify(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result) 437{ 438 if (argCount != 3 || !NPVARIANT_IS_STRING(args[0]) 439 || (!NPVARIANT_IS_STRING(args[1]) && !NPVARIANT_IS_NULL(args[1])) 440 || !NPVARIANT_IS_STRING(args[2])) 441 return false; 442 443 NPUTF8* urlString = createCStringFromNPVariant(&args[0]); 444 NPUTF8* targetString = (NPVARIANT_IS_STRING(args[1]) ? createCStringFromNPVariant(&args[1]) : NULL); 445 NPUTF8* callbackString = createCStringFromNPVariant(&args[2]); 446 447 NPIdentifier callbackIdentifier = browser->getstringidentifier(callbackString); 448 browser->geturlnotify(obj->npp, urlString, targetString, callbackIdentifier); 449 450 free(urlString); 451 free(targetString); 452 free(callbackString); 453 454 VOID_TO_NPVARIANT(*result); 455 return true; 456} 457 458static bool testInvokeDefault(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result) 459{ 460 if (!NPVARIANT_IS_OBJECT(args[0])) 461 return false; 462 463 NPObject *callback = NPVARIANT_TO_OBJECT(args[0]); 464 465 NPVariant invokeArgs[1]; 466 NPVariant browserResult; 467 468 STRINGZ_TO_NPVARIANT("test", invokeArgs[0]); 469 bool retval = browser->invokeDefault(obj->npp, callback, invokeArgs, 1, &browserResult); 470 471 if (retval) 472 browser->releasevariantvalue(&browserResult); 473 474 BOOLEAN_TO_NPVARIANT(retval, *result); 475 return true; 476} 477 478static bool destroyStream(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result) 479{ 480 NPError npError = browser->destroystream(obj->npp, obj->stream, NPRES_USER_BREAK); 481 INT32_TO_NPVARIANT(npError, *result); 482 return true; 483} 484 485static bool destroyNullStream(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result) 486{ 487 NPError npError = browser->destroystream(obj->npp, 0, NPRES_USER_BREAK); 488 INT32_TO_NPVARIANT(npError, *result); 489 return true; 490} 491 492static bool testEnumerate(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result) 493{ 494 if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_OBJECT(args[1])) 495 return false; 496 497 uint32_t count; 498 NPIdentifier* identifiers; 499 if (browser->enumerate(obj->npp, NPVARIANT_TO_OBJECT(args[0]), &identifiers, &count)) { 500 NPObject* outArray = NPVARIANT_TO_OBJECT(args[1]); 501 NPIdentifier pushIdentifier = browser->getstringidentifier("push"); 502 503 for (uint32_t i = 0; i < count; i++) { 504 NPUTF8* string = browser->utf8fromidentifier(identifiers[i]); 505 506 if (!string) 507 continue; 508 509 NPVariant args[1]; 510 STRINGZ_TO_NPVARIANT(string, args[0]); 511 NPVariant browserResult; 512 browser->invoke(obj->npp, outArray, pushIdentifier, args, 1, &browserResult); 513 browser->releasevariantvalue(&browserResult); 514 browser->memfree(string); 515 } 516 517 browser->memfree(identifiers); 518 } 519 520 VOID_TO_NPVARIANT(*result); 521 return true; 522} 523 524static bool testGetIntIdentifier(PluginObject*, const NPVariant* args, uint32_t argCount, NPVariant* result) 525{ 526 if (argCount != 1 || !NPVARIANT_IS_DOUBLE(args[0])) 527 return false; 528 529 NPIdentifier identifier = browser->getintidentifier((int)NPVARIANT_TO_DOUBLE(args[0])); 530 INT32_TO_NPVARIANT((int32)(long long)identifier, *result); 531 return true; 532} 533 534static bool testGetProperty(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result) 535{ 536 if (argCount == 0) 537 return false; 538 539 NPObject *object; 540 browser->getvalue(obj->npp, NPNVWindowNPObject, &object); 541 542 for (uint32_t i = 0; i < argCount; i++) { 543 assert(NPVARIANT_IS_STRING(args[i])); 544 NPUTF8* propertyString = createCStringFromNPVariant(&args[i]); 545 NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyString); 546 free(propertyString); 547 548 NPVariant variant; 549 bool retval = browser->getproperty(obj->npp, object, propertyIdentifier, &variant); 550 browser->releaseobject(object); 551 552 if (!retval) 553 break; 554 555 if (i + 1 < argCount) { 556 assert(NPVARIANT_IS_OBJECT(variant)); 557 object = NPVARIANT_TO_OBJECT(variant); 558 } else { 559 *result = variant; 560 return true; 561 } 562 } 563 564 VOID_TO_NPVARIANT(*result); 565 return false; 566} 567 568static bool testHasProperty(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result) 569{ 570 if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_STRING(args[1])) 571 return false; 572 573 NPUTF8* propertyString = createCStringFromNPVariant(&args[1]); 574 NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyString); 575 free(propertyString); 576 577 bool retval = browser->hasproperty(obj->npp, NPVARIANT_TO_OBJECT(args[0]), propertyIdentifier); 578 579 BOOLEAN_TO_NPVARIANT(retval, *result); 580 return true; 581} 582 583static bool testHasMethod(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result) 584{ 585 if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_STRING(args[1])) 586 return false; 587 588 NPUTF8* propertyString = createCStringFromNPVariant(&args[1]); 589 NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyString); 590 free(propertyString); 591 592 bool retval = browser->hasmethod(obj->npp, NPVARIANT_TO_OBJECT(args[0]), propertyIdentifier); 593 594 BOOLEAN_TO_NPVARIANT(retval, *result); 595 return true; 596} 597 598static bool testEvaluate(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result) 599{ 600 if (argCount != 1 || !NPVARIANT_IS_STRING(args[0])) 601 return false; 602 NPObject* windowScriptObject; 603 browser->getvalue(obj->npp, NPNVWindowNPObject, &windowScriptObject); 604 605 NPString s = NPVARIANT_TO_STRING(args[0]); 606 607 bool retval = browser->evaluate(obj->npp, windowScriptObject, &s, result); 608 browser->releaseobject(windowScriptObject); 609 return retval; 610} 611 612static bool testGetPropertyReturnValue(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result) 613{ 614 if (argCount != 2 || !NPVARIANT_IS_OBJECT(args[0]) || !NPVARIANT_IS_STRING(args[1])) 615 return false; 616 617 NPUTF8* propertyString = createCStringFromNPVariant(&args[1]); 618 NPIdentifier propertyIdentifier = browser->getstringidentifier(propertyString); 619 free(propertyString); 620 621 NPVariant variant; 622 bool retval = browser->getproperty(obj->npp, NPVARIANT_TO_OBJECT(args[0]), propertyIdentifier, &variant); 623 if (retval) 624 browser->releasevariantvalue(&variant); 625 626 BOOLEAN_TO_NPVARIANT(retval, *result); 627 return true; 628} 629 630static char* toCString(const NPString& string) 631{ 632 char* result = static_cast<char*>(malloc(string.UTF8Length + 1)); 633 memcpy(result, string.UTF8Characters, string.UTF8Length); 634 result[string.UTF8Length] = '\0'; 635 636 return result; 637} 638 639static bool testPostURLFile(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result) 640{ 641 if (argCount != 4 || !NPVARIANT_IS_STRING(args[0]) || !NPVARIANT_IS_STRING(args[1]) || !NPVARIANT_IS_STRING(args[2]) || !NPVARIANT_IS_STRING(args[3])) 642 return false; 643 644 NPString urlString = NPVARIANT_TO_STRING(args[0]); 645 char* url = toCString(urlString); 646 647 NPString targetString = NPVARIANT_TO_STRING(args[1]); 648 char* target = toCString(targetString); 649 650 NPString pathString = NPVARIANT_TO_STRING(args[2]); 651 char* path = toCString(pathString); 652 653 NPString contentsString = NPVARIANT_TO_STRING(args[3]); 654 655 FILE* tempFile = fopen(path, "w"); 656 if (!tempFile) 657 return false; 658 659 fwrite(contentsString.UTF8Characters, contentsString.UTF8Length, 1, tempFile); 660 fclose(tempFile); 661 662 NPError error = browser->posturl(obj->npp, url, target, pathString.UTF8Length, path, TRUE); 663 664 free(path); 665 free(target); 666 free(url); 667 668 BOOLEAN_TO_NPVARIANT(error == NPERR_NO_ERROR, *result); 669 return true; 670} 671 672static bool testConstruct(PluginObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result) 673{ 674 if (!argCount || !NPVARIANT_IS_OBJECT(args[0])) 675 return false; 676 677 return browser->construct(obj->npp, NPVARIANT_TO_OBJECT(args[0]), args + 1, argCount - 1, result); 678} 679 680// Helper function to notify the layout test controller that the test completed. 681void notifyTestCompletion(NPP npp, NPObject* object) 682{ 683 NPVariant result; 684 NPString script; 685 script.UTF8Characters = "javascript:window.layoutTestController.notifyDone();"; 686 script.UTF8Length = strlen("javascript:window.layoutTestController.notifyDone();"); 687 browser->evaluate(npp, object, &script, &result); 688 browser->releasevariantvalue(&result); 689} 690 691bool testDocumentOpen(NPP npp) 692{ 693 NPIdentifier documentId = browser->getstringidentifier("document"); 694 NPIdentifier openId = browser->getstringidentifier("open"); 695 696 NPObject *windowObject = NULL; 697 browser->getvalue(npp, NPNVWindowNPObject, &windowObject); 698 if (!windowObject) 699 return false; 700 701 NPVariant docVariant; 702 browser->getproperty(npp, windowObject, documentId, &docVariant); 703 if (docVariant.type != NPVariantType_Object) 704 return false; 705 706 NPObject *documentObject = NPVARIANT_TO_OBJECT(docVariant); 707 708 NPVariant openArgs[2]; 709 STRINGZ_TO_NPVARIANT("text/html", openArgs[0]); 710 STRINGZ_TO_NPVARIANT("_blank", openArgs[1]); 711 712 NPVariant result; 713 browser->invoke(npp, documentObject, openId, openArgs, 2, &result); 714 browser->releaseobject(documentObject); 715 716 if (result.type == NPVariantType_Object) { 717 pluginLogWithWindowObjectVariableArgs(windowObject, npp, "DOCUMENT OPEN SUCCESS"); 718 notifyTestCompletion(npp, result.value.objectValue); 719 browser->releaseobject(result.value.objectValue); 720 return true; 721 } 722 723 return false; 724} 725 726bool testWindowOpen(NPP npp) 727{ 728 NPIdentifier openId = browser->getstringidentifier("open"); 729 730 NPObject *windowObject = NULL; 731 browser->getvalue(npp, NPNVWindowNPObject, &windowObject); 732 if (!windowObject) 733 return false; 734 735 NPVariant openArgs[2]; 736 STRINGZ_TO_NPVARIANT("about:blank", openArgs[0]); 737 STRINGZ_TO_NPVARIANT("_blank", openArgs[1]); 738 739 NPVariant result; 740 browser->invoke(npp, windowObject, openId, openArgs, 2, &result); 741 if (result.type == NPVariantType_Object) { 742 pluginLogWithWindowObjectVariableArgs(windowObject, npp, "WINDOW OPEN SUCCESS"); 743 notifyTestCompletion(npp, result.value.objectValue); 744 browser->releaseobject(result.value.objectValue); 745 return true; 746 } 747 return false; 748} 749 750static bool pluginInvoke(NPObject* header, NPIdentifier name, const NPVariant* args, uint32_t argCount, NPVariant* result) 751{ 752 PluginObject* plugin = reinterpret_cast<PluginObject*>(header); 753 if (name == pluginMethodIdentifiers[ID_TEST_CALLBACK_METHOD]) 754 return testCallback(plugin, args, argCount, result); 755 else if (name == pluginMethodIdentifiers[ID_TEST_GETURL]) 756 return getURL(plugin, args, argCount, result); 757 else if (name == pluginMethodIdentifiers[ID_REMOVE_DEFAULT_METHOD]) 758 return removeDefaultMethod(plugin, args, argCount, result); 759 else if (name == pluginMethodIdentifiers[ID_TEST_DOM_ACCESS]) 760 return testDOMAccess(plugin, args, argCount, result); 761 else if (name == pluginMethodIdentifiers[ID_TEST_GET_URL_NOTIFY]) 762 return getURLNotify(plugin, args, argCount, result); 763 else if (name == pluginMethodIdentifiers[ID_TEST_INVOKE_DEFAULT]) 764 return testInvokeDefault(plugin, args, argCount, result); 765 else if (name == pluginMethodIdentifiers[ID_TEST_ENUMERATE]) 766 return testEnumerate(plugin, args, argCount, result); 767 else if (name == pluginMethodIdentifiers[ID_DESTROY_STREAM]) 768 return destroyStream(plugin, args, argCount, result); 769 else if (name == pluginMethodIdentifiers[ID_TEST_GETINTIDENTIFIER]) 770 return testGetIntIdentifier(plugin, args, argCount, result); 771 else if (name == pluginMethodIdentifiers[ID_TEST_EVALUATE]) 772 return testEvaluate(plugin, args, argCount, result); 773 else if (name == pluginMethodIdentifiers[ID_TEST_GET_PROPERTY]) 774 return testGetProperty(plugin, args, argCount, result); 775 else if (name == pluginMethodIdentifiers[ID_TEST_GET_PROPERTY_RETURN_VALUE]) 776 return testGetPropertyReturnValue(plugin, args, argCount, result); 777 else if (name == pluginMethodIdentifiers[ID_TEST_HAS_PROPERTY]) 778 return testHasProperty(plugin, args, argCount, result); 779 else if (name == pluginMethodIdentifiers[ID_TEST_HAS_METHOD]) 780 return testHasMethod(plugin, args, argCount, result); 781 else if (name == pluginMethodIdentifiers[ID_TEST_IDENTIFIER_TO_STRING]) 782 return testIdentifierToString(plugin, args, argCount, result); 783 else if (name == pluginMethodIdentifiers[ID_TEST_IDENTIFIER_TO_INT]) 784 return testIdentifierToInt(plugin, args, argCount, result); 785 else if (name == pluginMethodIdentifiers[ID_TEST_POSTURL_FILE]) 786 return testPostURLFile(plugin, args, argCount, result); 787 else if (name == pluginMethodIdentifiers[ID_TEST_CONSTRUCT]) 788 return testConstruct(plugin, args, argCount, result); 789 else if (name == pluginMethodIdentifiers[ID_TEST_THROW_EXCEPTION_METHOD]) { 790 browser->setexception(header, "plugin object testThrowException SUCCESS"); 791 return true; 792 } else if (name == pluginMethodIdentifiers[ID_TEST_FAIL_METHOD]) { 793 NPObject* windowScriptObject; 794 browser->getvalue(plugin->npp, NPNVWindowNPObject, &windowScriptObject); 795 browser->invoke(plugin->npp, windowScriptObject, name, args, argCount, result); 796 } else if (name == pluginMethodIdentifiers[ID_DESTROY_NULL_STREAM]) 797 return destroyNullStream(plugin, args, argCount, result); 798 else if (name == pluginMethodIdentifiers[ID_TEST_RELOAD_PLUGINS_NO_PAGES]) { 799 browser->reloadplugins(false); 800 return true; 801 } else if (name == pluginMethodIdentifiers[ID_TEST_RELOAD_PLUGINS_AND_PAGES]) { 802 browser->reloadplugins(true); 803 return true; 804 } else if (name == pluginMethodIdentifiers[ID_TEST_GET_BROWSER_PROPERTY]) { 805 browser->getproperty(plugin->npp, NPVARIANT_TO_OBJECT(args[0]), stringVariantToIdentifier(args[1]), result); 806 return true; 807 } else if (name == pluginMethodIdentifiers[ID_TEST_SET_BROWSER_PROPERTY]) { 808 browser->setproperty(plugin->npp, NPVARIANT_TO_OBJECT(args[0]), stringVariantToIdentifier(args[1]), &args[2]); 809 return true; 810 } 811 812 return false; 813} 814 815static bool pluginInvokeDefault(NPObject* obj, const NPVariant* args, uint32_t argCount, NPVariant* result) 816{ 817 INT32_TO_NPVARIANT(1, *result); 818 return true; 819} 820 821static void pluginInvalidate(NPObject* header) 822{ 823 PluginObject* plugin = reinterpret_cast<PluginObject*>(header); 824 plugin->testObject = 0; 825} 826 827static NPObject *pluginAllocate(NPP npp, NPClass *theClass) 828{ 829 PluginObject* newInstance = (PluginObject*)malloc(sizeof(PluginObject)); 830 831 if (!identifiersInitialized) { 832 identifiersInitialized = true; 833 initializeIdentifiers(); 834 } 835 836 newInstance->npp = npp; 837 newInstance->testObject = browser->createobject(npp, getTestClass()); 838 newInstance->eventLogging = FALSE; 839 newInstance->onStreamLoad = 0; 840 newInstance->onStreamDestroy = 0; 841 newInstance->onDestroy = 0; 842 newInstance->onURLNotify = 0; 843 newInstance->logDestroy = FALSE; 844 newInstance->logSetWindow = FALSE; 845 newInstance->returnErrorFromNewStream = FALSE; 846 newInstance->stream = 0; 847 848 newInstance->firstUrl = NULL; 849 newInstance->firstHeaders = NULL; 850 newInstance->lastUrl = NULL; 851 newInstance->lastHeaders = NULL; 852 853 newInstance->testDocumentOpenInDestroyStream = FALSE; 854 newInstance->testWindowOpen = FALSE; 855 856 return (NPObject*)newInstance; 857} 858 859static void pluginDeallocate(NPObject* header) 860{ 861 PluginObject* plugin = reinterpret_cast<PluginObject*>(header); 862 if (plugin->testObject) 863 browser->releaseobject(plugin->testObject); 864 865 free(plugin->firstUrl); 866 free(plugin->firstHeaders); 867 free(plugin->lastUrl); 868 free(plugin->lastHeaders); 869 free(plugin); 870} 871 872void handleCallback(PluginObject* object, const char *url, NPReason reason, void *notifyData) 873{ 874 assert(object); 875 876 NPVariant args[2]; 877 878 NPObject *windowScriptObject; 879 browser->getvalue(object->npp, NPNVWindowNPObject, &windowScriptObject); 880 881 NPIdentifier callbackIdentifier = notifyData; 882 883 INT32_TO_NPVARIANT(reason, args[0]); 884 885 char *strHdr = NULL; 886 if (object->firstUrl && object->firstHeaders && object->lastUrl && object->lastHeaders) { 887 // Format expected by JavaScript validator: four fields separated by \n\n: 888 // First URL; first header block; last URL; last header block. 889 // Note that header blocks already end with \n due to how NPStream::headers works. 890 int len = strlen(object->firstUrl) + 2 891 + strlen(object->firstHeaders) + 1 892 + strlen(object->lastUrl) + 2 893 + strlen(object->lastHeaders) + 1; 894 strHdr = (char*)malloc(len + 1); 895 snprintf(strHdr, len + 1, "%s\n\n%s\n%s\n\n%s\n", 896 object->firstUrl, object->firstHeaders, object->lastUrl, object->lastHeaders); 897 STRINGN_TO_NPVARIANT(strHdr, len, args[1]); 898 } else 899 NULL_TO_NPVARIANT(args[1]); 900 901 NPVariant browserResult; 902 browser->invoke(object->npp, windowScriptObject, callbackIdentifier, args, 2, &browserResult); 903 browser->releasevariantvalue(&browserResult); 904 905 free(strHdr); 906} 907 908void notifyStream(PluginObject* object, const char *url, const char *headers) 909{ 910 if (object->firstUrl == NULL) { 911 if (url) 912 object->firstUrl = strdup(url); 913 if (headers) 914 object->firstHeaders = strdup(headers); 915 } else { 916 free(object->lastUrl); 917 free(object->lastHeaders); 918 object->lastUrl = (url ? strdup(url) : NULL); 919 object->lastHeaders = (headers ? strdup(headers) : NULL); 920 } 921} 922 923void testNPRuntime(NPP npp) 924{ 925 NPObject* windowScriptObject; 926 browser->getvalue(npp, NPNVWindowNPObject, &windowScriptObject); 927 928 // Invoke 929 NPIdentifier testNPInvoke = browser->getstringidentifier("testNPInvoke"); 930 NPVariant args[7]; 931 932 VOID_TO_NPVARIANT(args[0]); 933 NULL_TO_NPVARIANT(args[1]); 934 BOOLEAN_TO_NPVARIANT(true, args[2]); 935 INT32_TO_NPVARIANT(242, args[3]); 936 DOUBLE_TO_NPVARIANT(242.242, args[4]); 937 STRINGZ_TO_NPVARIANT("Hello, World", args[5]); 938 OBJECT_TO_NPVARIANT(windowScriptObject, args[6]); 939 940 NPVariant result; 941 if (browser->invoke(npp, windowScriptObject, testNPInvoke, args, 7, &result)) 942 browser->releasevariantvalue(&result); 943 944 browser->releaseobject(windowScriptObject); 945} 946