landing patch for bug 326273 "Implement nsIThreadManager" (Mac portions by Mark Mentovai) with reviews from bienvenu, bsmedberg, bzbarsky, josh, roc, and ssieb
git-svn-id: svn://10.0.0.236/trunk@196254 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -122,9 +122,7 @@
|
||||
#include "nsIDOMMimeType.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "prprf.h"
|
||||
#include "plevent.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsIEventQueue.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIInputStreamTee.h"
|
||||
#include "nsIInterfaceInfoManager.h"
|
||||
#include "xptinfo.h"
|
||||
@@ -222,7 +220,6 @@ static NS_DEFINE_CID(kStreamConverterServiceCID, NS_STREAMCONVERTERSERVICE_CID);
|
||||
static const char kDirectoryServiceContractID[] = "@mozilla.org/file/directory_service;1";
|
||||
// for the dialog
|
||||
static NS_DEFINE_IID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
|
||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
static NS_DEFINE_CID(kCPluginManagerCID, NS_PLUGINMANAGER_CID); // needed for NS_TRY_SAFE_CALL
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
@@ -302,13 +299,14 @@ PRBool ReadSectionHeader(nsPluginManifestLineReader& reader, const char *token)
|
||||
// Little helper struct to asynchronously reframe any presentations (embedded)
|
||||
// or reload any documents (full-page), that contained plugins
|
||||
// which were shutdown as a result of a plugins.refresh(1)
|
||||
struct nsPluginDocReframeEvent: public PLEvent {
|
||||
nsPluginDocReframeEvent (nsISupportsArray* aDocs) { mDocs = aDocs; }
|
||||
nsresult HandlePluginDocReframeEvent();
|
||||
class nsPluginDocReframeEvent: public nsRunnable {
|
||||
public:
|
||||
nsPluginDocReframeEvent(nsISupportsArray* aDocs) { mDocs = aDocs; }
|
||||
NS_IMETHOD Run();
|
||||
nsCOMPtr<nsISupportsArray> mDocs;
|
||||
};
|
||||
|
||||
nsresult nsPluginDocReframeEvent::HandlePluginDocReframeEvent() {
|
||||
NS_IMETHODIMP nsPluginDocReframeEvent::Run() {
|
||||
NS_ENSURE_TRUE(mDocs, NS_ERROR_FAILURE);
|
||||
|
||||
PRUint32 c;
|
||||
@@ -345,25 +343,6 @@ nsresult nsPluginDocReframeEvent::HandlePluginDocReframeEvent() {
|
||||
return mDocs->Clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void* PR_CALLBACK HandlePluginDocReframePLEvent(PLEvent* aEvent)
|
||||
{
|
||||
nsPluginDocReframeEvent* event =
|
||||
NS_STATIC_CAST(nsPluginDocReframeEvent*, aEvent);
|
||||
event->HandlePluginDocReframeEvent();
|
||||
return nsnull;
|
||||
}
|
||||
static void PR_CALLBACK DestroyPluginDocReframePLEvent(PLEvent* aEvent)
|
||||
{
|
||||
nsPluginDocReframeEvent* event =
|
||||
NS_STATIC_CAST(nsPluginDocReframeEvent*, aEvent);
|
||||
delete event;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
nsActivePlugin::nsActivePlugin(nsPluginTag* aPluginTag,
|
||||
nsIPluginInstance* aInstance,
|
||||
@@ -976,55 +955,31 @@ void nsPluginTag::SetHost(nsPluginHostImpl * aHost)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// helper struct for asynchronous handeling of plugin unloading
|
||||
struct nsPluginUnloadEvent: public PLEvent {
|
||||
nsPluginUnloadEvent (PRLibrary* aLibrary);
|
||||
class nsPluginUnloadEvent : public nsRunnable {
|
||||
public:
|
||||
nsPluginUnloadEvent(PRLibrary* aLibrary)
|
||||
: mLibrary(aLibrary)
|
||||
{}
|
||||
|
||||
void HandleEvent() {
|
||||
if (mLibrary)
|
||||
NS_TRY_SAFE_CALL_VOID(PR_UnloadLibrary(mLibrary), nsnull, nsnull); // put our unload call in a saftey wrapper
|
||||
else
|
||||
NS_IMETHOD Run() {
|
||||
if (mLibrary) {
|
||||
// put our unload call in a saftey wrapper
|
||||
NS_TRY_SAFE_CALL_VOID(PR_UnloadLibrary(mLibrary), nsnull, nsnull);
|
||||
} else {
|
||||
NS_WARNING("missing library from nsPluginUnloadEvent");
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRLibrary* mLibrary;
|
||||
};
|
||||
nsPluginUnloadEvent::nsPluginUnloadEvent (PRLibrary* aLibrary)
|
||||
{
|
||||
mLibrary = aLibrary;
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
// helper static callback functions for plugin unloading PLEvents
|
||||
static void* PR_CALLBACK HandlePluginUnloadPLEvent(PLEvent* aEvent)
|
||||
{
|
||||
nsPluginUnloadEvent *event = NS_STATIC_CAST(nsPluginUnloadEvent*, aEvent);
|
||||
event->HandleEvent();
|
||||
return nsnull;
|
||||
}
|
||||
static void PR_CALLBACK DestroyPluginUnloadPLEvent(PLEvent* aEvent)
|
||||
{
|
||||
nsPluginUnloadEvent *event = NS_STATIC_CAST(nsPluginUnloadEvent*, aEvent);
|
||||
delete event;
|
||||
}
|
||||
|
||||
// unload plugin asynchronously if possible, otherwise just unload now
|
||||
nsresult PostPluginUnloadEvent (PRLibrary* aLibrary)
|
||||
nsresult PostPluginUnloadEvent(PRLibrary* aLibrary)
|
||||
{
|
||||
nsCOMPtr<nsIEventQueueService> eventService(do_GetService(kEventQueueServiceCID));
|
||||
if (eventService) {
|
||||
nsCOMPtr<nsIEventQueue> eventQueue;
|
||||
eventService->GetThreadEventQueue(PR_GetCurrentThread(), getter_AddRefs(eventQueue));
|
||||
if (eventQueue) {
|
||||
nsPluginUnloadEvent * ev = new nsPluginUnloadEvent(aLibrary);
|
||||
if (ev) {
|
||||
|
||||
PL_InitEvent(ev, nsnull, ::HandlePluginUnloadPLEvent, ::DestroyPluginUnloadPLEvent);
|
||||
if (NS_SUCCEEDED(eventQueue->PostEvent(ev)))
|
||||
return NS_OK;
|
||||
else NS_WARNING("failed to post event onto queue");
|
||||
|
||||
} else NS_WARNING("not able to create plugin unload event");
|
||||
} else NS_WARNING("couldn't get event queue");
|
||||
} else NS_WARNING("couldn't get event queue service");
|
||||
nsCOMPtr<nsIRunnable> ev = new nsPluginUnloadEvent(aLibrary);
|
||||
if (ev && NS_SUCCEEDED(NS_DispatchToCurrentThread(ev)))
|
||||
return NS_OK;
|
||||
|
||||
// failure case
|
||||
NS_TRY_SAFE_CALL_VOID(PR_UnloadLibrary(aLibrary), nsnull, nsnull);
|
||||
@@ -2753,19 +2708,9 @@ nsresult nsPluginHostImpl::ReloadPlugins(PRBool reloadPages)
|
||||
instsToReload &&
|
||||
NS_SUCCEEDED(instsToReload->Count(&c)) &&
|
||||
c > 0) {
|
||||
nsCOMPtr<nsIEventQueueService> eventService(do_GetService(kEventQueueServiceCID));
|
||||
if (eventService) {
|
||||
nsCOMPtr<nsIEventQueue> eventQueue;
|
||||
eventService->GetThreadEventQueue(PR_GetCurrentThread(), getter_AddRefs(eventQueue));
|
||||
if (eventQueue) {
|
||||
nsPluginDocReframeEvent * ev = new nsPluginDocReframeEvent(instsToReload);
|
||||
if (ev) {
|
||||
PL_InitEvent(ev, nsnull, HandlePluginDocReframePLEvent, DestroyPluginDocReframePLEvent);
|
||||
eventQueue->PostEvent(ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> ev = new nsPluginDocReframeEvent(instsToReload);
|
||||
if (ev)
|
||||
NS_DispatchToCurrentThread(ev);
|
||||
}
|
||||
|
||||
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
|
||||
|
||||
@@ -50,37 +50,41 @@
|
||||
|
||||
#include "nsDebug.h"
|
||||
|
||||
#include "plevent.h"
|
||||
#include "nsIEventQueueService.h"
|
||||
#include "nsGUIEvent.h"
|
||||
|
||||
#include "nsIPluginInstancePeer.h"
|
||||
#include "nsIPluginInstanceInternal.h"
|
||||
#include "nsPluginSafety.h"
|
||||
#include "nsPluginNativeWindow.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsTWeakRef.h"
|
||||
|
||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
static NS_DEFINE_CID(kCPluginManagerCID, NS_PLUGINMANAGER_CID); // needed for NS_TRY_SAFE_CALL
|
||||
|
||||
#define NS_PLUGIN_WINDOW_PROPERTY_ASSOCIATION "MozillaPluginWindowPropertyAssociation"
|
||||
|
||||
typedef nsTWeakRef<class nsPluginNativeWindowWin> PluginWindowWeakRef;
|
||||
|
||||
/**
|
||||
* PLEvent handling code
|
||||
*/
|
||||
class PluginWindowEvent : public PLEvent {
|
||||
class PluginWindowEvent : public nsRunnable {
|
||||
public:
|
||||
PluginWindowEvent();
|
||||
void Init(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
void Init(const PluginWindowWeakRef &ref, HWND hWnd, UINT msg, WPARAM wParam,
|
||||
LPARAM lParam);
|
||||
void Clear();
|
||||
HWND GetWnd() { return mWnd; };
|
||||
UINT GetMsg() { return mMsg; };
|
||||
WPARAM GetWParam() { return mWParam; };
|
||||
LPARAM GetLParam() { return mLParam; };
|
||||
PRBool GetIsAlloced() { return mIsAlloced; };
|
||||
void SetIsAlloced(PRBool aIsAlloced) { mIsAlloced = aIsAlloced; };
|
||||
PRBool InUse() { return (mWnd!=NULL || mMsg!=0); };
|
||||
PRBool InUse() { return (mWnd!=NULL || mMsg!=0); };
|
||||
|
||||
NS_IMETHOD Run();
|
||||
|
||||
protected:
|
||||
PluginWindowWeakRef mPluginWindowRef;
|
||||
HWND mWnd;
|
||||
UINT mMsg;
|
||||
WPARAM mWParam;
|
||||
@@ -101,10 +105,12 @@ void PluginWindowEvent::Clear()
|
||||
mLParam = 0;
|
||||
}
|
||||
|
||||
void PluginWindowEvent::Init(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLParam)
|
||||
void PluginWindowEvent::Init(const PluginWindowWeakRef &ref, HWND aWnd,
|
||||
UINT aMsg, WPARAM aWParam, LPARAM aLParam)
|
||||
{
|
||||
NS_ASSERTION(aWnd!=NULL && aMsg!=0, "invalid plugin event value");
|
||||
NS_ASSERTION(mWnd==NULL && mMsg==0 && mWParam==0 && mLParam==0,"event already in use");
|
||||
mPluginWindowRef = ref;
|
||||
mWnd = aWnd;
|
||||
mMsg = aMsg;
|
||||
mWParam = aWParam;
|
||||
@@ -139,14 +145,13 @@ public:
|
||||
// locals
|
||||
WNDPROC GetPrevWindowProc();
|
||||
WNDPROC GetWindowProc();
|
||||
nsIEventQueueService *GetEventService();
|
||||
PluginWindowEvent * GetPluginWindowEvent(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLParam);
|
||||
|
||||
private:
|
||||
WNDPROC mPrevWinProc;
|
||||
WNDPROC mPluginWinProc;
|
||||
nsCOMPtr<nsIEventQueueService> mEventService;
|
||||
PluginWindowEvent mPluginWindowEvent;
|
||||
PluginWindowWeakRef mWeakRef;
|
||||
nsRefPtr<PluginWindowEvent> mCachedPluginWindowEvent;
|
||||
|
||||
public:
|
||||
nsPluginType mPluginType;
|
||||
@@ -164,43 +169,27 @@ static PRBool ProcessFlashMessageDelayed(nsPluginNativeWindowWin * aWin,
|
||||
return PR_FALSE; // no need to delay
|
||||
|
||||
// do stuff
|
||||
nsIEventQueueService *eventService = aWin->GetEventService();
|
||||
if (eventService) {
|
||||
nsCOMPtr<nsIEventQueue> eventQueue;
|
||||
eventService->GetThreadEventQueue(PR_GetCurrentThread(),
|
||||
getter_AddRefs(eventQueue));
|
||||
if (eventQueue) {
|
||||
PluginWindowEvent *pwe = aWin->GetPluginWindowEvent(hWnd, msg, wParam, lParam);
|
||||
if (pwe) {
|
||||
eventQueue->PostEvent(pwe);
|
||||
return PR_TRUE;
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIRunnable> pwe = aWin->GetPluginWindowEvent(hWnd, msg, wParam, lParam);
|
||||
if (pwe) {
|
||||
NS_DispatchToCurrentThread(pwe);
|
||||
return PR_TRUE;
|
||||
}
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(void*)
|
||||
DelayedPopupsEnabledEvent_Handle(PLEvent *event)
|
||||
class nsDelayedPopupsEnabledEvent : public nsRunnable
|
||||
{
|
||||
nsIPluginInstanceInternal *instInternal =
|
||||
(nsIPluginInstanceInternal *)event->owner;
|
||||
|
||||
instInternal->PushPopupsEnabledState(PR_FALSE);
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(void)
|
||||
DelayedPopupsEnabledEvent_Destroy(PLEvent *event)
|
||||
{
|
||||
nsIPluginInstanceInternal *instInternal =
|
||||
(nsIPluginInstanceInternal *)event->owner;
|
||||
|
||||
NS_RELEASE(instInternal);
|
||||
|
||||
delete event;
|
||||
}
|
||||
public:
|
||||
nsDelayedPopupsEnabledEvent(nsIPluginInstanceInternal *inst)
|
||||
: mInst(inst)
|
||||
{}
|
||||
NS_IMETHOD Run() {
|
||||
mInst->PushPopupsEnabledState(PR_FALSE);
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
nsCOMPtr<nsIPluginInstanceInternal> mInst;
|
||||
};
|
||||
|
||||
/**
|
||||
* New plugin window procedure
|
||||
@@ -375,26 +364,10 @@ static LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM
|
||||
// code will pop any popup state pushed by this plugin on
|
||||
// destruction.
|
||||
|
||||
nsIEventQueueService *eventService = win->GetEventService();
|
||||
if (eventService) {
|
||||
nsCOMPtr<nsIEventQueue> 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);
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
new nsDelayedPopupsEnabledEvent(instInternal);
|
||||
if (event) {
|
||||
NS_DispatchToCurrentThread(event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -415,21 +388,14 @@ nsPluginNativeWindowWin::nsPluginNativeWindowWin() : nsPluginNativeWindow()
|
||||
|
||||
mPrevWinProc = NULL;
|
||||
mPluginWinProc = NULL;
|
||||
mPluginWindowEvent.SetIsAlloced(PR_FALSE);
|
||||
mPluginType = nsPluginType_Unknown;
|
||||
}
|
||||
|
||||
nsPluginNativeWindowWin::~nsPluginNativeWindowWin()
|
||||
{
|
||||
// clear any pending events to avoid dangling pointers
|
||||
nsCOMPtr<nsIEventQueueService> eventService(do_GetService(kEventQueueServiceCID));
|
||||
if (eventService) {
|
||||
nsCOMPtr<nsIEventQueue> eventQueue;
|
||||
eventService->GetThreadEventQueue(PR_GetCurrentThread(), getter_AddRefs(eventQueue));
|
||||
if (eventQueue) {
|
||||
eventQueue->RevokeEvents(this);
|
||||
}
|
||||
}
|
||||
// clear weak reference to self to prevent any pending events from
|
||||
// dereferencing this.
|
||||
mWeakRef.forget();
|
||||
}
|
||||
|
||||
WNDPROC nsPluginNativeWindowWin::GetPrevWindowProc()
|
||||
@@ -442,61 +408,39 @@ WNDPROC nsPluginNativeWindowWin::GetWindowProc()
|
||||
return mPluginWinProc;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(void*)
|
||||
PluginWindowEvent_Handle(PLEvent* self)
|
||||
NS_IMETHODIMP PluginWindowEvent::Run()
|
||||
{
|
||||
if (!self)
|
||||
return nsnull;
|
||||
nsPluginNativeWindowWin *win = mPluginWindowRef.get();
|
||||
if (!win)
|
||||
return NS_OK;
|
||||
|
||||
PluginWindowEvent *event = NS_STATIC_CAST(PluginWindowEvent*, self);
|
||||
|
||||
HWND hWnd = event->GetWnd();
|
||||
HWND hWnd = GetWnd();
|
||||
if (!hWnd)
|
||||
return nsnull;
|
||||
return NS_OK;
|
||||
|
||||
nsPluginNativeWindowWin * win = (nsPluginNativeWindowWin *)::GetProp(hWnd, NS_PLUGIN_WINDOW_PROPERTY_ASSOCIATION);
|
||||
if (win) {
|
||||
nsCOMPtr<nsIPluginInstance> inst;
|
||||
win->GetPluginInstance(inst);
|
||||
NS_TRY_SAFE_CALL_VOID(::CallWindowProc(win->GetWindowProc(),
|
||||
hWnd,
|
||||
event->GetMsg(),
|
||||
event->GetWParam(),
|
||||
event->GetLParam()),
|
||||
nsnull, inst);
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(void)
|
||||
PluginWindowEvent_Destroy(PLEvent* self)
|
||||
{
|
||||
if (!self)
|
||||
return;
|
||||
|
||||
PluginWindowEvent *event = NS_STATIC_CAST(PluginWindowEvent*, self);
|
||||
if (event->GetIsAlloced()) {
|
||||
delete event;
|
||||
}
|
||||
else
|
||||
event->Clear();
|
||||
}
|
||||
|
||||
nsIEventQueueService *nsPluginNativeWindowWin::GetEventService()
|
||||
{
|
||||
if (!mEventService) {
|
||||
mEventService = do_GetService(kEventQueueServiceCID);
|
||||
}
|
||||
|
||||
return mEventService;
|
||||
nsCOMPtr<nsIPluginInstance> inst;
|
||||
win->GetPluginInstance(inst);
|
||||
NS_TRY_SAFE_CALL_VOID(::CallWindowProc(win->GetWindowProc(),
|
||||
hWnd,
|
||||
GetMsg(),
|
||||
GetWParam(),
|
||||
GetLParam()),
|
||||
nsnull, inst);
|
||||
Clear();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PluginWindowEvent*
|
||||
nsPluginNativeWindowWin::GetPluginWindowEvent(HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLParam)
|
||||
{
|
||||
if (!mWeakRef) {
|
||||
mWeakRef = this;
|
||||
if (!mWeakRef)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
PluginWindowEvent *event;
|
||||
if (mPluginWindowEvent.InUse()) {
|
||||
if (!mCachedPluginWindowEvent || mCachedPluginWindowEvent->InUse()) {
|
||||
// We have the ability to alloc if needed in case in the future some plugin
|
||||
// should post multiple PostMessages. However, this could lead to many
|
||||
// alloc's per second which could become a performance issue. If/when this
|
||||
@@ -505,15 +449,13 @@ nsPluginNativeWindowWin::GetPluginWindowEvent(HWND aWnd, UINT aMsg, WPARAM aWPar
|
||||
event = new PluginWindowEvent();
|
||||
if (!event)
|
||||
return nsnull;
|
||||
|
||||
event->SetIsAlloced(PR_TRUE);
|
||||
}
|
||||
else {
|
||||
event = &mPluginWindowEvent;
|
||||
event = mCachedPluginWindowEvent;
|
||||
}
|
||||
NS_ADDREF(event);
|
||||
|
||||
event->Init(aWnd, aMsg, aWParam, aLParam);
|
||||
PL_InitEvent(event, (void *)this, &PluginWindowEvent_Handle, PluginWindowEvent_Destroy);
|
||||
event->Init(mWeakRef, aWnd, aMsg, aWParam, aLParam);
|
||||
return event;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user