зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
5c2cff1e6d
Коммит
f4b5812f5e
|
@ -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(¤t_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);
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче