pjs/lib/libmocha/et_moz.c

3117 строки
80 KiB
C

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
* Event handling in the Navigator / libmocha
*
* This file contains common code for separate threads to send messages
* to the mozilla thread to get it to do stuff
*/
#include "lm.h"
#include "xp.h"
#include "fe_proto.h"
#include "net.h"
#include "structs.h"
#include "prthread.h"
#include "prtypes.h"
#include "prmem.h"
#include "ds.h" /* XXX required by htmldlgs.h */
#include "htmldlgs.h"
#include "layout.h"
#include "np.h"
#include "prefapi.h"
#include "pa_parse.h"
#include "libi18n.h"
#include "netcache.h"
#include "secnav.h"
#define IL_CLIENT
#include "libimg.h" /* Image Library public API. */
#define CHECKBOX_ACCEPTBIT 0x01
#define CHECKBOX_CHECKBIT 0x02
/* pointer to the mocha thread */
extern PRThread *mozilla_thread;
/****************************************************************************/
PR_STATIC_CALLBACK(void*)
et_PostEvent(ETEvent * e, Bool sync)
{
/*
* Guard against the mozilla_event_queue goes away before we do
* on exit.
*/
if(!mozilla_event_queue)
return(NULL);
/*
* If we are already in the mozilla thread and about to send
* a synchronous message to ourselves just process it right
* now instead of deadlocking
*/
if(sync && PR_CurrentThread() == mozilla_thread) {
void * val;
val = e->event.handler(&e->event);
e->event.destructor(&e->event);
return(val);
}
if(sync)
return(PR_PostSynchronousEvent(mozilla_event_queue, &e->event));
PR_PostEvent(mozilla_event_queue, &e->event);
return(NULL);
}
/*
* synchonous events can't be destroyed until after PR_PostSynchronousEvent()
* has returned. This is a dummy destructor to make sure the event stays
* alive along enough
*/
PR_STATIC_CALLBACK(void)
et_DestroyEvent_WaitForIt(void * event)
{
}
/*
* Generic destructor for event with no private data
*/
PR_STATIC_CALLBACK(void)
et_DestroyEvent_GenericEvent(void * event)
{
XP_FREE(event);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
char* szMessage; /* message for dialog */
JSBool bConfirm; /* TRUE if confirmation, FALSE if alert */
} MozillaEvent_MessageBox;
typedef struct {
ETEvent ce;
char* mainMessage,
* checkMessage,
* okMessage,
* cancelMessage;
JSBool accepted; /* dialog was OKed? */
XP_Bool checked; /* checkbox is checked? */
} MozillaEvent_CheckConfirmBox; /* CheckConfirm message box event */
PR_STATIC_CALLBACK(void*)
et_HandleEvent_MessageBox(MozillaEvent_MessageBox* e)
{
void *pRet;
Bool bPriorJSCalling = FALSE;
if( e->ce.context ) {
bPriorJSCalling = e->ce.context->bJavaScriptCalling;
e->ce.context->bJavaScriptCalling = TRUE;
}
pRet = (void *)JSTYPE_BOOLEAN;
if( e->bConfirm )
pRet = (void *)FE_Confirm(e->ce.context, e->szMessage);
else
FE_Alert(e->ce.context, e->szMessage);
if( e->ce.context )
e->ce.context->bJavaScriptCalling = bPriorJSCalling;
return pRet;
}
PR_STATIC_CALLBACK(void)
et_DestroyEvent_MessageBox(MozillaEvent_MessageBox* event)
{
XP_FREE((char*)event->szMessage);
XP_FREE(event);
}
PR_STATIC_CALLBACK(void*)
et_HandleEvent_CheckConfirmBox(MozillaEvent_CheckConfirmBox* e)
{
void *pRet;
Bool bPriorJSCalling = FALSE;
if( e->ce.context ) {
bPriorJSCalling = e->ce.context->bJavaScriptCalling;
e->ce.context->bJavaScriptCalling = TRUE;
}
e->accepted = FE_CheckConfirm(e->ce.context, e->mainMessage,
e->checkMessage, e->okMessage, e->cancelMessage,
&e->checked);
/* we're restricted to a single (void *) return value, and we need to return
two separate booleans, thus the bit hackery: */
pRet = (void *) ((e->accepted ? CHECKBOX_ACCEPTBIT : 0x0) |
(e->checked ? CHECKBOX_CHECKBIT : 0x0));
if( e->ce.context )
e->ce.context->bJavaScriptCalling = bPriorJSCalling;
return pRet;
}
PR_STATIC_CALLBACK(void)
et_DestroyEvent_CheckConfirmBox(MozillaEvent_CheckConfirmBox* event)
{
XP_FREE((char *)event->mainMessage);
XP_FREE((void *)event->checkMessage);
XP_FREEIF((void *)event->okMessage);
XP_FREEIF((void *)event->cancelMessage);
XP_FREE((void *)event);
}
JSBool
ET_PostMessageBox(MWContext* context, char* szMessage, JSBool bConfirm)
{
JSBool ok = JS_TRUE;
MozillaEvent_MessageBox* event = PR_NEW(MozillaEvent_MessageBox);
if (event == NULL)
return(JS_FALSE);
event->ce.context = context;
event->szMessage = strdup(szMessage);
event->bConfirm = bConfirm;
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_MessageBox,
(PRDestroyEventProc)et_DestroyEvent_MessageBox);
ok = (JSBool) et_PostEvent(&event->ce, TRUE);
return(ok);
}
JSBool
ET_PostCheckConfirmBox(MWContext* context,
char* szMainMessage, char* szCheckMessage,
char* szOKMessage, char* szCancelMessage,
XP_Bool *bChecked)
{
uint8 rtnVal;
MozillaEvent_CheckConfirmBox* event = PR_NEW(MozillaEvent_CheckConfirmBox);
if (event == NULL)
return JS_FALSE;
event->ce.context = context;
event->mainMessage = szMainMessage ? strdup(szMainMessage) : 0;
event->checkMessage = szCheckMessage ? strdup(szCheckMessage) : 0;
event->okMessage = szOKMessage ? strdup(szOKMessage) : 0;
event->cancelMessage = szCancelMessage ? strdup(szCancelMessage) : 0;
event->checked = *bChecked;
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_CheckConfirmBox,
(PRDestroyEventProc)et_DestroyEvent_CheckConfirmBox);
rtnVal = (uint8) et_PostEvent(&event->ce, TRUE);
*bChecked = (rtnVal & CHECKBOX_CHECKBIT) ? JS_TRUE : JS_FALSE;
return (JSBool) (rtnVal & CHECKBOX_ACCEPTBIT) ? JS_TRUE : JS_FALSE;
}
/****************************************************************************/
typedef struct {
ETEvent ce;
const char * szMessage; /* progress message */
} MozillaEvent_Progress;
PR_STATIC_CALLBACK(void)
et_HandleEvent_Progress(MozillaEvent_Progress* e)
{
FE_Progress(e->ce.context, e->szMessage);
}
PR_STATIC_CALLBACK(void)
et_DestroyEvent_Progress(MozillaEvent_MessageBox* event)
{
XP_FREE((char*)event->szMessage);
XP_FREE(event);
}
void
ET_PostProgress(MWContext* context, const char* szMessage)
{
MozillaEvent_Progress* event = PR_NEW(MozillaEvent_Progress);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_Progress,
(PRDestroyEventProc)et_DestroyEvent_Progress);
event->ce.context = context;
if(szMessage)
event->szMessage = strdup(szMessage);
else
event->szMessage = NULL;
et_PostEvent(&event->ce, FALSE);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
void * pStuff;
} MozillaEvent_Void;
PR_STATIC_CALLBACK(void)
et_HandleEvent_ClearTimeout(MozillaEvent_Void* e)
{
FE_ClearTimeout(e->pStuff);
}
void
ET_PostClearTimeout(void * pStuff)
{
MozillaEvent_Void* event = PR_NEW(MozillaEvent_Void);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, NULL,
(PRHandleEventProc)et_HandleEvent_ClearTimeout,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->ce.context = NULL;
event->pStuff = pStuff;
et_PostEvent(&event->ce, FALSE);
}
/****************************************************************************/
/*
* OK, timeouts are messy. We are in a separate thread, we want to
* call the mozilla thread to fire a timeout. When the timeout
* fires we need to get a message sent back to our thread to call
* our timeout since, presumably, our timeout needs to run in our
* thread and not the mozilla thread.
* Make a duplicate of the current event structure in case the
* timeout gets fired and the 'run the closure' event gets sent
* before we have returned from PR_PostSynchronousEvent().
*/
PR_STATIC_CALLBACK(void*)
et_HandleEvent_SetTimeout(MozillaEvent_Timeout* e)
{
MozillaEvent_Timeout* event = XP_NEW_ZAP(MozillaEvent_Timeout);
if (event == NULL)
return(NULL);
event->fnCallback = e->fnCallback;
event->pClosure = e->pClosure;
event->ulTime = e->ulTime;
event->ce.doc_id = e->ce.doc_id;
event->ce.context = e->ce.context;
event->pTimerId = FE_SetTimeout(ET_FireTimeoutCallBack, event, e->ulTime);
return(event->pTimerId);
}
void *
ET_PostSetTimeout(TimeoutCallbackFunction fnCallback, void * pClosure,
uint32 ulTime, int32 doc_id)
{
MozillaEvent_Timeout* event = XP_NEW_ZAP(MozillaEvent_Timeout);
void * ret;
if (event == NULL)
return(NULL);
PR_InitEvent(&event->ce.event, NULL,
(PRHandleEventProc)et_HandleEvent_SetTimeout,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->ce.doc_id = doc_id;
event->fnCallback = fnCallback;
event->pClosure = pClosure;
event->ulTime = ulTime;
/* XXXMLM - pClosure appears to be an MWContext pointer in all the
* instances I've seen. I'll use it for now.
*/
event->ce.context = (MWContext *) pClosure;
ret = et_PostEvent(&event->ce, TRUE);
return(ret);
}
typedef struct {
ETEvent ce;
int32 wrap_width;
int32 parent_layer_id;
} MozillaEvent_CreateLayer;
PR_STATIC_CALLBACK(void*)
et_HandleEvent_CreateLayer(MozillaEvent_CreateLayer * e)
{
int32 layer_id;
/* See if the document has changed since this event was sent. */
if(e->ce.doc_id != XP_DOCID(e->ce.context))
return NULL;
layer_id = LO_CreateNewLayer(e->ce.context, e->wrap_width, e->parent_layer_id);
return (void*)layer_id;
}
int32
ET_PostCreateLayer(MWContext *context, int32 wrap_width, int32 parent_layer_id)
{
int32 ret;
MozillaEvent_CreateLayer * event = XP_NEW_ZAP(MozillaEvent_CreateLayer);
if (event == NULL)
return(0);
PR_InitEvent(&event->ce.event, NULL,
(PRHandleEventProc)et_HandleEvent_CreateLayer,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->ce.context = context;
event->ce.doc_id = XP_DOCID(context);
event->wrap_width = wrap_width;
event->parent_layer_id = parent_layer_id;
ret = (int32)et_PostEvent(&event->ce, TRUE);
return(ret);
}
/****************************************************************************/
PR_STATIC_CALLBACK(void)
et_HandleEvent_DestroyWindow(ETEvent* e)
{
e->context->waitingMode = FALSE;
FE_DestroyWindow(e->context);
}
void
ET_PostDestroyWindow(MWContext * context)
{
ETEvent * event = PR_NEW(ETEvent);
if (event == NULL)
return;
PR_InitEvent(&event->event, context,
(PRHandleEventProc)et_HandleEvent_DestroyWindow,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->context = context;
et_PostEvent(event, FALSE);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
LO_Element * pForm;
int32 action;
int32 docID;
PRPackedBool duplicate;
} MozillaEvent_ManipulateForm;
PR_STATIC_CALLBACK(void)
et_HandleEvent_ManipulateForm(MozillaEvent_ManipulateForm* e)
{
/* see if the document has changed since this event was sent */
if(e->docID != XP_DOCID(e->ce.context))
return;
switch(e->action) {
case EVENT_BLUR:
FE_BlurInputElement(e->ce.context, e->pForm);
break;
case EVENT_FOCUS:
FE_FocusInputElement(e->ce.context, e->pForm);
break;
case EVENT_SELECT:
FE_SelectInputElement(e->ce.context, e->pForm);
break;
case EVENT_CLICK:
FE_ClickInputElement(e->ce.context, e->pForm);
break;
case EVENT_CHANGE:
FE_ChangeInputElement(e->ce.context, e->pForm);
break;
default:
XP_ASSERT(0);
}
}
PR_STATIC_CALLBACK(void)
et_check_already_pending(MozillaEvent_ManipulateForm* event,
MozillaEvent_ManipulateForm* data,
PREventQueue* queue)
{
if (event->ce.event.owner == data->ce.event.owner) {
if (event->action == data->action)
data->duplicate = TRUE;
}
}
void
ET_PostManipulateForm(MWContext * context, LO_Element * pForm, int32 action)
{
MozillaEvent_ManipulateForm* event;
event = PR_NEW(MozillaEvent_ManipulateForm);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, pForm,
(PRHandleEventProc)et_HandleEvent_ManipulateForm,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->ce.context = context;
event->docID = XP_DOCID(context);
event->pForm = pForm;
event->action = action;
event->duplicate = FALSE;
/*
* Now that we have built the event use it to see if a similar
* event already exists. If one does, the owner field will
* get cleared in the event we just created
*/
PR_MapEvents(mozilla_event_queue,
(PREventFunProc)et_check_already_pending,
event);
if (event->duplicate) {
XP_FREE(event);
return;
}
et_PostEvent(&event->ce, FALSE);
}
/****************************************************************************/
PR_STATIC_CALLBACK(void)
et_HandleEvent_ClearView(ETEvent * e)
{
FE_ClearView(e->context, FE_VIEW);
}
void
ET_PostClearView(MWContext * context)
{
ETEvent * event = PR_NEW(ETEvent);
if (event == NULL)
return;
PR_InitEvent(&event->event, context,
(PRHandleEventProc)et_HandleEvent_ClearView,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->context = context;
et_PostEvent(event, FALSE);
}
/****************************************************************************/
PR_STATIC_CALLBACK(void)
et_HandleEvent_FreeImageElement(MozillaEvent_Void* e)
{
LO_ImageStruct *lo_image = (LO_ImageStruct *) e->pStuff;
IL_DestroyImage(lo_image->image_req);
lo_image->image_req = NULL;
}
/*
* From the code flow it looked like some people were depending
* on this getting done before continuing. Not sure if that
* is really the case or not. Do we need to be synchronous?
*/
void
ET_PostFreeImageElement(MWContext * context, void * pStuff)
{
MozillaEvent_Void* event = PR_NEW(MozillaEvent_Void);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_FreeImageElement,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->ce.context = context;
event->pStuff = pStuff;
et_PostEvent(&event->ce, TRUE);
}
/****************************************************************************/
/* Free all images in the mocha image context. */
PR_STATIC_CALLBACK(void)
et_HandleEvent_FreeAnonImages(MozillaEvent_Void* e)
{
IL_DestroyImageGroup((IL_GroupContext *)e->pStuff);
}
void
ET_PostFreeAnonImages(MWContext *context, IL_GroupContext *img_cx)
{
MozillaEvent_Void* event = PR_NEW(MozillaEvent_Void);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_FreeAnonImages,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->ce.context = context;
event->pStuff = img_cx;
et_PostEvent(&event->ce, FALSE);
}
/****************************************************************************/
/*
* Destroy the mocha image context in the Mozilla thread since
* its destruction must succeed the actual destruction of
* anonymous images.
*/
PR_STATIC_CALLBACK(void)
et_HandleEvent_FreeImageContext(MozillaEvent_Void* e)
{
IL_DestroyGroupContext((IL_GroupContext *)e->pStuff);
}
void
ET_PostFreeImageContext(MWContext *context, IL_GroupContext *img_cx)
{
MozillaEvent_Void* event = PR_NEW(MozillaEvent_Void);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_FreeImageContext,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->ce.context = context;
event->pStuff = img_cx;
et_PostEvent(&event->ce, FALSE);
}
/****************************************************************************/
PR_STATIC_CALLBACK(void)
et_HandleEvent_GetUrl(MozillaEvent_Void* e)
{
FE_GetURL(e->ce.context, (URL_Struct *) e->pStuff);
}
void
ET_PostGetUrl(MWContext * context, URL_Struct * pUrl)
{
MozillaEvent_Void* event = PR_NEW(MozillaEvent_Void);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_GetUrl,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->ce.context = context;
event->pStuff = pUrl;
et_PostEvent(&event->ce, FALSE);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
char* szMessage; /* message for dialog */
char* szDefault;
} MozillaEvent_Prompt;
PR_STATIC_CALLBACK(void *)
et_HandleEvent_Prompt(MozillaEvent_Prompt* e)
{
void *pRet;
Bool bPriorJSCalling = FALSE;
if( e->ce.context ) {
bPriorJSCalling = e->ce.context->bJavaScriptCalling;
e->ce.context->bJavaScriptCalling = TRUE;
}
pRet = (void *)FE_Prompt(e->ce.context, e->szMessage, e->szDefault);
if( e->ce.context )
e->ce.context->bJavaScriptCalling = bPriorJSCalling;
return pRet;
}
PR_STATIC_CALLBACK(void)
et_DestroyEvent_Prompt(MozillaEvent_Prompt* event)
{
XP_FREE((char*)event->szMessage);
XP_FREE((char*)event->szDefault);
XP_FREE(event);
}
char *
ET_PostPrompt(MWContext* context, const char* szMessage, const char * szDefault)
{
char * ret;
MozillaEvent_Prompt* event = PR_NEW(MozillaEvent_Prompt);
if (event == NULL)
return(NULL);
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_Prompt,
(PRDestroyEventProc)et_DestroyEvent_Prompt);
event->ce.context = context;
event->szMessage = strdup(szMessage);
if(szDefault)
event->szDefault = strdup(szDefault);
else
event->szDefault = NULL;
ret = (char *) et_PostEvent(&event->ce, TRUE);
return(ret);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
URL_Struct * pUrl;
char * szName;
Chrome * pChrome;
LMWindowGroup * group;
} MozillaEvent_NewWindow;
PR_STATIC_CALLBACK(void*)
et_HandleEvent_NewWindow(MozillaEvent_NewWindow* e)
{
LMWindowGroup *grp = e->group;
MWContext *ans = FE_MakeNewWindow(e->ce.context, e->pUrl,
e->szName, e->pChrome);
if(grp != NULL) {
LM_AddContextToGroup(grp, ans);
}
return (void *) ans;
}
PR_STATIC_CALLBACK(void)
et_DestroyEvent_NewWindow(MozillaEvent_NewWindow* event)
{
NET_DropURLStruct(event->pUrl);
if (event->szName)
XP_FREE((char*)event->szName);
XP_FREE(event);
}
MWContext *
ET_PostNewWindow(MWContext* context, URL_Struct * pUrl,
char * szName, Chrome * pChrome, LMWindowGroup *grp)
{
MWContext * ret;
MozillaEvent_NewWindow* event = PR_NEW(MozillaEvent_NewWindow);
if (event == NULL)
return(NULL);
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_NewWindow,
(PRDestroyEventProc)et_DestroyEvent_NewWindow);
event->ce.context = context;
event->pUrl = NET_HoldURLStruct(pUrl);
if(szName)
event->szName = strdup(szName);
else
event->szName = NULL;
event->pChrome = pChrome;
event->group = grp;
ret = (MWContext *) et_PostEvent(&event->ce, TRUE);
return(ret);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
Chrome * pChrome;
} MozillaEvent_UpdateWindow;
PR_STATIC_CALLBACK(void)
et_HandleEvent_UpdateWindow(MozillaEvent_UpdateWindow* e)
{
FE_UpdateChrome(e->ce.context, e->pChrome);
}
void
ET_PostUpdateChrome(MWContext* context, Chrome * pChrome)
{
MozillaEvent_UpdateWindow* event = PR_NEW(MozillaEvent_UpdateWindow);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_UpdateWindow,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->ce.context = context;
event->pChrome = pChrome;
et_PostEvent(&event->ce, TRUE);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
Chrome * pChrome;
} MozillaEvent_QueryWindow;
PR_STATIC_CALLBACK(void)
et_HandleEvent_QueryWindow(MozillaEvent_QueryWindow* e)
{
FE_QueryChrome(e->ce.context, e->pChrome);
}
void
ET_PostQueryChrome(MWContext* context, Chrome * pChrome)
{
MozillaEvent_QueryWindow* event = PR_NEW(MozillaEvent_QueryWindow);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_QueryWindow,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->ce.context = context;
event->pChrome = pChrome;
et_PostEvent(&event->ce, TRUE);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
int32 *pPixel;
int32 *pPallette;
} MozillaEvent_GetColorDepth;
PR_STATIC_CALLBACK(void)
et_HandleEvent_GetColorDepth(MozillaEvent_GetColorDepth* e)
{
FE_GetPixelAndColorDepth(e->ce.context, e->pPixel, e->pPallette);
}
void
ET_PostGetColorDepth(MWContext* context, int32 *pPixel, int32 *pPallette)
{
int32 *pMPixel = NULL, *pMPallette = NULL;
MozillaEvent_GetColorDepth* event = PR_NEW(MozillaEvent_GetColorDepth);
if (event == NULL)
return;
pMPixel = XP_ALLOC(sizeof(int32));
if (pMPixel == NULL)
goto fail;
pMPallette = XP_ALLOC(sizeof(int32));
if (pMPallette == NULL)
goto fail;
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_GetColorDepth,
(PRDestroyEventProc)et_DestroyEvent_WaitForIt);
event->ce.context = context;
event->pPixel = pMPixel;
event->pPallette = pMPallette;
et_PostEvent(&event->ce, TRUE);
*pPixel = *event->pPixel;
*pPallette = *event->pPallette;
fail:
if (pMPixel)
XP_FREE(pMPixel);
if (pMPallette)
XP_FREE(pMPallette);
if (event)
XP_FREE(event);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
int32 *pX;
int32 *pY;
} MozillaEvent_GetScreenSize;
PR_STATIC_CALLBACK(void)
et_HandleEvent_GetScreenSize(MozillaEvent_GetScreenSize* e)
{
FE_GetScreenSize(e->ce.context, e->pX, e->pY);
}
void
ET_PostGetScreenSize(MWContext* context, int32 *pX, int32 *pY)
{
int32 *pMX = NULL, *pMY = NULL;
MozillaEvent_GetScreenSize* event = PR_NEW(MozillaEvent_GetScreenSize);
if (event == NULL)
return;
pMX = XP_ALLOC(sizeof(int32));
if (pMX == NULL)
goto fail;
pMY = XP_ALLOC(sizeof(int32));
if (pMY == NULL)
goto fail;
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_GetScreenSize,
(PRDestroyEventProc)et_DestroyEvent_WaitForIt);
event->ce.context = context;
event->pX = pMX;
event->pY = pMY;
et_PostEvent(&event->ce, TRUE);
*pX = *event->pX;
*pY = *event->pY;
fail:
if (pMX)
XP_FREE(pMX);
if (pMY)
XP_FREE(pMY);
if (event)
XP_FREE(event);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
int32 *pX;
int32 *pY;
int32 *pLeft;
int32 *pTop;
} MozillaEvent_GetAvailScreenRect;
PR_STATIC_CALLBACK(void)
et_HandleEvent_GetAvailScreenRect(MozillaEvent_GetAvailScreenRect* e)
{
FE_GetAvailScreenRect(e->ce.context, e->pX, e->pY, e->pLeft, e->pTop);
}
void
ET_PostGetAvailScreenRect(MWContext* context, int32 *pX, int32 *pY, int32 *pLeft,
int32 *pTop)
{
int32 *pMX = NULL, *pMY = NULL, *pMLeft = NULL, *pMTop = NULL;
MozillaEvent_GetAvailScreenRect* event = PR_NEW(MozillaEvent_GetAvailScreenRect);
if (event == NULL)
return;
pMX = XP_ALLOC(sizeof(int32));
if (pMX == NULL)
goto fail;
pMY = XP_ALLOC(sizeof(int32));
if (pMY == NULL)
goto fail;
pMLeft = XP_ALLOC(sizeof(int32));
if (pMLeft == NULL)
goto fail;
pMTop = XP_ALLOC(sizeof(int32));
if (pMTop == NULL)
goto fail;
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_GetAvailScreenRect,
(PRDestroyEventProc)et_DestroyEvent_WaitForIt);
event->ce.context = context;
event->pX = pMX;
event->pY = pMY;
event->pLeft = pMLeft;
event->pTop = pMTop;
et_PostEvent(&event->ce, TRUE);
*pX = *event->pX;
*pY = *event->pY;
*pLeft = *event->pLeft;
*pTop = *event->pTop;
fail:
if (pMX)
XP_FREE(pMX);
if (pMY)
XP_FREE(pMY);
if (pMLeft)
XP_FREE(pMLeft);
if (pMTop)
XP_FREE(pMTop);
if (event)
XP_FREE(event);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
char * szText;
} MozillaEvent_GetSelectedText;
PR_STATIC_CALLBACK(void*)
et_HandleEvent_GetSelectedText(MozillaEvent_GetSelectedText* e)
{
char * rv;
rv = (char *)LO_GetSelectionText(e->ce.context);
if (rv)
rv = XP_STRDUP(rv);
return rv;
}
char *
ET_PostGetSelectedText(MWContext* context)
{
char * ret;
MozillaEvent_GetSelectedText* event = XP_NEW_ZAP(MozillaEvent_GetSelectedText);
if (event == NULL)
return(NULL);
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_GetSelectedText,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->ce.context = context;
ret = (char *) et_PostEvent(&event->ce, TRUE);
return(ret);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
int location;
int32 x, y;
} MozillaEvent_ScrollTo;
PR_STATIC_CALLBACK(void)
et_HandleEvent_ScrollTo(MozillaEvent_ScrollTo* e)
{
FE_ScrollDocTo(e->ce.context, e->location, e->x, e->y);
}
void
ET_PostScrollDocTo(MWContext* context, int loc, int32 x, int32 y)
{
MozillaEvent_ScrollTo* event = PR_NEW(MozillaEvent_ScrollTo);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_ScrollTo,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->ce.context = context;
event->location = loc;
event->x = x;
event->y = y;
et_PostEvent(&event->ce, FALSE);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
int location;
int32 x, y;
} MozillaEvent_ScrollBy;
PR_STATIC_CALLBACK(void)
et_HandleEvent_ScrollBy(MozillaEvent_ScrollBy* e)
{
FE_ScrollDocBy(e->ce.context, e->location, e->x, e->y);
}
void
ET_PostScrollDocBy(MWContext* context, int loc, int32 x, int32 y)
{
MozillaEvent_ScrollBy* event = PR_NEW(MozillaEvent_ScrollBy);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_ScrollBy,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->ce.context = context;
event->location = loc;
event->x = x;
event->y = y;
et_PostEvent(&event->ce, FALSE);
}
/****************************************************************************/
PR_STATIC_CALLBACK(void)
et_HandleEvent_BackCommand(ETEvent* e)
{
FE_BackCommand(e->context);
}
void
ET_PostBackCommand(MWContext* context)
{
ETEvent* event = PR_NEW(ETEvent);
if (event == NULL)
return;
PR_InitEvent(&event->event, context,
(PRHandleEventProc)et_HandleEvent_BackCommand,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->context = context;
et_PostEvent(event, FALSE);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
} MozillaEvent_ForwardCommand;
PR_STATIC_CALLBACK(void)
et_HandleEvent_ForwardCommand(ETEvent* e)
{
FE_ForwardCommand(e->context);
}
void
ET_PostForwardCommand(MWContext* context)
{
ETEvent* event = PR_NEW(ETEvent);
if (event == NULL)
return;
PR_InitEvent(&event->event, context,
(PRHandleEventProc)et_HandleEvent_ForwardCommand,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->context = context;
et_PostEvent(event, FALSE);
}
/****************************************************************************/
PR_STATIC_CALLBACK(void)
et_HandleEvent_HomeCommand(ETEvent* e)
{
FE_HomeCommand(e->context);
}
void
ET_PostHomeCommand(MWContext* context)
{
ETEvent* event = PR_NEW(ETEvent);
if (event == NULL)
return;
PR_InitEvent(&event->event, context,
(PRHandleEventProc)et_HandleEvent_HomeCommand,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->context = context;
et_PostEvent(event, FALSE);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
char * szName;
XP_Bool matchCase;
XP_Bool searchBackward;
} MozillaEvent_FindCommand;
PR_STATIC_CALLBACK(void*)
et_HandleEvent_FindCommand(MozillaEvent_FindCommand* e)
{
return(void *)FE_FindCommand(e->ce.context, e->szName, e->matchCase, e->searchBackward, FALSE);
}
PR_STATIC_CALLBACK(void)
et_DestroyEvent_FindCommand(MozillaEvent_FindCommand* event)
{
if(event->szName)
XP_FREE((char*)event->szName);
XP_FREE(event);
}
JSBool
ET_PostFindCommand(MWContext* context, char *szName, JSBool matchCase,
JSBool searchBackward)
{
JSBool ret;
MozillaEvent_FindCommand* event = PR_NEW(MozillaEvent_FindCommand);
if (event == NULL)
return JS_FALSE;
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_FindCommand,
(PRDestroyEventProc)et_DestroyEvent_FindCommand);
event->ce.context = context;
if(szName)
event->szName = strdup(szName);
else
event->szName = NULL;
event->matchCase = (XP_Bool)matchCase;
event->searchBackward = (XP_Bool)searchBackward;
ret = (JSBool)et_PostEvent(&event->ce, TRUE);
return(ret);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
} MozillaEvent_PrintCommand;
PR_STATIC_CALLBACK(void)
et_HandleEvent_PrintCommand(ETEvent* e)
{
FE_PrintCommand(e->context);
}
void
ET_PostPrintCommand(MWContext* context)
{
ETEvent* event = PR_NEW(ETEvent);
if (event == NULL)
return;
PR_InitEvent(&event->event, context,
(PRHandleEventProc)et_HandleEvent_PrintCommand,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->context = context;
et_PostEvent(event, FALSE);
}
/****************************************************************************/
PR_STATIC_CALLBACK(void)
et_HandleEvent_OpenFileCommand(ETEvent* e)
{
}
void
ET_PostOpenFileCommand(MWContext* context)
{
ETEvent* event = PR_NEW(ETEvent);
if (event == NULL)
return;
PR_InitEvent(&event->event, context,
(PRHandleEventProc)et_HandleEvent_OpenFileCommand,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->context = context;
et_PostEvent(event, FALSE);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
char* szMessage; /* message for dialog */
} MozillaEvent_HtmlAlert;
PR_STATIC_CALLBACK(void)
et_HandleEvent_HtmlAlert(MozillaEvent_HtmlAlert* e)
{
XP_MakeHTMLAlert(e->ce.context, e->szMessage);
}
PR_STATIC_CALLBACK(void)
et_DestroyEvent_HtmlAlert(MozillaEvent_HtmlAlert* event)
{
XP_FREE((char*)event->szMessage);
XP_FREE(event);
}
void
ET_MakeHTMLAlert(MWContext* context, const char* szMessage)
{
MozillaEvent_HtmlAlert* event = PR_NEW(MozillaEvent_HtmlAlert);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_HtmlAlert,
(PRDestroyEventProc)et_DestroyEvent_HtmlAlert);
event->ce.context = context;
event->szMessage = strdup(szMessage);
et_PostEvent(&event->ce, FALSE);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
LO_Element * pEle;
int type;
ETClosureFunc fnClosure;
void * pStuff;
ETEventStatus status;
} MozillaEvent_JsEventAck;
PR_STATIC_CALLBACK(void)
et_HandleEvent_JsEventAck(MozillaEvent_JsEventAck* e)
{
/* make sure we haven't gone away somehow */
if(e->ce.doc_id != XP_DOCID(e->ce.context))
e->status = EVENT_PANIC;
(*e->fnClosure) (e->ce.context, e->pEle, e->type, e->pStuff, e->status);
}
void
ET_PostJsEventAck(MWContext* context, LO_Element * pEle, int type,
ETClosureFunc fnClosure, void * pStuff,
ETEventStatus status)
{
MozillaEvent_JsEventAck* event = PR_NEW(MozillaEvent_JsEventAck);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_JsEventAck,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->ce.context = context;
event->ce.doc_id = XP_DOCID(context);
event->pEle = pEle;
event->type = type;
event->fnClosure = fnClosure;
event->pStuff = pStuff;
event->status = status;
et_PostEvent(&event->ce, FALSE);
}
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
typedef struct {
ETEvent ce;
FO_Present_Types format;
URL_Struct * pUrl;
void * pStuff;
uint32 ulBytes;
} MozillaEvent_GenericNetLib;
PR_STATIC_CALLBACK(void*)
et_HandleEvent_CacheConverter(MozillaEvent_GenericNetLib* e)
{
void *retval = (void *)NET_CacheConverter(e->format, e->pStuff, e->pUrl,
e->ce.context);
return retval;
}
PR_STATIC_CALLBACK(void)
et_DestroyEvent_NetlibWithUrl(MozillaEvent_GenericNetLib* e)
{
NET_DropURLStruct(e->pUrl);
XP_FREE(e);
}
NET_StreamClass *
ET_net_CacheConverter(FO_Present_Types format, void * obj,
URL_Struct *pUrl, MWContext * context)
{
NET_StreamClass * ret;
MozillaEvent_GenericNetLib* event = PR_NEW(MozillaEvent_GenericNetLib);
if (event == NULL)
return(NULL);
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_CacheConverter,
(PRDestroyEventProc)et_DestroyEvent_NetlibWithUrl);
event->ce.context = context;
event->format = format;
event->pStuff = obj;
event->pUrl = NET_HoldURLStruct(pUrl);
ret = (NET_StreamClass *) et_PostEvent(&event->ce, TRUE);
return(ret);
}
/****************************************************************************/
PR_STATIC_CALLBACK(void)
et_HandleEvent_FindURLInCache(MozillaEvent_GenericNetLib* e)
{
NET_FindURLInCache(e->pUrl, e->ce.context);
}
/* NOTE: as far as libmocha is concerned, we just need this routine
to complete. We don't care about the return value
*/
void
ET_net_FindURLInCache(URL_Struct * pUrl, MWContext * pContext)
{
MozillaEvent_GenericNetLib* event = PR_NEW(MozillaEvent_GenericNetLib);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, pContext,
(PRHandleEventProc)et_HandleEvent_FindURLInCache,
(PRDestroyEventProc)et_DestroyEvent_NetlibWithUrl);
event->ce.context = pContext;
event->pUrl = NET_HoldURLStruct(pUrl);
et_PostEvent(&event->ce, TRUE);
}
/****************************************************************************/
PR_STATIC_CALLBACK(void*)
et_HandleEvent_StreamBuilder(MozillaEvent_GenericNetLib* e)
{
NET_StreamClass *rv;
NET_SetActiveEntryBusyStatus(e->pUrl, TRUE);
rv = NET_StreamBuilder(e->format, e->pUrl, e->ce.context);
NET_SetActiveEntryBusyStatus(e->pUrl, FALSE);
return((void *)rv);
}
NET_StreamClass *
ET_net_StreamBuilder(FO_Present_Types format, URL_Struct *pUrl,
MWContext * pContext)
{
NET_StreamClass * ret;
MozillaEvent_GenericNetLib* event = PR_NEW(MozillaEvent_GenericNetLib);
if (event == NULL)
return(NULL);
PR_InitEvent(&event->ce.event, pContext,
(PRHandleEventProc)et_HandleEvent_StreamBuilder,
(PRDestroyEventProc)et_DestroyEvent_NetlibWithUrl);
event->ce.context = pContext;
event->format = format;
event->pUrl = NET_HoldURLStruct(pUrl);
ret = (NET_StreamClass *) et_PostEvent(&event->ce, TRUE);
return(ret);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
NET_StreamClass * stream;
void * data;
size_t len;
JSBool self_modifying;
JSBool processed;
} MozillaEvent_DocWrite;
/*
* A lot of this should get moved out to the layout module
* I don't think we need to bother locking layout in this function
* since we are running in the mozilla thread and the mocha
* thread is blocked waiting for our return value.
*/
PR_STATIC_CALLBACK(void*)
et_HandleEvent_DocWrite(MozillaEvent_DocWrite* e)
{
lo_TopState *top_state;
int32 pre_doc_id;
LO_Element * save_blocking = NULL;
LO_Element * current_script = NULL;
Bool bumped_no_newline_count = FALSE;
uint save_overflow=0;
int status;
e->processed = JS_TRUE;
/*
* If the context has a doc_id of -1 it means that its being destroyed
* If the context's doc_id has changed only process the event if the
* original doc_id was zero (i.e. this is the first write and it will
* create a new doc with a new doc_id)
*/
pre_doc_id = XP_DOCID(e->ce.context);
if ((e->ce.doc_id && e->ce.doc_id != pre_doc_id) || (pre_doc_id == -1)) {
#ifdef DEBUG_chouck
XP_TRACE(("Ignoring doc.write since doc_id changed"));
#endif
ET_DocWriteAck(e->ce.context, -1);
return((void *) -1);
}
if (!ET_ContinueProcessing(e->ce.context)) {
#ifdef DEBUG_chouck
XP_TRACE(("Ignoring doc.write since was interrupted"));
#endif
ET_DocWriteAck(e->ce.context, -1);
return((void *) -1);
}
/* make sure top_state doesn't go away while we are holding onto it */
LO_LockLayout();
top_state = lo_GetMochaTopState(e->ce.context);
/* tell layout that we are writing */
if (top_state) {
if (top_state->input_write_level >= MAX_INPUT_WRITE_LEVEL-1) {
LO_UnlockLayout();
ET_DocWriteAck(e->ce.context, -1);
return ((void *) -1);
}
top_state->input_write_level++;
if (top_state->doc_data) {
/* Suppress generated line counting if self-modifying. */
if (e->self_modifying) {
top_state->doc_data->no_newline_count++;
bumped_no_newline_count = TRUE;
}
/* Save the overflow counter and XXX */
save_overflow = top_state->doc_data->overflow_depth;
top_state->doc_data->overflow_depth = 0;
}
else {
save_overflow = 0;
}
current_script = top_state->current_script;
/*
* if we are currently blocked by a <script> tag unblock
* layout for this putblock since this is some of the
* script data coming through. If we are blocked on
* something other than a script tag don't unblock, this
* stuff will just get shoved onto the list to be
* processed after we get unblocked
*/
save_blocking = top_state->layout_blocking_element;
if (save_blocking && save_blocking->type == LO_SCRIPT)
top_state->layout_blocking_element = NULL;
}
LO_UnlockLayout();
/* shove the data out */
status = (*e->stream->put_block)(e->stream, e->data, e->len);
LO_LockLayout();
/* I doubt top_state could have changed but try to be safe */
top_state = lo_GetMochaTopState(e->ce.context);
/* if the doc is still around we are done so clean up */
if (top_state) {
/* Stop suppressing generated line counting if self-modifying. */
if (bumped_no_newline_count) {
XP_ASSERT(top_state->doc_data);
top_state->doc_data->no_newline_count--;
}
if (XP_DOCID(e->ce.context) == pre_doc_id) {
if (top_state->doc_data) {
top_state->doc_data->overflow_depth += save_overflow;
XP_ASSERT(top_state->doc_data->overflow_depth >= 0);
}
if(top_state->layout_blocking_element == NULL) {
/*
* the stuff we wrote didn't block us. continue to block
* on the script tag
*/
top_state->layout_blocking_element = save_blocking;
top_state->input_write_level--;
ET_DocWriteAck(e->ce.context, status);
}
else {
/*
* If we had been blocked on the script tag but now we are
* blocked by something else make sure we reblock on
* the script tag when the new thing is done
*/
LO_CreateReblockTag(e->ce.context, current_script);
}
}
else {
/*
* we just created a new top_state so its input_write_level
* value should be OK. Don't mess with it.
*/
ET_DocWriteAck(e->ce.context, status);
}
}
LO_UnlockLayout();
return((void *) status);
}
PR_STATIC_CALLBACK(void)
et_DestroyEvent_DocWrite(MozillaEvent_DocWrite* e)
{
if (!e->processed)
ET_DocWriteAck(e->ce.context, -1);
XP_FREE(e);
}
static QueueStackElement *
et_PushEventQueue(MWContext * context)
{
LMWindowGroup *grp;
QueueStackElement * qse;
char name[32];
grp = lm_MWContextToGroup(context);
if(grp == NULL) {
grp = LM_GetDefaultWindowGroup(context);
LM_AddContextToGroup(grp, context);
}
/* catch script src= tags that generate themselves. */
if (grp->queue_depth >= 5)
return NULL;
/* see if we've already got one */
qse = grp->queue_stack->up;
if (!qse) {
qse = XP_NEW_ZAP(QueueStackElement);
if (!qse)
return NULL;
PR_snprintf(name, sizeof name, "mocha-stack-queue-%d",
grp->queue_depth + 1);
qse->queue = PR_CreateEventQueue(name, grp->thread);
if (!qse->queue) {
XP_DELETE(qse);
return NULL;
}
grp->queue_count++;
qse->down = grp->queue_stack;
grp->queue_stack->up = qse;
}
grp->queue_depth++;
qse->context = context;
qse->done = FALSE;
/*
* This should get set by our caller
*/
qse->doc_id = -1;
grp->queue_stack = qse;
return qse;
}
static void *
et_PopEventQueue(MWContext *mwc)
{
LMWindowGroup *grp;
QueueStackElement * qse;
void * ret;
grp = lm_MWContextToGroup(mwc);
XP_ASSERT(grp != NULL);
qse = grp->queue_stack;
ret = qse->retval;
grp->queue_stack = qse->down;
grp->queue_depth--;
if (grp->queue_count > 2) {
/* free the entry we're popping */
grp->queue_stack->up = NULL;
PR_DestroyEventQueue(qse->queue);
XP_DELETE(qse);
grp->queue_count--;
}
return ret;
}
/*
* Send the string str over to the mozilla thread and push it through
* layout. This is an asynchronous event as far as NSPR is concerned
* but incase str pushes up any script or style tags we will enter a
* sub event loop to handle reflections and evaluations generated by
* this write but otherwise block the mocha thread until they have
* all been proceed.
*/
int
ET_lo_DoDocWrite(JSContext *cx, MWContext * context, NET_StreamClass * stream,
char * str, size_t len, int32 doc_id)
{
MochaDecoder * decoder;
MozillaEvent_DocWrite * event;
QueueStackElement * qse;
int ret = -1;
decoder = LM_GetMochaDecoder(context);
if (!decoder)
return ret;
#ifdef XP_UNIX
/*
* NOTE: we need to toss the string out if it's doc_id doesn't match
* the current XP_DOCID...
*
* the problem could be reproduced as follows on an IRIX 6.3
* O2 workstation with "lots" of plugins;
*
* 1. load a "plain" HTML page...
* 2. select "about:plugins" from the help menu...
* 3. select "about:communicator" from the help menu...
* 4. hit the "back" button quickly to move across the
* "about:plugins" page before it's had a chance to
* finish loading...
* 5. crashes trying to execute events from the "about:plugins"
* page in the context of the "plain" HTML page...
*
* WARNING: there seems to be a memory corruption problem somewhere
* in the "event" system. Follow the same procedure I
* outlined above, except instead of loading "about:plugins"
* from the menu, load the "aboutplg.html" source file
* directly. If you switch rapidly across this page
* you will eventually see errors like "freeing free
* chunk" and "passing junk pointer to realloc" in the
* course of freeing ETEvents. After a while, this will
* result in a variety of random crashes due to memory
* corruption errors... [ filing a new bug for this one ]
*
*/
if (doc_id && (doc_id != XP_DOCID(context))) {
LM_PutMochaDecoder(decoder);
return ret;
}
#endif
event = XP_NEW_ZAP(MozillaEvent_DocWrite);
if (event == NULL) {
LM_PutMochaDecoder(decoder);
return ret;
}
qse = et_PushEventQueue(context);
if (!qse) {
XP_FREEIF(event);
LM_PutMochaDecoder(decoder);
return ret;
}
/*
* Set the reciever doc_id to the one that gets passed in
*/
/* MLM - this used to be et_TopQueue, but we know that et_TopQueue
* and qse are equivalent at this point. */
qse->doc_id = doc_id;
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_DocWrite,
(PRDestroyEventProc)et_DestroyEvent_DocWrite);
event->ce.context = context;
event->ce.doc_id = doc_id;
event->data = str;
event->len = len;
event->stream = stream;
event->self_modifying = (JSBool)(cx == decoder->js_context);
et_PostEvent(&event->ce, FALSE);
/* spin here until we get our DocWriteAck */
et_SubEventLoop(qse);
ret = (int) et_PopEventQueue(context);
/* Sample the doc_id, since we know that it's good */
/* XXX do this in InitWindowContent only, not here and in DefineDocument */
decoder->doc_id = XP_DOCID(context);
LM_PutMochaDecoder(decoder);
return ret;
}
/****************************************************************************/
PR_STATIC_CALLBACK(Bool)
et_HandleEvent_PrepareLayerForWriting(JSEvent* e)
{
CL_Layer *layer;
Bool rv;
if (e->ce.doc_id != XP_DOCID(e->ce.context))
return FALSE;
LO_LockLayout();
layer = LO_GetLayerFromId(e->ce.context, e->layer_id);
/* e->data points to the referer string, or null */
rv = LO_PrepareLayerForWriting(e->ce.context, e->layer_id,
(const char *)e->data,
LO_GetLayerWrapWidth(layer));
LO_UnlockLayout();
return rv;
}
PR_STATIC_CALLBACK(void)
et_DestroyEvent_PrepareLayerForWriting(JSEvent* e)
{
XP_FREEIF(e->data);
XP_FREE(e);
}
Bool
ET_lo_PrepareLayerForWriting(MWContext *pContext, int32 layer_id,
const char *referer)
{
JSEvent * pEvent = (JSEvent *) XP_NEW_ZAP(JSEvent);
if(!pEvent)
return FALSE;
PR_InitEvent(&pEvent->ce.event, pContext,
(PRHandleEventProc)et_HandleEvent_PrepareLayerForWriting,
(PRDestroyEventProc)et_DestroyEvent_PrepareLayerForWriting);
/* fill in the non-PR fields we care about */
pEvent->ce.context = pContext;
pEvent->layer_id = layer_id;
pEvent->ce.doc_id = XP_DOCID(pContext);
pEvent->data = referer ? XP_STRDUP(referer) : NULL;
return (Bool)et_PostEvent(&pEvent->ce, TRUE);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
ETEvalAckFunc fn;
void * data;
char * str;
size_t len;
char * wysiwyg_url;
char * base_href;
Bool valid;
} MozillaEvent_EvalAck;
PR_STATIC_CALLBACK(void)
et_HandleEvent_EvalAck(MozillaEvent_EvalAck* e)
{
if (e->ce.doc_id == XP_DOCID(e->ce.context)) {
(e->fn) (e->data, e->str, e->len, e->wysiwyg_url,
e->base_href, e->valid);
}
else {
#ifdef DEBUG_chouck
XP_TRACE(("et_HandleEvent_EvalAck failed doc_id"));
#endif
}
}
void
ET_PostEvalAck(MWContext * context, int doc_id,
void * data, char * str, size_t len,
char * wysiwyg_url, char * base_href,
Bool valid, ETEvalAckFunc fn)
{
MozillaEvent_EvalAck* event;
if (fn == NULL)
return;
event = XP_NEW_ZAP(MozillaEvent_EvalAck);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, NULL,
(PRHandleEventProc)et_HandleEvent_EvalAck,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->ce.context = context;
event->ce.doc_id = doc_id;
event->data = data;
event->str = str;
event->len = len;
event->valid = valid;
event->fn = fn;
event->wysiwyg_url = wysiwyg_url;
event->base_href = base_href;
(void) et_PostEvent(&event->ce, FALSE);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
ETRestoreAckFunc fn;
void * data;
LO_BlockInitializeStruct *param;
} MozillaEvent_RestoreAck;
PR_STATIC_CALLBACK(void)
et_HandleEvent_RestoreAck(MozillaEvent_RestoreAck* e)
{
/* XXX Need to do a doc_id check to see if this is still valid */
(e->fn) (e->data, e->param);
}
void
ET_PostRestoreAck(void * data, LO_BlockInitializeStruct *param,
ETRestoreAckFunc fn)
{
MozillaEvent_RestoreAck* event;
if (fn == NULL)
return;
event = XP_NEW_ZAP(MozillaEvent_RestoreAck);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, NULL,
(PRHandleEventProc)et_HandleEvent_RestoreAck,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->data = data;
event->param = param;
event->fn = fn;
(void) et_PostEvent(&event->ce, FALSE);
}
/****************************************************************************/
typedef struct MozillaEvent_DiscardStruct {
ETEvent ce;
JSBool processed;
} MozillaEvent_DiscardStruct;
PR_STATIC_CALLBACK(void)
et_HandleEvent_DiscardDocument(MozillaEvent_DiscardStruct * e)
{
e->processed = JS_TRUE;
LO_DiscardDocument(e->ce.context);
ET_DocWriteAck(e->ce.context, 0);
}
PR_STATIC_CALLBACK(void)
et_DestroyEvent_DiscardDocument(MozillaEvent_DiscardStruct * e)
{
if (!e->processed)
ET_DocWriteAck(e->ce.context, 0);
}
void
ET_lo_DiscardDocument(MWContext * pContext)
{
MozillaEvent_DiscardStruct * event;
QueueStackElement * qse;
event = PR_NEW(MozillaEvent_DiscardStruct);
if (event == NULL)
return;
qse = et_PushEventQueue(pContext);
if (!qse) {
PR_DELETE(event);
return;
}
/* MLM - this used to be et_TopQueue, but we know that et_TopQueue
* and qse are equivalent at this point. */
qse->doc_id = XP_DOCID(pContext);
PR_InitEvent(&event->ce.event, pContext,
(PRHandleEventProc)et_HandleEvent_DiscardDocument,
(PRDestroyEventProc)et_DestroyEvent_DiscardDocument);
event->ce.context = pContext;
qse->discarding = TRUE;
et_PostEvent(&event->ce, FALSE);
/*
* Spin here until we get a ReleaseDocument (if needed) followed by a
* WriteAck send by our handler.
*/
et_SubEventLoop(qse);
qse->discarding = FALSE;
et_PopEventQueue(pContext);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
ETVoidPtrFunc fn;
void * data;
} MozillaEvent_CallFunc;
PR_STATIC_CALLBACK(void)
et_HandleEvent_CallFunction(MozillaEvent_CallFunc* e)
{
(e->fn) (e->data);
}
void
ET_moz_CallFunction(ETVoidPtrFunc fn, void * data)
{
MozillaEvent_CallFunc* event = PR_NEW(MozillaEvent_CallFunc);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, NULL,
(PRHandleEventProc)et_HandleEvent_CallFunction,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->fn = fn;
event->data = data;
et_PostEvent(&event->ce, TRUE);
}
void
ET_moz_CallFunctionAsync(ETVoidPtrFunc fn, void * data)
{
MozillaEvent_CallFunc* event = PR_NEW(MozillaEvent_CallFunc);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, NULL,
(PRHandleEventProc)et_HandleEvent_CallFunction,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->fn = fn;
event->data = data;
(void) et_PostEvent(&event->ce, FALSE);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
ETBoolPtrFunc fn;
void * data;
} MozillaEvent_CallFuncBool;
PR_STATIC_CALLBACK(PRBool)
et_HandleEvent_CallFunctionBool(MozillaEvent_CallFuncBool* e)
{
return (e->fn) (e->data);
}
PRBool
ET_moz_CallFunctionBool(ETBoolPtrFunc fn, void * data)
{
PRBool ret;
MozillaEvent_CallFuncBool* event = PR_NEW(MozillaEvent_CallFuncBool);
if (event == NULL)
return PR_FALSE;
PR_InitEvent(&event->ce.event, NULL,
(PRHandleEventProc)et_HandleEvent_CallFunctionBool,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->fn = fn;
event->data = data;
ret = (PRBool) et_PostEvent(&event->ce, TRUE);
return ret;
}
/****************************************************************************/
typedef struct {
ETEvent ce;
ETIntPtrFunc fn;
void * data;
} MozillaEvent_CallFuncInt;
PR_STATIC_CALLBACK(int32)
et_HandleEvent_CallFunctionInt(MozillaEvent_CallFuncInt* e)
{
return (e->fn) (e->data);
}
int32
ET_moz_CallFunctionInt(ETIntPtrFunc fn, void * data)
{
PRBool ret;
MozillaEvent_CallFuncInt* event = PR_NEW(MozillaEvent_CallFuncInt);
if (event == NULL)
return PR_FALSE;
PR_InitEvent(&event->ce.event, NULL,
(PRHandleEventProc)et_HandleEvent_CallFunctionInt,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->fn = fn;
event->data = data;
ret = (int32) et_PostEvent(&event->ce, TRUE);
return ret;
}
/****************************************************************************/
typedef struct {
ETEvent ce;
ETStringPtrFunc fn;
void * data;
} MozillaEvent_CallFuncString;
PR_STATIC_CALLBACK(char *)
et_HandleEvent_CallFunctionString(MozillaEvent_CallFuncString* e)
{
return (e->fn) (e->data);
}
char *
ET_moz_CallFunctionString(ETStringPtrFunc fn, void * data)
{
char * ret;
MozillaEvent_CallFuncString* event = PR_NEW(MozillaEvent_CallFuncString);
if (event == NULL)
return NULL;
PR_InitEvent(&event->ce.event, NULL,
(PRHandleEventProc)et_HandleEvent_CallFunctionString,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->fn = fn;
event->data = data;
ret = (char *) et_PostEvent(&event->ce, TRUE);
return ret;
}
/****************************************************************************/
void
ET_moz_CallAsyncAndSubEventLoop(ETVoidPtrFunc fn, void *data,
MWContext *context)
{
QueueStackElement *qse;
qse = et_PushEventQueue(context);
if ( qse == NULL ) {
return;
}
qse->inherit_parent = JS_TRUE;
qse->doc_id = 0;
ET_moz_CallFunctionAsync(fn, data);
et_SubEventLoop(qse);
(void)et_PopEventQueue(context);
return;
}
/****************************************************************************/
typedef struct {
ETEvent ce;
MKStreamAbortFunc fn;
void * data;
int status;
} MozillaEvent_CallAbort;
PR_STATIC_CALLBACK(void)
et_HandleEvent_Abort(MozillaEvent_CallAbort* e)
{
(*e->fn)(e->data, e->status);
}
void
ET_moz_Abort(MKStreamAbortFunc fn, void * data, int status)
{
MozillaEvent_CallAbort* event = PR_NEW(MozillaEvent_CallAbort);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, NULL,
(PRHandleEventProc)et_HandleEvent_Abort,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->fn = fn;
event->data = data;
event->status = status;
(void) et_PostEvent(&event->ce, TRUE);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
IL_GroupContext * img_cx;
LO_ImageStruct * img;
char * str;
NET_ReloadMethod how;
} MozillaEvent_GetImage;
PR_STATIC_CALLBACK(void)
et_HandleEvent_GetImage(MozillaEvent_GetImage* e)
{
IL_DisplayData dpy_data;
MWContext *pContext = e->ce.context;
IL_GroupContext *img_cx = e->img_cx;
LO_ImageStruct *lo_image = e->img;
const char *url = e->str;
if (e->ce.doc_id != XP_DOCID(pContext))
return;
XP_ASSERT(pContext->color_space);
if (!pContext->color_space)
return;
dpy_data.color_space = pContext->color_space;
dpy_data.dither_mode = IL_Auto;
IL_SetDisplayMode(img_cx, IL_COLOR_SPACE | IL_DITHER_MODE, &dpy_data);
LO_SetImageURL(pContext, img_cx, lo_image, url, e->how);
lo_image->pending_mocha_event = PR_FALSE;
}
PR_STATIC_CALLBACK(void)
et_DestroyEvent_GetImage(MozillaEvent_GetImage* e)
{
if (e->str)
XP_FREE(e->str);
XP_FREE(e);
}
void
ET_il_GetImage(const char * str, MWContext * pContext, IL_GroupContext *img_cx,
LO_ImageStruct * image_data, NET_ReloadMethod how)
{
MozillaEvent_GetImage* event = PR_NEW(MozillaEvent_GetImage);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, pContext,
(PRHandleEventProc)et_HandleEvent_GetImage,
(PRDestroyEventProc)et_DestroyEvent_GetImage);
event->ce.context = pContext;
event->ce.doc_id = XP_DOCID(pContext);
event->str = str ? strdup(str) : NULL;
event->img_cx = img_cx;
event->img = image_data;
event->how = how;
(void) et_PostEvent(&event->ce, FALSE);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
IL_GroupContext *pImgCX;
void *pDpyCX;
JSBool bAddObserver;
} MozillaEvent_GroupObserver;
PR_STATIC_CALLBACK(void)
et_HandleEvent_SetGroupObserver(MozillaEvent_GroupObserver* e)
{
MWContext *pContext = e->ce.context;
IL_DisplayData dpy_data;
if (e->bAddObserver)
IL_AddGroupObserver(e->pImgCX, FE_MochaImageGroupObserver, pContext);
else
IL_RemoveGroupObserver(e->pImgCX, FE_MochaImageGroupObserver, pContext);
dpy_data.display_context = e->pDpyCX;
IL_SetDisplayMode(e->pImgCX, IL_DISPLAY_CONTEXT, &dpy_data);
}
void
ET_il_SetGroupObserver(MWContext * pContext, IL_GroupContext *pImgCX, void *pDpyCX,
JSBool bAddObserver)
{
MozillaEvent_GroupObserver* event = PR_NEW(MozillaEvent_GroupObserver);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, pContext,
(PRHandleEventProc)et_HandleEvent_SetGroupObserver,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->ce.context = pContext;
event->pImgCX = pImgCX;
event->pDpyCX = pDpyCX;
event->bAddObserver = bAddObserver;
(void) et_PostEvent(&event->ce, TRUE);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
LO_Element * ele;
} MozillaEvent_Form;
PR_STATIC_CALLBACK(void)
et_HandleEvent_ResetForm(MozillaEvent_Form* e)
{
LO_ResetForm(e->ce.context, (LO_FormElementStruct *) e->ele);
}
void
ET_lo_ResetForm(MWContext * pContext, LO_Element * ele)
{
MozillaEvent_Form* event = XP_NEW_ZAP(MozillaEvent_Form);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, pContext,
(PRHandleEventProc)et_HandleEvent_ResetForm,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->ce.context = pContext;
event->ele = ele;
(void) et_PostEvent(&event->ce, TRUE);
}
/****************************************************************************/
PR_STATIC_CALLBACK(void)
et_HandleEvent_SubmitForm(MozillaEvent_Form* e)
{
/* XXX - I think this code should be here, but chouck must
have final say - fur
if (e->ce.doc_id != XP_DOCID(e->ce.context))
return;
*/
FE_SubmitInputElement(e->ce.context, e->ele);
}
void
ET_fe_SubmitInputElement(MWContext * pContext, LO_Element * ele)
{
MozillaEvent_Form* event = XP_NEW_ZAP(MozillaEvent_Form);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, pContext,
(PRHandleEventProc)et_HandleEvent_SubmitForm,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->ce.context = pContext;
event->ce.doc_id = XP_DOCID(pContext);
event->ele = ele;
(void) et_PostEvent(&event->ce, FALSE);
}
/****************************************************************************/
PR_STATIC_CALLBACK(void*)
et_HandleEvent_GetSecurityStatus(ETEvent * e)
{
return (void *) XP_GetSecurityStatus(e->context);
}
int
ET_GetSecurityStatus(MWContext * pContext)
{
int ret = 0;
ETEvent * event = XP_NEW_ZAP(ETEvent);
if (event == NULL)
return -1; /* SSL_SECURITY_STATUS_NOOPT */
PR_InitEvent(&event->event, pContext,
(PRHandleEventProc)et_HandleEvent_GetSecurityStatus,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->context = pContext;
ret = (int) et_PostEvent(event, TRUE);
return ret;
}
/****************************************************************************/
typedef struct {
ETEvent ce;
URL_Struct * pUrl;
const char * wysiwyg_url;
const char * base_href;
int32 layer_id;
} MozillaEvent_DocCacheConverter;
PR_STATIC_CALLBACK(void)
et_HandleEvent_SetWriteStream(MozillaEvent_DocCacheConverter * e)
{
lo_TopState *top_state;
top_state = lo_GetMochaTopState(e->ce.context);
if (top_state && !top_state->mocha_write_stream) {
top_state->mocha_write_stream
= NET_CloneWysiwygCacheFile(e->ce.context,
e->pUrl,
(uint32)top_state->script_bytes,
e->wysiwyg_url,
e->base_href);
}
}
PR_STATIC_CALLBACK(void)
et_DestroyEvent_SetWriteStream(MozillaEvent_DocCacheConverter * e)
{
NET_DropURLStruct(e->pUrl);
if (e->wysiwyg_url)
XP_FREE((char *) e->wysiwyg_url);
if (e->base_href)
XP_FREE((char *) e->base_href);
XP_FREE(e);
}
void
ET_moz_SetMochaWriteStream(MochaDecoder * decoder)
{
MozillaEvent_DocCacheConverter * event;
JSPrincipals *principals;
event = XP_NEW_ZAP(MozillaEvent_DocCacheConverter);
if (!event)
return;
PR_InitEvent(&event->ce.event, decoder->window_context,
(PRHandleEventProc)et_HandleEvent_SetWriteStream,
(PRDestroyEventProc)et_DestroyEvent_SetWriteStream);
event->ce.context = decoder->window_context;
event->pUrl = NET_HoldURLStruct(decoder->url_struct);
principals = lm_GetPrincipalsFromStackFrame(decoder->js_context);
event->wysiwyg_url = lm_MakeWysiwygUrl(decoder->js_context, decoder,
LO_DOCUMENT_LAYER_ID, principals);
event->base_href = LM_GetBaseHrefTag(decoder->js_context, principals);
et_PostEvent(&event->ce, TRUE);
}
/****************************************************************************/
PRIVATE NET_StreamClass *
lm_DocCacheConverterNoHistory(MWContext * context, URL_Struct * url,
const char * wysiwyg_url)
{
lo_TopState *top_state;
char *address;
NET_StreamClass *cache_stream;
top_state = lo_GetMochaTopState(context);
if (!top_state)
return NULL;
/* Save a wysiwyg copy in the URL struct for resize-reloads. */
url->wysiwyg_url = XP_STRDUP(wysiwyg_url);
if (!url->wysiwyg_url)
return NULL;
/* Then pass it via url_struct to create a cache converter stream. */
address = url->address;
url->address = url->wysiwyg_url;
cache_stream = NET_CacheConverter(FO_CACHE_ONLY,
(void *)1, /* XXX don't hold url */
url,
context);
url->address = address;
top_state->mocha_write_stream = cache_stream;
return cache_stream;
}
NET_StreamClass *
lm_DocCacheConverter(MWContext * context, URL_Struct * url,
const char * wysiwyg_url)
{
History_entry *he;
NET_StreamClass *cache_stream;
cache_stream = lm_DocCacheConverterNoHistory(context, url, wysiwyg_url);
/*
* Make a copy of wysiwyg_url in our history entry no matter what went
* wrong building cache_stream. This way, NET_GetURL can see the wysiwyg:
* prefix, notice when it misses the cache, and clear URL_s->resize_reload
* to make the reload from the original/generating URL destructive.
*/
he = SHIST_GetCurrent(&context->hist);
if (he) {
PR_FREEIF(he->wysiwyg_url);
he->wysiwyg_url = XP_STRDUP(wysiwyg_url);
}
return cache_stream;
}
PR_STATIC_CALLBACK(NET_StreamClass *)
et_HandleEvent_DocCacheConverter(MozillaEvent_DocCacheConverter * e)
{
NET_StreamClass * stream;
if (e->layer_id != LO_DOCUMENT_LAYER_ID) {
return lm_DocCacheConverterNoHistory(e->ce.context,
e->pUrl,
e->wysiwyg_url);
}
stream = lm_DocCacheConverter(e->ce.context,
e->pUrl,
e->wysiwyg_url);
return stream;
}
PR_STATIC_CALLBACK(void)
et_DestroyEvent_DocCacheConverter(MozillaEvent_DocCacheConverter * e)
{
NET_DropURLStruct(e->pUrl);
XP_FREE(e);
}
NET_StreamClass *
ET_moz_DocCacheConverter(MWContext * pContext, URL_Struct * pUrl,
char * wysiwyg_url, int32 layer_id)
{
NET_StreamClass * ret = NULL;
MozillaEvent_DocCacheConverter * event;
event = XP_NEW_ZAP(MozillaEvent_DocCacheConverter);
if (!event)
return ret;
PR_InitEvent(&event->ce.event, pContext,
(PRHandleEventProc)et_HandleEvent_DocCacheConverter,
(PRDestroyEventProc)et_DestroyEvent_DocCacheConverter);
event->ce.context = pContext;
event->pUrl = NET_HoldURLStruct(pUrl);
event->wysiwyg_url = wysiwyg_url;
event->layer_id = layer_id;
ret = et_PostEvent(&event->ce, TRUE);
return ret;
}
/****************************************************************************/
PR_STATIC_CALLBACK(void*)
et_HandleEvent_InitMoja(ETEvent* e)
{
return (void *) LM_InitMoja();
}
int
ET_InitMoja(MWContext* context)
{
int returnCode;
ETEvent * event;
/* XXX assert that we're on the mocha-thread */
/* fast check before sending an event and waiting for it */
returnCode = LM_IsMojaInitialized();
if (returnCode != LM_MOJA_UNINITIALIZED)
return returnCode;
event = PR_NEW(ETEvent);
if (event == NULL)
return LM_MOJA_OUT_OF_MEMORY;
PR_InitEvent(&event->event, context,
(PRHandleEventProc)et_HandleEvent_InitMoja,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->context = context;
returnCode = (int) et_PostEvent(event, TRUE);
return returnCode;
}
/****************************************************************************/
typedef struct {
ETEvent ce;
CL_Layer * layer;
int32 x, y;
void * param_ptr;
int32 param_val;
ETLayerOp op;
int32 doc_id;
char * referer;
} MozillaEvent_TweakLayer;
PR_STATIC_CALLBACK(int)
et_HandleEvent_TweakLayer(MozillaEvent_TweakLayer* e)
{
CL_Layer *layer;
Bool ret = TRUE;
/* check that the doc_id is valid */
if(XP_DOCID(e->ce.context) != e->ce.doc_id)
return FALSE;
switch(e->op) {
case CL_SetSrcWidth:
ret = LO_SetLayerSrc(e->ce.context, e->param_val, (char*)e->param_ptr,
e->referer, e->x);
break;
case CL_SetSrc:
layer = LO_GetLayerFromId(e->ce.context, e->param_val);
ret = LO_SetLayerSrc(e->ce.context, e->param_val, (char*)e->param_ptr,
e->referer, LO_GetLayerWrapWidth(layer));
break;
case CL_SetBgColor:
LO_SetLayerBgColor(e->layer, (LO_Color*)e->param_ptr);
if (e->param_ptr)
XP_FREE((void*)e->param_ptr);
break;
default:
XP_ASSERT(0);
}
return (int)ret;
}
PR_STATIC_CALLBACK(void)
et_DestroyEvent_TweakLayer(MozillaEvent_TweakLayer * event)
{
XP_FREEIF(event->referer);
XP_FREE(event);
}
/*
* These need to be synchronous so that if we set this and then
* immediately look at it we get the correct (new) value
*/
int
ET_TweakLayer(MWContext * context, CL_Layer* layer, int32 x, int32 y,
void *param_ptr, int32 param_val, ETLayerOp op,
const char *referer, int32 doc_id)
{
MozillaEvent_TweakLayer * event;
event = PR_NEW(MozillaEvent_TweakLayer);
if (event == NULL)
return 0;
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_TweakLayer,
(PRDestroyEventProc)et_DestroyEvent_TweakLayer);
event->ce.context = context;
event->ce.doc_id = doc_id;
event->layer = layer;
event->x = x;
event->y = y;
event->param_ptr = param_ptr;
event->param_val = param_val;
event->op = op;
event->referer = referer ? XP_STRDUP(referer) : NULL;
return (int)et_PostEvent(&event->ce, TRUE);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
XP_Bool refreshInstances;
} MozillaEvent_RefreshPlugins;
PR_STATIC_CALLBACK(void*)
et_HandleEvent_RefreshPlugins(MozillaEvent_RefreshPlugins* e)
{
return ((void*) NPL_RefreshPluginList(e->refreshInstances));
}
int32
ET_npl_RefreshPluginList(MWContext* context, XP_Bool refreshInstances)
{
int32 ret = -1;
MozillaEvent_RefreshPlugins* event = XP_NEW_ZAP(MozillaEvent_RefreshPlugins);
if (event == NULL)
return ret;
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_RefreshPlugins,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->ce.context = context;
event->refreshInstances = refreshInstances;
ret = (int32) et_PostEvent(&event->ce, TRUE);
return ret;
}
/****************************************************************************/
typedef struct {
ETEvent ce;
JSContext * cx;
uint argc;
jsval * argv;
jsval * rval;
char * string;
} MozillaEvent_HandlePref;
#define PREF_CHARSET (INTL_DefaultWinCharSetID(0))
PR_STATIC_CALLBACK(JSBool)
et_HandleEvent_HandlePref(MozillaEvent_HandlePref* e)
{
JSString * str;
char * cstr;
JSContext * mochaContext=NULL;
JSObject * mochaPrefObject=NULL;
str = JS_ValueToString(e->cx, e->argv[0]);
if (!str)
return JS_TRUE;
cstr = JS_GetStringBytes(str);
PREF_GetConfigContext(&mochaContext);
if (mochaContext == NULL) {
return JS_FALSE;
}
PREF_GetGlobalConfigObject(&mochaPrefObject);
if (mochaPrefObject == NULL) {
return JS_FALSE;
}
switch(e->argc) {
case 1:
{
int iType = PREF_GetPrefType((const char *)cstr);
int32 iRet;
XP_Bool bRet;
char * pRet;
switch (iType) {
/* these cases should be defines but...*/
case 8:
/* pref is a string*/
PREF_CopyCharPref((const char *)cstr,&pRet);
*e->rval = STRING_TO_JSVAL(pRet);
e->string = pRet;
break;
case 16:
/* pref is a int*/
PREF_GetIntPref((const char *)cstr,&iRet);
*e->rval = INT_TO_JSVAL(iRet);
break;
case 32:
/* pref is a bool*/
PREF_GetBoolPref((const char *)cstr,&bRet);
*e->rval = BOOLEAN_TO_JSVAL(bRet);
break;
}
}
break;
case 2:
{
if (JSVAL_IS_STRING(e->argv[1])) {
JSString * valueJSStr = JS_ValueToString(e->cx, e->argv[1]);
if (valueJSStr) {
char * valueStr = lm_StrToEncoding(e->cx, PREF_CHARSET, valueJSStr);
if (valueStr) {
PREF_SetCharPref(cstr, valueStr);
XP_FREE(valueStr);
}
}
}
else if (JSVAL_IS_INT(e->argv[1])) {
jsint intVal = JSVAL_TO_INT(e->argv[1]);
PREF_SetIntPref(cstr, (int32)intVal);
}
else if (JSVAL_IS_BOOLEAN(e->argv[1])) {
JSBool boolVal = JSVAL_TO_BOOLEAN(e->argv[1]);
PREF_SetBoolPref(cstr, (XP_Bool) boolVal);
}
else if (JSVAL_IS_NULL(e->argv[1])) {
PREF_DeleteBranch(cstr);
}
}
break;
}
return JS_TRUE;
}
JSBool
ET_HandlePref(JSContext * cx, uint argc, jsval * argv, jsval * rval)
{
JSBool ret;
MozillaEvent_HandlePref* event = XP_NEW_ZAP(MozillaEvent_HandlePref);
if (event == NULL)
return JS_TRUE;
PR_InitEvent(&event->ce.event, NULL,
(PRHandleEventProc)et_HandleEvent_HandlePref,
(PRDestroyEventProc)et_DestroyEvent_WaitForIt);
event->ce.context = NULL;
event->cx = cx;
event->argc = argc;
event->argv = argv;
event->rval = rval;
ret = (JSBool) et_PostEvent(&event->ce, TRUE);
/* if it was a string we need to convert the string to a JSString */
/* do we need to free event->string or does JS own it now ? */
if (ret == JS_TRUE && JSVAL_IS_STRING(*event->rval))
*rval = STRING_TO_JSVAL(lm_EncodingToStr(cx, PREF_CHARSET, event->string));
XP_FREE(event);
return ret;
}
/****************************************************************************/
typedef struct {
ETEvent ce;
ETVerifyComponentFunc fn;
ETBoolPtrFunc *pActive_callback;
ETVoidPtrFunc *pStartup_callback;
} MozillaEvent_VerifyComponentFunc;
PR_STATIC_CALLBACK(PRBool)
et_HandleEvent_VerifyComponentFunction(MozillaEvent_VerifyComponentFunc* e)
{
return (PRBool)(e->fn) ((void**)(e->pActive_callback),
(void**)(e->pStartup_callback));
}
PRBool
ET_moz_VerifyComponentFunction(ETVerifyComponentFunc fn, ETBoolPtrFunc *pActive_callback,
ETVoidPtrFunc *pStartup_callback)
{
PRBool ret;
MozillaEvent_VerifyComponentFunc* event = PR_NEW(MozillaEvent_VerifyComponentFunc);
if (event == NULL)
return PR_FALSE;
PR_InitEvent(&event->ce.event, NULL,
(PRHandleEventProc)et_HandleEvent_VerifyComponentFunction,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->fn = fn;
/* Pointers must be malloc'd inside libmocha before this call */
event->pActive_callback = pActive_callback;
event->pStartup_callback = pStartup_callback;
ret = (PRBool) et_PostEvent(&event->ce, TRUE);
return ret;
}
/****************************************************************************/
typedef struct {
ETEvent ce;
ETCompPropGetterFunc fn;
char *name;
} MozillaEvent_GetterFunc;
PR_STATIC_CALLBACK(void *)
et_HandleEvent_CompGetter(MozillaEvent_GetterFunc* e)
{
return (void *)(e->fn)(e->name);
}
PR_STATIC_CALLBACK(void)
et_DestroyEvent_CompGetter(MozillaEvent_GetterFunc * event)
{
if (event->name)
XP_FREE(event->name);
XP_FREE(event);
}
void *
ET_moz_CompGetterFunction(ETCompPropGetterFunc fn, char *name)
{
MozillaEvent_GetterFunc* event = PR_NEW(MozillaEvent_GetterFunc);
if (event == NULL)
return NULL;
PR_InitEvent(&event->ce.event, NULL,
(PRHandleEventProc)et_HandleEvent_CompGetter,
(PRDestroyEventProc)et_DestroyEvent_CompGetter);
event->fn = fn;
event->name = XP_STRDUP(name);
return (void *)et_PostEvent(&event->ce, TRUE);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
ETCompPropSetterFunc fn;
char *name;
void *data;
} MozillaEvent_SetterFunc;
PR_STATIC_CALLBACK(void)
et_HandleEvent_CompSetter(MozillaEvent_SetterFunc* e)
{
(e->fn)(e->name, e->data);
}
PR_STATIC_CALLBACK(void)
et_DestroyEvent_CompSetter(MozillaEvent_SetterFunc * event)
{
if (event->name)
XP_FREE(event->name);
XP_FREE(event);
}
void
ET_moz_CompSetterFunction(ETCompPropSetterFunc fn, char *name, void *data)
{
MozillaEvent_SetterFunc* event = PR_NEW(MozillaEvent_SetterFunc);
if (!event || !name)
return;
PR_InitEvent(&event->ce.event, NULL,
(PRHandleEventProc)et_HandleEvent_CompSetter,
(PRDestroyEventProc)et_DestroyEvent_CompSetter);
event->fn = fn;
event->name = XP_STRDUP(name);
event->data = data;
(void) et_PostEvent(&event->ce, FALSE);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
ETCompMethodFunc fn;
int32 argc;
JSCompArg *argv;
} MozillaEvent_MethodFunc;
PR_STATIC_CALLBACK(void *)
et_HandleEvent_CompMethod(MozillaEvent_MethodFunc* e)
{
return (void *)(e->fn)(e->argc, e->argv);
}
PR_STATIC_CALLBACK(void)
et_DestroyEvent_CompMethod(MozillaEvent_MethodFunc * event)
{
if (event->argv)
XP_FREE(event->argv);
XP_FREE(event);
}
void *
ET_moz_CompMethodFunction(ETCompMethodFunc fn, int32 argc, JSCompArg *argv)
{
MozillaEvent_MethodFunc* event = PR_NEW(MozillaEvent_MethodFunc);
if (!event || !argv)
return NULL;
PR_InitEvent(&event->ce.event, NULL,
(PRHandleEventProc)et_HandleEvent_CompMethod,
(PRDestroyEventProc)et_DestroyEvent_CompMethod);
event->fn = fn;
event->argc = argc;
event->argv = XP_ALLOC(argc * sizeof(JSCompArg));
if (event->argv)
XP_MEMCPY(event->argv, argv, (argc * sizeof(JSCompArg)));
return (void *)et_PostEvent(&event->ce, TRUE);
}
/****************************************************************************/
typedef struct {
ETEvent ce;
MWContext *context;
const char *script_name;
JSCFCookieData *data;
Bool *data_changed;
} MozillaEvent_JSCFExecute;
PR_STATIC_CALLBACK(void *)
et_HandleEvent_JSCFExecute(MozillaEvent_JSCFExecute* e)
{
void *ans;
JSCFResult res;
res = JSCF_Execute(e->context, e->script_name, e->data, e->data_changed);
return (void *) (&res);
}
JSCFResult
ET_JSCFExecute(MWContext *context, const char *script_name,
JSCFCookieData *data, Bool *data_changed)
{
JSCFResult *res;
MozillaEvent_JSCFExecute* event = PR_NEW(MozillaEvent_JSCFExecute);
if(!event)
return (JSCFResult) 0;
PR_InitEvent(&event->ce.event, NULL,
(PRHandleEventProc)et_HandleEvent_JSCFExecute,
(PRDestroyEventProc)et_DestroyEvent_GenericEvent);
event->context = context;
event->script_name = script_name;
event->data = data;
event->data_changed = data_changed;
res = et_PostEvent(&event->ce, TRUE);
return *res;
}
/****************************************************************************/
typedef struct {
ETEvent ce;
char* prin;
char* target;
char* risk;
PRBool isCert;
} MozillaEvent_signedAppletPrivileges;
PR_STATIC_CALLBACK(void)
et_HandleEvent_signedAppletPrivileges(MozillaEvent_signedAppletPrivileges* e)
{
SECNAV_signedAppletPrivilegesOnMozillaThread
(e->ce.context, e->prin, e->target, e->risk, e->isCert);
}
PR_STATIC_CALLBACK(void)
et_DestroyEvent_signedAppletPrivileges(MozillaEvent_signedAppletPrivileges* e)
{
XP_FREE((char*)e->prin);
XP_FREE((char*)e->target);
XP_FREE((char*)e->risk);
XP_FREE(e);
}
void
ET_PostSignedAppletPrivileges
(MWContext* context, char* prin, char* target, char* risk, PRBool isCert)
{
MozillaEvent_signedAppletPrivileges* event =
PR_NEW(MozillaEvent_signedAppletPrivileges);
if (event == NULL)
return;
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_signedAppletPrivileges,
(PRDestroyEventProc)et_DestroyEvent_signedAppletPrivileges);
event->ce.context = context;
event->prin = strdup(prin);
event->target = strdup(target);
event->risk = strdup(risk);
event->isCert = isCert;
et_PostEvent(&event->ce, FALSE);
}
#if DOM
/* Signal reflow from DOM alteration */
typedef struct {
ETEvent ce;
LO_Element *element;
PRBool reflow;
} MozillaEvent_DOMReflow;
PR_STATIC_CALLBACK(int)
et_HandleEvent_DOMReflow(MozillaEvent_DOMReflow* e)
{
/* check that the doc_id is valid */
if(XP_DOCID(e->ce.context) != e->ce.doc_id)
return FALSE;
/*
* XXX we should check e->reflow and only `redraw' if the element just
* changed colour or something.
*/
LO_RelayoutFromElement(e->ce.context, e->element);
return TRUE;
}
PR_STATIC_CALLBACK(void)
et_DestroyEvent_DOMReflow(MozillaEvent_DOMReflow * event)
{
XP_FREE(event);
}
int
ET_DOMReflow(MWContext *context, LO_Element *element, PRBool reflow,
int32 doc_id)
{
MozillaEvent_DOMReflow *event;
event = PR_NEW(MozillaEvent_DOMReflow);
if (!event)
return 0;
PR_InitEvent(&event->ce.event, context,
(PRHandleEventProc)et_HandleEvent_DOMReflow,
(PRDestroyEventProc)et_DestroyEvent_DOMReflow);
event->ce.context = context;
event->ce.doc_id = doc_id;
event->reflow = reflow;
event->element = element;
return (int)et_PostEvent(&event->ce, FALSE);
}
#endif