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