[iOS] Software keyboard is shown too frequently on some websites
[WebKit-https.git] / Source / WebKit / PluginProcess / PluginControllerProxy.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 "PluginControllerProxy.h"
28
29 #if ENABLE(NETSCAPE_PLUGIN_API)
30
31 #include "DataReference.h"
32 #include "NPObjectProxy.h"
33 #include "NPRemoteObjectMap.h"
34 #include "NPRuntimeUtilities.h"
35 #include "NPVariantData.h"
36 #include "NetscapePlugin.h"
37 #include "PluginCreationParameters.h"
38 #include "PluginProcess.h"
39 #include "PluginProxyMessages.h"
40 #include "ShareableBitmap.h"
41 #include "WebCoreArgumentCoders.h"
42 #include "WebProcessConnection.h"
43 #include <WebCore/GraphicsContext.h>
44 #include <WebCore/HTTPHeaderMap.h>
45 #include <WebCore/IdentifierRep.h>
46 #include <WebCore/NotImplemented.h>
47 #include <wtf/SetForScope.h>
48 #include <wtf/text/WTFString.h>
49
50 #if PLATFORM(COCOA)
51 #include "LayerHostingContext.h"
52 #endif
53
54 namespace WebKit {
55 using namespace WebCore;
56
57 PluginControllerProxy::PluginControllerProxy(WebProcessConnection* connection, const PluginCreationParameters& creationParameters)
58     : m_connection(connection)
59     , m_pluginInstanceID(creationParameters.pluginInstanceID)
60     , m_userAgent(creationParameters.userAgent)
61     , m_isPrivateBrowsingEnabled(creationParameters.isPrivateBrowsingEnabled)
62     , m_isMuted(creationParameters.isMuted)
63     , m_isAcceleratedCompositingEnabled(creationParameters.isAcceleratedCompositingEnabled)
64     , m_isInitializing(false)
65     , m_isVisible(false)
66     , m_isWindowVisible(false)
67     , m_paintTimer(RunLoop::main(), this, &PluginControllerProxy::paint)
68     , m_pluginDestructionProtectCount(0)
69     , m_pluginDestroyTimer(RunLoop::main(), this, &PluginControllerProxy::destroy)
70     , m_waitingForDidUpdate(false)
71     , m_pluginCanceledManualStreamLoad(false)
72 #if PLATFORM(COCOA)
73     , m_isComplexTextInputEnabled(false)
74 #endif
75     , m_contentsScaleFactor(creationParameters.contentsScaleFactor)
76     , m_windowNPObject(0)
77     , m_pluginElementNPObject(0)
78     , m_visiblityActivity("Plugin is visible.")
79 {
80 }
81
82 PluginControllerProxy::~PluginControllerProxy()
83 {
84     ASSERT(!m_plugin);
85
86     if (m_windowNPObject)
87         releaseNPObject(m_windowNPObject);
88
89     if (m_pluginElementNPObject)
90         releaseNPObject(m_pluginElementNPObject);
91 }
92
93 void PluginControllerProxy::setInitializationReply(Messages::WebProcessConnection::CreatePlugin::DelayedReply&& reply)
94 {
95     ASSERT(!m_initializationReply);
96     m_initializationReply = WTFMove(reply);
97 }
98
99 Messages::WebProcessConnection::CreatePlugin::DelayedReply PluginControllerProxy::takeInitializationReply()
100 {
101     return std::exchange(m_initializationReply, nullptr);
102 }
103
104 bool PluginControllerProxy::initialize(const PluginCreationParameters& creationParameters)
105 {
106     ASSERT(!m_plugin);
107
108     ASSERT(!m_isInitializing);
109     m_isInitializing = true; // Cannot use SetForScope here, because this object can be deleted before the function returns.
110
111     m_plugin = NetscapePlugin::create(PluginProcess::singleton().netscapePluginModule());
112     if (!m_plugin) {
113         // This will delete the plug-in controller proxy object.
114         m_connection->removePluginControllerProxy(this, 0);
115         return false;
116     }
117
118     if (creationParameters.windowNPObjectID)
119         m_windowNPObject = m_connection->npRemoteObjectMap()->createNPObjectProxy(creationParameters.windowNPObjectID, m_plugin.get());
120
121     bool returnValue = m_plugin->initialize(this, creationParameters.parameters);
122
123     if (!returnValue) {
124         // Get the plug-in so we can pass it to removePluginControllerProxy. The pointer is only
125         // used as an identifier so it's OK to just get a weak reference.
126         Plugin* plugin = m_plugin.get();
127         
128         m_plugin = nullptr;
129
130         // This will delete the plug-in controller proxy object.
131         m_connection->removePluginControllerProxy(this, plugin);
132         return false;
133     }
134
135     platformInitialize(creationParameters);
136
137     m_isInitializing = false;
138     return true;
139 }
140
141 void PluginControllerProxy::destroy()
142 {
143     ASSERT(m_plugin);
144
145     // FIXME: Consider removing m_pluginDestructionProtectCount and always use inSendSync here.
146     if (m_pluginDestructionProtectCount || m_connection->connection()->inSendSync()) {
147         // We have plug-in code on the stack so we can't destroy it right now.
148         // Destroy it later.
149         m_pluginDestroyTimer.startOneShot(0_s);
150         return;
151     }
152
153     // Get the plug-in so we can pass it to removePluginControllerProxy. The pointer is only
154     // used as an identifier so it's OK to just get a weak reference.
155     Plugin* plugin = m_plugin.get();
156
157     m_plugin->destroyPlugin();
158     m_plugin = nullptr;
159
160     platformDestroy();
161
162     // This will delete the plug-in controller proxy object.
163     m_connection->removePluginControllerProxy(this, plugin);
164 }
165
166 bool PluginControllerProxy::wantsWheelEvents() const
167 {
168     return m_plugin->wantsWheelEvents();
169 }
170
171 void PluginControllerProxy::paint()
172 {
173     ASSERT(!m_dirtyRect.isEmpty());
174     m_paintTimer.stop();
175
176     if (!m_backingStore)
177         return;
178
179     IntRect dirtyRect = m_dirtyRect;
180     m_dirtyRect = IntRect();
181
182     ASSERT(m_plugin);
183
184     // Create a graphics context.
185     auto graphicsContext = m_backingStore->createGraphicsContext();
186
187 #if PLATFORM(COCOA)
188     // FIXME: We should really call applyDeviceScaleFactor instead of scale, but that ends up calling into WKSI
189     // which we currently don't have initiated in the plug-in process.
190     graphicsContext->scale(m_contentsScaleFactor);
191 #endif
192
193     if (m_plugin->isTransparent())
194         graphicsContext->clearRect(dirtyRect);
195
196     m_plugin->paint(*graphicsContext, dirtyRect);
197
198     m_connection->connection()->send(Messages::PluginProxy::Update(dirtyRect), m_pluginInstanceID);
199 }
200
201 void PluginControllerProxy::startPaintTimer()
202 {
203     // Check if we should start the timer.
204     
205     if (m_dirtyRect.isEmpty())
206         return;
207
208     // FIXME: Check clip rect.
209     
210     if (m_paintTimer.isActive())
211         return;
212
213     if (m_waitingForDidUpdate)
214         return;
215
216     // Start the timer.
217     m_paintTimer.startOneShot(0_s);
218
219     m_waitingForDidUpdate = true;
220 }
221
222 void PluginControllerProxy::invalidate(const IntRect& rect)
223 {
224     IntRect dirtyRect = rect;
225
226     // Make sure that the dirty rect is not greater than the plug-in itself.
227     dirtyRect.intersect(IntRect(IntPoint(), m_pluginSize));
228     m_dirtyRect.unite(dirtyRect);
229
230     startPaintTimer();
231 }
232
233 String PluginControllerProxy::userAgent()
234 {
235     return m_userAgent;
236 }
237
238 void PluginControllerProxy::loadURL(uint64_t requestID, const String& method, const String& urlString, const String& target, const HTTPHeaderMap& headerFields, const Vector<uint8_t>& httpBody, bool allowPopups)
239 {
240     m_connection->connection()->send(Messages::PluginProxy::LoadURL(requestID, method, urlString, target, headerFields, httpBody, allowPopups), m_pluginInstanceID);
241 }
242
243 void PluginControllerProxy::continueStreamLoad(uint64_t streamID)
244 {
245     m_connection->connection()->send(Messages::PluginProxy::ContinueStreamLoad(streamID), m_pluginInstanceID);
246 }
247
248 void PluginControllerProxy::cancelStreamLoad(uint64_t streamID)
249 {
250     m_connection->connection()->send(Messages::PluginProxy::CancelStreamLoad(streamID), m_pluginInstanceID);
251 }
252
253 void PluginControllerProxy::cancelManualStreamLoad()
254 {
255     m_pluginCanceledManualStreamLoad = true;
256
257     m_connection->connection()->send(Messages::PluginProxy::CancelManualStreamLoad(), m_pluginInstanceID);
258 }
259
260 NPObject* PluginControllerProxy::windowScriptNPObject()
261 {
262     if (!m_windowNPObject)
263         return 0;
264
265     retainNPObject(m_windowNPObject);
266     return m_windowNPObject;
267 }
268
269 NPObject* PluginControllerProxy::pluginElementNPObject()
270 {
271     if (!m_pluginElementNPObject) {
272         uint64_t pluginElementNPObjectID = 0;
273
274         if (!m_connection->connection()->sendSync(Messages::PluginProxy::GetPluginElementNPObject(), Messages::PluginProxy::GetPluginElementNPObject::Reply(pluginElementNPObjectID), m_pluginInstanceID))
275             return 0;
276
277         if (!pluginElementNPObjectID)
278             return 0;
279
280         m_pluginElementNPObject = m_connection->npRemoteObjectMap()->createNPObjectProxy(pluginElementNPObjectID, m_plugin.get());
281         ASSERT(m_pluginElementNPObject);
282     }
283
284     retainNPObject(m_pluginElementNPObject);
285     return m_pluginElementNPObject;
286 }
287
288 bool PluginControllerProxy::evaluate(NPObject* npObject, const String& scriptString, NPVariant* result, bool allowPopups)
289 {
290     PluginDestructionProtector protector(this);
291
292     NPVariant npObjectAsNPVariant;
293     OBJECT_TO_NPVARIANT(npObject, npObjectAsNPVariant);
294
295     // Send the NPObject over as an NPVariantData.
296     NPVariantData npObjectAsNPVariantData = m_connection->npRemoteObjectMap()->npVariantToNPVariantData(npObjectAsNPVariant, m_plugin.get());
297
298     bool returnValue = false;
299     NPVariantData resultData;
300
301     if (!m_connection->connection()->sendSync(Messages::PluginProxy::Evaluate(npObjectAsNPVariantData, scriptString, allowPopups), Messages::PluginProxy::Evaluate::Reply(returnValue, resultData), m_pluginInstanceID))
302         return false;
303
304     if (!returnValue)
305         return false;
306
307     *result = m_connection->npRemoteObjectMap()->npVariantDataToNPVariant(resultData, m_plugin.get());
308     return true;
309 }
310
311 void PluginControllerProxy::setPluginIsPlayingAudio(bool pluginIsPlayingAudio)
312 {
313     m_connection->connection()->send(Messages::PluginProxy::SetPluginIsPlayingAudio(pluginIsPlayingAudio), m_pluginInstanceID);
314 }
315
316 void PluginControllerProxy::setStatusbarText(const String& statusbarText)
317 {
318     m_connection->connection()->send(Messages::PluginProxy::SetStatusbarText(statusbarText), m_pluginInstanceID);
319 }
320
321 bool PluginControllerProxy::isAcceleratedCompositingEnabled()
322 {
323     return m_isAcceleratedCompositingEnabled;
324 }
325
326 void PluginControllerProxy::pluginProcessCrashed()
327 {
328     // This should never be called from here.
329     ASSERT_NOT_REACHED();
330 }
331
332 void PluginControllerProxy::didInitializePlugin()
333 {
334     // This should only be called on the plugin in the web process.
335     ASSERT_NOT_REACHED();
336 }
337
338 void PluginControllerProxy::didFailToInitializePlugin()
339 {
340     // This should only be called on the plugin in the web process.
341     ASSERT_NOT_REACHED();
342 }
343
344 float PluginControllerProxy::contentsScaleFactor()
345 {
346     return m_contentsScaleFactor;
347 }
348
349 String PluginControllerProxy::proxiesForURL(const String& urlString)
350 {
351     String proxyString;
352
353     if (!m_connection->connection()->sendSync(Messages::PluginProxy::ProxiesForURL(urlString), Messages::PluginProxy::ProxiesForURL::Reply(proxyString), m_pluginInstanceID))
354         return String();
355
356     return proxyString;
357 }
358
359 String PluginControllerProxy::cookiesForURL(const String& urlString)
360 {
361     String cookieString;
362
363     if (!m_connection->connection()->sendSync(Messages::PluginProxy::CookiesForURL(urlString), Messages::PluginProxy::CookiesForURL::Reply(cookieString), m_pluginInstanceID))
364         return String();
365
366     return cookieString;
367 }
368
369 void PluginControllerProxy::setCookiesForURL(const String& urlString, const String& cookieString)
370 {
371     m_connection->connection()->send(Messages::PluginProxy::SetCookiesForURL(urlString, cookieString), m_pluginInstanceID);
372 }
373
374 bool PluginControllerProxy::isPrivateBrowsingEnabled()
375 {
376     return m_isPrivateBrowsingEnabled;
377 }
378
379 bool PluginControllerProxy::getAuthenticationInfo(const ProtectionSpace& protectionSpace, String& username, String& password)
380 {
381     bool returnValue;
382     if (!m_connection->connection()->sendSync(Messages::PluginProxy::GetAuthenticationInfo(protectionSpace), Messages::PluginProxy::GetAuthenticationInfo::Reply(returnValue, username, password), m_pluginInstanceID))
383         return false;
384
385     return returnValue;
386 }
387
388 void PluginControllerProxy::protectPluginFromDestruction()
389 {
390     m_pluginDestructionProtectCount++;
391 }
392
393 void PluginControllerProxy::unprotectPluginFromDestruction()
394 {
395     ASSERT(m_pluginDestructionProtectCount);
396
397     m_pluginDestructionProtectCount--;
398 }
399
400 void PluginControllerProxy::frameDidFinishLoading(uint64_t requestID)
401 {
402     m_plugin->frameDidFinishLoading(requestID);
403 }
404
405 void PluginControllerProxy::frameDidFail(uint64_t requestID, bool wasCancelled)
406 {
407     m_plugin->frameDidFail(requestID, wasCancelled);
408 }
409
410 void PluginControllerProxy::geometryDidChange(const IntSize& pluginSize, const IntRect& clipRect, const AffineTransform& pluginToRootViewTransform, float contentsScaleFactor, const ShareableBitmap::Handle& backingStoreHandle)
411 {
412     ASSERT(m_plugin);
413
414     m_pluginSize = pluginSize;
415
416     if (contentsScaleFactor != m_contentsScaleFactor) {
417         m_contentsScaleFactor = contentsScaleFactor;
418         m_plugin->contentsScaleFactorChanged(m_contentsScaleFactor);
419     }
420
421     platformGeometryDidChange();
422
423     if (!backingStoreHandle.isNull()) {
424         // Create a new backing store.
425         m_backingStore = ShareableBitmap::create(backingStoreHandle);
426     }
427
428     m_plugin->geometryDidChange(pluginSize, clipRect, pluginToRootViewTransform);
429 }
430
431 void PluginControllerProxy::visibilityDidChange(bool isVisible)
432 {
433     m_isVisible = isVisible;
434     
435     ASSERT(m_plugin);
436     m_plugin->visibilityDidChange(isVisible);
437
438     updateVisibilityActivity();
439 }
440
441 void PluginControllerProxy::windowFocusChanged(bool hasFocus)
442 {
443     ASSERT(m_plugin);
444     m_plugin->windowFocusChanged(hasFocus);
445 }
446
447 void PluginControllerProxy::windowVisibilityChanged(bool isVisible)
448 {
449     m_isWindowVisible = isVisible;
450
451     ASSERT(m_plugin);
452     m_plugin->windowVisibilityChanged(isVisible);
453
454     updateVisibilityActivity();
455 }
456
457 void PluginControllerProxy::updateVisibilityActivity()
458 {
459     if (m_isVisible && m_isWindowVisible)
460         m_visiblityActivity.start();
461     else
462         m_visiblityActivity.stop();
463 }
464
465 void PluginControllerProxy::didEvaluateJavaScript(uint64_t requestID, const String& result)
466 {
467     m_plugin->didEvaluateJavaScript(requestID, result);
468 }
469
470 void PluginControllerProxy::streamWillSendRequest(uint64_t streamID, const String& requestURLString, const String& redirectResponseURLString, uint32_t redirectResponseStatusCode)
471 {
472     m_plugin->streamWillSendRequest(streamID, URL({ }, requestURLString), URL({ }, redirectResponseURLString), redirectResponseStatusCode);
473 }
474
475 void PluginControllerProxy::streamDidReceiveResponse(uint64_t streamID, const String& responseURLString, uint32_t streamLength, uint32_t lastModifiedTime, const String& mimeType, const String& headers)
476 {
477     m_plugin->streamDidReceiveResponse(streamID, URL({ }, responseURLString), streamLength, lastModifiedTime, mimeType, headers, String());
478 }
479
480 void PluginControllerProxy::streamDidReceiveData(uint64_t streamID, const IPC::DataReference& data)
481 {
482     m_plugin->streamDidReceiveData(streamID, reinterpret_cast<const char*>(data.data()), data.size());
483 }
484
485 void PluginControllerProxy::streamDidFinishLoading(uint64_t streamID)
486 {
487     m_plugin->streamDidFinishLoading(streamID);
488 }
489
490 void PluginControllerProxy::streamDidFail(uint64_t streamID, bool wasCancelled)
491 {
492     m_plugin->streamDidFail(streamID, wasCancelled);
493 }
494
495 void PluginControllerProxy::manualStreamDidReceiveResponse(const String& responseURLString, uint32_t streamLength, uint32_t lastModifiedTime, const String& mimeType, const String& headers)
496 {
497     if (m_pluginCanceledManualStreamLoad)
498         return;
499
500     m_plugin->manualStreamDidReceiveResponse(URL({ }, responseURLString), streamLength, lastModifiedTime, mimeType, headers, String());
501 }
502
503 void PluginControllerProxy::manualStreamDidReceiveData(const IPC::DataReference& data)
504 {
505     if (m_pluginCanceledManualStreamLoad)
506         return;
507
508     m_plugin->manualStreamDidReceiveData(reinterpret_cast<const char*>(data.data()), data.size());
509 }
510
511 void PluginControllerProxy::manualStreamDidFinishLoading()
512 {
513     if (m_pluginCanceledManualStreamLoad)
514         return;
515     
516     m_plugin->manualStreamDidFinishLoading();
517 }
518
519 void PluginControllerProxy::manualStreamDidFail(bool wasCancelled)
520 {
521     if (m_pluginCanceledManualStreamLoad)
522         return;
523     
524     m_plugin->manualStreamDidFail(wasCancelled);
525 }
526
527 void PluginControllerProxy::handleMouseEvent(const WebMouseEvent& mouseEvent)
528 {
529     m_plugin->handleMouseEvent(mouseEvent);
530 }
531
532 void PluginControllerProxy::handleWheelEvent(const WebWheelEvent& wheelEvent, CompletionHandler<void(bool)>&& completionHandler)
533 {
534     completionHandler(m_plugin->handleWheelEvent(wheelEvent));
535 }
536
537 void PluginControllerProxy::handleMouseEnterEvent(const WebMouseEvent& mouseEnterEvent, CompletionHandler<void(bool)>&& completionHandler)
538 {
539     completionHandler(m_plugin->handleMouseEnterEvent(mouseEnterEvent));
540 }
541
542 void PluginControllerProxy::handleMouseLeaveEvent(const WebMouseEvent& mouseLeaveEvent, CompletionHandler<void(bool)>&& completionHandler)
543 {
544     completionHandler(m_plugin->handleMouseLeaveEvent(mouseLeaveEvent));
545 }
546
547 void PluginControllerProxy::handleKeyboardEvent(const WebKeyboardEvent& keyboardEvent, CompletionHandler<void(bool)>&& completionHandler)
548 {
549     completionHandler(m_plugin->handleKeyboardEvent(keyboardEvent));
550 }
551
552 void PluginControllerProxy::handleEditingCommand(const String& commandName, const String& argument, CompletionHandler<void(bool)>&& completionHandler)
553 {
554     completionHandler(m_plugin->handleEditingCommand(commandName, argument));
555 }
556     
557 void PluginControllerProxy::isEditingCommandEnabled(const String& commandName, CompletionHandler<void(bool)>&& completionHandler)
558 {
559     completionHandler(m_plugin->isEditingCommandEnabled(commandName));
560 }
561     
562 void PluginControllerProxy::handlesPageScaleFactor(CompletionHandler<void(bool)>&& completionHandler)
563 {
564     completionHandler(m_plugin->handlesPageScaleFactor());
565 }
566
567 void PluginControllerProxy::requiresUnifiedScaleFactor(CompletionHandler<void(bool)>&& completionHandler)
568 {
569     completionHandler(m_plugin->requiresUnifiedScaleFactor());
570 }
571
572 void PluginControllerProxy::paintEntirePlugin(CompletionHandler<void()>&& completionHandler)
573 {
574     if (m_pluginSize.isEmpty())
575         return completionHandler();
576
577     m_dirtyRect = IntRect(IntPoint(), m_pluginSize);
578     paint();
579     completionHandler();
580 }
581
582 void PluginControllerProxy::supportsSnapshotting(CompletionHandler<void(bool)>&& completionHandler)
583 {
584     completionHandler(m_plugin->supportsSnapshotting());
585 }
586
587 void PluginControllerProxy::snapshot(CompletionHandler<void(ShareableBitmap::Handle&&)> completionHandler)
588 {
589     ASSERT(m_plugin);
590     RefPtr<ShareableBitmap> bitmap = m_plugin->snapshot();
591     if (!bitmap)
592         return completionHandler({ });
593
594     ShareableBitmap::Handle backingStoreHandle;
595     bitmap->createHandle(backingStoreHandle);
596     completionHandler(WTFMove(backingStoreHandle));
597 }
598
599 void PluginControllerProxy::setFocus(bool hasFocus)
600 {
601     m_plugin->setFocus(hasFocus);
602 }
603
604 void PluginControllerProxy::didUpdate()
605 {
606     m_waitingForDidUpdate = false;
607     startPaintTimer();
608 }
609
610 void PluginControllerProxy::getPluginScriptableNPObject(CompletionHandler<void(uint64_t)>&& completionHandler)
611 {
612     NPObject* pluginScriptableNPObject = m_plugin->pluginScriptableNPObject();
613     if (!pluginScriptableNPObject)
614         return completionHandler(0);
615     
616     uint64_t pluginScriptableNPObjectID = m_connection->npRemoteObjectMap()->registerNPObject(pluginScriptableNPObject, m_plugin.get());
617     releaseNPObject(pluginScriptableNPObject);
618     completionHandler(pluginScriptableNPObjectID);
619 }
620
621 void PluginControllerProxy::storageBlockingStateChanged(bool isStorageBlockingEnabled)
622 {
623     if (m_storageBlockingEnabled != isStorageBlockingEnabled) {
624         m_storageBlockingEnabled = isStorageBlockingEnabled;
625         m_plugin->storageBlockingStateChanged(m_storageBlockingEnabled);
626     }
627 }
628
629 void PluginControllerProxy::privateBrowsingStateChanged(bool isPrivateBrowsingEnabled)
630 {
631     m_isPrivateBrowsingEnabled = isPrivateBrowsingEnabled;
632
633     m_plugin->privateBrowsingStateChanged(isPrivateBrowsingEnabled);
634 }
635
636 void PluginControllerProxy::mutedStateChanged(bool isMuted)
637 {
638     if (m_isMuted == isMuted)
639         return;
640     
641     m_isMuted = isMuted;
642     m_plugin->mutedStateChanged(isMuted);
643 }
644
645 void PluginControllerProxy::getFormValue(CompletionHandler<void(bool, String&&)>&& completionHandler)
646 {
647     String formValue;
648     bool returnValue = m_plugin->getFormValue(formValue);
649     completionHandler(returnValue, WTFMove(formValue));
650 }
651
652 #if PLATFORM(X11)
653 uint64_t PluginControllerProxy::createPluginContainer()
654 {
655     uint64_t windowID = 0;
656     m_connection->connection()->sendSync(Messages::PluginProxy::CreatePluginContainer(), Messages::PluginProxy::CreatePluginContainer::Reply(windowID), m_pluginInstanceID);
657     return windowID;
658 }
659
660 void PluginControllerProxy::windowedPluginGeometryDidChange(const IntRect& frameRect, const IntRect& clipRect, uint64_t windowID)
661 {
662     m_connection->connection()->send(Messages::PluginProxy::WindowedPluginGeometryDidChange(frameRect, clipRect, windowID), m_pluginInstanceID);
663 }
664
665 void PluginControllerProxy::windowedPluginVisibilityDidChange(bool isVisible, uint64_t windowID)
666 {
667     m_connection->connection()->send(Messages::PluginProxy::WindowedPluginVisibilityDidChange(isVisible, windowID), m_pluginInstanceID);
668 }
669 #endif
670
671 } // namespace WebKit
672
673 #endif // ENABLE(NETSCAPE_PLUGIN_API)