1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is Mozilla Plugin App.
18 * The Initial Developer of the Original Code is
19 * Chris Jones <jones.chris.g@gmail.com>
20 * Portions created by the Initial Developer are Copyright (C) 2009
21 * the Initial Developer. All Rights Reserved.
24 * Jim Mathies <jmathies@mozilla.com>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #include "PluginInstanceParent.h"
42 #include "BrowserStreamParent.h"
43 #include "PluginModuleParent.h"
44 #include "PluginStreamParent.h"
45 #include "StreamNotifyParent.h"
46 #include "npfunctions.h"
47 #include "nsAutoPtr.h"
48 #include "mozilla/unused.h"
49 #include "gfxASurface.h"
50 #include "gfxContext.h"
51 #include "gfxPlatform.h"
52 #include "gfxSharedImageSurface.h"
54 #include "gfxXlibSurface.h"
56 #include "gfxContext.h"
62 #include "mozilla/gfx/SharedDIBSurface.h"
64 using mozilla::gfx::SharedDIBSurface
;
66 // Plugin focus event for widget.
67 extern const PRUnichar
* kOOPPPluginFocusEventId
;
68 UINT gOOPPPluginFocusEvent
=
69 RegisterWindowMessage(kOOPPPluginFocusEventId
);
70 extern const PRUnichar
* kFlashFullscreenClass
;
71 UINT gOOPPSpinNativeLoopEvent
=
72 RegisterWindowMessage(L
"SyncChannel Spin Inner Loop Message");
73 UINT gOOPPStopNativeLoopEvent
=
74 RegisterWindowMessage(L
"SyncChannel Stop Inner Loop Message");
75 #elif defined(MOZ_WIDGET_GTK2)
77 #elif defined(XP_MACOSX)
78 #include <ApplicationServices/ApplicationServices.h>
79 #endif // defined(XP_MACOSX)
81 using namespace mozilla::plugins
;
83 PluginInstanceParent::PluginInstanceParent(PluginModuleParent
* parent
,
85 const nsCString
& aMimeType
,
86 const NPNetscapeFuncs
* npniface
)
90 , mWindowType(NPWindowTypeWindow
)
93 , mPluginWndProc(NULL
)
94 , mNestedEventState(false)
95 #endif // defined(XP_WIN)
97 #if defined(XP_MACOSX)
100 , mShColorSpace(nsnull
)
101 , mDrawingModel(NPDrawingModelCoreGraphics
)
105 InitQuirksModes(aMimeType
);
109 PluginInstanceParent::InitQuirksModes(const nsCString
& aMimeType
)
112 NS_NAMED_LITERAL_CSTRING(flash
, "application/x-shockwave-flash");
113 // Flash sends us Invalidate events so we will use those
114 // instead of the refresh timer.
115 if (!FindInReadable(flash
, aMimeType
)) {
116 mQuirks
|= COREANIMATION_REFRESH_TIMER
;
121 PluginInstanceParent::~PluginInstanceParent()
127 NS_ASSERTION(!(mPluginHWND
|| mPluginWndProc
),
128 "Subclass was not reset correctly before the dtor was reached!");
130 #if defined(OS_MACOSX)
131 if (mShWidth
!= 0 && mShHeight
!= 0) {
132 DeallocShmem(mShSurface
);
135 ::CGColorSpaceRelease(mShColorSpace
);
138 if (mDrawingModel
== NPDrawingModelCoreAnimation
) {
139 mParent
->RemoveFromRefreshTimer(this);
145 PluginInstanceParent::Init()
147 return !!mScriptableObjects
.Init();
153 ActorCollect(const void* aKey
,
154 PluginScriptableObjectParent
* aData
,
157 nsTArray
<PluginScriptableObjectParent
*>* objects
=
158 reinterpret_cast<nsTArray
<PluginScriptableObjectParent
*>*>(aUserData
);
159 return objects
->AppendElement(aData
) ? PL_DHASH_NEXT
: PL_DHASH_STOP
;
162 } // anonymous namespace
165 PluginInstanceParent::ActorDestroy(ActorDestroyReason why
)
168 if (why
== AbnormalShutdown
) {
169 // If the plugin process crashes, this is the only
170 // chance we get to destroy resources.
171 SharedSurfaceRelease();
172 UnsubclassPluginWindow();
175 // After this method, the data backing the remote surface may no
176 // longer be calid. The X surface may be destroyed, or the shared
177 // memory backing this surface may no longer be valid. The right
178 // way to inform the nsObjectFrame that the surface is no longer
179 // valid is with an invalidate call.
181 mFrontSurface
= NULL
;
182 const NPRect rect
= {0, 0, 0, 0};
183 RecvNPN_InvalidateRect(rect
);
185 XSync(DefaultXDisplay(), False
);
191 PluginInstanceParent::Destroy()
194 if (!CallNPP_Destroy(&retval
))
195 retval
= NPERR_GENERIC_ERROR
;
198 SharedSurfaceRelease();
199 UnsubclassPluginWindow();
205 PBrowserStreamParent
*
206 PluginInstanceParent::AllocPBrowserStream(const nsCString
& url
,
207 const uint32_t& length
,
208 const uint32_t& lastmodified
,
209 PStreamNotifyParent
* notifyData
,
210 const nsCString
& headers
,
211 const nsCString
& mimeType
,
212 const bool& seekable
,
216 NS_RUNTIMEABORT("Not reachable");
221 PluginInstanceParent::DeallocPBrowserStream(PBrowserStreamParent
* stream
)
228 PluginInstanceParent::AllocPPluginStream(const nsCString
& mimeType
,
229 const nsCString
& target
,
232 return new PluginStreamParent(this, mimeType
, target
, result
);
236 PluginInstanceParent::DeallocPPluginStream(PPluginStreamParent
* stream
)
243 PluginInstanceParent::AnswerNPN_GetValue_NPNVjavascriptEnabledBool(
248 *result
= mNPNIface
->getvalue(mNPP
, NPNVjavascriptEnabledBool
, &v
);
254 PluginInstanceParent::AnswerNPN_GetValue_NPNVisOfflineBool(bool* value
,
258 *result
= mNPNIface
->getvalue(mNPP
, NPNVisOfflineBool
, &v
);
264 PluginInstanceParent::AnswerNPN_GetValue_NPNVnetscapeWindow(NativeWindowHandle
* value
,
269 #elif defined(MOZ_X11)
271 #elif defined(XP_MACOSX)
273 #elif defined(ANDROID)
274 #warning Need Android impl
277 #warning Implement me
280 *result
= mNPNIface
->getvalue(mNPP
, NPNVnetscapeWindow
, &id
);
286 PluginInstanceParent::InternalGetValueForNPObject(
287 NPNVariable aVariable
,
288 PPluginScriptableObjectParent
** aValue
,
292 NPError result
= mNPNIface
->getvalue(mNPP
, aVariable
, (void*)&npobject
);
293 if (result
== NPERR_NO_ERROR
) {
294 NS_ASSERTION(npobject
, "Shouldn't return null and NPERR_NO_ERROR!");
296 PluginScriptableObjectParent
* actor
= GetActorForNPObject(npobject
);
297 mNPNIface
->releaseobject(npobject
);
300 *aResult
= NPERR_NO_ERROR
;
304 NS_ERROR("Failed to get actor!");
305 result
= NPERR_GENERIC_ERROR
;
314 PluginInstanceParent::AnswerNPN_GetValue_NPNVWindowNPObject(
315 PPluginScriptableObjectParent
** aValue
,
318 return InternalGetValueForNPObject(NPNVWindowNPObject
, aValue
, aResult
);
322 PluginInstanceParent::AnswerNPN_GetValue_NPNVPluginElementNPObject(
323 PPluginScriptableObjectParent
** aValue
,
326 return InternalGetValueForNPObject(NPNVPluginElementNPObject
, aValue
,
331 PluginInstanceParent::AnswerNPN_GetValue_NPNVprivateModeBool(bool* value
,
335 *result
= mNPNIface
->getvalue(mNPP
, NPNVprivateModeBool
, &v
);
341 PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginWindow(
342 const bool& windowed
, NPError
* result
)
344 NPBool isWindowed
= windowed
;
345 *result
= mNPNIface
->setvalue(mNPP
, NPPVpluginWindowBool
,
351 PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginTransparent(
352 const bool& transparent
, NPError
* result
)
354 NPBool isTransparent
= transparent
;
355 *result
= mNPNIface
->setvalue(mNPP
, NPPVpluginTransparentBool
,
356 (void*)isTransparent
);
361 PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginDrawingModel(
362 const int& drawingModel
, NPError
* result
)
365 if (drawingModel
== NPDrawingModelCoreAnimation
||
366 drawingModel
== NPDrawingModelInvalidatingCoreAnimation
) {
367 // We need to request CoreGraphics otherwise
368 // the nsObjectFrame will try to draw a CALayer
369 // that can not be shared across process.
370 mDrawingModel
= drawingModel
;
371 *result
= mNPNIface
->setvalue(mNPP
, NPPVpluginDrawingModel
,
372 (void*)NPDrawingModelCoreGraphics
);
373 if (drawingModel
== NPDrawingModelCoreAnimation
&&
374 mQuirks
& COREANIMATION_REFRESH_TIMER
) {
375 mParent
->AddToRefreshTimer(this);
378 mDrawingModel
= drawingModel
;
379 *result
= mNPNIface
->setvalue(mNPP
, NPPVpluginDrawingModel
,
380 (void*)drawingModel
);
384 *result
= NPERR_GENERIC_ERROR
;
390 PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginEventModel(
391 const int& eventModel
, NPError
* result
)
394 *result
= mNPNIface
->setvalue(mNPP
, NPPVpluginEventModel
,
398 *result
= NPERR_GENERIC_ERROR
;
404 PluginInstanceParent::AnswerNPN_GetURL(const nsCString
& url
,
405 const nsCString
& target
,
408 *result
= mNPNIface
->geturl(mNPP
,
409 NullableStringGet(url
),
410 NullableStringGet(target
));
415 PluginInstanceParent::AnswerNPN_PostURL(const nsCString
& url
,
416 const nsCString
& target
,
417 const nsCString
& buffer
,
421 *result
= mNPNIface
->posturl(mNPP
, url
.get(), NullableStringGet(target
),
422 buffer
.Length(), buffer
.get(), file
);
427 PluginInstanceParent::AllocPStreamNotify(const nsCString
& url
,
428 const nsCString
& target
,
430 const nsCString
& buffer
,
434 return new StreamNotifyParent();
438 PluginInstanceParent::AnswerPStreamNotifyConstructor(PStreamNotifyParent
* actor
,
439 const nsCString
& url
,
440 const nsCString
& target
,
442 const nsCString
& buffer
,
446 bool streamDestroyed
= false;
447 static_cast<StreamNotifyParent
*>(actor
)->
448 SetDestructionFlag(&streamDestroyed
);
451 *result
= mNPNIface
->geturlnotify(mNPP
,
452 NullableStringGet(url
),
453 NullableStringGet(target
),
457 *result
= mNPNIface
->posturlnotify(mNPP
,
458 NullableStringGet(url
),
459 NullableStringGet(target
),
461 NullableStringGet(buffer
),
465 if (!streamDestroyed
) {
466 static_cast<StreamNotifyParent
*>(actor
)->ClearDestructionFlag();
467 if (*result
!= NPERR_NO_ERROR
)
468 return PStreamNotifyParent::Send__delete__(actor
,
469 NPERR_GENERIC_ERROR
);
476 PluginInstanceParent::DeallocPStreamNotify(PStreamNotifyParent
* notifyData
)
483 PluginInstanceParent::RecvNPN_InvalidateRect(const NPRect
& rect
)
485 mNPNIface
->invalidaterect(mNPP
, const_cast<NPRect
*>(&rect
));
490 PluginInstanceParent::RecvShow(const NPRect
& updatedRect
,
491 const SurfaceDescriptor
& newSurface
,
492 SurfaceDescriptor
* prevSurface
)
494 nsRefPtr
<gfxASurface
> surface
;
495 if (newSurface
.type() == SurfaceDescriptor::TShmem
) {
496 if (!newSurface
.get_Shmem().IsReadable()) {
497 NS_WARNING("back surface not readable");
500 surface
= new gfxSharedImageSurface(newSurface
.get_Shmem());
503 else if (newSurface
.type() == SurfaceDescriptor::TSurfaceDescriptorX11
) {
504 SurfaceDescriptorX11 xdesc
= newSurface
.get_SurfaceDescriptorX11();
505 XRenderPictFormat pf
;
506 pf
.id
= xdesc
.xrenderPictID();
507 XRenderPictFormat
*incFormat
=
508 XRenderFindFormat(DefaultXDisplay(), PictFormatID
, &pf
, 0);
510 new gfxXlibSurface(DefaultScreenOfDisplay(DefaultXDisplay()),
511 xdesc
.XID(), incFormat
, xdesc
.size());
515 else if (newSurface
.type() == SurfaceDescriptor::TSurfaceDescriptorWin
) {
516 SurfaceDescriptorWin windesc
= newSurface
.get_SurfaceDescriptorWin();
517 SharedDIBSurface
* dibsurf
= new SharedDIBSurface();
518 if (dibsurf
->Attach(windesc
.handle(), windesc
.size().width
, windesc
.size().height
, windesc
.transparent()))
525 mFrontSurface
->GetType() == gfxASurface::SurfaceTypeXlib
)
526 XSync(DefaultXDisplay(), False
);
529 if (mFrontSurface
&& gfxSharedImageSurface::IsSharedImage(mFrontSurface
))
530 *prevSurface
= static_cast<gfxSharedImageSurface
*>(mFrontSurface
.get())->GetShmem();
532 *prevSurface
= null_t();
534 mFrontSurface
= surface
;
535 RecvNPN_InvalidateRect(updatedRect
);
541 PluginInstanceParent::AsyncSetWindow(NPWindow
* aWindow
)
543 NPRemoteWindow window
;
544 mWindowType
= aWindow
->type
;
545 window
.window
= reinterpret_cast<unsigned long>(aWindow
->window
);
546 window
.x
= aWindow
->x
;
547 window
.y
= aWindow
->y
;
548 window
.width
= aWindow
->width
;
549 window
.height
= aWindow
->height
;
550 window
.clipRect
= aWindow
->clipRect
;
551 window
.type
= aWindow
->type
;
552 if (!SendAsyncSetWindow(gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType(),
554 return NS_ERROR_FAILURE
;
560 PluginInstanceParent::GetSurface(gfxASurface
** aSurface
)
563 NS_ADDREF(*aSurface
= mFrontSurface
);
566 return NS_ERROR_NOT_AVAILABLE
;
570 PluginInstanceParent::NPP_SetWindow(const NPWindow
* aWindow
)
572 PLUGIN_LOG_DEBUG(("%s (aWindow=%p)", FULLFUNCTION
, (void*) aWindow
));
574 NS_ENSURE_TRUE(aWindow
, NPERR_GENERIC_ERROR
);
576 NPRemoteWindow window
;
577 mWindowType
= aWindow
->type
;
580 // On windowless controls, reset the shared memory surface as needed.
581 if (mWindowType
== NPWindowTypeDrawable
) {
582 // SharedSurfaceSetWindow will take care of NPRemoteWindow.
583 if (!SharedSurfaceSetWindow(aWindow
, window
)) {
584 return NPERR_OUT_OF_MEMORY_ERROR
;
588 SubclassPluginWindow(reinterpret_cast<HWND
>(aWindow
->window
));
590 window
.window
= reinterpret_cast<unsigned long>(aWindow
->window
);
591 window
.x
= aWindow
->x
;
592 window
.y
= aWindow
->y
;
593 window
.width
= aWindow
->width
;
594 window
.height
= aWindow
->height
;
595 window
.type
= aWindow
->type
;
598 window
.window
= reinterpret_cast<unsigned long>(aWindow
->window
);
599 window
.x
= aWindow
->x
;
600 window
.y
= aWindow
->y
;
601 window
.width
= aWindow
->width
;
602 window
.height
= aWindow
->height
;
603 window
.clipRect
= aWindow
->clipRect
; // MacOS specific
604 window
.type
= aWindow
->type
;
607 #if defined(XP_MACOSX)
608 if (mShWidth
!= window
.width
|| mShHeight
!= window
.height
) {
609 if (mDrawingModel
== NPDrawingModelCoreAnimation
||
610 mDrawingModel
== NPDrawingModelInvalidatingCoreAnimation
) {
614 mIOSurface
= nsIOSurface::CreateIOSurface(window
.width
, window
.height
);
615 } else if (mShWidth
* mShHeight
!= window
.width
* window
.height
) {
616 if (mShWidth
!= 0 && mShHeight
!= 0) {
617 DeallocShmem(mShSurface
);
622 if (window
.width
!= 0 && window
.height
!= 0) {
623 if (!AllocShmem(window
.width
* window
.height
*4,
624 SharedMemory::TYPE_BASIC
, &mShSurface
)) {
625 PLUGIN_LOG_DEBUG(("Shared memory could not be allocated."));
626 return NPERR_GENERIC_ERROR
;
630 mShWidth
= window
.width
;
631 mShHeight
= window
.height
;
635 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
636 const NPSetWindowCallbackStruct
* ws_info
=
637 static_cast<NPSetWindowCallbackStruct
*>(aWindow
->ws_info
);
638 window
.visualID
= ws_info
->visual
? ws_info
->visual
->visualid
: None
;
639 window
.colormap
= ws_info
->colormap
;
642 if (!CallNPP_SetWindow(window
))
643 return NPERR_GENERIC_ERROR
;
645 return NPERR_NO_ERROR
;
649 PluginInstanceParent::NPP_GetValue(NPPVariable aVariable
,
655 case NPPVpluginNeedsXEmbed
: {
659 if (!CallNPP_GetValue_NPPVpluginNeedsXEmbed(&needsXEmbed
, &rv
)) {
660 return NPERR_GENERIC_ERROR
;
663 if (NPERR_NO_ERROR
!= rv
) {
667 (*(NPBool
*)_retval
) = needsXEmbed
;
668 return NPERR_NO_ERROR
;
672 case NPPVpluginScriptableNPObject
: {
673 PPluginScriptableObjectParent
* actor
;
675 if (!CallNPP_GetValue_NPPVpluginScriptableNPObject(&actor
, &rv
)) {
676 return NPERR_GENERIC_ERROR
;
679 if (NPERR_NO_ERROR
!= rv
) {
684 NS_ERROR("NPPVpluginScriptableNPObject succeeded but null.");
685 return NPERR_GENERIC_ERROR
;
688 const NPNetscapeFuncs
* npn
= mParent
->GetNetscapeFuncs();
690 NS_WARNING("No netscape functions?!");
691 return NPERR_GENERIC_ERROR
;
695 static_cast<PluginScriptableObjectParent
*>(actor
)->GetObject(true);
696 NS_ASSERTION(object
, "This shouldn't ever be null!");
698 (*(NPObject
**)_retval
) = npn
->retainobject(object
);
699 return NPERR_NO_ERROR
;
703 PR_LOG(gPluginLog
, PR_LOG_WARNING
,
704 ("In PluginInstanceParent::NPP_GetValue: Unhandled NPPVariable %i (%s)",
705 (int) aVariable
, NPPVariableToString(aVariable
)));
706 return NPERR_GENERIC_ERROR
;
711 PluginInstanceParent::NPP_SetValue(NPNVariable variable
, void* value
)
714 case NPNVprivateModeBool
:
716 if (!CallNPP_SetValue_NPNVprivateModeBool(*static_cast<NPBool
*>(value
),
718 return NPERR_GENERIC_ERROR
;
723 NS_ERROR("Unhandled NPNVariable in NPP_SetValue");
724 PR_LOG(gPluginLog
, PR_LOG_WARNING
,
725 ("In PluginInstanceParent::NPP_SetValue: Unhandled NPNVariable %i (%s)",
726 (int) variable
, NPNVariableToString(variable
)));
727 return NPERR_GENERIC_ERROR
;
732 PluginInstanceParent::NPP_HandleEvent(void* event
)
734 PLUGIN_LOG_DEBUG_FUNCTION
;
736 #if defined(XP_MACOSX)
737 NPCocoaEvent
* npevent
= reinterpret_cast<NPCocoaEvent
*>(event
);
739 NPEvent
* npevent
= reinterpret_cast<NPEvent
*>(event
);
741 NPRemoteEvent npremoteevent
;
742 npremoteevent
.event
= *npevent
;
746 if (mWindowType
== NPWindowTypeDrawable
) {
747 if (DoublePassRenderingEvent() == npevent
->event
) {
748 CallPaint(npremoteevent
, &handled
);
752 switch (npevent
->event
) {
756 SharedSurfaceBeforePaint(rect
, npremoteevent
);
757 CallPaint(npremoteevent
, &handled
);
758 SharedSurfaceAfterPaint(npevent
);
765 // When the user selects fullscreen mode in Flash video players,
766 // WM_KILLFOCUS will be delayed by deferred event processing:
767 // WM_LBUTTONUP results in a call to CreateWindow within Flash,
768 // which fires WM_KILLFOCUS. Delayed delivery causes Flash to
769 // misinterpret the event, dropping back out of fullscreen. Trap
770 // this event and drop it.
771 PRUnichar szClass
[26];
772 HWND hwnd
= GetForegroundWindow();
773 if (hwnd
&& hwnd
!= mPluginHWND
&&
774 GetClassNameW(hwnd
, szClass
,
775 sizeof(szClass
)/sizeof(PRUnichar
)) &&
776 !wcscmp(szClass
, kFlashFullscreenClass
)) {
782 case WM_WINDOWPOSCHANGED
:
784 // We send this in nsObjectFrame just before painting
785 SendWindowPosChanged(npremoteevent
);
786 // nsObjectFrame doesn't care whether we handle this
787 // or not, just returning 1 for good hygiene
796 switch (npevent
->type
) {
798 PLUGIN_LOG_DEBUG((" schlepping drawable 0x%lx across the pipe\n",
799 npevent
->xgraphicsexpose
.drawable
));
800 // Make sure the X server has created the Drawable and completes any
801 // drawing before the plugin draws on top.
803 // XSync() waits for the X server to complete. Really this parent
804 // process does not need to wait; the child is the process that needs
805 // to wait. A possibly-slightly-better alternative would be to send
806 // an X event to the child that the child would wait for.
807 XSync(DefaultXDisplay(), False
);
809 return CallPaint(npremoteevent
, &handled
) ? handled
: 0;
812 // Release any active pointer grab so that the plugin X client can
813 // grab the pointer if it wishes.
814 Display
*dpy
= DefaultXDisplay();
815 # ifdef MOZ_WIDGET_GTK2
816 // GDK attempts to (asynchronously) track whether there is an active
817 // grab so ungrab through GDK.
818 gdk_pointer_ungrab(npevent
->xbutton
.time
);
820 XUngrabPointer(dpy
, npevent
->xbutton
.time
);
822 // Wait for the ungrab to complete.
829 if (npevent
->type
== NPCocoaEventDrawRect
) {
830 if (mDrawingModel
== NPDrawingModelCoreAnimation
||
831 mDrawingModel
== NPDrawingModelInvalidatingCoreAnimation
) {
833 NS_ERROR("No IOSurface allocated.");
836 if (!CallNPP_HandleEvent_IOSurface(npremoteevent
,
837 mIOSurface
->GetIOSurfaceID(),
839 return false; // no good way to handle errors here...
841 CGContextRef cgContext
= npevent
->data
.draw
.context
;
842 if (!mShColorSpace
) {
843 mShColorSpace
= CreateSystemColorSpace();
845 if (!mShColorSpace
) {
846 PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace."));
849 nsCARenderer::DrawSurfaceToCGContext(cgContext
, mIOSurface
,
851 npevent
->data
.draw
.x
,
852 npevent
->data
.draw
.y
,
853 npevent
->data
.draw
.width
,
854 npevent
->data
.draw
.height
);
857 if (mShWidth
== 0 && mShHeight
== 0) {
858 PLUGIN_LOG_DEBUG(("NPCocoaEventDrawRect on window of size 0."));
861 if (!mShSurface
.IsReadable()) {
862 PLUGIN_LOG_DEBUG(("Shmem is not readable."));
866 if (!CallNPP_HandleEvent_Shmem(npremoteevent
, mShSurface
,
867 &handled
, &mShSurface
))
868 return false; // no good way to handle errors here...
870 if (!mShSurface
.IsReadable()) {
871 PLUGIN_LOG_DEBUG(("Shmem not returned. Either the plugin crashed "
872 "or we have a bug."));
876 char* shContextByte
= mShSurface
.get
<char>();
878 if (!mShColorSpace
) {
879 mShColorSpace
= CreateSystemColorSpace();
881 if (!mShColorSpace
) {
882 PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace."));
885 CGContextRef shContext
= ::CGBitmapContextCreate(shContextByte
,
886 mShWidth
, mShHeight
, 8,
887 mShWidth
*4, mShColorSpace
,
888 kCGImageAlphaPremultipliedFirst
|
889 kCGBitmapByteOrder32Host
);
891 PLUGIN_LOG_DEBUG(("Could not allocate CGBitmapContext."));
895 CGImageRef shImage
= ::CGBitmapContextCreateImage(shContext
);
897 CGContextRef cgContext
= npevent
->data
.draw
.context
;
899 ::CGContextDrawImage(cgContext
,
900 CGRectMake(0,0,mShWidth
,mShHeight
),
902 ::CGImageRelease(shImage
);
904 ::CGContextRelease(shContext
);
907 ::CGContextRelease(shContext
);
913 if (!CallNPP_HandleEvent(npremoteevent
, &handled
))
914 return 0; // no good way to handle errors here...
920 PluginInstanceParent::NPP_NewStream(NPMIMEType type
, NPStream
* stream
,
921 NPBool seekable
, uint16_t* stype
)
923 PLUGIN_LOG_DEBUG(("%s (type=%s, stream=%p, seekable=%i)",
924 FULLFUNCTION
, (char*) type
, (void*) stream
, (int) seekable
));
926 BrowserStreamParent
* bs
= new BrowserStreamParent(this, stream
);
929 if (!CallPBrowserStreamConstructor(bs
,
930 NullableString(stream
->url
),
932 stream
->lastmodified
,
933 static_cast<PStreamNotifyParent
*>(stream
->notifyData
),
934 NullableString(stream
->headers
),
935 NullableString(type
), seekable
,
937 return NPERR_GENERIC_ERROR
;
939 if (NPERR_NO_ERROR
!= err
)
940 unused
<< PBrowserStreamParent::Send__delete__(bs
);
946 PluginInstanceParent::NPP_DestroyStream(NPStream
* stream
, NPReason reason
)
948 PLUGIN_LOG_DEBUG(("%s (stream=%p, reason=%i)",
949 FULLFUNCTION
, (void*) stream
, (int) reason
));
951 AStream
* s
= static_cast<AStream
*>(stream
->pdata
);
952 if (s
->IsBrowserStream()) {
953 BrowserStreamParent
* sp
=
954 static_cast<BrowserStreamParent
*>(s
);
955 if (sp
->mNPP
!= this)
956 NS_RUNTIMEABORT("Mismatched plugin data");
958 sp
->NPP_DestroyStream(reason
);
959 return NPERR_NO_ERROR
;
962 PluginStreamParent
* sp
=
963 static_cast<PluginStreamParent
*>(s
);
964 if (sp
->mInstance
!= this)
965 NS_RUNTIMEABORT("Mismatched plugin data");
967 return PPluginStreamParent::Call__delete__(sp
, reason
, false) ?
968 NPERR_NO_ERROR
: NPERR_GENERIC_ERROR
;
973 PluginInstanceParent::NPP_Print(NPPrint
* platformPrint
)
975 // TODO: implement me
976 NS_ERROR("Not implemented");
979 PPluginScriptableObjectParent
*
980 PluginInstanceParent::AllocPPluginScriptableObject()
982 return new PluginScriptableObjectParent(Proxy
);
988 struct ActorSearchData
990 PluginScriptableObjectParent
* actor
;
995 ActorSearch(const void* aKey
,
996 PluginScriptableObjectParent
* aData
,
999 ActorSearchData
* asd
= reinterpret_cast<ActorSearchData
*>(aUserData
);
1000 if (asd
->actor
== aData
) {
1002 return PL_DHASH_STOP
;
1004 return PL_DHASH_NEXT
;
1007 } // anonymous namespace
1011 PluginInstanceParent::DeallocPPluginScriptableObject(
1012 PPluginScriptableObjectParent
* aObject
)
1014 PluginScriptableObjectParent
* actor
=
1015 static_cast<PluginScriptableObjectParent
*>(aObject
);
1017 NPObject
* object
= actor
->GetObject(false);
1019 NS_ASSERTION(mScriptableObjects
.Get(object
, nsnull
),
1020 "NPObject not in the hash!");
1021 mScriptableObjects
.Remove(object
);
1025 ActorSearchData asd
= { actor
, false };
1026 mScriptableObjects
.EnumerateRead(ActorSearch
, &asd
);
1027 NS_ASSERTION(!asd
.found
, "Actor in the hash with a null NPObject!");
1036 PluginInstanceParent::RecvPPluginScriptableObjectConstructor(
1037 PPluginScriptableObjectParent
* aActor
)
1039 // This is only called in response to the child process requesting the
1040 // creation of an actor. This actor will represent an NPObject that is
1041 // created by the plugin and returned to the browser.
1042 PluginScriptableObjectParent
* actor
=
1043 static_cast<PluginScriptableObjectParent
*>(aActor
);
1044 NS_ASSERTION(!actor
->GetObject(false), "Actor already has an object?!");
1046 actor
->InitializeProxy();
1047 NS_ASSERTION(actor
->GetObject(false), "Actor should have an object!");
1053 PluginInstanceParent::NPP_URLNotify(const char* url
, NPReason reason
,
1056 PLUGIN_LOG_DEBUG(("%s (%s, %i, %p)",
1057 FULLFUNCTION
, url
, (int) reason
, notifyData
));
1059 PStreamNotifyParent
* streamNotify
=
1060 static_cast<PStreamNotifyParent
*>(notifyData
);
1061 unused
<< PStreamNotifyParent::Send__delete__(streamNotify
, reason
);
1065 PluginInstanceParent::RegisterNPObjectForActor(
1067 PluginScriptableObjectParent
* aActor
)
1069 NS_ASSERTION(aObject
&& aActor
, "Null pointers!");
1070 NS_ASSERTION(mScriptableObjects
.IsInitialized(), "Hash not initialized!");
1071 NS_ASSERTION(!mScriptableObjects
.Get(aObject
, nsnull
), "Duplicate entry!");
1072 return !!mScriptableObjects
.Put(aObject
, aActor
);
1076 PluginInstanceParent::UnregisterNPObject(NPObject
* aObject
)
1078 NS_ASSERTION(aObject
, "Null pointer!");
1079 NS_ASSERTION(mScriptableObjects
.IsInitialized(), "Hash not initialized!");
1080 NS_ASSERTION(mScriptableObjects
.Get(aObject
, nsnull
), "Unknown entry!");
1081 mScriptableObjects
.Remove(aObject
);
1084 PluginScriptableObjectParent
*
1085 PluginInstanceParent::GetActorForNPObject(NPObject
* aObject
)
1087 NS_ASSERTION(aObject
, "Null pointer!");
1089 if (aObject
->_class
== PluginScriptableObjectParent::GetClass()) {
1091 ParentNPObject
* object
= static_cast<ParentNPObject
*>(aObject
);
1092 NS_ASSERTION(object
->parent
, "Null actor!");
1093 return object
->parent
;
1096 PluginScriptableObjectParent
* actor
;
1097 if (mScriptableObjects
.Get(aObject
, &actor
)) {
1101 actor
= new PluginScriptableObjectParent(LocalObject
);
1103 NS_ERROR("Out of memory!");
1107 if (!SendPPluginScriptableObjectConstructor(actor
)) {
1108 NS_WARNING("Failed to send constructor message!");
1112 actor
->InitializeLocal(aObject
);
1117 PluginInstanceParent::AnswerNPN_PushPopupsEnabledState(const bool& aState
)
1119 mNPNIface
->pushpopupsenabledstate(mNPP
, aState
? 1 : 0);
1124 PluginInstanceParent::AnswerNPN_PopPopupsEnabledState()
1126 mNPNIface
->poppopupsenabledstate(mNPP
);
1131 PluginInstanceParent::AnswerNPN_GetValueForURL(const NPNURLVariable
& variable
,
1132 const nsCString
& url
,
1139 *result
= mNPNIface
->getvalueforurl(mNPP
, (NPNURLVariable
) variable
,
1140 url
.get(), &v
, &len
);
1141 if (NPERR_NO_ERROR
== *result
)
1142 value
->Adopt(v
, len
);
1148 PluginInstanceParent::AnswerNPN_SetValueForURL(const NPNURLVariable
& variable
,
1149 const nsCString
& url
,
1150 const nsCString
& value
,
1153 *result
= mNPNIface
->setvalueforurl(mNPP
, (NPNURLVariable
) variable
,
1154 url
.get(), value
.get(),
1160 PluginInstanceParent::AnswerNPN_GetAuthenticationInfo(const nsCString
& protocol
,
1161 const nsCString
& host
,
1162 const int32_t& port
,
1163 const nsCString
& scheme
,
1164 const nsCString
& realm
,
1165 nsCString
* username
,
1166 nsCString
* password
,
1174 *result
= mNPNIface
->getauthenticationinfo(mNPP
, protocol
.get(),
1176 scheme
.get(), realm
.get(),
1177 &u
, &ulen
, &p
, &plen
);
1178 if (NPERR_NO_ERROR
== *result
) {
1179 username
->Adopt(u
, ulen
);
1180 password
->Adopt(p
, plen
);
1186 PluginInstanceParent::AnswerNPN_ConvertPoint(const double& sourceX
,
1187 const bool& ignoreDestX
,
1188 const double& sourceY
,
1189 const bool& ignoreDestY
,
1190 const NPCoordinateSpace
& sourceSpace
,
1191 const NPCoordinateSpace
& destSpace
,
1196 *result
= mNPNIface
->convertpoint(mNPP
, sourceX
, sourceY
, sourceSpace
,
1197 ignoreDestX
? nsnull
: destX
,
1198 ignoreDestY
? nsnull
: destY
,
1207 plugin focus changes between processes
1209 focus from dom -> child:
1210 Focus manager calls on widget to set the focus on the window.
1211 We pick up the resulting wm_setfocus event here, and forward
1212 that over ipc to the child which calls set focus on itself.
1214 focus from child -> focus manager:
1215 Child picks up the local wm_setfocus and sends it via ipc over
1216 here. We then post a custom event to widget/src/windows/nswindow
1217 which fires off a gui event letting the browser know.
1220 static const PRUnichar kPluginInstanceParentProperty
[] =
1221 L
"PluginInstanceParentProperty";
1225 PluginInstanceParent::PluginWindowHookProc(HWND hWnd
,
1230 PluginInstanceParent
* self
= reinterpret_cast<PluginInstanceParent
*>(
1231 ::GetPropW(hWnd
, kPluginInstanceParentProperty
));
1233 NS_NOTREACHED("PluginInstanceParent::PluginWindowHookProc null this ptr!");
1234 return DefWindowProc(hWnd
, message
, wParam
, lParam
);
1237 NS_ASSERTION(self
->mPluginHWND
== hWnd
, "Wrong window!");
1241 // Let the child plugin window know it should take focus.
1242 self
->CallSetPluginFocus();
1246 self
->UnsubclassPluginWindow();
1250 return ::CallWindowProc(self
->mPluginWndProc
, hWnd
, message
, wParam
,
1255 PluginInstanceParent::SubclassPluginWindow(HWND aWnd
)
1257 NS_ASSERTION(!(mPluginHWND
&& aWnd
!= mPluginHWND
),
1258 "PluginInstanceParent::SubclassPluginWindow hwnd is not our window!");
1263 (WNDPROC
)::SetWindowLongPtrA(mPluginHWND
, GWLP_WNDPROC
,
1264 reinterpret_cast<LONG_PTR
>(PluginWindowHookProc
));
1265 bool bRes
= ::SetPropW(mPluginHWND
, kPluginInstanceParentProperty
, this);
1266 NS_ASSERTION(mPluginWndProc
,
1267 "PluginInstanceParent::SubclassPluginWindow failed to set subclass!");
1269 "PluginInstanceParent::SubclassPluginWindow failed to set prop!");
1274 PluginInstanceParent::UnsubclassPluginWindow()
1276 if (mPluginHWND
&& mPluginWndProc
) {
1277 ::SetWindowLongPtrA(mPluginHWND
, GWLP_WNDPROC
,
1278 reinterpret_cast<LONG_PTR
>(mPluginWndProc
));
1280 ::RemovePropW(mPluginHWND
, kPluginInstanceParentProperty
);
1282 mPluginWndProc
= NULL
;
1287 /* windowless drawing helpers */
1292 * windowless, offscreen:
1294 * WM_WINDOWPOSCHANGED: origin is relative to container
1295 * setwindow: origin is 0,0
1296 * WM_PAINT: origin is 0,0
1298 * windowless, native:
1300 * WM_WINDOWPOSCHANGED: origin is relative to container
1301 * setwindow: origin is relative to container
1302 * WM_PAINT: origin is relative to container
1304 * PluginInstanceParent:
1306 * painting: mPluginPort (nsIntRect, saved in SetWindow)
1310 PluginInstanceParent::SharedSurfaceRelease()
1312 mSharedSurfaceDib
.Close();
1316 PluginInstanceParent::SharedSurfaceSetWindow(const NPWindow
* aWindow
,
1317 NPRemoteWindow
& aRemoteWindow
)
1319 aRemoteWindow
.window
= nsnull
;
1320 aRemoteWindow
.x
= aWindow
->x
;
1321 aRemoteWindow
.y
= aWindow
->y
;
1322 aRemoteWindow
.width
= aWindow
->width
;
1323 aRemoteWindow
.height
= aWindow
->height
;
1324 aRemoteWindow
.type
= aWindow
->type
;
1326 nsIntRect
newPort(aWindow
->x
, aWindow
->y
, aWindow
->width
, aWindow
->height
);
1328 // save the the rect location within the browser window.
1329 mPluginPort
= newPort
;
1331 // move the port to our shared surface origin
1332 newPort
.MoveTo(0,0);
1334 // check to see if we have the room in shared surface
1335 if (mSharedSurfaceDib
.IsValid() && mSharedSize
.Contains(newPort
)) {
1337 aRemoteWindow
.surfaceHandle
= 0;
1341 // allocate a new shared surface
1342 SharedSurfaceRelease();
1343 if (NS_FAILED(mSharedSurfaceDib
.Create(reinterpret_cast<HDC
>(aWindow
->window
),
1344 newPort
.width
, newPort
.height
, false)))
1347 // save the new shared surface size we just allocated
1348 mSharedSize
= newPort
;
1350 base::SharedMemoryHandle handle
;
1351 if (NS_FAILED(mSharedSurfaceDib
.ShareToProcess(mParent
->ChildProcessHandle(), &handle
)))
1354 aRemoteWindow
.surfaceHandle
= handle
;
1360 PluginInstanceParent::SharedSurfaceBeforePaint(RECT
& rect
,
1361 NPRemoteEvent
& npremoteevent
)
1363 RECT
* dr
= (RECT
*)npremoteevent
.event
.lParam
;
1364 HDC parentHdc
= (HDC
)npremoteevent
.event
.wParam
;
1366 nsIntRect
dirtyRect(dr
->left
, dr
->top
, dr
->right
-dr
->left
, dr
->bottom
-dr
->top
);
1367 dirtyRect
.MoveBy(-mPluginPort
.x
, -mPluginPort
.y
); // should always be smaller than dirtyRect
1369 ::BitBlt(mSharedSurfaceDib
.GetHDC(),
1379 // setup the translated dirty rect we'll send to the child
1380 rect
.left
= dirtyRect
.x
;
1381 rect
.top
= dirtyRect
.y
;
1382 rect
.right
= dirtyRect
.x
+ dirtyRect
.width
;
1383 rect
.bottom
= dirtyRect
.y
+ dirtyRect
.height
;
1385 npremoteevent
.event
.wParam
= WPARAM(0);
1386 npremoteevent
.event
.lParam
= LPARAM(&rect
);
1390 PluginInstanceParent::SharedSurfaceAfterPaint(NPEvent
* npevent
)
1392 RECT
* dr
= (RECT
*)npevent
->lParam
;
1393 HDC parentHdc
= (HDC
)npevent
->wParam
;
1395 nsIntRect
dirtyRect(dr
->left
, dr
->top
, dr
->right
-dr
->left
, dr
->bottom
-dr
->top
);
1396 dirtyRect
.MoveBy(-mPluginPort
.x
, -mPluginPort
.y
);
1398 // src copy the shared dib into the parent surface we are handed.
1404 mSharedSurfaceDib
.GetHDC(),
1410 #endif // defined(OS_WIN)
1413 PluginInstanceParent::AnswerPluginFocusChange(const bool& gotFocus
)
1415 PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION
));
1417 // Currently only in use on windows - an rpc event we receive from the
1418 // child when it's plugin window (or one of it's children) receives keyboard
1419 // focus. We forward the event down to widget so the dom/focus manager can
1422 ::SendMessage(mPluginHWND
, gOOPPPluginFocusEvent
, gotFocus
? 1 : 0, 0);
1425 NS_NOTREACHED("PluginInstanceParent::AnswerPluginFocusChange not implemented!");
1432 PluginInstanceParent::Invalidate()
1434 NPRect windowRect
= {0, 0, mShHeight
, mShWidth
};
1435 RecvNPN_InvalidateRect(windowRect
);