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