Home | History | Annotate | Download | only in Plugins
      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 "PluginProcessConnection.h"
     38 #include "PluginProcessConnectionManager.h"
     39 #include "ShareableBitmap.h"
     40 #include "WebCoreArgumentCoders.h"
     41 #include "WebEvent.h"
     42 #include "WebProcessConnectionMessages.h"
     43 #include <WebCore/GraphicsContext.h>
     44 
     45 using namespace WebCore;
     46 
     47 namespace WebKit {
     48 
     49 static uint64_t generatePluginInstanceID()
     50 {
     51     static uint64_t uniquePluginInstanceID;
     52     return ++uniquePluginInstanceID;
     53 }
     54 
     55 PassRefPtr<PluginProxy> PluginProxy::create(const String& pluginPath)
     56 {
     57     return adoptRef(new PluginProxy(pluginPath));
     58 }
     59 
     60 PluginProxy::PluginProxy(const String& pluginPath)
     61     : m_pluginPath(pluginPath)
     62     , m_pluginInstanceID(generatePluginInstanceID())
     63     , m_pluginController(0)
     64     , m_pluginBackingStoreContainsValidData(false)
     65     , m_isStarted(false)
     66     , m_waitingForPaintInResponseToUpdate(false)
     67     , m_remoteLayerClientID(0)
     68 {
     69 }
     70 
     71 PluginProxy::~PluginProxy()
     72 {
     73 }
     74 
     75 void PluginProxy::pluginProcessCrashed()
     76 {
     77     if (m_pluginController)
     78         m_pluginController->pluginProcessCrashed();
     79 }
     80 
     81 bool PluginProxy::initialize(PluginController* pluginController, const Parameters& parameters)
     82 {
     83     ASSERT(!m_pluginController);
     84     ASSERT(pluginController);
     85 
     86     m_pluginController = pluginController;
     87 
     88     ASSERT(!m_connection);
     89     m_connection = PluginProcessConnectionManager::shared().getPluginProcessConnection(m_pluginPath);
     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     bool result = false;
    100 
    101     uint32_t remoteLayerClientID = 0;
    102     if (!m_connection->connection()->sendSync(Messages::WebProcessConnection::CreatePlugin(m_pluginInstanceID, parameters, pluginController->userAgent(), pluginController->isPrivateBrowsingEnabled(), pluginController->isAcceleratedCompositingEnabled()), Messages::WebProcessConnection::CreatePlugin::Reply(result, remoteLayerClientID), 0) || !result) {
    103         m_connection->removePluginProxy(this);
    104         return false;
    105     }
    106 
    107     m_remoteLayerClientID = remoteLayerClientID;
    108     m_isStarted = true;
    109 
    110     return true;
    111 }
    112 
    113 void PluginProxy::destroy()
    114 {
    115     ASSERT(m_isStarted);
    116 
    117     m_connection->connection()->sendSync(Messages::WebProcessConnection::DestroyPlugin(m_pluginInstanceID), Messages::WebProcessConnection::DestroyPlugin::Reply(), 0);
    118 
    119     m_isStarted = false;
    120     m_pluginController = 0;
    121 
    122     m_connection->removePluginProxy(this);
    123 }
    124 
    125 void PluginProxy::paint(GraphicsContext* graphicsContext, const IntRect& dirtyRect)
    126 {
    127     if (!needsBackingStore() || !m_backingStore)
    128         return;
    129 
    130     if (!m_pluginBackingStoreContainsValidData) {
    131         m_connection->connection()->sendSync(Messages::PluginControllerProxy::PaintEntirePlugin(), Messages::PluginControllerProxy::PaintEntirePlugin::Reply(), m_pluginInstanceID);
    132 
    133         // Blit the plug-in backing store into our own backing store.
    134         OwnPtr<WebCore::GraphicsContext> graphicsContext = m_backingStore->createGraphicsContext();
    135         graphicsContext->setCompositeOperation(CompositeCopy);
    136 
    137         m_pluginBackingStore->paint(*graphicsContext, IntPoint(), IntRect(0, 0, m_frameRect.width(), m_frameRect.height()));
    138 
    139         m_pluginBackingStoreContainsValidData = true;
    140     }
    141 
    142     IntRect dirtyRectInPluginCoordinates = dirtyRect;
    143     dirtyRectInPluginCoordinates.move(-m_frameRect.x(), -m_frameRect.y());
    144 
    145     m_backingStore->paint(*graphicsContext, dirtyRect.location(), dirtyRectInPluginCoordinates);
    146 
    147     if (m_waitingForPaintInResponseToUpdate) {
    148         m_waitingForPaintInResponseToUpdate = false;
    149         m_connection->connection()->send(Messages::PluginControllerProxy::DidUpdate(), m_pluginInstanceID);
    150         return;
    151     }
    152 }
    153 
    154 PassRefPtr<ShareableBitmap> PluginProxy::snapshot()
    155 {
    156     ShareableBitmap::Handle snapshotStoreHandle;
    157     m_connection->connection()->sendSync(Messages::PluginControllerProxy::Snapshot(), Messages::PluginControllerProxy::Snapshot::Reply(snapshotStoreHandle), m_pluginInstanceID);
    158 
    159     RefPtr<ShareableBitmap> snapshotBuffer = ShareableBitmap::create(snapshotStoreHandle);
    160     return snapshotBuffer.release();
    161 }
    162 
    163 bool PluginProxy::isTransparent()
    164 {
    165     // This should never be called from the web process.
    166     ASSERT_NOT_REACHED();
    167     return false;
    168 }
    169 
    170 void PluginProxy::geometryDidChange(const IntRect& frameRect, const IntRect& clipRect)
    171 {
    172     ASSERT(m_isStarted);
    173 
    174     m_frameRect = frameRect;
    175 
    176     if (!needsBackingStore()) {
    177         ShareableBitmap::Handle pluginBackingStoreHandle;
    178         m_connection->connection()->send(Messages::PluginControllerProxy::GeometryDidChange(frameRect, clipRect, pluginBackingStoreHandle), m_pluginInstanceID, CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply);
    179         return;
    180     }
    181 
    182     bool didUpdateBackingStore = false;
    183     if (!m_backingStore) {
    184         m_backingStore = ShareableBitmap::create(frameRect.size(), ShareableBitmap::SupportsAlpha);
    185         didUpdateBackingStore = true;
    186     } else if (frameRect.size() != m_backingStore->size()) {
    187         // The backing store already exists, just resize it.
    188         if (!m_backingStore->resize(frameRect.size()))
    189             return;
    190 
    191         didUpdateBackingStore = true;
    192     }
    193 
    194     ShareableBitmap::Handle pluginBackingStoreHandle;
    195 
    196     if (didUpdateBackingStore) {
    197         // Create a new plug-in backing store.
    198         m_pluginBackingStore = ShareableBitmap::createShareable(frameRect.size(), ShareableBitmap::SupportsAlpha);
    199         if (!m_pluginBackingStore)
    200             return;
    201 
    202         // Create a handle to the plug-in backing store so we can send it over.
    203         if (!m_pluginBackingStore->createHandle(pluginBackingStoreHandle)) {
    204             m_pluginBackingStore = nullptr;
    205             return;
    206         }
    207 
    208         m_pluginBackingStoreContainsValidData = false;
    209     }
    210 
    211     m_connection->connection()->send(Messages::PluginControllerProxy::GeometryDidChange(frameRect, clipRect, pluginBackingStoreHandle), m_pluginInstanceID, CoreIPC::DispatchMessageEvenWhenWaitingForSyncReply);
    212 }
    213 
    214 void PluginProxy::frameDidFinishLoading(uint64_t requestID)
    215 {
    216     m_connection->connection()->send(Messages::PluginControllerProxy::FrameDidFinishLoading(requestID), m_pluginInstanceID);
    217 }
    218 
    219 void PluginProxy::frameDidFail(uint64_t requestID, bool wasCancelled)
    220 {
    221     m_connection->connection()->send(Messages::PluginControllerProxy::FrameDidFail(requestID, wasCancelled), m_pluginInstanceID);
    222 }
    223 
    224 void PluginProxy::didEvaluateJavaScript(uint64_t requestID, const WTF::String& requestURLString, const WTF::String& result)
    225 {
    226     m_connection->connection()->send(Messages::PluginControllerProxy::DidEvaluateJavaScript(requestID, requestURLString, result), m_pluginInstanceID);
    227 }
    228 
    229 void PluginProxy::streamDidReceiveResponse(uint64_t streamID, const KURL& responseURL, uint32_t streamLength, uint32_t lastModifiedTime, const WTF::String& mimeType, const WTF::String& headers)
    230 {
    231     m_connection->connection()->send(Messages::PluginControllerProxy::StreamDidReceiveResponse(streamID, responseURL.string(), streamLength, lastModifiedTime, mimeType, headers), m_pluginInstanceID);
    232 }
    233 
    234 void PluginProxy::streamDidReceiveData(uint64_t streamID, const char* bytes, int length)
    235 {
    236     m_connection->connection()->send(Messages::PluginControllerProxy::StreamDidReceiveData(streamID, CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(bytes), length)), m_pluginInstanceID);
    237 }
    238 
    239 void PluginProxy::streamDidFinishLoading(uint64_t streamID)
    240 {
    241     m_connection->connection()->send(Messages::PluginControllerProxy::StreamDidFinishLoading(streamID), m_pluginInstanceID);
    242 }
    243 
    244 void PluginProxy::streamDidFail(uint64_t streamID, bool wasCancelled)
    245 {
    246     m_connection->connection()->send(Messages::PluginControllerProxy::StreamDidFail(streamID, wasCancelled), m_pluginInstanceID);
    247 }
    248 
    249 void PluginProxy::manualStreamDidReceiveResponse(const KURL& responseURL, uint32_t streamLength,  uint32_t lastModifiedTime, const WTF::String& mimeType, const WTF::String& headers)
    250 {
    251     m_connection->connection()->send(Messages::PluginControllerProxy::ManualStreamDidReceiveResponse(responseURL.string(), streamLength, lastModifiedTime, mimeType, headers), m_pluginInstanceID);
    252 }
    253 
    254 void PluginProxy::manualStreamDidReceiveData(const char* bytes, int length)
    255 {
    256     m_connection->connection()->send(Messages::PluginControllerProxy::ManualStreamDidReceiveData(CoreIPC::DataReference(reinterpret_cast<const uint8_t*>(bytes), length)), m_pluginInstanceID);
    257 }
    258 
    259 void PluginProxy::manualStreamDidFinishLoading()
    260 {
    261     m_connection->connection()->send(Messages::PluginControllerProxy::ManualStreamDidFinishLoading(), m_pluginInstanceID);
    262 }
    263 
    264 void PluginProxy::manualStreamDidFail(bool wasCancelled)
    265 {
    266     m_connection->connection()->send(Messages::PluginControllerProxy::ManualStreamDidFail(wasCancelled), m_pluginInstanceID);
    267 }
    268 
    269 bool PluginProxy::handleMouseEvent(const WebMouseEvent& mouseEvent)
    270 {
    271     bool handled = false;
    272     if (!m_connection->connection()->sendSync(Messages::PluginControllerProxy::HandleMouseEvent(mouseEvent), Messages::PluginControllerProxy::HandleMouseEvent::Reply(handled), m_pluginInstanceID))
    273         return false;
    274 
    275     return handled;
    276 }
    277 
    278 bool PluginProxy::handleWheelEvent(const WebWheelEvent& wheelEvent)
    279 {
    280     bool handled = false;
    281     if (!m_connection->connection()->sendSync(Messages::PluginControllerProxy::HandleWheelEvent(wheelEvent), Messages::PluginControllerProxy::HandleWheelEvent::Reply(handled), m_pluginInstanceID))
    282         return false;
    283 
    284     return handled;
    285 }
    286 
    287 bool PluginProxy::handleMouseEnterEvent(const WebMouseEvent& mouseEnterEvent)
    288 {
    289     bool handled = false;
    290     if (!m_connection->connection()->sendSync(Messages::PluginControllerProxy::HandleMouseEnterEvent(mouseEnterEvent), Messages::PluginControllerProxy::HandleMouseEnterEvent::Reply(handled), m_pluginInstanceID))
    291         return false;
    292 
    293     return handled;
    294 }
    295 
    296 bool PluginProxy::handleMouseLeaveEvent(const WebMouseEvent& mouseLeaveEvent)
    297 {
    298     bool handled = false;
    299     if (!m_connection->connection()->sendSync(Messages::PluginControllerProxy::HandleMouseLeaveEvent(mouseLeaveEvent), Messages::PluginControllerProxy::HandleMouseLeaveEvent::Reply(handled), m_pluginInstanceID))
    300         return false;
    301 
    302     return handled;
    303 }
    304 
    305 bool PluginProxy::handleKeyboardEvent(const WebKeyboardEvent& keyboardEvent)
    306 {
    307     bool handled = false;
    308     if (!m_connection->connection()->sendSync(Messages::PluginControllerProxy::HandleKeyboardEvent(keyboardEvent), Messages::PluginControllerProxy::HandleKeyboardEvent::Reply(handled), m_pluginInstanceID))
    309         return false;
    310 
    311     return handled;
    312 }
    313 
    314 void PluginProxy::setFocus(bool hasFocus)
    315 {
    316     m_connection->connection()->send(Messages::PluginControllerProxy::SetFocus(hasFocus), m_pluginInstanceID);
    317 }
    318 
    319 NPObject* PluginProxy::pluginScriptableNPObject()
    320 {
    321     uint64_t pluginScriptableNPObjectID = 0;
    322 
    323     if (!m_connection->connection()->sendSync(Messages::PluginControllerProxy::GetPluginScriptableNPObject(), Messages::PluginControllerProxy::GetPluginScriptableNPObject::Reply(pluginScriptableNPObjectID), m_pluginInstanceID))
    324         return 0;
    325 
    326     if (!pluginScriptableNPObjectID)
    327         return 0;
    328 
    329     return m_connection->npRemoteObjectMap()->createNPObjectProxy(pluginScriptableNPObjectID, this);
    330 }
    331 
    332 #if PLATFORM(MAC)
    333 void PluginProxy::windowFocusChanged(bool hasFocus)
    334 {
    335     m_connection->connection()->send(Messages::PluginControllerProxy::WindowFocusChanged(hasFocus), m_pluginInstanceID);
    336 }
    337 
    338 void PluginProxy::windowAndViewFramesChanged(const WebCore::IntRect& windowFrameInScreenCoordinates, const WebCore::IntRect& viewFrameInWindowCoordinates)
    339 {
    340     m_connection->connection()->send(Messages::PluginControllerProxy::WindowAndViewFramesChanged(windowFrameInScreenCoordinates, viewFrameInWindowCoordinates), m_pluginInstanceID);
    341 }
    342 
    343 void PluginProxy::windowVisibilityChanged(bool isVisible)
    344 {
    345     m_connection->connection()->send(Messages::PluginControllerProxy::WindowVisibilityChanged(isVisible), m_pluginInstanceID);
    346 }
    347 
    348 uint64_t PluginProxy::pluginComplexTextInputIdentifier() const
    349 {
    350     return m_pluginInstanceID;
    351 }
    352 
    353 void PluginProxy::sendComplexTextInput(const String& textInput)
    354 {
    355     m_connection->connection()->send(Messages::PluginControllerProxy::SendComplexTextInput(textInput), m_pluginInstanceID);
    356 }
    357 
    358 #endif
    359 
    360 void PluginProxy::privateBrowsingStateChanged(bool isPrivateBrowsingEnabled)
    361 {
    362     m_connection->connection()->send(Messages::PluginControllerProxy::PrivateBrowsingStateChanged(isPrivateBrowsingEnabled), m_pluginInstanceID);
    363 }
    364 
    365 PluginController* PluginProxy::controller()
    366 {
    367     return m_pluginController;
    368 }
    369 
    370 void PluginProxy::loadURL(uint64_t requestID, const String& method, const String& urlString, const String& target, const HTTPHeaderMap& headerFields, const Vector<uint8_t>& httpBody, bool allowPopups)
    371 {
    372     m_pluginController->loadURL(requestID, method, urlString, target, headerFields, httpBody, allowPopups);
    373 }
    374 
    375 void PluginProxy::proxiesForURL(const String& urlString, String& proxyString)
    376 {
    377     proxyString = m_pluginController->proxiesForURL(urlString);
    378 }
    379 
    380 void PluginProxy::cookiesForURL(const String& urlString, String& cookieString)
    381 {
    382     cookieString = m_pluginController->cookiesForURL(urlString);
    383 }
    384 
    385 void PluginProxy::setCookiesForURL(const String& urlString, const String& cookieString)
    386 {
    387     m_pluginController->setCookiesForURL(urlString, cookieString);
    388 }
    389 
    390 void PluginProxy::getWindowScriptNPObject(uint64_t& windowScriptNPObjectID)
    391 {
    392     NPObject* windowScriptNPObject = m_pluginController->windowScriptNPObject();
    393     if (!windowScriptNPObject) {
    394         windowScriptNPObjectID = 0;
    395         return;
    396     }
    397 
    398     windowScriptNPObjectID = m_connection->npRemoteObjectMap()->registerNPObject(windowScriptNPObject, this);
    399     releaseNPObject(windowScriptNPObject);
    400 }
    401 
    402 void PluginProxy::getPluginElementNPObject(uint64_t& pluginElementNPObjectID)
    403 {
    404     NPObject* pluginElementNPObject = m_pluginController->pluginElementNPObject();
    405     if (!pluginElementNPObject) {
    406         pluginElementNPObjectID = 0;
    407         return;
    408     }
    409 
    410     pluginElementNPObjectID = m_connection->npRemoteObjectMap()->registerNPObject(pluginElementNPObject, this);
    411     releaseNPObject(pluginElementNPObject);
    412 }
    413 
    414 void PluginProxy::evaluate(const NPVariantData& npObjectAsVariantData, const String& scriptString, bool allowPopups, bool& returnValue, NPVariantData& resultData)
    415 {
    416     PluginController::PluginDestructionProtector protector(m_pluginController);
    417 
    418     NPVariant npObjectAsVariant = m_connection->npRemoteObjectMap()->npVariantDataToNPVariant(npObjectAsVariantData, this);
    419     if (!NPVARIANT_IS_OBJECT(npObjectAsVariant) || !(NPVARIANT_TO_OBJECT(npObjectAsVariant))) {
    420         returnValue = false;
    421         return;
    422     }
    423 
    424     NPVariant result;
    425     returnValue = m_pluginController->evaluate(NPVARIANT_TO_OBJECT(npObjectAsVariant), scriptString, &result, allowPopups);
    426     if (!returnValue)
    427         return;
    428 
    429     // Convert the NPVariant to an NPVariantData.
    430     resultData = m_connection->npRemoteObjectMap()->npVariantToNPVariantData(result, this);
    431 
    432     // And release the result.
    433     releaseNPVariantValue(&result);
    434 
    435     releaseNPVariantValue(&npObjectAsVariant);
    436 }
    437 
    438 void PluginProxy::cancelStreamLoad(uint64_t streamID)
    439 {
    440     m_pluginController->cancelStreamLoad(streamID);
    441 }
    442 
    443 void PluginProxy::cancelManualStreamLoad()
    444 {
    445     m_pluginController->cancelManualStreamLoad();
    446 }
    447 
    448 void PluginProxy::setStatusbarText(const String& statusbarText)
    449 {
    450     m_pluginController->setStatusbarText(statusbarText);
    451 }
    452 
    453 #if PLATFORM(MAC)
    454 void PluginProxy::setComplexTextInputEnabled(bool complexTextInputEnabled)
    455 {
    456     m_pluginController->setComplexTextInputEnabled(complexTextInputEnabled);
    457 }
    458 #endif
    459 
    460 void PluginProxy::update(const IntRect& paintedRect)
    461 {
    462     if (paintedRect == m_frameRect)
    463         m_pluginBackingStoreContainsValidData = true;
    464 
    465     IntRect paintedRectPluginCoordinates = paintedRect;
    466     paintedRectPluginCoordinates.move(-m_frameRect.x(), -m_frameRect.y());
    467 
    468     if (m_backingStore) {
    469         // Blit the plug-in backing store into our own backing store.
    470         OwnPtr<GraphicsContext> graphicsContext = m_backingStore->createGraphicsContext();
    471         graphicsContext->setCompositeOperation(CompositeCopy);
    472         m_pluginBackingStore->paint(*graphicsContext, paintedRectPluginCoordinates.location(),
    473                                     paintedRectPluginCoordinates);
    474     }
    475 
    476     // Ask the controller to invalidate the rect for us.
    477     m_waitingForPaintInResponseToUpdate = true;
    478     m_pluginController->invalidate(paintedRectPluginCoordinates);
    479 }
    480 
    481 } // namespace WebKit
    482 
    483 #endif // ENABLE(PLUGIN_PROCESS)
    484