Fixing regression caused by bug 156452. Make sure the correct JS context is pushed onto the JS context stack before handling focus and blur code internally. This is needed since lots of focus and blur code rely on DOM range code that now does security checking when called to prevent from unauthorized use of a DOM range object. r=sicking@bigfoot.com, sr=bzbarsky@mit.edu, a=chofmann@netscape.com

This commit is contained in:
jst%netscape.com 2002-07-24 06:13:18 +00:00
Родитель 5c2cff1e6d
Коммит f4b5812f5e
3 изменённых файлов: 121 добавлений и 54 удалений

Просмотреть файл

@ -1124,6 +1124,87 @@ nsEventListenerManager::CompileEventHandlerInternal(nsIScriptContext *aContext,
return result;
}
void
nsCxPusher::Push(nsISupports *aCurrentTarget)
{
if (mCx || mPreviousCx) {
NS_ERROR("Whaaa! No double pushing with nsCxPusher::Push()!");
return;
}
nsCOMPtr<nsIScriptGlobalObject> sgo;
nsCOMPtr<nsIContent> content(do_QueryInterface(aCurrentTarget));
nsCOMPtr<nsIDocument> document;
if (content) {
content->GetDocument(*getter_AddRefs(document));
}
if (!document) {
document = do_QueryInterface(aCurrentTarget);
}
if (document) {
document->GetScriptGlobalObject(getter_AddRefs(sgo));
}
if (!document && !sgo) {
sgo = do_QueryInterface(aCurrentTarget);
}
nsCOMPtr<nsIScriptContext> scx;
if (sgo) {
sgo->GetContext(getter_AddRefs(scx));
if (scx) {
mCx = (JSContext *)scx->GetNativeContext();
}
}
nsCOMPtr<nsIJSContextStack> stack;
if (mCx) {
if (!mStack) {
mStack = do_GetService("@mozilla.org/js/xpc/ContextStack;1");
}
if (mStack) {
mStack->Peek(&mPreviousCx);
mStack->Push(mCx);
}
}
}
void
nsCxPusher::Pop()
{
if (!mCx || !mStack) {
mCx = nsnull;
mPreviousCx = nsnull;
return;
}
JSContext *unused;
mStack->Pop(&unused);
if (!mPreviousCx) {
// No JS is running, but executing the event handler might have
// caused some JS to run. Tell the script context that it's done.
nsIScriptContext *scx = NS_STATIC_CAST(nsIScriptContext *,
::JS_GetContextPrivate(mCx));
scx->ScriptEvaluated(PR_TRUE);
}
mCx = nsnull;
mPreviousCx = nsnull;
}
nsresult
nsEventListenerManager::HandleEventSubType(nsListenerStruct* aListenerStruct,
nsIDOMEvent* aDOMEvent,
@ -1171,49 +1252,9 @@ nsEventListenerManager::HandleEventSubType(nsListenerStruct* aListenerStruct,
}
}
nsCOMPtr<nsIScriptGlobalObject> sgo;
nsCOMPtr<nsIContent> content(do_QueryInterface(aCurrentTarget));
nsCOMPtr<nsIDocument> document;
if (content) {
content->GetDocument(*getter_AddRefs(document));
}
if (!document) {
document = do_QueryInterface(aCurrentTarget);
}
if (document) {
document->GetScriptGlobalObject(getter_AddRefs(sgo));
}
if (!sgo) {
sgo = do_QueryInterface(aCurrentTarget);
}
nsCOMPtr<nsIScriptContext> scx;
JSContext *cx = nsnull;
if (sgo) {
sgo->GetContext(getter_AddRefs(scx));
if (scx) {
cx = (JSContext *)scx->GetNativeContext();
}
}
nsCOMPtr<nsIJSContextStack> stack;
JSContext *current_cx = nsnull;
if (cx) {
stack = do_GetService("@mozilla.org/js/xpc/ContextStack;1");
if (stack) {
stack->Peek(&current_cx);
stack->Push(cx);
}
}
// nsCxPusher will automatically push and pop the current cx onto the
// context stack
nsCxPusher pusher(aCurrentTarget);
if (NS_SUCCEEDED(result)) {
nsCOMPtr<nsIPrivateDOMEvent> aPrivDOMEvent(do_QueryInterface(aDOMEvent));
@ -1222,17 +1263,6 @@ nsEventListenerManager::HandleEventSubType(nsListenerStruct* aListenerStruct,
aPrivDOMEvent->SetCurrentTarget(nsnull);
}
if (cx && stack) {
stack->Pop(&cx);
if (!current_cx) {
// No JS is running, but executing the event handler might have
// caused some JS to run. Tell the script context that it's done.
scx->ScriptEvaluated(PR_TRUE);
}
}
return result;
}

Просмотреть файл

@ -45,6 +45,7 @@
#include "nsIPrincipal.h"
#include "nsIDOMEventReceiver.h"
#include "nsHashtable.h"
#include "nsIJSContextStack.h"
class nsIDOMEvent;
class nsIAtom;
@ -321,4 +322,28 @@ protected:
#define NS_EVENT_BITS_CONTEXT_NONE 0x00
#define NS_EVENT_BITS_CONTEXT_MENU 0x01
class nsCxPusher
{
public:
nsCxPusher(nsISupports *aCurrentTarget)
: mCx(nsnull), mPreviousCx(nsnull)
{
Push(aCurrentTarget);
}
~nsCxPusher()
{
Pop();
}
void Push(nsISupports *aCurrentTarget);
void Pop();
private:
nsCOMPtr<nsIJSContextStack> mStack;
JSContext *mCx;
JSContext *mPreviousCx;
};
#endif // nsEventListenerManager_h__

Просмотреть файл

@ -38,6 +38,7 @@
#include "nsCOMPtr.h"
#include "nsEventStateManager.h"
#include "nsEventListenerManager.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsIFrame.h"
@ -3929,7 +3930,11 @@ nsEventStateManager::SendFocusBlur(nsIPresContext* aPresContext, nsIContent *aCo
nsCOMPtr<nsIContent> temp = gLastFocusedContent;
NS_RELEASE(gLastFocusedContent);
gLastFocusedContent = nsnull;
nsCxPusher pusher(temp);
temp->HandleDOMEvent(oldPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
pusher.Pop();
esm->SetFocusedContent(nsnull);
}
}
@ -3979,7 +3984,12 @@ nsEventStateManager::SendFocusBlur(nsIPresContext* aPresContext, nsIContent *aCo
nsCOMPtr<nsIDocument> temp = gLastFocusedDocument;
NS_RELEASE(gLastFocusedDocument);
gLastFocusedDocument = nsnull;
nsCxPusher pusher(temp);
temp->HandleDOMEvent(gLastFocusedPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
pusher.Pop();
pusher.Push(globalObject);
globalObject->HandleDOMEvent(gLastFocusedPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
}
}
@ -4026,6 +4036,7 @@ nsEventStateManager::SendFocusBlur(nsIPresContext* aPresContext, nsIContent *aCo
event.message = NS_FOCUS_CONTENT;
if (nsnull != mPresContext) {
nsCxPusher pusher(aContent);
aContent->HandleDOMEvent(mPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
}
@ -4047,6 +4058,7 @@ nsEventStateManager::SendFocusBlur(nsIPresContext* aPresContext, nsIContent *aCo
event.eventStructType = NS_EVENT;
event.message = NS_FOCUS_CONTENT;
if (nsnull != mPresContext && mDocument) {
nsCxPusher pusher(mDocument);
mDocument->HandleDOMEvent(mPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
}
}