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#if ENABLE(NETSCAPE_PLUGIN_API) 30 31#include "NPRuntimeUtilities.h" 32#include "NetscapePlugin.h" 33#include "PluginController.h" 34#include <WebCore/HTTPHeaderMap.h> 35#include <WebCore/HTTPHeaderNames.h> 36#include <WebCore/IdentifierRep.h> 37#include <WebCore/NotImplemented.h> 38#include <WebCore/ProtectionSpace.h> 39#include <WebCore/SharedBuffer.h> 40#include <memory> 41#include <utility> 42#include <wtf/text/StringBuilder.h> 43 44using namespace WebCore; 45 46namespace WebKit { 47 48// Helper class for delaying destruction of a plug-in. 49class PluginDestructionProtector { 50public: 51 explicit PluginDestructionProtector(NetscapePlugin* plugin) 52 { 53 if (plugin) 54 m_protector = std::make_unique<PluginController::PluginDestructionProtector>(static_cast<Plugin*>(plugin)->controller()); 55 } 56 57private: 58 std::unique_ptr<PluginController::PluginDestructionProtector> m_protector; 59}; 60 61static bool startsWithBlankLine(const char* bytes, unsigned length) 62{ 63 return length > 0 && bytes[0] == '\n'; 64} 65 66static 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 94static 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 122static String capitalizeRFC822HeaderFieldName(const String& name) 123{ 124 bool capitalizeCharacter = true; 125 StringBuilder 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.toString(); 146} 147 148static 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 value = oldValue + ", " + value; 207 208 headerFields.set(lastHeaderKey, value); 209 } 210 } 211 212 return headerFields; 213} 214 215static NPError parsePostBuffer(bool isFile, const char *buffer, uint32_t length, bool parseHeaders, HTTPHeaderMap& headerFields, Vector<uint8_t>& bodyData) 216{ 217 RefPtr<SharedBuffer> fileContents; 218 const char* postBuffer = 0; 219 uint32_t postBufferSize = 0; 220 221 if (isFile) { 222 fileContents = SharedBuffer::createWithContentsOfFile(String::fromUTF8(buffer)); 223 if (!fileContents) 224 return NPERR_FILE_NOT_FOUND; 225 226 postBuffer = fileContents->data(); 227 postBufferSize = fileContents->size(); 228 229 // FIXME: The NPAPI spec states that the file should be deleted here. 230 } else { 231 postBuffer = buffer; 232 postBufferSize = length; 233 } 234 235 if (parseHeaders) { 236 if (startsWithBlankLine(postBuffer, postBufferSize)) { 237 postBuffer++; 238 postBufferSize--; 239 } else { 240 int location = locationAfterFirstBlankLine(postBuffer, postBufferSize); 241 if (location != -1) { 242 // If the blank line is somewhere in the middle of the buffer, everything before is the header 243 headerFields = parseRFC822HeaderFields(postBuffer, location); 244 unsigned dataLength = postBufferSize - location; 245 246 // Sometimes plugins like to set Content-Length themselves when they post, 247 // but WebFoundation does not like that. So we will remove the header 248 // and instead truncate the data to the requested length. 249 String contentLength = headerFields.get(HTTPHeaderName::ContentLength); 250 251 if (!contentLength.isNull()) 252 dataLength = std::min(contentLength.toInt(), (int)dataLength); 253 headerFields.remove(HTTPHeaderName::ContentLength); 254 255 postBuffer += location; 256 postBufferSize = dataLength; 257 } 258 } 259 } 260 261 ASSERT(bodyData.isEmpty()); 262 bodyData.append(postBuffer, postBufferSize); 263 264 return NPERR_NO_ERROR; 265} 266 267static String makeURLString(const char* url) 268{ 269 String urlString(url); 270 271 // Strip return characters. 272 urlString.replaceWithLiteral('\r', ""); 273 urlString.replaceWithLiteral('\n', ""); 274 275 return urlString; 276} 277 278static NPError NPN_GetURL(NPP npp, const char* url, const char* target) 279{ 280 if (!url) 281 return NPERR_GENERIC_ERROR; 282 283 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 284 plugin->loadURL("GET", makeURLString(url), target, HTTPHeaderMap(), Vector<uint8_t>(), false, 0); 285 286 return NPERR_GENERIC_ERROR; 287} 288 289static NPError NPN_PostURL(NPP npp, const char* url, const char* target, uint32_t len, const char* buf, NPBool file) 290{ 291 HTTPHeaderMap headerFields; 292 Vector<uint8_t> postData; 293 294 // NPN_PostURL only allows headers if the post buffer points to a file. 295 bool parseHeaders = file; 296 297 NPError error = parsePostBuffer(file, buf, len, parseHeaders, headerFields, postData); 298 if (error != NPERR_NO_ERROR) 299 return error; 300 301 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 302 plugin->loadURL("POST", makeURLString(url), target, WTF::move(headerFields), postData, false, 0); 303 return NPERR_NO_ERROR; 304} 305 306static NPError NPN_RequestRead(NPStream*, NPByteRange*) 307{ 308 notImplemented(); 309 return NPERR_GENERIC_ERROR; 310} 311 312static NPError NPN_NewStream(NPP, NPMIMEType, const char*, NPStream**) 313{ 314 notImplemented(); 315 return NPERR_GENERIC_ERROR; 316} 317 318static int32_t NPN_Write(NPP, NPStream*, int32_t, void*) 319{ 320 notImplemented(); 321 return -1; 322} 323 324static NPError NPN_DestroyStream(NPP npp, NPStream* stream, NPReason reason) 325{ 326 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 327 328 return plugin->destroyStream(stream, reason); 329} 330 331static void NPN_Status(NPP npp, const char* message) 332{ 333 String statusbarText; 334 if (!message) 335 statusbarText = ""; 336 else 337 statusbarText = String::fromUTF8WithLatin1Fallback(message, strlen(message)); 338 339 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 340 plugin->setStatusbarText(statusbarText); 341} 342 343static const char* NPN_UserAgent(NPP npp) 344{ 345 return NetscapePlugin::userAgent(npp); 346} 347 348static void* NPN_MemAlloc(uint32_t size) 349{ 350 return npnMemAlloc(size); 351} 352 353static void NPN_MemFree(void* ptr) 354{ 355 npnMemFree(ptr); 356} 357 358static uint32_t NPN_MemFlush(uint32_t) 359{ 360 return 0; 361} 362 363static void NPN_ReloadPlugins(NPBool) 364{ 365 notImplemented(); 366} 367 368static JRIEnv* NPN_GetJavaEnv(void) 369{ 370 notImplemented(); 371 return 0; 372} 373 374static jref NPN_GetJavaPeer(NPP) 375{ 376 notImplemented(); 377 return 0; 378} 379 380static NPError NPN_GetURLNotify(NPP npp, const char* url, const char* target, void* notifyData) 381{ 382 if (!url) 383 return NPERR_GENERIC_ERROR; 384 385 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 386 plugin->loadURL("GET", makeURLString(url), target, HTTPHeaderMap(), Vector<uint8_t>(), true, notifyData); 387 388 return NPERR_NO_ERROR; 389} 390 391static NPError NPN_PostURLNotify(NPP npp, const char* url, const char* target, uint32_t len, const char* buf, NPBool file, void* notifyData) 392{ 393 HTTPHeaderMap headerFields; 394 Vector<uint8_t> postData; 395 NPError error = parsePostBuffer(file, buf, len, true, headerFields, postData); 396 if (error != NPERR_NO_ERROR) 397 return error; 398 399 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 400 plugin->loadURL("POST", makeURLString(url), target, headerFields, postData, true, notifyData); 401 return NPERR_NO_ERROR; 402} 403 404#if PLATFORM(COCOA) 405// Whether the browser supports compositing of Core Animation plug-ins. 406static const unsigned WKNVSupportsCompositingCoreAnimationPluginsBool = 74656; 407 408// Whether the browser expects a non-retained Core Animation layer. 409static const unsigned WKNVExpectsNonretainedLayer = 74657; 410 411// 74658 and 74659 are no longer implemented. 412 413static const unsigned WKNVPlugInContainer = 74660; 414 415#endif 416 417static NPError NPN_GetValue(NPP npp, NPNVariable variable, void *value) 418{ 419 switch (static_cast<unsigned>(variable)) { 420 case NPNVWindowNPObject: { 421 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 422 PluginDestructionProtector protector(plugin.get()); 423 424 NPObject* windowNPObject = plugin->windowScriptNPObject(); 425 if (!windowNPObject) 426 return NPERR_GENERIC_ERROR; 427 428 *(NPObject**)value = windowNPObject; 429 break; 430 } 431 case NPNVPluginElementNPObject: { 432 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 433 PluginDestructionProtector protector(plugin.get()); 434 435 NPObject* pluginElementNPObject = plugin->pluginElementNPObject(); 436 *(NPObject**)value = pluginElementNPObject; 437 break; 438 } 439 case NPNVprivateModeBool: { 440 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 441 442 *(NPBool*)value = plugin->isPrivateBrowsingEnabled(); 443 break; 444 } 445#if PLATFORM(COCOA) 446 case NPNVsupportsCoreGraphicsBool: 447 // Always claim to support the Core Graphics drawing model. 448 *(NPBool*)value = true; 449 break; 450 451 case WKNVSupportsCompositingCoreAnimationPluginsBool: 452 case NPNVsupportsCoreAnimationBool: { 453 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 454 455 *(NPBool*)value = plugin->isAcceleratedCompositingEnabled(); 456 break; 457 } 458 case NPNVcontentsScaleFactor: { 459 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 460 461 *(double*)value = plugin->contentsScaleFactor(); 462 break; 463 } 464 case NPNVsupportsCocoaBool: 465 // Always claim to support the Cocoa event model. 466 *(NPBool*)value = true; 467 break; 468 469 case NPNVsupportsUpdatedCocoaTextInputBool: { 470 // The plug-in is asking whether we support the updated Cocoa text input model. 471 // If we haven't yet delivered a key down event to the plug-in, we can opt into the updated 472 // model and say that we support it. Otherwise, we'll just fall back and say that we don't support it. 473 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 474 475 bool supportsUpdatedTextInput = !plugin->hasHandledAKeyDownEvent(); 476 if (supportsUpdatedTextInput) 477 plugin->setPluginWantsLegacyCocoaTextInput(false); 478 479 *reinterpret_cast<NPBool*>(value) = supportsUpdatedTextInput; 480 break; 481 } 482 483 case WKNVCALayerRenderServerPort: { 484 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 485 486 *(mach_port_t*)value = plugin->compositingRenderServerPort(); 487 break; 488 } 489 490 case WKNVExpectsNonretainedLayer: { 491 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 492 493 // Asking for this will make us expect a non-retained layer from the plug-in. 494 plugin->setPluginReturnsNonretainedLayer(true); 495 *(NPBool*)value = true; 496 break; 497 } 498 499 case WKNVPlugInContainer: { 500 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 501 *reinterpret_cast<void**>(value) = plugin->plugInContainer(); 502 break; 503 } 504 505#ifndef NP_NO_QUICKDRAW 506 case NPNVsupportsQuickDrawBool: 507 // We don't support the QuickDraw drawing model. 508 *(NPBool*)value = false; 509 break; 510#endif 511#ifndef NP_NO_CARBON 512 case NPNVsupportsCarbonBool: 513 *(NPBool*)value = true; 514 break; 515#endif 516#elif PLUGIN_ARCHITECTURE(X11) 517 case NPNVxDisplay: { 518 if (!npp) 519 return NPERR_GENERIC_ERROR; 520 *reinterpret_cast<Display**>(value) = NetscapePlugin::x11HostDisplay(); 521 break; 522 } 523 case NPNVSupportsXEmbedBool: 524 *static_cast<NPBool*>(value) = true; 525 break; 526 case NPNVSupportsWindowless: 527 *static_cast<NPBool*>(value) = true; 528 break; 529 530 case NPNVToolkit: { 531 // Gtk based plugins need to be assured about the toolkit version. 532 const uint32_t expectedGtkToolKitVersion = 2; 533 *reinterpret_cast<uint32_t*>(value) = expectedGtkToolKitVersion; 534 break; 535 } 536 537 // TODO: implement NPNVnetscapeWindow once we want to support windowed plugins. 538#endif 539 default: 540 notImplemented(); 541 return NPERR_GENERIC_ERROR; 542 } 543 544 return NPERR_NO_ERROR; 545} 546 547static NPError NPN_SetValue(NPP npp, NPPVariable variable, void *value) 548{ 549 switch (variable) { 550#if PLATFORM(COCOA) 551 case NPPVpluginDrawingModel: { 552 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 553 554 NPDrawingModel drawingModel = static_cast<NPDrawingModel>(reinterpret_cast<uintptr_t>(value)); 555 return plugin->setDrawingModel(drawingModel); 556 } 557 558 case NPPVpluginEventModel: { 559 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 560 561 NPEventModel eventModel = static_cast<NPEventModel>(reinterpret_cast<uintptr_t>(value)); 562 return plugin->setEventModel(eventModel); 563 } 564#endif 565 566 case NPPVpluginWindowBool: { 567 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 568 plugin->setIsWindowed(value); 569 return NPERR_NO_ERROR; 570 } 571 572 case NPPVpluginTransparentBool: { 573 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 574 plugin->setIsTransparent(value); 575 return NPERR_NO_ERROR; 576 } 577 578 default: 579 notImplemented(); 580 return NPERR_GENERIC_ERROR; 581 } 582} 583 584static void NPN_InvalidateRect(NPP npp, NPRect* invalidRect) 585{ 586#if PLUGIN_ARCHITECTURE(X11) 587 // NSPluginWrapper, a plugin wrapper binary that allows running 32-bit plugins 588 // on 64-bit architectures typically used in X11, will sometimes give us a null NPP here. 589 if (!npp) 590 return; 591#endif 592 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 593 plugin->invalidate(invalidRect); 594} 595 596static void NPN_InvalidateRegion(NPP npp, NPRegion) 597{ 598 // FIXME: We could at least figure out the bounding rectangle of the invalid region. 599 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 600 plugin->invalidate(0); 601} 602 603static void NPN_ForceRedraw(NPP) 604{ 605 notImplemented(); 606} 607 608static NPIdentifier NPN_GetStringIdentifier(const NPUTF8 *name) 609{ 610 return static_cast<NPIdentifier>(IdentifierRep::get(name)); 611} 612 613static void NPN_GetStringIdentifiers(const NPUTF8 **names, int32_t nameCount, NPIdentifier *identifiers) 614{ 615 ASSERT(names); 616 ASSERT(identifiers); 617 618 if (!names || !identifiers) 619 return; 620 621 for (int32_t i = 0; i < nameCount; ++i) 622 identifiers[i] = NPN_GetStringIdentifier(names[i]); 623} 624 625static NPIdentifier NPN_GetIntIdentifier(int32_t intid) 626{ 627 return static_cast<NPIdentifier>(IdentifierRep::get(intid)); 628} 629 630static bool NPN_IdentifierIsString(NPIdentifier identifier) 631{ 632 return static_cast<IdentifierRep*>(identifier)->isString(); 633} 634 635static NPUTF8 *NPN_UTF8FromIdentifier(NPIdentifier identifier) 636{ 637 const char* string = static_cast<IdentifierRep*>(identifier)->string(); 638 if (!string) 639 return 0; 640 641 uint32_t stringLength = strlen(string); 642 char* utf8String = npnMemNewArray<char>(stringLength + 1); 643 memcpy(utf8String, string, stringLength); 644 utf8String[stringLength] = '\0'; 645 646 return utf8String; 647} 648 649static int32_t NPN_IntFromIdentifier(NPIdentifier identifier) 650{ 651 return static_cast<IdentifierRep*>(identifier)->number(); 652} 653 654static NPObject* NPN_CreateObject(NPP npp, NPClass *npClass) 655{ 656 return createNPObject(npp, npClass); 657} 658 659static NPObject *NPN_RetainObject(NPObject *npObject) 660{ 661 retainNPObject(npObject); 662 return npObject; 663} 664 665static void NPN_ReleaseObject(NPObject *npObject) 666{ 667 releaseNPObject(npObject); 668} 669 670static bool NPN_Invoke(NPP npp, NPObject *npObject, NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 671{ 672 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 673 PluginDestructionProtector protector(plugin.get()); 674 675 if (npObject->_class->invoke) 676 return npObject->_class->invoke(npObject, methodName, arguments, argumentCount, result); 677 678 return false; 679} 680 681static bool NPN_InvokeDefault(NPP npp, NPObject *npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 682{ 683 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 684 PluginDestructionProtector protector(plugin.get()); 685 686 if (npObject->_class->invokeDefault) 687 return npObject->_class->invokeDefault(npObject, arguments, argumentCount, result); 688 689 return false; 690} 691 692static bool NPN_Evaluate(NPP npp, NPObject *npObject, NPString *script, NPVariant* result) 693{ 694 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 695 PluginDestructionProtector protector(plugin.get()); 696 697 String scriptString = String::fromUTF8WithLatin1Fallback(script->UTF8Characters, script->UTF8Length); 698 699 return plugin->evaluate(npObject, scriptString, result); 700} 701 702static bool NPN_GetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, NPVariant* result) 703{ 704 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 705 PluginDestructionProtector protector(plugin.get()); 706 707 if (npObject->_class->getProperty) 708 return npObject->_class->getProperty(npObject, propertyName, result); 709 710 return false; 711} 712 713static bool NPN_SetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, const NPVariant* value) 714{ 715 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 716 PluginDestructionProtector protector(plugin.get()); 717 718 if (npObject->_class->setProperty) 719 return npObject->_class->setProperty(npObject, propertyName, value); 720 721 return false; 722} 723 724static bool NPN_RemoveProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName) 725{ 726 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 727 PluginDestructionProtector protector(plugin.get()); 728 729 if (npObject->_class->removeProperty) 730 return npObject->_class->removeProperty(npObject, propertyName); 731 732 return false; 733} 734 735static bool NPN_HasProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName) 736{ 737 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 738 PluginDestructionProtector protector(plugin.get()); 739 740 if (npObject->_class->hasProperty) 741 return npObject->_class->hasProperty(npObject, propertyName); 742 743 return false; 744} 745 746static bool NPN_HasMethod(NPP npp, NPObject* npObject, NPIdentifier methodName) 747{ 748 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 749 PluginDestructionProtector protector(plugin.get()); 750 751 if (npObject->_class->hasMethod) 752 return npObject->_class->hasMethod(npObject, methodName); 753 754 return false; 755} 756 757static void NPN_ReleaseVariantValue(NPVariant* variant) 758{ 759 releaseNPVariantValue(variant); 760} 761 762static void NPN_SetException(NPObject*, const NPUTF8* message) 763{ 764 NetscapePlugin::setException(message); 765} 766 767static void NPN_PushPopupsEnabledState(NPP npp, NPBool enabled) 768{ 769 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 770 plugin->pushPopupsEnabledState(enabled); 771} 772 773static void NPN_PopPopupsEnabledState(NPP npp) 774{ 775 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 776 plugin->popPopupsEnabledState(); 777} 778 779static bool NPN_Enumerate(NPP npp, NPObject* npObject, NPIdentifier** identifiers, uint32_t* identifierCount) 780{ 781 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 782 PluginDestructionProtector protector(plugin.get()); 783 784 if (NP_CLASS_STRUCT_VERSION_HAS_ENUM(npObject->_class) && npObject->_class->enumerate) 785 return npObject->_class->enumerate(npObject, identifiers, identifierCount); 786 787 return false; 788} 789 790static void NPN_PluginThreadAsyncCall(NPP npp, void (*function)(void*), void* userData) 791{ 792 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 793 794 plugin->pluginThreadAsyncCall(function, userData); 795} 796 797static bool NPN_Construct(NPP npp, NPObject* npObject, const NPVariant* arguments, uint32_t argumentCount, NPVariant* result) 798{ 799 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 800 PluginDestructionProtector protector(plugin.get()); 801 802 if (NP_CLASS_STRUCT_VERSION_HAS_CTOR(npObject->_class) && npObject->_class->construct) 803 return npObject->_class->construct(npObject, arguments, argumentCount, result); 804 805 return false; 806} 807 808static NPError copyCString(const CString& string, char** value, uint32_t* len) 809{ 810 ASSERT(!string.isNull()); 811 ASSERT(value); 812 ASSERT(len); 813 814 *value = npnMemNewArray<char>(string.length()); 815 if (!*value) 816 return NPERR_GENERIC_ERROR; 817 818 memcpy(*value, string.data(), string.length()); 819 *len = string.length(); 820 return NPERR_NO_ERROR; 821} 822 823static NPError NPN_GetValueForURL(NPP npp, NPNURLVariable variable, const char* url, char** value, uint32_t* len) 824{ 825 if (!value || !len) 826 return NPERR_GENERIC_ERROR; 827 828 switch (variable) { 829 case NPNURLVCookie: { 830 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 831 PluginDestructionProtector protector(plugin.get()); 832 833 String cookies = plugin->cookiesForURL(makeURLString(url)); 834 if (cookies.isNull()) 835 return NPERR_GENERIC_ERROR; 836 837 return copyCString(cookies.utf8(), value, len); 838 } 839 840 case NPNURLVProxy: { 841 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 842 PluginDestructionProtector protector(plugin.get()); 843 844 String proxies = plugin->proxiesForURL(makeURLString(url)); 845 if (proxies.isNull()) 846 return NPERR_GENERIC_ERROR; 847 848 return copyCString(proxies.utf8(), value, len); 849 } 850 default: 851 notImplemented(); 852 return NPERR_GENERIC_ERROR; 853 } 854} 855 856static NPError NPN_SetValueForURL(NPP npp, NPNURLVariable variable, const char* url, const char* value, uint32_t len) 857{ 858 switch (variable) { 859 case NPNURLVCookie: { 860 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 861 PluginDestructionProtector protector(plugin.get()); 862 863 plugin->setCookiesForURL(makeURLString(url), String(value, len)); 864 return NPERR_NO_ERROR; 865 } 866 867 case NPNURLVProxy: 868 // Can't set the proxy for a URL. 869 return NPERR_GENERIC_ERROR; 870 871 default: 872 notImplemented(); 873 return NPERR_GENERIC_ERROR; 874 } 875} 876 877static bool initializeProtectionSpace(const char* protocol, const char* host, int port, const char* scheme, const char* realm, ProtectionSpace& protectionSpace) 878{ 879 ProtectionSpaceServerType serverType; 880 if (!strcasecmp(protocol, "http")) 881 serverType = ProtectionSpaceServerHTTP; 882 else if (!strcasecmp(protocol, "https")) 883 serverType = ProtectionSpaceServerHTTPS; 884 else { 885 // We only care about http and https. 886 return false; 887 } 888 889 ProtectionSpaceAuthenticationScheme authenticationScheme = ProtectionSpaceAuthenticationSchemeDefault; 890 if (serverType == ProtectionSpaceServerHTTP) { 891 if (!strcasecmp(scheme, "basic")) 892 authenticationScheme = ProtectionSpaceAuthenticationSchemeHTTPBasic; 893 else if (!strcmp(scheme, "digest")) 894 authenticationScheme = ProtectionSpaceAuthenticationSchemeHTTPDigest; 895 } 896 897 protectionSpace = ProtectionSpace(host, port, serverType, realm, authenticationScheme); 898 return true; 899} 900 901static NPError NPN_GetAuthenticationInfo(NPP npp, const char* protocol, const char* host, int32_t port, const char* scheme, 902 const char* realm, char** username, uint32_t* usernameLength, char** password, uint32_t* passwordLength) 903{ 904 if (!protocol || !host || !scheme || !realm || !username || !usernameLength || !password || !passwordLength) 905 return NPERR_GENERIC_ERROR; 906 907 ProtectionSpace protectionSpace; 908 if (!initializeProtectionSpace(protocol, host, port, scheme, realm, protectionSpace)) 909 return NPERR_GENERIC_ERROR; 910 911 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 912 String usernameString; 913 String passwordString; 914 if (!plugin->getAuthenticationInfo(protectionSpace, usernameString, passwordString)) 915 return NPERR_GENERIC_ERROR; 916 917 NPError result = copyCString(usernameString.utf8(), username, usernameLength); 918 if (result != NPERR_NO_ERROR) 919 return result; 920 921 result = copyCString(passwordString.utf8(), password, passwordLength); 922 if (result != NPERR_NO_ERROR) { 923 npnMemFree(*username); 924 return result; 925 } 926 927 return NPERR_NO_ERROR; 928} 929 930static uint32_t NPN_ScheduleTimer(NPP npp, uint32_t interval, NPBool repeat, void (*timerFunc)(NPP npp, uint32_t timerID)) 931{ 932 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 933 934 return plugin->scheduleTimer(interval, repeat, timerFunc); 935} 936 937static void NPN_UnscheduleTimer(NPP npp, uint32_t timerID) 938{ 939 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 940 941 plugin->unscheduleTimer(timerID); 942} 943 944#if PLATFORM(COCOA) 945static NPError NPN_PopUpContextMenu(NPP npp, NPMenu* menu) 946{ 947 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 948 949 return plugin->popUpContextMenu(menu); 950} 951 952static NPBool NPN_ConvertPoint(NPP npp, double sourceX, double sourceY, NPCoordinateSpace sourceSpace, double* destX, double* destY, NPCoordinateSpace destSpace) 953{ 954 RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp); 955 956 double destinationX; 957 double destinationY; 958 959 bool returnValue = plugin->convertPoint(sourceX, sourceY, sourceSpace, destinationX, destinationY, destSpace); 960 961 if (destX) 962 *destX = destinationX; 963 if (destY) 964 *destY = destinationY; 965 966 return returnValue; 967} 968#endif 969 970static void initializeBrowserFuncs(NPNetscapeFuncs &netscapeFuncs) 971{ 972 netscapeFuncs.size = sizeof(NPNetscapeFuncs); 973 netscapeFuncs.version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR; 974 975 netscapeFuncs.geturl = NPN_GetURL; 976 netscapeFuncs.posturl = NPN_PostURL; 977 netscapeFuncs.requestread = NPN_RequestRead; 978 netscapeFuncs.newstream = NPN_NewStream; 979 netscapeFuncs.write = NPN_Write; 980 netscapeFuncs.destroystream = NPN_DestroyStream; 981 netscapeFuncs.status = NPN_Status; 982 netscapeFuncs.uagent = NPN_UserAgent; 983 netscapeFuncs.memalloc = NPN_MemAlloc; 984 netscapeFuncs.memfree = NPN_MemFree; 985 netscapeFuncs.memflush = NPN_MemFlush; 986 netscapeFuncs.reloadplugins = NPN_ReloadPlugins; 987 netscapeFuncs.getJavaEnv = NPN_GetJavaEnv; 988 netscapeFuncs.getJavaPeer = NPN_GetJavaPeer; 989 netscapeFuncs.geturlnotify = NPN_GetURLNotify; 990 netscapeFuncs.posturlnotify = NPN_PostURLNotify; 991 netscapeFuncs.getvalue = NPN_GetValue; 992 netscapeFuncs.setvalue = NPN_SetValue; 993 netscapeFuncs.invalidaterect = NPN_InvalidateRect; 994 netscapeFuncs.invalidateregion = NPN_InvalidateRegion; 995 netscapeFuncs.forceredraw = NPN_ForceRedraw; 996 997 netscapeFuncs.getstringidentifier = NPN_GetStringIdentifier; 998 netscapeFuncs.getstringidentifiers = NPN_GetStringIdentifiers; 999 netscapeFuncs.getintidentifier = NPN_GetIntIdentifier; 1000 netscapeFuncs.identifierisstring = NPN_IdentifierIsString; 1001 netscapeFuncs.utf8fromidentifier = NPN_UTF8FromIdentifier; 1002 netscapeFuncs.intfromidentifier = NPN_IntFromIdentifier; 1003 netscapeFuncs.createobject = NPN_CreateObject; 1004 netscapeFuncs.retainobject = NPN_RetainObject; 1005 netscapeFuncs.releaseobject = NPN_ReleaseObject; 1006 netscapeFuncs.invoke = NPN_Invoke; 1007 netscapeFuncs.invokeDefault = NPN_InvokeDefault; 1008 netscapeFuncs.evaluate = NPN_Evaluate; 1009 netscapeFuncs.getproperty = NPN_GetProperty; 1010 netscapeFuncs.setproperty = NPN_SetProperty; 1011 netscapeFuncs.removeproperty = NPN_RemoveProperty; 1012 netscapeFuncs.hasproperty = NPN_HasProperty; 1013 netscapeFuncs.hasmethod = NPN_HasMethod; 1014 netscapeFuncs.releasevariantvalue = NPN_ReleaseVariantValue; 1015 netscapeFuncs.setexception = NPN_SetException; 1016 netscapeFuncs.pushpopupsenabledstate = NPN_PushPopupsEnabledState; 1017 netscapeFuncs.poppopupsenabledstate = NPN_PopPopupsEnabledState; 1018 netscapeFuncs.enumerate = NPN_Enumerate; 1019 netscapeFuncs.pluginthreadasynccall = NPN_PluginThreadAsyncCall; 1020 netscapeFuncs.construct = NPN_Construct; 1021 netscapeFuncs.getvalueforurl = NPN_GetValueForURL; 1022 netscapeFuncs.setvalueforurl = NPN_SetValueForURL; 1023 netscapeFuncs.getauthenticationinfo = NPN_GetAuthenticationInfo; 1024 netscapeFuncs.scheduletimer = NPN_ScheduleTimer; 1025 netscapeFuncs.unscheduletimer = NPN_UnscheduleTimer; 1026#if PLATFORM(COCOA) 1027 netscapeFuncs.popupcontextmenu = NPN_PopUpContextMenu; 1028 netscapeFuncs.convertpoint = NPN_ConvertPoint; 1029#else 1030 netscapeFuncs.popupcontextmenu = 0; 1031 netscapeFuncs.convertpoint = 0; 1032#endif 1033} 1034 1035NPNetscapeFuncs* netscapeBrowserFuncs() 1036{ 1037 static NPNetscapeFuncs netscapeFuncs; 1038 static bool initialized = false; 1039 1040 if (!initialized) { 1041 initializeBrowserFuncs(netscapeFuncs); 1042 initialized = true; 1043 } 1044 1045 return &netscapeFuncs; 1046} 1047 1048} // namespace WebKit 1049 1050#endif // ENABLE(NETSCAPE_PLUGIN_API) 1051