1 /* 2 * Copyright (C) 2010 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "NetscapeBrowserFuncs.h" 28 29 #include "NPRuntimeUtilities.h" 30 #include "NetscapePlugin.h" 31 #include "PluginController.h" 32 #include <WebCore/HTTPHeaderMap.h> 33 #include <WebCore/IdentifierRep.h> 34 #include <WebCore/NotImplemented.h> 35 #include <WebCore/SharedBuffer.h> 36 #include <utility> 37 38 #if PLATFORM(QT) 39 #include <QX11Info> 40 #elif PLATFORM(GTK) 41 #include <gdk/gdkx.h> 42 #endif 43 44 using namespace WebCore; 45 using namespace std; 46 47 namespace WebKit { 48 49 // Helper class for delaying destruction of a plug-in. 50 class PluginDestructionProtector { 51 public: 52 explicit PluginDestructionProtector(NetscapePlugin* plugin) 53 : m_protector(static_cast<Plugin*>(plugin)->controller()) 54 { 55 } 56 57 private: 58 PluginController::PluginDestructionProtector m_protector; 59 }; 60 61 static bool startsWithBlankLine(const char* bytes, unsigned length) 62 { 63 return length > 0 && bytes[0] == '\n'; 64 } 65 66 static int locationAfterFirstBlankLine(const char* bytes, unsigned length) 67 { 68 for (unsigned i = 0; i < length - 4; i++) { 69 // Support for Acrobat. It sends "\n\n". 70 if (bytes[i] == '\n' && bytes[i + 1] == '\n') 71 return i + 2; 72 73 // Returns the position after 2 CRLF's or 1 CRLF if it is the first line. 74 if (bytes[i] == '\r' && bytes[i + 1] == '\n') { 75 i += 2; 76 if (i == 2) 77 return i; 78 79 if (bytes[i] == '\n') { 80 // Support for Director. It sends "\r\n\n" (3880387). 81 return i + 1; 82 } 83 84 if (bytes[i] == '\r' && bytes[i + 1] == '\n') { 85 // Support for Flash. It sends "\r\n\r\n" (3758113). 86 return i + 2; 87 } 88 } 89 } 90 91 return -1; 92 } 93 94 static const char* findEndOfLine(const char* bytes, unsigned length) 95 { 96 // According to the HTTP specification EOL is defined as 97 // a CRLF pair. Unfortunately, some servers will use LF 98 // instead. Worse yet, some servers will use a combination 99 // of both (e.g. <header>CRLFLF<body>), so findEOL needs 100 // to be more forgiving. It will now accept CRLF, LF or 101 // CR. 102 // 103 // It returns 0 if EOLF is not found or it will return 104 // a pointer to the first terminating character. 105 for (unsigned i = 0; i < length; i++) { 106 if (bytes[i] == '\n') 107 return bytes + i; 108 if (bytes[i] == '\r') { 109 // Check to see if spanning buffer bounds 110 // (CRLF is across reads). If so, wait for 111 // next read. 112 if (i + 1 == length) 113 break; 114 115 return bytes + i; 116 } 117 } 118 119 return 0; 120 } 121 122 static String capitalizeRFC822HeaderFieldName(const String& name) 123 { 124 bool capitalizeCharacter = true; 125 String result; 126 127 for (unsigned i = 0; i < name.length(); i++) { 128 UChar c; 129 130 if (capitalizeCharacter && name[i] >= 'a' && name[i] <= 'z') 131 c = toASCIIUpper(name[i]); 132 else if (!capitalizeCharacter && name[i] >= 'A' && name[i] <= 'Z') 133 c = toASCIILower(name[i]); 134 else 135 c = name[i]; 136 137 if (name[i] == '-') 138 capitalizeCharacter = true; 139 else 140 capitalizeCharacter = false; 141 142 result.append(c); 143 } 144 145 return result; 146 } 147 148 static HTTPHeaderMap parseRFC822HeaderFields(const char* bytes, unsigned length) 149 { 150 String lastHeaderKey; 151 HTTPHeaderMap headerFields; 152 153 // Loop over lines until we're past the header, or we can't find any more end-of-lines 154 while (const char* endOfLine = findEndOfLine(bytes, length)) { 155 const char* line = bytes; 156 int lineLength = endOfLine - bytes; 157 158 // Move bytes to the character after the terminator as returned by findEndOfLine. 159 bytes = endOfLine + 1; 160 if ((*endOfLine == '\r') && (*bytes == '\n')) 161 bytes++; // Safe since findEndOfLine won't return a spanning CRLF. 162 163 length -= (bytes - line); 164 if (!lineLength) { 165 // Blank line; we're at the end of the header 166 break; 167 } 168 169 if (*line == ' ' || *line == '\t') { 170 // Continuation of the previous header 171 if (lastHeaderKey.isNull()) { 172 // malformed header; ignore it and continue 173 continue; 174 } 175 176 // Merge the continuation of the previous header 177 String currentValue = headerFields.get(lastHeaderKey); 178 String newValue(line, lineLength); 179 180 headerFields.set(lastHeaderKey, currentValue + newValue); 181 } else { 182 // Brand new header 183 const char* colon = line; 184 while (*colon != ':' && colon != endOfLine) 185 colon++; 186 187 if (colon == endOfLine) { 188 // malformed header; ignore it and continue 189 continue; 190 } 191 192 lastHeaderKey = capitalizeRFC822HeaderFieldName(String(line, colon - line)); 193 String value; 194 195 for (colon++; colon != endOfLine; colon++) { 196 if (*colon != ' ' && *colon != '\t') 197 break; 198 } 199 if (colon == endOfLine) 200 value = ""; 201 else 202 value = String(colon, endOfLine - colon); 203 204 String oldValue = headerFields.get(lastHeaderKey); 205 if (!oldValue.isNull()) { 206 String tmp = oldValue; 207 tmp += ", "; 208 tmp += value; 209 value = tmp; 210 } 211 212 headerFields.set(lastHeaderKey, value); 213 } 214 } 215 216 return headerFields; 217 } 218 219 static NPError parsePostBuffer(bool isFile, const char *buffer, uint32_t length, bool parseHeaders, HTTPHeaderMap& headerFields, Vector<uint8_t>& bodyData) 220 { 221 RefPtr<SharedBuffer> fileContents; 222 const char* postBuffer = 0; 223 uint32_t postBufferSize = 0; 224 225 if (isFile) { 226 fileContents = SharedBuffer::createWithContentsOfFile(String::fromUTF8(buffer)); 227 if (!fileContents) 228 return NPERR_FILE_NOT_FOUND; 229 230 postBuffer = fileContents->data(); 231 postBufferSize = fileContents->size(); 232 233 // FIXME: The NPAPI spec states that the file should be deleted here. 234 } else { 235 postBuffer = buffer; 236 postBufferSize = length; 237 } 238 239 if (parseHeaders) { 240 if (startsWithBlankLine(postBuffer, postBufferSize)) { 241 postBuffer++; 242 postBufferSize--; 243 } else { 244 int location = locationAfterFirstBlankLine(postBuffer, postBufferSize); 245 if (location != -1) { 246 // If the blank line is somewhere in the middle of the buffer, everything before is the header 247 headerFields = parseRFC822HeaderFields(postBuffer, location); 248 unsigned dataLength = postBufferSize - location; 249 250 // Sometimes plugins like to set Content-Length themselves when they post, 251 // but WebFoundation does not like that. So we will remove the header 252 // and instead truncate the data to the requested length. 253 String contentLength = headerFields.get("Content-Length"); 254 255 if (!contentLength.isNull()) 256 dataLength = min(contentLength.toInt(), (int)dataLength); 257 headerFields.remove("Content-Length"); 258 259 postBuffer += location; 260 postBufferSize = dataLength; 261 262 } 263 } 264 } 265 266 ASSERT(bodyData.isEmpty()); 267 bodyData.append(postBuffer, postBufferSize); 268 269 return NPERR_NO_ERROR; 270 } 271 272 static String makeURLString(const char* url) 273 { 274 String urlString(url); 275 276 // Strip return characters. 277 urlString.replace('\r', ""); 278 urlString.replace('\n', ""); 279 280 return urlString; 281 } 282 283 static NPError NPN_GetURL(NPP npp, const char* url, const char* target) 284 { 285 if (!url) 286 return NPERR_GENERIC_ERROR; 287 288 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 289 plugin->loadURL("GET", makeURLString(url), target, HTTPHeaderMap(), Vector<uint8_t>(), false, 0); 290 291 return NPERR_GENERIC_ERROR; 292 } 293 294 static NPError NPN_PostURL(NPP npp, const char* url, const char* target, uint32_t len, const char* buf, NPBool file) 295 { 296 HTTPHeaderMap headerFields; 297 Vector<uint8_t> postData; 298 299 // NPN_PostURL only allows headers if the post buffer points to a file. 300 bool parseHeaders = file; 301 302 NPError error = parsePostBuffer(file, buf, len, parseHeaders, headerFields, postData); 303 if (error != NPERR_NO_ERROR) 304 return error; 305 306 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 307 plugin->loadURL("POST", makeURLString(url), target, headerFields, postData, false, 0); 308 return NPERR_NO_ERROR; 309 } 310 311 static NPError NPN_RequestRead(NPStream* stream, NPByteRange* rangeList) 312 { 313 notImplemented(); 314 return NPERR_GENERIC_ERROR; 315 } 316 317 static NPError NPN_NewStream(NPP instance, NPMIMEType type, const char* target, NPStream** stream) 318 { 319 notImplemented(); 320 return NPERR_GENERIC_ERROR; 321 } 322 323 static int32_t NPN_Write(NPP instance, NPStream* stream, int32_t len, void* buffer) 324 { 325 notImplemented(); 326 return -1; 327 } 328 329 static NPError NPN_DestroyStream(NPP npp, NPStream* stream, NPReason reason) 330 { 331 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 332 333 return plugin->destroyStream(stream, reason); 334 } 335 336 static void NPN_Status(NPP npp, const char* message) 337 { 338 String statusbarText; 339 if (!message) 340 statusbarText = ""; 341 else 342 statusbarText = String::fromUTF8WithLatin1Fallback(message, strlen(message)); 343 344 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 345 plugin->setStatusbarText(statusbarText); 346 } 347 348 static const char* NPN_UserAgent(NPP npp) 349 { 350 return NetscapePlugin::userAgent(npp); 351 } 352 353 static void* NPN_MemAlloc(uint32_t size) 354 { 355 return npnMemAlloc(size); 356 } 357 358 static void NPN_MemFree(void* ptr) 359 { 360 npnMemFree(ptr); 361 } 362 363 static uint32_t NPN_MemFlush(uint32_t size) 364 { 365 return 0; 366 } 367 368 static void NPN_ReloadPlugins(NPBool reloadPages) 369 { 370 notImplemented(); 371 } 372 373 static JRIEnv* NPN_GetJavaEnv(void) 374 { 375 notImplemented(); 376 return 0; 377 } 378 379 static jref NPN_GetJavaPeer(NPP instance) 380 { 381 notImplemented(); 382 return 0; 383 } 384 385 static NPError NPN_GetURLNotify(NPP npp, const char* url, const char* target, void* notifyData) 386 { 387 if (!url) 388 return NPERR_GENERIC_ERROR; 389 390 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 391 plugin->loadURL("GET", makeURLString(url), target, HTTPHeaderMap(), Vector<uint8_t>(), true, notifyData); 392 393 return NPERR_NO_ERROR; 394 } 395 396 static NPError NPN_PostURLNotify(NPP npp, const char* url, const char* target, uint32_t len, const char* buf, NPBool file, void* notifyData) 397 { 398 HTTPHeaderMap headerFields; 399 Vector<uint8_t> postData; 400 NPError error = parsePostBuffer(file, buf, len, true, headerFields, postData); 401 if (error != NPERR_NO_ERROR) 402 return error; 403 404 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 405 plugin->loadURL("POST", makeURLString(url), target, headerFields, postData, true, notifyData); 406 return NPERR_NO_ERROR; 407 } 408 409 #if PLATFORM(MAC) 410 // true if the browser supports hardware compositing of Core Animation plug-ins. 411 static const unsigned WKNVSupportsCompositingCoreAnimationPluginsBool = 74656; 412 413 // The Core Animation render server port. 414 static const unsigned WKNVCALayerRenderServerPort = 71879; 415 416 #endif 417 418 static NPError NPN_GetValue(NPP npp, NPNVariable variable, void *value) 419 { 420 switch (variable) { 421 case NPNVWindowNPObject: { 422 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 423 PluginDestructionProtector protector(plugin.get()); 424 425 NPObject* windowNPObject = plugin->windowScriptNPObject(); 426 if (!windowNPObject) 427 return NPERR_GENERIC_ERROR; 428 429 *(NPObject**)value = windowNPObject; 430 break; 431 } 432 case NPNVPluginElementNPObject: { 433 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 434 PluginDestructionProtector protector(plugin.get()); 435 436 NPObject* pluginElementNPObject = plugin->pluginElementNPObject(); 437 *(NPObject**)value = pluginElementNPObject; 438 break; 439 } 440 case NPNVprivateModeBool: { 441 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 442 443 *(NPBool*)value = plugin->isPrivateBrowsingEnabled(); 444 break; 445 } 446 #if PLATFORM(MAC) 447 case NPNVsupportsCoreGraphicsBool: 448 // Always claim to support the Core Graphics drawing model. 449 *(NPBool*)value = true; 450 break; 451 452 case WKNVSupportsCompositingCoreAnimationPluginsBool: 453 case NPNVsupportsCoreAnimationBool: { 454 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 455 456 *(NPBool*)value = plugin->isAcceleratedCompositingEnabled(); 457 break; 458 } 459 case NPNVsupportsCocoaBool: 460 // Always claim to support the Cocoa event model. 461 *(NPBool*)value = true; 462 break; 463 464 case WKNVCALayerRenderServerPort: { 465 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 466 467 *(mach_port_t*)value = plugin->compositingRenderServerPort(); 468 break; 469 } 470 471 #ifndef NP_NO_QUICKDRAW 472 case NPNVsupportsQuickDrawBool: 473 // We don't support the QuickDraw drawing model. 474 *(NPBool*)value = false; 475 break; 476 #endif 477 #ifndef NP_NO_CARBON 478 case NPNVsupportsCarbonBool: 479 // FIXME: We should support the Carbon event model. 480 *(NPBool*)value = false; 481 break; 482 #endif 483 #elif PLATFORM(WIN) 484 case NPNVnetscapeWindow: { 485 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 486 *reinterpret_cast<HWND*>(value) = plugin->containingWindow(); 487 break; 488 } 489 case NPNVSupportsWindowless: 490 *(NPBool*)value = true; 491 break; 492 #elif PLUGIN_ARCHITECTURE(X11) 493 case NPNVxDisplay: 494 #if PLATFORM(QT) 495 *reinterpret_cast<Display**>(value) = QX11Info::display(); 496 break; 497 #elif PLATFORM(GTK) 498 *reinterpret_cast<Display**>(value) = GDK_DISPLAY_XDISPLAY(gdk_display_get_default()); 499 break; 500 #else 501 goto default; 502 #endif 503 case NPNVSupportsXEmbedBool: 504 *static_cast<NPBool*>(value) = true; 505 break; 506 case NPNVSupportsWindowless: 507 *static_cast<NPBool*>(value) = true; 508 break; 509 510 case NPNVToolkit: { 511 const uint32_t expectedGTKToolKitVersion = 2; 512 513 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 514 *reinterpret_cast<uint32_t*>(value) = plugin->quirks().contains(PluginQuirks::RequiresGTKToolKit) ? 515 expectedGTKToolKitVersion : 0; 516 break; 517 } 518 519 // TODO: implement NPNVnetscapeWindow once we want to support windowed plugins. 520 #endif 521 default: 522 notImplemented(); 523 return NPERR_GENERIC_ERROR; 524 } 525 526 return NPERR_NO_ERROR; 527 } 528 529 static NPError NPN_SetValue(NPP npp, NPPVariable variable, void *value) 530 { 531 switch (variable) { 532 #if PLATFORM(MAC) 533 case NPPVpluginDrawingModel: { 534 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 535 536 NPDrawingModel drawingModel = static_cast<NPDrawingModel>(reinterpret_cast<uintptr_t>(value)); 537 return plugin->setDrawingModel(drawingModel); 538 } 539 540 case NPPVpluginEventModel: { 541 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 542 543 NPEventModel eventModel = static_cast<NPEventModel>(reinterpret_cast<uintptr_t>(value)); 544 return plugin->setEventModel(eventModel); 545 } 546 #endif 547 548 case NPPVpluginWindowBool: { 549 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 550 plugin->setIsWindowed(value); 551 return NPERR_NO_ERROR; 552 } 553 554 case NPPVpluginTransparentBool: { 555 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 556 plugin->setIsTransparent(value); 557 return NPERR_NO_ERROR; 558 } 559 560 default: 561 notImplemented(); 562 return NPERR_GENERIC_ERROR; 563 } 564 } 565 566 static void NPN_InvalidateRect(NPP npp, NPRect* invalidRect) 567 { 568 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 569 plugin->invalidate(invalidRect); 570 } 571 572 static void NPN_InvalidateRegion(NPP npp, NPRegion invalidRegion) 573 { 574 // FIXME: We could at least figure out the bounding rectangle of the invalid region. 575 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 576 plugin->invalidate(0); 577 } 578 579 static void NPN_ForceRedraw(NPP instance) 580 { 581 notImplemented(); 582 } 583 584 static NPIdentifier NPN_GetStringIdentifier(const NPUTF8 *name) 585 { 586 return static_cast<NPIdentifier>(IdentifierRep::get(name)); 587 } 588 589 static void NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount, NPIdentifier *identifiers) 590 { 591 ASSERT(names); 592 ASSERT(identifiers); 593 594 if (!names || !identifiers) 595 return; 596 597 for (int32_t i = 0; i < nameCount; ++i) 598 identifiers[i] = NPN_GetStringIdentifier(names[i]); 599 } 600 601 static NPIdentifier NPN_GetIntIdentifier(int32_t intid) 602 { 603 return static_cast<NPIdentifier>(IdentifierRep::get(intid)); 604 } 605 606 static bool NPN_IdentifierIsString(NPIdentifier identifier) 607 { 608 return static_cast<IdentifierRep*>(identifier)->isString(); 609 } 610 611 static NPUTF8 *NPN_UTF8FromIdentifier(NPIdentifier identifier) 612 { 613 const char* string = static_cast<IdentifierRep*>(identifier)->string(); 614 if (!string) 615 return 0; 616 617 uint32_t stringLength = strlen(string); 618 char* utf8String = npnMemNewArray<char>(stringLength + 1); 619 memcpy(utf8String, string, stringLength); 620 utf8String[stringLength] = '\0'; 621 622 return utf8String; 623 } 624 625 static int32_t NPN_IntFromIdentifier(NPIdentifier identifier) 626 { 627 return static_cast<IdentifierRep*>(identifier)->number(); 628 } 629 630 static NPObject* NPN_CreateObject(NPP npp, NPClass *npClass) 631 { 632 return createNPObject(npp, npClass); 633 } 634 635 static NPObject *NPN_RetainObject(NPObject *npObject) 636 { 637 retainNPObject(npObject); 638 return npObject; 639 } 640 641 static void NPN_ReleaseObject(NPObject *npObject) 642 { 643 releaseNPObject(npObject); 644 } 645 646 static bool NPN_Invoke(NPP, NPObject *npObject, NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 647 { 648 if (npObject->_class->invoke) 649 return npObject->_class->invoke(npObject, methodName, arguments, argumentCount, result); 650 651 return false; 652 } 653 654 static bool NPN_InvokeDefault(NPP, NPObject *npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 655 { 656 if (npObject->_class->invokeDefault) 657 return npObject->_class->invokeDefault(npObject, arguments, argumentCount, result); 658 659 return false; 660 } 661 662 static bool NPN_Evaluate(NPP npp, NPObject *npObject, NPString *script, NPVariant* result) 663 { 664 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 665 PluginDestructionProtector protector(plugin.get()); 666 667 String scriptString = String::fromUTF8WithLatin1Fallback(script->UTF8Characters, script->UTF8Length); 668 669 return plugin->evaluate(npObject, scriptString, result); 670 } 671 672 static bool NPN_GetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, NPVariant* result) 673 { 674 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 675 PluginDestructionProtector protector(plugin.get()); 676 677 if (npObject->_class->getProperty) 678 return npObject->_class->getProperty(npObject, propertyName, result); 679 680 return false; 681 } 682 683 static bool NPN_SetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, const NPVariant* value) 684 { 685 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 686 PluginDestructionProtector protector(plugin.get()); 687 688 if (npObject->_class->setProperty) 689 return npObject->_class->setProperty(npObject, propertyName, value); 690 691 return false; 692 } 693 694 static bool NPN_RemoveProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName) 695 { 696 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 697 PluginDestructionProtector protector(plugin.get()); 698 699 if (npObject->_class->removeProperty) 700 return npObject->_class->removeProperty(npObject, propertyName); 701 702 return false; 703 } 704 705 static bool NPN_HasProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName) 706 { 707 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 708 PluginDestructionProtector protector(plugin.get()); 709 710 if (npObject->_class->hasProperty) 711 return npObject->_class->hasProperty(npObject, propertyName); 712 713 return false; 714 } 715 716 static bool NPN_HasMethod(NPP npp, NPObject* npObject, NPIdentifier methodName) 717 { 718 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 719 PluginDestructionProtector protector(plugin.get()); 720 721 if (npObject->_class->hasMethod) 722 return npObject->_class->hasMethod(npObject, methodName); 723 724 return false; 725 } 726 727 static void NPN_ReleaseVariantValue(NPVariant* variant) 728 { 729 releaseNPVariantValue(variant); 730 } 731 732 static void NPN_SetException(NPObject*, const NPUTF8* message) 733 { 734 NetscapePlugin::setException(message); 735 } 736 737 static void NPN_PushPopupsEnabledState(NPP npp, NPBool enabled) 738 { 739 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 740 plugin->pushPopupsEnabledState(enabled); 741 } 742 743 static void NPN_PopPopupsEnabledState(NPP npp) 744 { 745 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 746 plugin->popPopupsEnabledState(); 747 } 748 749 static bool NPN_Enumerate(NPP npp, NPObject* npObject, NPIdentifier** identifiers, uint32_t* identifierCount) 750 { 751 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 752 PluginDestructionProtector protector(plugin.get()); 753 754 if (NP_CLASS_STRUCT_VERSION_HAS_ENUM(npObject->_class) && npObject->_class->enumerate) 755 return npObject->_class->enumerate(npObject, identifiers, identifierCount); 756 757 return false; 758 } 759 760 static void NPN_PluginThreadAsyncCall(NPP instance, void (*func) (void*), void* userData) 761 { 762 notImplemented(); 763 } 764 765 static bool NPN_Construct(NPP npp, NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 766 { 767 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 768 PluginDestructionProtector protector(plugin.get()); 769 770 if (NP_CLASS_STRUCT_VERSION_HAS_CTOR(npObject->_class) && npObject->_class->construct) 771 return npObject->_class->construct(npObject, arguments, argumentCount, result); 772 773 return false; 774 } 775 776 static NPError copyCString(const CString& string, char** value, uint32_t* len) 777 { 778 ASSERT(!string.isNull()); 779 ASSERT(value); 780 ASSERT(len); 781 782 *value = npnMemNewArray<char>(string.length()); 783 if (!*value) 784 return NPERR_GENERIC_ERROR; 785 786 memcpy(*value, string.data(), string.length()); 787 *len = string.length(); 788 return NPERR_NO_ERROR; 789 } 790 791 static NPError NPN_GetValueForURL(NPP npp, NPNURLVariable variable, const char* url, char** value, uint32_t* len) 792 { 793 if (!value || !len) 794 return NPERR_GENERIC_ERROR; 795 796 switch (variable) { 797 case NPNURLVCookie: { 798 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 799 PluginDestructionProtector protector(plugin.get()); 800 801 String cookies = plugin->cookiesForURL(makeURLString(url)); 802 if (cookies.isNull()) 803 return NPERR_GENERIC_ERROR; 804 805 return copyCString(cookies.utf8(), value, len); 806 } 807 808 case NPNURLVProxy: { 809 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 810 PluginDestructionProtector protector(plugin.get()); 811 812 String proxies = plugin->proxiesForURL(makeURLString(url)); 813 if (proxies.isNull()) 814 return NPERR_GENERIC_ERROR; 815 816 return copyCString(proxies.utf8(), value, len); 817 } 818 default: 819 notImplemented(); 820 return NPERR_GENERIC_ERROR; 821 } 822 } 823 824 static NPError NPN_SetValueForURL(NPP npp, NPNURLVariable variable, const char* url, const char* value, uint32_t len) 825 { 826 switch (variable) { 827 case NPNURLVCookie: { 828 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 829 PluginDestructionProtector protector(plugin.get()); 830 831 plugin->setCookiesForURL(makeURLString(url), String(value, len)); 832 return NPERR_NO_ERROR; 833 } 834 835 case NPNURLVProxy: 836 // Can't set the proxy for a URL. 837 return NPERR_GENERIC_ERROR; 838 839 default: 840 notImplemented(); 841 return NPERR_GENERIC_ERROR; 842 } 843 } 844 845 static NPError NPN_GetAuthenticationInfo(NPP instance, const char* protocol, const char* host, int32_t port, const char* scheme, 846 const char* realm, char** username, uint32_t* ulen, char** password, uint32_t* plen) 847 { 848 notImplemented(); 849 return NPERR_GENERIC_ERROR; 850 } 851 852 static uint32_t NPN_ScheduleTimer(NPP instance, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID)) 853 { 854 notImplemented(); 855 return NPERR_GENERIC_ERROR; 856 } 857 858 static void NPN_UnscheduleTimer(NPP instance, uint32_t timerID) 859 { 860 notImplemented(); 861 } 862 863 #if PLATFORM(MAC) 864 static NPError NPN_PopUpContextMenu(NPP npp, NPMenu* menu) 865 { 866 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 867 868 return plugin->popUpContextMenu(menu); 869 } 870 871 static NPBool NPN_ConvertPoint(NPP npp, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double* destX, double* destY, NPCoordinateSpace destSpace) 872 { 873 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 874 875 double destinationX; 876 double destinationY; 877 878 bool returnValue = plugin->convertPoint(sourceX, sourceY, sourceSpace, destinationX, destinationY, destSpace); 879 880 if (destX) 881 *destX = destinationX; 882 if (destY) 883 *destY = destinationY; 884 885 return returnValue; 886 } 887 #endif 888 889 static void initializeBrowserFuncs(NPNetscapeFuncs &netscapeFuncs) 890 { 891 netscapeFuncs.size = sizeof(NPNetscapeFuncs); 892 netscapeFuncs.version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR; 893 894 netscapeFuncs.geturl = NPN_GetURL; 895 netscapeFuncs.posturl = NPN_PostURL; 896 netscapeFuncs.requestread = NPN_RequestRead; 897 netscapeFuncs.newstream = NPN_NewStream; 898 netscapeFuncs.write = NPN_Write; 899 netscapeFuncs.destroystream = NPN_DestroyStream; 900 netscapeFuncs.status = NPN_Status; 901 netscapeFuncs.uagent = NPN_UserAgent; 902 netscapeFuncs.memalloc = NPN_MemAlloc; 903 netscapeFuncs.memfree = NPN_MemFree; 904 netscapeFuncs.memflush = NPN_MemFlush; 905 netscapeFuncs.reloadplugins = NPN_ReloadPlugins; 906 netscapeFuncs.getJavaEnv = NPN_GetJavaEnv; 907 netscapeFuncs.getJavaPeer = NPN_GetJavaPeer; 908 netscapeFuncs.geturlnotify = NPN_GetURLNotify; 909 netscapeFuncs.posturlnotify = NPN_PostURLNotify; 910 netscapeFuncs.getvalue = NPN_GetValue; 911 netscapeFuncs.setvalue = NPN_SetValue; 912 netscapeFuncs.invalidaterect = NPN_InvalidateRect; 913 netscapeFuncs.invalidateregion = NPN_InvalidateRegion; 914 netscapeFuncs.forceredraw = NPN_ForceRedraw; 915 916 netscapeFuncs.getstringidentifier = NPN_GetStringIdentifier; 917 netscapeFuncs.getstringidentifiers = NPN_GetStringIdentifiers; 918 netscapeFuncs.getintidentifier = NPN_GetIntIdentifier; 919 netscapeFuncs.identifierisstring = NPN_IdentifierIsString; 920 netscapeFuncs.utf8fromidentifier = NPN_UTF8FromIdentifier; 921 netscapeFuncs.intfromidentifier = NPN_IntFromIdentifier; 922 netscapeFuncs.createobject = NPN_CreateObject; 923 netscapeFuncs.retainobject = NPN_RetainObject; 924 netscapeFuncs.releaseobject = NPN_ReleaseObject; 925 netscapeFuncs.invoke = NPN_Invoke; 926 netscapeFuncs.invokeDefault = NPN_InvokeDefault; 927 netscapeFuncs.evaluate = NPN_Evaluate; 928 netscapeFuncs.getproperty = NPN_GetProperty; 929 netscapeFuncs.setproperty = NPN_SetProperty; 930 netscapeFuncs.removeproperty = NPN_RemoveProperty; 931 netscapeFuncs.hasproperty = NPN_HasProperty; 932 netscapeFuncs.hasmethod = NPN_HasMethod; 933 netscapeFuncs.releasevariantvalue = NPN_ReleaseVariantValue; 934 netscapeFuncs.setexception = NPN_SetException; 935 netscapeFuncs.pushpopupsenabledstate = NPN_PushPopupsEnabledState; 936 netscapeFuncs.poppopupsenabledstate = NPN_PopPopupsEnabledState; 937 netscapeFuncs.enumerate = NPN_Enumerate; 938 netscapeFuncs.pluginthreadasynccall = NPN_PluginThreadAsyncCall; 939 netscapeFuncs.construct = NPN_Construct; 940 netscapeFuncs.getvalueforurl = NPN_GetValueForURL; 941 netscapeFuncs.setvalueforurl = NPN_SetValueForURL; 942 netscapeFuncs.getauthenticationinfo = NPN_GetAuthenticationInfo; 943 netscapeFuncs.scheduletimer = NPN_ScheduleTimer; 944 netscapeFuncs.unscheduletimer = NPN_UnscheduleTimer; 945 #if PLATFORM(MAC) 946 netscapeFuncs.popupcontextmenu = NPN_PopUpContextMenu; 947 netscapeFuncs.convertpoint = NPN_ConvertPoint; 948 #else 949 netscapeFuncs.popupcontextmenu = 0; 950 netscapeFuncs.convertpoint = 0; 951 #endif 952 } 953 954 NPNetscapeFuncs* netscapeBrowserFuncs() 955 { 956 static NPNetscapeFuncs netscapeFuncs; 957 static bool initialized = false; 958 959 if (!initialized) { 960 initializeBrowserFuncs(netscapeFuncs); 961 initialized = true; 962 } 963 964 return &netscapeFuncs; 965 } 966 967 } // namespace WebKit 968