зеркало из https://github.com/mozilla/gecko-dev.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:
Родитель
de37872cdd
Коммит
7cd3446784
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче