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 "PluginInstanceChild.h"
41 #include "PluginModuleChild.h"
42 #include "BrowserStreamChild.h"
43 #include "PluginStreamChild.h"
44 #include "StreamNotifyChild.h"
45 #include "PluginProcessChild.h"
46 #include "gfxASurface.h"
47 #include "gfxContext.h"
49 #include "gfxXlibSurface.h"
52 #include "mozilla/gfx/SharedDIBSurface.h"
54 using mozilla::gfx::SharedDIBSurface
;
56 #include "gfxSharedImageSurface.h"
58 #include "gfxAlphaRecovery.h"
60 #include "mozilla/ipc/SyncChannel.h"
62 using mozilla::ipc::ProcessChild
;
63 using namespace mozilla::plugins
;
65 #ifdef MOZ_WIDGET_GTK2
70 #include "gtk2xtbin.h"
72 #elif defined(MOZ_WIDGET_QT)
75 #ifndef WM_MOUSEHWHEEL
76 #define WM_MOUSEHWHEEL 0x020E
79 #include "nsWindowsDllInterceptor.h"
81 typedef BOOL (WINAPI
*User32TrackPopupMenu
)(HMENU hMenu
,
88 static WindowsDllInterceptor sUser32Intercept
;
89 static HWND sWinlessPopupSurrogateHWND
= NULL
;
90 static User32TrackPopupMenu sUser32TrackPopupMenuStub
= NULL
;
92 using mozilla::gfx::SharedDIB
;
97 // Flash WM_USER message delay time for PostDelayedTask. Borrowed
98 // from Chromium's web plugin delegate src. See 'flash msg throttling
99 // helpers' section for details.
100 const int kFlashWMUSERMessageThrottleDelayMs
= 5;
102 static const TCHAR kPluginIgnoreSubclassProperty
[] = TEXT("PluginIgnoreSubclassProperty");
104 #elif defined(XP_MACOSX)
105 #include <ApplicationServices/ApplicationServices.h>
106 #endif // defined(XP_MACOSX)
109 struct RunnableMethodTraits
<PluginInstanceChild
>
111 static void RetainCallee(PluginInstanceChild
* obj
) { }
112 static void ReleaseCallee(PluginInstanceChild
* obj
) { }
115 PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs
* aPluginIface
)
116 : mPluginIface(aPluginIface
)
117 , mCachedWindowActor(nsnull
)
118 , mCachedElementActor(nsnull
)
120 , mPluginWindowHWND(0)
122 , mPluginParentHWND(0)
123 , mCachedWinlessPluginHWND(0)
124 , mWinlessPopupSurrogateHWND(0)
125 , mWinlessThrottleOldWndProc(0)
126 , mWinlessHiddenMsgHWND(0)
129 , mAsyncCallMutex("PluginInstanceChild::mAsyncCallMutex")
130 #if defined(OS_MACOSX)
131 #if defined(__i386__)
132 , mEventModel(NPEventModelCarbon
)
134 , mShColorSpace(nsnull
)
136 , mDrawingModel(NPDrawingModelCoreGraphics
)
137 , mCurrentEvent(nsnull
)
139 , mLayersRendering(false)
141 , mCurrentSurfaceActor(NULL
)
142 , mBackSurfaceActor(NULL
)
144 , mAccumulatedInvalidRect(0,0,0,0)
145 , mIsTransparent(false)
146 , mSurfaceType(gfxASurface::SurfaceTypeMax
)
147 , mCurrentInvalidateTask(nsnull
)
148 , mCurrentAsyncSetWindowTask(nsnull
)
149 , mPendingPluginCall(false)
150 , mDoAlphaExtraction(false)
152 , mSurfaceDifferenceRect(0,0,0,0)
153 #if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
154 , mMaemoImageRendering(PR_FALSE
)
157 memset(&mWindow
, 0, sizeof(mWindow
));
158 mData
.ndata
= (void*) this;
159 mData
.pdata
= nsnull
;
160 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
161 mWindow
.ws_info
= &mWsInfo
;
162 memset(&mWsInfo
, 0, sizeof(mWsInfo
));
163 mWsInfo
.display
= DefaultXDisplay();
164 #endif // MOZ_X11 && XP_UNIX && !XP_MACOSX
166 memset(&mAlphaExtract
, 0, sizeof(mAlphaExtract
));
170 HookSystemParametersInfo();
173 // Maemo flash can render plugin with any provided rectangle and not require this quirk.
174 #ifndef MOZ_PLATFORM_MAEMO
175 const char *description
= NULL
;
176 mPluginIface
->getvalue(GetNPP(), NPPVpluginDescriptionString
,
179 NS_NAMED_LITERAL_CSTRING(flash10Head
, "Shockwave Flash 10.");
180 if (StringBeginsWith(nsDependentCString(description
), flash10Head
)) {
181 PluginModuleChild::current()->AddQuirk(PluginModuleChild::QUIRK_FLASH_EXPOSE_COORD_TRANSLATION
);
188 PluginInstanceChild::~PluginInstanceChild()
191 NS_ASSERTION(!mPluginWindowHWND
, "Destroying PluginInstanceChild without NPP_Destroy?");
193 #if defined(OS_MACOSX)
195 ::CGColorSpaceRelease(mShColorSpace
);
198 ::CGContextRelease(mShContext
);
204 PluginInstanceChild::GetQuirks()
206 return PluginModuleChild::current()->GetQuirks();
210 PluginInstanceChild::InternalGetNPObjectForValue(NPNVariable aValue
,
213 PluginScriptableObjectChild
* actor
;
214 NPError result
= NPERR_NO_ERROR
;
217 case NPNVWindowNPObject
:
218 if (!(actor
= mCachedWindowActor
)) {
219 PPluginScriptableObjectChild
* actorProtocol
;
220 CallNPN_GetValue_NPNVWindowNPObject(&actorProtocol
, &result
);
221 if (result
== NPERR_NO_ERROR
) {
222 actor
= mCachedWindowActor
=
223 static_cast<PluginScriptableObjectChild
*>(actorProtocol
);
224 NS_ASSERTION(actor
, "Null actor!");
225 PluginModuleChild::sBrowserFuncs
.retainobject(
226 actor
->GetObject(false));
231 case NPNVPluginElementNPObject
:
232 if (!(actor
= mCachedElementActor
)) {
233 PPluginScriptableObjectChild
* actorProtocol
;
234 CallNPN_GetValue_NPNVPluginElementNPObject(&actorProtocol
,
236 if (result
== NPERR_NO_ERROR
) {
237 actor
= mCachedElementActor
=
238 static_cast<PluginScriptableObjectChild
*>(actorProtocol
);
239 NS_ASSERTION(actor
, "Null actor!");
240 PluginModuleChild::sBrowserFuncs
.retainobject(
241 actor
->GetObject(false));
247 NS_NOTREACHED("Don't know what to do with this value type!");
252 NPError currentResult
;
253 PPluginScriptableObjectChild
* currentActor
;
256 case NPNVWindowNPObject
:
257 CallNPN_GetValue_NPNVWindowNPObject(¤tActor
,
260 case NPNVPluginElementNPObject
:
261 CallNPN_GetValue_NPNVPluginElementNPObject(¤tActor
,
265 NS_NOTREACHED("Don't know what to do with this value type!");
268 // Make sure that the current actor returned by the parent matches our
270 NS_ASSERTION(static_cast<PluginScriptableObjectChild
*>(currentActor
) ==
271 actor
, "Cached actor is out of date!");
272 NS_ASSERTION(currentResult
== result
, "Results don't match?!");
276 if (result
!= NPERR_NO_ERROR
) {
280 NPObject
* object
= actor
->GetObject(false);
281 NS_ASSERTION(object
, "Null object?!");
283 *aObject
= PluginModuleChild::sBrowserFuncs
.retainobject(object
);
284 return NPERR_NO_ERROR
;
289 PluginInstanceChild::NPN_GetValue(NPNVariable aVar
,
292 PLUGIN_LOG_DEBUG(("%s (aVar=%i)", FULLFUNCTION
, (int) aVar
));
293 AssertPluginThread();
297 case NPNVSupportsWindowless
:
298 #if defined(OS_LINUX) || defined(OS_WIN)
299 *((NPBool
*)aValue
) = true;
301 *((NPBool
*)aValue
) = false;
303 return NPERR_NO_ERROR
;
305 #if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
306 case NPNVSupportsWindowlessLocal
: {
308 const char *graphicsSystem
= PR_GetEnv("MOZ_QT_GRAPHICSSYSTEM");
309 // we should set local rendering to false in order to render X-Plugin
310 // there is no possibility to change it later on maemo5 platform
311 mMaemoImageRendering
= (!(graphicsSystem
&& !strcmp(graphicsSystem
, "native")));
313 *((NPBool
*)aValue
) = mMaemoImageRendering
;
314 return NPERR_NO_ERROR
;
317 #if defined(OS_LINUX)
318 case NPNVSupportsXEmbedBool
:
319 *((NPBool
*)aValue
) = true;
320 return NPERR_NO_ERROR
;
323 *((NPNToolkitType
*)aValue
) = NPNVGtk2
;
324 return NPERR_NO_ERROR
;
326 #elif defined(OS_WIN)
328 return NPERR_GENERIC_ERROR
;
330 case NPNVjavascriptEnabledBool
: {
333 if (!CallNPN_GetValue_NPNVjavascriptEnabledBool(&v
, &result
)) {
334 return NPERR_GENERIC_ERROR
;
336 *static_cast<NPBool
*>(aValue
) = v
;
340 case NPNVisOfflineBool
: {
343 if (!CallNPN_GetValue_NPNVisOfflineBool(&v
, &result
)) {
344 return NPERR_GENERIC_ERROR
;
346 *static_cast<NPBool
*>(aValue
) = v
;
350 case NPNVprivateModeBool
: {
353 if (!CallNPN_GetValue_NPNVprivateModeBool(&v
, &result
)) {
354 return NPERR_GENERIC_ERROR
;
356 *static_cast<NPBool
*>(aValue
) = v
;
360 case NPNVWindowNPObject
: // Intentional fall-through
361 case NPNVPluginElementNPObject
: {
363 NPError result
= InternalGetNPObjectForValue(aVar
, &object
);
364 if (result
== NPERR_NO_ERROR
) {
365 *((NPObject
**)aValue
) = object
;
370 case NPNVnetscapeWindow
: {
372 if (mWindow
.type
== NPWindowTypeDrawable
) {
373 if (mCachedWinlessPluginHWND
) {
374 *static_cast<HWND
*>(aValue
) = mCachedWinlessPluginHWND
;
375 return NPERR_NO_ERROR
;
378 if (!CallNPN_GetValue_NPNVnetscapeWindow(&mCachedWinlessPluginHWND
, &result
)) {
379 return NPERR_GENERIC_ERROR
;
381 *static_cast<HWND
*>(aValue
) = mCachedWinlessPluginHWND
;
385 *static_cast<HWND
*>(aValue
) = mPluginWindowHWND
;
386 return NPERR_NO_ERROR
;
388 #elif defined(MOZ_X11)
390 CallNPN_GetValue_NPNVnetscapeWindow(static_cast<XID
*>(aValue
), &result
);
393 return NPERR_GENERIC_ERROR
;
398 case NPNVsupportsCoreGraphicsBool
: {
399 *((NPBool
*)aValue
) = true;
400 return NPERR_NO_ERROR
;
403 case NPNVsupportsCoreAnimationBool
: {
404 *((NPBool
*)aValue
) = true;
405 return NPERR_NO_ERROR
;
408 case NPNVsupportsInvalidatingCoreAnimationBool
: {
409 *((NPBool
*)aValue
) = true;
410 return NPERR_NO_ERROR
;
413 case NPNVsupportsCocoaBool
: {
414 *((NPBool
*)aValue
) = true;
415 return NPERR_NO_ERROR
;
419 case NPNVsupportsCarbonBool
: {
420 *((NPBool
*)aValue
) = false;
421 return NPERR_NO_ERROR
;
425 case NPNVsupportsUpdatedCocoaTextInputBool
: {
426 *static_cast<NPBool
*>(aValue
) = true;
427 return NPERR_NO_ERROR
;
430 #ifndef NP_NO_QUICKDRAW
431 case NPNVsupportsQuickDrawBool
: {
432 *((NPBool
*)aValue
) = false;
433 return NPERR_NO_ERROR
;
435 #endif /* NP_NO_QUICKDRAW */
436 #endif /* XP_MACOSX */
439 PR_LOG(gPluginLog
, PR_LOG_WARNING
,
440 ("In PluginInstanceChild::NPN_GetValue: Unhandled NPNVariable %i (%s)",
441 (int) aVar
, NPNVariableToString(aVar
)));
442 return NPERR_GENERIC_ERROR
;
449 PluginInstanceChild::NPN_SetValue(NPPVariable aVar
, void* aValue
)
451 PR_LOG(gPluginLog
, PR_LOG_DEBUG
, ("%s (aVar=%i, aValue=%p)",
452 FULLFUNCTION
, (int) aVar
, aValue
));
454 AssertPluginThread();
457 case NPPVpluginWindowBool
: {
459 bool windowed
= (NPBool
) (intptr_t) aValue
;
461 if (!CallNPN_SetValue_NPPVpluginWindow(windowed
, &rv
))
462 return NPERR_GENERIC_ERROR
;
467 case NPPVpluginTransparentBool
: {
469 mIsTransparent
= (!!aValue
);
471 if (!CallNPN_SetValue_NPPVpluginTransparent(mIsTransparent
, &rv
))
472 return NPERR_GENERIC_ERROR
;
478 case NPPVpluginDrawingModel
: {
480 int drawingModel
= (int16
) (intptr_t) aValue
;
482 if (!CallNPN_SetValue_NPPVpluginDrawingModel(drawingModel
, &rv
))
483 return NPERR_GENERIC_ERROR
;
484 mDrawingModel
= drawingModel
;
489 case NPPVpluginEventModel
: {
491 int eventModel
= (int16
) (intptr_t) aValue
;
493 if (!CallNPN_SetValue_NPPVpluginEventModel(eventModel
, &rv
))
494 return NPERR_GENERIC_ERROR
;
495 #if defined(__i386__)
496 mEventModel
= static_cast<NPEventModel
>(eventModel
);
504 PR_LOG(gPluginLog
, PR_LOG_WARNING
,
505 ("In PluginInstanceChild::NPN_SetValue: Unhandled NPPVariable %i (%s)",
506 (int) aVar
, NPPVariableToString(aVar
)));
507 return NPERR_GENERIC_ERROR
;
512 PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginNeedsXEmbed(
513 bool* needs
, NPError
* rv
)
515 AssertPluginThread();
518 // The documentation on the types for many variables in NP(N|P)_GetValue
519 // is vague. Often boolean values are NPBool (1 byte), but
520 // https://developer.mozilla.org/en/XEmbed_Extension_for_Mozilla_Plugins
521 // treats NPPVpluginNeedsXEmbed as PRBool (int), and
522 // on x86/32-bit, flash stores to this using |movl 0x1,&needsXEmbed|.
523 // thus we can't use NPBool for needsXEmbed, or the three bytes above
524 // it on the stack would get clobbered. so protect with the larger PRBool.
525 PRBool needsXEmbed
= 0;
526 if (!mPluginIface
->getvalue
) {
527 *rv
= NPERR_GENERIC_ERROR
;
530 *rv
= mPluginIface
->getvalue(GetNPP(), NPPVpluginNeedsXEmbed
,
533 *needs
= needsXEmbed
;
538 NS_RUNTIMEABORT("shouldn't be called on non-X11 platforms");
539 return false; // not reached
545 PluginInstanceChild::AnswerNPP_GetValue_NPPVpluginScriptableNPObject(
546 PPluginScriptableObjectChild
** aValue
,
549 AssertPluginThread();
551 NPObject
* object
= nsnull
;
552 NPError result
= NPERR_GENERIC_ERROR
;
553 if (mPluginIface
->getvalue
) {
554 result
= mPluginIface
->getvalue(GetNPP(), NPPVpluginScriptableNPObject
,
557 if (result
== NPERR_NO_ERROR
&& object
) {
558 PluginScriptableObjectChild
* actor
= GetActorForNPObject(object
);
560 // If we get an actor then it has retained. Otherwise we don't need it
562 PluginModuleChild::sBrowserFuncs
.releaseobject(object
);
565 *aResult
= NPERR_NO_ERROR
;
569 NS_ERROR("Failed to get actor!");
570 result
= NPERR_GENERIC_ERROR
;
573 result
= NPERR_GENERIC_ERROR
;
582 PluginInstanceChild::AnswerNPP_SetValue_NPNVprivateModeBool(const bool& value
,
585 if (!mPluginIface
->setvalue
) {
586 *result
= NPERR_GENERIC_ERROR
;
591 *result
= mPluginIface
->setvalue(GetNPP(), NPNVprivateModeBool
, &v
);
596 PluginInstanceChild::AnswerNPP_HandleEvent(const NPRemoteEvent
& event
,
599 PLUGIN_LOG_DEBUG_FUNCTION
;
600 AssertPluginThread();
602 #if defined(MOZ_X11) && defined(DEBUG)
603 if (GraphicsExpose
== event
.event
.type
)
604 PLUGIN_LOG_DEBUG((" received drawable 0x%lx\n",
605 event
.event
.xgraphicsexpose
.drawable
));
609 // Mac OS X does not define an NPEvent structure. It defines more specific types.
610 NPCocoaEvent evcopy
= event
.event
;
612 // Make sure we reset mCurrentEvent in case of an exception
613 AutoRestore
<const NPCocoaEvent
*> savePreviousEvent(mCurrentEvent
);
615 // Track the current event for NPN_PopUpContextMenu.
616 mCurrentEvent
= &event
.event
;
618 // Make a copy since we may modify values.
619 NPEvent evcopy
= event
.event
;
623 // FIXME/bug 567645: temporarily drop the "dummy event" on the floor
624 if (WM_NULL
== evcopy
.event
)
627 // Painting for win32. SharedSurfacePaint handles everything.
628 if (mWindow
.type
== NPWindowTypeDrawable
) {
629 if (evcopy
.event
== WM_PAINT
) {
630 *handled
= SharedSurfacePaint(evcopy
);
633 else if (DoublePassRenderingEvent() == evcopy
.event
) {
634 // We'll render to mSharedSurfaceDib first, then render to a cached bitmap
635 // we store locally. The two passes are for alpha extraction, so the second
636 // pass must be to a flat white surface in order for things to work.
637 mAlphaExtract
.doublePass
= RENDER_BACK_ONE
;
642 *handled
= WinlessHandleEvent(evcopy
);
646 // XXX A previous call to mPluginIface->event might block, e.g. right click
647 // for context menu. Still, we might get here again, calling into the plugin
648 // a second time while it's in the previous call.
649 if (!mPluginIface
->event
)
652 *handled
= mPluginIface
->event(&mData
, reinterpret_cast<void*>(&evcopy
));
655 // Release any reference counted objects created in the child process.
656 if (evcopy
.type
== NPCocoaEventKeyDown
||
657 evcopy
.type
== NPCocoaEventKeyUp
) {
658 ::CFRelease((CFStringRef
)evcopy
.data
.key
.characters
);
659 ::CFRelease((CFStringRef
)evcopy
.data
.key
.charactersIgnoringModifiers
);
661 else if (evcopy
.type
== NPCocoaEventTextInput
) {
662 ::CFRelease((CFStringRef
)evcopy
.data
.text
.text
);
667 if (GraphicsExpose
== event
.event
.type
) {
668 // Make sure the X server completes the drawing before the parent
669 // draws on top and destroys the Drawable.
671 // XSync() waits for the X server to complete. Really this child
672 // process does not need to wait; the parent is the process that needs
673 // to wait. A possibly-slightly-better alternative would be to send
674 // an X event to the parent that the parent would wait for.
675 XSync(mWsInfo
.display
, False
);
685 PluginInstanceChild::AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent
& event
,
690 PLUGIN_LOG_DEBUG_FUNCTION
;
691 AssertPluginThread();
695 NPCocoaEvent evcopy
= event
.event
;
697 if (evcopy
.type
== NPCocoaEventDrawRect
) {
698 if (!mShColorSpace
) {
699 mShColorSpace
= CreateSystemColorSpace();
700 if (!mShColorSpace
) {
701 PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace."));
708 void* cgContextByte
= mem
.get
<char>();
709 mShContext
= ::CGBitmapContextCreate(cgContextByte
,
710 mWindow
.width
, mWindow
.height
, 8,
711 mWindow
.width
* 4, mShColorSpace
,
712 kCGImageAlphaPremultipliedFirst
|
713 kCGBitmapByteOrder32Host
);
716 PLUGIN_LOG_DEBUG(("Could not allocate CGBitmapContext."));
722 CGRect clearRect
= ::CGRectMake(0, 0, mWindow
.width
, mWindow
.height
);
723 ::CGContextClearRect(mShContext
, clearRect
);
724 evcopy
.data
.draw
.context
= mShContext
;
726 PLUGIN_LOG_DEBUG(("Invalid event type for AnswerNNP_HandleEvent_Shmem."));
732 if (!mPluginIface
->event
) {
735 ::CGContextSaveGState(evcopy
.data
.draw
.context
);
736 *handled
= mPluginIface
->event(&mData
, reinterpret_cast<void*>(&evcopy
));
737 ::CGContextRestoreGState(evcopy
.data
.draw
.context
);
746 PluginInstanceChild::AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent
& event
,
751 NS_RUNTIMEABORT("not reached.");
759 PluginInstanceChild::AnswerNPP_HandleEvent_IOSurface(const NPRemoteEvent
& event
,
760 const uint32_t &surfaceid
,
763 PLUGIN_LOG_DEBUG_FUNCTION
;
764 AssertPluginThread();
768 NPCocoaEvent evcopy
= event
.event
;
769 nsIOSurface
* surf
= nsIOSurface::LookupSurface(surfaceid
);
771 NS_ERROR("Invalid IOSurface.");
776 if (evcopy
.type
== NPCocoaEventDrawRect
) {
777 mCARenderer
.AttachIOSurface(surf
);
778 if (!mCARenderer
.isInit()) {
779 void *caLayer
= nsnull
;
780 NPError result
= mPluginIface
->getvalue(GetNPP(),
781 NPPVpluginCoreAnimationLayer
,
783 if (result
!= NPERR_NO_ERROR
|| !caLayer
) {
784 PLUGIN_LOG_DEBUG(("Plugin requested CoreAnimation but did not "
785 "provide CALayer."));
789 mCARenderer
.SetupRenderer(caLayer
, mWindow
.width
, mWindow
.height
);
790 // Flash needs to have the window set again after this step
791 if (mPluginIface
->setwindow
)
792 (void) mPluginIface
->setwindow(&mData
, &mWindow
);
795 PLUGIN_LOG_DEBUG(("Invalid event type for "
796 "AnswerNNP_HandleEvent_IOSurface."));
801 mCARenderer
.Render(mWindow
.width
, mWindow
.height
, nsnull
);
809 PluginInstanceChild::AnswerNPP_HandleEvent_IOSurface(const NPRemoteEvent
& event
,
810 const uint32_t &surfaceid
,
813 NS_RUNTIMEABORT("NPP_HandleEvent_IOSurface is a OSX-only message");
819 PluginInstanceChild::RecvWindowPosChanged(const NPRemoteEvent
& event
)
821 NS_ASSERTION(!mLayersRendering
&& !mPendingPluginCall
,
822 "Shouldn't be receiving WindowPosChanged with layer rendering");
826 return AnswerNPP_HandleEvent(event
, &dontcare
);
828 NS_RUNTIMEABORT("WindowPosChanged is a windows-only message");
834 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
836 XVisualIDToInfo(Display
* aDisplay
, VisualID aVisualID
,
837 Visual
** aVisual
, unsigned int* aDepth
)
839 if (aVisualID
== None
) {
845 const Screen
* screen
= DefaultScreenOfDisplay(aDisplay
);
847 for (int d
= 0; d
< screen
->ndepths
; d
++) {
848 Depth
*d_info
= &screen
->depths
[d
];
849 for (int v
= 0; v
< d_info
->nvisuals
; v
++) {
850 Visual
* visual
= &d_info
->visuals
[v
];
851 if (visual
->visualid
== aVisualID
) {
853 *aDepth
= d_info
->depth
;
859 NS_ERROR("VisualID not on Screen.");
865 PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow
& aWindow
)
867 PLUGIN_LOG_DEBUG(("%s (aWindow=<window: 0x%lx, x: %d, y: %d, width: %d, height: %d>)",
870 aWindow
.x
, aWindow
.y
,
871 aWindow
.width
, aWindow
.height
));
872 NS_ASSERTION(!mLayersRendering
&& !mPendingPluginCall
,
873 "Shouldn't be receiving NPP_SetWindow with layer rendering");
874 AssertPluginThread();
876 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
877 // The minimum info is sent over IPC to allow this
878 // code to determine the rest.
880 mWindow
.window
= reinterpret_cast<void*>(aWindow
.window
);
881 mWindow
.x
= aWindow
.x
;
882 mWindow
.y
= aWindow
.y
;
883 mWindow
.width
= aWindow
.width
;
884 mWindow
.height
= aWindow
.height
;
885 mWindow
.clipRect
= aWindow
.clipRect
;
886 mWindow
.type
= aWindow
.type
;
888 mWsInfo
.colormap
= aWindow
.colormap
;
889 if (!XVisualIDToInfo(mWsInfo
.display
, aWindow
.visualID
,
890 &mWsInfo
.visual
, &mWsInfo
.depth
))
893 #ifdef MOZ_WIDGET_GTK2
894 if (gtk_check_version(2,18,7) != NULL
) { // older
895 if (aWindow
.type
== NPWindowTypeWindow
) {
896 GdkWindow
* socket_window
= gdk_window_lookup(aWindow
.window
);
898 // A GdkWindow for the socket already exists. Need to
899 // workaround https://bugzilla.gnome.org/show_bug.cgi?id=607061
900 // See wrap_gtk_plug_embedded in PluginModuleChild.cpp.
901 g_object_set_data(G_OBJECT(socket_window
),
902 "moz-existed-before-set-window",
903 GUINT_TO_POINTER(1));
907 if (aWindow
.visualID
!= None
908 && gtk_check_version(2, 12, 10) != NULL
) { // older
909 // Workaround for a bug in Gtk+ (prior to 2.12.10) where deleting
910 // a foreign GdkColormap will also free the XColormap.
911 // http://git.gnome.org/browse/gtk+/log/gdk/x11/gdkcolor-x11.c?id=GTK_2_12_10
912 GdkVisual
*gdkvisual
= gdkx_visual_get(aWindow
.visualID
);
913 GdkColormap
*gdkcolor
=
914 gdk_x11_colormap_foreign_new(gdkvisual
, aWindow
.colormap
);
916 if (g_object_get_data(G_OBJECT(gdkcolor
), "moz-have-extra-ref")) {
917 // We already have a ref to keep the object alive.
918 g_object_unref(gdkcolor
);
920 // leak and mark as already leaked
921 g_object_set_data(G_OBJECT(gdkcolor
),
922 "moz-have-extra-ref", GUINT_TO_POINTER(1));
928 if (mPluginIface
->setwindow
)
929 (void) mPluginIface
->setwindow(&mData
, &mWindow
);
931 #elif defined(OS_WIN)
932 switch (aWindow
.type
) {
933 case NPWindowTypeWindow
:
935 if (!CreatePluginWindow())
938 ReparentPluginWindow((HWND
)aWindow
.window
);
939 SizePluginWindow(aWindow
.width
, aWindow
.height
);
941 mWindow
.window
= (void*)mPluginWindowHWND
;
942 mWindow
.x
= aWindow
.x
;
943 mWindow
.y
= aWindow
.y
;
944 mWindow
.width
= aWindow
.width
;
945 mWindow
.height
= aWindow
.height
;
946 mWindow
.type
= aWindow
.type
;
948 if (mPluginIface
->setwindow
) {
949 SetProp(mPluginWindowHWND
, kPluginIgnoreSubclassProperty
, (HANDLE
)1);
950 (void) mPluginIface
->setwindow(&mData
, &mWindow
);
951 WNDPROC wndProc
= reinterpret_cast<WNDPROC
>(
952 GetWindowLongPtr(mPluginWindowHWND
, GWLP_WNDPROC
));
953 if (wndProc
!= PluginWindowProc
) {
954 mPluginWndProc
= reinterpret_cast<WNDPROC
>(
955 SetWindowLongPtr(mPluginWindowHWND
, GWLP_WNDPROC
,
956 reinterpret_cast<LONG_PTR
>(PluginWindowProc
)));
958 RemoveProp(mPluginWindowHWND
, kPluginIgnoreSubclassProperty
);
959 HookSetWindowLongPtr();
964 case NPWindowTypeDrawable
:
965 mWindow
.type
= aWindow
.type
;
966 if (GetQuirks() & PluginModuleChild::QUIRK_WINLESS_TRACKPOPUP_HOOK
)
967 CreateWinlessPopupSurrogate();
968 if (GetQuirks() & PluginModuleChild::QUIRK_FLASH_THROTTLE_WMUSER_EVENTS
)
969 SetupFlashMsgThrottle();
970 return SharedSurfaceSetWindow(aWindow
);
974 NS_NOTREACHED("Bad plugin window type.");
979 #elif defined(XP_MACOSX)
981 mWindow
.x
= aWindow
.x
;
982 mWindow
.y
= aWindow
.y
;
983 mWindow
.width
= aWindow
.width
;
984 mWindow
.height
= aWindow
.height
;
985 mWindow
.clipRect
= aWindow
.clipRect
;
986 mWindow
.type
= aWindow
.type
;
989 // Release the shared context so that it is reallocated
990 // with the new size.
991 ::CGContextRelease(mShContext
);
995 if (mPluginIface
->setwindow
)
996 (void) mPluginIface
->setwindow(&mData
, &mWindow
);
998 #elif defined(ANDROID)
999 # warning Need Android impl
1001 # error Implement me for your OS
1008 PluginInstanceChild::Initialize()
1015 static const TCHAR kWindowClassName
[] = TEXT("GeckoPluginWindow");
1016 static const TCHAR kPluginInstanceChildProperty
[] = TEXT("PluginInstanceChildProperty");
1017 static const TCHAR kFlashThrottleProperty
[] = TEXT("MozillaFlashThrottleProperty");
1021 PluginInstanceChild::RegisterWindowClass()
1023 static bool alreadyRegistered
= false;
1024 if (alreadyRegistered
)
1027 alreadyRegistered
= true;
1030 wcex
.cbSize
= sizeof(WNDCLASSEX
);
1031 wcex
.style
= CS_DBLCLKS
;
1032 wcex
.lpfnWndProc
= DummyWindowProc
;
1033 wcex
.cbClsExtra
= 0;
1034 wcex
.cbWndExtra
= 0;
1035 wcex
.hInstance
= GetModuleHandle(NULL
);
1038 wcex
.hbrBackground
= reinterpret_cast<HBRUSH
>(COLOR_WINDOW
+ 1);
1039 wcex
.lpszMenuName
= 0;
1040 wcex
.lpszClassName
= kWindowClassName
;
1043 return RegisterClassEx(&wcex
) ? true : false;
1047 HandleMouseCapture(HWND aWnd
, UINT aMessage
)
1049 // Make sure capture is released by the child on mouse events. Fixes a
1050 // problem with flash full screen mode mouse input. Appears to be
1051 // caused by a bug in flash, since we are not setting the capture
1052 // on the window. (In non-oopp land, we would set and release via
1053 // widget for other reasons.)
1055 case WM_LBUTTONDOWN
:
1056 case WM_MBUTTONDOWN
:
1057 case WM_RBUTTONDOWN
:
1068 LRESULT CALLBACK
MouseHookProc(int code
,
1072 if (code
== HC_ACTION
) {
1073 MOUSEHOOKSTRUCT
* hookStruct
=
1074 reinterpret_cast<MOUSEHOOKSTRUCT
*>(lParam
);
1076 HandleMouseCapture(hookStruct
->hwnd
, wParam
);
1079 return CallNextHookEx(NULL
, code
, wParam
, lParam
);
1083 PluginInstanceChild::CreatePluginWindow()
1085 // already initialized
1086 if (mPluginWindowHWND
)
1089 if (!RegisterWindowClass())
1093 CreateWindowEx(WS_EX_LEFT
| WS_EX_LTRREADING
|
1094 WS_EX_NOPARENTNOTIFY
| // XXXbent Get rid of this!
1095 WS_EX_RIGHTSCROLLBAR
,
1096 kWindowClassName
, 0,
1097 WS_POPUP
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
, 0, 0,
1098 0, 0, NULL
, 0, GetModuleHandle(NULL
), 0);
1099 if (!mPluginWindowHWND
)
1101 if (!SetProp(mPluginWindowHWND
, kPluginInstanceChildProperty
, this))
1104 // Apparently some plugins require an ASCII WndProc.
1105 SetWindowLongPtrA(mPluginWindowHWND
, GWLP_WNDPROC
,
1106 reinterpret_cast<LONG_PTR
>(DefWindowProcA
));
1108 // Mouse capture hook for flash full screen capture bug
1109 if (GetQuirks() & PluginModuleChild::QUIRK_FLASH_HOOK_MOUSE_CAPTURE
) {
1110 mMouseHook
= SetWindowsHookEx(WH_MOUSE
, MouseHookProc
, NULL
,
1111 GetCurrentThreadId());
1117 PluginInstanceChild::DestroyPluginWindow()
1119 if (mPluginWindowHWND
) {
1120 // Unsubclass the window.
1121 WNDPROC wndProc
= reinterpret_cast<WNDPROC
>(
1122 GetWindowLongPtr(mPluginWindowHWND
, GWLP_WNDPROC
));
1123 // Removed prior to SetWindowLongPtr, see HookSetWindowLongPtr.
1124 RemoveProp(mPluginWindowHWND
, kPluginInstanceChildProperty
);
1125 if (wndProc
== PluginWindowProc
) {
1126 NS_ASSERTION(mPluginWndProc
, "Should have old proc here!");
1127 SetWindowLongPtr(mPluginWindowHWND
, GWLP_WNDPROC
,
1128 reinterpret_cast<LONG_PTR
>(mPluginWndProc
));
1131 DestroyWindow(mPluginWindowHWND
);
1132 mPluginWindowHWND
= 0;
1136 UnhookWindowsHookEx(mMouseHook
);
1142 PluginInstanceChild::ReparentPluginWindow(HWND hWndParent
)
1144 if (hWndParent
!= mPluginParentHWND
&& IsWindow(hWndParent
)) {
1145 // Fix the child window's style to be a child window.
1146 LONG_PTR style
= GetWindowLongPtr(mPluginWindowHWND
, GWL_STYLE
);
1147 style
|= WS_CHILD
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
;
1149 SetWindowLongPtr(mPluginWindowHWND
, GWL_STYLE
, style
);
1151 // Do the reparenting.
1152 SetParent(mPluginWindowHWND
, hWndParent
);
1154 // Make sure we're visible.
1155 ShowWindow(mPluginWindowHWND
, SW_SHOWNA
);
1157 mPluginParentHWND
= hWndParent
;
1161 PluginInstanceChild::SizePluginWindow(int width
,
1164 if (mPluginWindowHWND
) {
1165 mPluginSize
.x
= width
;
1166 mPluginSize
.y
= height
;
1167 SetWindowPos(mPluginWindowHWND
, NULL
, 0, 0, width
, height
,
1168 SWP_NOZORDER
| SWP_NOREPOSITION
);
1172 // See chromium's webplugin_delegate_impl.cc for explanation of this function.
1175 PluginInstanceChild::DummyWindowProc(HWND hWnd
,
1180 return CallWindowProc(DefWindowProc
, hWnd
, message
, wParam
, lParam
);
1185 PluginInstanceChild::PluginWindowProc(HWND hWnd
,
1190 NS_ASSERTION(!mozilla::ipc::SyncChannel::IsPumpingMessages(),
1191 "Failed to prevent a nonqueued message from running!");
1192 PluginInstanceChild
* self
= reinterpret_cast<PluginInstanceChild
*>(
1193 GetProp(hWnd
, kPluginInstanceChildProperty
));
1195 NS_NOTREACHED("Badness!");
1199 NS_ASSERTION(self
->mPluginWindowHWND
== hWnd
, "Wrong window!");
1201 // Adobe's shockwave positions the plugin window relative to the browser
1202 // frame when it initializes. With oopp disabled, this wouldn't have an
1203 // effect. With oopp, GeckoPluginWindow is a child of the parent plugin
1204 // window, so the move offsets the child within the parent. Generally
1205 // we don't want plugins moving or sizing our window, so we prevent these
1207 if (message
== WM_WINDOWPOSCHANGING
) {
1208 WINDOWPOS
* pos
= reinterpret_cast<WINDOWPOS
*>(lParam
);
1209 if (pos
&& (!(pos
->flags
& SWP_NOMOVE
) || !(pos
->flags
& SWP_NOSIZE
))) {
1210 pos
->x
= pos
->y
= 0;
1211 pos
->cx
= self
->mPluginSize
.x
;
1212 pos
->cy
= self
->mPluginSize
.y
;
1213 LRESULT res
= CallWindowProc(self
->mPluginWndProc
, hWnd
, message
, wParam
,
1215 pos
->x
= pos
->y
= 0;
1216 pos
->cx
= self
->mPluginSize
.x
;
1217 pos
->cy
= self
->mPluginSize
.y
;
1222 // The plugin received keyboard focus, let the parent know so the dom is up to date.
1223 if (message
== WM_MOUSEACTIVATE
)
1224 self
->CallPluginFocusChange(true);
1226 // Prevent lockups due to plugins making rpc calls when the parent
1227 // is making a synchronous SendMessage call to the child window. Add
1228 // more messages as needed.
1229 if ((InSendMessageEx(NULL
)&(ISMEX_REPLIED
|ISMEX_SEND
)) == ISMEX_SEND
) {
1232 case WM_MOUSEHWHEEL
:
1241 if (message
== WM_KILLFOCUS
)
1242 self
->CallPluginFocusChange(false);
1244 if (message
== WM_USER
+1 &&
1245 (self
->GetQuirks() & PluginModuleChild::QUIRK_FLASH_THROTTLE_WMUSER_EVENTS
)) {
1246 self
->FlashThrottleMessage(hWnd
, message
, wParam
, lParam
, true);
1250 HandleMouseCapture(hWnd
, message
);
1252 LRESULT res
= CallWindowProc(self
->mPluginWndProc
, hWnd
, message
, wParam
,
1255 if (message
== WM_CLOSE
)
1256 self
->DestroyPluginWindow();
1258 if (message
== WM_NCDESTROY
)
1259 RemoveProp(hWnd
, kPluginInstanceChildProperty
);
1264 /* system parameters info hook for flash */
1266 typedef BOOL (WINAPI
*User32SystemParametersInfoW
)(UINT uiAction
,
1271 static User32SystemParametersInfoW sUser32SystemParametersInfoWStub
= NULL
;
1273 static BOOL WINAPI
User32SystemParametersInfoHook(UINT uiAction
,
1278 if (!sUser32SystemParametersInfoWStub
) {
1279 NS_NOTREACHED("sUser32SystemParametersInfoWStub not set??");
1283 // Tell them cleartype is disabled, so they don't mess with
1284 // the alpha channel in our buffers.
1285 if (uiAction
== SPI_GETFONTSMOOTHINGTYPE
&& pvParam
) {
1286 *((UINT
*)(pvParam
)) = FE_FONTSMOOTHINGSTANDARD
;
1290 return sUser32SystemParametersInfoWStub(uiAction
, uiParam
, pvParam
, fWinIni
);
1294 PluginInstanceChild::HookSystemParametersInfo()
1296 if (!(GetQuirks() & PluginModuleChild::QUIRK_FLASH_MASK_CLEARTYPE_SETTINGS
))
1298 if (sUser32SystemParametersInfoWStub
)
1300 sUser32Intercept
.Init("gdi32.dll");
1301 sUser32Intercept
.AddHook("SystemParametersInfoW", User32SystemParametersInfoHook
,
1302 (void**) &sUser32SystemParametersInfoWStub
);
1305 /* set window long ptr hook for flash */
1308 * Flash will reset the subclass of our widget at various times.
1309 * (Notably when entering and exiting full screen mode.) This
1310 * occurs independent of the main plugin window event procedure.
1311 * We trap these subclass calls to prevent our subclass hook from
1313 * Note, ascii versions can be nixed once flash versions < 10.1
1314 * are considered obsolete.
1319 (WINAPI
*User32SetWindowLongPtrA
)(HWND hWnd
,
1321 LONG_PTR dwNewLong
);
1323 (WINAPI
*User32SetWindowLongPtrW
)(HWND hWnd
,
1325 LONG_PTR dwNewLong
);
1326 static User32SetWindowLongPtrA sUser32SetWindowLongAHookStub
= NULL
;
1327 static User32SetWindowLongPtrW sUser32SetWindowLongWHookStub
= NULL
;
1330 (WINAPI
*User32SetWindowLongA
)(HWND hWnd
,
1334 (WINAPI
*User32SetWindowLongW
)(HWND hWnd
,
1337 static User32SetWindowLongA sUser32SetWindowLongAHookStub
= NULL
;
1338 static User32SetWindowLongW sUser32SetWindowLongWHookStub
= NULL
;
1341 extern LRESULT CALLBACK
1342 NeuteredWindowProc(HWND hwnd
,
1347 const wchar_t kOldWndProcProp
[] = L
"MozillaIPCOldWndProc";
1351 PluginInstanceChild::SetWindowLongHookCheck(HWND hWnd
,
1355 // Let this go through if it's not a subclass
1356 if (nIndex
!= GWLP_WNDPROC
||
1357 // if it's not a subclassed plugin window
1358 !GetProp(hWnd
, kPluginInstanceChildProperty
) ||
1359 // if we're not disabled
1360 GetProp(hWnd
, kPluginIgnoreSubclassProperty
) ||
1361 // if the subclass is set to a known procedure
1362 newLong
== reinterpret_cast<LONG_PTR
>(PluginWindowProc
) ||
1363 newLong
== reinterpret_cast<LONG_PTR
>(NeuteredWindowProc
) ||
1364 newLong
== reinterpret_cast<LONG_PTR
>(DefWindowProcA
) ||
1365 newLong
== reinterpret_cast<LONG_PTR
>(DefWindowProcW
) ||
1366 // if the subclass is a WindowsMessageLoop subclass restore
1367 GetProp(hWnd
, kOldWndProcProp
))
1369 // prevent the subclass
1375 PluginInstanceChild::SetWindowLongPtrAHook(HWND hWnd
,
1380 PluginInstanceChild::SetWindowLongAHook(HWND hWnd
,
1385 if (SetWindowLongHookCheck(hWnd
, nIndex
, newLong
))
1386 return sUser32SetWindowLongAHookStub(hWnd
, nIndex
, newLong
);
1388 // Set flash's new subclass to get the result.
1389 LONG_PTR proc
= sUser32SetWindowLongAHookStub(hWnd
, nIndex
, newLong
);
1391 // We already checked this in SetWindowLongHookCheck
1392 PluginInstanceChild
* self
= reinterpret_cast<PluginInstanceChild
*>(
1393 GetProp(hWnd
, kPluginInstanceChildProperty
));
1395 // Hook our subclass back up, just like we do on setwindow.
1396 WNDPROC currentProc
=
1397 reinterpret_cast<WNDPROC
>(GetWindowLongPtr(hWnd
, GWLP_WNDPROC
));
1398 if (currentProc
!= PluginWindowProc
) {
1399 self
->mPluginWndProc
=
1400 reinterpret_cast<WNDPROC
>(sUser32SetWindowLongAHookStub(hWnd
, nIndex
,
1401 reinterpret_cast<LONG_PTR
>(PluginWindowProc
)));
1408 PluginInstanceChild::SetWindowLongPtrWHook(HWND hWnd
,
1413 PluginInstanceChild::SetWindowLongWHook(HWND hWnd
,
1418 if (SetWindowLongHookCheck(hWnd
, nIndex
, newLong
))
1419 return sUser32SetWindowLongWHookStub(hWnd
, nIndex
, newLong
);
1421 // Set flash's new subclass to get the result.
1422 LONG_PTR proc
= sUser32SetWindowLongWHookStub(hWnd
, nIndex
, newLong
);
1424 // We already checked this in SetWindowLongHookCheck
1425 PluginInstanceChild
* self
= reinterpret_cast<PluginInstanceChild
*>(
1426 GetProp(hWnd
, kPluginInstanceChildProperty
));
1428 // Hook our subclass back up, just like we do on setwindow.
1429 WNDPROC currentProc
=
1430 reinterpret_cast<WNDPROC
>(GetWindowLongPtr(hWnd
, GWLP_WNDPROC
));
1431 if (currentProc
!= PluginWindowProc
) {
1432 self
->mPluginWndProc
=
1433 reinterpret_cast<WNDPROC
>(sUser32SetWindowLongAHookStub(hWnd
, nIndex
,
1434 reinterpret_cast<LONG_PTR
>(PluginWindowProc
)));
1440 PluginInstanceChild::HookSetWindowLongPtr()
1443 // XXX WindowsDllInterceptor doesn't support hooks
1444 // in 64-bit builds, disabling this code for now.
1448 if (!(GetQuirks() & PluginModuleChild::QUIRK_FLASH_HOOK_SETLONGPTR
))
1451 sUser32Intercept
.Init("user32.dll");
1453 sUser32Intercept
.AddHook("SetWindowLongPtrA", SetWindowLongPtrAHook
,
1454 (void**) &sUser32SetWindowLongAHookStub
);
1455 sUser32Intercept
.AddHook("SetWindowLongPtrW", SetWindowLongPtrWHook
,
1456 (void**) &sUser32SetWindowLongWHookStub
);
1458 sUser32Intercept
.AddHook("SetWindowLongA", SetWindowLongAHook
,
1459 (void**) &sUser32SetWindowLongAHookStub
);
1460 sUser32Intercept
.AddHook("SetWindowLongW", SetWindowLongWHook
,
1461 (void**) &sUser32SetWindowLongWHookStub
);
1465 /* windowless track popup menu helpers */
1469 PluginInstanceChild::TrackPopupHookProc(HMENU hMenu
,
1475 CONST RECT
*prcRect
)
1477 if (!sUser32TrackPopupMenuStub
) {
1478 NS_ERROR("TrackPopupMenu stub isn't set! Badness!");
1482 // Only change the parent when we know this is a context on the plugin
1483 // surface within the browser. Prevents resetting the parent on child ui
1484 // displayed by plugins that have working parent-child relationships.
1485 PRUnichar szClass
[21];
1486 bool haveClass
= GetClassNameW(hWnd
, szClass
, NS_ARRAY_LENGTH(szClass
));
1488 (wcscmp(szClass
, L
"MozillaWindowClass") &&
1489 wcscmp(szClass
, L
"SWFlash_Placeholder"))) {
1490 // Unrecognized parent
1491 return sUser32TrackPopupMenuStub(hMenu
, uFlags
, x
, y
, nReserved
,
1495 // Called on an unexpected event, warn.
1496 if (!sWinlessPopupSurrogateHWND
) {
1498 "Untraced TrackPopupHookProc call! Menu might not work right!");
1499 return sUser32TrackPopupMenuStub(hMenu
, uFlags
, x
, y
, nReserved
,
1503 HWND surrogateHwnd
= sWinlessPopupSurrogateHWND
;
1504 sWinlessPopupSurrogateHWND
= NULL
;
1506 // Popups that don't use TPM_RETURNCMD expect a final command message
1507 // when an item is selected and the context closes. Since we replace
1508 // the parent, we need to forward this back to the real parent so it
1509 // can act on the menu item selected.
1510 bool isRetCmdCall
= (uFlags
& TPM_RETURNCMD
);
1512 // A little trick scrounged from chromium's code - set the focus
1513 // to our surrogate parent so keyboard nav events go to the menu.
1514 HWND focusHwnd
= SetFocus(surrogateHwnd
);
1515 DWORD res
= sUser32TrackPopupMenuStub(hMenu
, uFlags
|TPM_RETURNCMD
, x
, y
,
1516 nReserved
, surrogateHwnd
, prcRect
);
1517 if (IsWindow(focusHwnd
)) {
1518 SetFocus(focusHwnd
);
1521 if (!isRetCmdCall
&& res
) {
1522 SendMessage(hWnd
, WM_COMMAND
, MAKEWPARAM(res
, 0), 0);
1529 PluginInstanceChild::InitPopupMenuHook()
1531 if (!(GetQuirks() & PluginModuleChild::QUIRK_WINLESS_TRACKPOPUP_HOOK
) ||
1532 sUser32TrackPopupMenuStub
)
1535 // Note, once WindowsDllInterceptor is initialized for a module,
1536 // it remains initialized for that particular module for it's
1537 // lifetime. Additional instances are needed if other modules need
1539 sUser32Intercept
.Init("user32.dll");
1540 sUser32Intercept
.AddHook("TrackPopupMenu", TrackPopupHookProc
,
1541 (void**) &sUser32TrackPopupMenuStub
);
1545 PluginInstanceChild::CreateWinlessPopupSurrogate()
1547 // already initialized
1548 if (mWinlessPopupSurrogateHWND
)
1553 if (!CallNPN_GetValue_NPNVnetscapeWindow(&hwnd
, &result
)) {
1554 NS_ERROR("CallNPN_GetValue_NPNVnetscapeWindow failed.");
1558 mWinlessPopupSurrogateHWND
=
1559 CreateWindowEx(WS_EX_NOPARENTNOTIFY
, L
"Static", NULL
, WS_CHILD
, 0, 0,
1560 0, 0, hwnd
, 0, GetModuleHandle(NULL
), 0);
1561 if (!mWinlessPopupSurrogateHWND
) {
1562 NS_ERROR("CreateWindowEx failed for winless placeholder!");
1569 PluginInstanceChild::DestroyWinlessPopupSurrogate()
1571 if (mWinlessPopupSurrogateHWND
)
1572 DestroyWindow(mWinlessPopupSurrogateHWND
);
1573 mWinlessPopupSurrogateHWND
= NULL
;
1576 /* windowless handle event helpers */
1579 NeedsNestedEventCoverage(UINT msg
)
1581 // Events we assume some sort of modal ui *might* be generated.
1586 case WM_LBUTTONDOWN
:
1587 case WM_RBUTTONDOWN
:
1588 case WM_MBUTTONDOWN
:
1589 case WM_CONTEXTMENU
:
1596 IsMouseInputEvent(UINT msg
)
1603 case WM_LBUTTONDOWN
:
1604 case WM_RBUTTONDOWN
:
1605 case WM_MBUTTONDOWN
:
1606 case WM_LBUTTONDBLCLK
:
1607 case WM_MBUTTONDBLCLK
:
1608 case WM_RBUTTONDBLCLK
:
1615 PluginInstanceChild::WinlessHandleEvent(NPEvent
& event
)
1617 if (!mPluginIface
->event
)
1620 if (!NeedsNestedEventCoverage(event
.event
)) {
1621 return mPluginIface
->event(&mData
, reinterpret_cast<void*>(&event
));
1624 // Events that might generate nested event dispatch loops need
1625 // special handling during delivery.
1628 // TrackPopupMenu will fail if the parent window is not associated with
1629 // our ui thread. So we hook TrackPopupMenu so we can hand in a surrogate
1630 // parent created in the child process.
1631 if ((GetQuirks() & PluginModuleChild::QUIRK_WINLESS_TRACKPOPUP_HOOK
) && // XXX turn on by default?
1632 (event
.event
== WM_RBUTTONDOWN
|| // flash
1633 event
.event
== WM_RBUTTONUP
)) { // silverlight
1634 sWinlessPopupSurrogateHWND
= mWinlessPopupSurrogateHWND
;
1637 handled
= mPluginIface
->event(&mData
, reinterpret_cast<void*>(&event
));
1639 sWinlessPopupSurrogateHWND
= NULL
;
1644 /* windowless drawing helpers */
1647 PluginInstanceChild::SharedSurfaceSetWindow(const NPRemoteWindow
& aWindow
)
1649 // If the surfaceHandle is empty, parent is telling us we can reuse our cached
1650 // memory surface and hdc. Otherwise, we need to reset, usually due to a
1651 // expanding plugin port size.
1652 if (!aWindow
.surfaceHandle
) {
1653 if (!mSharedSurfaceDib
.IsValid()) {
1658 // Attach to the new shared surface parent handed us.
1659 if (NS_FAILED(mSharedSurfaceDib
.Attach((SharedDIB::Handle
)aWindow
.surfaceHandle
,
1660 aWindow
.width
, aWindow
.height
, false)))
1662 // Free any alpha extraction resources if needed. This will be reset
1663 // the next time it's used.
1664 AlphaExtractCacheRelease();
1667 // NPRemoteWindow's origin is the origin of our shared dib.
1668 mWindow
.x
= aWindow
.x
;
1669 mWindow
.y
= aWindow
.y
;
1670 mWindow
.width
= aWindow
.width
;
1671 mWindow
.height
= aWindow
.height
;
1672 mWindow
.type
= aWindow
.type
;
1674 mWindow
.window
= reinterpret_cast<void*>(mSharedSurfaceDib
.GetHDC());
1675 ::SetViewportOrgEx(mSharedSurfaceDib
.GetHDC(), -aWindow
.x
, -aWindow
.y
, NULL
);
1677 if (mPluginIface
->setwindow
)
1678 mPluginIface
->setwindow(&mData
, &mWindow
);
1684 PluginInstanceChild::SharedSurfaceRelease()
1686 mSharedSurfaceDib
.Close();
1687 AlphaExtractCacheRelease();
1690 /* double pass cache buffer - (rarely) used in cases where alpha extraction
1691 * occurs for windowless plugins. */
1694 PluginInstanceChild::AlphaExtractCacheSetup()
1696 AlphaExtractCacheRelease();
1698 mAlphaExtract
.hdc
= ::CreateCompatibleDC(NULL
);
1700 if (!mAlphaExtract
.hdc
)
1703 BITMAPINFOHEADER bmih
;
1704 memset((void*)&bmih
, 0, sizeof(BITMAPINFOHEADER
));
1705 bmih
.biSize
= sizeof(BITMAPINFOHEADER
);
1706 bmih
.biWidth
= mWindow
.width
;
1707 bmih
.biHeight
= mWindow
.height
;
1709 bmih
.biBitCount
= 32;
1710 bmih
.biCompression
= BI_RGB
;
1712 void* ppvBits
= nsnull
;
1713 mAlphaExtract
.bmp
= ::CreateDIBSection(mAlphaExtract
.hdc
,
1718 (unsigned long)sizeof(BITMAPINFOHEADER
));
1719 if (!mAlphaExtract
.bmp
)
1722 DeleteObject(::SelectObject(mAlphaExtract
.hdc
, mAlphaExtract
.bmp
));
1727 PluginInstanceChild::AlphaExtractCacheRelease()
1729 if (mAlphaExtract
.bmp
)
1730 ::DeleteObject(mAlphaExtract
.bmp
);
1732 if (mAlphaExtract
.hdc
)
1733 ::DeleteObject(mAlphaExtract
.hdc
);
1735 mAlphaExtract
.bmp
= NULL
;
1736 mAlphaExtract
.hdc
= NULL
;
1740 PluginInstanceChild::UpdatePaintClipRect(RECT
* aRect
)
1743 // Update the clip rect on our internal hdc
1744 HRGN clip
= ::CreateRectRgnIndirect(aRect
);
1745 ::SelectClipRgn(mSharedSurfaceDib
.GetHDC(), clip
);
1746 ::DeleteObject(clip
);
1751 PluginInstanceChild::SharedSurfacePaint(NPEvent
& evcopy
)
1753 if (!mPluginIface
->event
)
1756 RECT
* pRect
= reinterpret_cast<RECT
*>(evcopy
.lParam
);
1758 switch(mAlphaExtract
.doublePass
) {
1760 // pass the internal hdc to the plugin
1761 UpdatePaintClipRect(pRect
);
1762 evcopy
.wParam
= WPARAM(mSharedSurfaceDib
.GetHDC());
1763 return mPluginIface
->event(&mData
, reinterpret_cast<void*>(&evcopy
));
1765 case RENDER_BACK_ONE
:
1766 // Handle a double pass render used in alpha extraction for transparent
1767 // plugins. (See nsObjectFrame and gfxWindowsNativeDrawing for details.)
1768 // We render twice, once to the shared dib, and once to a cache which
1769 // we copy back on a second paint. These paints can't be spread across
1770 // multiple rpc messages as delays cause animation frame changes.
1771 if (!mAlphaExtract
.bmp
&& !AlphaExtractCacheSetup()) {
1772 mAlphaExtract
.doublePass
= RENDER_NATIVE
;
1776 // See gfxWindowsNativeDrawing, color order doesn't have to match.
1777 UpdatePaintClipRect(pRect
);
1778 ::FillRect(mSharedSurfaceDib
.GetHDC(), pRect
, (HBRUSH
)GetStockObject(WHITE_BRUSH
));
1779 evcopy
.wParam
= WPARAM(mSharedSurfaceDib
.GetHDC());
1780 if (!mPluginIface
->event(&mData
, reinterpret_cast<void*>(&evcopy
))) {
1781 mAlphaExtract
.doublePass
= RENDER_NATIVE
;
1785 // Copy to cache. We render to shared dib so we don't have to call
1786 // setwindow between calls (flash issue).
1787 ::BitBlt(mAlphaExtract
.hdc
,
1790 pRect
->right
- pRect
->left
,
1791 pRect
->bottom
- pRect
->top
,
1792 mSharedSurfaceDib
.GetHDC(),
1797 ::FillRect(mSharedSurfaceDib
.GetHDC(), pRect
, (HBRUSH
)GetStockObject(BLACK_BRUSH
));
1798 if (!mPluginIface
->event(&mData
, reinterpret_cast<void*>(&evcopy
))) {
1799 mAlphaExtract
.doublePass
= RENDER_NATIVE
;
1802 mAlphaExtract
.doublePass
= RENDER_BACK_TWO
;
1805 case RENDER_BACK_TWO
:
1806 // copy our cached surface back
1807 UpdatePaintClipRect(pRect
);
1808 ::BitBlt(mSharedSurfaceDib
.GetHDC(),
1811 pRect
->right
- pRect
->left
,
1812 pRect
->bottom
- pRect
->top
,
1817 mAlphaExtract
.doublePass
= RENDER_NATIVE
;
1824 /* flash msg throttling helpers */
1826 // Flash has the unfortunate habit of flooding dispatch loops with custom
1827 // windowing events they use for timing. We throttle these by dropping the
1828 // delivery priority below any other event, including pending ipc io
1829 // notifications. We do this for both windowed and windowless controls.
1830 // Note flash's windowless msg window can last longer than our instance,
1831 // so we try to unhook when the window is destroyed and in NPP_Destroy.
1834 PluginInstanceChild::UnhookWinlessFlashThrottle()
1836 // We may have already unhooked
1837 if (!mWinlessThrottleOldWndProc
)
1840 WNDPROC tmpProc
= mWinlessThrottleOldWndProc
;
1841 mWinlessThrottleOldWndProc
= nsnull
;
1843 NS_ASSERTION(mWinlessHiddenMsgHWND
,
1844 "Missing mWinlessHiddenMsgHWND w/subclass set??");
1846 // reset the subclass
1847 SetWindowLongPtr(mWinlessHiddenMsgHWND
, GWLP_WNDPROC
,
1848 reinterpret_cast<LONG_PTR
>(tmpProc
));
1850 // Remove our instance prop
1851 RemoveProp(mWinlessHiddenMsgHWND
, kFlashThrottleProperty
);
1852 mWinlessHiddenMsgHWND
= nsnull
;
1857 PluginInstanceChild::WinlessHiddenFlashWndProc(HWND hWnd
,
1862 PluginInstanceChild
* self
= reinterpret_cast<PluginInstanceChild
*>(
1863 GetProp(hWnd
, kFlashThrottleProperty
));
1865 NS_NOTREACHED("Badness!");
1869 NS_ASSERTION(self
->mWinlessThrottleOldWndProc
,
1870 "Missing subclass procedure!!");
1873 if (message
== WM_USER
+1) {
1874 self
->FlashThrottleMessage(hWnd
, message
, wParam
, lParam
, false);
1879 if (message
== WM_CLOSE
|| message
== WM_NCDESTROY
) {
1880 WNDPROC tmpProc
= self
->mWinlessThrottleOldWndProc
;
1881 self
->UnhookWinlessFlashThrottle();
1882 LRESULT res
= CallWindowProc(tmpProc
, hWnd
, message
, wParam
, lParam
);
1886 return CallWindowProc(self
->mWinlessThrottleOldWndProc
,
1887 hWnd
, message
, wParam
, lParam
);
1890 // Enumerate all thread windows looking for flash's hidden message window.
1891 // Once we find it, sub class it so we can throttle user msgs.
1894 PluginInstanceChild::EnumThreadWindowsCallback(HWND hWnd
,
1897 PluginInstanceChild
* self
= reinterpret_cast<PluginInstanceChild
*>(aParam
);
1899 NS_NOTREACHED("Enum befuddled!");
1903 PRUnichar className
[64];
1904 if (!GetClassNameW(hWnd
, className
, sizeof(className
)/sizeof(PRUnichar
)))
1907 if (!wcscmp(className
, L
"SWFlash_PlaceholderX")) {
1908 WNDPROC oldWndProc
=
1909 reinterpret_cast<WNDPROC
>(GetWindowLongPtr(hWnd
, GWLP_WNDPROC
));
1910 // Only set this if we haven't already.
1911 if (oldWndProc
!= WinlessHiddenFlashWndProc
) {
1912 if (self
->mWinlessThrottleOldWndProc
) {
1913 NS_WARNING("mWinlessThrottleWndProc already set???");
1916 // Subsclass and store self as a property
1917 self
->mWinlessHiddenMsgHWND
= hWnd
;
1918 self
->mWinlessThrottleOldWndProc
=
1919 reinterpret_cast<WNDPROC
>(SetWindowLongPtr(hWnd
, GWLP_WNDPROC
,
1920 reinterpret_cast<LONG_PTR
>(WinlessHiddenFlashWndProc
)));
1921 SetProp(hWnd
, kFlashThrottleProperty
, self
);
1922 NS_ASSERTION(self
->mWinlessThrottleOldWndProc
,
1923 "SetWindowLongPtr failed?!");
1925 // Return no matter what once we find the right window.
1934 PluginInstanceChild::SetupFlashMsgThrottle()
1936 if (mWindow
.type
== NPWindowTypeDrawable
) {
1937 // Search for the flash hidden message window and subclass it. Only
1938 // search for flash windows belonging to our ui thread!
1939 if (mWinlessThrottleOldWndProc
)
1941 EnumThreadWindows(GetCurrentThreadId(), EnumThreadWindowsCallback
,
1942 reinterpret_cast<LPARAM
>(this));
1945 // Already setup through quirks and the subclass.
1951 PluginInstanceChild::FlashThrottleAsyncMsg::GetProc()
1954 return mWindowed
? mInstance
->mPluginWndProc
:
1955 mInstance
->mWinlessThrottleOldWndProc
;
1961 PluginInstanceChild::FlashThrottleAsyncMsg::Run()
1963 RemoveFromAsyncList();
1965 // GetProc() checks mInstance, and pulls the procedure from
1966 // PluginInstanceChild. We don't transport sub-class procedure
1967 // ptrs around in FlashThrottleAsyncMsg msgs.
1971 // deliver the event to flash
1972 CallWindowProc(GetProc(), GetWnd(), GetMsg(), GetWParam(), GetLParam());
1976 PluginInstanceChild::FlashThrottleMessage(HWND aWnd
,
1982 // We reuse ChildAsyncCall so we get the cancelation work
1983 // that's done in Destroy.
1984 FlashThrottleAsyncMsg
* task
= new FlashThrottleAsyncMsg(this,
1985 aWnd
, aMsg
, aWParam
, aLParam
, isWindowed
);
1990 MutexAutoLock
lock(mAsyncCallMutex
);
1991 mPendingAsyncCalls
.AppendElement(task
);
1993 MessageLoop::current()->PostDelayedTask(FROM_HERE
,
1994 task
, kFlashWMUSERMessageThrottleDelayMs
);
2000 PluginInstanceChild::AnswerSetPluginFocus()
2002 PR_LOG(gPluginLog
, PR_LOG_DEBUG
, ("%s", FULLFUNCTION
));
2005 // Parent is letting us know something set focus to the plugin.
2006 if (::GetFocus() == mPluginWindowHWND
)
2008 ::SetFocus(mPluginWindowHWND
);
2011 NS_NOTREACHED("PluginInstanceChild::AnswerSetPluginFocus not implemented!");
2017 PluginInstanceChild::AnswerUpdateWindow()
2019 PR_LOG(gPluginLog
, PR_LOG_DEBUG
, ("%s", FULLFUNCTION
));
2022 if (mPluginWindowHWND
) {
2024 if (GetUpdateRect(GetParent(mPluginWindowHWND
), &rect
, FALSE
)) {
2025 ::InvalidateRect(mPluginWindowHWND
, &rect
, FALSE
);
2027 UpdateWindow(mPluginWindowHWND
);
2031 NS_NOTREACHED("PluginInstanceChild::AnswerUpdateWindow not implemented!");
2036 PPluginScriptableObjectChild
*
2037 PluginInstanceChild::AllocPPluginScriptableObject()
2039 AssertPluginThread();
2040 return new PluginScriptableObjectChild(Proxy
);
2044 PluginInstanceChild::DeallocPPluginScriptableObject(
2045 PPluginScriptableObjectChild
* aObject
)
2047 AssertPluginThread();
2053 PluginInstanceChild::RecvPPluginScriptableObjectConstructor(
2054 PPluginScriptableObjectChild
* aActor
)
2056 AssertPluginThread();
2058 // This is only called in response to the parent process requesting the
2059 // creation of an actor. This actor will represent an NPObject that is
2060 // created by the browser and returned to the plugin.
2061 PluginScriptableObjectChild
* actor
=
2062 static_cast<PluginScriptableObjectChild
*>(aActor
);
2063 NS_ASSERTION(!actor
->GetObject(false), "Actor already has an object?!");
2065 actor
->InitializeProxy();
2066 NS_ASSERTION(actor
->GetObject(false), "Actor should have an object!");
2072 PluginInstanceChild::AnswerPBrowserStreamConstructor(
2073 PBrowserStreamChild
* aActor
,
2074 const nsCString
& url
,
2075 const uint32_t& length
,
2076 const uint32_t& lastmodified
,
2077 PStreamNotifyChild
* notifyData
,
2078 const nsCString
& headers
,
2079 const nsCString
& mimeType
,
2080 const bool& seekable
,
2084 AssertPluginThread();
2085 *rv
= static_cast<BrowserStreamChild
*>(aActor
)
2086 ->StreamConstructed(mimeType
, seekable
, stype
);
2090 PBrowserStreamChild
*
2091 PluginInstanceChild::AllocPBrowserStream(const nsCString
& url
,
2092 const uint32_t& length
,
2093 const uint32_t& lastmodified
,
2094 PStreamNotifyChild
* notifyData
,
2095 const nsCString
& headers
,
2096 const nsCString
& mimeType
,
2097 const bool& seekable
,
2101 AssertPluginThread();
2102 return new BrowserStreamChild(this, url
, length
, lastmodified
,
2103 static_cast<StreamNotifyChild
*>(notifyData
),
2104 headers
, mimeType
, seekable
, rv
, stype
);
2108 PluginInstanceChild::DeallocPBrowserStream(PBrowserStreamChild
* stream
)
2110 AssertPluginThread();
2116 PluginInstanceChild::AllocPPluginStream(const nsCString
& mimeType
,
2117 const nsCString
& target
,
2120 NS_RUNTIMEABORT("not callable");
2125 PluginInstanceChild::DeallocPPluginStream(PPluginStreamChild
* stream
)
2127 AssertPluginThread();
2133 PluginInstanceChild::AllocPStreamNotify(const nsCString
& url
,
2134 const nsCString
& target
,
2136 const nsCString
& buffer
,
2140 AssertPluginThread();
2141 NS_RUNTIMEABORT("not reached");
2146 StreamNotifyChild::ActorDestroy(ActorDestroyReason why
)
2148 if (AncestorDeletion
== why
&& mBrowserStream
) {
2149 NS_ERROR("Pending NPP_URLNotify not called when closing an instance.");
2151 // reclaim responsibility for deleting ourself
2152 mBrowserStream
->mStreamNotify
= NULL
;
2153 mBrowserStream
= NULL
;
2159 StreamNotifyChild::SetAssociatedStream(BrowserStreamChild
* bs
)
2161 NS_ASSERTION(bs
, "Shouldn't be null");
2162 NS_ASSERTION(!mBrowserStream
, "Two streams for one streamnotify?");
2164 mBrowserStream
= bs
;
2168 StreamNotifyChild::Recv__delete__(const NPReason
& reason
)
2170 AssertPluginThread();
2173 mBrowserStream
->NotifyPending();
2175 NPP_URLNotify(reason
);
2181 StreamNotifyChild::RecvRedirectNotify(const nsCString
& url
, const int32_t& status
)
2183 // NPP_URLRedirectNotify requires a non-null closure. Since core logic
2184 // assumes that all out-of-process notify streams have non-null closure
2185 // data it will assume that the plugin was notified at this point and
2186 // expect a response otherwise the redirect will hang indefinitely.
2188 SendRedirectNotifyResponse(false);
2191 PluginInstanceChild
* instance
= static_cast<PluginInstanceChild
*>(Manager());
2192 if (instance
->mPluginIface
->urlredirectnotify
)
2193 instance
->mPluginIface
->urlredirectnotify(instance
->GetNPP(), url
.get(), status
, mClosure
);
2199 StreamNotifyChild::NPP_URLNotify(NPReason reason
)
2201 PluginInstanceChild
* instance
= static_cast<PluginInstanceChild
*>(Manager());
2204 instance
->mPluginIface
->urlnotify(instance
->GetNPP(), mURL
.get(),
2209 PluginInstanceChild::DeallocPStreamNotify(PStreamNotifyChild
* notifyData
)
2211 AssertPluginThread();
2213 if (!static_cast<StreamNotifyChild
*>(notifyData
)->mBrowserStream
)
2218 PluginScriptableObjectChild
*
2219 PluginInstanceChild::GetActorForNPObject(NPObject
* aObject
)
2221 AssertPluginThread();
2222 NS_ASSERTION(aObject
, "Null pointer!");
2224 if (aObject
->_class
== PluginScriptableObjectChild::GetClass()) {
2225 // One of ours! It's a browser-provided object.
2226 ChildNPObject
* object
= static_cast<ChildNPObject
*>(aObject
);
2227 NS_ASSERTION(object
->parent
, "Null actor!");
2228 return object
->parent
;
2231 PluginScriptableObjectChild
* actor
=
2232 PluginModuleChild::current()->GetActorForNPObject(aObject
);
2234 // Plugin-provided object that we've previously wrapped.
2238 actor
= new PluginScriptableObjectChild(LocalObject
);
2239 if (!SendPPluginScriptableObjectConstructor(actor
)) {
2240 NS_ERROR("Failed to send constructor message!");
2244 actor
->InitializeLocal(aObject
);
2249 PluginInstanceChild::NPN_NewStream(NPMIMEType aMIMEType
, const char* aWindow
,
2252 AssertPluginThread();
2254 PluginStreamChild
* ps
= new PluginStreamChild();
2257 CallPPluginStreamConstructor(ps
, nsDependentCString(aMIMEType
),
2258 NullableString(aWindow
), &result
);
2259 if (NPERR_NO_ERROR
!= result
) {
2261 PPluginStreamChild::Call__delete__(ps
, NPERR_GENERIC_ERROR
, true);
2265 *aStream
= &ps
->mStream
;
2266 return NPERR_NO_ERROR
;
2270 PluginInstanceChild::NPN_URLRedirectResponse(void* notifyData
, NPBool allow
)
2276 InfallibleTArray
<PStreamNotifyChild
*> notifyStreams
;
2277 ManagedPStreamNotifyChild(notifyStreams
);
2278 PRUint32 notifyStreamCount
= notifyStreams
.Length();
2279 for (PRUint32 i
= 0; i
< notifyStreamCount
; i
++) {
2280 StreamNotifyChild
* sn
= static_cast<StreamNotifyChild
*>(notifyStreams
[i
]);
2281 if (sn
->mClosure
== notifyData
) {
2282 sn
->SendRedirectNotifyResponse(static_cast<bool>(allow
));
2286 NS_ASSERTION(PR_FALSE
, "Couldn't find stream for redirect response!");
2290 PluginInstanceChild::RecvAsyncSetWindow(const gfxSurfaceType
& aSurfaceType
,
2291 const NPRemoteWindow
& aWindow
)
2293 AssertPluginThread();
2295 NS_ASSERTION(!aWindow
.window
, "Remote window should be null.");
2297 if (mCurrentAsyncSetWindowTask
) {
2298 mCurrentAsyncSetWindowTask
->Cancel();
2299 mCurrentAsyncSetWindowTask
= nsnull
;
2302 if (mPendingPluginCall
) {
2303 // We shouldn't process this now. Run it later.
2304 mCurrentAsyncSetWindowTask
=
2305 NewRunnableMethod
<PluginInstanceChild
,
2306 void (PluginInstanceChild::*)(const gfxSurfaceType
&, const NPRemoteWindow
&, bool),
2307 gfxSurfaceType
, NPRemoteWindow
, bool>
2308 (this, &PluginInstanceChild::DoAsyncSetWindow
,
2309 aSurfaceType
, aWindow
, true);
2310 MessageLoop::current()->PostTask(FROM_HERE
, mCurrentAsyncSetWindowTask
);
2312 DoAsyncSetWindow(aSurfaceType
, aWindow
, false);
2319 PluginInstanceChild::DoAsyncSetWindow(const gfxSurfaceType
& aSurfaceType
,
2320 const NPRemoteWindow
& aWindow
,
2323 AssertPluginThread();
2324 NS_ASSERTION(!aWindow
.window
, "Remote window should be null.");
2325 NS_ASSERTION(!mPendingPluginCall
, "Can't do SetWindow during plugin call!");
2328 if (!mCurrentAsyncSetWindowTask
) {
2331 mCurrentAsyncSetWindowTask
= nsnull
;
2334 mWindow
.window
= NULL
;
2335 if (mWindow
.width
!= aWindow
.width
|| mWindow
.height
!= aWindow
.height
) {
2336 ClearCurrentSurface();
2337 mAccumulatedInvalidRect
= nsIntRect(0, 0, aWindow
.width
, aWindow
.height
);
2339 if (mWindow
.clipRect
.top
!= aWindow
.clipRect
.top
||
2340 mWindow
.clipRect
.left
!= aWindow
.clipRect
.left
||
2341 mWindow
.clipRect
.bottom
!= aWindow
.clipRect
.bottom
||
2342 mWindow
.clipRect
.right
!= aWindow
.clipRect
.right
)
2343 mAccumulatedInvalidRect
= nsIntRect(0, 0, aWindow
.width
, aWindow
.height
);
2345 mWindow
.x
= aWindow
.x
;
2346 mWindow
.y
= aWindow
.y
;
2347 mWindow
.width
= aWindow
.width
;
2348 mWindow
.height
= aWindow
.height
;
2349 mWindow
.clipRect
= aWindow
.clipRect
;
2350 mWindow
.type
= aWindow
.type
;
2352 if (GetQuirks() & PluginModuleChild::QUIRK_SILVERLIGHT_DEFAULT_TRANSPARENT
)
2353 mIsTransparent
= true;
2355 mLayersRendering
= true;
2356 mSurfaceType
= aSurfaceType
;
2357 UpdateWindowAttributes(true);
2360 if (GetQuirks() & PluginModuleChild::QUIRK_WINLESS_TRACKPOPUP_HOOK
)
2361 CreateWinlessPopupSurrogate();
2362 if (GetQuirks() & PluginModuleChild::QUIRK_FLASH_THROTTLE_WMUSER_EVENTS
)
2363 SetupFlashMsgThrottle();
2366 if (!mAccumulatedInvalidRect
.IsEmpty()) {
2367 AsyncShowPluginFrame();
2371 static inline gfxRect
2372 GfxFromNsRect(const nsIntRect
& aRect
)
2374 return gfxRect(aRect
.x
, aRect
.y
, aRect
.width
, aRect
.height
);
2378 PluginInstanceChild::CreateOptSurface(void)
2380 NS_ASSERTION(!mCurrentSurface
, "mCurrentSurfaceActor can get out of sync.");
2382 nsRefPtr
<gfxASurface
> retsurf
;
2383 gfxASurface::gfxImageFormat format
=
2384 mIsTransparent
? gfxASurface::ImageFormatARGB32
:
2385 gfxASurface::ImageFormatRGB24
;
2387 #if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
2388 // On Maemo 5, we must send the Visibility event to activate the plugin
2389 if (mMaemoImageRendering
) {
2390 NPEvent pluginEvent
;
2391 XVisibilityEvent
& visibilityEvent
= pluginEvent
.xvisibility
;
2392 visibilityEvent
.type
= VisibilityNotify
;
2393 visibilityEvent
.display
= 0;
2394 visibilityEvent
.state
= VisibilityUnobscured
;
2395 mPluginIface
->event(&mData
, reinterpret_cast<void*>(&pluginEvent
));
2399 Display
* dpy
= mWsInfo
.display
;
2400 Screen
* screen
= DefaultScreenOfDisplay(dpy
);
2401 if (format
== gfxASurface::ImageFormatRGB24
&&
2402 DefaultDepth(dpy
, DefaultScreen(dpy
)) == 16) {
2403 format
= gfxASurface::ImageFormatRGB16_565
;
2406 if (mSurfaceType
== gfxASurface::SurfaceTypeXlib
) {
2407 XRenderPictFormat
* xfmt
= gfxXlibSurface::FindRenderFormat(dpy
, format
);
2409 NS_ERROR("Need X falback surface, but FindRenderFormat failed");
2413 gfxXlibSurface::Create(screen
, xfmt
,
2414 gfxIntSize(mWindow
.width
,
2416 return mCurrentSurface
!= nsnull
;
2421 if (mSurfaceType
== gfxASurface::SurfaceTypeWin32
||
2422 mSurfaceType
== gfxASurface::SurfaceTypeD2D
) {
2424 SharedDIBSurface
* s
= new SharedDIBSurface();
2425 if (!s
->Create(reinterpret_cast<HDC
>(mWindow
.window
),
2426 mWindow
.width
, mWindow
.height
, mIsTransparent
))
2429 mCurrentSurface
= s
;
2433 NS_RUNTIMEABORT("Shared-memory drawing not expected on Windows.");
2436 // Make common shmem implementation working for any platform
2438 gfxSharedImageSurface::CreateUnsafe(this, gfxIntSize(mWindow
.width
, mWindow
.height
), format
);
2439 return !!mCurrentSurface
;
2443 PluginInstanceChild::MaybeCreatePlatformHelperSurface(void)
2445 if (!mCurrentSurface
) {
2446 NS_ERROR("Cannot create helper surface without mCurrentSurface");
2450 #ifdef MOZ_PLATFORM_MAEMO
2451 // On maemo plugins support non-default visual rendering
2452 bool supportNonDefaultVisual
= true;
2454 bool supportNonDefaultVisual
= false;
2457 Screen
* screen
= DefaultScreenOfDisplay(mWsInfo
.display
);
2458 Visual
* defaultVisual
= DefaultVisualOfScreen(screen
);
2459 Visual
* visual
= nsnull
;
2460 Colormap colormap
= 0;
2461 mDoAlphaExtraction
= false;
2462 bool createHelperSurface
= false;
2464 if (mCurrentSurface
->GetType() == gfxASurface::SurfaceTypeXlib
) {
2465 static_cast<gfxXlibSurface
*>(mCurrentSurface
.get())->
2466 GetColormapAndVisual(&colormap
, &visual
);
2467 // Create helper surface if layer surface visual not same as default
2468 // and we don't support non-default visual rendering
2469 if (!visual
|| (defaultVisual
!= visual
&& !supportNonDefaultVisual
)) {
2470 createHelperSurface
= true;
2471 visual
= defaultVisual
;
2472 mDoAlphaExtraction
= mIsTransparent
;
2474 } else if (mCurrentSurface
->GetType() == gfxASurface::SurfaceTypeImage
) {
2475 #if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
2476 if (mMaemoImageRendering
) {
2477 // No helper surface needed, when mMaemoImageRendering is TRUE.
2478 // we can rendering directly into image memory
2479 // with NPImageExpose Maemo5 NPAPI
2483 // For image layer surface we should always create helper surface
2484 createHelperSurface
= true;
2485 // Check if we can create helper surface with non-default visual
2486 visual
= gfxXlibSurface::FindVisual(screen
,
2487 static_cast<gfxImageSurface
*>(mCurrentSurface
.get())->Format());
2488 if (visual
&& defaultVisual
!= visual
&& !supportNonDefaultVisual
) {
2489 visual
= defaultVisual
;
2490 mDoAlphaExtraction
= mIsTransparent
;
2494 if (createHelperSurface
) {
2496 NS_ERROR("Need X falback surface, but visual failed");
2500 gfxXlibSurface::Create(screen
, visual
,
2501 mCurrentSurface
->GetSize());
2502 if (!mHelperSurface
) {
2503 NS_WARNING("Fail to create create helper surface");
2513 PluginInstanceChild::EnsureCurrentBuffer(void)
2515 if (mCurrentSurface
) {
2519 if (!mWindow
.width
|| !mWindow
.height
) {
2523 if (!CreateOptSurface()) {
2524 NS_ERROR("Cannot create optimized surface");
2528 if (!MaybeCreatePlatformHelperSurface()) {
2529 NS_ERROR("Cannot create helper surface");
2537 PluginInstanceChild::UpdateWindowAttributes(bool aForceSetWindow
)
2539 nsRefPtr
<gfxASurface
> curSurface
= mHelperSurface
? mHelperSurface
: mCurrentSurface
;
2540 bool needWindowUpdate
= aForceSetWindow
;
2542 Visual
* visual
= nsnull
;
2543 Colormap colormap
= 0;
2544 if (curSurface
&& curSurface
->GetType() == gfxASurface::SurfaceTypeXlib
) {
2545 static_cast<gfxXlibSurface
*>(curSurface
.get())->
2546 GetColormapAndVisual(&colormap
, &visual
);
2547 if (visual
!= mWsInfo
.visual
|| colormap
!= mWsInfo
.colormap
) {
2548 mWsInfo
.visual
= visual
;
2549 mWsInfo
.colormap
= colormap
;
2550 needWindowUpdate
= true;
2553 #if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
2554 else if (curSurface
&& curSurface
->GetType() == gfxASurface::SurfaceTypeImage
2555 && mMaemoImageRendering
) {
2556 // For maemo5 we need to setup window/colormap to 0
2557 // and specify depth of image surface
2558 gfxImageSurface
* img
= static_cast<gfxImageSurface
*>(curSurface
.get());
2559 if (mWindow
.window
||
2560 mWsInfo
.depth
!= gfxUtils::ImageFormatToDepth(img
->Format()) ||
2562 mWindow
.window
= nsnull
;
2563 mWsInfo
.depth
= gfxUtils::ImageFormatToDepth(img
->Format());
2564 mWsInfo
.colormap
= 0;
2565 needWindowUpdate
= PR_TRUE
;
2574 NS_ASSERTION(SharedDIBSurface::IsSharedDIBSurface(curSurface
),
2575 "Expected (SharedDIB) image surface.");
2577 SharedDIBSurface
* dibsurf
= static_cast<SharedDIBSurface
*>(curSurface
.get());
2578 dc
= dibsurf
->GetHDC();
2580 if (mWindow
.window
!= dc
) {
2581 mWindow
.window
= dc
;
2582 needWindowUpdate
= true;
2586 if (!needWindowUpdate
) {
2591 // On Windows, we translate the device context, in order for the window
2592 // origin to be correct.
2593 mWindow
.x
= mWindow
.y
= 0;
2597 // The clip rect is relative to drawable top-left.
2600 // Don't ask the plugin to draw outside the drawable. The clip rect
2601 // is in plugin coordinates, not window coordinates.
2602 // This also ensures that the unsigned clip rectangle offsets won't be -ve.
2603 clipRect
.SetRect(0, 0, mWindow
.width
, mWindow
.height
);
2605 mWindow
.clipRect
.left
= 0;
2606 mWindow
.clipRect
.top
= 0;
2607 mWindow
.clipRect
.right
= clipRect
.XMost();
2608 mWindow
.clipRect
.bottom
= clipRect
.YMost();
2612 // Windowless plugins on Windows need a WM_WINDOWPOSCHANGED event to update
2613 // their location... or at least Flash does: Silverlight uses the
2614 // window.x/y passed to NPP_SetWindow
2616 if (mPluginIface
->event
) {
2617 WINDOWPOS winpos
= {
2619 mWindow
.x
, mWindow
.y
,
2620 mWindow
.width
, mWindow
.height
,
2623 NPEvent pluginEvent
= {
2624 WM_WINDOWPOSCHANGED
, 0,
2627 mPluginIface
->event(&mData
, &pluginEvent
);
2631 if (mPluginIface
->setwindow
) {
2632 mPluginIface
->setwindow(&mData
, &mWindow
);
2637 PluginInstanceChild::PaintRectToPlatformSurface(const nsIntRect
& aRect
,
2638 gfxASurface
* aSurface
)
2640 bool temporarilyMakeVisible
= !IsVisible() && !mHasPainted
;
2641 if (temporarilyMakeVisible
) {
2642 mWindow
.clipRect
.right
= mWindow
.width
;
2643 mWindow
.clipRect
.bottom
= mWindow
.height
;
2646 UpdateWindowAttributes();
2649 #if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
2650 // On maemo5 we do support Image rendering NPAPI
2651 if (mMaemoImageRendering
&&
2652 aSurface
->GetType() == gfxASurface::SurfaceTypeImage
) {
2654 gfxImageSurface
* image
= static_cast<gfxImageSurface
*>(aSurface
);
2655 NPImageExpose imgExp
;
2656 imgExp
.depth
= gfxUtils::ImageFormatToDepth(image
->Format());
2659 imgExp
.width
= aRect
.width
;
2660 imgExp
.height
= aRect
.height
;
2661 imgExp
.stride
= image
->Stride();
2662 imgExp
.data
= (char *)image
->Data();
2663 imgExp
.dataSize
.width
= image
->Width();
2664 imgExp
.dataSize
.height
= image
->Height();
2665 imgExp
.translateX
= 0;
2666 imgExp
.translateY
= 0;
2669 NPEvent pluginEvent
;
2670 XGraphicsExposeEvent
& exposeEvent
= pluginEvent
.xgraphicsexpose
;
2671 exposeEvent
.type
= GraphicsExpose
;
2672 exposeEvent
.display
= 0;
2673 // Store imageExpose structure pointer as drawable member
2674 exposeEvent
.drawable
= (Drawable
)&imgExp
;
2675 exposeEvent
.x
= imgExp
.x
;
2676 exposeEvent
.y
= imgExp
.y
;
2677 exposeEvent
.width
= imgExp
.width
;
2678 exposeEvent
.height
= imgExp
.height
;
2679 exposeEvent
.count
= 0;
2680 // information not set:
2681 exposeEvent
.serial
= 0;
2682 exposeEvent
.send_event
= False
;
2683 exposeEvent
.major_code
= 0;
2684 exposeEvent
.minor_code
= 0;
2685 mPluginIface
->event(&mData
, reinterpret_cast<void*>(&exposeEvent
));
2689 NS_ASSERTION(aSurface
->GetType() == gfxASurface::SurfaceTypeXlib
,
2690 "Non supported platform surface type");
2692 NPEvent pluginEvent
;
2693 XGraphicsExposeEvent
& exposeEvent
= pluginEvent
.xgraphicsexpose
;
2694 exposeEvent
.type
= GraphicsExpose
;
2695 exposeEvent
.display
= mWsInfo
.display
;
2696 exposeEvent
.drawable
= static_cast<gfxXlibSurface
*>(aSurface
)->XDrawable();
2697 exposeEvent
.x
= aRect
.x
;
2698 exposeEvent
.y
= aRect
.y
;
2699 exposeEvent
.width
= aRect
.width
;
2700 exposeEvent
.height
= aRect
.height
;
2701 exposeEvent
.count
= 0;
2702 // information not set:
2703 exposeEvent
.serial
= 0;
2704 exposeEvent
.send_event
= False
;
2705 exposeEvent
.major_code
= 0;
2706 exposeEvent
.minor_code
= 0;
2707 mPluginIface
->event(&mData
, reinterpret_cast<void*>(&exposeEvent
));
2709 #elif defined(XP_WIN)
2710 NS_ASSERTION(SharedDIBSurface::IsSharedDIBSurface(aSurface
),
2711 "Expected (SharedDIB) image surface.");
2713 // This rect is in the window coordinate space. aRect is in the plugin
2714 // coordinate space.
2716 mWindow
.x
+ aRect
.x
,
2717 mWindow
.y
+ aRect
.y
,
2718 mWindow
.x
+ aRect
.XMost(),
2719 mWindow
.y
+ aRect
.YMost()
2721 NPEvent paintEvent
= {
2723 uintptr_t(mWindow
.window
),
2727 ::SetViewportOrgEx((HDC
) mWindow
.window
, -mWindow
.x
, -mWindow
.y
, NULL
);
2728 ::SelectClipRgn((HDC
) mWindow
.window
, NULL
);
2729 ::IntersectClipRect((HDC
) mWindow
.window
, rect
.left
, rect
.top
, rect
.right
, rect
.bottom
);
2730 mPluginIface
->event(&mData
, reinterpret_cast<void*>(&paintEvent
));
2732 NS_RUNTIMEABORT("Surface type not implemented.");
2735 if (temporarilyMakeVisible
) {
2736 mWindow
.clipRect
.right
= mWindow
.clipRect
.bottom
= 0;
2738 if (mPluginIface
->setwindow
) {
2739 mPluginIface
->setwindow(&mData
, &mWindow
);
2745 PluginInstanceChild::PaintRectToSurface(const nsIntRect
& aRect
,
2746 gfxASurface
* aSurface
,
2747 const gfxRGBA
& aColor
)
2749 // Render using temporary X surface, with copy to image surface
2750 nsIntRect
plPaintRect(aRect
);
2751 nsRefPtr
<gfxASurface
> renderSurface
= aSurface
;
2753 if (mIsTransparent
&& (GetQuirks() & PluginModuleChild::QUIRK_FLASH_EXPOSE_COORD_TRANSLATION
)) {
2754 // Work around a bug in Flash up to 10.1 d51 at least, where expose event
2755 // top left coordinates within the plugin-rect and not at the drawable
2756 // origin are misinterpreted. (We can move the top left coordinate
2757 // provided it is within the clipRect.), see bug 574583
2758 plPaintRect
.SetRect(0, 0, aRect
.XMost(), aRect
.YMost());
2760 if (renderSurface
->GetType() != gfxASurface::SurfaceTypeXlib
) {
2761 // On X11 we can paint to non Xlib surface only with HelperSurface
2762 #if (MOZ_PLATFORM_MAEMO == 5) || (MOZ_PLATFORM_MAEMO == 6)
2763 // Don't use mHelperSurface if surface is image and mMaemoImageRendering is TRUE
2764 if (!mMaemoImageRendering
||
2765 renderSurface
->GetType() != gfxASurface::SurfaceTypeImage
)
2767 renderSurface
= mHelperSurface
;
2771 if (mIsTransparent
) {
2772 // Clear surface content for transparent rendering
2773 nsRefPtr
<gfxContext
> ctx
= new gfxContext(renderSurface
);
2774 ctx
->SetColor(aColor
);
2775 ctx
->SetOperator(gfxContext::OPERATOR_SOURCE
);
2776 ctx
->Rectangle(GfxFromNsRect(plPaintRect
));
2780 PaintRectToPlatformSurface(plPaintRect
, renderSurface
);
2782 if (renderSurface
!= aSurface
) {
2783 // Copy helper surface content to target
2784 nsRefPtr
<gfxContext
> ctx
= new gfxContext(aSurface
);
2785 ctx
->SetSource(renderSurface
);
2786 ctx
->SetOperator(gfxContext::OPERATOR_SOURCE
);
2787 ctx
->Rectangle(GfxFromNsRect(aRect
));
2793 PluginInstanceChild::PaintRectWithAlphaExtraction(const nsIntRect
& aRect
,
2794 gfxASurface
* aSurface
)
2796 // Paint onto black image
2797 bool needImageSurface
= true;
2798 nsRefPtr
<gfxImageSurface
> blackImage
;
2799 gfxIntSize
clipSize(aRect
.width
, aRect
.height
);
2800 gfxPoint
deviceOffset(-aRect
.x
, -aRect
.y
);
2801 // Try to re-use existing image surface, and avoid one copy
2802 if (aSurface
->GetType() == gfxASurface::SurfaceTypeImage
) {
2803 gfxImageSurface
*surface
= static_cast<gfxImageSurface
*>(aSurface
);
2804 if (surface
->Format() == gfxASurface::ImageFormatARGB32
) {
2805 needImageSurface
= false;
2806 blackImage
= surface
->GetSubimage(GfxFromNsRect(aRect
));
2809 // otherwise create new helper surface
2810 if (needImageSurface
) {
2811 blackImage
= new gfxImageSurface(clipSize
, gfxASurface::ImageFormatARGB32
);
2814 // Paint to black image
2815 blackImage
->SetDeviceOffset(deviceOffset
);
2816 PaintRectToSurface(aRect
, blackImage
, gfxRGBA(0.0, 0.0, 0.0));
2818 // Paint onto white image
2819 nsRefPtr
<gfxImageSurface
> whiteImage
=
2820 new gfxImageSurface(clipSize
, gfxASurface::ImageFormatRGB24
);
2822 whiteImage
->SetDeviceOffset(deviceOffset
);
2823 PaintRectToSurface(aRect
, whiteImage
, gfxRGBA(1.0, 1.0, 1.0));
2825 // Extract Alpha from black and white image and store to black Image
2826 gfxRect
rect(aRect
.x
, aRect
.y
, aRect
.width
, aRect
.height
);
2827 if (!gfxAlphaRecovery::RecoverAlpha(blackImage
, whiteImage
, nsnull
)) {
2831 if (needImageSurface
) {
2832 nsRefPtr
<gfxContext
> ctx
= new gfxContext(aSurface
);
2833 ctx
->SetOperator(gfxContext::OPERATOR_SOURCE
);
2834 ctx
->SetSource(blackImage
);
2835 ctx
->Rectangle(GfxFromNsRect(aRect
));
2841 PluginInstanceChild::ShowPluginFrame()
2843 if (mPendingPluginCall
) {
2847 AutoRestore
<bool> pending(mPendingPluginCall
);
2848 mPendingPluginCall
= true;
2850 if (!EnsureCurrentBuffer()) {
2854 // Make expose rect not bigger than clip rect
2855 mAccumulatedInvalidRect
.IntersectRect(mAccumulatedInvalidRect
,
2856 nsIntRect(mWindow
.clipRect
.left
, mWindow
.clipRect
.top
,
2857 mWindow
.clipRect
.right
- mWindow
.clipRect
.left
,
2858 mWindow
.clipRect
.bottom
- mWindow
.clipRect
.top
));
2860 // Clear accRect here to be able to pass
2861 // test_invalidate_during_plugin_paint test
2862 nsIntRect rect
= mAccumulatedInvalidRect
;
2863 mAccumulatedInvalidRect
.Empty();
2865 if (!ReadbackDifferenceRect(rect
)) {
2866 // Just repaint whole plugin, because we cannot read back from Shmem which is owned by another process
2867 rect
.SetRect(0, 0, mWindow
.width
, mWindow
.height
);
2870 if (mDoAlphaExtraction
) {
2871 PaintRectWithAlphaExtraction(rect
, mCurrentSurface
);
2873 PaintRectToSurface(rect
, mCurrentSurface
, gfxRGBA(0.0, 0.0, 0.0, 0.0));
2877 NPRect r
= { (uint16_t)rect
.y
, (uint16_t)rect
.x
,
2878 (uint16_t)rect
.YMost(), (uint16_t)rect
.XMost() };
2879 SurfaceDescriptor currSurf
;
2881 if (mCurrentSurface
->GetType() == gfxASurface::SurfaceTypeXlib
) {
2882 gfxXlibSurface
*xsurf
= static_cast<gfxXlibSurface
*>(mCurrentSurface
.get());
2883 currSurf
= SurfaceDescriptorX11(xsurf
->XDrawable(), xsurf
->XRenderFormat()->id
,
2884 mCurrentSurface
->GetSize());
2885 // Need to sync all pending x-paint requests
2886 // before giving drawable to another process
2887 XSync(mWsInfo
.display
, False
);
2891 if (SharedDIBSurface::IsSharedDIBSurface(mCurrentSurface
)) {
2892 SharedDIBSurface
* s
= static_cast<SharedDIBSurface
*>(mCurrentSurface
.get());
2893 if (!mCurrentSurfaceActor
) {
2894 base::SharedMemoryHandle handle
= NULL
;
2895 s
->ShareToProcess(PluginModuleChild::current()->OtherProcess(), &handle
);
2897 mCurrentSurfaceActor
=
2898 SendPPluginSurfaceConstructor(handle
,
2899 mCurrentSurface
->GetSize(),
2902 currSurf
= mCurrentSurfaceActor
;
2906 if (gfxSharedImageSurface::IsSharedImage(mCurrentSurface
)) {
2907 currSurf
= static_cast<gfxSharedImageSurface
*>(mCurrentSurface
.get())->GetShmem();
2909 NS_RUNTIMEABORT("Surface type is not remotable");
2913 // Unused, except to possibly return a shmem to us
2914 SurfaceDescriptor returnSurf
;
2916 if (!SendShow(r
, currSurf
, &returnSurf
)) {
2921 mSurfaceDifferenceRect
= rect
;
2926 PluginInstanceChild::ReadbackDifferenceRect(const nsIntRect
& rect
)
2931 // We can read safely from XSurface,SharedDIBSurface and Unsafe SharedMemory,
2932 // because PluginHost is not able to modify that surface
2933 #if defined(MOZ_X11)
2934 if (mBackSurface
->GetType() != gfxASurface::SurfaceTypeXlib
&&
2935 !gfxSharedImageSurface::IsSharedImage(mBackSurface
))
2937 #elif defined(XP_WIN)
2938 if (!SharedDIBSurface::IsSharedDIBSurface(mBackSurface
))
2944 if (mSurfaceDifferenceRect
.IsEmpty())
2947 // Read back previous content
2948 nsRefPtr
<gfxContext
> ctx
= new gfxContext(mCurrentSurface
);
2949 ctx
->SetOperator(gfxContext::OPERATOR_SOURCE
);
2950 ctx
->SetSource(mBackSurface
);
2951 // Subtract from mSurfaceDifferenceRect area which is overlapping with rect
2953 result
.Sub(mSurfaceDifferenceRect
, nsIntRegion(rect
));
2954 nsIntRegionRectIterator
iter(result
);
2956 while ((r
= iter
.Next()) != nsnull
) {
2957 ctx
->Rectangle(GfxFromNsRect(*r
));
2965 PluginInstanceChild::InvalidateRectDelayed(void)
2967 if (!mCurrentInvalidateTask
) {
2971 mCurrentInvalidateTask
= nsnull
;
2972 if (mAccumulatedInvalidRect
.IsEmpty() || (mHasPainted
&& !IsVisible())) {
2976 if (!ShowPluginFrame()) {
2977 AsyncShowPluginFrame();
2982 PluginInstanceChild::AsyncShowPluginFrame(void)
2984 if (mCurrentInvalidateTask
|| (mHasPainted
&& !IsVisible())) {
2988 mCurrentInvalidateTask
=
2989 NewRunnableMethod(this, &PluginInstanceChild::InvalidateRectDelayed
);
2990 MessageLoop::current()->PostTask(FROM_HERE
, mCurrentInvalidateTask
);
2994 PluginInstanceChild::InvalidateRect(NPRect
* aInvalidRect
)
2996 NS_ASSERTION(aInvalidRect
, "Null pointer!");
2999 // Invalidate and draw locally for windowed plugins.
3000 if (mWindow
.type
== NPWindowTypeWindow
) {
3001 NS_ASSERTION(IsWindow(mPluginWindowHWND
), "Bad window?!");
3002 RECT rect
= { aInvalidRect
->left
, aInvalidRect
->top
,
3003 aInvalidRect
->right
, aInvalidRect
->bottom
};
3004 ::InvalidateRect(mPluginWindowHWND
, &rect
, FALSE
);
3009 if (mLayersRendering
) {
3010 nsIntRect
r(aInvalidRect
->left
, aInvalidRect
->top
,
3011 aInvalidRect
->right
- aInvalidRect
->left
,
3012 aInvalidRect
->bottom
- aInvalidRect
->top
);
3014 mAccumulatedInvalidRect
.UnionRect(r
, mAccumulatedInvalidRect
);
3015 // If we are able to paint and invalidate sent, then reset
3016 // accumulated rectangle
3017 AsyncShowPluginFrame();
3020 SendNPN_InvalidateRect(*aInvalidRect
);
3024 PluginInstanceChild::ScheduleTimer(uint32_t interval
, bool repeat
,
3027 ChildTimer
* t
= new ChildTimer(this, interval
, repeat
, func
);
3033 mTimers
.AppendElement(t
);
3038 PluginInstanceChild::UnscheduleTimer(uint32_t id
)
3043 mTimers
.RemoveElement(id
, ChildTimer::IDComparator());
3047 PluginInstanceChild::AsyncCall(PluginThreadCallback aFunc
, void* aUserData
)
3049 ChildAsyncCall
* task
= new ChildAsyncCall(this, aFunc
, aUserData
);
3052 MutexAutoLock
lock(mAsyncCallMutex
);
3053 mPendingAsyncCalls
.AppendElement(task
);
3055 ProcessChild::message_loop()->PostTask(FROM_HERE
, task
);
3058 static PLDHashOperator
3059 InvalidateObject(DeletingObjectEntry
* e
, void* userArg
)
3061 NPObject
* o
= e
->GetKey();
3062 if (!e
->mDeleted
&& o
->_class
&& o
->_class
->invalidate
)
3063 o
->_class
->invalidate(o
);
3065 return PL_DHASH_NEXT
;
3068 static PLDHashOperator
3069 DeleteObject(DeletingObjectEntry
* e
, void* userArg
)
3071 NPObject
* o
= e
->GetKey();
3075 #ifdef NS_BUILD_REFCNT_LOGGING
3077 int32_t refcnt
= o
->referenceCount
;
3080 NS_LOG_RELEASE(o
, refcnt
, "NPObject");
3085 PluginModuleChild::DeallocNPObject(o
);
3088 return PL_DHASH_NEXT
;
3092 PluginInstanceChild::SwapSurfaces()
3094 nsRefPtr
<gfxASurface
> tmpsurf
= mCurrentSurface
;
3096 PPluginSurfaceChild
* tmpactor
= mCurrentSurfaceActor
;
3099 mCurrentSurface
= mBackSurface
;
3101 mCurrentSurfaceActor
= mBackSurfaceActor
;
3104 mBackSurface
= tmpsurf
;
3106 mBackSurfaceActor
= tmpactor
;
3109 // Outdated back surface... not usable anymore due to changed plugin size.
3110 // Dropping obsolete surface
3111 if (mCurrentSurface
&& mBackSurface
&&
3112 mCurrentSurface
->GetSize() != mBackSurface
->GetSize()) {
3113 mCurrentSurface
= nsnull
;
3115 if (mCurrentSurfaceActor
) {
3116 PPluginSurfaceChild::Send__delete__(mCurrentSurfaceActor
);
3117 mCurrentSurfaceActor
= NULL
;
3124 PluginInstanceChild::ClearCurrentSurface()
3126 mCurrentSurface
= nsnull
;
3128 if (mCurrentSurfaceActor
) {
3129 PPluginSurfaceChild::Send__delete__(mCurrentSurfaceActor
);
3130 mCurrentSurfaceActor
= NULL
;
3133 mHelperSurface
= nsnull
;
3137 PluginInstanceChild::ClearAllSurfaces()
3140 // Get last surface back, and drop it
3141 SurfaceDescriptor temp
= null_t();
3142 NPRect r
= { 0, 0, 1, 1 };
3143 SendShow(r
, temp
, &temp
);
3145 if (gfxSharedImageSurface::IsSharedImage(mCurrentSurface
))
3146 DeallocShmem(static_cast<gfxSharedImageSurface
*>(mCurrentSurface
.get())->GetShmem());
3147 if (gfxSharedImageSurface::IsSharedImage(mBackSurface
))
3148 DeallocShmem(static_cast<gfxSharedImageSurface
*>(mBackSurface
.get())->GetShmem());
3149 mCurrentSurface
= nsnull
;
3150 mBackSurface
= nsnull
;
3153 if (mCurrentSurfaceActor
) {
3154 PPluginSurfaceChild::Send__delete__(mCurrentSurfaceActor
);
3155 mCurrentSurfaceActor
= NULL
;
3157 if (mBackSurfaceActor
) {
3158 PPluginSurfaceChild::Send__delete__(mBackSurfaceActor
);
3159 mBackSurfaceActor
= NULL
;
3165 PluginInstanceChild::AnswerNPP_Destroy(NPError
* aResult
)
3167 PLUGIN_LOG_DEBUG_METHOD
;
3168 AssertPluginThread();
3171 SetProp(mPluginWindowHWND
, kPluginIgnoreSubclassProperty
, (HANDLE
)1);
3174 InfallibleTArray
<PBrowserStreamChild
*> streams
;
3175 ManagedPBrowserStreamChild(streams
);
3177 // First make sure none of these streams become deleted
3178 for (PRUint32 i
= 0; i
< streams
.Length(); ) {
3179 if (static_cast<BrowserStreamChild
*>(streams
[i
])->InstanceDying())
3182 streams
.RemoveElementAt(i
);
3184 for (PRUint32 i
= 0; i
< streams
.Length(); ++i
)
3185 static_cast<BrowserStreamChild
*>(streams
[i
])->FinishDelivery();
3188 if (mCurrentInvalidateTask
) {
3189 mCurrentInvalidateTask
->Cancel();
3190 mCurrentInvalidateTask
= nsnull
;
3192 if (mCurrentAsyncSetWindowTask
) {
3193 mCurrentAsyncSetWindowTask
->Cancel();
3194 mCurrentAsyncSetWindowTask
= nsnull
;
3197 // NPP_Destroy() should be a synchronization point for plugin threads
3198 // calling NPN_AsyncCall: after this function returns, they are no longer
3199 // allowed to make async calls on this instance.
3200 PluginModuleChild::current()->NPP_Destroy(this);
3205 mDeletingHash
= new nsTHashtable
<DeletingObjectEntry
>;
3206 mDeletingHash
->Init();
3207 PluginModuleChild::current()->FindNPObjectsForInstance(this);
3209 mDeletingHash
->EnumerateEntries(InvalidateObject
, NULL
);
3210 mDeletingHash
->EnumerateEntries(DeleteObject
, NULL
);
3212 // Null out our cached actors as they should have been killed in the
3213 // PluginInstanceDestroyed call above.
3214 mCachedWindowActor
= nsnull
;
3215 mCachedElementActor
= nsnull
;
3218 SharedSurfaceRelease();
3219 DestroyWinlessPopupSurrogate();
3220 UnhookWinlessFlashThrottle();
3221 DestroyPluginWindow();
3224 // Pending async calls are discarded, not delivered. This matches the
3225 // in-process behavior.
3226 for (PRUint32 i
= 0; i
< mPendingAsyncCalls
.Length(); ++i
)
3227 mPendingAsyncCalls
[i
]->Cancel();
3229 mPendingAsyncCalls
.Clear();