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