[Mac] Should be able to scroll embedded PDFs using mouse
[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 #include "NPRuntimeObjectMap.h"
30 #include "NPRuntimeUtilities.h"
31 #include "NetscapePluginStream.h"
32 #include "PluginController.h"
33 #include "ShareableBitmap.h"
34 #include "WorkItem.h"
35 #include <WebCore/GraphicsContext.h>
36 #include <WebCore/HTTPHeaderMap.h>
37 #include <WebCore/IntRect.h>
38 #include <WebCore/KURL.h>
39 #include <utility>
40 #include <wtf/text/CString.h>
41
42 using namespace WebCore;
43 using namespace std;
44
45 namespace WebKit {
46
47 // The plug-in that we're currently calling NPP_New for.
48 static NetscapePlugin* currentNPPNewPlugin;
49
50 PassRefPtr<NetscapePlugin> NetscapePlugin::create(PassRefPtr<NetscapePluginModule> pluginModule)
51 {
52     if (!pluginModule)
53         return 0;
54
55     return adoptRef(new NetscapePlugin(pluginModule));
56 }
57     
58 NetscapePlugin::NetscapePlugin(PassRefPtr<NetscapePluginModule> pluginModule)
59     : m_nextRequestID(0)
60     , m_pluginModule(pluginModule)
61     , m_npWindow()
62     , m_isStarted(false)
63 #if PLATFORM(MAC)
64     , m_isWindowed(false)
65 #else
66     , m_isWindowed(true)
67 #endif
68     , m_isTransparent(false)
69     , m_inNPPNew(false)
70     , m_loadManually(false)
71     , m_nextTimerID(0)
72 #if PLATFORM(MAC)
73     , m_drawingModel(static_cast<NPDrawingModel>(-1))
74     , m_eventModel(static_cast<NPEventModel>(-1))
75     , m_pluginReturnsNonretainedLayer(!m_pluginModule->pluginQuirks().contains(PluginQuirks::ReturnsRetainedCoreAnimationLayer))
76     , m_currentMouseEvent(0)
77     , m_pluginHasFocus(false)
78     , m_windowHasFocus(false)
79     , m_pluginWantsLegacyCocoaTextInput(true)
80     , m_isComplexTextInputEnabled(false)
81     , m_hasHandledAKeyDownEvent(false)
82     , m_ignoreNextKeyUpEventCounter(0)
83 #ifndef NP_NO_CARBON
84     , m_nullEventTimer(RunLoop::main(), this, &NetscapePlugin::nullEventTimerFired)
85     , m_npCGContext()
86 #endif
87 #elif PLUGIN_ARCHITECTURE(X11)
88     , m_drawable(0)
89     , m_pluginDisplay(0)
90 #endif
91 {
92     m_npp.ndata = this;
93     m_npp.pdata = 0;
94     
95     m_pluginModule->incrementLoadCount();
96 }
97
98 NetscapePlugin::~NetscapePlugin()
99 {
100     ASSERT(!m_isStarted);
101     ASSERT(m_timers.isEmpty());
102
103     m_pluginModule->decrementLoadCount();
104 }
105
106 PassRefPtr<NetscapePlugin> NetscapePlugin::fromNPP(NPP npp)
107 {
108     if (npp)
109         return static_cast<NetscapePlugin*>(npp->ndata);
110
111     // FIXME: Return the current NetscapePlugin here.
112     ASSERT_NOT_REACHED();
113     return 0;
114 }
115
116 void NetscapePlugin::invalidate(const NPRect* invalidRect)
117 {
118     IntRect rect;
119     
120     if (!invalidRect)
121         rect = IntRect(0, 0, m_frameRect.width(), m_frameRect.height());
122     else
123         rect = IntRect(invalidRect->left, invalidRect->top,
124                        invalidRect->right - invalidRect->left, invalidRect->bottom - invalidRect->top);
125     
126     if (platformInvalidate(rect))
127         return;
128
129     controller()->invalidate(rect);
130 }
131
132 const char* NetscapePlugin::userAgent(NPP npp)
133 {
134     if (npp)
135         return fromNPP(npp)->userAgent();
136
137     if (currentNPPNewPlugin)
138         return currentNPPNewPlugin->userAgent();
139
140     return 0;
141 }
142
143 const char* NetscapePlugin::userAgent()
144 {
145 #if PLUGIN_ARCHITECTURE(WIN)
146     static const char* MozillaUserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0";
147     
148     if (quirks().contains(PluginQuirks::WantsMozillaUserAgent))
149         return MozillaUserAgent;
150 #endif
151
152     if (m_userAgent.isNull()) {
153         String userAgent = controller()->userAgent();
154         ASSERT(!userAgent.isNull());
155
156 #if PLUGIN_ARCHITECTURE(MAC)
157         if (quirks().contains(PluginQuirks::AppendVersion3UserAgent))
158             userAgent += " Version/3.2.1";
159 #endif
160
161         m_userAgent = userAgent.utf8();
162     }
163     return m_userAgent.data();
164 }
165
166 void NetscapePlugin::loadURL(const String& method, const String& urlString, const String& target, const HTTPHeaderMap& headerFields, const Vector<uint8_t>& httpBody,
167                              bool sendNotification, void* notificationData)
168 {
169     uint64_t requestID = ++m_nextRequestID;
170     
171     controller()->loadURL(requestID, method, urlString, target, headerFields, httpBody, allowPopups());
172
173     if (target.isNull()) {
174         // The browser is going to send the data in a stream, create a plug-in stream.
175         RefPtr<NetscapePluginStream> pluginStream = NetscapePluginStream::create(this, requestID, urlString, sendNotification, notificationData);
176         ASSERT(!m_streams.contains(requestID));
177
178         m_streams.set(requestID, pluginStream.release());
179         return;
180     }
181
182     if (sendNotification) {
183         // Eventually we are going to get a frameDidFinishLoading or frameDidFail call for this request.
184         // Keep track of the notification data so we can call NPP_URLNotify.
185         ASSERT(!m_pendingURLNotifications.contains(requestID));
186         m_pendingURLNotifications.set(requestID, make_pair(urlString, notificationData));
187     }
188 }
189
190 NPError NetscapePlugin::destroyStream(NPStream* stream, NPReason reason)
191 {
192     NetscapePluginStream* pluginStream = 0;
193
194     for (StreamsMap::const_iterator it = m_streams.begin(), end = m_streams.end(); it != end; ++it) {
195         if (it->second->npStream() == stream) {
196             pluginStream = it->second.get();
197             break;
198         }
199     }
200
201     if (!pluginStream)
202         return NPERR_INVALID_INSTANCE_ERROR;
203
204     return pluginStream->destroy(reason);
205 }
206
207 void NetscapePlugin::setIsWindowed(bool isWindowed)
208 {
209     // Once the plugin has started, it's too late to change whether the plugin is windowed or not.
210     // (This is true in Firefox and Chrome, too.) Disallow setting m_isWindowed in that case to
211     // keep our internal state consistent.
212     if (m_isStarted)
213         return;
214
215     m_isWindowed = isWindowed;
216 }
217
218 void NetscapePlugin::setIsTransparent(bool isTransparent)
219 {
220     m_isTransparent = isTransparent;
221 }
222
223 void NetscapePlugin::setStatusbarText(const String& statusbarText)
224 {
225     controller()->setStatusbarText(statusbarText);
226 }
227
228 static void (*setExceptionFunction)(const String&);
229
230 void NetscapePlugin::setSetExceptionFunction(void (*function)(const String&))
231 {
232     ASSERT(!setExceptionFunction || setExceptionFunction == function);
233     setExceptionFunction = function;
234 }
235
236 void NetscapePlugin::setException(const String& exceptionString)
237 {
238     ASSERT(setExceptionFunction);
239     setExceptionFunction(exceptionString);
240 }
241
242 bool NetscapePlugin::evaluate(NPObject* npObject, const String& scriptString, NPVariant* result)
243 {
244     return controller()->evaluate(npObject, scriptString, result, allowPopups());
245 }
246
247 bool NetscapePlugin::isPrivateBrowsingEnabled()
248 {
249     return controller()->isPrivateBrowsingEnabled();
250 }
251
252 NPObject* NetscapePlugin::windowScriptNPObject()
253 {
254     return controller()->windowScriptNPObject();
255 }
256
257 NPObject* NetscapePlugin::pluginElementNPObject()
258 {
259     return controller()->pluginElementNPObject();
260 }
261
262 bool NetscapePlugin::tryToShortCircuitInvoke(NPObject* npObject, NPIdentifier methodName, const NPVariant* arguments, uint32_t argumentCount, bool& returnValue, NPVariant& result)
263 {
264     return controller()->tryToShortCircuitInvoke(npObject, methodName, arguments, argumentCount, returnValue, result);
265 }
266
267 void 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
278 void 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
289 bool NetscapePlugin::isAcceleratedCompositingEnabled()
290 {
291 #if USE(ACCELERATED_COMPOSITING)
292     return controller()->isAcceleratedCompositingEnabled();
293 #else
294     return false;
295 #endif
296 }
297
298 void NetscapePlugin::pushPopupsEnabledState(bool state)
299 {
300     m_popupEnabledStates.append(state);
301 }
302  
303 void NetscapePlugin::popPopupsEnabledState()
304 {
305     ASSERT(!m_popupEnabledStates.isEmpty());
306
307     m_popupEnabledStates.removeLast();
308 }
309
310 void NetscapePlugin::pluginThreadAsyncCall(void (*function)(void*), void* userData)
311 {
312     RunLoop::main()->scheduleWork(WorkItem::create(this, &NetscapePlugin::handlePluginThreadAsyncCall, function, userData));
313 }
314     
315 void NetscapePlugin::handlePluginThreadAsyncCall(void (*function)(void*), void* userData)
316 {
317     if (!m_isStarted)
318         return;
319
320     function(userData);
321 }
322
323 PassOwnPtr<NetscapePlugin::Timer> NetscapePlugin::Timer::create(NetscapePlugin* netscapePlugin, unsigned timerID, unsigned interval, bool repeat, TimerFunc timerFunc)
324 {
325     return adoptPtr(new Timer(netscapePlugin, timerID, interval, repeat, timerFunc));
326 }
327
328 NetscapePlugin::Timer::Timer(NetscapePlugin* netscapePlugin, unsigned timerID, unsigned interval, bool repeat, TimerFunc timerFunc)
329     : m_netscapePlugin(netscapePlugin)
330     , m_timerID(timerID)
331     , m_interval(interval)
332     , m_repeat(repeat)
333     , m_timerFunc(timerFunc)
334     , m_timer(RunLoop::main(), this, &Timer::timerFired)
335 {
336 }
337
338 NetscapePlugin::Timer::~Timer()
339 {
340 }
341
342 void NetscapePlugin::Timer::start()
343 {
344     double timeInterval = m_interval / 1000.0;
345
346     if (m_repeat)
347         m_timer.startRepeating(timeInterval);
348     else
349         m_timer.startOneShot(timeInterval);
350 }
351
352 void NetscapePlugin::Timer::stop()
353 {
354     m_timer.stop();
355 }
356
357 void NetscapePlugin::Timer::timerFired()
358 {
359     m_timerFunc(&m_netscapePlugin->m_npp, m_timerID);
360
361     if (!m_repeat)
362         m_netscapePlugin->unscheduleTimer(m_timerID);
363 }
364
365 uint32_t NetscapePlugin::scheduleTimer(unsigned interval, bool repeat, void (*timerFunc)(NPP, unsigned timerID))
366 {
367     if (!timerFunc)
368         return 0;
369
370     // FIXME: Handle wrapping around.
371     unsigned timerID = ++m_nextTimerID;
372
373     OwnPtr<Timer> timer = Timer::create(this, timerID, interval, repeat, timerFunc);
374     
375     // FIXME: Based on the plug-in visibility, figure out if we should throttle the timer, or if we should start it at all.
376     timer->start();
377     m_timers.set(timerID, timer.leakPtr());
378
379     return timerID;
380 }
381
382 void NetscapePlugin::unscheduleTimer(unsigned timerID)
383 {
384     TimerMap::iterator it = m_timers.find(timerID);
385     if (it == m_timers.end())
386         return;
387
388     OwnPtr<Timer> timer = adoptPtr(it->second);
389     m_timers.remove(it);
390
391     timer->stop();
392 }
393
394 String NetscapePlugin::proxiesForURL(const String& urlString)
395 {
396     return controller()->proxiesForURL(urlString);
397 }
398     
399 String NetscapePlugin::cookiesForURL(const String& urlString)
400 {
401     return controller()->cookiesForURL(urlString);
402 }
403
404 void NetscapePlugin::setCookiesForURL(const String& urlString, const String& cookieString)
405 {
406     controller()->setCookiesForURL(urlString, cookieString);
407 }
408
409 bool NetscapePlugin::getAuthenticationInfo(const ProtectionSpace& protectionSpace, String& username, String& password)
410 {
411     return controller()->getAuthenticationInfo(protectionSpace, username, password);
412 }
413
414 NPError NetscapePlugin::NPP_New(NPMIMEType pluginType, uint16_t mode, int16_t argc, char* argn[], char* argv[], NPSavedData* savedData)
415 {
416     return m_pluginModule->pluginFuncs().newp(pluginType, &m_npp, mode, argc, argn, argv, savedData);
417 }
418     
419 NPError NetscapePlugin::NPP_Destroy(NPSavedData** savedData)
420 {
421     return m_pluginModule->pluginFuncs().destroy(&m_npp, savedData);
422 }
423
424 NPError NetscapePlugin::NPP_SetWindow(NPWindow* npWindow)
425 {
426     return m_pluginModule->pluginFuncs().setwindow(&m_npp, npWindow);
427 }
428
429 NPError NetscapePlugin::NPP_NewStream(NPMIMEType mimeType, NPStream* stream, NPBool seekable, uint16_t* streamType)
430 {
431     return m_pluginModule->pluginFuncs().newstream(&m_npp, mimeType, stream, seekable, streamType);
432 }
433
434 NPError NetscapePlugin::NPP_DestroyStream(NPStream* stream, NPReason reason)
435 {
436     return m_pluginModule->pluginFuncs().destroystream(&m_npp, stream, reason);
437 }
438
439 void NetscapePlugin::NPP_StreamAsFile(NPStream* stream, const char* filename)
440 {
441     return m_pluginModule->pluginFuncs().asfile(&m_npp, stream, filename);
442 }
443
444 int32_t NetscapePlugin::NPP_WriteReady(NPStream* stream)
445 {
446     return m_pluginModule->pluginFuncs().writeready(&m_npp, stream);
447 }
448
449 int32_t NetscapePlugin::NPP_Write(NPStream* stream, int32_t offset, int32_t len, void* buffer)
450 {
451     return m_pluginModule->pluginFuncs().write(&m_npp, stream, offset, len, buffer);
452 }
453
454 int16_t NetscapePlugin::NPP_HandleEvent(void* event)
455 {
456     return m_pluginModule->pluginFuncs().event(&m_npp, event);
457 }
458
459 void NetscapePlugin::NPP_URLNotify(const char* url, NPReason reason, void* notifyData)
460 {
461     m_pluginModule->pluginFuncs().urlnotify(&m_npp, url, reason, notifyData);
462 }
463
464 NPError NetscapePlugin::NPP_GetValue(NPPVariable variable, void *value)
465 {
466     if (!m_pluginModule->pluginFuncs().getvalue)
467         return NPERR_GENERIC_ERROR;
468
469     return m_pluginModule->pluginFuncs().getvalue(&m_npp, variable, value);
470 }
471
472 NPError NetscapePlugin::NPP_SetValue(NPNVariable variable, void *value)
473 {
474     if (!m_pluginModule->pluginFuncs().setvalue)
475         return NPERR_GENERIC_ERROR;
476
477     return m_pluginModule->pluginFuncs().setvalue(&m_npp, variable, value);
478 }
479
480 void NetscapePlugin::callSetWindow()
481 {
482 #if PLUGIN_ARCHITECTURE(X11)
483     // We use a backing store as the painting area for the plugin.
484     m_npWindow.x = 0;
485     m_npWindow.y = 0;
486 #else
487     m_npWindow.x = m_frameRect.x();
488     m_npWindow.y = m_frameRect.y();
489 #endif
490     m_npWindow.width = m_frameRect.width();
491     m_npWindow.height = m_frameRect.height();
492     m_npWindow.clipRect.top = m_clipRect.y();
493     m_npWindow.clipRect.left = m_clipRect.x();
494     m_npWindow.clipRect.bottom = m_clipRect.maxY();
495     m_npWindow.clipRect.right = m_clipRect.maxX();
496
497     NPP_SetWindow(&m_npWindow);
498 }
499
500 bool NetscapePlugin::shouldLoadSrcURL()
501 {
502     // Check if we should cancel the load
503     NPBool cancelSrcStream = false;
504
505     if (NPP_GetValue(NPPVpluginCancelSrcStream, &cancelSrcStream) != NPERR_NO_ERROR)
506         return true;
507
508     return !cancelSrcStream;
509 }
510
511 NetscapePluginStream* NetscapePlugin::streamFromID(uint64_t streamID)
512 {
513     return m_streams.get(streamID).get();
514 }
515
516 void NetscapePlugin::stopAllStreams()
517 {
518     Vector<RefPtr<NetscapePluginStream> > streams;
519     copyValuesToVector(m_streams, streams);
520
521     for (size_t i = 0; i < streams.size(); ++i)
522         streams[i]->stop(NPRES_USER_BREAK);
523 }
524
525 bool NetscapePlugin::allowPopups() const
526 {
527     if (m_pluginModule->pluginFuncs().version >= NPVERS_HAS_POPUPS_ENABLED_STATE) {
528         if (!m_popupEnabledStates.isEmpty())
529             return m_popupEnabledStates.last();
530     }
531
532     // FIXME: Check if the current event is a user gesture.
533     // Really old versions of Flash required this for popups to work, but all newer versions
534     // support NPN_PushPopupEnabledState/NPN_PopPopupEnabledState.
535     return false;
536 }
537
538 bool NetscapePlugin::initialize(const Parameters& parameters)
539 {
540     uint16_t mode = parameters.loadManually ? NP_FULL : NP_EMBED;
541     
542     m_loadManually = parameters.loadManually;
543
544     CString mimeTypeCString = parameters.mimeType.utf8();
545
546     ASSERT(parameters.names.size() == parameters.values.size());
547
548     Vector<CString> paramNames;
549     Vector<CString> paramValues;
550     for (size_t i = 0; i < parameters.names.size(); ++i) {
551         String parameterName = parameters.names[i];
552
553 #if PLUGIN_ARCHITECTURE(MAC)
554         if (m_pluginModule->pluginQuirks().contains(PluginQuirks::WantsLowercaseParameterNames))
555             parameterName = parameterName.lower();
556 #endif
557
558         paramNames.append(parameterName.utf8());
559         paramValues.append(parameters.values[i].utf8());
560     }
561
562     // The strings that these pointers point to are kept alive by paramNames and paramValues.
563     Vector<const char*> names;
564     Vector<const char*> values;
565     for (size_t i = 0; i < paramNames.size(); ++i) {
566         names.append(paramNames[i].data());
567         values.append(paramValues[i].data());
568     }
569
570 #if PLUGIN_ARCHITECTURE(MAC)
571     if (m_pluginModule->pluginQuirks().contains(PluginQuirks::MakeTransparentIfBackgroundAttributeExists)) {
572         for (size_t i = 0; i < parameters.names.size(); ++i) {
573             if (equalIgnoringCase(parameters.names[i], "background")) {
574                 setIsTransparent(true);
575                 break;
576             }
577         }
578     }
579 #endif
580
581     NetscapePlugin* previousNPPNewPlugin = currentNPPNewPlugin;
582     
583     m_inNPPNew = true;
584     currentNPPNewPlugin = this;
585
586     NPError error = NPP_New(const_cast<char*>(mimeTypeCString.data()), mode, names.size(),
587                             const_cast<char**>(names.data()), const_cast<char**>(values.data()), 0);
588
589     m_inNPPNew = false;
590     currentNPPNewPlugin = previousNPPNewPlugin;
591
592     if (error != NPERR_NO_ERROR)
593         return false;
594
595     m_isStarted = true;
596
597     // FIXME: This is not correct in all cases.
598     m_npWindow.type = NPWindowTypeDrawable;
599
600     if (!platformPostInitialize()) {
601         destroy();
602         return false;
603     }
604
605     // Load the src URL if needed.
606     if (!parameters.loadManually && !parameters.url.isEmpty() && shouldLoadSrcURL())
607         loadURL("GET", parameters.url.string(), String(), HTTPHeaderMap(), Vector<uint8_t>(), false, 0);
608     
609     return true;
610 }
611     
612 void NetscapePlugin::destroy()
613 {
614     ASSERT(m_isStarted);
615
616     // Stop all streams.
617     stopAllStreams();
618
619 #if !PLUGIN_ARCHITECTURE(MAC) && !PLUGIN_ARCHITECTURE(X11)
620     m_npWindow.window = 0;
621     callSetWindow();
622 #endif
623
624     NPP_Destroy(0);
625
626     m_isStarted = false;
627
628     platformDestroy();
629
630     deleteAllValues(m_timers);
631     m_timers.clear();
632 }
633     
634 void NetscapePlugin::paint(GraphicsContext* context, const IntRect& dirtyRect)
635 {
636     ASSERT(m_isStarted);
637     
638     platformPaint(context, dirtyRect);
639 }
640
641 PassRefPtr<ShareableBitmap> NetscapePlugin::snapshot()
642 {
643     if (!supportsSnapshotting() || m_frameRect.isEmpty())
644         return 0;
645
646     ASSERT(m_isStarted);
647     
648     RefPtr<ShareableBitmap> bitmap = ShareableBitmap::createShareable(m_frameRect.size(), ShareableBitmap::SupportsAlpha);
649     OwnPtr<GraphicsContext> context = bitmap->createGraphicsContext();
650
651     context->translate(-m_frameRect.x(), -m_frameRect.y());
652
653     platformPaint(context.get(), m_frameRect, true);
654     
655     return bitmap.release();
656 }
657
658 bool NetscapePlugin::isTransparent()
659 {
660     return m_isTransparent;
661 }
662
663 void NetscapePlugin::geometryDidChange(const IntRect& frameRect, const IntRect& clipRect)
664 {
665     ASSERT(m_isStarted);
666
667     if (m_frameRect == frameRect && m_clipRect == clipRect) {
668         // Nothing to do.
669         return;
670     }
671
672     m_frameRect = frameRect;
673     m_clipRect = clipRect;
674
675     platformGeometryDidChange();
676     callSetWindow();
677 }
678
679 void NetscapePlugin::visibilityDidChange()
680 {
681     ASSERT(m_isStarted);
682
683     platformVisibilityDidChange();
684 }
685
686 void NetscapePlugin::frameDidFinishLoading(uint64_t requestID)
687 {
688     ASSERT(m_isStarted);
689     
690     PendingURLNotifyMap::iterator it = m_pendingURLNotifications.find(requestID);
691     if (it == m_pendingURLNotifications.end())
692         return;
693
694     String url = it->second.first;
695     void* notificationData = it->second.second;
696
697     m_pendingURLNotifications.remove(it);
698     
699     NPP_URLNotify(url.utf8().data(), NPRES_DONE, notificationData);
700 }
701
702 void NetscapePlugin::frameDidFail(uint64_t requestID, bool wasCancelled)
703 {
704     ASSERT(m_isStarted);
705     
706     PendingURLNotifyMap::iterator it = m_pendingURLNotifications.find(requestID);
707     if (it == m_pendingURLNotifications.end())
708         return;
709
710     String url = it->second.first;
711     void* notificationData = it->second.second;
712
713     m_pendingURLNotifications.remove(it);
714     
715     NPP_URLNotify(url.utf8().data(), wasCancelled ? NPRES_USER_BREAK : NPRES_NETWORK_ERR, notificationData);
716 }
717
718 void NetscapePlugin::didEvaluateJavaScript(uint64_t requestID, const String& result)
719 {
720     ASSERT(m_isStarted);
721     
722     if (NetscapePluginStream* pluginStream = streamFromID(requestID))
723         pluginStream->sendJavaScriptStream(result);
724 }
725
726 void NetscapePlugin::streamDidReceiveResponse(uint64_t streamID, const KURL& responseURL, uint32_t streamLength, 
727                                               uint32_t lastModifiedTime, const String& mimeType, const String& headers)
728 {
729     ASSERT(m_isStarted);
730     
731     if (NetscapePluginStream* pluginStream = streamFromID(streamID))
732         pluginStream->didReceiveResponse(responseURL, streamLength, lastModifiedTime, mimeType, headers);
733 }
734
735 void NetscapePlugin::streamDidReceiveData(uint64_t streamID, const char* bytes, int length)
736 {
737     ASSERT(m_isStarted);
738     
739     if (NetscapePluginStream* pluginStream = streamFromID(streamID))
740         pluginStream->didReceiveData(bytes, length);
741 }
742
743 void NetscapePlugin::streamDidFinishLoading(uint64_t streamID)
744 {
745     ASSERT(m_isStarted);
746     
747     if (NetscapePluginStream* pluginStream = streamFromID(streamID))
748         pluginStream->didFinishLoading();
749 }
750
751 void NetscapePlugin::streamDidFail(uint64_t streamID, bool wasCancelled)
752 {
753     ASSERT(m_isStarted);
754     
755     if (NetscapePluginStream* pluginStream = streamFromID(streamID))
756         pluginStream->didFail(wasCancelled);
757 }
758
759 void NetscapePlugin::manualStreamDidReceiveResponse(const KURL& responseURL, uint32_t streamLength, uint32_t lastModifiedTime, 
760                                                     const String& mimeType, const String& headers)
761 {
762     ASSERT(m_isStarted);
763     ASSERT(m_loadManually);
764     ASSERT(!m_manualStream);
765     
766     m_manualStream = NetscapePluginStream::create(this, 0, responseURL.string(), false, 0);
767     m_manualStream->didReceiveResponse(responseURL, streamLength, lastModifiedTime, mimeType, headers);
768 }
769
770 void NetscapePlugin::manualStreamDidReceiveData(const char* bytes, int length)
771 {
772     ASSERT(m_isStarted);
773     ASSERT(m_loadManually);
774     ASSERT(m_manualStream);
775
776     m_manualStream->didReceiveData(bytes, length);
777 }
778
779 void NetscapePlugin::manualStreamDidFinishLoading()
780 {
781     ASSERT(m_isStarted);
782     ASSERT(m_loadManually);
783     ASSERT(m_manualStream);
784
785     m_manualStream->didFinishLoading();
786 }
787
788 void NetscapePlugin::manualStreamDidFail(bool wasCancelled)
789 {
790     ASSERT(m_isStarted);
791     ASSERT(m_loadManually);
792     ASSERT(m_manualStream);
793
794     m_manualStream->didFail(wasCancelled);
795 }
796
797 bool NetscapePlugin::handleMouseEvent(const WebMouseEvent& mouseEvent)
798 {
799     ASSERT(m_isStarted);
800     
801     return platformHandleMouseEvent(mouseEvent);
802 }
803     
804 bool NetscapePlugin::handleWheelEvent(const WebWheelEvent& wheelEvent)
805 {
806     ASSERT(m_isStarted);
807
808     return platformHandleWheelEvent(wheelEvent);
809 }
810
811 bool NetscapePlugin::handleMouseEnterEvent(const WebMouseEvent& mouseEvent)
812 {
813     ASSERT(m_isStarted);
814
815     return platformHandleMouseEnterEvent(mouseEvent);
816 }
817
818 bool NetscapePlugin::handleMouseLeaveEvent(const WebMouseEvent& mouseEvent)
819 {
820     ASSERT(m_isStarted);
821
822     return platformHandleMouseLeaveEvent(mouseEvent);
823 }
824
825 bool NetscapePlugin::handleKeyboardEvent(const WebKeyboardEvent& keyboardEvent)
826 {
827     ASSERT(m_isStarted);
828
829     return platformHandleKeyboardEvent(keyboardEvent);
830 }
831
832 void NetscapePlugin::setFocus(bool hasFocus)
833 {
834     ASSERT(m_isStarted);
835
836     platformSetFocus(hasFocus);
837 }
838
839 NPObject* NetscapePlugin::pluginScriptableNPObject()
840 {
841     ASSERT(m_isStarted);
842     NPObject* scriptableNPObject = 0;
843     
844     if (NPP_GetValue(NPPVpluginScriptableNPObject, &scriptableNPObject) != NPERR_NO_ERROR)
845         return 0;
846
847 #if PLUGIN_ARCHITECTURE(MAC)
848     if (m_pluginModule->pluginQuirks().contains(PluginQuirks::ReturnsNonRetainedScriptableNPObject))
849         retainNPObject(scriptableNPObject);        
850 #endif    
851
852     return scriptableNPObject;
853 }
854
855 void NetscapePlugin::privateBrowsingStateChanged(bool privateBrowsingEnabled)
856 {
857     ASSERT(m_isStarted);
858
859     // From https://wiki.mozilla.org/Plugins:PrivateMode
860     //   When the browser turns private mode on or off it will call NPP_SetValue for "NPNVprivateModeBool" 
861     //   (assigned enum value 18) with a pointer to an NPBool value on all applicable instances.
862     //   Plugins should check the boolean value pointed to, not the pointer itself. 
863     //   The value will be true when private mode is on.
864     NPBool value = privateBrowsingEnabled;
865     NPP_SetValue(NPNVprivateModeBool, &value);
866 }
867
868 bool NetscapePlugin::getFormValue(String& formValue)
869 {
870     ASSERT(m_isStarted);
871
872     char* formValueString = 0;
873     if (NPP_GetValue(NPPVformValue, &formValueString) != NPERR_NO_ERROR)
874         return false;
875
876     formValue = String::fromUTF8(formValueString);
877
878     // The plug-in allocates the form value string with NPN_MemAlloc so it needs to be freed with NPN_MemFree.
879     npnMemFree(formValueString);
880     return true;
881 }
882
883 bool NetscapePlugin::handleScroll(ScrollDirection, ScrollGranularity)
884 {
885     return false;
886 }
887
888 Scrollbar* NetscapePlugin::horizontalScrollbar()
889 {
890     return 0;
891 }
892
893 Scrollbar* NetscapePlugin::verticalScrollbar()
894 {
895     return 0;
896 }
897
898 bool NetscapePlugin::supportsSnapshotting() const
899 {
900 #if PLATFORM(MAC)
901     return m_pluginModule && m_pluginModule->pluginQuirks().contains(PluginQuirks::SupportsSnapshotting);
902 #endif
903     return false;
904 }
905
906 } // namespace WebKit