michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: sw=4 ts=4 et : michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "mozilla/DebugOnly.h" michael@0: #include // for intptr_t michael@0: michael@0: #include "PluginInstanceParent.h" michael@0: #include "BrowserStreamParent.h" michael@0: #include "PluginBackgroundDestroyer.h" michael@0: #include "PluginModuleParent.h" michael@0: #include "PluginStreamParent.h" michael@0: #include "StreamNotifyParent.h" michael@0: #include "npfunctions.h" michael@0: #include "nsAutoPtr.h" michael@0: #include "gfxASurface.h" michael@0: #include "gfxContext.h" michael@0: #include "gfxPlatform.h" michael@0: #include "gfxSharedImageSurface.h" michael@0: #include "nsNPAPIPluginInstance.h" michael@0: #ifdef MOZ_X11 michael@0: #include "gfxXlibSurface.h" michael@0: #endif michael@0: #include "gfxContext.h" michael@0: #include "gfxColor.h" michael@0: #include "gfxUtils.h" michael@0: #include "mozilla/gfx/2D.h" michael@0: #include "Layers.h" michael@0: #include "SharedTextureImage.h" michael@0: #include "GLContext.h" michael@0: #include "GLContextProvider.h" michael@0: michael@0: #ifdef XP_MACOSX michael@0: #include "MacIOSurfaceImage.h" michael@0: #endif michael@0: michael@0: #if defined(OS_WIN) michael@0: #include michael@0: #include "gfxWindowsPlatform.h" michael@0: #include "mozilla/plugins/PluginSurfaceParent.h" michael@0: michael@0: // Plugin focus event for widget. michael@0: extern const wchar_t* kOOPPPluginFocusEventId; michael@0: UINT gOOPPPluginFocusEvent = michael@0: RegisterWindowMessage(kOOPPPluginFocusEventId); michael@0: extern const wchar_t* kFlashFullscreenClass; michael@0: #elif defined(MOZ_WIDGET_GTK) michael@0: #include michael@0: #elif defined(XP_MACOSX) michael@0: #include michael@0: #endif // defined(XP_MACOSX) michael@0: michael@0: using namespace mozilla::plugins; michael@0: using namespace mozilla::layers; michael@0: using namespace mozilla::gl; michael@0: michael@0: bool michael@0: StreamNotifyParent::RecvRedirectNotifyResponse(const bool& allow) michael@0: { michael@0: PluginInstanceParent* instance = static_cast(Manager()); michael@0: instance->mNPNIface->urlredirectresponse(instance->mNPP, this, static_cast(allow)); michael@0: return true; michael@0: } michael@0: michael@0: PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent, michael@0: NPP npp, michael@0: const nsCString& aMimeType, michael@0: const NPNetscapeFuncs* npniface) michael@0: : mParent(parent) michael@0: , mNPP(npp) michael@0: , mNPNIface(npniface) michael@0: , mWindowType(NPWindowTypeWindow) michael@0: , mDrawingModel(kDefaultDrawingModel) michael@0: #if defined(OS_WIN) michael@0: , mPluginHWND(nullptr) michael@0: , mPluginWndProc(nullptr) michael@0: , mNestedEventState(false) michael@0: #endif // defined(XP_WIN) michael@0: #if defined(XP_MACOSX) michael@0: , mShWidth(0) michael@0: , mShHeight(0) michael@0: , mShColorSpace(nullptr) michael@0: #endif michael@0: { michael@0: } michael@0: michael@0: PluginInstanceParent::~PluginInstanceParent() michael@0: { michael@0: if (mNPP) michael@0: mNPP->pdata = nullptr; michael@0: michael@0: #if defined(OS_WIN) michael@0: NS_ASSERTION(!(mPluginHWND || mPluginWndProc), michael@0: "Subclass was not reset correctly before the dtor was reached!"); michael@0: #endif michael@0: #if defined(MOZ_WIDGET_COCOA) michael@0: if (mShWidth != 0 && mShHeight != 0) { michael@0: DeallocShmem(mShSurface); michael@0: } michael@0: if (mShColorSpace) michael@0: ::CGColorSpaceRelease(mShColorSpace); michael@0: #endif michael@0: if (mRemoteImageDataShmem.IsWritable()) { michael@0: if (mImageContainer) { michael@0: mImageContainer->SetRemoteImageData(nullptr, nullptr); michael@0: mImageContainer->SetCompositionNotifySink(nullptr); michael@0: } michael@0: DeallocShmem(mRemoteImageDataShmem); michael@0: } michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::Init() michael@0: { michael@0: return true; michael@0: } michael@0: michael@0: void michael@0: PluginInstanceParent::ActorDestroy(ActorDestroyReason why) michael@0: { michael@0: #if defined(OS_WIN) michael@0: if (why == AbnormalShutdown) { michael@0: // If the plugin process crashes, this is the only michael@0: // chance we get to destroy resources. michael@0: SharedSurfaceRelease(); michael@0: UnsubclassPluginWindow(); michael@0: } michael@0: #endif michael@0: // After this method, the data backing the remote surface may no michael@0: // longer be valid. The X surface may be destroyed, or the shared michael@0: // memory backing this surface may no longer be valid. michael@0: if (mFrontSurface) { michael@0: mFrontSurface = nullptr; michael@0: if (mImageContainer) { michael@0: mImageContainer->SetCurrentImage(nullptr); michael@0: } michael@0: #ifdef MOZ_X11 michael@0: FinishX(DefaultXDisplay()); michael@0: #endif michael@0: } michael@0: } michael@0: michael@0: NPError michael@0: PluginInstanceParent::Destroy() michael@0: { michael@0: NPError retval; michael@0: if (!CallNPP_Destroy(&retval)) michael@0: retval = NPERR_GENERIC_ERROR; michael@0: michael@0: #if defined(OS_WIN) michael@0: SharedSurfaceRelease(); michael@0: UnsubclassPluginWindow(); michael@0: #endif michael@0: michael@0: return retval; michael@0: } michael@0: michael@0: PBrowserStreamParent* michael@0: PluginInstanceParent::AllocPBrowserStreamParent(const nsCString& url, michael@0: const uint32_t& length, michael@0: const uint32_t& lastmodified, michael@0: PStreamNotifyParent* notifyData, michael@0: const nsCString& headers, michael@0: const nsCString& mimeType, michael@0: const bool& seekable, michael@0: NPError* rv, michael@0: uint16_t *stype) michael@0: { michael@0: NS_RUNTIMEABORT("Not reachable"); michael@0: return nullptr; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::DeallocPBrowserStreamParent(PBrowserStreamParent* stream) michael@0: { michael@0: delete stream; michael@0: return true; michael@0: } michael@0: michael@0: PPluginStreamParent* michael@0: PluginInstanceParent::AllocPPluginStreamParent(const nsCString& mimeType, michael@0: const nsCString& target, michael@0: NPError* result) michael@0: { michael@0: return new PluginStreamParent(this, mimeType, target, result); michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::DeallocPPluginStreamParent(PPluginStreamParent* stream) michael@0: { michael@0: delete stream; michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::AnswerNPN_GetValue_NPNVnetscapeWindow(NativeWindowHandle* value, michael@0: NPError* result) michael@0: { michael@0: #ifdef XP_WIN michael@0: HWND id; michael@0: #elif defined(MOZ_X11) michael@0: XID id; michael@0: #elif defined(XP_MACOSX) michael@0: intptr_t id; michael@0: #elif defined(ANDROID) michael@0: // TODO: Need Android impl michael@0: int id; michael@0: #elif defined(MOZ_WIDGET_QT) michael@0: // TODO: Need Qt non X impl michael@0: int id; michael@0: #else michael@0: #warning Implement me michael@0: #endif michael@0: michael@0: *result = mNPNIface->getvalue(mNPP, NPNVnetscapeWindow, &id); michael@0: *value = id; michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::InternalGetValueForNPObject( michael@0: NPNVariable aVariable, michael@0: PPluginScriptableObjectParent** aValue, michael@0: NPError* aResult) michael@0: { michael@0: NPObject* npobject; michael@0: NPError result = mNPNIface->getvalue(mNPP, aVariable, (void*)&npobject); michael@0: if (result == NPERR_NO_ERROR) { michael@0: NS_ASSERTION(npobject, "Shouldn't return null and NPERR_NO_ERROR!"); michael@0: michael@0: PluginScriptableObjectParent* actor = GetActorForNPObject(npobject); michael@0: mNPNIface->releaseobject(npobject); michael@0: if (actor) { michael@0: *aValue = actor; michael@0: *aResult = NPERR_NO_ERROR; michael@0: return true; michael@0: } michael@0: michael@0: NS_ERROR("Failed to get actor!"); michael@0: result = NPERR_GENERIC_ERROR; michael@0: } michael@0: michael@0: *aValue = nullptr; michael@0: *aResult = result; michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::IsAsyncDrawing() michael@0: { michael@0: return IsDrawingModelAsync(mDrawingModel); michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::AnswerNPN_GetValue_NPNVWindowNPObject( michael@0: PPluginScriptableObjectParent** aValue, michael@0: NPError* aResult) michael@0: { michael@0: return InternalGetValueForNPObject(NPNVWindowNPObject, aValue, aResult); michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::AnswerNPN_GetValue_NPNVPluginElementNPObject( michael@0: PPluginScriptableObjectParent** aValue, michael@0: NPError* aResult) michael@0: { michael@0: return InternalGetValueForNPObject(NPNVPluginElementNPObject, aValue, michael@0: aResult); michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::AnswerNPN_GetValue_NPNVprivateModeBool(bool* value, michael@0: NPError* result) michael@0: { michael@0: NPBool v; michael@0: *result = mNPNIface->getvalue(mNPP, NPNVprivateModeBool, &v); michael@0: *value = v; michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::AnswerNPN_GetValue_DrawingModelSupport(const NPNVariable& model, bool* value) michael@0: { michael@0: *value = false; michael@0: michael@0: #ifdef XP_WIN michael@0: switch (model) { michael@0: case NPNVsupportsAsyncWindowsDXGISurfaceBool: { michael@0: if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() == gfxWindowsPlatform::RENDER_DIRECT2D) { michael@0: *value = true; michael@0: } michael@0: } michael@0: } michael@0: #endif michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::AnswerNPN_GetValue_NPNVdocumentOrigin(nsCString* value, michael@0: NPError* result) michael@0: { michael@0: void *v = nullptr; michael@0: *result = mNPNIface->getvalue(mNPP, NPNVdocumentOrigin, &v); michael@0: if (*result == NPERR_NO_ERROR && v) { michael@0: value->Adopt(static_cast(v)); michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginWindow( michael@0: const bool& windowed, NPError* result) michael@0: { michael@0: // Yes, we are passing a boolean as a void*. We have to cast to intptr_t michael@0: // first to avoid gcc warnings about casting to a pointer from a michael@0: // non-pointer-sized integer. michael@0: *result = mNPNIface->setvalue(mNPP, NPPVpluginWindowBool, michael@0: (void*)(intptr_t)windowed); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginTransparent( michael@0: const bool& transparent, NPError* result) michael@0: { michael@0: *result = mNPNIface->setvalue(mNPP, NPPVpluginTransparentBool, michael@0: (void*)(intptr_t)transparent); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginUsesDOMForCursor( michael@0: const bool& useDOMForCursor, NPError* result) michael@0: { michael@0: *result = mNPNIface->setvalue(mNPP, NPPVpluginUsesDOMForCursorBool, michael@0: (void*)(intptr_t)useDOMForCursor); michael@0: return true; michael@0: } michael@0: michael@0: class NotificationSink : public CompositionNotifySink michael@0: { michael@0: public: michael@0: NotificationSink(PluginInstanceParent *aInstance) : mInstance(aInstance) michael@0: { } michael@0: michael@0: virtual void DidComposite() { mInstance->DidComposite(); } michael@0: private: michael@0: PluginInstanceParent *mInstance; michael@0: }; michael@0: michael@0: bool michael@0: PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginDrawingModel( michael@0: const int& drawingModel, OptionalShmem *shmem, CrossProcessMutexHandle *mutex, NPError* result) michael@0: { michael@0: *shmem = null_t(); michael@0: michael@0: #ifdef XP_MACOSX michael@0: if (drawingModel == NPDrawingModelCoreAnimation || michael@0: drawingModel == NPDrawingModelInvalidatingCoreAnimation) { michael@0: // We need to request CoreGraphics otherwise michael@0: // the nsObjectFrame will try to draw a CALayer michael@0: // that can not be shared across process. michael@0: mDrawingModel = drawingModel; michael@0: *result = mNPNIface->setvalue(mNPP, NPPVpluginDrawingModel, michael@0: (void*)NPDrawingModelCoreGraphics); michael@0: } else michael@0: #endif michael@0: if (drawingModel == NPDrawingModelAsyncBitmapSurface michael@0: #ifdef XP_WIN michael@0: || drawingModel == NPDrawingModelAsyncWindowsDXGISurface michael@0: #endif michael@0: ) { michael@0: ImageContainer *container = GetImageContainer(); michael@0: if (!container) { michael@0: *result = NPERR_GENERIC_ERROR; michael@0: return true; michael@0: } michael@0: michael@0: #ifdef XP_WIN michael@0: if (drawingModel == NPDrawingModelAsyncWindowsDXGISurface && michael@0: gfxWindowsPlatform::GetPlatform()->GetRenderMode() != gfxWindowsPlatform::RENDER_DIRECT2D) { michael@0: *result = NPERR_GENERIC_ERROR; michael@0: return true; michael@0: } michael@0: #endif michael@0: michael@0: mDrawingModel = drawingModel; michael@0: *result = mNPNIface->setvalue(mNPP, NPPVpluginDrawingModel, michael@0: reinterpret_cast(static_cast(drawingModel))); michael@0: michael@0: michael@0: if (*result != NPERR_NO_ERROR) { michael@0: return true; michael@0: } michael@0: michael@0: AllocUnsafeShmem(sizeof(RemoteImageData), SharedMemory::TYPE_BASIC, &mRemoteImageDataShmem); michael@0: michael@0: *shmem = mRemoteImageDataShmem; michael@0: michael@0: mRemoteImageDataMutex = new CrossProcessMutex("PluginInstanceParent.mRemoteImageDataMutex"); michael@0: michael@0: *mutex = mRemoteImageDataMutex->ShareToProcess(OtherProcess()); michael@0: container->SetRemoteImageData(mRemoteImageDataShmem.get(), mRemoteImageDataMutex); michael@0: michael@0: mNotifySink = new NotificationSink(this); michael@0: michael@0: container->SetCompositionNotifySink(mNotifySink); michael@0: } else if ( michael@0: #if defined(XP_WIN) michael@0: drawingModel == NPDrawingModelSyncWin michael@0: #elif defined(XP_MACOSX) michael@0: drawingModel == NPDrawingModelOpenGL || michael@0: drawingModel == NPDrawingModelCoreGraphics michael@0: #elif defined(MOZ_X11) michael@0: drawingModel == NPDrawingModelSyncX michael@0: #else michael@0: false michael@0: #endif michael@0: ) { michael@0: *shmem = null_t(); michael@0: michael@0: mDrawingModel = drawingModel; michael@0: *result = mNPNIface->setvalue(mNPP, NPPVpluginDrawingModel, michael@0: (void*)(intptr_t)drawingModel); michael@0: michael@0: if (mRemoteImageDataShmem.IsWritable()) { michael@0: if (mImageContainer) { michael@0: mImageContainer->SetRemoteImageData(nullptr, nullptr); michael@0: mImageContainer->SetCompositionNotifySink(nullptr); michael@0: } michael@0: DeallocShmem(mRemoteImageDataShmem); michael@0: mRemoteImageDataMutex = nullptr; michael@0: } michael@0: } else { michael@0: *result = NPERR_GENERIC_ERROR; michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginEventModel( michael@0: const int& eventModel, NPError* result) michael@0: { michael@0: #ifdef XP_MACOSX michael@0: *result = mNPNIface->setvalue(mNPP, NPPVpluginEventModel, michael@0: (void*)(intptr_t)eventModel); michael@0: return true; michael@0: #else michael@0: *result = NPERR_GENERIC_ERROR; michael@0: return true; michael@0: #endif michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::AnswerNPN_GetURL(const nsCString& url, michael@0: const nsCString& target, michael@0: NPError* result) michael@0: { michael@0: *result = mNPNIface->geturl(mNPP, michael@0: NullableStringGet(url), michael@0: NullableStringGet(target)); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::AnswerNPN_PostURL(const nsCString& url, michael@0: const nsCString& target, michael@0: const nsCString& buffer, michael@0: const bool& file, michael@0: NPError* result) michael@0: { michael@0: *result = mNPNIface->posturl(mNPP, url.get(), NullableStringGet(target), michael@0: buffer.Length(), buffer.get(), file); michael@0: return true; michael@0: } michael@0: michael@0: PStreamNotifyParent* michael@0: PluginInstanceParent::AllocPStreamNotifyParent(const nsCString& url, michael@0: const nsCString& target, michael@0: const bool& post, michael@0: const nsCString& buffer, michael@0: const bool& file, michael@0: NPError* result) michael@0: { michael@0: return new StreamNotifyParent(); michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::AnswerPStreamNotifyConstructor(PStreamNotifyParent* actor, michael@0: const nsCString& url, michael@0: const nsCString& target, michael@0: const bool& post, michael@0: const nsCString& buffer, michael@0: const bool& file, michael@0: NPError* result) michael@0: { michael@0: bool streamDestroyed = false; michael@0: static_cast(actor)-> michael@0: SetDestructionFlag(&streamDestroyed); michael@0: michael@0: if (!post) { michael@0: *result = mNPNIface->geturlnotify(mNPP, michael@0: NullableStringGet(url), michael@0: NullableStringGet(target), michael@0: actor); michael@0: } michael@0: else { michael@0: *result = mNPNIface->posturlnotify(mNPP, michael@0: NullableStringGet(url), michael@0: NullableStringGet(target), michael@0: buffer.Length(), michael@0: NullableStringGet(buffer), michael@0: file, actor); michael@0: } michael@0: michael@0: if (streamDestroyed) { michael@0: // If the stream was destroyed, we must return an error code in the michael@0: // constructor. michael@0: *result = NPERR_GENERIC_ERROR; michael@0: } michael@0: else { michael@0: static_cast(actor)->ClearDestructionFlag(); michael@0: if (*result != NPERR_NO_ERROR) michael@0: return PStreamNotifyParent::Send__delete__(actor, michael@0: NPERR_GENERIC_ERROR); michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::DeallocPStreamNotifyParent(PStreamNotifyParent* notifyData) michael@0: { michael@0: delete notifyData; michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::RecvNPN_InvalidateRect(const NPRect& rect) michael@0: { michael@0: mNPNIface->invalidaterect(mNPP, const_cast(&rect)); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::RecvShow(const NPRect& updatedRect, michael@0: const SurfaceDescriptor& newSurface, michael@0: SurfaceDescriptor* prevSurface) michael@0: { michael@0: PLUGIN_LOG_DEBUG( michael@0: ("[InstanceParent][%p] RecvShow for ", michael@0: this, updatedRect.left, updatedRect.top, michael@0: updatedRect.right - updatedRect.left, michael@0: updatedRect.bottom - updatedRect.top)); michael@0: michael@0: // XXXjwatt rewrite to use Moz2D michael@0: nsRefPtr surface; michael@0: if (newSurface.type() == SurfaceDescriptor::TShmem) { michael@0: if (!newSurface.get_Shmem().IsReadable()) { michael@0: NS_WARNING("back surface not readable"); michael@0: return false; michael@0: } michael@0: surface = gfxSharedImageSurface::Open(newSurface.get_Shmem()); michael@0: } michael@0: #ifdef XP_MACOSX michael@0: else if (newSurface.type() == SurfaceDescriptor::TIOSurfaceDescriptor) { michael@0: IOSurfaceDescriptor iodesc = newSurface.get_IOSurfaceDescriptor(); michael@0: michael@0: RefPtr newIOSurface = michael@0: MacIOSurface::LookupSurface(iodesc.surfaceId(), michael@0: iodesc.contentsScaleFactor()); michael@0: michael@0: if (!newIOSurface) { michael@0: NS_WARNING("Got bad IOSurfaceDescriptor in RecvShow"); michael@0: return false; michael@0: } michael@0: michael@0: if (mFrontIOSurface) michael@0: *prevSurface = IOSurfaceDescriptor(mFrontIOSurface->GetIOSurfaceID(), michael@0: mFrontIOSurface->GetContentsScaleFactor()); michael@0: else michael@0: *prevSurface = null_t(); michael@0: michael@0: mFrontIOSurface = newIOSurface; michael@0: michael@0: RecvNPN_InvalidateRect(updatedRect); michael@0: michael@0: PLUGIN_LOG_DEBUG((" (RecvShow invalidated for surface %p)", michael@0: mFrontSurface.get())); michael@0: michael@0: return true; michael@0: } michael@0: #endif michael@0: #ifdef MOZ_X11 michael@0: else if (newSurface.type() == SurfaceDescriptor::TSurfaceDescriptorX11) { michael@0: surface = newSurface.get_SurfaceDescriptorX11().OpenForeign(); michael@0: } michael@0: #endif michael@0: #ifdef XP_WIN michael@0: else if (newSurface.type() == SurfaceDescriptor::TPPluginSurfaceParent) { michael@0: PluginSurfaceParent* s = michael@0: static_cast(newSurface.get_PPluginSurfaceParent()); michael@0: surface = s->Surface(); michael@0: } michael@0: #endif michael@0: michael@0: if (mFrontSurface) { michael@0: // This is the "old front buffer" we're about to hand back to michael@0: // the plugin. We might still have drawing operations michael@0: // referencing it. michael@0: #ifdef MOZ_X11 michael@0: if (mFrontSurface->GetType() == gfxSurfaceType::Xlib) { michael@0: // Finish with the surface and XSync here to ensure the server has michael@0: // finished operations on the surface before the plugin starts michael@0: // scribbling on it again, or worse, destroys it. michael@0: mFrontSurface->Finish(); michael@0: FinishX(DefaultXDisplay()); michael@0: } else michael@0: #endif michael@0: { michael@0: mFrontSurface->Flush(); michael@0: } michael@0: } michael@0: michael@0: if (mFrontSurface && gfxSharedImageSurface::IsSharedImage(mFrontSurface)) michael@0: *prevSurface = static_cast(mFrontSurface.get())->GetShmem(); michael@0: else michael@0: *prevSurface = null_t(); michael@0: michael@0: if (surface) { michael@0: // Notify the cairo backend that this surface has changed behind michael@0: // its back. michael@0: gfxRect ur(updatedRect.left, updatedRect.top, michael@0: updatedRect.right - updatedRect.left, michael@0: updatedRect.bottom - updatedRect.top); michael@0: surface->MarkDirty(ur); michael@0: michael@0: ImageContainer *container = GetImageContainer(); michael@0: nsRefPtr image = container->CreateImage(ImageFormat::CAIRO_SURFACE); michael@0: NS_ASSERTION(image->GetFormat() == ImageFormat::CAIRO_SURFACE, "Wrong format?"); michael@0: CairoImage* cairoImage = static_cast(image.get()); michael@0: CairoImage::Data cairoData; michael@0: cairoData.mSize = surface->GetSize().ToIntSize(); michael@0: cairoData.mSourceSurface = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, surface); michael@0: cairoImage->SetData(cairoData); michael@0: michael@0: container->SetCurrentImage(cairoImage); michael@0: } michael@0: else if (mImageContainer) { michael@0: mImageContainer->SetCurrentImage(nullptr); michael@0: } michael@0: michael@0: mFrontSurface = surface; michael@0: RecvNPN_InvalidateRect(updatedRect); michael@0: michael@0: PLUGIN_LOG_DEBUG((" (RecvShow invalidated for surface %p)", michael@0: mFrontSurface.get())); michael@0: michael@0: return true; michael@0: } michael@0: michael@0: nsresult michael@0: PluginInstanceParent::AsyncSetWindow(NPWindow* aWindow) michael@0: { michael@0: NPRemoteWindow window; michael@0: mWindowType = aWindow->type; michael@0: window.window = reinterpret_cast(aWindow->window); michael@0: window.x = aWindow->x; michael@0: window.y = aWindow->y; michael@0: window.width = aWindow->width; michael@0: window.height = aWindow->height; michael@0: window.clipRect = aWindow->clipRect; michael@0: window.type = aWindow->type; michael@0: #ifdef XP_MACOSX michael@0: double scaleFactor = 1.0; michael@0: mNPNIface->getvalue(mNPP, NPNVcontentsScaleFactor, &scaleFactor); michael@0: window.contentsScaleFactor = scaleFactor; michael@0: #endif michael@0: if (!SendAsyncSetWindow(gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType(), michael@0: window)) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: PluginInstanceParent::GetImageContainer(ImageContainer** aContainer) michael@0: { michael@0: #ifdef XP_MACOSX michael@0: MacIOSurface* ioSurface = nullptr; michael@0: michael@0: if (mFrontIOSurface) { michael@0: ioSurface = mFrontIOSurface; michael@0: } else if (mIOSurface) { michael@0: ioSurface = mIOSurface; michael@0: } michael@0: michael@0: if (!mFrontSurface && !ioSurface) michael@0: #else michael@0: if (!mFrontSurface) michael@0: #endif michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: michael@0: ImageContainer *container = GetImageContainer(); michael@0: michael@0: if (!container) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: if (IsAsyncDrawing()) { michael@0: NS_IF_ADDREF(container); michael@0: *aContainer = container; michael@0: return NS_OK; michael@0: } michael@0: michael@0: #ifdef XP_MACOSX michael@0: if (ioSurface) { michael@0: nsRefPtr image = container->CreateImage(ImageFormat::MAC_IOSURFACE); michael@0: if (!image) { michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: NS_ASSERTION(image->GetFormat() == ImageFormat::MAC_IOSURFACE, "Wrong format?"); michael@0: michael@0: MacIOSurfaceImage* pluginImage = static_cast(image.get()); michael@0: pluginImage->SetSurface(ioSurface); michael@0: michael@0: container->SetCurrentImageInTransaction(pluginImage); michael@0: michael@0: NS_IF_ADDREF(container); michael@0: *aContainer = container; michael@0: return NS_OK; michael@0: } michael@0: #endif michael@0: michael@0: NS_IF_ADDREF(container); michael@0: *aContainer = container; michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: PluginInstanceParent::GetImageSize(nsIntSize* aSize) michael@0: { michael@0: if (mFrontSurface) { michael@0: gfxIntSize size = mFrontSurface->GetSize(); michael@0: *aSize = nsIntSize(size.width, size.height); michael@0: return NS_OK; michael@0: } michael@0: michael@0: #ifdef XP_MACOSX michael@0: if (mFrontIOSurface) { michael@0: *aSize = nsIntSize(mFrontIOSurface->GetWidth(), mFrontIOSurface->GetHeight()); michael@0: return NS_OK; michael@0: } else if (mIOSurface) { michael@0: *aSize = nsIntSize(mIOSurface->GetWidth(), mIOSurface->GetHeight()); michael@0: return NS_OK; michael@0: } michael@0: #endif michael@0: michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: } michael@0: michael@0: #ifdef XP_MACOSX michael@0: nsresult michael@0: PluginInstanceParent::IsRemoteDrawingCoreAnimation(bool *aDrawing) michael@0: { michael@0: *aDrawing = (NPDrawingModelCoreAnimation == (NPDrawingModel)mDrawingModel || michael@0: NPDrawingModelInvalidatingCoreAnimation == (NPDrawingModel)mDrawingModel); michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: PluginInstanceParent::ContentsScaleFactorChanged(double aContentsScaleFactor) michael@0: { michael@0: bool rv = SendContentsScaleFactorChanged(aContentsScaleFactor); michael@0: return rv ? NS_OK : NS_ERROR_FAILURE; michael@0: } michael@0: #endif // #ifdef XP_MACOSX michael@0: michael@0: nsresult michael@0: PluginInstanceParent::SetBackgroundUnknown() michael@0: { michael@0: PLUGIN_LOG_DEBUG(("[InstanceParent][%p] SetBackgroundUnknown", this)); michael@0: michael@0: if (mBackground) { michael@0: DestroyBackground(); michael@0: NS_ABORT_IF_FALSE(!mBackground, "Background not destroyed"); michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: PluginInstanceParent::BeginUpdateBackground(const nsIntRect& aRect, michael@0: gfxContext** aCtx) michael@0: { michael@0: PLUGIN_LOG_DEBUG( michael@0: ("[InstanceParent][%p] BeginUpdateBackground for ", michael@0: this, aRect.x, aRect.y, aRect.width, aRect.height)); michael@0: michael@0: if (!mBackground) { michael@0: // XXX if we failed to create a background surface on one michael@0: // update, there's no guarantee that later updates will be for michael@0: // the entire background area until successful. We might want michael@0: // to fix that eventually. michael@0: NS_ABORT_IF_FALSE(aRect.TopLeft() == nsIntPoint(0, 0), michael@0: "Expecting rect for whole frame"); michael@0: if (!CreateBackground(aRect.Size())) { michael@0: *aCtx = nullptr; michael@0: return NS_OK; michael@0: } michael@0: } michael@0: michael@0: gfxIntSize sz = mBackground->GetSize(); michael@0: #ifdef DEBUG michael@0: NS_ABORT_IF_FALSE(nsIntRect(0, 0, sz.width, sz.height).Contains(aRect), michael@0: "Update outside of background area"); michael@0: #endif michael@0: michael@0: RefPtr dt = gfxPlatform::GetPlatform()-> michael@0: CreateDrawTargetForSurface(mBackground, gfx::IntSize(sz.width, sz.height)); michael@0: nsRefPtr ctx = new gfxContext(dt); michael@0: ctx.forget(aCtx); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: PluginInstanceParent::EndUpdateBackground(gfxContext* aCtx, michael@0: const nsIntRect& aRect) michael@0: { michael@0: PLUGIN_LOG_DEBUG( michael@0: ("[InstanceParent][%p] EndUpdateBackground for ", michael@0: this, aRect.x, aRect.y, aRect.width, aRect.height)); michael@0: michael@0: #ifdef MOZ_X11 michael@0: // Have to XSync here to avoid the plugin trying to draw with this michael@0: // surface racing with its creation in the X server. We also want michael@0: // to avoid the plugin drawing onto stale pixels, then handing us michael@0: // back a front surface from those pixels that we might michael@0: // recomposite for "a while" until the next update. This XSync michael@0: // still doesn't guarantee that the plugin draws onto a consistent michael@0: // view of its background, but it does mean that the plugin is michael@0: // drawing onto pixels no older than those in the latest michael@0: // EndUpdateBackground(). michael@0: XSync(DefaultXDisplay(), False); michael@0: #endif michael@0: michael@0: unused << SendUpdateBackground(BackgroundDescriptor(), aRect); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::CreateBackground(const nsIntSize& aSize) michael@0: { michael@0: NS_ABORT_IF_FALSE(!mBackground, "Already have a background"); michael@0: michael@0: // XXX refactor me michael@0: michael@0: #if defined(MOZ_X11) michael@0: Screen* screen = DefaultScreenOfDisplay(DefaultXDisplay()); michael@0: Visual* visual = DefaultVisualOfScreen(screen); michael@0: mBackground = gfxXlibSurface::Create(screen, visual, michael@0: gfxIntSize(aSize.width, aSize.height)); michael@0: return !!mBackground; michael@0: michael@0: #elif defined(XP_WIN) michael@0: // We have chosen to create an unsafe surface in which the plugin michael@0: // can read from the region while we're writing to it. michael@0: mBackground = michael@0: gfxSharedImageSurface::CreateUnsafe( michael@0: this, michael@0: gfxIntSize(aSize.width, aSize.height), michael@0: gfxImageFormat::RGB24); michael@0: return !!mBackground; michael@0: #else michael@0: return nullptr; michael@0: #endif michael@0: } michael@0: michael@0: void michael@0: PluginInstanceParent::DestroyBackground() michael@0: { michael@0: if (!mBackground) { michael@0: return; michael@0: } michael@0: michael@0: // Relinquish ownership of |mBackground| to its destroyer michael@0: PPluginBackgroundDestroyerParent* pbd = michael@0: new PluginBackgroundDestroyerParent(mBackground); michael@0: mBackground = nullptr; michael@0: michael@0: // If this fails, there's no problem: |bd| will be destroyed along michael@0: // with the old background surface. michael@0: unused << SendPPluginBackgroundDestroyerConstructor(pbd); michael@0: } michael@0: michael@0: mozilla::plugins::SurfaceDescriptor michael@0: PluginInstanceParent::BackgroundDescriptor() michael@0: { michael@0: NS_ABORT_IF_FALSE(mBackground, "Need a background here"); michael@0: michael@0: // XXX refactor me michael@0: michael@0: #ifdef MOZ_X11 michael@0: gfxXlibSurface* xsurf = static_cast(mBackground.get()); michael@0: return SurfaceDescriptorX11(xsurf); michael@0: #endif michael@0: michael@0: #ifdef XP_WIN michael@0: NS_ABORT_IF_FALSE(gfxSharedImageSurface::IsSharedImage(mBackground), michael@0: "Expected shared image surface"); michael@0: gfxSharedImageSurface* shmem = michael@0: static_cast(mBackground.get()); michael@0: return shmem->GetShmem(); michael@0: #endif michael@0: michael@0: // If this is ever used, which it shouldn't be, it will trigger a michael@0: // hard assertion in IPDL-generated code. michael@0: return mozilla::plugins::SurfaceDescriptor(); michael@0: } michael@0: michael@0: ImageContainer* michael@0: PluginInstanceParent::GetImageContainer() michael@0: { michael@0: if (mImageContainer) { michael@0: return mImageContainer; michael@0: } michael@0: michael@0: mImageContainer = LayerManager::CreateImageContainer(); michael@0: return mImageContainer; michael@0: } michael@0: michael@0: PPluginBackgroundDestroyerParent* michael@0: PluginInstanceParent::AllocPPluginBackgroundDestroyerParent() michael@0: { michael@0: NS_RUNTIMEABORT("'Power-user' ctor is used exclusively"); michael@0: return nullptr; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::DeallocPPluginBackgroundDestroyerParent( michael@0: PPluginBackgroundDestroyerParent* aActor) michael@0: { michael@0: delete aActor; michael@0: return true; michael@0: } michael@0: michael@0: NPError michael@0: PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow) michael@0: { michael@0: PLUGIN_LOG_DEBUG(("%s (aWindow=%p)", FULLFUNCTION, (void*) aWindow)); michael@0: michael@0: NS_ENSURE_TRUE(aWindow, NPERR_GENERIC_ERROR); michael@0: michael@0: NPRemoteWindow window; michael@0: mWindowType = aWindow->type; michael@0: michael@0: #if defined(OS_WIN) michael@0: // On windowless controls, reset the shared memory surface as needed. michael@0: if (mWindowType == NPWindowTypeDrawable) { michael@0: // SharedSurfaceSetWindow will take care of NPRemoteWindow. michael@0: if (!SharedSurfaceSetWindow(aWindow, window)) { michael@0: return NPERR_OUT_OF_MEMORY_ERROR; michael@0: } michael@0: } michael@0: else { michael@0: SubclassPluginWindow(reinterpret_cast(aWindow->window)); michael@0: michael@0: window.window = reinterpret_cast(aWindow->window); michael@0: window.x = aWindow->x; michael@0: window.y = aWindow->y; michael@0: window.width = aWindow->width; michael@0: window.height = aWindow->height; michael@0: window.type = aWindow->type; michael@0: } michael@0: #else michael@0: window.window = reinterpret_cast(aWindow->window); michael@0: window.x = aWindow->x; michael@0: window.y = aWindow->y; michael@0: window.width = aWindow->width; michael@0: window.height = aWindow->height; michael@0: window.clipRect = aWindow->clipRect; // MacOS specific michael@0: window.type = aWindow->type; michael@0: #endif michael@0: michael@0: #if defined(XP_MACOSX) michael@0: double floatScaleFactor = 1.0; michael@0: mNPNIface->getvalue(mNPP, NPNVcontentsScaleFactor, &floatScaleFactor); michael@0: int scaleFactor = ceil(floatScaleFactor); michael@0: window.contentsScaleFactor = floatScaleFactor; michael@0: michael@0: if (mShWidth != window.width * scaleFactor || mShHeight != window.height * scaleFactor) { michael@0: if (mDrawingModel == NPDrawingModelCoreAnimation || michael@0: mDrawingModel == NPDrawingModelInvalidatingCoreAnimation) { michael@0: mIOSurface = MacIOSurface::CreateIOSurface(window.width, window.height, michael@0: floatScaleFactor); michael@0: } else if (uint32_t(mShWidth * mShHeight) != michael@0: window.width * scaleFactor * window.height * scaleFactor) { michael@0: if (mShWidth != 0 && mShHeight != 0) { michael@0: DeallocShmem(mShSurface); michael@0: mShWidth = 0; michael@0: mShHeight = 0; michael@0: } michael@0: michael@0: if (window.width != 0 && window.height != 0) { michael@0: if (!AllocShmem(window.width * scaleFactor * window.height*4 * scaleFactor, michael@0: SharedMemory::TYPE_BASIC, &mShSurface)) { michael@0: PLUGIN_LOG_DEBUG(("Shared memory could not be allocated.")); michael@0: return NPERR_GENERIC_ERROR; michael@0: } michael@0: } michael@0: } michael@0: mShWidth = window.width * scaleFactor; michael@0: mShHeight = window.height * scaleFactor; michael@0: } michael@0: #endif michael@0: michael@0: #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX) michael@0: const NPSetWindowCallbackStruct* ws_info = michael@0: static_cast(aWindow->ws_info); michael@0: window.visualID = ws_info->visual ? ws_info->visual->visualid : None; michael@0: window.colormap = ws_info->colormap; michael@0: #endif michael@0: michael@0: if (!CallNPP_SetWindow(window)) michael@0: return NPERR_GENERIC_ERROR; michael@0: michael@0: return NPERR_NO_ERROR; michael@0: } michael@0: michael@0: NPError michael@0: PluginInstanceParent::NPP_GetValue(NPPVariable aVariable, michael@0: void* _retval) michael@0: { michael@0: switch (aVariable) { michael@0: michael@0: case NPPVpluginWantsAllNetworkStreams: { michael@0: bool wantsAllStreams; michael@0: NPError rv; michael@0: michael@0: if (!CallNPP_GetValue_NPPVpluginWantsAllNetworkStreams(&wantsAllStreams, &rv)) { michael@0: return NPERR_GENERIC_ERROR; michael@0: } michael@0: michael@0: if (NPERR_NO_ERROR != rv) { michael@0: return rv; michael@0: } michael@0: michael@0: (*(NPBool*)_retval) = wantsAllStreams; michael@0: return NPERR_NO_ERROR; michael@0: } michael@0: michael@0: #ifdef MOZ_X11 michael@0: case NPPVpluginNeedsXEmbed: { michael@0: bool needsXEmbed; michael@0: NPError rv; michael@0: michael@0: if (!CallNPP_GetValue_NPPVpluginNeedsXEmbed(&needsXEmbed, &rv)) { michael@0: return NPERR_GENERIC_ERROR; michael@0: } michael@0: michael@0: if (NPERR_NO_ERROR != rv) { michael@0: return rv; michael@0: } michael@0: michael@0: (*(NPBool*)_retval) = needsXEmbed; michael@0: return NPERR_NO_ERROR; michael@0: } michael@0: #endif michael@0: michael@0: case NPPVpluginScriptableNPObject: { michael@0: PPluginScriptableObjectParent* actor; michael@0: NPError rv; michael@0: if (!CallNPP_GetValue_NPPVpluginScriptableNPObject(&actor, &rv)) { michael@0: return NPERR_GENERIC_ERROR; michael@0: } michael@0: michael@0: if (NPERR_NO_ERROR != rv) { michael@0: return rv; michael@0: } michael@0: michael@0: if (!actor) { michael@0: NS_ERROR("NPPVpluginScriptableNPObject succeeded but null."); michael@0: return NPERR_GENERIC_ERROR; michael@0: } michael@0: michael@0: const NPNetscapeFuncs* npn = mParent->GetNetscapeFuncs(); michael@0: if (!npn) { michael@0: NS_WARNING("No netscape functions?!"); michael@0: return NPERR_GENERIC_ERROR; michael@0: } michael@0: michael@0: NPObject* object = michael@0: static_cast(actor)->GetObject(true); michael@0: NS_ASSERTION(object, "This shouldn't ever be null!"); michael@0: michael@0: (*(NPObject**)_retval) = npn->retainobject(object); michael@0: return NPERR_NO_ERROR; michael@0: } michael@0: michael@0: #ifdef MOZ_ACCESSIBILITY_ATK michael@0: case NPPVpluginNativeAccessibleAtkPlugId: { michael@0: nsCString plugId; michael@0: NPError rv; michael@0: if (!CallNPP_GetValue_NPPVpluginNativeAccessibleAtkPlugId(&plugId, &rv)) { michael@0: return NPERR_GENERIC_ERROR; michael@0: } michael@0: michael@0: if (NPERR_NO_ERROR != rv) { michael@0: return rv; michael@0: } michael@0: michael@0: (*(nsCString*)_retval) = plugId; michael@0: return NPERR_NO_ERROR; michael@0: } michael@0: #endif michael@0: michael@0: default: michael@0: PR_LOG(GetPluginLog(), PR_LOG_WARNING, michael@0: ("In PluginInstanceParent::NPP_GetValue: Unhandled NPPVariable %i (%s)", michael@0: (int) aVariable, NPPVariableToString(aVariable))); michael@0: return NPERR_GENERIC_ERROR; michael@0: } michael@0: } michael@0: michael@0: NPError michael@0: PluginInstanceParent::NPP_SetValue(NPNVariable variable, void* value) michael@0: { michael@0: switch (variable) { michael@0: case NPNVprivateModeBool: michael@0: NPError result; michael@0: if (!CallNPP_SetValue_NPNVprivateModeBool(*static_cast(value), michael@0: &result)) michael@0: return NPERR_GENERIC_ERROR; michael@0: michael@0: return result; michael@0: michael@0: default: michael@0: NS_ERROR("Unhandled NPNVariable in NPP_SetValue"); michael@0: PR_LOG(GetPluginLog(), PR_LOG_WARNING, michael@0: ("In PluginInstanceParent::NPP_SetValue: Unhandled NPNVariable %i (%s)", michael@0: (int) variable, NPNVariableToString(variable))); michael@0: return NPERR_GENERIC_ERROR; michael@0: } michael@0: } michael@0: michael@0: void michael@0: PluginInstanceParent::NPP_URLRedirectNotify(const char* url, int32_t status, michael@0: void* notifyData) michael@0: { michael@0: if (!notifyData) michael@0: return; michael@0: michael@0: PStreamNotifyParent* streamNotify = static_cast(notifyData); michael@0: unused << streamNotify->SendRedirectNotify(NullableString(url), status); michael@0: } michael@0: michael@0: int16_t michael@0: PluginInstanceParent::NPP_HandleEvent(void* event) michael@0: { michael@0: PLUGIN_LOG_DEBUG_FUNCTION; michael@0: michael@0: #if defined(XP_MACOSX) michael@0: NPCocoaEvent* npevent = reinterpret_cast(event); michael@0: #else michael@0: NPEvent* npevent = reinterpret_cast(event); michael@0: #endif michael@0: NPRemoteEvent npremoteevent; michael@0: npremoteevent.event = *npevent; michael@0: #if defined(XP_MACOSX) michael@0: double scaleFactor = 1.0; michael@0: mNPNIface->getvalue(mNPP, NPNVcontentsScaleFactor, &scaleFactor); michael@0: npremoteevent.contentsScaleFactor = scaleFactor; michael@0: #endif michael@0: int16_t handled = 0; michael@0: michael@0: #if defined(OS_WIN) michael@0: if (mWindowType == NPWindowTypeDrawable) { michael@0: if (IsAsyncDrawing()) { michael@0: if (npevent->event == WM_PAINT || npevent->event == DoublePassRenderingEvent()) { michael@0: // This plugin maintains its own async drawing. michael@0: return handled; michael@0: } michael@0: } michael@0: if (DoublePassRenderingEvent() == npevent->event) { michael@0: return CallPaint(npremoteevent, &handled) && handled; michael@0: } michael@0: michael@0: switch (npevent->event) { michael@0: case WM_PAINT: michael@0: { michael@0: RECT rect; michael@0: SharedSurfaceBeforePaint(rect, npremoteevent); michael@0: if (!CallPaint(npremoteevent, &handled)) { michael@0: handled = false; michael@0: } michael@0: SharedSurfaceAfterPaint(npevent); michael@0: return handled; michael@0: } michael@0: break; michael@0: michael@0: case WM_KILLFOCUS: michael@0: { michael@0: // When the user selects fullscreen mode in Flash video players, michael@0: // WM_KILLFOCUS will be delayed by deferred event processing: michael@0: // WM_LBUTTONUP results in a call to CreateWindow within Flash, michael@0: // which fires WM_KILLFOCUS. Delayed delivery causes Flash to michael@0: // misinterpret the event, dropping back out of fullscreen. Trap michael@0: // this event and drop it. michael@0: wchar_t szClass[26]; michael@0: HWND hwnd = GetForegroundWindow(); michael@0: if (hwnd && hwnd != mPluginHWND && michael@0: GetClassNameW(hwnd, szClass, michael@0: sizeof(szClass)/sizeof(char16_t)) && michael@0: !wcscmp(szClass, kFlashFullscreenClass)) { michael@0: return 0; michael@0: } michael@0: } michael@0: break; michael@0: michael@0: case WM_WINDOWPOSCHANGED: michael@0: { michael@0: // We send this in nsObjectFrame just before painting michael@0: return SendWindowPosChanged(npremoteevent); michael@0: } michael@0: break; michael@0: } michael@0: } michael@0: #endif michael@0: michael@0: #if defined(MOZ_X11) michael@0: switch (npevent->type) { michael@0: case GraphicsExpose: michael@0: PLUGIN_LOG_DEBUG((" schlepping drawable 0x%lx across the pipe\n", michael@0: npevent->xgraphicsexpose.drawable)); michael@0: // Make sure the X server has created the Drawable and completes any michael@0: // drawing before the plugin draws on top. michael@0: // michael@0: // XSync() waits for the X server to complete. Really this parent michael@0: // process does not need to wait; the child is the process that needs michael@0: // to wait. A possibly-slightly-better alternative would be to send michael@0: // an X event to the child that the child would wait for. michael@0: FinishX(DefaultXDisplay()); michael@0: michael@0: return CallPaint(npremoteevent, &handled) ? handled : 0; michael@0: michael@0: case ButtonPress: michael@0: // Release any active pointer grab so that the plugin X client can michael@0: // grab the pointer if it wishes. michael@0: Display *dpy = DefaultXDisplay(); michael@0: # ifdef MOZ_WIDGET_GTK michael@0: // GDK attempts to (asynchronously) track whether there is an active michael@0: // grab so ungrab through GDK. michael@0: gdk_pointer_ungrab(npevent->xbutton.time); michael@0: # else michael@0: XUngrabPointer(dpy, npevent->xbutton.time); michael@0: # endif michael@0: // Wait for the ungrab to complete. michael@0: XSync(dpy, False); michael@0: break; michael@0: } michael@0: #endif michael@0: michael@0: #ifdef XP_MACOSX michael@0: if (npevent->type == NPCocoaEventDrawRect) { michael@0: if (mDrawingModel == NPDrawingModelCoreAnimation || michael@0: mDrawingModel == NPDrawingModelInvalidatingCoreAnimation) { michael@0: if (!mIOSurface) { michael@0: NS_ERROR("No IOSurface allocated."); michael@0: return false; michael@0: } michael@0: if (!CallNPP_HandleEvent_IOSurface(npremoteevent, michael@0: mIOSurface->GetIOSurfaceID(), michael@0: &handled)) michael@0: return false; // no good way to handle errors here... michael@0: michael@0: CGContextRef cgContext = npevent->data.draw.context; michael@0: if (!mShColorSpace) { michael@0: mShColorSpace = CreateSystemColorSpace(); michael@0: } michael@0: if (!mShColorSpace) { michael@0: PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace.")); michael@0: return false; michael@0: } michael@0: if (cgContext) { michael@0: nsCARenderer::DrawSurfaceToCGContext(cgContext, mIOSurface, michael@0: mShColorSpace, michael@0: npevent->data.draw.x, michael@0: npevent->data.draw.y, michael@0: npevent->data.draw.width, michael@0: npevent->data.draw.height); michael@0: } michael@0: return true; michael@0: } else if (mFrontIOSurface) { michael@0: CGContextRef cgContext = npevent->data.draw.context; michael@0: if (!mShColorSpace) { michael@0: mShColorSpace = CreateSystemColorSpace(); michael@0: } michael@0: if (!mShColorSpace) { michael@0: PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace.")); michael@0: return false; michael@0: } michael@0: if (cgContext) { michael@0: nsCARenderer::DrawSurfaceToCGContext(cgContext, mFrontIOSurface, michael@0: mShColorSpace, michael@0: npevent->data.draw.x, michael@0: npevent->data.draw.y, michael@0: npevent->data.draw.width, michael@0: npevent->data.draw.height); michael@0: } michael@0: return true; michael@0: } else { michael@0: if (mShWidth == 0 && mShHeight == 0) { michael@0: PLUGIN_LOG_DEBUG(("NPCocoaEventDrawRect on window of size 0.")); michael@0: return false; michael@0: } michael@0: if (!mShSurface.IsReadable()) { michael@0: PLUGIN_LOG_DEBUG(("Shmem is not readable.")); michael@0: return false; michael@0: } michael@0: michael@0: if (!CallNPP_HandleEvent_Shmem(npremoteevent, mShSurface, michael@0: &handled, &mShSurface)) michael@0: return false; // no good way to handle errors here... michael@0: michael@0: if (!mShSurface.IsReadable()) { michael@0: PLUGIN_LOG_DEBUG(("Shmem not returned. Either the plugin crashed " michael@0: "or we have a bug.")); michael@0: return false; michael@0: } michael@0: michael@0: char* shContextByte = mShSurface.get(); michael@0: michael@0: if (!mShColorSpace) { michael@0: mShColorSpace = CreateSystemColorSpace(); michael@0: } michael@0: if (!mShColorSpace) { michael@0: PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace.")); michael@0: return false; michael@0: } michael@0: CGContextRef shContext = ::CGBitmapContextCreate(shContextByte, michael@0: mShWidth, mShHeight, 8, michael@0: mShWidth*4, mShColorSpace, michael@0: kCGImageAlphaPremultipliedFirst | michael@0: kCGBitmapByteOrder32Host); michael@0: if (!shContext) { michael@0: PLUGIN_LOG_DEBUG(("Could not allocate CGBitmapContext.")); michael@0: return false; michael@0: } michael@0: michael@0: CGImageRef shImage = ::CGBitmapContextCreateImage(shContext); michael@0: if (shImage) { michael@0: CGContextRef cgContext = npevent->data.draw.context; michael@0: michael@0: ::CGContextDrawImage(cgContext, michael@0: CGRectMake(0,0,mShWidth,mShHeight), michael@0: shImage); michael@0: ::CGImageRelease(shImage); michael@0: } else { michael@0: ::CGContextRelease(shContext); michael@0: return false; michael@0: } michael@0: ::CGContextRelease(shContext); michael@0: return true; michael@0: } michael@0: } michael@0: #endif michael@0: michael@0: if (!CallNPP_HandleEvent(npremoteevent, &handled)) michael@0: return 0; // no good way to handle errors here... michael@0: michael@0: return handled; michael@0: } michael@0: michael@0: NPError michael@0: PluginInstanceParent::NPP_NewStream(NPMIMEType type, NPStream* stream, michael@0: NPBool seekable, uint16_t* stype) michael@0: { michael@0: PLUGIN_LOG_DEBUG(("%s (type=%s, stream=%p, seekable=%i)", michael@0: FULLFUNCTION, (char*) type, (void*) stream, (int) seekable)); michael@0: michael@0: BrowserStreamParent* bs = new BrowserStreamParent(this, stream); michael@0: michael@0: NPError err; michael@0: if (!CallPBrowserStreamConstructor(bs, michael@0: NullableString(stream->url), michael@0: stream->end, michael@0: stream->lastmodified, michael@0: static_cast(stream->notifyData), michael@0: NullableString(stream->headers), michael@0: NullableString(type), seekable, michael@0: &err, stype)) michael@0: return NPERR_GENERIC_ERROR; michael@0: michael@0: if (NPERR_NO_ERROR != err) michael@0: unused << PBrowserStreamParent::Send__delete__(bs); michael@0: michael@0: return err; michael@0: } michael@0: michael@0: NPError michael@0: PluginInstanceParent::NPP_DestroyStream(NPStream* stream, NPReason reason) michael@0: { michael@0: PLUGIN_LOG_DEBUG(("%s (stream=%p, reason=%i)", michael@0: FULLFUNCTION, (void*) stream, (int) reason)); michael@0: michael@0: AStream* s = static_cast(stream->pdata); michael@0: if (s->IsBrowserStream()) { michael@0: BrowserStreamParent* sp = michael@0: static_cast(s); michael@0: if (sp->mNPP != this) michael@0: NS_RUNTIMEABORT("Mismatched plugin data"); michael@0: michael@0: sp->NPP_DestroyStream(reason); michael@0: return NPERR_NO_ERROR; michael@0: } michael@0: else { michael@0: PluginStreamParent* sp = michael@0: static_cast(s); michael@0: if (sp->mInstance != this) michael@0: NS_RUNTIMEABORT("Mismatched plugin data"); michael@0: michael@0: return PPluginStreamParent::Call__delete__(sp, reason, false) ? michael@0: NPERR_NO_ERROR : NPERR_GENERIC_ERROR; michael@0: } michael@0: } michael@0: michael@0: void michael@0: PluginInstanceParent::NPP_Print(NPPrint* platformPrint) michael@0: { michael@0: // TODO: implement me michael@0: NS_ERROR("Not implemented"); michael@0: } michael@0: michael@0: PPluginScriptableObjectParent* michael@0: PluginInstanceParent::AllocPPluginScriptableObjectParent() michael@0: { michael@0: return new PluginScriptableObjectParent(Proxy); michael@0: } michael@0: michael@0: #ifdef DEBUG michael@0: namespace { michael@0: michael@0: struct ActorSearchData michael@0: { michael@0: PluginScriptableObjectParent* actor; michael@0: bool found; michael@0: }; michael@0: michael@0: PLDHashOperator michael@0: ActorSearch(NPObject* aKey, michael@0: PluginScriptableObjectParent* aData, michael@0: void* aUserData) michael@0: { michael@0: ActorSearchData* asd = reinterpret_cast(aUserData); michael@0: if (asd->actor == aData) { michael@0: asd->found = true; michael@0: return PL_DHASH_STOP; michael@0: } michael@0: return PL_DHASH_NEXT; michael@0: } michael@0: michael@0: } // anonymous namespace michael@0: #endif // DEBUG michael@0: michael@0: bool michael@0: PluginInstanceParent::DeallocPPluginScriptableObjectParent( michael@0: PPluginScriptableObjectParent* aObject) michael@0: { michael@0: PluginScriptableObjectParent* actor = michael@0: static_cast(aObject); michael@0: michael@0: NPObject* object = actor->GetObject(false); michael@0: if (object) { michael@0: NS_ASSERTION(mScriptableObjects.Get(object, nullptr), michael@0: "NPObject not in the hash!"); michael@0: mScriptableObjects.Remove(object); michael@0: } michael@0: #ifdef DEBUG michael@0: else { michael@0: ActorSearchData asd = { actor, false }; michael@0: mScriptableObjects.EnumerateRead(ActorSearch, &asd); michael@0: NS_ASSERTION(!asd.found, "Actor in the hash with a null NPObject!"); michael@0: } michael@0: #endif michael@0: michael@0: delete actor; michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::RecvPPluginScriptableObjectConstructor( michael@0: PPluginScriptableObjectParent* aActor) michael@0: { michael@0: // This is only called in response to the child process requesting the michael@0: // creation of an actor. This actor will represent an NPObject that is michael@0: // created by the plugin and returned to the browser. michael@0: PluginScriptableObjectParent* actor = michael@0: static_cast(aActor); michael@0: NS_ASSERTION(!actor->GetObject(false), "Actor already has an object?!"); michael@0: michael@0: actor->InitializeProxy(); michael@0: NS_ASSERTION(actor->GetObject(false), "Actor should have an object!"); michael@0: michael@0: return true; michael@0: } michael@0: michael@0: void michael@0: PluginInstanceParent::NPP_URLNotify(const char* url, NPReason reason, michael@0: void* notifyData) michael@0: { michael@0: PLUGIN_LOG_DEBUG(("%s (%s, %i, %p)", michael@0: FULLFUNCTION, url, (int) reason, notifyData)); michael@0: michael@0: PStreamNotifyParent* streamNotify = michael@0: static_cast(notifyData); michael@0: unused << PStreamNotifyParent::Send__delete__(streamNotify, reason); michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::RegisterNPObjectForActor( michael@0: NPObject* aObject, michael@0: PluginScriptableObjectParent* aActor) michael@0: { michael@0: NS_ASSERTION(aObject && aActor, "Null pointers!"); michael@0: NS_ASSERTION(!mScriptableObjects.Get(aObject, nullptr), "Duplicate entry!"); michael@0: mScriptableObjects.Put(aObject, aActor); michael@0: return true; michael@0: } michael@0: michael@0: void michael@0: PluginInstanceParent::UnregisterNPObject(NPObject* aObject) michael@0: { michael@0: NS_ASSERTION(aObject, "Null pointer!"); michael@0: NS_ASSERTION(mScriptableObjects.Get(aObject, nullptr), "Unknown entry!"); michael@0: mScriptableObjects.Remove(aObject); michael@0: } michael@0: michael@0: PluginScriptableObjectParent* michael@0: PluginInstanceParent::GetActorForNPObject(NPObject* aObject) michael@0: { michael@0: NS_ASSERTION(aObject, "Null pointer!"); michael@0: michael@0: if (aObject->_class == PluginScriptableObjectParent::GetClass()) { michael@0: // One of ours! michael@0: ParentNPObject* object = static_cast(aObject); michael@0: NS_ASSERTION(object->parent, "Null actor!"); michael@0: return object->parent; michael@0: } michael@0: michael@0: PluginScriptableObjectParent* actor; michael@0: if (mScriptableObjects.Get(aObject, &actor)) { michael@0: return actor; michael@0: } michael@0: michael@0: actor = new PluginScriptableObjectParent(LocalObject); michael@0: if (!actor) { michael@0: NS_ERROR("Out of memory!"); michael@0: return nullptr; michael@0: } michael@0: michael@0: if (!SendPPluginScriptableObjectConstructor(actor)) { michael@0: NS_WARNING("Failed to send constructor message!"); michael@0: return nullptr; michael@0: } michael@0: michael@0: actor->InitializeLocal(aObject); michael@0: return actor; michael@0: } michael@0: michael@0: PPluginSurfaceParent* michael@0: PluginInstanceParent::AllocPPluginSurfaceParent(const WindowsSharedMemoryHandle& handle, michael@0: const gfxIntSize& size, michael@0: const bool& transparent) michael@0: { michael@0: #ifdef XP_WIN michael@0: return new PluginSurfaceParent(handle, size, transparent); michael@0: #else michael@0: NS_ERROR("This shouldn't be called!"); michael@0: return nullptr; michael@0: #endif michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::DeallocPPluginSurfaceParent(PPluginSurfaceParent* s) michael@0: { michael@0: #ifdef XP_WIN michael@0: delete s; michael@0: return true; michael@0: #else michael@0: return false; michael@0: #endif michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::AnswerNPN_PushPopupsEnabledState(const bool& aState) michael@0: { michael@0: mNPNIface->pushpopupsenabledstate(mNPP, aState ? 1 : 0); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::AnswerNPN_PopPopupsEnabledState() michael@0: { michael@0: mNPNIface->poppopupsenabledstate(mNPP); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::AnswerNPN_GetValueForURL(const NPNURLVariable& variable, michael@0: const nsCString& url, michael@0: nsCString* value, michael@0: NPError* result) michael@0: { michael@0: char* v; michael@0: uint32_t len; michael@0: michael@0: *result = mNPNIface->getvalueforurl(mNPP, (NPNURLVariable) variable, michael@0: url.get(), &v, &len); michael@0: if (NPERR_NO_ERROR == *result) michael@0: value->Adopt(v, len); michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::AnswerNPN_SetValueForURL(const NPNURLVariable& variable, michael@0: const nsCString& url, michael@0: const nsCString& value, michael@0: NPError* result) michael@0: { michael@0: *result = mNPNIface->setvalueforurl(mNPP, (NPNURLVariable) variable, michael@0: url.get(), value.get(), michael@0: value.Length()); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::AnswerNPN_GetAuthenticationInfo(const nsCString& protocol, michael@0: const nsCString& host, michael@0: const int32_t& port, michael@0: const nsCString& scheme, michael@0: const nsCString& realm, michael@0: nsCString* username, michael@0: nsCString* password, michael@0: NPError* result) michael@0: { michael@0: char* u; michael@0: uint32_t ulen; michael@0: char* p; michael@0: uint32_t plen; michael@0: michael@0: *result = mNPNIface->getauthenticationinfo(mNPP, protocol.get(), michael@0: host.get(), port, michael@0: scheme.get(), realm.get(), michael@0: &u, &ulen, &p, &plen); michael@0: if (NPERR_NO_ERROR == *result) { michael@0: username->Adopt(u, ulen); michael@0: password->Adopt(p, plen); michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::AnswerNPN_ConvertPoint(const double& sourceX, michael@0: const bool& ignoreDestX, michael@0: const double& sourceY, michael@0: const bool& ignoreDestY, michael@0: const NPCoordinateSpace& sourceSpace, michael@0: const NPCoordinateSpace& destSpace, michael@0: double *destX, michael@0: double *destY, michael@0: bool *result) michael@0: { michael@0: *result = mNPNIface->convertpoint(mNPP, sourceX, sourceY, sourceSpace, michael@0: ignoreDestX ? nullptr : destX, michael@0: ignoreDestY ? nullptr : destY, michael@0: destSpace); michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::AnswerNPN_InitAsyncSurface(const gfxIntSize& size, michael@0: const NPImageFormat& format, michael@0: NPRemoteAsyncSurface* surfData, michael@0: bool* result) michael@0: { michael@0: if (!IsAsyncDrawing()) { michael@0: *result = false; michael@0: return true; michael@0: } michael@0: michael@0: switch (mDrawingModel) { michael@0: case NPDrawingModelAsyncBitmapSurface: { michael@0: Shmem sharedMem; michael@0: if (!AllocUnsafeShmem(size.width * size.height * 4, SharedMemory::TYPE_BASIC, &sharedMem)) { michael@0: *result = false; michael@0: return true; michael@0: } michael@0: michael@0: surfData->size() = size; michael@0: surfData->hostPtr() = (uintptr_t)sharedMem.get(); michael@0: surfData->stride() = size.width * 4; michael@0: surfData->format() = format; michael@0: surfData->data() = sharedMem; michael@0: *result = true; michael@0: return true; michael@0: } michael@0: #ifdef XP_WIN michael@0: case NPDrawingModelAsyncWindowsDXGISurface: { michael@0: ID3D10Device1 *device = gfxWindowsPlatform::GetPlatform()->GetD3D10Device(); michael@0: michael@0: nsRefPtr texture; michael@0: michael@0: CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, size.width, size.height, 1, 1); michael@0: desc.MiscFlags = D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX; michael@0: desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; michael@0: if (FAILED(device->CreateTexture2D(&desc, nullptr, getter_AddRefs(texture)))) { michael@0: *result = false; michael@0: return true; michael@0: } michael@0: michael@0: nsRefPtr resource; michael@0: if (FAILED(texture->QueryInterface(IID_IDXGIResource, getter_AddRefs(resource)))) { michael@0: *result = false; michael@0: return true; michael@0: } michael@0: michael@0: HANDLE sharedHandle; michael@0: michael@0: if (FAILED(resource->GetSharedHandle(&sharedHandle))) { michael@0: *result = false; michael@0: return true; michael@0: } michael@0: michael@0: surfData->size() = size; michael@0: surfData->data() = sharedHandle; michael@0: surfData->format() = format; michael@0: michael@0: mTextureMap.Put(sharedHandle, texture); michael@0: *result = true; michael@0: } michael@0: #endif michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::RecvRedrawPlugin() michael@0: { michael@0: nsNPAPIPluginInstance *inst = static_cast(mNPP->ndata); michael@0: if (!inst) { michael@0: return false; michael@0: } michael@0: michael@0: inst->RedrawPlugin(); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::RecvNegotiatedCarbon() michael@0: { michael@0: nsNPAPIPluginInstance *inst = static_cast(mNPP->ndata); michael@0: if (!inst) { michael@0: return false; michael@0: } michael@0: inst->CarbonNPAPIFailure(); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::RecvReleaseDXGISharedSurface(const DXGISharedSurfaceHandle &aHandle) michael@0: { michael@0: #ifdef XP_WIN michael@0: mTextureMap.Remove(aHandle); michael@0: #endif michael@0: return true; michael@0: } michael@0: michael@0: #if defined(OS_WIN) michael@0: michael@0: /* michael@0: plugin focus changes between processes michael@0: michael@0: focus from dom -> child: michael@0: Focus manager calls on widget to set the focus on the window. michael@0: We pick up the resulting wm_setfocus event here, and forward michael@0: that over ipc to the child which calls set focus on itself. michael@0: michael@0: focus from child -> focus manager: michael@0: Child picks up the local wm_setfocus and sends it via ipc over michael@0: here. We then post a custom event to widget/windows/nswindow michael@0: which fires off a gui event letting the browser know. michael@0: */ michael@0: michael@0: static const wchar_t kPluginInstanceParentProperty[] = michael@0: L"PluginInstanceParentProperty"; michael@0: michael@0: // static michael@0: LRESULT CALLBACK michael@0: PluginInstanceParent::PluginWindowHookProc(HWND hWnd, michael@0: UINT message, michael@0: WPARAM wParam, michael@0: LPARAM lParam) michael@0: { michael@0: PluginInstanceParent* self = reinterpret_cast( michael@0: ::GetPropW(hWnd, kPluginInstanceParentProperty)); michael@0: if (!self) { michael@0: NS_NOTREACHED("PluginInstanceParent::PluginWindowHookProc null this ptr!"); michael@0: return DefWindowProc(hWnd, message, wParam, lParam); michael@0: } michael@0: michael@0: NS_ASSERTION(self->mPluginHWND == hWnd, "Wrong window!"); michael@0: michael@0: switch (message) { michael@0: case WM_SETFOCUS: michael@0: // Let the child plugin window know it should take focus. michael@0: unused << self->CallSetPluginFocus(); michael@0: break; michael@0: michael@0: case WM_CLOSE: michael@0: self->UnsubclassPluginWindow(); michael@0: break; michael@0: } michael@0: michael@0: if (self->mPluginWndProc == PluginWindowHookProc) { michael@0: NS_NOTREACHED( michael@0: "PluginWindowHookProc invoking mPluginWndProc w/" michael@0: "mPluginWndProc == PluginWindowHookProc????"); michael@0: return DefWindowProc(hWnd, message, wParam, lParam); michael@0: } michael@0: return ::CallWindowProc(self->mPluginWndProc, hWnd, message, wParam, michael@0: lParam); michael@0: } michael@0: michael@0: void michael@0: PluginInstanceParent::SubclassPluginWindow(HWND aWnd) michael@0: { michael@0: NS_ASSERTION(!(mPluginHWND && aWnd != mPluginHWND), michael@0: "PluginInstanceParent::SubclassPluginWindow hwnd is not our window!"); michael@0: michael@0: if (!mPluginHWND) { michael@0: mPluginHWND = aWnd; michael@0: mPluginWndProc = michael@0: (WNDPROC)::SetWindowLongPtrA(mPluginHWND, GWLP_WNDPROC, michael@0: reinterpret_cast(PluginWindowHookProc)); michael@0: DebugOnly bRes = ::SetPropW(mPluginHWND, kPluginInstanceParentProperty, this); michael@0: NS_ASSERTION(mPluginWndProc, michael@0: "PluginInstanceParent::SubclassPluginWindow failed to set subclass!"); michael@0: NS_ASSERTION(bRes, michael@0: "PluginInstanceParent::SubclassPluginWindow failed to set prop!"); michael@0: } michael@0: } michael@0: michael@0: void michael@0: PluginInstanceParent::UnsubclassPluginWindow() michael@0: { michael@0: if (mPluginHWND && mPluginWndProc) { michael@0: ::SetWindowLongPtrA(mPluginHWND, GWLP_WNDPROC, michael@0: reinterpret_cast(mPluginWndProc)); michael@0: michael@0: ::RemovePropW(mPluginHWND, kPluginInstanceParentProperty); michael@0: michael@0: mPluginWndProc = nullptr; michael@0: mPluginHWND = nullptr; michael@0: } michael@0: } michael@0: michael@0: /* windowless drawing helpers */ michael@0: michael@0: /* michael@0: * Origin info: michael@0: * michael@0: * windowless, offscreen: michael@0: * michael@0: * WM_WINDOWPOSCHANGED: origin is relative to container michael@0: * setwindow: origin is 0,0 michael@0: * WM_PAINT: origin is 0,0 michael@0: * michael@0: * windowless, native: michael@0: * michael@0: * WM_WINDOWPOSCHANGED: origin is relative to container michael@0: * setwindow: origin is relative to container michael@0: * WM_PAINT: origin is relative to container michael@0: * michael@0: * PluginInstanceParent: michael@0: * michael@0: * painting: mPluginPort (nsIntRect, saved in SetWindow) michael@0: */ michael@0: michael@0: void michael@0: PluginInstanceParent::SharedSurfaceRelease() michael@0: { michael@0: mSharedSurfaceDib.Close(); michael@0: } michael@0: michael@0: bool michael@0: PluginInstanceParent::SharedSurfaceSetWindow(const NPWindow* aWindow, michael@0: NPRemoteWindow& aRemoteWindow) michael@0: { michael@0: aRemoteWindow.window = 0; michael@0: aRemoteWindow.x = aWindow->x; michael@0: aRemoteWindow.y = aWindow->y; michael@0: aRemoteWindow.width = aWindow->width; michael@0: aRemoteWindow.height = aWindow->height; michael@0: aRemoteWindow.type = aWindow->type; michael@0: michael@0: nsIntRect newPort(aWindow->x, aWindow->y, aWindow->width, aWindow->height); michael@0: michael@0: // save the the rect location within the browser window. michael@0: mPluginPort = newPort; michael@0: michael@0: // move the port to our shared surface origin michael@0: newPort.MoveTo(0,0); michael@0: michael@0: // check to see if we have the room in shared surface michael@0: if (mSharedSurfaceDib.IsValid() && mSharedSize.Contains(newPort)) { michael@0: // ok to paint michael@0: aRemoteWindow.surfaceHandle = 0; michael@0: return true; michael@0: } michael@0: michael@0: // allocate a new shared surface michael@0: SharedSurfaceRelease(); michael@0: if (NS_FAILED(mSharedSurfaceDib.Create(reinterpret_cast(aWindow->window), michael@0: newPort.width, newPort.height, false))) michael@0: return false; michael@0: michael@0: // save the new shared surface size we just allocated michael@0: mSharedSize = newPort; michael@0: michael@0: base::SharedMemoryHandle handle; michael@0: if (NS_FAILED(mSharedSurfaceDib.ShareToProcess(mParent->ChildProcessHandle(), &handle))) michael@0: return false; michael@0: michael@0: aRemoteWindow.surfaceHandle = handle; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: void michael@0: PluginInstanceParent::SharedSurfaceBeforePaint(RECT& rect, michael@0: NPRemoteEvent& npremoteevent) michael@0: { michael@0: RECT* dr = (RECT*)npremoteevent.event.lParam; michael@0: HDC parentHdc = (HDC)npremoteevent.event.wParam; michael@0: michael@0: nsIntRect dirtyRect(dr->left, dr->top, dr->right-dr->left, dr->bottom-dr->top); michael@0: dirtyRect.MoveBy(-mPluginPort.x, -mPluginPort.y); // should always be smaller than dirtyRect michael@0: michael@0: ::BitBlt(mSharedSurfaceDib.GetHDC(), michael@0: dirtyRect.x, michael@0: dirtyRect.y, michael@0: dirtyRect.width, michael@0: dirtyRect.height, michael@0: parentHdc, michael@0: dr->left, michael@0: dr->top, michael@0: SRCCOPY); michael@0: michael@0: // setup the translated dirty rect we'll send to the child michael@0: rect.left = dirtyRect.x; michael@0: rect.top = dirtyRect.y; michael@0: rect.right = dirtyRect.x + dirtyRect.width; michael@0: rect.bottom = dirtyRect.y + dirtyRect.height; michael@0: michael@0: npremoteevent.event.wParam = WPARAM(0); michael@0: npremoteevent.event.lParam = LPARAM(&rect); michael@0: } michael@0: michael@0: void michael@0: PluginInstanceParent::SharedSurfaceAfterPaint(NPEvent* npevent) michael@0: { michael@0: RECT* dr = (RECT*)npevent->lParam; michael@0: HDC parentHdc = (HDC)npevent->wParam; michael@0: michael@0: nsIntRect dirtyRect(dr->left, dr->top, dr->right-dr->left, dr->bottom-dr->top); michael@0: dirtyRect.MoveBy(-mPluginPort.x, -mPluginPort.y); michael@0: michael@0: // src copy the shared dib into the parent surface we are handed. michael@0: ::BitBlt(parentHdc, michael@0: dr->left, michael@0: dr->top, michael@0: dirtyRect.width, michael@0: dirtyRect.height, michael@0: mSharedSurfaceDib.GetHDC(), michael@0: dirtyRect.x, michael@0: dirtyRect.y, michael@0: SRCCOPY); michael@0: } michael@0: michael@0: #endif // defined(OS_WIN) michael@0: michael@0: bool michael@0: PluginInstanceParent::AnswerPluginFocusChange(const bool& gotFocus) michael@0: { michael@0: PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION)); michael@0: michael@0: // Currently only in use on windows - an rpc event we receive from the michael@0: // child when it's plugin window (or one of it's children) receives keyboard michael@0: // focus. We forward the event down to widget so the dom/focus manager can michael@0: // be updated. michael@0: #if defined(OS_WIN) michael@0: ::SendMessage(mPluginHWND, gOOPPPluginFocusEvent, gotFocus ? 1 : 0, 0); michael@0: return true; michael@0: #else michael@0: NS_NOTREACHED("PluginInstanceParent::AnswerPluginFocusChange not implemented!"); michael@0: return false; michael@0: #endif michael@0: }