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 | |
48 | namespace WebKit { |
49 | using namespace WebCore; |
50 | |
51 | static uint64_t generatePluginInstanceID() |
52 | { |
53 | static uint64_t uniquePluginInstanceID; |
54 | return ++uniquePluginInstanceID; |
55 | } |
56 | |
57 | Ref<PluginProxy> PluginProxy::create(uint64_t pluginProcessToken, bool isRestartedProcess) |
58 | { |
59 | return adoptRef(*new PluginProxy(pluginProcessToken, isRestartedProcess)); |
60 | } |
61 | |
62 | PluginProxy::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 | |
76 | PluginProxy::~PluginProxy() |
77 | { |
78 | } |
79 | |
80 | void PluginProxy::pluginProcessCrashed() |
81 | { |
82 | controller()->pluginProcessCrashed(); |
83 | } |
84 | |
85 | bool 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 | |
120 | bool PluginProxy::canInitializeAsynchronously() const |
121 | { |
122 | return controller()->asynchronousPluginInitializationEnabled() && (m_connection->supportsAsynchronousPluginInitialization() || controller()->asynchronousPluginInitializationEnabledForAllPlugins()); |
123 | } |
124 | |
125 | bool 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 | |
144 | void 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 | |
155 | void 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 | |
166 | void 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 | |
179 | void 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 | |
193 | void 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 | |
206 | void 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 | |
232 | bool 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 | |
244 | RefPtr<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 | |
255 | bool PluginProxy::isTransparent() |
256 | { |
257 | // This should never be called from the web process. |
258 | ASSERT_NOT_REACHED(); |
259 | return false; |
260 | } |
261 | |
262 | bool PluginProxy::wantsWheelEvents() |
263 | { |
264 | return m_wantsWheelEvents; |
265 | } |
266 | |
267 | void 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 | |
291 | void 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 | |
305 | void PluginProxy::visibilityDidChange(bool isVisible) |
306 | { |
307 | ASSERT(m_isStarted); |
308 | m_connection->connection()->send(Messages::PluginControllerProxy::VisibilityDidChange(isVisible), m_pluginInstanceID); |
309 | } |
310 | |
311 | void PluginProxy::frameDidFinishLoading(uint64_t requestID) |
312 | { |
313 | m_connection->connection()->send(Messages::PluginControllerProxy::FrameDidFinishLoading(requestID), m_pluginInstanceID); |
314 | } |
315 | |
316 | void PluginProxy::frameDidFail(uint64_t requestID, bool wasCancelled) |
317 | { |
318 | m_connection->connection()->send(Messages::PluginControllerProxy::FrameDidFail(requestID, wasCancelled), m_pluginInstanceID); |
319 | } |
320 | |
321 | void PluginProxy::didEvaluateJavaScript(uint64_t requestID, const WTF::String& result) |
322 | { |
323 | m_connection->connection()->send(Messages::PluginControllerProxy::DidEvaluateJavaScript(requestID, result), m_pluginInstanceID); |
324 | } |
325 | |
326 | void 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 | |
331 | void PluginProxy::streamDidReceiveResponse(uint64_t streamID, const URL& responseURL, uint32_t streamLength, uint32_t lastModifiedTime, const WTF::String& mimeType, const WTF::String& , const String& /* suggestedFileName */) |
332 | { |
333 | m_connection->connection()->send(Messages::PluginControllerProxy::StreamDidReceiveResponse(streamID, responseURL.string(), streamLength, lastModifiedTime, mimeType, headers), m_pluginInstanceID); |
334 | } |
335 | |
336 | void 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 | |
341 | void PluginProxy::streamDidFinishLoading(uint64_t streamID) |
342 | { |
343 | m_connection->connection()->send(Messages::PluginControllerProxy::StreamDidFinishLoading(streamID), m_pluginInstanceID); |
344 | } |
345 | |
346 | void PluginProxy::streamDidFail(uint64_t streamID, bool wasCancelled) |
347 | { |
348 | m_connection->connection()->send(Messages::PluginControllerProxy::StreamDidFail(streamID, wasCancelled), m_pluginInstanceID); |
349 | } |
350 | |
351 | void PluginProxy::manualStreamDidReceiveResponse(const URL& responseURL, uint32_t streamLength, uint32_t lastModifiedTime, const WTF::String& mimeType, const WTF::String& , const String& /* suggestedFileName */) |
352 | { |
353 | m_connection->connection()->send(Messages::PluginControllerProxy::ManualStreamDidReceiveResponse(responseURL.string(), streamLength, lastModifiedTime, mimeType, headers), m_pluginInstanceID); |
354 | } |
355 | |
356 | void 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 | |
361 | void PluginProxy::manualStreamDidFinishLoading() |
362 | { |
363 | m_connection->connection()->send(Messages::PluginControllerProxy::ManualStreamDidFinishLoading(), m_pluginInstanceID); |
364 | } |
365 | |
366 | void PluginProxy::manualStreamDidFail(bool wasCancelled) |
367 | { |
368 | m_connection->connection()->send(Messages::PluginControllerProxy::ManualStreamDidFail(wasCancelled), m_pluginInstanceID); |
369 | } |
370 | |
371 | bool 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 | |
380 | bool 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 | |
392 | bool 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 | |
404 | bool 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 | |
416 | bool 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 | |
422 | bool 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 | |
434 | void PluginProxy::setFocus(bool hasFocus) |
435 | { |
436 | m_connection->connection()->send(Messages::PluginControllerProxy::SetFocus(hasFocus), m_pluginInstanceID); |
437 | } |
438 | |
439 | bool 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 | |
451 | bool 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 | |
463 | bool 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 | |
475 | bool 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 | |
487 | NPObject* 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 | |
504 | void PluginProxy::windowFocusChanged(bool hasFocus) |
505 | { |
506 | m_connection->connection()->send(Messages::PluginControllerProxy::WindowFocusChanged(hasFocus), m_pluginInstanceID); |
507 | } |
508 | |
509 | void PluginProxy::windowVisibilityChanged(bool isVisible) |
510 | { |
511 | m_connection->connection()->send(Messages::PluginControllerProxy::WindowVisibilityChanged(isVisible), m_pluginInstanceID); |
512 | } |
513 | |
514 | #if PLATFORM(COCOA) |
515 | void PluginProxy::windowAndViewFramesChanged(const WebCore::IntRect& windowFrameInScreenCoordinates, const WebCore::IntRect& viewFrameInWindowCoordinates) |
516 | { |
517 | m_connection->connection()->send(Messages::PluginControllerProxy::WindowAndViewFramesChanged(windowFrameInScreenCoordinates, viewFrameInWindowCoordinates), m_pluginInstanceID); |
518 | } |
519 | uint64_t PluginProxy::pluginComplexTextInputIdentifier() const |
520 | { |
521 | return m_pluginInstanceID; |
522 | } |
523 | |
524 | void PluginProxy::sendComplexTextInput(const String& textInput) |
525 | { |
526 | m_connection->connection()->send(Messages::PluginControllerProxy::SendComplexTextInput(textInput), m_pluginInstanceID); |
527 | } |
528 | #endif |
529 | |
530 | void PluginProxy::contentsScaleFactorChanged(float) |
531 | { |
532 | geometryDidChange(); |
533 | } |
534 | |
535 | void PluginProxy::storageBlockingStateChanged(bool isStorageBlockingEnabled) |
536 | { |
537 | m_connection->connection()->send(Messages::PluginControllerProxy::StorageBlockingStateChanged(isStorageBlockingEnabled), m_pluginInstanceID); |
538 | } |
539 | |
540 | void PluginProxy::privateBrowsingStateChanged(bool isPrivateBrowsingEnabled) |
541 | { |
542 | m_connection->connection()->send(Messages::PluginControllerProxy::PrivateBrowsingStateChanged(isPrivateBrowsingEnabled), m_pluginInstanceID); |
543 | } |
544 | |
545 | void PluginProxy::mutedStateChanged(bool isMuted) |
546 | { |
547 | m_connection->connection()->send(Messages::PluginControllerProxy::MutedStateChanged(isMuted), m_pluginInstanceID); |
548 | } |
549 | |
550 | bool 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 | |
559 | bool PluginProxy::handleScroll(ScrollDirection, ScrollGranularity) |
560 | { |
561 | return false; |
562 | } |
563 | |
564 | Scrollbar* PluginProxy::horizontalScrollbar() |
565 | { |
566 | return 0; |
567 | } |
568 | |
569 | Scrollbar* PluginProxy::verticalScrollbar() |
570 | { |
571 | return 0; |
572 | } |
573 | |
574 | void PluginProxy::(uint64_t requestID, const String& method, const String& urlString, const String& target, const HTTPHeaderMap& , const Vector<uint8_t>& httpBody, bool ) |
575 | { |
576 | controller()->loadURL(requestID, method, urlString, target, headerFields, httpBody, allowPopups); |
577 | } |
578 | |
579 | void PluginProxy::proxiesForURL(const String& urlString, CompletionHandler<void(String)>&& completionHandler) |
580 | { |
581 | completionHandler(controller()->proxiesForURL(urlString)); |
582 | } |
583 | |
584 | void PluginProxy::cookiesForURL(const String& urlString, CompletionHandler<void(String)>&& completionHandler) |
585 | { |
586 | completionHandler(controller()->cookiesForURL(urlString)); |
587 | } |
588 | |
589 | void PluginProxy::setCookiesForURL(const String& urlString, const String& cookieString) |
590 | { |
591 | controller()->setCookiesForURL(urlString, cookieString); |
592 | } |
593 | |
594 | void 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 | |
602 | float PluginProxy::contentsScaleFactor() |
603 | { |
604 | return controller()->contentsScaleFactor(); |
605 | } |
606 | |
607 | bool 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 | |
625 | uint64_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 | |
637 | IntRect PluginProxy::pluginBounds() |
638 | { |
639 | return IntRect(IntPoint(), m_pluginSize); |
640 | } |
641 | |
642 | void 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 | |
653 | void PluginProxy::evaluate(const NPVariantData& npObjectAsVariantData, const String& scriptString, bool , 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 | |
676 | void PluginProxy::setPluginIsPlayingAudio(bool pluginIsPlayingAudio) |
677 | { |
678 | controller()->setPluginIsPlayingAudio(pluginIsPlayingAudio); |
679 | } |
680 | |
681 | void PluginProxy::continueStreamLoad(uint64_t streamID) |
682 | { |
683 | controller()->continueStreamLoad(streamID); |
684 | } |
685 | |
686 | void PluginProxy::cancelStreamLoad(uint64_t streamID) |
687 | { |
688 | controller()->cancelStreamLoad(streamID); |
689 | } |
690 | |
691 | void PluginProxy::cancelManualStreamLoad() |
692 | { |
693 | controller()->cancelManualStreamLoad(); |
694 | } |
695 | |
696 | void PluginProxy::setStatusbarText(const String& statusbarText) |
697 | { |
698 | controller()->setStatusbarText(statusbarText); |
699 | } |
700 | |
701 | #if PLATFORM(X11) |
702 | void PluginProxy::createPluginContainer(CompletionHandler<void(uint64_t windowID)>&& completionHandler) |
703 | { |
704 | completionHandler(controller()->createPluginContainer()); |
705 | } |
706 | |
707 | void PluginProxy::windowedPluginGeometryDidChange(const WebCore::IntRect& frameRect, const WebCore::IntRect& clipRect, uint64_t windowID) |
708 | { |
709 | controller()->windowedPluginGeometryDidChange(frameRect, clipRect, windowID); |
710 | } |
711 | |
712 | void PluginProxy::windowedPluginVisibilityDidChange(bool isVisible, uint64_t windowID) |
713 | { |
714 | controller()->windowedPluginVisibilityDidChange(isVisible, windowID); |
715 | } |
716 | #endif |
717 | |
718 | void 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 | |
736 | IntPoint PluginProxy::convertToRootView(const IntPoint& point) const |
737 | { |
738 | return m_pluginToRootViewTransform.mapPoint(point); |
739 | } |
740 | |
741 | RefPtr<WebCore::SharedBuffer> PluginProxy::liveResourceData() const |
742 | { |
743 | return nullptr; |
744 | } |
745 | |
746 | } // namespace WebKit |
747 | |
748 | #endif // ENABLE(NETSCAPE_PLUGIN_API) |
749 | |