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 "PluginProxy.h"
28
29#if ENABLE(NETSCAPE_PLUGIN_API)
30
31#include "DataReference.h"
32#include "NPRemoteObjectMap.h"
33#include "NPRuntimeUtilities.h"
34#include "NPVariantData.h"
35#include "PluginController.h"
36#include "PluginControllerProxyMessages.h"
37#include "PluginCreationParameters.h"
38#include "PluginProcessConnection.h"
39#include "PluginProcessConnectionManager.h"
40#include "ShareableBitmap.h"
41#include "WebCoreArgumentCoders.h"
42#include "WebEvent.h"
43#include "WebProcess.h"
44#include "WebProcessConnectionMessages.h"
45#include <WebCore/GraphicsContext.h>
46#include <WebCore/SharedBuffer.h>
47
48namespace WebKit {
49using namespace WebCore;
50
51static uint64_t generatePluginInstanceID()
52{
53 static uint64_t uniquePluginInstanceID;
54 return ++uniquePluginInstanceID;
55}
56
57Ref<PluginProxy> PluginProxy::create(uint64_t pluginProcessToken, bool isRestartedProcess)
58{
59 return adoptRef(*new PluginProxy(pluginProcessToken, isRestartedProcess));
60}
61
62PluginProxy::PluginProxy(uint64_t pluginProcessToken, bool isRestartedProcess)
63 : Plugin(PluginProxyType)
64 , m_pluginProcessToken(pluginProcessToken)
65 , m_pluginInstanceID(generatePluginInstanceID())
66 , m_pluginBackingStoreContainsValidData(false)
67 , m_isStarted(false)
68 , m_waitingForPaintInResponseToUpdate(false)
69 , m_wantsWheelEvents(false)
70 , m_remoteLayerClientID(0)
71 , m_waitingOnAsynchronousInitialization(false)
72 , m_isRestartedProcess(isRestartedProcess)
73{
74}
75
76PluginProxy::~PluginProxy()
77{
78}
79
80void PluginProxy::pluginProcessCrashed()
81{
82 controller()->pluginProcessCrashed();
83}
84
85bool PluginProxy::initialize(const Parameters& parameters)
86{
87 ASSERT(!m_connection);
88 m_connection = WebProcess::singleton().pluginProcessConnectionManager().getPluginProcessConnection(m_pluginProcessToken);
89
90 if (!m_connection)
91 return false;
92
93 // Add the plug-in proxy before creating the plug-in; it needs to be in the map because CreatePlugin
94 // can call back out to the plug-in proxy.
95 m_connection->addPluginProxy(this);
96
97 // Ask the plug-in process to create a plug-in.
98 m_pendingPluginCreationParameters = std::make_unique<PluginCreationParameters>();
99
100 m_pendingPluginCreationParameters->pluginInstanceID = m_pluginInstanceID;
101 m_pendingPluginCreationParameters->windowNPObjectID = windowNPObjectID();
102 m_pendingPluginCreationParameters->parameters = parameters;
103 m_pendingPluginCreationParameters->userAgent = controller()->userAgent();
104 m_pendingPluginCreationParameters->contentsScaleFactor = contentsScaleFactor();
105 m_pendingPluginCreationParameters->isPrivateBrowsingEnabled = controller()->isPrivateBrowsingEnabled();
106 m_pendingPluginCreationParameters->isMuted = controller()->isMuted();
107 m_pendingPluginCreationParameters->artificialPluginInitializationDelayEnabled = controller()->artificialPluginInitializationDelayEnabled();
108 m_pendingPluginCreationParameters->isAcceleratedCompositingEnabled = controller()->isAcceleratedCompositingEnabled();
109
110 if (!canInitializeAsynchronously())
111 return initializeSynchronously();
112
113 // Remember that we tried to create this plug-in asynchronously in case we need to create it synchronously later.
114 m_waitingOnAsynchronousInitialization = true;
115 PluginCreationParameters creationParameters(*m_pendingPluginCreationParameters.get());
116 m_connection->connection()->send(Messages::WebProcessConnection::CreatePluginAsynchronously(creationParameters), m_pluginInstanceID);
117 return true;
118}
119
120bool PluginProxy::canInitializeAsynchronously() const
121{
122 return controller()->asynchronousPluginInitializationEnabled() && (m_connection->supportsAsynchronousPluginInitialization() || controller()->asynchronousPluginInitializationEnabledForAllPlugins());
123}
124
125bool PluginProxy::initializeSynchronously()
126{
127 ASSERT(m_pendingPluginCreationParameters);
128
129 m_pendingPluginCreationParameters->asynchronousCreationIncomplete = m_waitingOnAsynchronousInitialization;
130 bool result = false;
131 bool wantsWheelEvents = false;
132 uint32_t remoteLayerClientID = 0;
133
134 PluginCreationParameters parameters(*m_pendingPluginCreationParameters.get());
135
136 if (!m_connection->connection()->sendSync(Messages::WebProcessConnection::CreatePlugin(parameters), Messages::WebProcessConnection::CreatePlugin::Reply(result, wantsWheelEvents, remoteLayerClientID), 0) || !result)
137 didFailToCreatePluginInternal();
138 else
139 didCreatePluginInternal(wantsWheelEvents, remoteLayerClientID);
140
141 return result;
142}
143
144void PluginProxy::didCreatePlugin(bool wantsWheelEvents, uint32_t remoteLayerClientID, CompletionHandler<void()>&& completionHandler)
145{
146 // We might have tried to create the plug-in sychronously while waiting on the asynchronous reply,
147 // in which case we should ignore this message.
148 if (!m_waitingOnAsynchronousInitialization)
149 return completionHandler();
150
151 didCreatePluginInternal(wantsWheelEvents, remoteLayerClientID);
152 completionHandler();
153}
154
155void PluginProxy::didFailToCreatePlugin(CompletionHandler<void()>&& completionHandler)
156{
157 // We might have tried to create the plug-in sychronously while waiting on the asynchronous reply,
158 // in which case we should ignore this message.
159 if (!m_waitingOnAsynchronousInitialization)
160 return completionHandler();
161
162 didFailToCreatePluginInternal();
163 completionHandler();
164}
165
166void PluginProxy::didCreatePluginInternal(bool wantsWheelEvents, uint32_t remoteLayerClientID)
167{
168 m_wantsWheelEvents = wantsWheelEvents;
169 m_remoteLayerClientID = remoteLayerClientID;
170 m_isStarted = true;
171 controller()->didInitializePlugin();
172
173 // Whether synchronously or asynchronously, this plug-in was created and we shouldn't need to remember
174 // anything about how.
175 m_pendingPluginCreationParameters = nullptr;
176 m_waitingOnAsynchronousInitialization = false;
177}
178
179void PluginProxy::didFailToCreatePluginInternal()
180{
181 // Calling out to the connection and the controller could potentially cause the plug-in proxy to go away, so protect it here.
182 Ref<PluginProxy> protect(*this);
183
184 m_connection->removePluginProxy(this);
185 controller()->didFailToInitializePlugin();
186
187 // Whether synchronously or asynchronously, this plug-in failed to create and we shouldn't need to remember
188 // anything about how.
189 m_pendingPluginCreationParameters = nullptr;
190 m_waitingOnAsynchronousInitialization = false;
191}
192
193void PluginProxy::destroy()
194{
195 m_isStarted = false;
196
197 if (!m_connection)
198 return;
199
200 // Although this message is sent synchronously, the Plugin process replies immediately (before performing any tasks) so this is only waiting for
201 // confirmation that the Plugin process received the DestroyPlugin message.
202 m_connection->connection()->sendSync(Messages::WebProcessConnection::DestroyPlugin(m_pluginInstanceID, m_waitingOnAsynchronousInitialization), Messages::WebProcessConnection::DestroyPlugin::Reply(), 0, 1_s);
203 m_connection->removePluginProxy(this);
204}
205
206void PluginProxy::paint(GraphicsContext& graphicsContext, const IntRect& dirtyRect)
207{
208 if (!needsBackingStore() || !m_backingStore)
209 return;
210
211 if (!m_pluginBackingStoreContainsValidData) {
212 m_connection->connection()->sendSync(Messages::PluginControllerProxy::PaintEntirePlugin(), Messages::PluginControllerProxy::PaintEntirePlugin::Reply(), m_pluginInstanceID);
213
214 // Blit the plug-in backing store into our own backing store.
215 auto graphicsContext = m_backingStore->createGraphicsContext();
216 graphicsContext->applyDeviceScaleFactor(contentsScaleFactor());
217 graphicsContext->setCompositeOperation(CompositeCopy);
218
219 m_pluginBackingStore->paint(*graphicsContext, contentsScaleFactor(), IntPoint(), pluginBounds());
220
221 m_pluginBackingStoreContainsValidData = true;
222 }
223
224 m_backingStore->paint(graphicsContext, contentsScaleFactor(), dirtyRect.location(), dirtyRect);
225
226 if (m_waitingForPaintInResponseToUpdate) {
227 m_waitingForPaintInResponseToUpdate = false;
228 m_connection->connection()->send(Messages::PluginControllerProxy::DidUpdate(), m_pluginInstanceID);
229 }
230}
231
232bool PluginProxy::supportsSnapshotting() const
233{
234 if (m_waitingOnAsynchronousInitialization)
235 return false;
236
237 bool isSupported = false;
238 if (m_connection && !m_connection->connection()->sendSync(Messages::PluginControllerProxy::SupportsSnapshotting(), Messages::PluginControllerProxy::SupportsSnapshotting::Reply(isSupported), m_pluginInstanceID))
239 return false;
240
241 return isSupported;
242}
243
244RefPtr<ShareableBitmap> PluginProxy::snapshot()
245{
246 ShareableBitmap::Handle snapshotStoreHandle;
247 m_connection->connection()->sendSync(Messages::PluginControllerProxy::Snapshot(), Messages::PluginControllerProxy::Snapshot::Reply(snapshotStoreHandle), m_pluginInstanceID);
248
249 if (snapshotStoreHandle.isNull())
250 return nullptr;
251
252 return ShareableBitmap::create(snapshotStoreHandle);
253}
254
255bool PluginProxy::isTransparent()
256{
257 // This should never be called from the web process.
258 ASSERT_NOT_REACHED();
259 return false;
260}
261
262bool PluginProxy::wantsWheelEvents()
263{
264 return m_wantsWheelEvents;
265}
266
267void PluginProxy::geometryDidChange()
268{
269 ASSERT(m_isStarted);
270
271 ShareableBitmap::Handle pluginBackingStoreHandle;
272
273 if (updateBackingStore()) {
274 // Create a new plug-in backing store.
275 m_pluginBackingStore = ShareableBitmap::createShareable(m_backingStore->size(), { });
276 if (!m_pluginBackingStore)
277 return;
278
279 // Create a handle to the plug-in backing store so we can send it over.
280 if (!m_pluginBackingStore->createHandle(pluginBackingStoreHandle)) {
281 m_pluginBackingStore = nullptr;
282 return;
283 }
284
285 m_pluginBackingStoreContainsValidData = false;
286 }
287
288 m_connection->connection()->send(Messages::PluginControllerProxy::GeometryDidChange(m_pluginSize, m_clipRect, m_pluginToRootViewTransform, contentsScaleFactor(), pluginBackingStoreHandle), m_pluginInstanceID, IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply);
289}
290
291void PluginProxy::geometryDidChange(const IntSize& pluginSize, const IntRect& clipRect, const AffineTransform& pluginToRootViewTransform)
292{
293 if (pluginSize == m_pluginSize && m_clipRect == clipRect && m_pluginToRootViewTransform == pluginToRootViewTransform) {
294 // Nothing to do.
295 return;
296 }
297
298 m_pluginSize = pluginSize;
299 m_clipRect = clipRect;
300 m_pluginToRootViewTransform = pluginToRootViewTransform;
301
302 geometryDidChange();
303}
304
305void PluginProxy::visibilityDidChange(bool isVisible)
306{
307 ASSERT(m_isStarted);
308 m_connection->connection()->send(Messages::PluginControllerProxy::VisibilityDidChange(isVisible), m_pluginInstanceID);
309}
310
311void PluginProxy::frameDidFinishLoading(uint64_t requestID)
312{
313 m_connection->connection()->send(Messages::PluginControllerProxy::FrameDidFinishLoading(requestID), m_pluginInstanceID);
314}
315
316void PluginProxy::frameDidFail(uint64_t requestID, bool wasCancelled)
317{
318 m_connection->connection()->send(Messages::PluginControllerProxy::FrameDidFail(requestID, wasCancelled), m_pluginInstanceID);
319}
320
321void PluginProxy::didEvaluateJavaScript(uint64_t requestID, const WTF::String& result)
322{
323 m_connection->connection()->send(Messages::PluginControllerProxy::DidEvaluateJavaScript(requestID, result), m_pluginInstanceID);
324}
325
326void PluginProxy::streamWillSendRequest(uint64_t streamID, const URL& requestURL, const URL& responseURL, int responseStatus)
327{
328 m_connection->connection()->send(Messages::PluginControllerProxy::StreamWillSendRequest(streamID, requestURL.string(), responseURL.string(), responseStatus), m_pluginInstanceID);
329}
330
331void PluginProxy::streamDidReceiveResponse(uint64_t streamID, const URL& responseURL, uint32_t streamLength, uint32_t lastModifiedTime, const WTF::String& mimeType, const WTF::String& headers, const String& /* suggestedFileName */)
332{
333 m_connection->connection()->send(Messages::PluginControllerProxy::StreamDidReceiveResponse(streamID, responseURL.string(), streamLength, lastModifiedTime, mimeType, headers), m_pluginInstanceID);
334}
335
336void PluginProxy::streamDidReceiveData(uint64_t streamID, const char* bytes, int length)
337{
338 m_connection->connection()->send(Messages::PluginControllerProxy::StreamDidReceiveData(streamID, IPC::DataReference(reinterpret_cast<const uint8_t*>(bytes), length)), m_pluginInstanceID);
339}
340
341void PluginProxy::streamDidFinishLoading(uint64_t streamID)
342{
343 m_connection->connection()->send(Messages::PluginControllerProxy::StreamDidFinishLoading(streamID), m_pluginInstanceID);
344}
345
346void PluginProxy::streamDidFail(uint64_t streamID, bool wasCancelled)
347{
348 m_connection->connection()->send(Messages::PluginControllerProxy::StreamDidFail(streamID, wasCancelled), m_pluginInstanceID);
349}
350
351void PluginProxy::manualStreamDidReceiveResponse(const URL& responseURL, uint32_t streamLength, uint32_t lastModifiedTime, const WTF::String& mimeType, const WTF::String& headers, const String& /* suggestedFileName */)
352{
353 m_connection->connection()->send(Messages::PluginControllerProxy::ManualStreamDidReceiveResponse(responseURL.string(), streamLength, lastModifiedTime, mimeType, headers), m_pluginInstanceID);
354}
355
356void PluginProxy::manualStreamDidReceiveData(const char* bytes, int length)
357{
358 m_connection->connection()->send(Messages::PluginControllerProxy::ManualStreamDidReceiveData(IPC::DataReference(reinterpret_cast<const uint8_t*>(bytes), length)), m_pluginInstanceID);
359}
360
361void PluginProxy::manualStreamDidFinishLoading()
362{
363 m_connection->connection()->send(Messages::PluginControllerProxy::ManualStreamDidFinishLoading(), m_pluginInstanceID);
364}
365
366void PluginProxy::manualStreamDidFail(bool wasCancelled)
367{
368 m_connection->connection()->send(Messages::PluginControllerProxy::ManualStreamDidFail(wasCancelled), m_pluginInstanceID);
369}
370
371bool PluginProxy::handleMouseEvent(const WebMouseEvent& mouseEvent)
372{
373 if (m_waitingOnAsynchronousInitialization)
374 return false;
375
376 m_connection->connection()->send(Messages::PluginControllerProxy::HandleMouseEvent(mouseEvent), m_pluginInstanceID);
377 return true;
378}
379
380bool PluginProxy::handleWheelEvent(const WebWheelEvent& wheelEvent)
381{
382 if (m_waitingOnAsynchronousInitialization)
383 return false;
384
385 bool handled = false;
386 if (!m_connection->connection()->sendSync(Messages::PluginControllerProxy::HandleWheelEvent(wheelEvent), Messages::PluginControllerProxy::HandleWheelEvent::Reply(handled), m_pluginInstanceID))
387 return false;
388
389 return handled;
390}
391
392bool PluginProxy::handleMouseEnterEvent(const WebMouseEvent& mouseEnterEvent)
393{
394 if (m_waitingOnAsynchronousInitialization)
395 return false;
396
397 bool handled = false;
398 if (!m_connection->connection()->sendSync(Messages::PluginControllerProxy::HandleMouseEnterEvent(mouseEnterEvent), Messages::PluginControllerProxy::HandleMouseEnterEvent::Reply(handled), m_pluginInstanceID))
399 return false;
400
401 return handled;
402}
403
404bool PluginProxy::handleMouseLeaveEvent(const WebMouseEvent& mouseLeaveEvent)
405{
406 if (m_waitingOnAsynchronousInitialization)
407 return false;
408
409 bool handled = false;
410 if (!m_connection->connection()->sendSync(Messages::PluginControllerProxy::HandleMouseLeaveEvent(mouseLeaveEvent), Messages::PluginControllerProxy::HandleMouseLeaveEvent::Reply(handled), m_pluginInstanceID))
411 return false;
412
413 return handled;
414}
415
416bool PluginProxy::handleContextMenuEvent(const WebMouseEvent&)
417{
418 // 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.
419 return true;
420}
421
422bool PluginProxy::handleKeyboardEvent(const WebKeyboardEvent& keyboardEvent)
423{
424 if (m_waitingOnAsynchronousInitialization)
425 return false;
426
427 bool handled = false;
428 if (!m_connection->connection()->sendSync(Messages::PluginControllerProxy::HandleKeyboardEvent(keyboardEvent), Messages::PluginControllerProxy::HandleKeyboardEvent::Reply(handled), m_pluginInstanceID))
429 return false;
430
431 return handled;
432}
433
434void PluginProxy::setFocus(bool hasFocus)
435{
436 m_connection->connection()->send(Messages::PluginControllerProxy::SetFocus(hasFocus), m_pluginInstanceID);
437}
438
439bool PluginProxy::handleEditingCommand(const String& commandName, const String& argument)
440{
441 if (m_waitingOnAsynchronousInitialization)
442 return false;
443
444 bool handled = false;
445 if (!m_connection->connection()->sendSync(Messages::PluginControllerProxy::HandleEditingCommand(commandName, argument), Messages::PluginControllerProxy::HandleEditingCommand::Reply(handled), m_pluginInstanceID))
446 return false;
447
448 return handled;
449}
450
451bool PluginProxy::isEditingCommandEnabled(const String& commandName)
452{
453 if (m_waitingOnAsynchronousInitialization)
454 return false;
455
456 bool enabled = false;
457 if (!m_connection->connection()->sendSync(Messages::PluginControllerProxy::IsEditingCommandEnabled(commandName), Messages::PluginControllerProxy::IsEditingCommandEnabled::Reply(enabled), m_pluginInstanceID))
458 return false;
459
460 return enabled;
461}
462
463bool PluginProxy::handlesPageScaleFactor() const
464{
465 if (m_waitingOnAsynchronousInitialization)
466 return false;
467
468 bool handled = false;
469 if (!m_connection->connection()->sendSync(Messages::PluginControllerProxy::HandlesPageScaleFactor(), Messages::PluginControllerProxy::HandlesPageScaleFactor::Reply(handled), m_pluginInstanceID))
470 return false;
471
472 return handled;
473}
474
475bool PluginProxy::requiresUnifiedScaleFactor() const
476{
477 if (m_waitingOnAsynchronousInitialization)
478 return false;
479
480 bool required = false;
481 if (!m_connection->connection()->sendSync(Messages::PluginControllerProxy::RequiresUnifiedScaleFactor(), Messages::PluginControllerProxy::RequiresUnifiedScaleFactor::Reply(required), m_pluginInstanceID))
482 return false;
483
484 return required;
485}
486
487NPObject* PluginProxy::pluginScriptableNPObject()
488{
489 // Sending the synchronous Messages::PluginControllerProxy::GetPluginScriptableNPObject message can cause us to dispatch an
490 // incoming synchronous message that ends up destroying the PluginProxy object.
491 PluginController::PluginDestructionProtector protector(controller());
492
493 uint64_t pluginScriptableNPObjectID = 0;
494
495 if (!m_connection->connection()->sendSync(Messages::PluginControllerProxy::GetPluginScriptableNPObject(), Messages::PluginControllerProxy::GetPluginScriptableNPObject::Reply(pluginScriptableNPObjectID), m_pluginInstanceID))
496 return 0;
497
498 if (!pluginScriptableNPObjectID)
499 return 0;
500
501 return m_connection->npRemoteObjectMap()->createNPObjectProxy(pluginScriptableNPObjectID, this);
502}
503
504void PluginProxy::windowFocusChanged(bool hasFocus)
505{
506 m_connection->connection()->send(Messages::PluginControllerProxy::WindowFocusChanged(hasFocus), m_pluginInstanceID);
507}
508
509void PluginProxy::windowVisibilityChanged(bool isVisible)
510{
511 m_connection->connection()->send(Messages::PluginControllerProxy::WindowVisibilityChanged(isVisible), m_pluginInstanceID);
512}
513
514#if PLATFORM(COCOA)
515void PluginProxy::windowAndViewFramesChanged(const WebCore::IntRect& windowFrameInScreenCoordinates, const WebCore::IntRect& viewFrameInWindowCoordinates)
516{
517 m_connection->connection()->send(Messages::PluginControllerProxy::WindowAndViewFramesChanged(windowFrameInScreenCoordinates, viewFrameInWindowCoordinates), m_pluginInstanceID);
518}
519uint64_t PluginProxy::pluginComplexTextInputIdentifier() const
520{
521 return m_pluginInstanceID;
522}
523
524void PluginProxy::sendComplexTextInput(const String& textInput)
525{
526 m_connection->connection()->send(Messages::PluginControllerProxy::SendComplexTextInput(textInput), m_pluginInstanceID);
527}
528#endif
529
530void PluginProxy::contentsScaleFactorChanged(float)
531{
532 geometryDidChange();
533}
534
535void PluginProxy::storageBlockingStateChanged(bool isStorageBlockingEnabled)
536{
537 m_connection->connection()->send(Messages::PluginControllerProxy::StorageBlockingStateChanged(isStorageBlockingEnabled), m_pluginInstanceID);
538}
539
540void PluginProxy::privateBrowsingStateChanged(bool isPrivateBrowsingEnabled)
541{
542 m_connection->connection()->send(Messages::PluginControllerProxy::PrivateBrowsingStateChanged(isPrivateBrowsingEnabled), m_pluginInstanceID);
543}
544
545void PluginProxy::mutedStateChanged(bool isMuted)
546{
547 m_connection->connection()->send(Messages::PluginControllerProxy::MutedStateChanged(isMuted), m_pluginInstanceID);
548}
549
550bool PluginProxy::getFormValue(String& formValue)
551{
552 bool returnValue;
553 if (!m_connection->connection()->sendSync(Messages::PluginControllerProxy::GetFormValue(), Messages::PluginControllerProxy::GetFormValue::Reply(returnValue, formValue), m_pluginInstanceID))
554 return false;
555
556 return returnValue;
557}
558
559bool PluginProxy::handleScroll(ScrollDirection, ScrollGranularity)
560{
561 return false;
562}
563
564Scrollbar* PluginProxy::horizontalScrollbar()
565{
566 return 0;
567}
568
569Scrollbar* PluginProxy::verticalScrollbar()
570{
571 return 0;
572}
573
574void PluginProxy::loadURL(uint64_t requestID, const String& method, const String& urlString, const String& target, const HTTPHeaderMap& headerFields, const Vector<uint8_t>& httpBody, bool allowPopups)
575{
576 controller()->loadURL(requestID, method, urlString, target, headerFields, httpBody, allowPopups);
577}
578
579void PluginProxy::proxiesForURL(const String& urlString, CompletionHandler<void(String)>&& completionHandler)
580{
581 completionHandler(controller()->proxiesForURL(urlString));
582}
583
584void PluginProxy::cookiesForURL(const String& urlString, CompletionHandler<void(String)>&& completionHandler)
585{
586 completionHandler(controller()->cookiesForURL(urlString));
587}
588
589void PluginProxy::setCookiesForURL(const String& urlString, const String& cookieString)
590{
591 controller()->setCookiesForURL(urlString, cookieString);
592}
593
594void PluginProxy::getAuthenticationInfo(const ProtectionSpace& protectionSpace, CompletionHandler<void(bool returnValue, String username, String password)>&& completionHandler)
595{
596 String username;
597 String password;
598 bool returnValue = controller()->getAuthenticationInfo(protectionSpace, username, password);
599 completionHandler(returnValue, username, password);
600}
601
602float PluginProxy::contentsScaleFactor()
603{
604 return controller()->contentsScaleFactor();
605}
606
607bool PluginProxy::updateBackingStore()
608{
609 if (m_pluginSize.isEmpty() || !needsBackingStore())
610 return false;
611
612 IntSize backingStoreSize = m_pluginSize;
613 backingStoreSize.scale(contentsScaleFactor());
614
615 if (m_backingStore) {
616 if (m_backingStore->size() == backingStoreSize)
617 return false;
618 m_backingStore = nullptr; // Give malloc a chance to recycle our backing store.
619 }
620
621 m_backingStore = ShareableBitmap::create(backingStoreSize, { });
622 return !!m_backingStore;
623}
624
625uint64_t PluginProxy::windowNPObjectID()
626{
627 NPObject* windowScriptNPObject = controller()->windowScriptNPObject();
628 if (!windowScriptNPObject)
629 return 0;
630
631 uint64_t windowNPObjectID = m_connection->npRemoteObjectMap()->registerNPObject(windowScriptNPObject, this);
632 releaseNPObject(windowScriptNPObject);
633
634 return windowNPObjectID;
635}
636
637IntRect PluginProxy::pluginBounds()
638{
639 return IntRect(IntPoint(), m_pluginSize);
640}
641
642void PluginProxy::getPluginElementNPObject(CompletionHandler<void(uint64_t)>&& completionHandler)
643{
644 NPObject* pluginElementNPObject = controller()->pluginElementNPObject();
645 if (!pluginElementNPObject)
646 return completionHandler(0);
647
648 uint64_t pluginElementNPObjectID = m_connection->npRemoteObjectMap()->registerNPObject(pluginElementNPObject, this);
649 releaseNPObject(pluginElementNPObject);
650 completionHandler(pluginElementNPObjectID);
651}
652
653void PluginProxy::evaluate(const NPVariantData& npObjectAsVariantData, const String& scriptString, bool allowPopups, CompletionHandler<void(bool returnValue, NPVariantData&& resultData)>&& completionHandler)
654{
655 PluginController::PluginDestructionProtector protector(controller());
656
657 NPVariant npObjectAsVariant = m_connection->npRemoteObjectMap()->npVariantDataToNPVariant(npObjectAsVariantData, this);
658 if (!NPVARIANT_IS_OBJECT(npObjectAsVariant) || !(NPVARIANT_TO_OBJECT(npObjectAsVariant)))
659 return completionHandler(false, { });
660
661 NPVariant result;
662 bool returnValue = controller()->evaluate(NPVARIANT_TO_OBJECT(npObjectAsVariant), scriptString, &result, allowPopups);
663 if (!returnValue)
664 return completionHandler(false, { });
665
666 // Convert the NPVariant to an NPVariantData.
667 NPVariantData resultData = m_connection->npRemoteObjectMap()->npVariantToNPVariantData(result, this);
668
669 // And release the result.
670 releaseNPVariantValue(&result);
671 releaseNPVariantValue(&npObjectAsVariant);
672
673 completionHandler(returnValue, WTFMove(resultData));
674}
675
676void PluginProxy::setPluginIsPlayingAudio(bool pluginIsPlayingAudio)
677{
678 controller()->setPluginIsPlayingAudio(pluginIsPlayingAudio);
679}
680
681void PluginProxy::continueStreamLoad(uint64_t streamID)
682{
683 controller()->continueStreamLoad(streamID);
684}
685
686void PluginProxy::cancelStreamLoad(uint64_t streamID)
687{
688 controller()->cancelStreamLoad(streamID);
689}
690
691void PluginProxy::cancelManualStreamLoad()
692{
693 controller()->cancelManualStreamLoad();
694}
695
696void PluginProxy::setStatusbarText(const String& statusbarText)
697{
698 controller()->setStatusbarText(statusbarText);
699}
700
701#if PLATFORM(X11)
702void PluginProxy::createPluginContainer(CompletionHandler<void(uint64_t windowID)>&& completionHandler)
703{
704 completionHandler(controller()->createPluginContainer());
705}
706
707void PluginProxy::windowedPluginGeometryDidChange(const WebCore::IntRect& frameRect, const WebCore::IntRect& clipRect, uint64_t windowID)
708{
709 controller()->windowedPluginGeometryDidChange(frameRect, clipRect, windowID);
710}
711
712void PluginProxy::windowedPluginVisibilityDidChange(bool isVisible, uint64_t windowID)
713{
714 controller()->windowedPluginVisibilityDidChange(isVisible, windowID);
715}
716#endif
717
718void PluginProxy::update(const IntRect& paintedRect)
719{
720 if (paintedRect == pluginBounds())
721 m_pluginBackingStoreContainsValidData = true;
722
723 if (m_backingStore) {
724 // Blit the plug-in backing store into our own backing store.
725 auto graphicsContext = m_backingStore->createGraphicsContext();
726 graphicsContext->applyDeviceScaleFactor(contentsScaleFactor());
727 graphicsContext->setCompositeOperation(CompositeCopy);
728 m_pluginBackingStore->paint(*graphicsContext, contentsScaleFactor(), paintedRect.location(), paintedRect);
729 }
730
731 // Ask the controller to invalidate the rect for us.
732 m_waitingForPaintInResponseToUpdate = true;
733 controller()->invalidate(paintedRect);
734}
735
736IntPoint PluginProxy::convertToRootView(const IntPoint& point) const
737{
738 return m_pluginToRootViewTransform.mapPoint(point);
739}
740
741RefPtr<WebCore::SharedBuffer> PluginProxy::liveResourceData() const
742{
743 return nullptr;
744}
745
746} // namespace WebKit
747
748#endif // ENABLE(NETSCAPE_PLUGIN_API)
749