From cb410c0ff919a8dd9fce3b403fe75106bf8c522a Mon Sep 17 00:00:00 2001 From: "hyatt%netscape.com" Date: Fri, 15 Sep 2000 23:28:29 +0000 Subject: [PATCH] Fix for bug #45989, theft of clipboard using XBL. r=ben --- content/xbl/src/nsXBLBinding.cpp | 112 +++-------- content/xbl/src/nsXBLBinding.h | 14 +- content/xbl/src/nsXBLEventHandler.cpp | 263 +++++++++++++++++--------- content/xbl/src/nsXBLEventHandler.h | 42 +++- layout/xbl/src/nsXBLBinding.cpp | 112 +++-------- layout/xbl/src/nsXBLBinding.h | 14 +- layout/xbl/src/nsXBLEventHandler.cpp | 263 +++++++++++++++++--------- layout/xbl/src/nsXBLEventHandler.h | 42 +++- 8 files changed, 486 insertions(+), 376 deletions(-) diff --git a/content/xbl/src/nsXBLBinding.cpp b/content/xbl/src/nsXBLBinding.cpp index c79c418cbf8a..525c4bbfb769 100644 --- a/content/xbl/src/nsXBLBinding.cpp +++ b/content/xbl/src/nsXBLBinding.cpp @@ -669,32 +669,15 @@ nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement, nsIXBLBinding** aB receiver = do_QueryInterface(otherElement); } - // Add an event listener for mouse and key events only. - PRBool mouse, key, focus, xul, scroll, form; - mouse = key = focus = xul = scroll = form = PR_FALSE; + PRBool supported = PR_FALSE; + if (!special) + supported = PR_TRUE; + else supported = IsSupportedHandler(&iid); - if (!special) { - key = IsKeyHandler(type); - if (!key) { - mouse = IsMouseHandler(type); - if (!mouse) { - focus = IsFocusHandler(type); - if (!focus) { - xul = IsXULHandler(type); - if (!xul) { - scroll = IsScrollHandler(type); - if (!scroll) - form = IsFormHandler(type); - } - } - } - } - } - - if (mouse || key || focus || xul || scroll || form || special) { + if (supported) { // Create a new nsXBLEventHandler. nsXBLEventHandler* handler; - NS_NewXBLEventHandler(receiver, curr, type, &handler); + NS_NewXBLEventHandler(receiver, curr, eventAtom, &handler); // We chain all our event handlers together for easy // removal later (if/when the binding dies). @@ -713,33 +696,33 @@ nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement, nsIXBLBinding** aB useCapture = PR_TRUE; // Add the event listener. - if (mouse) + if (iid.Equals(NS_GET_IID(nsIDOMMouseListener))) receiver->AddEventListener(type, (nsIDOMMouseListener*)handler, useCapture); - else if(key) + else if(iid.Equals(NS_GET_IID(nsIDOMKeyListener))) receiver->AddEventListener(type, (nsIDOMKeyListener*)handler, useCapture); - else if(focus) + else if(iid.Equals(NS_GET_IID(nsIDOMFocusListener))) receiver->AddEventListener(type, (nsIDOMFocusListener*)handler, useCapture); - else if (xul) + else if (iid.Equals(NS_GET_IID(nsIDOMMenuListener))) receiver->AddEventListener(type, (nsIDOMMenuListener*)handler, useCapture); - else if (scroll) + else if (iid.Equals(NS_GET_IID(nsIDOMScrollListener))) receiver->AddEventListener(type, (nsIDOMScrollListener*)handler, useCapture); - else if (form) + else if (iid.Equals(NS_GET_IID(nsIDOMFormListener))) receiver->AddEventListener(type, (nsIDOMFormListener*)handler, useCapture); - + if (!special) // Let the listener manager hold on to the handler. NS_RELEASE(handler); } - else { - // Call AddScriptEventListener for other IID types - // XXX Want this to all go away! - NS_WARNING("***** Non-compliant XBL event listener attached! *****"); - nsAutoString value; - child->GetAttribute(kNameSpaceID_None, kActionAtom, value); - if (value.IsEmpty()) - GetTextData(child, value); + } + else { + // Call AddScriptEventListener for other IID types + // XXX Want this to all go away! + NS_WARNING("***** Non-compliant XBL event listener attached! *****"); + nsAutoString value; + child->GetAttribute(kNameSpaceID_None, kActionAtom, value); + if (value.IsEmpty()) + GetTextData(child, value); - AddScriptEventListener(mBoundElement, eventAtom, value, iid); - } + AddScriptEventListener(mBoundElement, eventAtom, value, iid); } } @@ -1675,49 +1658,16 @@ nsXBLBinding::GetEventHandlerIID(nsIAtom* aName, nsIID* aIID, PRBool* aFound) } PRBool -nsXBLBinding::IsMouseHandler(const nsString& aName) +nsXBLBinding::IsSupportedHandler(const nsIID* aIID) { - return ((aName == NS_LITERAL_STRING("click")) || (aName == NS_LITERAL_STRING("dblclick")) || (aName == NS_LITERAL_STRING("mousedown")) || - (aName == NS_LITERAL_STRING("mouseover")) || (aName == NS_LITERAL_STRING("mouseout")) || (aName == NS_LITERAL_STRING("mouseup"))); + return (aIID->Equals(NS_GET_IID(nsIDOMMouseListener)) || + aIID->Equals(NS_GET_IID(nsIDOMKeyListener)) || + aIID->Equals(NS_GET_IID(nsIDOMFocusListener)) || + aIID->Equals(NS_GET_IID(nsIDOMMenuListener)) || + aIID->Equals(NS_GET_IID(nsIDOMScrollListener)) || + aIID->Equals(NS_GET_IID(nsIDOMFormListener))); } - -PRBool -nsXBLBinding::IsKeyHandler(const nsString& aName) -{ - return ((aName == NS_LITERAL_STRING("keypress")) || (aName == NS_LITERAL_STRING("keydown")) || (aName == NS_LITERAL_STRING("keyup"))); -} - -PRBool -nsXBLBinding::IsFocusHandler(const nsString& aName) -{ - return ((aName == NS_LITERAL_STRING("focus")) || (aName == NS_LITERAL_STRING("blur"))); -} - -PRBool -nsXBLBinding::IsXULHandler(const nsString& aName) -{ - return ((aName == NS_LITERAL_STRING("create")) || (aName == NS_LITERAL_STRING("destroy")) || (aName == NS_LITERAL_STRING("broadcast")) || - (aName == NS_LITERAL_STRING("command")) || (aName == NS_LITERAL_STRING("commandupdate")) || (aName == NS_LITERAL_STRING("close"))); -} - -PRBool -nsXBLBinding::IsScrollHandler(const nsString& aName) -{ - return (aName == NS_LITERAL_STRING("overflow") || - aName == NS_LITERAL_STRING("underflow") || - aName == NS_LITERAL_STRING("overflowchanged")); -} - -PRBool -nsXBLBinding::IsFormHandler(const nsString& aName) -{ - return (aName == NS_LITERAL_STRING("submit") || - aName == NS_LITERAL_STRING("reset") || - aName == NS_LITERAL_STRING("change") || - aName == NS_LITERAL_STRING("input") || - aName == NS_LITERAL_STRING("select")); -} - + NS_IMETHODIMP nsXBLBinding::AddScriptEventListener(nsIContent* aElement, nsIAtom* aName, const nsString& aValue, REFNSIID aIID) { diff --git a/content/xbl/src/nsXBLBinding.h b/content/xbl/src/nsXBLBinding.h index 8593942d1fdd..b015da46283b 100644 --- a/content/xbl/src/nsXBLBinding.h +++ b/content/xbl/src/nsXBLBinding.h @@ -146,15 +146,12 @@ public: static EventHandlerMapEntry kEventHandlerMap[]; - static PRBool IsMouseHandler(const nsString& aName); - static PRBool IsKeyHandler(const nsString& aName); - static PRBool IsFocusHandler(const nsString& aName); - static PRBool IsXULHandler(const nsString& aName); - static PRBool IsScrollHandler(const nsString& aName); - static PRBool IsFormHandler(const nsString& aName); - + static PRBool IsSupportedHandler(const nsIID* aIID); + static nsFixedSizeAllocator kPool; + static void GetEventHandlerIID(nsIAtom* aName, nsIID* aIID, PRBool* aFound); + // Internal member functions protected: NS_IMETHOD InitClass(const nsCString& aClassName, @@ -170,8 +167,7 @@ protected: NS_IMETHOD ConstructAttributeTable(nsIContent* aElement); - static void GetEventHandlerIID(nsIAtom* aName, nsIID* aIID, PRBool* aFound); - + // MEMBER VARIABLES protected: nsCString mDocURI; diff --git a/content/xbl/src/nsXBLEventHandler.cpp b/content/xbl/src/nsXBLEventHandler.cpp index 79f99c59f69c..d6f8c10b0444 100644 --- a/content/xbl/src/nsXBLEventHandler.cpp +++ b/content/xbl/src/nsXBLEventHandler.cpp @@ -49,6 +49,8 @@ #include "nsIDOMWindowInternal.h" #include "nsIPref.h" #include "nsIServiceManager.h" +#include "nsIURI.h" +#include "nsXPIDLString.h" static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); @@ -64,13 +66,38 @@ nsIAtom* nsXBLEventHandler::kBindingAttachedAtom = nsnull; nsIAtom* nsXBLEventHandler::kBindingDetachedAtom = nsnull; nsIAtom* nsXBLEventHandler::kModifiersAtom = nsnull; +nsIAtom* nsXBLEventHandler::kKeyDownAtom = nsnull; +nsIAtom* nsXBLEventHandler::kKeyUpAtom = nsnull; +nsIAtom* nsXBLEventHandler::kKeyPressAtom = nsnull; +nsIAtom* nsXBLEventHandler::kMouseDownAtom = nsnull; +nsIAtom* nsXBLEventHandler::kMouseUpAtom = nsnull; +nsIAtom* nsXBLEventHandler::kMouseClickAtom = nsnull; +nsIAtom* nsXBLEventHandler::kMouseDblClickAtom = nsnull; +nsIAtom* nsXBLEventHandler::kMouseOverAtom = nsnull; +nsIAtom* nsXBLEventHandler::kMouseOutAtom = nsnull; +nsIAtom* nsXBLEventHandler::kFocusAtom = nsnull; +nsIAtom* nsXBLEventHandler::kBlurAtom = nsnull; +nsIAtom* nsXBLEventHandler::kCreateAtom = nsnull; +nsIAtom* nsXBLEventHandler::kCloseAtom = nsnull; +nsIAtom* nsXBLEventHandler::kCommandUpdateAtom = nsnull; +nsIAtom* nsXBLEventHandler::kBroadcastAtom = nsnull; +nsIAtom* nsXBLEventHandler::kDestroyAtom = nsnull; +nsIAtom* nsXBLEventHandler::kOverflowAtom = nsnull; +nsIAtom* nsXBLEventHandler::kUnderflowAtom = nsnull; +nsIAtom* nsXBLEventHandler::kOverflowChangedAtom = nsnull; +nsIAtom* nsXBLEventHandler::kSubmitAtom = nsnull; +nsIAtom* nsXBLEventHandler::kResetAtom = nsnull; +nsIAtom* nsXBLEventHandler::kInputAtom = nsnull; +nsIAtom* nsXBLEventHandler::kSelectAtom = nsnull; +nsIAtom* nsXBLEventHandler::kChangeAtom = nsnull; + nsXBLEventHandler::nsXBLEventHandler(nsIDOMEventReceiver* aEventReceiver, nsIXBLPrototypeHandler* aHandler, - const nsString& aEventName) + nsIAtom* aEventName) { NS_INIT_REFCNT(); mEventReceiver = aEventReceiver; mProtoHandler = aHandler; - mEventName.Assign(aEventName); + mEventName = aEventName; mNextHandler = nsnull; gRefCnt++; if (gRefCnt == 1) { @@ -84,6 +111,32 @@ nsXBLEventHandler::nsXBLEventHandler(nsIDOMEventReceiver* aEventReceiver, nsIXBL kButtonAtom = NS_NewAtom("button"); kBindingAttachedAtom = NS_NewAtom("bindingattached"); kBindingDetachedAtom = NS_NewAtom("bindingdetached"); + + kKeyUpAtom = NS_NewAtom("keyup"); + kKeyDownAtom = NS_NewAtom("keydown"); + kKeyPressAtom = NS_NewAtom("keypress"); + kMouseDownAtom = NS_NewAtom("mousedown"); + kMouseUpAtom = NS_NewAtom("mouseup"); + kMouseClickAtom = NS_NewAtom("click"); + kMouseDblClickAtom = NS_NewAtom("dblclick"); + kMouseOverAtom = NS_NewAtom("mouseover"); + kMouseOutAtom = NS_NewAtom("mouseout"); + + kFocusAtom = NS_NewAtom("focus"); + kBlurAtom = NS_NewAtom("blur"); + kCreateAtom = NS_NewAtom("create"); + kCloseAtom = NS_NewAtom("close"); + kDestroyAtom = NS_NewAtom("destroy"); + kCommandUpdateAtom = NS_NewAtom("commandupdate"); + kBroadcastAtom = NS_NewAtom("broadcast"); + kOverflowAtom = NS_NewAtom("overflow"); + kUnderflowAtom = NS_NewAtom("underflow"); + kOverflowChangedAtom = NS_NewAtom("overflowchanged"); + kInputAtom = NS_NewAtom("input"); + kSelectAtom = NS_NewAtom("select"); + kChangeAtom = NS_NewAtom("change"); + kSubmitAtom = NS_NewAtom("submit"); + kResetAtom = NS_NewAtom("reset"); } } @@ -101,6 +154,32 @@ nsXBLEventHandler::~nsXBLEventHandler() NS_RELEASE(kClickCountAtom); NS_RELEASE(kBindingAttachedAtom); NS_RELEASE(kBindingDetachedAtom); + + NS_RELEASE(kKeyUpAtom); + NS_RELEASE(kKeyDownAtom); + NS_RELEASE(kKeyPressAtom); + NS_RELEASE(kMouseUpAtom); + NS_RELEASE(kMouseDownAtom); + NS_RELEASE(kMouseClickAtom); + NS_RELEASE(kMouseDblClickAtom); + NS_RELEASE(kMouseOverAtom); + NS_RELEASE(kMouseOutAtom); + + NS_RELEASE(kFocusAtom); + NS_RELEASE(kBlurAtom); + NS_RELEASE(kCloseAtom); + NS_RELEASE(kCommandUpdateAtom); + NS_RELEASE(kBroadcastAtom); + NS_RELEASE(kCreateAtom); + NS_RELEASE(kDestroyAtom); + NS_RELEASE(kOverflowAtom); + NS_RELEASE(kUnderflowAtom); + NS_RELEASE(kOverflowChangedAtom); + NS_RELEASE(kInputAtom); + NS_RELEASE(kSubmitAtom); + NS_RELEASE(kResetAtom); + NS_RELEASE(kSelectAtom); + NS_RELEASE(kChangeAtom); } } @@ -111,7 +190,7 @@ NS_IMETHODIMP nsXBLEventHandler::BindingAttached() { nsresult ret; - if (mEventName == NS_LITERAL_STRING("bindingattached")) { + if (mEventName.get() == kBindingAttachedAtom) { nsMouseEvent event; event.eventStructType = NS_EVENT; event.message = NS_MENU_ACTION; @@ -156,7 +235,7 @@ NS_IMETHODIMP nsXBLEventHandler::BindingDetached() { nsresult ret; - if (mEventName == NS_LITERAL_STRING("bindingdetached")) { + if (mEventName.get() == kBindingDetachedAtom) { nsMouseEvent event; event.eventStructType = NS_EVENT; event.message = NS_MENU_ACTION; @@ -205,7 +284,7 @@ nsresult nsXBLEventHandler::HandleEvent(nsIDOMEvent* aEvent) nsresult nsXBLEventHandler::KeyUp(nsIDOMEvent* aKeyEvent) { - if (mEventName != NS_LITERAL_STRING("keyup")) + if (mEventName.get() != kKeyUpAtom) return NS_OK; PRBool matched = PR_FALSE; @@ -215,13 +294,13 @@ nsresult nsXBLEventHandler::KeyUp(nsIDOMEvent* aKeyEvent) } if (matched) - ExecuteHandler(NS_LITERAL_STRING("keyup"), aKeyEvent); + ExecuteHandler(mEventName, aKeyEvent); return NS_OK; } nsresult nsXBLEventHandler::KeyDown(nsIDOMEvent* aKeyEvent) { - if (mEventName != NS_LITERAL_STRING("keydown")) + if (mEventName.get() != kKeyDownAtom) return NS_OK; PRBool matched = PR_FALSE; @@ -231,13 +310,13 @@ nsresult nsXBLEventHandler::KeyDown(nsIDOMEvent* aKeyEvent) } if (matched) - ExecuteHandler(NS_LITERAL_STRING("keydown"), aKeyEvent); + ExecuteHandler(mEventName, aKeyEvent); return NS_OK; } nsresult nsXBLEventHandler::KeyPress(nsIDOMEvent* aKeyEvent) { - if (mEventName != NS_LITERAL_STRING("keypress")) + if (mEventName.get() != kKeyPressAtom) return NS_OK; PRBool matched = PR_FALSE; @@ -247,13 +326,13 @@ nsresult nsXBLEventHandler::KeyPress(nsIDOMEvent* aKeyEvent) } if (matched) - ExecuteHandler(NS_LITERAL_STRING("keypress"), aKeyEvent); + ExecuteHandler(mEventName, aKeyEvent); return NS_OK; } nsresult nsXBLEventHandler::MouseDown(nsIDOMEvent* aMouseEvent) { - if (mEventName != NS_LITERAL_STRING("mousedown")) + if (mEventName.get() != kMouseDownAtom) return NS_OK; PRBool matched = PR_FALSE; @@ -263,13 +342,13 @@ nsresult nsXBLEventHandler::MouseDown(nsIDOMEvent* aMouseEvent) } if (matched) - ExecuteHandler(NS_LITERAL_STRING("mousedown"), aMouseEvent); + ExecuteHandler(mEventName, aMouseEvent); return NS_OK; } nsresult nsXBLEventHandler::MouseUp(nsIDOMEvent* aMouseEvent) { - if (mEventName != NS_LITERAL_STRING("mouseup")) + if (mEventName.get() != kMouseUpAtom) return NS_OK; PRBool matched = PR_FALSE; @@ -279,13 +358,13 @@ nsresult nsXBLEventHandler::MouseUp(nsIDOMEvent* aMouseEvent) } if (matched) - ExecuteHandler(NS_LITERAL_STRING("mouseup"), aMouseEvent); + ExecuteHandler(mEventName, aMouseEvent); return NS_OK; } nsresult nsXBLEventHandler::MouseClick(nsIDOMEvent* aMouseEvent) { - if (mEventName != NS_LITERAL_STRING("click")) + if (mEventName.get() != kMouseClickAtom) return NS_OK; PRBool matched = PR_FALSE; @@ -295,13 +374,13 @@ nsresult nsXBLEventHandler::MouseClick(nsIDOMEvent* aMouseEvent) } if (matched) - ExecuteHandler(NS_LITERAL_STRING("click"), aMouseEvent); + ExecuteHandler(mEventName, aMouseEvent); return NS_OK; } nsresult nsXBLEventHandler::MouseDblClick(nsIDOMEvent* aMouseEvent) { - if (mEventName != NS_LITERAL_STRING("dblclick")) + if (mEventName.get() != kMouseDblClickAtom) return NS_OK; PRBool matched = PR_FALSE; @@ -311,13 +390,13 @@ nsresult nsXBLEventHandler::MouseDblClick(nsIDOMEvent* aMouseEvent) } if (matched) - ExecuteHandler(NS_LITERAL_STRING("dblclick"), aMouseEvent); + ExecuteHandler(mEventName, aMouseEvent); return NS_OK; } nsresult nsXBLEventHandler::MouseOver(nsIDOMEvent* aMouseEvent) { - if (mEventName != NS_LITERAL_STRING("mouseover")) + if (mEventName.get() != kMouseOverAtom) return NS_OK; PRBool matched = PR_FALSE; @@ -327,13 +406,13 @@ nsresult nsXBLEventHandler::MouseOver(nsIDOMEvent* aMouseEvent) } if (matched) - ExecuteHandler(NS_LITERAL_STRING("mouseover"), aMouseEvent); + ExecuteHandler(mEventName, aMouseEvent); return NS_OK; } nsresult nsXBLEventHandler::MouseOut(nsIDOMEvent* aMouseEvent) { - if (mEventName != NS_LITERAL_STRING("mouseout")) + if (mEventName.get() != kMouseOutAtom) return NS_OK; PRBool matched = PR_FALSE; @@ -343,159 +422,159 @@ nsresult nsXBLEventHandler::MouseOut(nsIDOMEvent* aMouseEvent) } if (matched) - ExecuteHandler(NS_LITERAL_STRING("mouseout"), aMouseEvent); + ExecuteHandler(mEventName, aMouseEvent); return NS_OK; } nsresult nsXBLEventHandler::Focus(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("focus")) + if (mEventName.get() != kFocusAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("focus"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Blur(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("blur")) + if (mEventName.get() != kBlurAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("blur"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Action(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("command")) + if (mEventName.get() != kCommandAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("command"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Create(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("create")) + if (mEventName.get() != kCreateAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("create"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Close(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("close")) + if (mEventName.get() != kCloseAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("close"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Broadcast(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("broadcast")) + if (mEventName.get() != kBroadcastAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("broadcast"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::CommandUpdate(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("commandupdate")) + if (mEventName.get() != kCommandUpdateAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("commandupdate"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Overflow(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("overflow")) + if (mEventName.get() != kOverflowAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("overflow"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Underflow(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("underflow")) + if (mEventName.get() != kUnderflowAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("underflow"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::OverflowChanged(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("underflowchanged")) + if (mEventName.get() != kOverflowChangedAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("underflowchanged"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Destroy(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("destroy")) + if (mEventName.get() != kDestroyAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("destroy"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Submit(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("submit")) + if (mEventName.get() != kSubmitAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("submit"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Reset(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("reset")) + if (mEventName.get() != kResetAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("reset"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Select(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("select")) + if (mEventName.get() != kSelectAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("select"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Change(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("change")) + if (mEventName.get() != kChangeAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("change"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Input(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("input")) + if (mEventName.get() != kInputAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("input"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } NS_IMETHODIMP -nsXBLEventHandler::ExecuteHandler(const nsAReadableString & aEventName, nsIDOMEvent* aEvent) +nsXBLEventHandler::ExecuteHandler(nsIAtom* aEventName, nsIDOMEvent* aEvent) { if (!mProtoHandler) return NS_ERROR_FAILURE; @@ -510,6 +589,20 @@ nsXBLEventHandler::ExecuteHandler(const nsAReadableString & aEventName, nsIDOMEv nsAutoString command; handlerElement->GetAttribute(kNameSpaceID_None, kCommandAtom, command); if (!command.IsEmpty()) { + // Make sure the XBL doc is chrome. + // Fix for bug #45989 + if (!mProtoHandler) + return NS_OK; + nsCOMPtr handler; + mProtoHandler->GetHandlerElement(getter_AddRefs(handler)); + nsCOMPtr document; + handler->GetDocument(*getter_AddRefs(document)); + nsCOMPtr url = getter_AddRefs(document->GetDocumentURL()); + nsXPIDLCString scheme; + url->GetScheme(getter_Copies(scheme)); + if (PL_strcmp(scheme, "chrome") != 0) + return NS_OK; + // We are the default action for this command. // Stop any other default action from executing. aEvent->PreventDefault(); @@ -538,7 +631,9 @@ nsXBLEventHandler::ExecuteHandler(const nsAReadableString & aEventName, nsIDOMEv // Look for a compiled handler on the element. // Should be compiled and bound with "on" in front of the name. nsAutoString onEvent; onEvent.AssignWithConversion("onxbl"); - onEvent += aEventName; + nsAutoString str; + mEventName->ToString(str); + onEvent += str; nsCOMPtr onEventAtom = getter_AddRefs(NS_NewAtom(onEvent)); void* handler = nsnull; @@ -645,8 +740,8 @@ nsXBLEventHandler::RemoveEventHandlers() if (!mProtoHandler) return; - if (mEventName == NS_LITERAL_STRING("bindingattached") || - mEventName == NS_LITERAL_STRING("bindingdetached")) { + if (mEventName.get() == kBindingAttachedAtom || + mEventName.get() == kBindingDetachedAtom) { // Release and drop. mProtoHandler = nsnull; NS_RELEASE_THIS(); @@ -668,41 +763,23 @@ nsXBLEventHandler::RemoveEventHandlers() nsAutoString type; handlerElement->GetAttribute(kNameSpaceID_None, nsXBLBinding::kEventAtom, type); - // Figure out our type. - PRBool key = nsXBLBinding::IsKeyHandler(type); - if (key) { - mEventReceiver->RemoveEventListener(type, (nsIDOMKeyListener*)this, useCapture); - return; - } + PRBool found = PR_FALSE; + nsIID iid; + nsXBLBinding::GetEventHandlerIID(mEventName, &iid, &found); - PRBool mouse = nsXBLBinding::IsMouseHandler(type); - if (mouse) { - mEventReceiver->RemoveEventListener(type, (nsIDOMMouseListener*)this, useCapture); - return; - } - - PRBool focus = nsXBLBinding::IsFocusHandler(type); - if (focus) { - mEventReceiver->RemoveEventListener(type, (nsIDOMFocusListener*)this, useCapture); - return; - } - - PRBool xul = nsXBLBinding::IsXULHandler(type); - if (xul) { - mEventReceiver->RemoveEventListener(type, (nsIDOMMenuListener*)this, useCapture); - return; - } - - PRBool scroll = nsXBLBinding::IsScrollHandler(type); - if (scroll) { - mEventReceiver->RemoveEventListener(type, (nsIDOMScrollListener*)this, useCapture); - return; - } - - PRBool form = nsXBLBinding::IsFormHandler(type); - if (form) { - mEventReceiver->RemoveEventListener(type, (nsIDOMFormListener*)this, useCapture); - return; + if (found) { + if (iid.Equals(NS_GET_IID(nsIDOMMouseListener))) + mEventReceiver->AddEventListener(type, (nsIDOMMouseListener*)this, useCapture); + else if(iid.Equals(NS_GET_IID(nsIDOMKeyListener))) + mEventReceiver->AddEventListener(type, (nsIDOMKeyListener*)this, useCapture); + else if(iid.Equals(NS_GET_IID(nsIDOMFocusListener))) + mEventReceiver->AddEventListener(type, (nsIDOMFocusListener*)this, useCapture); + else if (iid.Equals(NS_GET_IID(nsIDOMMenuListener))) + mEventReceiver->AddEventListener(type, (nsIDOMMenuListener*)this, useCapture); + else if (iid.Equals(NS_GET_IID(nsIDOMScrollListener))) + mEventReceiver->AddEventListener(type, (nsIDOMScrollListener*)this, useCapture); + else if (iid.Equals(NS_GET_IID(nsIDOMFormListener))) + mEventReceiver->AddEventListener(type, (nsIDOMFormListener*)this, useCapture); } } @@ -734,7 +811,7 @@ nsXBLEventHandler::GetTextData(nsIContent *aParent, nsString& aResult) nsresult NS_NewXBLEventHandler(nsIDOMEventReceiver* aRec, nsIXBLPrototypeHandler* aHandler, - const nsString& aEventName, + nsIAtom* aEventName, nsXBLEventHandler** aResult) { *aResult = new nsXBLEventHandler(aRec, aHandler, aEventName); diff --git a/content/xbl/src/nsXBLEventHandler.h b/content/xbl/src/nsXBLEventHandler.h index e211728bd79a..11f293b2b36d 100644 --- a/content/xbl/src/nsXBLEventHandler.h +++ b/content/xbl/src/nsXBLEventHandler.h @@ -43,6 +43,8 @@ class nsIAtom; class nsIController; class nsIXBLPrototypeHandler; +// XXX This should be broken up into subclasses for each listener IID type, so we +// can cut down on the bloat of the handlers. class nsXBLEventHandler : public nsIDOMKeyListener, public nsIDOMMouseListener, public nsIDOMMenuListener, @@ -51,7 +53,7 @@ class nsXBLEventHandler : public nsIDOMKeyListener, public nsIDOMFormListener { public: - nsXBLEventHandler(nsIDOMEventReceiver* aReceiver, nsIXBLPrototypeHandler* aHandler, const nsString& aEventName); + nsXBLEventHandler(nsIDOMEventReceiver* aReceiver, nsIXBLPrototypeHandler* aHandler, nsIAtom* aEventName); virtual ~nsXBLEventHandler(); NS_IMETHOD BindingAttached(); @@ -109,7 +111,7 @@ public: protected: NS_IMETHOD GetController(nsIController** aResult); - NS_IMETHOD ExecuteHandler(const nsAReadableString & aEventName, nsIDOMEvent* aEvent); + NS_IMETHOD ExecuteHandler(nsIAtom* aEventName, nsIDOMEvent* aEvent); static PRUint32 gRefCnt; static nsIAtom* kKeyAtom; @@ -123,20 +125,50 @@ protected: static nsIAtom* kBindingDetachedAtom; static nsIAtom* kModifiersAtom; + static nsIAtom* kKeyUpAtom; + static nsIAtom* kKeyDownAtom; + static nsIAtom* kKeyPressAtom; + + static nsIAtom* kMouseDownAtom; + static nsIAtom* kMouseUpAtom; + static nsIAtom* kMouseClickAtom; + static nsIAtom* kMouseDblClickAtom; + static nsIAtom* kMouseOverAtom; + static nsIAtom* kMouseOutAtom; + + static nsIAtom* kFocusAtom; + static nsIAtom* kBlurAtom; + + static nsIAtom* kCreateAtom; + static nsIAtom* kCloseAtom; + static nsIAtom* kDestroyAtom; + static nsIAtom* kCommandUpdateAtom; + static nsIAtom* kBroadcastAtom; + + static nsIAtom* kOverflowAtom; + static nsIAtom* kUnderflowAtom; + static nsIAtom* kOverflowChangedAtom; + + static nsIAtom* kSubmitAtom; + static nsIAtom* kResetAtom; + static nsIAtom* kChangeAtom; + static nsIAtom* kSelectAtom; + static nsIAtom* kInputAtom; + static nsresult GetTextData(nsIContent *aParent, nsString& aResult); protected: nsIDOMEventReceiver* mEventReceiver; // Both of these refs are weak. nsCOMPtr mProtoHandler; - nsAutoString mEventName; - + nsCOMPtr mEventName; + nsXBLEventHandler* mNextHandler; // Handlers are chained for easy unloading later. }; extern nsresult NS_NewXBLEventHandler(nsIDOMEventReceiver* aEventReceiver, nsIXBLPrototypeHandler* aHandlerElement, - const nsString& aEventName, + nsIAtom* aEventName, nsXBLEventHandler** aResult); diff --git a/layout/xbl/src/nsXBLBinding.cpp b/layout/xbl/src/nsXBLBinding.cpp index c79c418cbf8a..525c4bbfb769 100644 --- a/layout/xbl/src/nsXBLBinding.cpp +++ b/layout/xbl/src/nsXBLBinding.cpp @@ -669,32 +669,15 @@ nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement, nsIXBLBinding** aB receiver = do_QueryInterface(otherElement); } - // Add an event listener for mouse and key events only. - PRBool mouse, key, focus, xul, scroll, form; - mouse = key = focus = xul = scroll = form = PR_FALSE; + PRBool supported = PR_FALSE; + if (!special) + supported = PR_TRUE; + else supported = IsSupportedHandler(&iid); - if (!special) { - key = IsKeyHandler(type); - if (!key) { - mouse = IsMouseHandler(type); - if (!mouse) { - focus = IsFocusHandler(type); - if (!focus) { - xul = IsXULHandler(type); - if (!xul) { - scroll = IsScrollHandler(type); - if (!scroll) - form = IsFormHandler(type); - } - } - } - } - } - - if (mouse || key || focus || xul || scroll || form || special) { + if (supported) { // Create a new nsXBLEventHandler. nsXBLEventHandler* handler; - NS_NewXBLEventHandler(receiver, curr, type, &handler); + NS_NewXBLEventHandler(receiver, curr, eventAtom, &handler); // We chain all our event handlers together for easy // removal later (if/when the binding dies). @@ -713,33 +696,33 @@ nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement, nsIXBLBinding** aB useCapture = PR_TRUE; // Add the event listener. - if (mouse) + if (iid.Equals(NS_GET_IID(nsIDOMMouseListener))) receiver->AddEventListener(type, (nsIDOMMouseListener*)handler, useCapture); - else if(key) + else if(iid.Equals(NS_GET_IID(nsIDOMKeyListener))) receiver->AddEventListener(type, (nsIDOMKeyListener*)handler, useCapture); - else if(focus) + else if(iid.Equals(NS_GET_IID(nsIDOMFocusListener))) receiver->AddEventListener(type, (nsIDOMFocusListener*)handler, useCapture); - else if (xul) + else if (iid.Equals(NS_GET_IID(nsIDOMMenuListener))) receiver->AddEventListener(type, (nsIDOMMenuListener*)handler, useCapture); - else if (scroll) + else if (iid.Equals(NS_GET_IID(nsIDOMScrollListener))) receiver->AddEventListener(type, (nsIDOMScrollListener*)handler, useCapture); - else if (form) + else if (iid.Equals(NS_GET_IID(nsIDOMFormListener))) receiver->AddEventListener(type, (nsIDOMFormListener*)handler, useCapture); - + if (!special) // Let the listener manager hold on to the handler. NS_RELEASE(handler); } - else { - // Call AddScriptEventListener for other IID types - // XXX Want this to all go away! - NS_WARNING("***** Non-compliant XBL event listener attached! *****"); - nsAutoString value; - child->GetAttribute(kNameSpaceID_None, kActionAtom, value); - if (value.IsEmpty()) - GetTextData(child, value); + } + else { + // Call AddScriptEventListener for other IID types + // XXX Want this to all go away! + NS_WARNING("***** Non-compliant XBL event listener attached! *****"); + nsAutoString value; + child->GetAttribute(kNameSpaceID_None, kActionAtom, value); + if (value.IsEmpty()) + GetTextData(child, value); - AddScriptEventListener(mBoundElement, eventAtom, value, iid); - } + AddScriptEventListener(mBoundElement, eventAtom, value, iid); } } @@ -1675,49 +1658,16 @@ nsXBLBinding::GetEventHandlerIID(nsIAtom* aName, nsIID* aIID, PRBool* aFound) } PRBool -nsXBLBinding::IsMouseHandler(const nsString& aName) +nsXBLBinding::IsSupportedHandler(const nsIID* aIID) { - return ((aName == NS_LITERAL_STRING("click")) || (aName == NS_LITERAL_STRING("dblclick")) || (aName == NS_LITERAL_STRING("mousedown")) || - (aName == NS_LITERAL_STRING("mouseover")) || (aName == NS_LITERAL_STRING("mouseout")) || (aName == NS_LITERAL_STRING("mouseup"))); + return (aIID->Equals(NS_GET_IID(nsIDOMMouseListener)) || + aIID->Equals(NS_GET_IID(nsIDOMKeyListener)) || + aIID->Equals(NS_GET_IID(nsIDOMFocusListener)) || + aIID->Equals(NS_GET_IID(nsIDOMMenuListener)) || + aIID->Equals(NS_GET_IID(nsIDOMScrollListener)) || + aIID->Equals(NS_GET_IID(nsIDOMFormListener))); } - -PRBool -nsXBLBinding::IsKeyHandler(const nsString& aName) -{ - return ((aName == NS_LITERAL_STRING("keypress")) || (aName == NS_LITERAL_STRING("keydown")) || (aName == NS_LITERAL_STRING("keyup"))); -} - -PRBool -nsXBLBinding::IsFocusHandler(const nsString& aName) -{ - return ((aName == NS_LITERAL_STRING("focus")) || (aName == NS_LITERAL_STRING("blur"))); -} - -PRBool -nsXBLBinding::IsXULHandler(const nsString& aName) -{ - return ((aName == NS_LITERAL_STRING("create")) || (aName == NS_LITERAL_STRING("destroy")) || (aName == NS_LITERAL_STRING("broadcast")) || - (aName == NS_LITERAL_STRING("command")) || (aName == NS_LITERAL_STRING("commandupdate")) || (aName == NS_LITERAL_STRING("close"))); -} - -PRBool -nsXBLBinding::IsScrollHandler(const nsString& aName) -{ - return (aName == NS_LITERAL_STRING("overflow") || - aName == NS_LITERAL_STRING("underflow") || - aName == NS_LITERAL_STRING("overflowchanged")); -} - -PRBool -nsXBLBinding::IsFormHandler(const nsString& aName) -{ - return (aName == NS_LITERAL_STRING("submit") || - aName == NS_LITERAL_STRING("reset") || - aName == NS_LITERAL_STRING("change") || - aName == NS_LITERAL_STRING("input") || - aName == NS_LITERAL_STRING("select")); -} - + NS_IMETHODIMP nsXBLBinding::AddScriptEventListener(nsIContent* aElement, nsIAtom* aName, const nsString& aValue, REFNSIID aIID) { diff --git a/layout/xbl/src/nsXBLBinding.h b/layout/xbl/src/nsXBLBinding.h index 8593942d1fdd..b015da46283b 100644 --- a/layout/xbl/src/nsXBLBinding.h +++ b/layout/xbl/src/nsXBLBinding.h @@ -146,15 +146,12 @@ public: static EventHandlerMapEntry kEventHandlerMap[]; - static PRBool IsMouseHandler(const nsString& aName); - static PRBool IsKeyHandler(const nsString& aName); - static PRBool IsFocusHandler(const nsString& aName); - static PRBool IsXULHandler(const nsString& aName); - static PRBool IsScrollHandler(const nsString& aName); - static PRBool IsFormHandler(const nsString& aName); - + static PRBool IsSupportedHandler(const nsIID* aIID); + static nsFixedSizeAllocator kPool; + static void GetEventHandlerIID(nsIAtom* aName, nsIID* aIID, PRBool* aFound); + // Internal member functions protected: NS_IMETHOD InitClass(const nsCString& aClassName, @@ -170,8 +167,7 @@ protected: NS_IMETHOD ConstructAttributeTable(nsIContent* aElement); - static void GetEventHandlerIID(nsIAtom* aName, nsIID* aIID, PRBool* aFound); - + // MEMBER VARIABLES protected: nsCString mDocURI; diff --git a/layout/xbl/src/nsXBLEventHandler.cpp b/layout/xbl/src/nsXBLEventHandler.cpp index 79f99c59f69c..d6f8c10b0444 100644 --- a/layout/xbl/src/nsXBLEventHandler.cpp +++ b/layout/xbl/src/nsXBLEventHandler.cpp @@ -49,6 +49,8 @@ #include "nsIDOMWindowInternal.h" #include "nsIPref.h" #include "nsIServiceManager.h" +#include "nsIURI.h" +#include "nsXPIDLString.h" static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); @@ -64,13 +66,38 @@ nsIAtom* nsXBLEventHandler::kBindingAttachedAtom = nsnull; nsIAtom* nsXBLEventHandler::kBindingDetachedAtom = nsnull; nsIAtom* nsXBLEventHandler::kModifiersAtom = nsnull; +nsIAtom* nsXBLEventHandler::kKeyDownAtom = nsnull; +nsIAtom* nsXBLEventHandler::kKeyUpAtom = nsnull; +nsIAtom* nsXBLEventHandler::kKeyPressAtom = nsnull; +nsIAtom* nsXBLEventHandler::kMouseDownAtom = nsnull; +nsIAtom* nsXBLEventHandler::kMouseUpAtom = nsnull; +nsIAtom* nsXBLEventHandler::kMouseClickAtom = nsnull; +nsIAtom* nsXBLEventHandler::kMouseDblClickAtom = nsnull; +nsIAtom* nsXBLEventHandler::kMouseOverAtom = nsnull; +nsIAtom* nsXBLEventHandler::kMouseOutAtom = nsnull; +nsIAtom* nsXBLEventHandler::kFocusAtom = nsnull; +nsIAtom* nsXBLEventHandler::kBlurAtom = nsnull; +nsIAtom* nsXBLEventHandler::kCreateAtom = nsnull; +nsIAtom* nsXBLEventHandler::kCloseAtom = nsnull; +nsIAtom* nsXBLEventHandler::kCommandUpdateAtom = nsnull; +nsIAtom* nsXBLEventHandler::kBroadcastAtom = nsnull; +nsIAtom* nsXBLEventHandler::kDestroyAtom = nsnull; +nsIAtom* nsXBLEventHandler::kOverflowAtom = nsnull; +nsIAtom* nsXBLEventHandler::kUnderflowAtom = nsnull; +nsIAtom* nsXBLEventHandler::kOverflowChangedAtom = nsnull; +nsIAtom* nsXBLEventHandler::kSubmitAtom = nsnull; +nsIAtom* nsXBLEventHandler::kResetAtom = nsnull; +nsIAtom* nsXBLEventHandler::kInputAtom = nsnull; +nsIAtom* nsXBLEventHandler::kSelectAtom = nsnull; +nsIAtom* nsXBLEventHandler::kChangeAtom = nsnull; + nsXBLEventHandler::nsXBLEventHandler(nsIDOMEventReceiver* aEventReceiver, nsIXBLPrototypeHandler* aHandler, - const nsString& aEventName) + nsIAtom* aEventName) { NS_INIT_REFCNT(); mEventReceiver = aEventReceiver; mProtoHandler = aHandler; - mEventName.Assign(aEventName); + mEventName = aEventName; mNextHandler = nsnull; gRefCnt++; if (gRefCnt == 1) { @@ -84,6 +111,32 @@ nsXBLEventHandler::nsXBLEventHandler(nsIDOMEventReceiver* aEventReceiver, nsIXBL kButtonAtom = NS_NewAtom("button"); kBindingAttachedAtom = NS_NewAtom("bindingattached"); kBindingDetachedAtom = NS_NewAtom("bindingdetached"); + + kKeyUpAtom = NS_NewAtom("keyup"); + kKeyDownAtom = NS_NewAtom("keydown"); + kKeyPressAtom = NS_NewAtom("keypress"); + kMouseDownAtom = NS_NewAtom("mousedown"); + kMouseUpAtom = NS_NewAtom("mouseup"); + kMouseClickAtom = NS_NewAtom("click"); + kMouseDblClickAtom = NS_NewAtom("dblclick"); + kMouseOverAtom = NS_NewAtom("mouseover"); + kMouseOutAtom = NS_NewAtom("mouseout"); + + kFocusAtom = NS_NewAtom("focus"); + kBlurAtom = NS_NewAtom("blur"); + kCreateAtom = NS_NewAtom("create"); + kCloseAtom = NS_NewAtom("close"); + kDestroyAtom = NS_NewAtom("destroy"); + kCommandUpdateAtom = NS_NewAtom("commandupdate"); + kBroadcastAtom = NS_NewAtom("broadcast"); + kOverflowAtom = NS_NewAtom("overflow"); + kUnderflowAtom = NS_NewAtom("underflow"); + kOverflowChangedAtom = NS_NewAtom("overflowchanged"); + kInputAtom = NS_NewAtom("input"); + kSelectAtom = NS_NewAtom("select"); + kChangeAtom = NS_NewAtom("change"); + kSubmitAtom = NS_NewAtom("submit"); + kResetAtom = NS_NewAtom("reset"); } } @@ -101,6 +154,32 @@ nsXBLEventHandler::~nsXBLEventHandler() NS_RELEASE(kClickCountAtom); NS_RELEASE(kBindingAttachedAtom); NS_RELEASE(kBindingDetachedAtom); + + NS_RELEASE(kKeyUpAtom); + NS_RELEASE(kKeyDownAtom); + NS_RELEASE(kKeyPressAtom); + NS_RELEASE(kMouseUpAtom); + NS_RELEASE(kMouseDownAtom); + NS_RELEASE(kMouseClickAtom); + NS_RELEASE(kMouseDblClickAtom); + NS_RELEASE(kMouseOverAtom); + NS_RELEASE(kMouseOutAtom); + + NS_RELEASE(kFocusAtom); + NS_RELEASE(kBlurAtom); + NS_RELEASE(kCloseAtom); + NS_RELEASE(kCommandUpdateAtom); + NS_RELEASE(kBroadcastAtom); + NS_RELEASE(kCreateAtom); + NS_RELEASE(kDestroyAtom); + NS_RELEASE(kOverflowAtom); + NS_RELEASE(kUnderflowAtom); + NS_RELEASE(kOverflowChangedAtom); + NS_RELEASE(kInputAtom); + NS_RELEASE(kSubmitAtom); + NS_RELEASE(kResetAtom); + NS_RELEASE(kSelectAtom); + NS_RELEASE(kChangeAtom); } } @@ -111,7 +190,7 @@ NS_IMETHODIMP nsXBLEventHandler::BindingAttached() { nsresult ret; - if (mEventName == NS_LITERAL_STRING("bindingattached")) { + if (mEventName.get() == kBindingAttachedAtom) { nsMouseEvent event; event.eventStructType = NS_EVENT; event.message = NS_MENU_ACTION; @@ -156,7 +235,7 @@ NS_IMETHODIMP nsXBLEventHandler::BindingDetached() { nsresult ret; - if (mEventName == NS_LITERAL_STRING("bindingdetached")) { + if (mEventName.get() == kBindingDetachedAtom) { nsMouseEvent event; event.eventStructType = NS_EVENT; event.message = NS_MENU_ACTION; @@ -205,7 +284,7 @@ nsresult nsXBLEventHandler::HandleEvent(nsIDOMEvent* aEvent) nsresult nsXBLEventHandler::KeyUp(nsIDOMEvent* aKeyEvent) { - if (mEventName != NS_LITERAL_STRING("keyup")) + if (mEventName.get() != kKeyUpAtom) return NS_OK; PRBool matched = PR_FALSE; @@ -215,13 +294,13 @@ nsresult nsXBLEventHandler::KeyUp(nsIDOMEvent* aKeyEvent) } if (matched) - ExecuteHandler(NS_LITERAL_STRING("keyup"), aKeyEvent); + ExecuteHandler(mEventName, aKeyEvent); return NS_OK; } nsresult nsXBLEventHandler::KeyDown(nsIDOMEvent* aKeyEvent) { - if (mEventName != NS_LITERAL_STRING("keydown")) + if (mEventName.get() != kKeyDownAtom) return NS_OK; PRBool matched = PR_FALSE; @@ -231,13 +310,13 @@ nsresult nsXBLEventHandler::KeyDown(nsIDOMEvent* aKeyEvent) } if (matched) - ExecuteHandler(NS_LITERAL_STRING("keydown"), aKeyEvent); + ExecuteHandler(mEventName, aKeyEvent); return NS_OK; } nsresult nsXBLEventHandler::KeyPress(nsIDOMEvent* aKeyEvent) { - if (mEventName != NS_LITERAL_STRING("keypress")) + if (mEventName.get() != kKeyPressAtom) return NS_OK; PRBool matched = PR_FALSE; @@ -247,13 +326,13 @@ nsresult nsXBLEventHandler::KeyPress(nsIDOMEvent* aKeyEvent) } if (matched) - ExecuteHandler(NS_LITERAL_STRING("keypress"), aKeyEvent); + ExecuteHandler(mEventName, aKeyEvent); return NS_OK; } nsresult nsXBLEventHandler::MouseDown(nsIDOMEvent* aMouseEvent) { - if (mEventName != NS_LITERAL_STRING("mousedown")) + if (mEventName.get() != kMouseDownAtom) return NS_OK; PRBool matched = PR_FALSE; @@ -263,13 +342,13 @@ nsresult nsXBLEventHandler::MouseDown(nsIDOMEvent* aMouseEvent) } if (matched) - ExecuteHandler(NS_LITERAL_STRING("mousedown"), aMouseEvent); + ExecuteHandler(mEventName, aMouseEvent); return NS_OK; } nsresult nsXBLEventHandler::MouseUp(nsIDOMEvent* aMouseEvent) { - if (mEventName != NS_LITERAL_STRING("mouseup")) + if (mEventName.get() != kMouseUpAtom) return NS_OK; PRBool matched = PR_FALSE; @@ -279,13 +358,13 @@ nsresult nsXBLEventHandler::MouseUp(nsIDOMEvent* aMouseEvent) } if (matched) - ExecuteHandler(NS_LITERAL_STRING("mouseup"), aMouseEvent); + ExecuteHandler(mEventName, aMouseEvent); return NS_OK; } nsresult nsXBLEventHandler::MouseClick(nsIDOMEvent* aMouseEvent) { - if (mEventName != NS_LITERAL_STRING("click")) + if (mEventName.get() != kMouseClickAtom) return NS_OK; PRBool matched = PR_FALSE; @@ -295,13 +374,13 @@ nsresult nsXBLEventHandler::MouseClick(nsIDOMEvent* aMouseEvent) } if (matched) - ExecuteHandler(NS_LITERAL_STRING("click"), aMouseEvent); + ExecuteHandler(mEventName, aMouseEvent); return NS_OK; } nsresult nsXBLEventHandler::MouseDblClick(nsIDOMEvent* aMouseEvent) { - if (mEventName != NS_LITERAL_STRING("dblclick")) + if (mEventName.get() != kMouseDblClickAtom) return NS_OK; PRBool matched = PR_FALSE; @@ -311,13 +390,13 @@ nsresult nsXBLEventHandler::MouseDblClick(nsIDOMEvent* aMouseEvent) } if (matched) - ExecuteHandler(NS_LITERAL_STRING("dblclick"), aMouseEvent); + ExecuteHandler(mEventName, aMouseEvent); return NS_OK; } nsresult nsXBLEventHandler::MouseOver(nsIDOMEvent* aMouseEvent) { - if (mEventName != NS_LITERAL_STRING("mouseover")) + if (mEventName.get() != kMouseOverAtom) return NS_OK; PRBool matched = PR_FALSE; @@ -327,13 +406,13 @@ nsresult nsXBLEventHandler::MouseOver(nsIDOMEvent* aMouseEvent) } if (matched) - ExecuteHandler(NS_LITERAL_STRING("mouseover"), aMouseEvent); + ExecuteHandler(mEventName, aMouseEvent); return NS_OK; } nsresult nsXBLEventHandler::MouseOut(nsIDOMEvent* aMouseEvent) { - if (mEventName != NS_LITERAL_STRING("mouseout")) + if (mEventName.get() != kMouseOutAtom) return NS_OK; PRBool matched = PR_FALSE; @@ -343,159 +422,159 @@ nsresult nsXBLEventHandler::MouseOut(nsIDOMEvent* aMouseEvent) } if (matched) - ExecuteHandler(NS_LITERAL_STRING("mouseout"), aMouseEvent); + ExecuteHandler(mEventName, aMouseEvent); return NS_OK; } nsresult nsXBLEventHandler::Focus(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("focus")) + if (mEventName.get() != kFocusAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("focus"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Blur(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("blur")) + if (mEventName.get() != kBlurAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("blur"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Action(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("command")) + if (mEventName.get() != kCommandAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("command"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Create(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("create")) + if (mEventName.get() != kCreateAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("create"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Close(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("close")) + if (mEventName.get() != kCloseAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("close"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Broadcast(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("broadcast")) + if (mEventName.get() != kBroadcastAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("broadcast"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::CommandUpdate(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("commandupdate")) + if (mEventName.get() != kCommandUpdateAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("commandupdate"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Overflow(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("overflow")) + if (mEventName.get() != kOverflowAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("overflow"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Underflow(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("underflow")) + if (mEventName.get() != kUnderflowAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("underflow"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::OverflowChanged(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("underflowchanged")) + if (mEventName.get() != kOverflowChangedAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("underflowchanged"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Destroy(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("destroy")) + if (mEventName.get() != kDestroyAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("destroy"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Submit(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("submit")) + if (mEventName.get() != kSubmitAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("submit"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Reset(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("reset")) + if (mEventName.get() != kResetAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("reset"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Select(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("select")) + if (mEventName.get() != kSelectAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("select"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Change(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("change")) + if (mEventName.get() != kChangeAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("change"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } nsresult nsXBLEventHandler::Input(nsIDOMEvent* aEvent) { - if (mEventName != NS_LITERAL_STRING("input")) + if (mEventName.get() != kInputAtom) return NS_OK; - ExecuteHandler(NS_LITERAL_STRING("input"), aEvent); + ExecuteHandler(mEventName, aEvent); return NS_OK; } NS_IMETHODIMP -nsXBLEventHandler::ExecuteHandler(const nsAReadableString & aEventName, nsIDOMEvent* aEvent) +nsXBLEventHandler::ExecuteHandler(nsIAtom* aEventName, nsIDOMEvent* aEvent) { if (!mProtoHandler) return NS_ERROR_FAILURE; @@ -510,6 +589,20 @@ nsXBLEventHandler::ExecuteHandler(const nsAReadableString & aEventName, nsIDOMEv nsAutoString command; handlerElement->GetAttribute(kNameSpaceID_None, kCommandAtom, command); if (!command.IsEmpty()) { + // Make sure the XBL doc is chrome. + // Fix for bug #45989 + if (!mProtoHandler) + return NS_OK; + nsCOMPtr handler; + mProtoHandler->GetHandlerElement(getter_AddRefs(handler)); + nsCOMPtr document; + handler->GetDocument(*getter_AddRefs(document)); + nsCOMPtr url = getter_AddRefs(document->GetDocumentURL()); + nsXPIDLCString scheme; + url->GetScheme(getter_Copies(scheme)); + if (PL_strcmp(scheme, "chrome") != 0) + return NS_OK; + // We are the default action for this command. // Stop any other default action from executing. aEvent->PreventDefault(); @@ -538,7 +631,9 @@ nsXBLEventHandler::ExecuteHandler(const nsAReadableString & aEventName, nsIDOMEv // Look for a compiled handler on the element. // Should be compiled and bound with "on" in front of the name. nsAutoString onEvent; onEvent.AssignWithConversion("onxbl"); - onEvent += aEventName; + nsAutoString str; + mEventName->ToString(str); + onEvent += str; nsCOMPtr onEventAtom = getter_AddRefs(NS_NewAtom(onEvent)); void* handler = nsnull; @@ -645,8 +740,8 @@ nsXBLEventHandler::RemoveEventHandlers() if (!mProtoHandler) return; - if (mEventName == NS_LITERAL_STRING("bindingattached") || - mEventName == NS_LITERAL_STRING("bindingdetached")) { + if (mEventName.get() == kBindingAttachedAtom || + mEventName.get() == kBindingDetachedAtom) { // Release and drop. mProtoHandler = nsnull; NS_RELEASE_THIS(); @@ -668,41 +763,23 @@ nsXBLEventHandler::RemoveEventHandlers() nsAutoString type; handlerElement->GetAttribute(kNameSpaceID_None, nsXBLBinding::kEventAtom, type); - // Figure out our type. - PRBool key = nsXBLBinding::IsKeyHandler(type); - if (key) { - mEventReceiver->RemoveEventListener(type, (nsIDOMKeyListener*)this, useCapture); - return; - } + PRBool found = PR_FALSE; + nsIID iid; + nsXBLBinding::GetEventHandlerIID(mEventName, &iid, &found); - PRBool mouse = nsXBLBinding::IsMouseHandler(type); - if (mouse) { - mEventReceiver->RemoveEventListener(type, (nsIDOMMouseListener*)this, useCapture); - return; - } - - PRBool focus = nsXBLBinding::IsFocusHandler(type); - if (focus) { - mEventReceiver->RemoveEventListener(type, (nsIDOMFocusListener*)this, useCapture); - return; - } - - PRBool xul = nsXBLBinding::IsXULHandler(type); - if (xul) { - mEventReceiver->RemoveEventListener(type, (nsIDOMMenuListener*)this, useCapture); - return; - } - - PRBool scroll = nsXBLBinding::IsScrollHandler(type); - if (scroll) { - mEventReceiver->RemoveEventListener(type, (nsIDOMScrollListener*)this, useCapture); - return; - } - - PRBool form = nsXBLBinding::IsFormHandler(type); - if (form) { - mEventReceiver->RemoveEventListener(type, (nsIDOMFormListener*)this, useCapture); - return; + if (found) { + if (iid.Equals(NS_GET_IID(nsIDOMMouseListener))) + mEventReceiver->AddEventListener(type, (nsIDOMMouseListener*)this, useCapture); + else if(iid.Equals(NS_GET_IID(nsIDOMKeyListener))) + mEventReceiver->AddEventListener(type, (nsIDOMKeyListener*)this, useCapture); + else if(iid.Equals(NS_GET_IID(nsIDOMFocusListener))) + mEventReceiver->AddEventListener(type, (nsIDOMFocusListener*)this, useCapture); + else if (iid.Equals(NS_GET_IID(nsIDOMMenuListener))) + mEventReceiver->AddEventListener(type, (nsIDOMMenuListener*)this, useCapture); + else if (iid.Equals(NS_GET_IID(nsIDOMScrollListener))) + mEventReceiver->AddEventListener(type, (nsIDOMScrollListener*)this, useCapture); + else if (iid.Equals(NS_GET_IID(nsIDOMFormListener))) + mEventReceiver->AddEventListener(type, (nsIDOMFormListener*)this, useCapture); } } @@ -734,7 +811,7 @@ nsXBLEventHandler::GetTextData(nsIContent *aParent, nsString& aResult) nsresult NS_NewXBLEventHandler(nsIDOMEventReceiver* aRec, nsIXBLPrototypeHandler* aHandler, - const nsString& aEventName, + nsIAtom* aEventName, nsXBLEventHandler** aResult) { *aResult = new nsXBLEventHandler(aRec, aHandler, aEventName); diff --git a/layout/xbl/src/nsXBLEventHandler.h b/layout/xbl/src/nsXBLEventHandler.h index e211728bd79a..11f293b2b36d 100644 --- a/layout/xbl/src/nsXBLEventHandler.h +++ b/layout/xbl/src/nsXBLEventHandler.h @@ -43,6 +43,8 @@ class nsIAtom; class nsIController; class nsIXBLPrototypeHandler; +// XXX This should be broken up into subclasses for each listener IID type, so we +// can cut down on the bloat of the handlers. class nsXBLEventHandler : public nsIDOMKeyListener, public nsIDOMMouseListener, public nsIDOMMenuListener, @@ -51,7 +53,7 @@ class nsXBLEventHandler : public nsIDOMKeyListener, public nsIDOMFormListener { public: - nsXBLEventHandler(nsIDOMEventReceiver* aReceiver, nsIXBLPrototypeHandler* aHandler, const nsString& aEventName); + nsXBLEventHandler(nsIDOMEventReceiver* aReceiver, nsIXBLPrototypeHandler* aHandler, nsIAtom* aEventName); virtual ~nsXBLEventHandler(); NS_IMETHOD BindingAttached(); @@ -109,7 +111,7 @@ public: protected: NS_IMETHOD GetController(nsIController** aResult); - NS_IMETHOD ExecuteHandler(const nsAReadableString & aEventName, nsIDOMEvent* aEvent); + NS_IMETHOD ExecuteHandler(nsIAtom* aEventName, nsIDOMEvent* aEvent); static PRUint32 gRefCnt; static nsIAtom* kKeyAtom; @@ -123,20 +125,50 @@ protected: static nsIAtom* kBindingDetachedAtom; static nsIAtom* kModifiersAtom; + static nsIAtom* kKeyUpAtom; + static nsIAtom* kKeyDownAtom; + static nsIAtom* kKeyPressAtom; + + static nsIAtom* kMouseDownAtom; + static nsIAtom* kMouseUpAtom; + static nsIAtom* kMouseClickAtom; + static nsIAtom* kMouseDblClickAtom; + static nsIAtom* kMouseOverAtom; + static nsIAtom* kMouseOutAtom; + + static nsIAtom* kFocusAtom; + static nsIAtom* kBlurAtom; + + static nsIAtom* kCreateAtom; + static nsIAtom* kCloseAtom; + static nsIAtom* kDestroyAtom; + static nsIAtom* kCommandUpdateAtom; + static nsIAtom* kBroadcastAtom; + + static nsIAtom* kOverflowAtom; + static nsIAtom* kUnderflowAtom; + static nsIAtom* kOverflowChangedAtom; + + static nsIAtom* kSubmitAtom; + static nsIAtom* kResetAtom; + static nsIAtom* kChangeAtom; + static nsIAtom* kSelectAtom; + static nsIAtom* kInputAtom; + static nsresult GetTextData(nsIContent *aParent, nsString& aResult); protected: nsIDOMEventReceiver* mEventReceiver; // Both of these refs are weak. nsCOMPtr mProtoHandler; - nsAutoString mEventName; - + nsCOMPtr mEventName; + nsXBLEventHandler* mNextHandler; // Handlers are chained for easy unloading later. }; extern nsresult NS_NewXBLEventHandler(nsIDOMEventReceiver* aEventReceiver, nsIXBLPrototypeHandler* aHandlerElement, - const nsString& aEventName, + nsIAtom* aEventName, nsXBLEventHandler** aResult);