Bug 658714 Part 9: Don't use EventGroups for system-group. r=smaug
authorJonas Sicking <jonas@sicking.cc>
Thu, 23 Jun 2011 19:18:02 -0700
changeset 71620 47c73a8334bb6b4bc059fcd6e8bbf6ac8d2a4cb1
parent 71619 7236111084214e4141934859855a79a96a19de13
child 71621 c980dcde975498d0529112b4a2854e31d5212f16
push idunknown
push userunknown
push dateunknown
reviewerssmaug
bugs658714
milestone7.0a1
Bug 658714 Part 9: Don't use EventGroups for system-group. r=smaug
content/base/src/nsGenericElement.cpp
content/events/public/nsIEventListenerService.idl
content/events/src/nsDOMEventTargetHelper.cpp
content/events/src/nsEventListenerManager.cpp
content/events/src/nsEventListenerManager.h
content/events/src/nsEventListenerService.cpp
content/html/content/src/nsTextEditorState.cpp
content/smil/nsSMILTimeValueSpec.cpp
content/smil/nsSMILTimeValueSpec.h
content/xbl/src/nsXBLBinding.cpp
content/xbl/src/nsXBLService.cpp
content/xul/content/src/nsXULElement.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsWindowRoot.cpp
dom/interfaces/events/nsIDOMEventTarget.idl
dom/src/threads/nsDOMWorkerMessageHandler.cpp
dom/src/threads/nsDOMWorkerMessageHandler.h
editor/libeditor/base/nsEditorEventListener.cpp
editor/libeditor/html/tests/test_contenteditable_text_input_handling.html
editor/libeditor/html/tests/test_htmleditor_keyevent_handling.html
editor/libeditor/text/tests/test_bug569988.html
editor/libeditor/text/tests/test_texteditor_keyevent_handling.html
embedding/browser/webBrowser/nsDocShellTreeOwner.cpp
layout/forms/nsFileControlFrame.cpp
testing/mochitest/specialpowers/content/specialpowers.js
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -1057,24 +1057,16 @@ nsINode::RemoveEventListenerByIID(nsIDOM
 }
 
 nsEventListenerManager*
 nsINode::GetListenerManager(PRBool aCreateIfNotFound)
 {
   return nsContentUtils::GetListenerManager(this, aCreateIfNotFound);
 }
 
-nsresult
-nsINode::GetSystemEventGroup(nsIDOMEventGroup** aGroup)
-{
-  nsEventListenerManager* elm = GetListenerManager(PR_TRUE);
-  NS_ENSURE_STATE(elm);
-  return elm->GetSystemEventGroupLM(aGroup);
-}
-
 nsIScriptContext*
 nsINode::GetContextForEventHandlers(nsresult* aRv)
 {
   return nsContentUtils::GetContextForEventHandlers(this, aRv);
 }
 
 //----------------------------------------------------------------------
 
--- a/content/events/public/nsIEventListenerService.idl
+++ b/content/events/public/nsIEventListenerService.idl
@@ -62,17 +62,17 @@ interface nsIEventListenerInfo : nsISupp
 
   /**
    * If jsdIDebuggerService is active and the listener is implemented in JS,
    * this returns the listener as a jsdIValue. Otherwise null.
    */
   nsISupports getDebugObject();
 };
 
-[scriptable, uuid(7b0ca544-a38f-4072-96c6-5fff4996277a)]
+[scriptable, uuid(0cf94aa6-ea9a-44cb-a063-be834afa679d)]
 interface nsIEventListenerService : nsISupports
 {
   /**
    * Returns an array of nsIEventListenerInfo objects.
    * If aEventTarget doesn't have any listeners, this returns null.
    */
   void getListenerInfoFor(in nsIDOMEventTarget aEventTarget,
                           [optional] out unsigned long aCount,
@@ -94,13 +94,24 @@ interface nsIEventListenerService : nsIS
 
   /**
    * Returns true if a event target has any listener for the given type.
    */
   boolean hasListenersFor(in nsIDOMEventTarget aEventTarget,
                           in DOMString aType);
 
   /**
-   * Returns system event group.
+   * Add a system-group eventlistener to a event target.
    */
-  readonly attribute nsIDOMEventGroup systemEventGroup;
+  void addSystemEventListener(in nsIDOMEventTarget target,
+                              in DOMString type,
+                              in nsIDOMEventListener listener,
+                              in boolean useCapture);
+
+  /**
+   * Remove a system-group eventlistener from a event target.
+   */
+  void removeSystemEventListener(in nsIDOMEventTarget target,
+                                 in DOMString type,
+                                 in nsIDOMEventListener listener,
+                                 in boolean useCapture);
 };
 
--- a/content/events/src/nsDOMEventTargetHelper.cpp
+++ b/content/events/src/nsDOMEventTargetHelper.cpp
@@ -221,24 +221,16 @@ nsDOMEventTargetHelper::RemoveEventListe
 {
   nsEventListenerManager* elm = GetListenerManager(PR_FALSE);
   if (elm) {
     elm->RemoveEventListenerByIID(aListener, aIID, NS_EVENT_FLAG_BUBBLE);
   }
   return NS_OK;
 }
 
-nsresult
-nsDOMEventTargetHelper::GetSystemEventGroup(nsIDOMEventGroup** aGroup)
-{
-  nsEventListenerManager* elm = GetListenerManager(PR_TRUE);
-  NS_ENSURE_STATE(elm);
-  return elm->GetSystemEventGroupLM(aGroup);
-}
-
 nsIScriptContext*
 nsDOMEventTargetHelper::GetContextForEventHandlers(nsresult* aRv)
 {
   *aRv = CheckInnerWindowCorrectness();
   if (NS_FAILED(*aRv)) {
     return nsnull;
   }
   return mScriptContext;
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -267,17 +267,16 @@ static const EventTypeData sEventTypes[]
   IMPL_EVENTTYPEDATA(Focus),
   IMPL_EVENTTYPEDATA(Form),
   IMPL_EVENTTYPEDATA(Text),
   IMPL_EVENTTYPEDATA(Composition),
   IMPL_EVENTTYPEDATA(UI)
 };
 
 // Strong references to event groups
-nsIDOMEventGroup* gSystemEventGroup = nsnull;
 nsIDOMEventGroup* gDOM2EventGroup = nsnull;
 
 PRUint32 nsEventListenerManager::mInstanceCount = 0;
 PRUint32 nsEventListenerManager::sCreatedCount = 0;
 
 nsEventListenerManager::nsEventListenerManager(nsISupports* aTarget) :
   mTarget(aTarget)
 {
@@ -311,30 +310,20 @@ void
 nsEventListenerManager::RemoveAllListeners()
 {
   mListeners.Clear();
 }
 
 void
 nsEventListenerManager::Shutdown()
 {
-  NS_IF_RELEASE(gSystemEventGroup);
   sAddListenerID = JSID_VOID;
   nsDOMEvent::Shutdown();
 }
 
-nsIDOMEventGroup*
-nsEventListenerManager::GetSystemEventGroup()
-{
-  if (!gSystemEventGroup) {
-    CallCreateInstance(kDOMEventGroupCID, &gSystemEventGroup);
-  }
-  return gSystemEventGroup;
-}
-
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsEventListenerManager)
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsEventListenerManager, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsEventListenerManager, Release)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsEventListenerManager)
   PRUint32 count = tmp->mListeners.Length();
   for (PRUint32 i = 0; i < count; i++) {
@@ -404,28 +393,16 @@ nsEventListenerManager::AddEventListener
                                          PRInt32 aFlags,
                                          nsIDOMEventGroup* aEvtGrp)
 {
   NS_ENSURE_TRUE(aListener, NS_ERROR_FAILURE);
   NS_ENSURE_TRUE(aType || aTypeData, NS_ERROR_FAILURE);
 
   nsRefPtr<nsIDOMEventListener> kungFuDeathGrip = aListener;
 
-  PRBool isSame = PR_FALSE;
-  PRUint16 group = 0;
-  nsCOMPtr<nsIDOMEventGroup> sysGroup;
-  GetSystemEventGroupLM(getter_AddRefs(sysGroup));
-  if (sysGroup) {
-    sysGroup->IsSameEventGroup(aEvtGrp, &isSame);
-    if (isSame) {
-      group = NS_EVENT_FLAG_SYSTEM_EVENT;
-      mMayHaveSystemGroupListeners = PR_TRUE;
-    }
-  }
-
   if (!aTypeData) {
     // If we don't have type data, we can try to QI listener to the right
     // interface and set mTypeData only if QI succeeds. This way we can save
     // calls to DispatchToInterface (in HandleEvent) in those cases when QI
     // would fail.
     // @see also DispatchToInterface()
     const EventTypeData* td = GetTypeDataForEventName(aTypeAtom);
     if (td && td->iid) {
@@ -438,34 +415,36 @@ nsEventListenerManager::AddEventListener
     }
   }
 
   nsListenerStruct* ls;
   PRUint32 count = mListeners.Length();
   for (PRUint32 i = 0; i < count; i++) {
     ls = &mListeners.ElementAt(i);
     if (ls->mListener == aListener && ls->mFlags == aFlags &&
-        ls->mGroupFlags == group &&
         (EVENT_TYPE_EQUALS(ls, aType, aTypeAtom) ||
          EVENT_TYPE_DATA_EQUALS(aTypeData, ls->mTypeData))) {
       return NS_OK;
     }
   }
 
   mNoListenerForEvent = NS_EVENT_TYPE_NULL;
   mNoListenerForEventAtom = nsnull;
 
   ls = mListeners.AppendElement();
   ls->mListener = aListener;
   ls->mEventType = aType;
   ls->mTypeAtom = aTypeAtom;
   ls->mFlags = aFlags;
-  ls->mGroupFlags = group;
   ls->mHandlerIsString = PR_FALSE;
   ls->mTypeData = aTypeData;
+
+  if (aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) {
+    mMayHaveSystemGroupListeners = PR_TRUE;
+  }
   if (aFlags & NS_EVENT_FLAG_CAPTURE) {
     mMayHaveCapturingListeners = PR_TRUE;
   }
 
   if (aType == NS_AFTERPAINT) {
     mMayHavePaintEventListener = PR_TRUE;
     nsPIDOMWindow* window = GetInnerWindowForTarget();
     if (window) {
@@ -520,35 +499,23 @@ nsEventListenerManager::RemoveEventListe
                                             const EventTypeData* aTypeData,
                                             PRInt32 aFlags,
                                             nsIDOMEventGroup* aEvtGrp)
 {
   if (!aListener || !(aType || aTypeData)) {
     return;
   }
 
-  PRBool isSame = PR_FALSE;
-  PRUint16 group = 0;
-  nsCOMPtr<nsIDOMEventGroup> sysGroup;
-  GetSystemEventGroupLM(getter_AddRefs(sysGroup));
-  if (sysGroup) {
-    sysGroup->IsSameEventGroup(aEvtGrp, &isSame);
-    if (isSame) {
-      group = NS_EVENT_FLAG_SYSTEM_EVENT;
-    }
-  }
-
   nsListenerStruct* ls;
   aFlags &= ~NS_PRIV_EVENT_UNTRUSTED_PERMITTED;
 
   PRUint32 count = mListeners.Length();
   for (PRUint32 i = 0; i < count; ++i) {
     ls = &mListeners.ElementAt(i);
     if (ls->mListener == aListener &&
-        ls->mGroupFlags == group &&
         ((ls->mFlags & ~NS_PRIV_EVENT_UNTRUSTED_PERMITTED) == aFlags) &&
         (EVENT_TYPE_EQUALS(ls, aType, aUserType) ||
          (!(ls->mEventType) &&
           EVENT_TYPE_DATA_EQUALS(ls->mTypeData, aTypeData)))) {
       nsRefPtr<nsEventListenerManager> kungFuDeathGrip = this;
       mListeners.RemoveElementAt(i);
       mNoListenerForEvent = NS_EVENT_TYPE_NULL;
       mNoListenerForEventAtom = nsnull;
@@ -1141,17 +1108,16 @@ nsEventListenerManager::HandleEventInter
                                             PRUint32 aFlags,
                                             nsEventStatus* aEventStatus,
                                             nsCxPusher* aPusher)
 {
   //Set the value of the internal PreventDefault flag properly based on aEventStatus
   if (*aEventStatus == nsEventStatus_eConsumeNoDefault) {
     aEvent->flags |= NS_EVENT_FLAG_NO_DEFAULT;
   }
-  PRUint16 currentGroup = aFlags & NS_EVENT_FLAG_SYSTEM_EVENT;
 
   const EventTypeData* typeData = nsnull;
   const EventDispatchData* dispData = nsnull;
   if (aEvent->message != NS_USER_DEFINED_EVENT) {
     // Check if this is the same type of event as what a listener manager
     // handled last time.
     if (aEvent->message == sLatestEventType) {
       typeData = sLatestEventTypeData;
@@ -1186,18 +1152,21 @@ found:
     PRBool useGenericInterface =
       (!useTypeInterface && ListenerCanHandle(ls, aEvent));
     // Don't fire the listener if it's been removed.
     // Check that the phase is same in event and event listener.
     // Handle only trusted events, except when listener permits untrusted events.
     if (useTypeInterface || useGenericInterface) {
       if (ls->mListener) {
         hasListener = PR_TRUE;
-        if (ls->mFlags & aFlags &&
-            ls->mGroupFlags == currentGroup &&
+        // XXX The (mFlags & aFlags) test here seems fragile. Shouldn't we
+        // specifically only test the capture/bubble flags.
+        if ((ls->mFlags & aFlags & ~NS_EVENT_FLAG_SYSTEM_EVENT) &&
+            (ls->mFlags & NS_EVENT_FLAG_SYSTEM_EVENT) ==
+            (aFlags & NS_EVENT_FLAG_SYSTEM_EVENT) &&
             (NS_IS_TRUSTED_EVENT(aEvent) ||
              ls->mFlags & NS_PRIV_EVENT_UNTRUSTED_PERMITTED)) {
           if (!*aDOMEvent) {
             nsEventDispatcher::CreateEvent(aPresContext, aEvent,
                                            EmptyString(), aDOMEvent);
           }
           if (*aDOMEvent) {
             if (!aEvent->currentTarget) {
@@ -1240,25 +1209,16 @@ found:
 void
 nsEventListenerManager::Disconnect()
 {
   mTarget = nsnull;
   RemoveAllListeners();
 }
 
 nsresult
-nsEventListenerManager::GetSystemEventGroupLM(nsIDOMEventGroup **aGroup)
-{
-  *aGroup = GetSystemEventGroup();
-  NS_ENSURE_TRUE(*aGroup, NS_ERROR_OUT_OF_MEMORY);
-  NS_ADDREF(*aGroup);
-  return NS_OK;
-}
-
-nsresult
 nsEventListenerManager::GetDOM2EventGroup(nsIDOMEventGroup **aGroup)
 {
   if (!gDOM2EventGroup) {
     nsresult result;
     nsCOMPtr<nsIDOMEventGroup> group(do_CreateInstance(kDOMEventGroupCID,&result));
     if (NS_FAILED(result))
       return result;
 
@@ -1416,17 +1376,17 @@ nsEventListenerManager::GetListenerInfo(
 {
   nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mTarget);
   NS_ENSURE_STATE(target);
   aList->Clear();
   PRUint32 count = mListeners.Length();
   for (PRUint32 i = 0; i < count; ++i) {
     const nsListenerStruct& ls = mListeners.ElementAt(i);
     PRBool capturing = !!(ls.mFlags & NS_EVENT_FLAG_CAPTURE);
-    PRBool systemGroup = !!(ls.mGroupFlags & NS_EVENT_FLAG_SYSTEM_EVENT);
+    PRBool systemGroup = !!(ls.mFlags & NS_EVENT_FLAG_SYSTEM_EVENT);
     PRBool allowsUntrusted = !!(ls.mFlags & NS_PRIV_EVENT_UNTRUSTED_PERMITTED);
     // If this is a script handler and we haven't yet
     // compiled the event handler itself
     if ((ls.mFlags & NS_PRIV_EVENT_FLAG_SCRIPT) && ls.mHandlerIsString) {
       nsCOMPtr<nsIJSEventListener> jslistener = do_QueryInterface(ls.mListener);
       if (jslistener) {
         CompileEventHandlerInternal(jslistener->GetEventContext(),
                                     jslistener->GetEventScope(),
--- a/content/events/src/nsEventListenerManager.h
+++ b/content/events/src/nsEventListenerManager.h
@@ -62,17 +62,16 @@ class nsPIDOMWindow;
 class nsCxPusher;
 class nsIEventListenerInfo;
 
 typedef struct {
   nsRefPtr<nsIDOMEventListener> mListener;
   PRUint32                      mEventType;
   nsCOMPtr<nsIAtom>             mTypeAtom;
   PRUint16                      mFlags;
-  PRUint16                      mGroupFlags;
   PRBool                        mHandlerIsString;
   const EventTypeData*          mTypeData;
 } nsListenerStruct;
 
 /*
  * Event listener manager
  */
 
@@ -164,18 +163,16 @@ public:
                            nsIDOMEvent** aDOMEvent,
                            nsIDOMEventTarget* aCurrentTarget,
                            PRUint32 aFlags,
                            nsEventStatus* aEventStatus,
                            nsCxPusher* aPusher);
 
   void Disconnect();
 
-  nsresult GetSystemEventGroupLM(nsIDOMEventGroup **aGroup);
-
   PRBool HasMutationListeners();
 
   PRBool HasUnloadListeners();
 
   PRUint32 MutationListenerBits();
 
   PRBool HasListenersFor(const nsAString& aEventName);
 
@@ -185,18 +182,16 @@ public:
 
   PRUint32 GetIdentifierForEvent(nsIAtom* aEvent);
 
   // nsIDOM3EventTarget
   NS_DECL_NSIDOM3EVENTTARGET
 
   static void Shutdown();
 
-  static nsIDOMEventGroup* GetSystemEventGroup();
-
   /**
    * Returns PR_TRUE if there may be a paint event listener registered,
    * PR_FALSE if there definitely isn't.
    */
   PRBool MayHavePaintEventListener() { return mMayHavePaintEventListener; }
 
   /**
    * Returns PR_TRUE if there may be a MozAudioAvailable event listener registered,
--- a/content/events/src/nsEventListenerService.cpp
+++ b/content/events/src/nsEventListenerService.cpp
@@ -261,22 +261,52 @@ nsEventListenerService::HasListenersFor(
                                         PRBool* aRetVal)
 {
   nsEventListenerManager* elm = aEventTarget->GetListenerManager(PR_FALSE);
   *aRetVal = elm && elm->HasListenersFor(aType);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsEventListenerService::GetSystemEventGroup(nsIDOMEventGroup** aSystemGroup)
+nsEventListenerService::AddSystemEventListener(nsIDOMEventTarget *aTarget,
+                                               const nsAString& aType,
+                                               nsIDOMEventListener* aListener,
+                                               PRBool aUseCapture)
 {
-  NS_ENSURE_ARG_POINTER(aSystemGroup);
-  *aSystemGroup = nsEventListenerManager::GetSystemEventGroup();
-  NS_ENSURE_TRUE(*aSystemGroup, NS_ERROR_OUT_OF_MEMORY);
-  NS_ADDREF(*aSystemGroup);
+  NS_PRECONDITION(aTarget, "Missing target");
+  NS_PRECONDITION(aListener, "Missing listener");
+
+  nsEventListenerManager* manager = aTarget->GetListenerManager(PR_TRUE);
+  NS_ENSURE_STATE(manager);
+
+  PRInt32 flags = aUseCapture ? NS_EVENT_FLAG_CAPTURE |
+                                NS_EVENT_FLAG_SYSTEM_EVENT :
+                                NS_EVENT_FLAG_BUBBLE |
+                                NS_EVENT_FLAG_SYSTEM_EVENT;
+  return manager->AddEventListenerByType(aListener, aType, flags, nsnull);
+}
+
+NS_IMETHODIMP
+nsEventListenerService::RemoveSystemEventListener(nsIDOMEventTarget *aTarget,
+                                                  const nsAString& aType,
+                                                  nsIDOMEventListener* aListener,
+                                                  PRBool aUseCapture)
+{
+  NS_PRECONDITION(aTarget, "Missing target");
+  NS_PRECONDITION(aListener, "Missing listener");
+
+  nsEventListenerManager* manager = aTarget->GetListenerManager(PR_FALSE);
+  if (manager) {
+    PRInt32 flags = aUseCapture ? NS_EVENT_FLAG_CAPTURE |
+                                  NS_EVENT_FLAG_SYSTEM_EVENT :
+                                  NS_EVENT_FLAG_BUBBLE |
+                                  NS_EVENT_FLAG_SYSTEM_EVENT;
+    manager->RemoveEventListenerByType(aListener, aType, flags, nsnull);
+  }
+
   return NS_OK;
 }
 
 nsresult
 NS_NewEventListenerService(nsIEventListenerService** aResult)
 {
   *aResult = new nsEventListenerService();
   NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
--- a/content/html/content/src/nsTextEditorState.cpp
+++ b/content/html/content/src/nsTextEditorState.cpp
@@ -59,16 +59,17 @@
 #include "nsINativeKeyBindings.h"
 #include "nsIDocumentEncoder.h"
 #include "nsISelectionPrivate.h"
 #include "nsPIDOMWindow.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIDOMEventGroup.h"
 #include "nsIEditor.h"
 #include "nsTextEditRules.h"
+#include "nsEventListenerManager.h"
 
 #include "nsTextEditorState.h"
 
 using namespace mozilla::dom;
 
 static NS_DEFINE_CID(kTextEditorCID, NS_TEXTEDITOR_CID);
 
 static nsINativeKeyBindings *sNativeInputBindings = nsnull;
@@ -1508,31 +1509,39 @@ nsTextEditorState::UnbindFromFrame(nsTex
     mSelCon->SetScrollableFrame(nsnull);
     mSelCon = nsnull;
   }
 
   if (mTextListener)
   {
     mTextListener->SetFrame(nsnull);
 
-    nsCOMPtr<nsIDOMEventGroup> systemGroup;
-    nsCOMPtr<nsIContent> content = do_QueryInterface(mTextCtrlElement);
-    content->GetSystemEventGroup(getter_AddRefs(systemGroup));
-    nsCOMPtr<nsIDOM3EventTarget> dom3Targ = do_QueryInterface(mTextCtrlElement);
-    if (dom3Targ) {
+    nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mTextCtrlElement);
+    nsEventListenerManager* manager =
+      target->GetListenerManager(PR_FALSE);
+    if (manager) {
       // cast because of ambiguous base
       nsIDOMEventListener *listener = static_cast<nsIDOMKeyListener*>
                                                  (mTextListener);
 
-      dom3Targ->RemoveGroupedEventListener(NS_LITERAL_STRING("keydown"),
-                                           listener, PR_FALSE, systemGroup);
-      dom3Targ->RemoveGroupedEventListener(NS_LITERAL_STRING("keypress"),
-                                           listener, PR_FALSE, systemGroup);
-      dom3Targ->RemoveGroupedEventListener(NS_LITERAL_STRING("keyup"),
-                                           listener, PR_FALSE, systemGroup);
+      manager->RemoveEventListenerByType(listener,
+                                         NS_LITERAL_STRING("keydown"),
+                                         NS_EVENT_FLAG_BUBBLE |
+                                         NS_EVENT_FLAG_SYSTEM_EVENT,
+                                         nsnull);
+      manager->RemoveEventListenerByType(listener,
+                                         NS_LITERAL_STRING("keypress"),
+                                         NS_EVENT_FLAG_BUBBLE |
+                                         NS_EVENT_FLAG_SYSTEM_EVENT,
+                                         nsnull);
+      manager->RemoveEventListenerByType(listener,
+                                         NS_LITERAL_STRING("keyup"),
+                                         NS_EVENT_FLAG_BUBBLE |
+                                         NS_EVENT_FLAG_SYSTEM_EVENT,
+                                         nsnull);
     }
 
     NS_RELEASE(mTextListener);
     mTextListener = nsnull;
   }
 
   mBoundFrame = nsnull;
 
@@ -1932,33 +1941,36 @@ nsTextEditorState::SetValue(const nsAStr
   ValueWasChanged(!!mRootNode);
 
   mTextCtrlElement->OnValueChanged(!!mRootNode);
 }
 
 void
 nsTextEditorState::InitializeKeyboardEventListeners()
 {
-  nsCOMPtr<nsIContent> content = do_QueryInterface(mTextCtrlElement);
-
   //register key listeners
-  nsCOMPtr<nsIDOMEventGroup> systemGroup;
-  content->GetSystemEventGroup(getter_AddRefs(systemGroup));
-  nsCOMPtr<nsIDOM3EventTarget> dom3Targ = do_QueryInterface(content);
-  if (dom3Targ) {
+  nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mTextCtrlElement);
+  nsEventListenerManager* manager = target->GetListenerManager(PR_TRUE);
+  if (manager) {
     // cast because of ambiguous base
     nsIDOMEventListener *listener = static_cast<nsIDOMKeyListener*>
                                                (mTextListener);
 
-    dom3Targ->AddGroupedEventListener(NS_LITERAL_STRING("keydown"),
-                                      listener, PR_FALSE, systemGroup);
-    dom3Targ->AddGroupedEventListener(NS_LITERAL_STRING("keypress"),
-                                      listener, PR_FALSE, systemGroup);
-    dom3Targ->AddGroupedEventListener(NS_LITERAL_STRING("keyup"),
-                                      listener, PR_FALSE, systemGroup);
+    manager->AddEventListenerByType(listener, NS_LITERAL_STRING("keydown"),
+                                    NS_EVENT_FLAG_BUBBLE |
+                                    NS_EVENT_FLAG_SYSTEM_EVENT,
+                                    nsnull);
+    manager->AddEventListenerByType(listener, NS_LITERAL_STRING("keypress"),
+                                    NS_EVENT_FLAG_BUBBLE |
+                                    NS_EVENT_FLAG_SYSTEM_EVENT,
+                                    nsnull);
+    manager->AddEventListenerByType(listener, NS_LITERAL_STRING("keyup"),
+                                    NS_EVENT_FLAG_BUBBLE |
+                                    NS_EVENT_FLAG_SYSTEM_EVENT,
+                                    nsnull);
   }
 
   mSelCon->SetScrollableFrame(do_QueryFrame(mBoundFrame->GetFirstChild(nsnull)));
 }
 
 /* static */ void
 nsTextEditorState::ShutDown()
 {
--- a/content/smil/nsSMILTimeValueSpec.cpp
+++ b/content/smil/nsSMILTimeValueSpec.cpp
@@ -332,55 +332,50 @@ nsSMILTimeValueSpec::RegisterEventListen
 
   if (!aTarget)
     return;
 
   if (!mEventListener) {
     mEventListener = new EventListener(this);
   }
 
-  nsCOMPtr<nsIDOMEventGroup> sysGroup;
-  nsEventListenerManager* elm =
-    GetEventListenerManager(aTarget, getter_AddRefs(sysGroup));
+  nsEventListenerManager* elm = GetEventListenerManager(aTarget);
   if (!elm)
     return;
   
   elm->AddEventListenerByType(mEventListener,
                               nsDependentAtomString(mParams.mEventSymbol),
                               NS_EVENT_FLAG_BUBBLE |
-                              NS_PRIV_EVENT_UNTRUSTED_PERMITTED,
-                              sysGroup);
+                              NS_PRIV_EVENT_UNTRUSTED_PERMITTED |
+                              NS_EVENT_FLAG_SYSTEM_EVENT,
+                              nsnull);
 }
 
 void
 nsSMILTimeValueSpec::UnregisterEventListener(Element* aTarget)
 {
   if (!aTarget || !mEventListener)
     return;
 
-  nsCOMPtr<nsIDOMEventGroup> sysGroup;
-  nsEventListenerManager* elm =
-    GetEventListenerManager(aTarget, getter_AddRefs(sysGroup));
+  nsEventListenerManager* elm = GetEventListenerManager(aTarget);
   if (!elm)
     return;
 
   elm->RemoveEventListenerByType(mEventListener,
                                  nsDependentAtomString(mParams.mEventSymbol),
                                  NS_EVENT_FLAG_BUBBLE |
-                                 NS_PRIV_EVENT_UNTRUSTED_PERMITTED,
-                                 sysGroup);
+                                 NS_PRIV_EVENT_UNTRUSTED_PERMITTED |
+                                 NS_EVENT_FLAG_SYSTEM_EVENT,
+                                 nsnull);
 }
 
 nsEventListenerManager*
-nsSMILTimeValueSpec::GetEventListenerManager(Element* aTarget,
-                                             nsIDOMEventGroup** aSystemGroup)
+nsSMILTimeValueSpec::GetEventListenerManager(Element* aTarget)
 {
   NS_ABORT_IF_FALSE(aTarget, "null target; can't get EventListenerManager");
-  NS_ABORT_IF_FALSE(aSystemGroup && !*aSystemGroup,
-      "Bad out param for system group");
 
   nsCOMPtr<nsIDOMEventTarget> target;
 
   if (mParams.mType == nsSMILTimeValueSpecParams::ACCESSKEY) {
     nsIDocument* doc = aTarget->GetCurrentDoc();
     if (!doc)
       return nsnull;
     nsPIDOMWindow* win = doc->GetWindow();
@@ -388,25 +383,17 @@ nsSMILTimeValueSpec::GetEventListenerMan
       return nsnull;
     target = do_QueryInterface(win);
   } else {
     target = aTarget;
   }
   if (!target)
     return nsnull;
 
-  nsEventListenerManager* elm = target->GetListenerManager(PR_TRUE);
-  if (!elm)
-    return nsnull;
-
-  aTarget->GetSystemEventGroup(aSystemGroup);
-  if (!*aSystemGroup)
-    return nsnull;
-
-  return elm;
+  return target->GetListenerManager(PR_TRUE);
 }
 
 void
 nsSMILTimeValueSpec::HandleEvent(nsIDOMEvent* aEvent)
 {
   NS_ABORT_IF_FALSE(mEventListener, "Got event without an event listener");
   NS_ABORT_IF_FALSE(IsEventBased(),
                     "Got event for non-event nsSMILTimeValueSpec");
--- a/content/smil/nsSMILTimeValueSpec.h
+++ b/content/smil/nsSMILTimeValueSpec.h
@@ -90,18 +90,17 @@ public:
   void Unlink();
 
 protected:
   void UpdateReferencedElement(Element* aFrom, Element* aTo);
   void UnregisterFromReferencedElement(Element* aElement);
   nsSMILTimedElement* GetTimedElement(Element* aElement);
   void RegisterEventListener(Element* aElement);
   void UnregisterEventListener(Element* aElement);
-  nsEventListenerManager* GetEventListenerManager(Element* aElement,
-      nsIDOMEventGroup** aSystemGroup);
+  nsEventListenerManager* GetEventListenerManager(Element* aElement);
   void HandleEvent(nsIDOMEvent* aEvent);
   PRBool CheckEventDetail(nsIDOMEvent* aEvent);
   PRBool CheckRepeatEventDetail(nsIDOMEvent* aEvent);
   PRBool CheckAccessKeyEventDetail(nsIDOMEvent* aEvent);
   nsSMILTimeValue ConvertBetweenTimeContainers(const nsSMILTimeValue& aSrcTime,
                                       const nsSMILTimeContainer* aSrcContainer);
 
   nsSMILTimedElement*           mOwner;
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -836,94 +836,83 @@ nsXBLBinding::InstallEventHandlers()
     nsXBLPrototypeHandler* handlerChain = mPrototypeBinding->GetPrototypeHandlers();
 
     if (handlerChain) {
       nsEventListenerManager* manager =
         mBoundElement->GetListenerManager(PR_TRUE);
       if (!manager)
         return;
 
-      nsCOMPtr<nsIDOMEventGroup> systemEventGroup;
       PRBool isChromeDoc =
         nsContentUtils::IsChromeDoc(mBoundElement->GetOwnerDoc());
       PRBool isChromeBinding = mPrototypeBinding->IsChrome();
       nsXBLPrototypeHandler* curr;
       for (curr = handlerChain; curr; curr = curr->GetNextHandler()) {
         // Fetch the event type.
         nsCOMPtr<nsIAtom> eventAtom = curr->GetEventName();
         if (!eventAtom ||
             eventAtom == nsGkAtoms::keyup ||
             eventAtom == nsGkAtoms::keydown ||
             eventAtom == nsGkAtoms::keypress)
           continue;
 
-        // If this is a command, add it in the system event group, otherwise 
-        // add it to the standard event group.
-
-        // This is a weak ref. systemEventGroup above is already a
-        // strong ref, so we are guaranteed it will not go away.
-        nsIDOMEventGroup* eventGroup = nsnull;
-        if ((curr->GetType() & (NS_HANDLER_TYPE_XBL_COMMAND | NS_HANDLER_TYPE_SYSTEM)) &&
-            (isChromeBinding || mBoundElement->IsInNativeAnonymousSubtree())) {
-          if (!systemEventGroup)
-            manager->GetSystemEventGroupLM(getter_AddRefs(systemEventGroup));
-          eventGroup = systemEventGroup;
-        }
-
         nsXBLEventHandler* handler = curr->GetEventHandler();
         if (handler) {
           // Figure out if we're using capturing or not.
           PRInt32 flags = (curr->GetPhase() == NS_PHASE_CAPTURING) ?
             NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE;
 
+          // If this is a command, add it in the system event group
+          if ((curr->GetType() & (NS_HANDLER_TYPE_XBL_COMMAND |
+                                  NS_HANDLER_TYPE_SYSTEM)) &&
+              (isChromeBinding || mBoundElement->IsInNativeAnonymousSubtree())) {
+            flags |= NS_EVENT_FLAG_SYSTEM_EVENT;
+          }
+
           PRBool hasAllowUntrustedAttr = curr->HasAllowUntrustedAttr();
           if ((hasAllowUntrustedAttr && curr->AllowUntrustedEvents()) ||
               (!hasAllowUntrustedAttr && !isChromeDoc)) {
             flags |= NS_PRIV_EVENT_UNTRUSTED_PERMITTED;
           }
 
           manager->AddEventListenerByType(handler,
                                           nsDependentAtomString(eventAtom),
-                                          flags, eventGroup);
+                                          flags, nsnull);
         }
       }
 
       const nsCOMArray<nsXBLKeyEventHandler>* keyHandlers =
         mPrototypeBinding->GetKeyEventHandlers();
       PRInt32 i;
       for (i = 0; i < keyHandlers->Count(); ++i) {
         nsXBLKeyEventHandler* handler = keyHandlers->ObjectAt(i);
         handler->SetIsBoundToChrome(isChromeDoc);
 
         nsAutoString type;
         handler->GetEventName(type);
 
         // If this is a command, add it in the system event group, otherwise 
         // add it to the standard event group.
 
-        // This is a weak ref. systemEventGroup above is already a
-        // strong ref, so we are guaranteed it will not go away.
-        nsIDOMEventGroup* eventGroup = nsnull;
-        if ((handler->GetType() & (NS_HANDLER_TYPE_XBL_COMMAND | NS_HANDLER_TYPE_SYSTEM)) &&
-            (isChromeBinding || mBoundElement->IsInNativeAnonymousSubtree())) {
-          if (!systemEventGroup)
-            manager->GetSystemEventGroupLM(getter_AddRefs(systemEventGroup));
-          eventGroup = systemEventGroup;
-        }
-
         // Figure out if we're using capturing or not.
         PRInt32 flags = (handler->GetPhase() == NS_PHASE_CAPTURING) ?
           NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE;
 
+        if ((handler->GetType() & (NS_HANDLER_TYPE_XBL_COMMAND |
+                                   NS_HANDLER_TYPE_SYSTEM)) &&
+            (isChromeBinding || mBoundElement->IsInNativeAnonymousSubtree())) {
+          flags |= NS_EVENT_FLAG_SYSTEM_EVENT;
+        }
+
         // For key handlers we have to set NS_PRIV_EVENT_UNTRUSTED_PERMITTED flag.
         // Whether the handling of the event is allowed or not is handled in
         // nsXBLKeyEventHandler::HandleEvent
         flags |= NS_PRIV_EVENT_UNTRUSTED_PERMITTED;
 
-        manager->AddEventListenerByType(handler, type, flags, eventGroup);
+        manager->AddEventListenerByType(handler, type, flags, nsnull);
       }
     }
   }
 
   if (mNextBinding)
     mNextBinding->InstallEventHandlers();
 }
 
@@ -998,17 +987,16 @@ nsXBLBinding::UnhookEventHandlers()
   if (handlerChain) {
     nsEventListenerManager* manager =
       mBoundElement->GetListenerManager(PR_FALSE);
     if (!manager) {
       return;
     }
                                       
     PRBool isChromeBinding = mPrototypeBinding->IsChrome();
-    nsCOMPtr<nsIDOMEventGroup> systemEventGroup;
     nsXBLPrototypeHandler* curr;
     for (curr = handlerChain; curr; curr = curr->GetNextHandler()) {
       nsXBLEventHandler* handler = curr->GetCachedEventHandler();
       if (!handler) {
         continue;
       }
       
       nsCOMPtr<nsIAtom> eventAtom = curr->GetEventName();
@@ -1020,29 +1008,25 @@ nsXBLBinding::UnhookEventHandlers()
 
       // Figure out if we're using capturing or not.
       PRInt32 flags = (curr->GetPhase() == NS_PHASE_CAPTURING) ?
         NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE;
 
       // If this is a command, remove it from the system event group,
       // otherwise remove it from the standard event group.
 
-      // This is a weak ref. systemEventGroup above is already a
-      // strong ref, so we are guaranteed it will not go away.
-      nsIDOMEventGroup* eventGroup = nsnull;
-      if ((curr->GetType() & (NS_HANDLER_TYPE_XBL_COMMAND | NS_HANDLER_TYPE_SYSTEM)) &&
+      if ((curr->GetType() & (NS_HANDLER_TYPE_XBL_COMMAND |
+                              NS_HANDLER_TYPE_SYSTEM)) &&
           (isChromeBinding || mBoundElement->IsInNativeAnonymousSubtree())) {
-        if (!systemEventGroup)
-          manager->GetSystemEventGroupLM(getter_AddRefs(systemEventGroup));
-        eventGroup = systemEventGroup;
+        flags |= NS_EVENT_FLAG_SYSTEM_EVENT;
       }
 
       manager->RemoveEventListenerByType(handler,
                                          nsDependentAtomString(eventAtom),
-                                         flags, eventGroup);
+                                         flags, nsnull);
     }
 
     const nsCOMArray<nsXBLKeyEventHandler>* keyHandlers =
       mPrototypeBinding->GetKeyEventHandlers();
     PRInt32 i;
     for (i = 0; i < keyHandlers->Count(); ++i) {
       nsXBLKeyEventHandler* handler = keyHandlers->ObjectAt(i);
 
@@ -1051,27 +1035,22 @@ nsXBLBinding::UnhookEventHandlers()
 
       // Figure out if we're using capturing or not.
       PRInt32 flags = (handler->GetPhase() == NS_PHASE_CAPTURING) ?
         NS_EVENT_FLAG_CAPTURE : NS_EVENT_FLAG_BUBBLE;
 
       // If this is a command, remove it from the system event group, otherwise 
       // remove it from the standard event group.
 
-      // This is a weak ref. systemEventGroup above is already a
-      // strong ref, so we are guaranteed it will not go away.
-      nsIDOMEventGroup* eventGroup = nsnull;
       if ((handler->GetType() & (NS_HANDLER_TYPE_XBL_COMMAND | NS_HANDLER_TYPE_SYSTEM)) &&
           (isChromeBinding || mBoundElement->IsInNativeAnonymousSubtree())) {
-        if (!systemEventGroup)
-          manager->GetSystemEventGroupLM(getter_AddRefs(systemEventGroup));
-        eventGroup = systemEventGroup;
+        flags |= NS_EVENT_FLAG_SYSTEM_EVENT;
       }
 
-      manager->RemoveEventListenerByType(handler, type, flags, eventGroup);
+      manager->RemoveEventListenerByType(handler, type, flags, nsnull);
     }
   }
 }
 
 void
 nsXBLBinding::ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocument)
 {
   if (aOldDocument != aNewDocument) {
--- a/content/xbl/src/nsXBLService.cpp
+++ b/content/xbl/src/nsXBLService.cpp
@@ -714,45 +714,49 @@ nsXBLService::AttachGlobalKeyHandler(nsI
   // check if the receiver is a content node (not a document), and hook
   // it to the document if that is the case.
   nsCOMPtr<nsIDOMEventTarget> piTarget = aTarget;
   nsCOMPtr<nsIContent> contentNode(do_QueryInterface(aTarget));
   if (contentNode) {
     // Only attach if we're really in a document
     nsCOMPtr<nsIDocument> doc = contentNode->GetCurrentDoc();
     if (doc)
-      piTarget = do_QueryInterface(doc); // We're a XUL keyset. Attach to our document.
+      piTarget = doc; // We're a XUL keyset. Attach to our document.
   }
+
+  nsEventListenerManager* manager = piTarget->GetListenerManager(PR_TRUE);
     
-  if (!piTarget)
+  if (!piTarget || !manager)
     return NS_ERROR_FAILURE;
 
   // the listener already exists, so skip this
   if (contentNode && contentNode->GetProperty(nsGkAtoms::listener))
     return NS_OK;
     
   nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(contentNode));
 
   // Create the key handler
   nsXBLWindowKeyHandler* handler;
   NS_NewXBLWindowKeyHandler(elt, piTarget, &handler); // This addRef's
   if (!handler)
     return NS_ERROR_FAILURE;
 
   // listen to these events
-  nsCOMPtr<nsIDOMEventGroup> systemGroup;
-  piTarget->GetSystemEventGroup(getter_AddRefs(systemGroup));
-  nsCOMPtr<nsIDOM3EventTarget> target = do_QueryInterface(piTarget);
-
-  target->AddGroupedEventListener(NS_LITERAL_STRING("keydown"), handler,
-                                  PR_FALSE, systemGroup);
-  target->AddGroupedEventListener(NS_LITERAL_STRING("keyup"), handler, 
-                                  PR_FALSE, systemGroup);
-  target->AddGroupedEventListener(NS_LITERAL_STRING("keypress"), handler, 
-                                  PR_FALSE, systemGroup);
+  manager->AddEventListenerByType(handler, NS_LITERAL_STRING("keydown"),
+                                  NS_EVENT_FLAG_BUBBLE |
+                                  NS_EVENT_FLAG_SYSTEM_EVENT,
+                                  nsnull);
+  manager->AddEventListenerByType(handler, NS_LITERAL_STRING("keyup"),
+                                  NS_EVENT_FLAG_BUBBLE |
+                                  NS_EVENT_FLAG_SYSTEM_EVENT,
+                                  nsnull);
+  manager->AddEventListenerByType(handler, NS_LITERAL_STRING("keypress"),
+                                  NS_EVENT_FLAG_BUBBLE |
+                                  NS_EVENT_FLAG_SYSTEM_EVENT,
+                                  nsnull);
 
   if (contentNode)
     return contentNode->SetProperty(nsGkAtoms::listener, handler,
                                     nsPropertyTable::SupportsDtorFunc, PR_TRUE);
 
   // release the handler. The reference will be maintained by the event target,
   // and, if there is a content node, the property.
   NS_RELEASE(handler);
@@ -771,34 +775,39 @@ nsXBLService::DetachGlobalKeyHandler(nsI
   nsCOMPtr<nsIContent> contentNode(do_QueryInterface(aTarget));
   if (!contentNode) // detaching is only supported for content nodes
     return NS_ERROR_FAILURE;
 
   // Only attach if we're really in a document
   nsCOMPtr<nsIDocument> doc = contentNode->GetCurrentDoc();
   if (doc)
     piTarget = do_QueryInterface(doc);
-  if (!piTarget)
+
+  nsEventListenerManager* manager = piTarget->GetListenerManager(PR_TRUE);
+    
+  if (!piTarget || !manager)
     return NS_ERROR_FAILURE;
 
   nsIDOMEventListener* handler =
     static_cast<nsIDOMEventListener*>(contentNode->GetProperty(nsGkAtoms::listener));
   if (!handler)
     return NS_ERROR_FAILURE;
 
-  nsCOMPtr<nsIDOMEventGroup> systemGroup;
-  piTarget->GetSystemEventGroup(getter_AddRefs(systemGroup));
-  nsCOMPtr<nsIDOM3EventTarget> target = do_QueryInterface(piTarget);
-
-  target->RemoveGroupedEventListener(NS_LITERAL_STRING("keydown"), handler,
-                                     PR_FALSE, systemGroup);
-  target->RemoveGroupedEventListener(NS_LITERAL_STRING("keyup"), handler, 
-                                     PR_FALSE, systemGroup);
-  target->RemoveGroupedEventListener(NS_LITERAL_STRING("keypress"), handler, 
-                                     PR_FALSE, systemGroup);
+  manager->RemoveEventListenerByType(handler, NS_LITERAL_STRING("keydown"),
+                                     NS_EVENT_FLAG_BUBBLE |
+                                     NS_EVENT_FLAG_SYSTEM_EVENT,
+                                     nsnull);
+  manager->RemoveEventListenerByType(handler, NS_LITERAL_STRING("keyup"),
+                                     NS_EVENT_FLAG_BUBBLE |
+                                     NS_EVENT_FLAG_SYSTEM_EVENT,
+                                     nsnull);
+  manager->RemoveEventListenerByType(handler, NS_LITERAL_STRING("keypress"),
+                                     NS_EVENT_FLAG_BUBBLE |
+                                     NS_EVENT_FLAG_SYSTEM_EVENT,
+                                     nsnull);
 
   contentNode->DeleteProperty(nsGkAtoms::listener);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXBLService::Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* aSomeData)
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -2182,29 +2182,29 @@ static void
 PopupListenerPropertyDtor(void* aObject, nsIAtom* aPropertyName,
                           void* aPropertyValue, void* aData)
 {
   nsIDOMEventListener* listener =
     static_cast<nsIDOMEventListener*>(aPropertyValue);
   if (!listener) {
     return;
   }
-  nsCOMPtr<nsIDOM3EventTarget> target =
-    do_QueryInterface(static_cast<nsINode*>(aObject));
-  if (target) {
-    nsCOMPtr<nsIDOMEventGroup> systemGroup;
-    static_cast<nsIDOMEventTarget*>(aObject)->
-      GetSystemEventGroup(getter_AddRefs(systemGroup));
-    if (systemGroup) {
-      target->RemoveGroupedEventListener(NS_LITERAL_STRING("mousedown"),
-                                         listener, PR_FALSE, systemGroup);
-
-      target->RemoveGroupedEventListener(NS_LITERAL_STRING("contextmenu"),
-                                         listener, PR_FALSE, systemGroup);
-    }
+  nsEventListenerManager* manager = static_cast<nsINode*>(aObject)->
+    GetListenerManager(PR_FALSE);
+  if (manager) {
+    manager->RemoveEventListenerByType(listener,
+                                       NS_LITERAL_STRING("mousedown"),
+                                       NS_EVENT_FLAG_BUBBLE |
+                                       NS_EVENT_FLAG_SYSTEM_EVENT,
+                                       nsnull);
+    manager->RemoveEventListenerByType(listener,
+                                       NS_LITERAL_STRING("contextmenu"),
+                                       NS_EVENT_FLAG_BUBBLE |
+                                       NS_EVENT_FLAG_SYSTEM_EVENT,
+                                       nsnull);
   }
   NS_RELEASE(listener);
 }
 
 nsresult
 nsXULElement::AddPopupListener(nsIAtom* aName)
 {
     // Add a popup listener to the element
@@ -2216,41 +2216,43 @@ nsXULElement::AddPopupListener(nsIAtom* 
 
     nsCOMPtr<nsIDOMEventListener> popupListener =
         static_cast<nsIDOMEventListener*>(GetProperty(listenerAtom));
     if (popupListener) {
         // Popup listener is already installed.
         return NS_OK;
     }
 
-    nsCOMPtr<nsIDOMEventGroup> systemGroup;
-    GetSystemEventGroup(getter_AddRefs(systemGroup));
-    NS_ENSURE_STATE(systemGroup);
-
     nsresult rv = NS_NewXULPopupListener(this, isContext,
                                          getter_AddRefs(popupListener));
     if (NS_FAILED(rv))
         return rv;
 
     // Add the popup as a listener on this element.
-    nsCOMPtr<nsIDOM3EventTarget> target(do_QueryInterface(static_cast<nsIContent *>(this)));
-    NS_ENSURE_TRUE(target, NS_ERROR_FAILURE);
+    nsEventListenerManager* manager = GetListenerManager(PR_TRUE);
+    NS_ENSURE_TRUE(manager, NS_ERROR_FAILURE);
     rv = SetProperty(listenerAtom, popupListener, PopupListenerPropertyDtor,
                      PR_TRUE);
     NS_ENSURE_SUCCESS(rv, rv);
     // Want the property to have a reference to the listener.
     nsIDOMEventListener* listener = nsnull;
     popupListener.swap(listener);
 
     if (isContext) {
-      target->AddGroupedEventListener(NS_LITERAL_STRING("contextmenu"),
-                                      listener, PR_FALSE, systemGroup);
+      manager->AddEventListenerByType(listener,
+                                      NS_LITERAL_STRING("contextmenu"),
+                                      NS_EVENT_FLAG_BUBBLE |
+                                      NS_EVENT_FLAG_SYSTEM_EVENT,
+                                      nsnull);
     } else {
-      target->AddGroupedEventListener(NS_LITERAL_STRING("mousedown"),
-                                      listener, PR_FALSE, systemGroup);
+      manager->AddEventListenerByType(listener,
+                                      NS_LITERAL_STRING("mousedown"),
+                                      NS_EVENT_FLAG_BUBBLE |
+                                      NS_EVENT_FLAG_SYSTEM_EVENT,
+                                      nsnull);
     }
     return NS_OK;
 }
 
 nsEventStates
 nsXULElement::IntrinsicState() const
 {
     nsEventStates state = nsStyledElement::IntrinsicState();
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -7360,24 +7360,16 @@ nsGlobalWindow::GetListenerManager(PRBoo
   if (!mListenerManager && aCreateIfNotFound) {
     mListenerManager =
       new nsEventListenerManager(static_cast<nsIDOMEventTarget*>(this));
   }
 
   return mListenerManager;
 }
 
-nsresult
-nsGlobalWindow::GetSystemEventGroup(nsIDOMEventGroup **aGroup)
-{
-  nsEventListenerManager* manager = GetListenerManager(PR_TRUE);
-  NS_ENSURE_STATE(manager);
-  return manager->GetSystemEventGroupLM(aGroup);
-}
-
 nsIScriptContext*
 nsGlobalWindow::GetContextForEventHandlers(nsresult* aRv)
 {
   nsIScriptContext* scx = GetContext();
   *aRv = scx ? NS_OK : NS_ERROR_UNEXPECTED;
   return scx;
 }
 
--- a/dom/base/nsWindowRoot.cpp
+++ b/dom/base/nsWindowRoot.cpp
@@ -212,24 +212,16 @@ nsWindowRoot::GetListenerManager(PRBool 
   if (!mListenerManager && aCreateIfNotFound) {
     mListenerManager =
       new nsEventListenerManager(static_cast<nsIDOMEventTarget*>(this));
   }
 
   return mListenerManager;
 }
 
-nsresult
-nsWindowRoot::GetSystemEventGroup(nsIDOMEventGroup **aGroup)
-{
-  nsEventListenerManager* manager = GetListenerManager(PR_TRUE);
-  NS_ENSURE_STATE(manager);
-  return manager->GetSystemEventGroupLM(aGroup);
-}
-
 nsIScriptContext*
 nsWindowRoot::GetContextForEventHandlers(nsresult* aRv)
 {
   *aRv = NS_OK;
   return nsnull;
 }
 
 nsresult
--- a/dom/interfaces/events/nsIDOMEventTarget.idl
+++ b/dom/interfaces/events/nsIDOMEventTarget.idl
@@ -255,21 +255,16 @@ interface nsIDOMEventTarget : nsISupport
   /**
    * Remove event listener for nsIID.
    */
   [noscript, nostdcall]
   void RemoveEventListenerByIID(in nsIDOMEventListener aListener,
                                 in nsIIDRef aIID);
 
   /**
-   * Get the system event group.
-   */
-  [noscript, nostdcall] nsIDOMEventGroup GetSystemEventGroup();
-
-  /**
    * Get the script context in which the event handlers should be run.
    * May return null.
    * @note Caller *must* check the value of aRv.
    */
   [notxpcom, nostdcall]
   nsIScriptContext GetContextForEventHandlers(out nsresult aRv);
 
   /**
--- a/dom/src/threads/nsDOMWorkerMessageHandler.cpp
+++ b/dom/src/threads/nsDOMWorkerMessageHandler.cpp
@@ -419,23 +419,16 @@ nsDOMWorkerMessageHandler::AddEventListe
 nsresult
 nsDOMWorkerMessageHandler::RemoveEventListenerByIID(nsIDOMEventListener *aListener,
                                                     const nsIID & aIID)
 {
   NS_ERROR("Should not be called");
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
-nsresult
-nsDOMWorkerMessageHandler::GetSystemEventGroup(nsIDOMEventGroup **_retval)
-{
-  NS_ERROR("Should not be called");
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
 nsIScriptContext*
 nsDOMWorkerMessageHandler::GetContextForEventHandlers(nsresult *aRv)
 {
   NS_ERROR("Should not be called");
   *aRv = NS_ERROR_NOT_IMPLEMENTED;
   return nsnull;
 }
 
--- a/dom/src/threads/nsDOMWorkerMessageHandler.h
+++ b/dom/src/threads/nsDOMWorkerMessageHandler.h
@@ -163,14 +163,13 @@ private:
   virtual nsIDOMEventTarget * GetTargetForEventTargetChain(void) { return _to GetTargetForEventTargetChain(); } \
   virtual nsresult PreHandleEvent(nsEventChainPreVisitor & aVisitor) { return _to PreHandleEvent(aVisitor); } \
   virtual nsresult WillHandleEvent(nsEventChainPostVisitor & aVisitor) { return _to WillHandleEvent(aVisitor); } \
   virtual nsresult PostHandleEvent(nsEventChainPostVisitor & aVisitor) { return _to PostHandleEvent(aVisitor); } \
   virtual nsresult DispatchDOMEvent(nsEvent *aEvent, nsIDOMEvent *aDOMEvent, nsPresContext *aPresContext, nsEventStatus *aEventStatus) { return _to DispatchDOMEvent(aEvent, aDOMEvent, aPresContext, aEventStatus); } \
   virtual nsEventListenerManager * GetListenerManager(PRBool aMayCreate) { return _to GetListenerManager(aMayCreate); } \
   virtual nsresult AddEventListenerByIID(nsIDOMEventListener *aListener, const nsIID & aIID) { return _to AddEventListenerByIID(aListener, aIID); } \
   virtual nsresult RemoveEventListenerByIID(nsIDOMEventListener *aListener, const nsIID & aIID) { return _to RemoveEventListenerByIID(aListener, aIID); } \
-  virtual nsresult GetSystemEventGroup(nsIDOMEventGroup **_retval NS_OUTPARAM) { return _to GetSystemEventGroup(_retval); } \
   virtual nsIScriptContext * GetContextForEventHandlers(nsresult *aRv NS_OUTPARAM) { return _to GetContextForEventHandlers(aRv); } \
   virtual JSContext * GetJSContextForEventHandlers(void) { return _to GetJSContextForEventHandlers(); } 
 
 
 #endif /* __NSDOMWORKERMESSAGEHANDLER_H__ */
--- a/editor/libeditor/base/nsEditorEventListener.cpp
+++ b/editor/libeditor/base/nsEditorEventListener.cpp
@@ -125,51 +125,59 @@ nsEditorEventListener::InstallToEditor()
   NS_PRECONDITION(mEditor, "The caller must set mEditor");
 
   nsCOMPtr<nsIDOMEventTarget> piTarget = mEditor->GetDOMEventTarget();
   NS_ENSURE_TRUE(piTarget, NS_ERROR_FAILURE);
 
   nsresult rv;
 
   // register the event listeners with the listener manager
-  nsCOMPtr<nsIDOMEventGroup> sysGroup;
-  piTarget->GetSystemEventGroup(getter_AddRefs(sysGroup));
-  NS_ENSURE_STATE(sysGroup);
   nsEventListenerManager* elmP = piTarget->GetListenerManager(PR_TRUE);
   NS_ENSURE_STATE(elmP);
 
   nsCOMPtr<nsIDOMEventListener> listenerBase;
   CallQueryInterface(this, getter_AddRefs(listenerBase));
 
   rv = elmP->AddEventListenerByType(listenerBase,
                                     NS_LITERAL_STRING("keypress"),
                                     NS_EVENT_FLAG_BUBBLE |
-                                    NS_PRIV_EVENT_UNTRUSTED_PERMITTED,
-                                    sysGroup);
+                                    NS_PRIV_EVENT_UNTRUSTED_PERMITTED |
+                                    NS_EVENT_FLAG_SYSTEM_EVENT,
+                                    nsnull);
   NS_ENSURE_SUCCESS(rv, rv);
   // See bug 455215, we cannot use the standard dragstart event yet
   rv = elmP->AddEventListenerByType(listenerBase,
                                     NS_LITERAL_STRING("draggesture"),
-                                    NS_EVENT_FLAG_BUBBLE, sysGroup);
+                                    NS_EVENT_FLAG_BUBBLE |
+                                    NS_EVENT_FLAG_SYSTEM_EVENT,
+                                    nsnull);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = elmP->AddEventListenerByType(listenerBase,
                                     NS_LITERAL_STRING("dragenter"),
-                                    NS_EVENT_FLAG_BUBBLE, sysGroup);
+                                    NS_EVENT_FLAG_BUBBLE |
+                                    NS_EVENT_FLAG_SYSTEM_EVENT,
+                                    nsnull);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = elmP->AddEventListenerByType(listenerBase,
                                     NS_LITERAL_STRING("dragover"),
-                                    NS_EVENT_FLAG_BUBBLE, sysGroup);
+                                    NS_EVENT_FLAG_BUBBLE |
+                                    NS_EVENT_FLAG_SYSTEM_EVENT,
+                                    nsnull);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = elmP->AddEventListenerByType(listenerBase,
                                     NS_LITERAL_STRING("dragexit"),
-                                    NS_EVENT_FLAG_BUBBLE, sysGroup);
+                                    NS_EVENT_FLAG_BUBBLE |
+                                    NS_EVENT_FLAG_SYSTEM_EVENT,
+                                    nsnull);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = elmP->AddEventListenerByType(listenerBase,
                                     NS_LITERAL_STRING("drop"),
-                                    NS_EVENT_FLAG_BUBBLE, sysGroup);
+                                    NS_EVENT_FLAG_BUBBLE |
+                                    NS_EVENT_FLAG_SYSTEM_EVENT,
+                                    nsnull);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = elmP->AddEventListenerByIID(listenerBase,
                                    NS_GET_IID(nsIDOMMouseListener),
                                    NS_EVENT_FLAG_CAPTURE);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Focus event doesn't bubble so adding the listener to capturing phase.
@@ -208,43 +216,50 @@ nsEditorEventListener::UninstallFromEdit
     return;
   }
 
   nsEventListenerManager* elmP =
     piTarget->GetListenerManager(PR_TRUE);
   if (!elmP) {
     return;
   }
-  nsCOMPtr<nsIDOMEventGroup> sysGroup;
-  piTarget->GetSystemEventGroup(getter_AddRefs(sysGroup));
-  if (!sysGroup) {
-    return;
-  }
 
   nsCOMPtr<nsIDOMEventListener> listenerBase;
   CallQueryInterface(this, getter_AddRefs(listenerBase));
 
   elmP->RemoveEventListenerByType(listenerBase,
                                   NS_LITERAL_STRING("keypress"),
-                                  NS_EVENT_FLAG_BUBBLE, sysGroup);
+                                  NS_EVENT_FLAG_BUBBLE |
+                                  NS_EVENT_FLAG_SYSTEM_EVENT,
+                                  nsnull);
   elmP->RemoveEventListenerByType(listenerBase,
                                   NS_LITERAL_STRING("draggesture"),
-                                  NS_EVENT_FLAG_BUBBLE, sysGroup);
+                                  NS_EVENT_FLAG_BUBBLE |
+                                  NS_EVENT_FLAG_SYSTEM_EVENT,
+                                  nsnull);
   elmP->RemoveEventListenerByType(listenerBase,
                                   NS_LITERAL_STRING("dragenter"),
-                                  NS_EVENT_FLAG_BUBBLE, sysGroup);
+                                  NS_EVENT_FLAG_BUBBLE |
+                                  NS_EVENT_FLAG_SYSTEM_EVENT,
+                                  nsnull);
   elmP->RemoveEventListenerByType(listenerBase,
                                   NS_LITERAL_STRING("dragover"),
-                                  NS_EVENT_FLAG_BUBBLE, sysGroup);
+                                  NS_EVENT_FLAG_BUBBLE |
+                                  NS_EVENT_FLAG_SYSTEM_EVENT,
+                                  nsnull);
   elmP->RemoveEventListenerByType(listenerBase,
                                   NS_LITERAL_STRING("dragexit"),
-                                  NS_EVENT_FLAG_BUBBLE, sysGroup);
+                                  NS_EVENT_FLAG_BUBBLE |
+                                  NS_EVENT_FLAG_SYSTEM_EVENT,
+                                  nsnull);
   elmP->RemoveEventListenerByType(listenerBase,
                                   NS_LITERAL_STRING("drop"),
-                                  NS_EVENT_FLAG_BUBBLE, sysGroup);
+                                  NS_EVENT_FLAG_BUBBLE |
+                                  NS_EVENT_FLAG_SYSTEM_EVENT,
+                                  nsnull);
 
   elmP->RemoveEventListenerByIID(listenerBase,
                                  NS_GET_IID(nsIDOMMouseListener),
                                  NS_EVENT_FLAG_CAPTURE);
 
   elmP->RemoveEventListenerByIID(listenerBase,
                                  NS_GET_IID(nsIDOMFocusListener),
                                  NS_EVENT_FLAG_CAPTURE);
--- a/editor/libeditor/html/tests/test_contenteditable_text_input_handling.html
+++ b/editor/libeditor/html/tests/test_contenteditable_text_input_handling.html
@@ -32,22 +32,19 @@ function runTests()
              getService(Components.interfaces.nsIFocusManager);
 
   var listener = {
     handleEvent: function _hv(aEvent)
     {
       aEvent.preventDefault(); // prevent the browser default behavior
     }
   };
-  var systemGroup =
-    Components.classes["@mozilla.org/eventlistenerservice;1"].
-      getService(Components.interfaces.nsIEventListenerService).
-      systemEventGroup;
-  window.QueryInterface(Components.interfaces.nsIDOM3EventTarget);
-  window.addGroupedEventListener("keypress", listener, false, systemGroup);
+  var els = Components.classes["@mozilla.org/eventlistenerservice;1"].
+    getService(Components.interfaces.nsIEventListenerService);
+  els.addSystemEventListener(window, "keypress", listener, false);
 
   var staticContent = document.getElementById("static");
   staticContent._defaultValue = getTextValue(staticContent);
   staticContent._isFocusable = false;
   staticContent._isEditable = false;
   staticContent._isContentEditable = false;
   staticContent._description = "non-editable p element";
   var inputInStatic = document.getElementById("inputInStatic");
@@ -319,17 +316,17 @@ function runTests()
   }
 
   testTextInput(inputInStatic);
   testTextInput(textareaInStatic);
   testTextInput(editor);
   testTextInput(inputInEditor);
   testTextInput(textareaInEditor);
 
-  window.removeGroupedEventListener("keypress", listener, false, systemGroup);
+  els.removeSystemEventListener(window, "keypress", listener, false);
 
   SimpleTest.finish();
 }
 
 </script>
 </body>
 
 </html>
--- a/editor/libeditor/html/tests/test_htmleditor_keyevent_handling.html
+++ b/editor/libeditor/html/tests/test_htmleditor_keyevent_handling.html
@@ -80,23 +80,18 @@ function runTests()
            " was consumed already, so, we cannot test the editor behavior actually");
       aPreventedOnBubbling = true;
     }
 
     is(bubblingPhase.prevented, aPreventedOnBubbling,
        getDesciption(aPreventedOnBubbling) + "prevented on bubbling phase");
   }
 
-  var systemGroup =
-    Components.classes["@mozilla.org/eventlistenerservice;1"].
-      getService(Components.interfaces.nsIEventListenerService).
-      systemEventGroup;
-  window.QueryInterface(Components.interfaces.nsIDOM3EventTarget);
-  window.addGroupedEventListener("keypress", listener, true, systemGroup);
-  window.addGroupedEventListener("keypress", listener, false, systemGroup);
+  SpecialPowers.addSystemEventListener(window, "keypress", listener, true);
+  SpecialPowers.addSystemEventListener(window, "keypress", listener, false);
 
   function doTest(aElement, aDescription,
                   aIsReadonly, aIsTabbable, aIsPlaintext)
   {
     function reset(aText)
     {
       capturingPhase.fired = false;
       capturingPhase.prevented = false;
@@ -655,18 +650,18 @@ function runTests()
 
   // readonly, plaintext and non-tabbable
   editor.flags = (flags | nsIPlaintextEditor.eEditorPlaintextMask |
                           nsIPlaintextEditor.eEditorReadonlyMask) &
                  ~(nsIPlaintextEditor.eEditorAllowInteraction);
   doTest(htmlEditor, "readonly and non-tabbable HTML editor but plaintext mode",
          true, false, true);
 
-  window.removeGroupedEventListener("keypress", listener, true, systemGroup);
-  window.removeGroupedEventListener("keypress", listener, false, systemGroup);
+  SpecialPowers.removeSystemEventListener(window, "keypress", listener, true);
+  SpecialPowers.removeSystemEventListener(window, "keypress", listener, false);
 
   SimpleTest.finish();
 }
 
 </script>
 </body>
 
 </html>
--- a/editor/libeditor/text/tests/test_bug569988.html
+++ b/editor/libeditor/text/tests/test_bug569988.html
@@ -55,34 +55,28 @@ function onPromptLoad(subject, topic, da
   gPromptInput.focus();
 }
 
 function onPromptFocus() {
   ok(true, "onPromptFocus is called");
   netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
   gPromptInput.removeEventListener("focus", onPromptFocus, false);
 
-  var systemGroup =
-    Components.classes["@mozilla.org/eventlistenerservice;1"].
-      getService(Components.interfaces.nsIEventListenerService).
-      systemEventGroup;
-  gPromptInput.QueryInterface(Components.interfaces.nsIDOM3EventTarget);
   var listener = {
     handleEvent: function _hv(aEvent)
     {
-      netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
       var isPrevented = aEvent.getPreventDefault();
       ok(!isPrevented, "ESC key event is prevented by editor");
-      gPromptInput.removeGroupedEventListener("keypress", listener, false,
-                                              systemGroup);
+      SpecialPowers.removeSystemEventListener(gPromptInput, "keypress",
+                                              listener, false);
       SimpleTest.finish();
     }
   };
-  gPromptInput.addGroupedEventListener("keypress", listener, false,
-                                       systemGroup);
+  SpecialPowers.addSystemEventListener(gPromptInput, "keypress", listener,
+                                       false);
   ok(true, "sending key");
   synthesizeKey("VK_ESCAPE", { }, gPromptInput.ownerDocument.defaultView);
 }
 
 </script>
 </pre>
 </body>
 </html>
--- a/editor/libeditor/text/tests/test_texteditor_keyevent_handling.html
+++ b/editor/libeditor/text/tests/test_texteditor_keyevent_handling.html
@@ -85,24 +85,21 @@ function runTests()
            " was consumed already, so, we cannot test the editor behavior actually");
       aPreventedOnBubbling = true;
     }
 
     is(bubblingPhase.prevented, aPreventedOnBubbling,
        getDesciption(aPreventedOnBubbling) + "prevented on bubbling phase");
   }
 
-  var systemGroup =
-    Components.classes["@mozilla.org/eventlistenerservice;1"].
-      getService(Components.interfaces.nsIEventListenerService).
-      systemEventGroup;
   var parentElement = document.getElementById("display");
-  parentElement.QueryInterface(Components.interfaces.nsIDOM3EventTarget);
-  parentElement.addGroupedEventListener("keypress", listener, true, systemGroup);
-  parentElement.addGroupedEventListener("keypress", listener, false, systemGroup);
+  SpecialPowers.addSystemEventListener(parentElement, "keypress", listener,
+                                       true);
+  SpecialPowers.addSystemEventListener(parentElement, "keypress", listener,
+                                       false);
 
   function doTest(aElement, aDescription, aIsSingleLine, aIsReadonly,
                   aIsTabbable)
   {
     function reset(aText)
     {
       capturingPhase.fired = false;
       capturingPhase.prevented = false;
@@ -402,18 +399,20 @@ function runTests()
                            nsIPlaintextEditor.eEditorAllowInteraction);
   doTest(textarea, "non-tabbable <textarea>", false, false, false);
 
   textarea.setAttribute("readonly", "readonly");
   doTest(textarea, "non-tabbable <textarea readonly>", false, true, false);
 
   editor.flags = flags;
 
-  parentElement.removeGroupedEventListener("keypress", listener, true, systemGroup);
-  parentElement.removeGroupedEventListener("keypress", listener, false, systemGroup);
+  SpecialPowers.removeSystemEventListener(parentElement, "keypress", listener,
+                                          true);
+  SpecialPowers.removeSystemEventListener(parentElement, "keypress", listener,
+                                          false);
 
   SimpleTest.finish();
 }
 
 </script>
 </body>
 
 </html>
--- a/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp
+++ b/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp
@@ -883,28 +883,28 @@ nsDocShellTreeOwner::AddChromeListeners(
         rv = NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
   // register dragover and drop event listeners with the listener manager
   nsCOMPtr<nsIDOMEventTarget> target;
   GetDOMEventTarget(mWebBrowser, getter_AddRefs(target));
 
-  nsCOMPtr<nsIDOMEventGroup> sysGroup;
-  target->GetSystemEventGroup(getter_AddRefs(sysGroup));
   nsEventListenerManager* elmP = target->GetListenerManager(PR_TRUE);
-  if (sysGroup && elmP)
+  if (elmP)
   {
     rv = elmP->AddEventListenerByType(this, NS_LITERAL_STRING("dragover"),
-                                      NS_EVENT_FLAG_BUBBLE,
-                                      sysGroup);
+                                      NS_EVENT_FLAG_BUBBLE |
+                                      NS_EVENT_FLAG_SYSTEM_EVENT,
+                                      nsnull);
     NS_ENSURE_SUCCESS(rv, rv);
     rv = elmP->AddEventListenerByType(this, NS_LITERAL_STRING("drop"),
-                                      NS_EVENT_FLAG_BUBBLE,
-                                      sysGroup);
+                                      NS_EVENT_FLAG_BUBBLE |
+                                      NS_EVENT_FLAG_SYSTEM_EVENT,
+                                      nsnull);
   }
 
   return rv;
   
 } // AddChromeListeners
 
 
 NS_IMETHODIMP
@@ -919,27 +919,27 @@ nsDocShellTreeOwner::RemoveChromeListene
     NS_RELEASE(mChromeContextMenuListener);
   }
 
   nsCOMPtr<nsIDOMEventTarget> piTarget;
   GetDOMEventTarget(mWebBrowser, getter_AddRefs(piTarget));
   if (!piTarget)
     return NS_OK;
 
-  nsCOMPtr<nsIDOMEventGroup> sysGroup;
-  piTarget->GetSystemEventGroup(getter_AddRefs(sysGroup));
   nsEventListenerManager* elmP = piTarget->GetListenerManager(PR_TRUE);
-  if (sysGroup && elmP)
+  if (elmP)
   {
     elmP->RemoveEventListenerByType(this, NS_LITERAL_STRING("dragover"),
-                                    NS_EVENT_FLAG_BUBBLE,
-                                    sysGroup);
+                                    NS_EVENT_FLAG_BUBBLE |
+                                    NS_EVENT_FLAG_SYSTEM_EVENT,
+                                    nsnull);
     elmP->RemoveEventListenerByType(this, NS_LITERAL_STRING("drop"),
-                                    NS_EVENT_FLAG_BUBBLE,
-                                    sysGroup);
+                                    NS_EVENT_FLAG_BUBBLE |
+                                    NS_EVENT_FLAG_SYSTEM_EVENT,
+                                    nsnull);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShellTreeOwner::HandleEvent(nsIDOMEvent* aEvent)
 {
--- a/layout/forms/nsFileControlFrame.cpp
+++ b/layout/forms/nsFileControlFrame.cpp
@@ -69,16 +69,17 @@
 #include "nsNodeInfoManager.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsContentUtils.h"
 #include "nsDisplayList.h"
 #include "nsIDOMNSUIEvent.h"
 #include "nsIDOMEventGroup.h"
 #include "nsIDOM3EventTarget.h"
 #include "nsIDOMHTMLInputElement.h"
+#include "nsEventListenerManager.h"
 #ifdef ACCESSIBILITY
 #include "nsAccessibilityService.h"
 #endif
 
 #include "nsInterfaceHashtable.h"
 #include "nsURIHashKey.h"
 #include "nsILocalFile.h"
 #include "nsNetCID.h"
@@ -146,37 +147,33 @@ nsFileControlFrame::DestroyFrom(nsIFrame
                                     mMouseListener, PR_FALSE);
     dragTarget->RemoveEventListener(NS_LITERAL_STRING("dragover"),
                                     mMouseListener, PR_FALSE);
   }
 
   // remove mMouseListener as a mouse event listener (bug 40533, bug 355931)
   NS_NAMED_LITERAL_STRING(click, "click");
 
-  nsCOMPtr<nsIDOMEventGroup> systemGroup;
-  mContent->GetSystemEventGroup(getter_AddRefs(systemGroup));
-
-  nsCOMPtr<nsIDOM3EventTarget> dom3Capture = do_QueryInterface(mCapture);
-  if (dom3Capture) {
-    nsContentUtils::DestroyAnonymousContent(&mCapture);
-  }
+  nsContentUtils::DestroyAnonymousContent(&mCapture);
 
-  nsCOMPtr<nsIDOM3EventTarget> dom3Browse = do_QueryInterface(mBrowse);
-  if (dom3Browse) {
-    dom3Browse->RemoveGroupedEventListener(click, mMouseListener, PR_FALSE,
-                                           systemGroup);
-    nsContentUtils::DestroyAnonymousContent(&mBrowse);
+  nsEventListenerManager* elm = mBrowse->GetListenerManager(PR_FALSE);
+  if (elm) {
+    elm->RemoveEventListenerByType(mMouseListener, click,
+                                   NS_EVENT_FLAG_BUBBLE |
+                                   NS_EVENT_FLAG_SYSTEM_EVENT, nsnull);
   }
-  nsCOMPtr<nsIDOM3EventTarget> dom3TextContent =
-    do_QueryInterface(mTextContent);
-  if (dom3TextContent) {
-    dom3TextContent->RemoveGroupedEventListener(click, mMouseListener, PR_FALSE,
-                                                systemGroup);
-    nsContentUtils::DestroyAnonymousContent(&mTextContent);
+  nsContentUtils::DestroyAnonymousContent(&mBrowse);
+
+  elm = mTextContent->GetListenerManager(PR_FALSE);
+  if (elm) {
+    elm->RemoveEventListenerByType(mMouseListener, click,
+                                   NS_EVENT_FLAG_BUBBLE |
+                                   NS_EVENT_FLAG_SYSTEM_EVENT, nsnull);
   }
+  nsContentUtils::DestroyAnonymousContent(&mTextContent);
 
   mCaptureMouseListener->ForgetFrame();
   mMouseListener->ForgetFrame();
   nsBlockFrame::DestroyFrom(aDestructRoot);
 }
 
 struct CaptureCallbackData {
   nsICapturePicker* picker;
@@ -275,25 +272,24 @@ nsFileControlFrame::CreateAnonymousConte
   nsCOMPtr<nsIDOMEventTarget> dragTarget = do_QueryInterface(mContent);
   NS_ENSURE_STATE(dragTarget);
   dragTarget->AddEventListener(NS_LITERAL_STRING("drop"),
                                mMouseListener, PR_FALSE);
   dragTarget->AddEventListener(NS_LITERAL_STRING("dragover"),
                                mMouseListener, PR_FALSE);
 
   NS_NAMED_LITERAL_STRING(click, "click");
-  nsCOMPtr<nsIDOMEventGroup> systemGroup;
-  mContent->GetSystemEventGroup(getter_AddRefs(systemGroup));
-  nsCOMPtr<nsIDOM3EventTarget> dom3TextContent =
-    do_QueryInterface(mTextContent);
-  NS_ENSURE_STATE(dom3TextContent);
+  nsEventListenerManager* manager = mTextContent->GetListenerManager(PR_TRUE);
+  NS_ENSURE_STATE(manager);
   // Register as an event listener of the textbox
   // to open file dialog on mouse click
-  dom3TextContent->AddGroupedEventListener(click, mMouseListener, PR_FALSE,
-                                           systemGroup);
+  manager->AddEventListenerByType(mMouseListener, click,
+                                  NS_EVENT_FLAG_BUBBLE |
+                                  NS_EVENT_FLAG_SYSTEM_EVENT,
+                                  nsnull);
 
   // Create the browse button
   nodeInfo = doc->NodeInfoManager()->GetNodeInfo(nsGkAtoms::input, nsnull,
                                                  kNameSpaceID_XHTML,
                                                  nsIDOMNode::ELEMENT_NODE);
   NS_NewHTMLElement(getter_AddRefs(mBrowse), nodeInfo.forget(),
                     dom::NOT_FROM_PARSER);
   if (!mBrowse)
@@ -353,22 +349,26 @@ nsFileControlFrame::CreateAnonymousConte
   }
 
   if (!aElements.AppendElement(mBrowse))
     return NS_ERROR_OUT_OF_MEMORY;
 
   if (mCapture && !aElements.AppendElement(mCapture))
     return NS_ERROR_OUT_OF_MEMORY;
 
-  nsCOMPtr<nsIDOM3EventTarget> dom3Browse = do_QueryInterface(mBrowse);
-  NS_ENSURE_STATE(dom3Browse);
+  nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mBrowse);
+  NS_ENSURE_STATE(target);
+  manager = target->GetListenerManager(PR_TRUE);
+  NS_ENSURE_STATE(manager);
   // Register as an event listener of the button
   // to open file dialog on mouse click
-  dom3Browse->AddGroupedEventListener(click, mMouseListener, PR_FALSE,
-                                      systemGroup);
+  manager->AddEventListenerByType(mMouseListener, click,
+                                  NS_EVENT_FLAG_BUBBLE |
+                                  NS_EVENT_FLAG_SYSTEM_EVENT,
+                                  nsnull);
 
   SyncAttr(kNameSpaceID_None, nsGkAtoms::size,     SYNC_TEXT);
   SyncDisabledState();
 
   return NS_OK;
 }
 
 void
--- a/testing/mochitest/specialpowers/content/specialpowers.js
+++ b/testing/mochitest/specialpowers/content/specialpowers.js
@@ -285,16 +285,27 @@ SpecialPowers.prototype = {
 
   executeSoon: function(aFunc) {
     var tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
     tm.mainThread.dispatch({
       run: function() {
         aFunc();
       }
     }, Ci.nsIThread.DISPATCH_NORMAL);
+  },
+
+  addSystemEventListener: function(target, type, listener, useCapture) {
+    Components.classes["@mozilla.org/eventlistenerservice;1"].
+      getService(Components.interfaces.nsIEventListenerService).
+      addSystemEventListener(target, type, listener, useCapture);
+  },
+  removeSystemEventListener: function(target, type, listener, useCapture) {
+    Components.classes["@mozilla.org/eventlistenerservice;1"].
+      getService(Components.interfaces.nsIEventListenerService).
+      removeSystemEventListener(target, type, listener, useCapture);
   }
 };
 
 // Expose everything but internal APIs (starting with underscores) to
 // web content.
 SpecialPowers.prototype.__exposedProps__ = {};
 for each (i in Object.keys(SpecialPowers.prototype).filter(function(v) {return v.charAt(0) != "_";})) {
   SpecialPowers.prototype.__exposedProps__[i] = "r";