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 "NetscapePlugin.h" 28 29#if ENABLE(NETSCAPE_PLUGIN_API) 30 31#include "NPRuntimeObjectMap.h" 32#include "NPRuntimeUtilities.h" 33#include "NetscapePluginStream.h" 34#include "PluginController.h" 35#include "ShareableBitmap.h" 36#include <WebCore/GraphicsContext.h> 37#include <WebCore/HTTPHeaderMap.h> 38#include <WebCore/IntRect.h> 39#include <WebCore/URL.h> 40#include <WebCore/SharedBuffer.h> 41#include <runtime/JSObject.h> 42#include <utility> 43#include <wtf/text/CString.h> 44 45using namespace WebCore; 46 47namespace WebKit { 48 49// The plug-in that we're currently calling NPP_New for. 50static NetscapePlugin* currentNPPNewPlugin; 51 52PassRefPtr<NetscapePlugin> NetscapePlugin::create(PassRefPtr<NetscapePluginModule> pluginModule) 53{ 54 if (!pluginModule) 55 return 0; 56 57 return adoptRef(new NetscapePlugin(pluginModule)); 58} 59 60NetscapePlugin::NetscapePlugin(PassRefPtr<NetscapePluginModule> pluginModule) 61 : m_nextRequestID(0) 62 , m_pluginModule(pluginModule) 63 , m_npWindow() 64 , m_isStarted(false) 65#if PLATFORM(COCOA) 66 , m_isWindowed(false) 67#else 68 , m_isWindowed(true) 69#endif 70 , m_isTransparent(false) 71 , m_inNPPNew(false) 72 , m_shouldUseManualLoader(false) 73 , m_hasCalledSetWindow(false) 74 , m_isVisible(false) 75 , m_nextTimerID(0) 76#if PLATFORM(COCOA) 77 , m_drawingModel(static_cast<NPDrawingModel>(-1)) 78 , m_eventModel(static_cast<NPEventModel>(-1)) 79 , m_pluginReturnsNonretainedLayer(!m_pluginModule->pluginQuirks().contains(PluginQuirks::ReturnsRetainedCoreAnimationLayer)) 80 , m_layerHostingMode(LayerHostingMode::InProcess) 81 , m_currentMouseEvent(0) 82 , m_pluginHasFocus(false) 83 , m_windowHasFocus(false) 84 , m_pluginWantsLegacyCocoaTextInput(true) 85 , m_isComplexTextInputEnabled(false) 86 , m_hasHandledAKeyDownEvent(false) 87 , m_ignoreNextKeyUpEventCounter(0) 88#ifndef NP_NO_CARBON 89 , m_nullEventTimer(RunLoop::main(), this, &NetscapePlugin::nullEventTimerFired) 90 , m_npCGContext() 91#endif 92#elif PLUGIN_ARCHITECTURE(X11) 93 , m_drawable(0) 94 , m_pluginDisplay(0) 95#if PLATFORM(GTK) 96 , m_platformPluginWidget(0) 97#endif 98#endif 99{ 100 m_npp.ndata = this; 101 m_npp.pdata = 0; 102 103 m_pluginModule->incrementLoadCount(); 104} 105 106NetscapePlugin::~NetscapePlugin() 107{ 108 ASSERT(!m_isStarted); 109 ASSERT(m_timers.isEmpty()); 110 111 m_pluginModule->decrementLoadCount(); 112} 113 114PassRefPtr<NetscapePlugin> NetscapePlugin::fromNPP(NPP npp) 115{ 116 if (!npp) 117 return 0; 118 119 return static_cast<NetscapePlugin*>(npp->ndata); 120} 121 122void NetscapePlugin::invalidate(const NPRect* invalidRect) 123{ 124 IntRect rect; 125 126 if (!invalidRect) 127 rect = IntRect(0, 0, m_pluginSize.width(), m_pluginSize.height()); 128 else 129 rect = IntRect(invalidRect->left, invalidRect->top, invalidRect->right - invalidRect->left, invalidRect->bottom - invalidRect->top); 130 131 if (platformInvalidate(rect)) 132 return; 133 134 controller()->invalidate(rect); 135} 136 137const char* NetscapePlugin::userAgent(NPP npp) 138{ 139 if (npp) 140 return fromNPP(npp)->userAgent(); 141 142 if (currentNPPNewPlugin) 143 return currentNPPNewPlugin->userAgent(); 144 145 return 0; 146} 147 148const char* NetscapePlugin::userAgent() 149{ 150#if PLUGIN_ARCHITECTURE(WIN) 151 static const char* MozillaUserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0"; 152 153 if (quirks().contains(PluginQuirks::WantsMozillaUserAgent)) 154 return MozillaUserAgent; 155#endif 156 157 if (m_userAgent.isNull()) { 158 String userAgent = controller()->userAgent(); 159 ASSERT(!userAgent.isNull()); 160 161#if PLUGIN_ARCHITECTURE(MAC) 162 if (quirks().contains(PluginQuirks::AppendVersion3UserAgent)) 163 userAgent.append(" Version/3.2.1"); 164#endif 165 166 m_userAgent = userAgent.utf8(); 167 } 168 return m_userAgent.data(); 169} 170 171void NetscapePlugin::loadURL(const String& method, const String& urlString, const String& target, const HTTPHeaderMap& headerFields, const Vector<uint8_t>& httpBody, 172 bool sendNotification, void* notificationData) 173{ 174 uint64_t requestID = ++m_nextRequestID; 175 176 controller()->loadURL(requestID, method, urlString, target, headerFields, httpBody, allowPopups()); 177 178 if (target.isNull()) { 179 // The browser is going to send the data in a stream, create a plug-in stream. 180 RefPtr<NetscapePluginStream> pluginStream = NetscapePluginStream::create(this, requestID, urlString, sendNotification, notificationData); 181 ASSERT(!m_streams.contains(requestID)); 182 183 m_streams.set(requestID, pluginStream.release()); 184 return; 185 } 186 187 if (sendNotification) { 188 // Eventually we are going to get a frameDidFinishLoading or frameDidFail call for this request. 189 // Keep track of the notification data so we can call NPP_URLNotify. 190 ASSERT(!m_pendingURLNotifications.contains(requestID)); 191 m_pendingURLNotifications.set(requestID, std::make_pair(urlString, notificationData)); 192 } 193} 194 195NPError NetscapePlugin::destroyStream(NPStream* stream, NPReason reason) 196{ 197 NetscapePluginStream* pluginStream = 0; 198 199 for (StreamsMap::const_iterator it = m_streams.begin(), end = m_streams.end(); it != end; ++it) { 200 if (it->value->npStream() == stream) { 201 pluginStream = it->value.get(); 202 break; 203 } 204 } 205 206 if (!pluginStream) 207 return NPERR_INVALID_INSTANCE_ERROR; 208 209 return pluginStream->destroy(reason); 210} 211 212void NetscapePlugin::setIsWindowed(bool isWindowed) 213{ 214 // Once the plugin has started, it's too late to change whether the plugin is windowed or not. 215 // (This is true in Firefox and Chrome, too.) Disallow setting m_isWindowed in that case to 216 // keep our internal state consistent. 217 if (m_isStarted) 218 return; 219 220 m_isWindowed = isWindowed; 221} 222 223void NetscapePlugin::setIsTransparent(bool isTransparent) 224{ 225 m_isTransparent = isTransparent; 226} 227 228void NetscapePlugin::setStatusbarText(const String& statusbarText) 229{ 230 controller()->setStatusbarText(statusbarText); 231} 232 233static void (*setExceptionFunction)(const String&); 234 235void NetscapePlugin::setSetExceptionFunction(void (*function)(const String&)) 236{ 237 ASSERT(!setExceptionFunction || setExceptionFunction == function); 238 setExceptionFunction = function; 239} 240 241void NetscapePlugin::setException(const String& exceptionString) 242{ 243 ASSERT(setExceptionFunction); 244 setExceptionFunction(exceptionString); 245} 246 247bool NetscapePlugin::evaluate(NPObject* npObject, const String& scriptString, NPVariant* result) 248{ 249 return controller()->evaluate(npObject, scriptString, result, allowPopups()); 250} 251 252bool NetscapePlugin::isPrivateBrowsingEnabled() 253{ 254 return controller()->isPrivateBrowsingEnabled(); 255} 256 257NPObject* NetscapePlugin::windowScriptNPObject() 258{ 259 return controller()->windowScriptNPObject(); 260} 261 262NPObject* NetscapePlugin::pluginElementNPObject() 263{ 264 return controller()->pluginElementNPObject(); 265} 266 267void NetscapePlugin::cancelStreamLoad(NetscapePluginStream* pluginStream) 268{ 269 if (pluginStream == m_manualStream) { 270 controller()->cancelManualStreamLoad(); 271 return; 272 } 273 274 // Ask the plug-in controller to cancel this stream load. 275 controller()->cancelStreamLoad(pluginStream->streamID()); 276} 277 278void NetscapePlugin::removePluginStream(NetscapePluginStream* pluginStream) 279{ 280 if (pluginStream == m_manualStream) { 281 m_manualStream = 0; 282 return; 283 } 284 285 ASSERT(m_streams.get(pluginStream->streamID()) == pluginStream); 286 m_streams.remove(pluginStream->streamID()); 287} 288 289bool NetscapePlugin::isAcceleratedCompositingEnabled() 290{ 291 return controller()->isAcceleratedCompositingEnabled(); 292} 293 294void NetscapePlugin::pushPopupsEnabledState(bool state) 295{ 296 m_popupEnabledStates.append(state); 297} 298 299void NetscapePlugin::popPopupsEnabledState() 300{ 301 ASSERT(!m_popupEnabledStates.isEmpty()); 302 303 m_popupEnabledStates.removeLast(); 304} 305 306void NetscapePlugin::pluginThreadAsyncCall(void (*function)(void*), void* userData) 307{ 308 RefPtr<NetscapePlugin> plugin(this); 309 RunLoop::main().dispatch([plugin, function, userData] { 310 if (!plugin->m_isStarted) 311 return; 312 313 function(userData); 314 }); 315} 316 317NetscapePlugin::Timer::Timer(NetscapePlugin* netscapePlugin, unsigned timerID, unsigned interval, bool repeat, TimerFunc timerFunc) 318 : m_netscapePlugin(netscapePlugin) 319 , m_timerID(timerID) 320 , m_interval(interval) 321 , m_repeat(repeat) 322 , m_timerFunc(timerFunc) 323 , m_timer(RunLoop::main(), this, &Timer::timerFired) 324{ 325} 326 327NetscapePlugin::Timer::~Timer() 328{ 329} 330 331void NetscapePlugin::Timer::start() 332{ 333 double timeInterval = m_interval / 1000.0; 334 335 if (m_repeat) 336 m_timer.startRepeating(timeInterval); 337 else 338 m_timer.startOneShot(timeInterval); 339} 340 341void NetscapePlugin::Timer::stop() 342{ 343 m_timer.stop(); 344} 345 346void NetscapePlugin::Timer::timerFired() 347{ 348 m_timerFunc(&m_netscapePlugin->m_npp, m_timerID); 349 350 if (!m_repeat) 351 m_netscapePlugin->unscheduleTimer(m_timerID); 352} 353 354uint32_t NetscapePlugin::scheduleTimer(unsigned interval, bool repeat, void (*timerFunc)(NPP, unsigned timerID)) 355{ 356 if (!timerFunc) 357 return 0; 358 359 // FIXME: Handle wrapping around. 360 unsigned timerID = ++m_nextTimerID; 361 362 auto timer = std::make_unique<Timer>(this, timerID, interval, repeat, timerFunc); 363 364 // FIXME: Based on the plug-in visibility, figure out if we should throttle the timer, or if we should start it at all. 365 timer->start(); 366 m_timers.set(timerID, WTF::move(timer)); 367 368 return timerID; 369} 370 371void NetscapePlugin::unscheduleTimer(unsigned timerID) 372{ 373 if (auto timer = m_timers.take(timerID)) 374 timer->stop(); 375} 376 377double NetscapePlugin::contentsScaleFactor() 378{ 379 return controller()->contentsScaleFactor(); 380} 381 382String NetscapePlugin::proxiesForURL(const String& urlString) 383{ 384 return controller()->proxiesForURL(urlString); 385} 386 387String NetscapePlugin::cookiesForURL(const String& urlString) 388{ 389 return controller()->cookiesForURL(urlString); 390} 391 392void NetscapePlugin::setCookiesForURL(const String& urlString, const String& cookieString) 393{ 394 controller()->setCookiesForURL(urlString, cookieString); 395} 396 397bool NetscapePlugin::getAuthenticationInfo(const ProtectionSpace& protectionSpace, String& username, String& password) 398{ 399 return controller()->getAuthenticationInfo(protectionSpace, username, password); 400} 401 402NPError NetscapePlugin::NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* savedData) 403{ 404 return m_pluginModule->pluginFuncs().newp(pluginType, &m_npp, mode, argc, argn, argv, savedData); 405} 406 407NPError NetscapePlugin::NPP_Destroy(NPSavedData** savedData) 408{ 409 return m_pluginModule->pluginFuncs().destroy(&m_npp, savedData); 410} 411 412NPError NetscapePlugin::NPP_SetWindow(NPWindow* npWindow) 413{ 414 return m_pluginModule->pluginFuncs().setwindow(&m_npp, npWindow); 415} 416 417NPError NetscapePlugin::NPP_NewStream(NPMIMEType mimeType, NPStream* stream, NPBool seekable, uint16_t* streamType) 418{ 419 return m_pluginModule->pluginFuncs().newstream(&m_npp, mimeType, stream, seekable, streamType); 420} 421 422NPError NetscapePlugin::NPP_DestroyStream(NPStream* stream, NPReason reason) 423{ 424 return m_pluginModule->pluginFuncs().destroystream(&m_npp, stream, reason); 425} 426 427void NetscapePlugin::NPP_StreamAsFile(NPStream* stream, const char* filename) 428{ 429 return m_pluginModule->pluginFuncs().asfile(&m_npp, stream, filename); 430} 431 432int32_t NetscapePlugin::NPP_WriteReady(NPStream* stream) 433{ 434 return m_pluginModule->pluginFuncs().writeready(&m_npp, stream); 435} 436 437int32_t NetscapePlugin::NPP_Write(NPStream* stream, int32_t offset, int32_t len, void* buffer) 438{ 439 return m_pluginModule->pluginFuncs().write(&m_npp, stream, offset, len, buffer); 440} 441 442int16_t NetscapePlugin::NPP_HandleEvent(void* event) 443{ 444 return m_pluginModule->pluginFuncs().event(&m_npp, event); 445} 446 447void NetscapePlugin::NPP_URLNotify(const char* url, NPReason reason, void* notifyData) 448{ 449 m_pluginModule->pluginFuncs().urlnotify(&m_npp, url, reason, notifyData); 450} 451 452NPError NetscapePlugin::NPP_GetValue(NPPVariable variable, void *value) 453{ 454 if (!m_pluginModule->pluginFuncs().getvalue) 455 return NPERR_GENERIC_ERROR; 456 457 return m_pluginModule->pluginFuncs().getvalue(&m_npp, variable, value); 458} 459 460NPError NetscapePlugin::NPP_SetValue(NPNVariable variable, void *value) 461{ 462 if (!m_pluginModule->pluginFuncs().setvalue) 463 return NPERR_GENERIC_ERROR; 464 465 return m_pluginModule->pluginFuncs().setvalue(&m_npp, variable, value); 466} 467 468void NetscapePlugin::callSetWindow() 469{ 470 if (wantsPluginRelativeNPWindowCoordinates()) { 471 m_npWindow.x = 0; 472 m_npWindow.y = 0; 473 m_npWindow.clipRect.top = m_clipRect.y(); 474 m_npWindow.clipRect.left = m_clipRect.x(); 475 } else { 476 IntPoint pluginLocationInRootViewCoordinates = convertToRootView(IntPoint()); 477 IntPoint clipRectInRootViewCoordinates = convertToRootView(m_clipRect.location()); 478 479 m_npWindow.x = pluginLocationInRootViewCoordinates.x(); 480 m_npWindow.y = pluginLocationInRootViewCoordinates.y(); 481 m_npWindow.clipRect.top = clipRectInRootViewCoordinates.y(); 482 m_npWindow.clipRect.left = clipRectInRootViewCoordinates.x(); 483 } 484 485 m_npWindow.width = m_pluginSize.width(); 486 m_npWindow.height = m_pluginSize.height(); 487 m_npWindow.clipRect.right = m_npWindow.clipRect.left + m_clipRect.width(); 488 m_npWindow.clipRect.bottom = m_npWindow.clipRect.top + m_clipRect.height(); 489 490 NPP_SetWindow(&m_npWindow); 491 m_hasCalledSetWindow = true; 492} 493 494void NetscapePlugin::callSetWindowInvisible() 495{ 496 NPWindow invisibleWindow = m_npWindow; 497 498 invisibleWindow.window = 0; 499 invisibleWindow.clipRect.top = 0; 500 invisibleWindow.clipRect.left = 0; 501 invisibleWindow.clipRect.bottom = 0; 502 invisibleWindow.clipRect.right = 0; 503 504 NPP_SetWindow(&invisibleWindow); 505 m_hasCalledSetWindow = true; 506} 507 508bool NetscapePlugin::shouldLoadSrcURL() 509{ 510 // Check if we should cancel the load 511 NPBool cancelSrcStream = false; 512 513 if (NPP_GetValue(NPPVpluginCancelSrcStream, &cancelSrcStream) != NPERR_NO_ERROR) 514 return true; 515 516 return !cancelSrcStream; 517} 518 519NetscapePluginStream* NetscapePlugin::streamFromID(uint64_t streamID) 520{ 521 return m_streams.get(streamID); 522} 523 524void NetscapePlugin::stopAllStreams() 525{ 526 Vector<RefPtr<NetscapePluginStream>> streams; 527 copyValuesToVector(m_streams, streams); 528 529 for (size_t i = 0; i < streams.size(); ++i) 530 streams[i]->stop(NPRES_USER_BREAK); 531} 532 533bool NetscapePlugin::allowPopups() const 534{ 535 if (m_pluginModule->pluginFuncs().version >= NPVERS_HAS_POPUPS_ENABLED_STATE) { 536 if (!m_popupEnabledStates.isEmpty()) 537 return m_popupEnabledStates.last(); 538 } 539 540 // FIXME: Check if the current event is a user gesture. 541 // Really old versions of Flash required this for popups to work, but all newer versions 542 // support NPN_PushPopupEnabledState/NPN_PopPopupEnabledState. 543 return false; 544} 545 546#if PLUGIN_ARCHITECTURE(MAC) 547static bool isTransparentSilverlightBackgroundValue(const String& lowercaseBackgroundValue) 548{ 549 // This checks if the background color value is transparent, according to 550 // the format documented at http://msdn.microsoft.com/en-us/library/cc838148(VS.95).aspx 551 if (lowercaseBackgroundValue.startsWith('#')) { 552 if (lowercaseBackgroundValue.length() == 5 && lowercaseBackgroundValue[1] != 'f') { 553 // An 8-bit RGB value with alpha transparency, in the form #ARGB. 554 return true; 555 } 556 557 if (lowercaseBackgroundValue.length() == 9 && !(lowercaseBackgroundValue[1] == 'f' && lowercaseBackgroundValue[2] == 'f')) { 558 // A 16-bit RGB value with alpha transparency, in the form #AARRGGBB. 559 return true; 560 } 561 } else if (lowercaseBackgroundValue.startsWith("sc#")) { 562 Vector<String> components; 563 lowercaseBackgroundValue.substring(3).split(",", components); 564 565 // An ScRGB value with alpha transparency, in the form sc#A,R,G,B. 566 if (components.size() == 4) { 567 if (components[0].toDouble() < 1) 568 return true; 569 } 570 } else if (lowercaseBackgroundValue == "transparent") 571 return true; 572 573 // This is an opaque color. 574 return false; 575} 576#endif 577 578bool NetscapePlugin::initialize(const Parameters& parameters) 579{ 580 uint16_t mode = parameters.isFullFramePlugin ? NP_FULL : NP_EMBED; 581 582 m_shouldUseManualLoader = parameters.shouldUseManualLoader; 583 584 CString mimeTypeCString = parameters.mimeType.utf8(); 585 586 ASSERT(parameters.names.size() == parameters.values.size()); 587 588 Vector<CString> paramNames; 589 Vector<CString> paramValues; 590 for (size_t i = 0; i < parameters.names.size(); ++i) { 591 String parameterName = parameters.names[i]; 592 593#if PLUGIN_ARCHITECTURE(MAC) 594 if (m_pluginModule->pluginQuirks().contains(PluginQuirks::WantsLowercaseParameterNames)) 595 parameterName = parameterName.lower(); 596#endif 597 598 paramNames.append(parameterName.utf8()); 599 paramValues.append(parameters.values[i].utf8()); 600 } 601 602#if PLUGIN_ARCHITECTURE(X11) 603 if (equalIgnoringCase(parameters.mimeType, "application/x-shockwave-flash")) { 604 size_t wmodeIndex = parameters.names.find("wmode"); 605 if (wmodeIndex != notFound) { 606 // Transparent window mode is not supported by X11 backend. 607 if (equalIgnoringCase(parameters.values[wmodeIndex], "transparent") 608 || (m_pluginModule->pluginQuirks().contains(PluginQuirks::ForceFlashWindowlessMode) && equalIgnoringCase(parameters.values[wmodeIndex], "window"))) 609 paramValues[wmodeIndex] = "opaque"; 610 } else if (m_pluginModule->pluginQuirks().contains(PluginQuirks::ForceFlashWindowlessMode)) { 611 paramNames.append("wmode"); 612 paramValues.append("opaque"); 613 } 614 } else if (equalIgnoringCase(parameters.mimeType, "application/x-webkit-test-netscape")) { 615 paramNames.append("windowedPlugin"); 616 paramValues.append("false"); 617 } 618#endif 619 620 // The strings that these pointers point to are kept alive by paramNames and paramValues. 621 Vector<const char*> names; 622 Vector<const char*> values; 623 for (size_t i = 0; i < paramNames.size(); ++i) { 624 names.append(paramNames[i].data()); 625 values.append(paramValues[i].data()); 626 } 627 628#if PLUGIN_ARCHITECTURE(MAC) 629 if (m_pluginModule->pluginQuirks().contains(PluginQuirks::MakeOpaqueUnlessTransparentSilverlightBackgroundAttributeExists)) { 630 for (size_t i = 0; i < parameters.names.size(); ++i) { 631 if (equalIgnoringCase(parameters.names[i], "background")) { 632 setIsTransparent(isTransparentSilverlightBackgroundValue(parameters.values[i].lower())); 633 break; 634 } 635 } 636 } 637 638 m_layerHostingMode = parameters.layerHostingMode; 639#endif 640 641 platformPreInitialize(); 642 643 NetscapePlugin* previousNPPNewPlugin = currentNPPNewPlugin; 644 645 m_inNPPNew = true; 646 currentNPPNewPlugin = this; 647 648 NPError error = NPP_New(const_cast<char*>(mimeTypeCString.data()), mode, names.size(), 649 const_cast<char**>(names.data()), const_cast<char**>(values.data()), 0); 650 651 m_inNPPNew = false; 652 currentNPPNewPlugin = previousNPPNewPlugin; 653 654 if (error != NPERR_NO_ERROR) 655 return false; 656 657 m_isStarted = true; 658 659 // FIXME: This is not correct in all cases. 660 m_npWindow.type = NPWindowTypeDrawable; 661 662 if (!platformPostInitialize()) { 663 destroy(); 664 return false; 665 } 666 667 // Load the src URL if needed. 668 if (!parameters.shouldUseManualLoader && !parameters.url.isEmpty() && shouldLoadSrcURL()) 669 loadURL("GET", parameters.url.string(), String(), HTTPHeaderMap(), Vector<uint8_t>(), false, 0); 670 671 return true; 672} 673 674void NetscapePlugin::destroy() 675{ 676 ASSERT(m_isStarted); 677 678 // Stop all streams. 679 stopAllStreams(); 680 681#if !PLUGIN_ARCHITECTURE(MAC) && !PLUGIN_ARCHITECTURE(X11) 682 m_npWindow.window = 0; 683 callSetWindow(); 684#endif 685 686 NPP_Destroy(0); 687 688 m_isStarted = false; 689 690 platformDestroy(); 691 692 m_timers.clear(); 693} 694 695void NetscapePlugin::paint(GraphicsContext* context, const IntRect& dirtyRect) 696{ 697 ASSERT(m_isStarted); 698 699 platformPaint(context, dirtyRect); 700} 701 702PassRefPtr<ShareableBitmap> NetscapePlugin::snapshot() 703{ 704 if (!supportsSnapshotting() || m_pluginSize.isEmpty()) 705 return 0; 706 707 ASSERT(m_isStarted); 708 709 IntSize backingStoreSize = m_pluginSize; 710 backingStoreSize.scale(contentsScaleFactor()); 711 712 RefPtr<ShareableBitmap> bitmap = ShareableBitmap::createShareable(backingStoreSize, ShareableBitmap::SupportsAlpha); 713 auto context = bitmap->createGraphicsContext(); 714 715 // FIXME: We should really call applyDeviceScaleFactor instead of scale, but that ends up calling into WKSI 716 // which we currently don't have initiated in the plug-in process. 717 context->scale(FloatSize(contentsScaleFactor(), contentsScaleFactor())); 718 719 platformPaint(context.get(), IntRect(IntPoint(), m_pluginSize), true); 720 721 return bitmap.release(); 722} 723 724bool NetscapePlugin::isTransparent() 725{ 726 return m_isTransparent; 727} 728 729bool NetscapePlugin::wantsWheelEvents() 730{ 731 return m_pluginModule->pluginQuirks().contains(PluginQuirks::WantsWheelEvents); 732} 733 734void NetscapePlugin::geometryDidChange(const IntSize& pluginSize, const IntRect& clipRect, const AffineTransform& pluginToRootViewTransform) 735{ 736 ASSERT(m_isStarted); 737 738 if (pluginSize == m_pluginSize && m_clipRect == clipRect && m_pluginToRootViewTransform == pluginToRootViewTransform) { 739 // Nothing to do. 740 return; 741 } 742 743 bool shouldCallSetWindow = true; 744 745 // If the plug-in doesn't want window relative coordinates, we don't need to call setWindow unless its size or clip rect changes. 746 if (m_hasCalledSetWindow && wantsPluginRelativeNPWindowCoordinates() && m_pluginSize == pluginSize && m_clipRect == clipRect) 747 shouldCallSetWindow = false; 748 749 m_pluginSize = pluginSize; 750 m_clipRect = clipRect; 751 m_pluginToRootViewTransform = pluginToRootViewTransform; 752 753 IntPoint frameRectLocationInWindowCoordinates = m_pluginToRootViewTransform.mapPoint(IntPoint()); 754 m_frameRectInWindowCoordinates = IntRect(frameRectLocationInWindowCoordinates, m_pluginSize); 755 756 platformGeometryDidChange(); 757 758 if (!shouldCallSetWindow) 759 return; 760 761 callSetWindow(); 762} 763 764void NetscapePlugin::visibilityDidChange(bool isVisible) 765{ 766 ASSERT(m_isStarted); 767 768 if (m_isVisible == isVisible) 769 return; 770 771 m_isVisible = isVisible; 772 platformVisibilityDidChange(); 773} 774 775void NetscapePlugin::frameDidFinishLoading(uint64_t requestID) 776{ 777 ASSERT(m_isStarted); 778 779 auto notification = m_pendingURLNotifications.take(requestID); 780 if (notification.first.isEmpty()) 781 return; 782 783 NPP_URLNotify(notification.first.utf8().data(), NPRES_DONE, notification.second); 784} 785 786void NetscapePlugin::frameDidFail(uint64_t requestID, bool wasCancelled) 787{ 788 ASSERT(m_isStarted); 789 790 auto notification = m_pendingURLNotifications.take(requestID); 791 if (notification.first.isNull()) 792 return; 793 794 NPP_URLNotify(notification.first.utf8().data(), wasCancelled ? NPRES_USER_BREAK : NPRES_NETWORK_ERR, notification.second); 795} 796 797void NetscapePlugin::didEvaluateJavaScript(uint64_t requestID, const String& result) 798{ 799 ASSERT(m_isStarted); 800 801 if (NetscapePluginStream* pluginStream = streamFromID(requestID)) 802 pluginStream->sendJavaScriptStream(result); 803} 804 805void NetscapePlugin::streamDidReceiveResponse(uint64_t streamID, const URL& responseURL, uint32_t streamLength, 806 uint32_t lastModifiedTime, const String& mimeType, const String& headers, const String& /* suggestedFileName */) 807{ 808 ASSERT(m_isStarted); 809 810 if (NetscapePluginStream* pluginStream = streamFromID(streamID)) 811 pluginStream->didReceiveResponse(responseURL, streamLength, lastModifiedTime, mimeType, headers); 812} 813 814void NetscapePlugin::streamDidReceiveData(uint64_t streamID, const char* bytes, int length) 815{ 816 ASSERT(m_isStarted); 817 818 if (NetscapePluginStream* pluginStream = streamFromID(streamID)) 819 pluginStream->didReceiveData(bytes, length); 820} 821 822void NetscapePlugin::streamDidFinishLoading(uint64_t streamID) 823{ 824 ASSERT(m_isStarted); 825 826 if (NetscapePluginStream* pluginStream = streamFromID(streamID)) 827 pluginStream->didFinishLoading(); 828} 829 830void NetscapePlugin::streamDidFail(uint64_t streamID, bool wasCancelled) 831{ 832 ASSERT(m_isStarted); 833 834 if (NetscapePluginStream* pluginStream = streamFromID(streamID)) 835 pluginStream->didFail(wasCancelled); 836} 837 838void NetscapePlugin::manualStreamDidReceiveResponse(const URL& responseURL, uint32_t streamLength, uint32_t lastModifiedTime, 839 const String& mimeType, const String& headers, const String& /* suggestedFileName */) 840{ 841 ASSERT(m_isStarted); 842 ASSERT(m_shouldUseManualLoader); 843 ASSERT(!m_manualStream); 844 845 m_manualStream = NetscapePluginStream::create(this, 0, responseURL.string(), false, 0); 846 m_manualStream->didReceiveResponse(responseURL, streamLength, lastModifiedTime, mimeType, headers); 847} 848 849void NetscapePlugin::manualStreamDidReceiveData(const char* bytes, int length) 850{ 851 ASSERT(m_isStarted); 852 ASSERT(m_shouldUseManualLoader); 853 ASSERT(m_manualStream); 854 855 m_manualStream->didReceiveData(bytes, length); 856} 857 858void NetscapePlugin::manualStreamDidFinishLoading() 859{ 860 ASSERT(m_isStarted); 861 ASSERT(m_shouldUseManualLoader); 862 ASSERT(m_manualStream); 863 864 m_manualStream->didFinishLoading(); 865} 866 867void NetscapePlugin::manualStreamDidFail(bool wasCancelled) 868{ 869 ASSERT(m_isStarted); 870 ASSERT(m_shouldUseManualLoader); 871 872 if (!m_manualStream) 873 return; 874 m_manualStream->didFail(wasCancelled); 875} 876 877bool NetscapePlugin::handleMouseEvent(const WebMouseEvent& mouseEvent) 878{ 879 ASSERT(m_isStarted); 880 881 return platformHandleMouseEvent(mouseEvent); 882} 883 884bool NetscapePlugin::handleWheelEvent(const WebWheelEvent& wheelEvent) 885{ 886 ASSERT(m_isStarted); 887 888 return platformHandleWheelEvent(wheelEvent); 889} 890 891bool NetscapePlugin::handleMouseEnterEvent(const WebMouseEvent& mouseEvent) 892{ 893 ASSERT(m_isStarted); 894 895 return platformHandleMouseEnterEvent(mouseEvent); 896} 897 898bool NetscapePlugin::handleMouseLeaveEvent(const WebMouseEvent& mouseEvent) 899{ 900 ASSERT(m_isStarted); 901 902 return platformHandleMouseLeaveEvent(mouseEvent); 903} 904 905bool NetscapePlugin::handleContextMenuEvent(const WebMouseEvent&) 906{ 907 // We don't know if the plug-in has handled mousedown event by displaying a context menu, so we never want WebKit to show a default one. 908 return true; 909} 910 911bool NetscapePlugin::handleKeyboardEvent(const WebKeyboardEvent& keyboardEvent) 912{ 913 ASSERT(m_isStarted); 914 915 return platformHandleKeyboardEvent(keyboardEvent); 916} 917 918bool NetscapePlugin::handleEditingCommand(const String& /* commandName */, const String& /* argument */) 919{ 920 return false; 921} 922 923bool NetscapePlugin::isEditingCommandEnabled(const String& /* commandName */) 924{ 925 return false; 926} 927 928bool NetscapePlugin::shouldAllowScripting() 929{ 930 return true; 931} 932 933bool NetscapePlugin::shouldAllowNavigationFromDrags() 934{ 935 return false; 936} 937 938bool NetscapePlugin::handlesPageScaleFactor() 939{ 940 return false; 941} 942 943void NetscapePlugin::setFocus(bool hasFocus) 944{ 945 ASSERT(m_isStarted); 946 947 platformSetFocus(hasFocus); 948} 949 950NPObject* NetscapePlugin::pluginScriptableNPObject() 951{ 952 ASSERT(m_isStarted); 953 NPObject* scriptableNPObject = 0; 954 955 if (NPP_GetValue(NPPVpluginScriptableNPObject, &scriptableNPObject) != NPERR_NO_ERROR) 956 return 0; 957 958#if PLUGIN_ARCHITECTURE(MAC) 959 if (m_pluginModule->pluginQuirks().contains(PluginQuirks::ReturnsNonRetainedScriptableNPObject)) 960 retainNPObject(scriptableNPObject); 961#endif 962 963 return scriptableNPObject; 964} 965 966unsigned NetscapePlugin::countFindMatches(const String&, WebCore::FindOptions, unsigned) 967{ 968 return 0; 969} 970 971bool NetscapePlugin::findString(const String&, WebCore::FindOptions, unsigned) 972{ 973 return false; 974} 975 976void NetscapePlugin::contentsScaleFactorChanged(float scaleFactor) 977{ 978 ASSERT(m_isStarted); 979 980#if PLUGIN_ARCHITECTURE(MAC) 981 double contentsScaleFactor = scaleFactor; 982 NPP_SetValue(NPNVcontentsScaleFactor, &contentsScaleFactor); 983#else 984 UNUSED_PARAM(scaleFactor); 985#endif 986} 987 988void NetscapePlugin::storageBlockingStateChanged(bool storageBlockingEnabled) 989{ 990 if (m_storageBlockingState != storageBlockingEnabled) { 991 m_storageBlockingState = storageBlockingEnabled; 992 updateNPNPrivateMode(); 993 } 994} 995 996void NetscapePlugin::privateBrowsingStateChanged(bool privateBrowsingEnabled) 997{ 998 if (m_privateBrowsingState != privateBrowsingEnabled) { 999 m_privateBrowsingState = privateBrowsingEnabled; 1000 updateNPNPrivateMode(); 1001 } 1002} 1003 1004void NetscapePlugin::updateNPNPrivateMode() 1005{ 1006 ASSERT(m_isStarted); 1007 1008 // From https://wiki.mozilla.org/Plugins:PrivateMode 1009 // When the browser turns private mode on or off it will call NPP_SetValue for "NPNVprivateModeBool" 1010 // (assigned enum value 18) with a pointer to an NPBool value on all applicable instances. 1011 // Plugins should check the boolean value pointed to, not the pointer itself. 1012 // The value will be true when private mode is on. 1013 NPBool value = m_privateBrowsingState || m_storageBlockingState; 1014 NPP_SetValue(NPNVprivateModeBool, &value); 1015} 1016 1017bool NetscapePlugin::getFormValue(String& formValue) 1018{ 1019 ASSERT(m_isStarted); 1020 1021 char* formValueString = 0; 1022 if (NPP_GetValue(NPPVformValue, &formValueString) != NPERR_NO_ERROR) 1023 return false; 1024 1025 formValue = String::fromUTF8(formValueString); 1026 1027 // The plug-in allocates the form value string with NPN_MemAlloc so it needs to be freed with NPN_MemFree. 1028 npnMemFree(formValueString); 1029 return true; 1030} 1031 1032bool NetscapePlugin::handleScroll(ScrollDirection, ScrollGranularity) 1033{ 1034 return false; 1035} 1036 1037Scrollbar* NetscapePlugin::horizontalScrollbar() 1038{ 1039 return 0; 1040} 1041 1042Scrollbar* NetscapePlugin::verticalScrollbar() 1043{ 1044 return 0; 1045} 1046 1047bool NetscapePlugin::supportsSnapshotting() const 1048{ 1049#if PLATFORM(COCOA) 1050 return m_pluginModule && m_pluginModule->pluginQuirks().contains(PluginQuirks::SupportsSnapshotting); 1051#endif 1052 return false; 1053} 1054 1055PassRefPtr<WebCore::SharedBuffer> NetscapePlugin::liveResourceData() const 1056{ 1057 return 0; 1058} 1059 1060IntPoint NetscapePlugin::convertToRootView(const IntPoint& pointInPluginCoordinates) const 1061{ 1062 return m_pluginToRootViewTransform.mapPoint(pointInPluginCoordinates); 1063} 1064 1065bool NetscapePlugin::convertFromRootView(const IntPoint& pointInRootViewCoordinates, IntPoint& pointInPluginCoordinates) 1066{ 1067 if (!m_pluginToRootViewTransform.isInvertible()) 1068 return false; 1069 1070 pointInPluginCoordinates = m_pluginToRootViewTransform.inverse().mapPoint(pointInRootViewCoordinates); 1071 return true; 1072} 1073 1074} // namespace WebKit 1075 1076#endif // ENABLE(NETSCAPE_PLUGIN_API) 1077