From 4f8ee0f3ffb1a2498695342d07e06e828e8cd847 Mon Sep 17 00:00:00 2001 From: "jst%mozilla.jstenback.com" Date: Sat, 18 Jun 2005 06:06:45 +0000 Subject: [PATCH] Fixing bug 176079. Provide an API for plugins to control whether popups are enabled or not. Disable popups by default from plugins, but enable/disable popups while handling user input events (mouse click, keydown etc) on the platforms where it's possible (Win32 and Mac), but do that only if the plugin doesn't support the popup enabling/disabling API. r+sr+a=brendan@mozilla.org --- dom/public/base/nsPIDOMWindow.h | 5 +- dom/src/base/nsGlobalWindow.cpp | 5 +- dom/src/base/nsGlobalWindow.h | 2 +- modules/libpref/src/init/all.js | 6 + modules/plugin/base/public/npapi.h | 9 +- modules/plugin/base/public/npupp.h | 56 ++++++++- .../base/public/nsIPluginInstanceInternal.h | 5 + modules/plugin/base/public/nsplugindefs.h | 2 + modules/plugin/base/src/ns4xPlugin.cpp | 58 +++++++--- .../plugin/base/src/ns4xPluginInstance.cpp | 100 ++++++++++++++++ modules/plugin/base/src/ns4xPluginInstance.h | 13 ++- .../base/src/nsPluginNativeWindowWin.cpp | 109 ++++++++++++++++-- 12 files changed, 327 insertions(+), 43 deletions(-) diff --git a/dom/public/base/nsPIDOMWindow.h b/dom/public/base/nsPIDOMWindow.h index e7bf18276c0..76396294dd2 100644 --- a/dom/public/base/nsPIDOMWindow.h +++ b/dom/public/base/nsPIDOMWindow.h @@ -137,7 +137,8 @@ public: virtual void SetOpenerScriptURL(nsIURI* aURI) = 0; - virtual PopupControlState PushPopupControlState(PopupControlState aState) const = 0; + virtual PopupControlState PushPopupControlState(PopupControlState aState, + PRBool aForce) const = 0; virtual void PopPopupControlState(PopupControlState state) const = 0; virtual PopupControlState GetPopupControlState() const = 0; virtual OpenAllowValue GetOpenAllow(const nsAString &aName) = 0; @@ -205,7 +206,7 @@ public: : mWindow(aWindow), mOldState(openAbused) { if (aWindow) { - mOldState = aWindow->PushPopupControlState(aState); + mOldState = aWindow->PushPopupControlState(aState, PR_FALSE); } } diff --git a/dom/src/base/nsGlobalWindow.cpp b/dom/src/base/nsGlobalWindow.cpp index b7e3bc97315..056cc33873b 100644 --- a/dom/src/base/nsGlobalWindow.cpp +++ b/dom/src/base/nsGlobalWindow.cpp @@ -410,9 +410,10 @@ PopPopupControlState(PopupControlState aState) } PopupControlState -nsGlobalWindow::PushPopupControlState(PopupControlState aState) const +nsGlobalWindow::PushPopupControlState(PopupControlState aState, + PRBool aForce) const { - return ::PushPopupControlState(aState, PR_FALSE); + return ::PushPopupControlState(aState, aForce); } void diff --git a/dom/src/base/nsGlobalWindow.h b/dom/src/base/nsGlobalWindow.h index 39c7676aabf..66e1b9e9697 100644 --- a/dom/src/base/nsGlobalWindow.h +++ b/dom/src/base/nsGlobalWindow.h @@ -199,7 +199,7 @@ public: virtual NS_HIDDEN_(void) SetOpenerScriptURL(nsIURI* aURI); - virtual NS_HIDDEN_(PopupControlState) PushPopupControlState(PopupControlState state) const; + virtual NS_HIDDEN_(PopupControlState) PushPopupControlState(PopupControlState state, PRBool aForce) const; virtual NS_HIDDEN_(void) PopPopupControlState(PopupControlState state) const; virtual NS_HIDDEN_(PopupControlState) GetPopupControlState() const; virtual NS_HIDDEN_(OpenAllowValue) GetOpenAllow(const nsAString &aName); diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index f4285250724..6d04fb4449d 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -420,6 +420,12 @@ pref("dom.popup_maximum", 20); pref("dom.popup_allowed_events", "change click dblclick mouseup reset submit"); pref("dom.disable_open_click_delay", 1000); +// Disable popups from plugins by default +// 0 = openAllowed +// 1 = openControlled +// 2 = openAbused +pref("privacy.popups.disable_from_plugins", 2); + pref("dom.event.contextmenu.enabled", true); pref("javascript.enabled", true); diff --git a/modules/plugin/base/public/npapi.h b/modules/plugin/base/public/npapi.h index a80ecbeb1c8..ad9795e3025 100644 --- a/modules/plugin/base/public/npapi.h +++ b/modules/plugin/base/public/npapi.h @@ -37,7 +37,7 @@ /* - * npapi.h $Revision: 3.39 $ + * npapi.h $Revision: 3.40 $ * Netscape client plug-in API spec */ @@ -125,7 +125,7 @@ /*----------------------------------------------------------------------*/ #define NP_VERSION_MAJOR 0 -#define NP_VERSION_MINOR 15 +#define NP_VERSION_MINOR 16 /* The OS/2 version of Netscape uses RC_DATA to define the @@ -673,9 +673,6 @@ void NP_LOADDS NPP_URLNotify(NPP instance, const char* url, jref NP_LOADDS NPP_GetJavaClass(void); #endif NPError NP_LOADDS NPP_GetValue(NPP instance, NPPVariable variable, void *value); -/* - * Uh, shouldn't NPP_SetValue() take an NPPVariable and not an NPNVariable? - */ NPError NP_LOADDS NPP_SetValue(NPP instance, NPNVariable variable, void *value); /* @@ -714,6 +711,8 @@ NPError NP_LOADDS NPN_SetValue(NPP instance, NPPVariable variable, void *value); void NP_LOADDS NPN_InvalidateRect(NPP instance, NPRect *invalidRect); void NP_LOADDS NPN_InvalidateRegion(NPP instance, NPRegion invalidRegion); void NP_LOADDS NPN_ForceRedraw(NPP instance); +void NP_LOADDS NPN_PushPopupEnabledState(NPP instance, NPBool enabled); +void NP_LOADDS NPN_PopPopupEnabledState(NPP instance); #ifdef __cplusplus } /* end extern "C" */ diff --git a/modules/plugin/base/public/npupp.h b/modules/plugin/base/public/npupp.h index dc8dbb3f5ca..f7e8e5d62d9 100644 --- a/modules/plugin/base/public/npupp.h +++ b/modules/plugin/base/public/npupp.h @@ -37,7 +37,7 @@ /* - * npupp.h $Revision: 3.19 $ + * npupp.h $Revision: 3.20 $ * function call mecahnics needed by platform specific glue code. */ @@ -1585,6 +1585,58 @@ typedef void (* NP_LOADDS NPN_SetExceptionUPP)(NPObject *obj, const NPUTF8 *mess #endif +/* NPN_PushPopupsEnabledStateUPP */ + +#if _NPUPP_USE_UPP_ + +typedef UniversalProcPtr NPN_PushPopupsEnabledStateUPP; +enum { + uppNPN_PushPopupsEnabledStateProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPBool))) + | RESULT_SIZE(SIZE_CODE(0)) +}; + +#define NewNPN_PushPopupsEnabledStateProc(FUNC) \ + (NPN_PushPopupsEnabledStateUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_PushPopupsEnabledStateProcInfo, GetCurrentArchitecture()) +#define CallNPN_PushPopupsEnabledStateProc(FUNC, ARG1, ARG2) \ + (jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_PushPopupsEnabledStateProcInfo, (ARG1), (ARG2)) + +#else + +typedef bool (* NP_LOADDS NPN_PushPopupsEnabledStateUPP)(NPP npp, NPBool enabled); +#define NewNPN_PushPopupsEnabledStateProc(FUNC) \ + ((NPN_PushPopupsEnabledStateUPP) (FUNC)) +#define CallNPN_PushPopupsEnabledStateProc(FUNC, ARG1, ARG2) \ + (*(FUNC))((ARG1), (ARG2)) + +#endif + +/* NPN_PopPopupsEnabledState */ + +#if _NPUPP_USE_UPP_ + +typedef UniversalProcPtr NPN_PopPopupsEnabledStateUPP; +enum { + uppNPN_PopPopupsEnabledStateProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | RESULT_SIZE(SIZE_CODE(0)) +}; + +#define NewNPN_PopPopupsEnabledStateProc(FUNC) \ + (NPN_PopPopupsEnabledStateUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_PopPopupsEnabledStateProcInfo, GetCurrentArchitecture()) +#define CallNPN_PopPopupsEnabledStateProc(FUNC, ARG1) \ + (jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_PopPopupsEnabledStateProcInfo, (ARG1)) + +#else + +typedef bool (* NP_LOADDS NPN_PopPopupsEnabledStateUPP)(NPP npp); +#define NewNPN_PopPopupsEnabledStateProc(FUNC) \ + ((NPN_PopPopupsEnabledStateUPP) (FUNC)) +#define CallNPN_PopPopupsEnabledStateProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +#endif @@ -1660,6 +1712,8 @@ typedef struct _NPNetscapeFuncs { NPN_HasMethodUPP hasmethod; NPN_ReleaseVariantValueUPP releasevariantvalue; NPN_SetExceptionUPP setexception; + NPN_PushPopupsEnabledStateUPP pushpopupsenabledstate; + NPN_PopPopupsEnabledStateUPP poppopupsenabledstate; } NPNetscapeFuncs; #ifdef XP_MAC diff --git a/modules/plugin/base/public/nsIPluginInstanceInternal.h b/modules/plugin/base/public/nsIPluginInstanceInternal.h index 97b72f7f9b2..710dc468bd1 100644 --- a/modules/plugin/base/public/nsIPluginInstanceInternal.h +++ b/modules/plugin/base/public/nsIPluginInstanceInternal.h @@ -54,6 +54,11 @@ public: virtual JSObject *GetJSObject(JSContext *cx) = 0; virtual nsresult GetFormValue(nsAString& aValue) = 0; + + virtual void PushPopupsEnabledState(PRBool aEnabled) = 0; + virtual void PopPopupsEnabledState() = 0; + + virtual PRUint16 GetPluginAPIVersion() = 0; }; #endif /* nsIPluginInstanceInternal_h___ */ diff --git a/modules/plugin/base/public/nsplugindefs.h b/modules/plugin/base/public/nsplugindefs.h index edb2d533099..86781cab969 100644 --- a/modules/plugin/base/public/nsplugindefs.h +++ b/modules/plugin/base/public/nsplugindefs.h @@ -365,6 +365,8 @@ enum nsPluginReason { (nsMajorVersion(suppliedV) == nsMajorVersion(requiredV) \ && nsMinorVersion(suppliedV) >= nsMinorVersion(requiredV)) +#define NP_POPUP_API_VERSION 16 + //////////////////////////////////////////////////////////////////////////////// // Classes //////////////////////////////////////////////////////////////////////////////// diff --git a/modules/plugin/base/src/ns4xPlugin.cpp b/modules/plugin/base/src/ns4xPlugin.cpp index 33a5e644564..5b16ac033cd 100644 --- a/modules/plugin/base/src/ns4xPlugin.cpp +++ b/modules/plugin/base/src/ns4xPlugin.cpp @@ -169,6 +169,12 @@ PR_BEGIN_EXTERN_C static void NP_EXPORT _forceredraw(NPP npp); + static void NP_EXPORT + _pushpopupsenabledstate(NPP npp, NPBool enabled); + + static void NP_EXPORT + _poppopupsenabledstate(NPP npp); + static const char* NP_EXPORT _useragent(NPP npp); @@ -375,6 +381,12 @@ ns4xPlugin::CheckClassInitialized(void) CALLBACKS.setexception = NewNPN_SetExceptionProc(FP2TV(_setexception)); + CALLBACKS.pushpopupsenabledstate = + NewNPN_PushPopupsEnabledStateProc(FP2TV(_pushpopupsenabledstate)); + + CALLBACKS.poppopupsenabledstate = + NewNPN_PopPopupsEnabledStateProc(FP2TV(_poppopupsenabledstate)); + initialized = TRUE; NPN_PLUGIN_LOG(PLUGIN_LOG_NORMAL,("NPN callbacks initialized\n")); @@ -1858,27 +1870,16 @@ _getvalue(NPP npp, NPNVariable variable, void *result) } case NPNVDOMWindow: { - ns4xPluginInstance *inst = (ns4xPluginInstance *) npp->ndata; + ns4xPluginInstance *inst = (ns4xPluginInstance *)npp->ndata; NS_ENSURE_TRUE(inst, NPERR_GENERIC_ERROR); - nsCOMPtr pip; - inst->GetPeer(getter_AddRefs(pip)); - nsCOMPtr pp (do_QueryInterface(pip)); - if (pp) { - nsCOMPtr owner; - pp->GetOwner(getter_AddRefs(owner)); - if (owner) { - nsCOMPtr doc; - owner->GetDocument(getter_AddRefs(doc)); - if (doc) { - nsCOMPtr domWindow = - do_QueryInterface(doc->GetScriptGlobalObject()); - if (domWindow) { - NS_ADDREF(*(nsIDOMWindow**)result = domWindow.get()); - return NPERR_NO_ERROR; - } - } - } + nsIDOMWindow *domWindow = inst->GetDOMWindow().get(); + + if (domWindow) { + // Pass over ownership of domWindow to the caller. + (*(nsIDOMWindow**)result) = domWindow; + + return NPERR_NO_ERROR; } return NPERR_GENERIC_ERROR; } @@ -2076,5 +2077,24 @@ _getJavaPeer(NPP npp) #endif /* OJI */ +void NP_EXPORT +_pushpopupsenabledstate(NPP npp, NPBool enabled) +{ + ns4xPluginInstance *inst = (ns4xPluginInstance *)npp->ndata; + if (!inst) + return; + + inst->PushPopupsEnabledState(enabled); +} + +void NP_EXPORT +_poppopupsenabledstate(NPP npp) +{ + ns4xPluginInstance *inst = (ns4xPluginInstance *)npp->ndata; + if (!inst) + return; + + inst->PopPopupsEnabledState(); +} NPP NPPStack::sCurrentNPP = nsnull; diff --git a/modules/plugin/base/src/ns4xPluginInstance.cpp b/modules/plugin/base/src/ns4xPluginInstance.cpp index ddc7b9abbaf..daf7215ee78 100644 --- a/modules/plugin/base/src/ns4xPluginInstance.cpp +++ b/modules/plugin/base/src/ns4xPluginInstance.cpp @@ -49,6 +49,12 @@ #include "nsPluginSafety.h" #include "nsPluginLogging.h" +#include "nsPIPluginInstancePeer.h" +#include "nsIDOMWindow.h" +#include "nsPIDOMWindow.h" +#include "nsIDocument.h" +#include "nsIScriptGlobalObject.h" + #include "nsJSNPRuntime.h" #ifdef XP_OS2 @@ -877,6 +883,16 @@ NS_IMETHODIMP ns4xPluginInstance::Stop(void) NPError error; + // Make sure the plugin didn't leave popups enabled. + if (mPopupStates.Count() > 0) { + nsCOMPtr window = GetDOMWindow(); + nsCOMPtr piwindow = do_QueryInterface(window); + + if (piwindow) { + piwindow->PopPopupControlState(openAbused); + } + } + #if defined(MOZ_WIDGET_GTK) || defined (MOZ_WIDGET_GTK2) if (mXtBin) { gtk_widget_destroy(mXtBin); @@ -927,6 +943,39 @@ NS_IMETHODIMP ns4xPluginInstance::Stop(void) return NS_OK; } +already_AddRefed +ns4xPluginInstance::GetDOMWindow() +{ + nsCOMPtr pp (do_QueryInterface(mPeer)); + if (!pp) { + return nsnull; + } + + nsCOMPtr owner; + pp->GetOwner(getter_AddRefs(owner)); + + if (!owner) { + return nsnull; + } + + nsCOMPtr doc; + owner->GetDocument(getter_AddRefs(doc)); + + if (!doc) { + return nsnull; + } + + nsIScriptGlobalObject *sgo = doc->GetScriptGlobalObject(); + + if (!sgo) { + return nsnull; + } + + nsIDOMWindow *window; + CallQueryInterface(sgo, &window); + + return window; +} //////////////////////////////////////////////////////////////////////// nsresult ns4xPluginInstance::InitializePlugin(nsIPluginInstancePeer* peer) @@ -1564,3 +1613,54 @@ ns4xPluginInstance::GetFormValue(nsAString& aValue) return NS_OK; } + +void +ns4xPluginInstance::PushPopupsEnabledState(PRBool aEnabled) +{ + nsCOMPtr window = GetDOMWindow(); + nsCOMPtr piwindow = do_QueryInterface(window); + + if (!piwindow) + return; + + PopupControlState oldState = + piwindow->PushPopupControlState(aEnabled ? openAllowed : openAbused, + PR_TRUE); + + if (!mPopupStates.AppendElement(NS_INT32_TO_PTR(oldState))) { + // Appending to our state stack failed, push what we just popped. + + piwindow->PopPopupControlState(oldState); + } +} + +void +ns4xPluginInstance::PopPopupsEnabledState() +{ + PRInt32 last = mPopupStates.Count() - 1; + + if (last < 0) { + // Nothing to pop. + + return; + } + + nsCOMPtr window = GetDOMWindow(); + nsCOMPtr piwindow = do_QueryInterface(window); + + if (!piwindow) + return; + + PopupControlState oldState = + (PopupControlState)NS_PTR_TO_INT32(mPopupStates[last]); + + piwindow->PopPopupControlState(oldState); + + mPopupStates.RemoveElementAt(last); +} + +PRUint16 +ns4xPluginInstance::GetPluginAPIVersion() +{ + return fCallbacks->version; +} diff --git a/modules/plugin/base/src/ns4xPluginInstance.h b/modules/plugin/base/src/ns4xPluginInstance.h index 0f5bbf57122..57fedf757ce 100644 --- a/modules/plugin/base/src/ns4xPluginInstance.h +++ b/modules/plugin/base/src/ns4xPluginInstance.h @@ -49,6 +49,7 @@ #endif /* HPUX11 */ #include "nsCOMPtr.h" +#include "nsVoidArray.h" #include "nsIPlugin.h" #include "nsIPluginInstance.h" #include "nsIPluginInstancePeer.h" @@ -71,6 +72,7 @@ //////////////////////////////////////////////////////////////////////// class ns4xPluginStreamListener; +class nsIDOMWindow; struct nsInstanceStream { @@ -132,6 +134,11 @@ public: virtual nsresult GetFormValue(nsAString& aValue); + virtual void PushPopupsEnabledState(PRBool aEnabled); + virtual void PopPopupsEnabledState(); + + virtual PRUint16 GetPluginAPIVersion(); + //////////////////////////////////////////////////////////////////////// // ns4xPluginInstance-specific methods @@ -174,7 +181,9 @@ public: { return mPeer; } - + + already_AddRefed GetDOMWindow(); + protected: nsresult InitializePlugin(nsIPluginInstancePeer* peer); @@ -223,6 +232,8 @@ protected: public: PRLibrary* fLibrary; nsInstanceStream *mStreams; + + nsVoidArray mPopupStates; }; #endif // ns4xPluginInstance_h__ diff --git a/modules/plugin/base/src/nsPluginNativeWindowWin.cpp b/modules/plugin/base/src/nsPluginNativeWindowWin.cpp index fd40cae7840..440ae2a13ec 100644 --- a/modules/plugin/base/src/nsPluginNativeWindowWin.cpp +++ b/modules/plugin/base/src/nsPluginNativeWindowWin.cpp @@ -54,6 +54,7 @@ #include "nsIEventQueueService.h" #include "nsIPluginInstancePeer.h" +#include "nsIPluginInstanceInternal.h" #include "nsPluginSafety.h" #include "nsPluginNativeWindow.h" @@ -134,7 +135,7 @@ private: public: // locals WNDPROC GetWindowProc(); - nsresult GetEventService(nsCOMPtr &aEventService); + nsIEventQueueService *GetEventService(); PluginWindowEvent * GetPluginWindowEvent(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLParam); private: @@ -158,10 +159,11 @@ static PRBool ProcessFlashMessageDelayed(nsPluginNativeWindowWin * aWin, return PR_FALSE; // no need to delay // do stuff - nsCOMPtr eventService; - if (NS_SUCCEEDED(aWin->GetEventService(eventService))) { + nsIEventQueueService *eventService = aWin->GetEventService(); + if (eventService) { nsCOMPtr eventQueue; - eventService->GetThreadEventQueue(PR_GetCurrentThread(), getter_AddRefs(eventQueue)); + eventService->GetThreadEventQueue(PR_GetCurrentThread(), + getter_AddRefs(eventQueue)); if (eventQueue) { PluginWindowEvent *pwe = aWin->GetPluginWindowEvent(hWnd, msg, wParam, lParam); if (pwe) { @@ -173,6 +175,28 @@ static PRBool ProcessFlashMessageDelayed(nsPluginNativeWindowWin * aWin, return PR_FALSE; } +PR_STATIC_CALLBACK(void*) +DelayedPopupsEnabledEvent_Handle(PLEvent *event) +{ + nsIPluginInstanceInternal *instInternal = + (nsIPluginInstanceInternal *)event->owner; + + instInternal->PushPopupsEnabledState(); + + return nsnull; +} + +PR_STATIC_CALLBACK(void) +DelayedPopupsEnabledEvent_Destroy(PLEvent *event) +{ + nsIPluginInstanceInternal *instInternal = + (nsIPluginInstanceInternal *)event->owner; + + NS_RELEASE(instInternal); + + delete event; +} + /** * New plugin window procedure */ @@ -220,7 +244,7 @@ static LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM } } - + PRBool enablePopups = PR_FALSE; // Activate/deactivate mouse capture on the plugin widget // here, before we pass the Windows event to the plugin @@ -237,8 +261,11 @@ static LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM widget->CaptureMouse(PR_TRUE); break; } - case WM_MBUTTONUP: case WM_LBUTTONUP: + enablePopups = PR_TRUE; + + // fall through + case WM_MBUTTONUP: case WM_RBUTTONUP: { nsCOMPtr widget; win->GetPluginWidget(getter_AddRefs(widget)); @@ -246,8 +273,18 @@ static LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM widget->CaptureMouse(PR_FALSE); break; } - } + case WM_KEYDOWN: + // Ignore repeating keydown messages... + if ((lParam & 0x40000000) != 0) { + break; + } + // fall through + case WM_KEYUP: + enablePopups = PR_TRUE; + + break; + } // Macromedia Flash plugin may flood the message queue with some special messages // (WM_USER+1) causing 100% CPU consumption and GUI freeze, see mozilla bug 132759; @@ -259,9 +296,21 @@ static LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM LRESULT res = TRUE; + nsCOMPtr instInternal; nsCOMPtr inst; win->GetPluginInstance(inst); + if (enablePopups) { + nsCOMPtr tmp = do_QueryInterface(inst); + + if (tmp && !nsVersionOK(tmp->GetPluginAPIVersion(), + NP_POPUP_API_VERSION)) { + tmp.swap(instInternal); + + instInternal->PushPopupsEnabledState(); + } + } + sInMessageDispatch = PR_TRUE; NS_TRY_SAFE_CALL_RETURN(res, @@ -270,6 +319,44 @@ static LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM sInMessageDispatch = PR_FALSE; + if (instInternal) { + // Popups are enabled (were enabled before the call to + // CallWindowProc()). Some plugins (at least the flash player) + // post messages from their key handlers etc that delay the actual + // processing, so we need to delay the disabling of popups so that + // popups remain enabled when the flash player ends up processing + // the actual key handlers. We do this by posting an event that + // does the disabling, this way our disabling will happen after + // the handlers in the plugin are done. + + // Note that it's not fatal if any of this fails (which won't + // happen unless we're out of memory anyways) since the plugin + // code will pop any popup state pushed by this plugin on + // destruction. + + nsIEventQueueService *eventService = win->GetEventService(); + if (eventService) { + nsCOMPtr eventQueue; + eventService->GetThreadEventQueue(PR_GetCurrentThread(), + getter_AddRefs(eventQueue)); + if (eventQueue) { + PLEvent *event = new PLEvent; + + if (event) { + nsIPluginInstanceInternal *eventInst = instInternal; + + // Make the event own the plugin instance. + NS_ADDREF(eventInst); + + PL_InitEvent(event, eventInst, DelayedPopupsEnabledEvent_Handle, + DelayedPopupsEnabledEvent_Destroy); + + eventQueue->PostEvent(event); + } + } + } + } + return res; } @@ -349,15 +436,13 @@ PluginWindowEvent_Destroy(PLEvent* self) event->Clear(); } -nsresult nsPluginNativeWindowWin::GetEventService(nsCOMPtr &aEventService) +nsIEventQueueService *nsPluginNativeWindowWin::GetEventService() { if (!mEventService) { mEventService = do_GetService(kEventQueueServiceCID); - if (!mEventService) - return NS_ERROR_FAILURE; } - aEventService = mEventService; - return NS_OK; + + return mEventService; } PluginWindowEvent*