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:
darin%meer.net
2006-05-10 17:30:15 +00:00
parent 489b71db67
commit 42edf059cf
375 changed files with 8634 additions and 15801 deletions

View File

@@ -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,

View File

@@ -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;
}