Bug 734057 - Make nsDOMEventTargetHelper to not have strong pointer to window, r=jst,bent
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Tue, 13 Mar 2012 02:56:07 +0200
changeset 88923 0c35057e2bb41d3440942338b5ad3c7d9c2a3345
parent 88922 dfcb11712ec227cc6ec259acc8646b98f81f8d00
child 88924 483fb2f1da11019ea8a5791c9cba384de25afa46
push id7074
push usermak77@bonardo.net
push dateTue, 13 Mar 2012 13:49:46 +0000
treeherdermozilla-inbound@d87ad51531b5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjst, bent
bugs734057
milestone13.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 734057 - Make nsDOMEventTargetHelper to not have strong pointer to window, r=jst,bent
content/base/src/nsDOMFileReader.cpp
content/base/src/nsEventSource.cpp
content/base/src/nsEventSource.h
content/base/src/nsWebSocket.cpp
content/base/src/nsWebSocket.h
content/base/src/nsXMLHttpRequest.cpp
content/base/src/nsXMLHttpRequest.h
content/events/src/nsDOMEventTargetHelper.cpp
content/events/src/nsDOMEventTargetHelper.h
dom/base/DOMRequest.cpp
dom/base/Navigator.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/battery/BatteryManager.cpp
dom/battery/BatteryManager.h
dom/indexedDB/IDBCursor.cpp
dom/indexedDB/IDBCursor.h
dom/indexedDB/IDBDatabase.cpp
dom/indexedDB/IDBDatabase.h
dom/indexedDB/IDBFactory.cpp
dom/indexedDB/IDBRequest.cpp
dom/indexedDB/IDBRequest.h
dom/indexedDB/IDBTransaction.cpp
dom/indexedDB/IDBWrapperCache.h
dom/network/src/Connection.cpp
dom/network/src/Connection.h
dom/sms/interfaces/nsISmsRequestManager.idl
dom/sms/src/SmsManager.cpp
dom/sms/src/SmsManager.h
dom/sms/src/SmsRequest.cpp
dom/sms/src/SmsRequest.h
dom/sms/src/SmsRequestManager.cpp
dom/src/notification/nsDesktopNotification.cpp
dom/src/notification/nsDesktopNotification.h
dom/src/offline/nsDOMOfflineResourceList.cpp
dom/src/offline/nsDOMOfflineResourceList.h
--- a/content/base/src/nsDOMFileReader.cpp
+++ b/content/base/src/nsDOMFileReader.cpp
@@ -194,31 +194,29 @@ NS_IMPL_EVENT_HANDLER(nsDOMFileReader, l
 NS_IMPL_FORWARD_EVENT_HANDLER(nsDOMFileReader, abort, FileIOObject)
 NS_IMPL_FORWARD_EVENT_HANDLER(nsDOMFileReader, progress, FileIOObject)
 NS_IMPL_FORWARD_EVENT_HANDLER(nsDOMFileReader, error, FileIOObject)
 
 NS_IMETHODIMP
 nsDOMFileReader::Initialize(nsISupports* aOwner, JSContext* cx, JSObject* obj,
                             PRUint32 argc, jsval *argv)
 {
-  mOwner = do_QueryInterface(aOwner);
-  if (!mOwner) {
+  nsCOMPtr<nsPIDOMWindow> owner = do_QueryInterface(aOwner);
+  if (!owner) {
     NS_WARNING("Unexpected nsIJSNativeInitializer owner");
     return NS_OK;
   }
 
+  BindToOwner(owner);
+
   // This object is bound to a |window|,
-  // so reset the principal and script context.
+  // so reset the principal.
   nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal = do_QueryInterface(aOwner);
   NS_ENSURE_STATE(scriptPrincipal);
   mPrincipal = scriptPrincipal->GetPrincipal();
-  nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aOwner);
-  NS_ENSURE_STATE(sgo);
-  mScriptContext = sgo->GetContext();
-  NS_ENSURE_STATE(mScriptContext);
 
   return NS_OK; 
 }
 
 // nsIInterfaceRequestor
 
 NS_IMETHODIMP
 nsDOMFileReader::GetInterface(const nsIID & aIID, void **aResult)
--- a/content/base/src/nsEventSource.cpp
+++ b/content/base/src/nsEventSource.cpp
@@ -171,16 +171,25 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(EventSource)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(nsEventSource, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(nsEventSource, nsDOMEventTargetHelper)
 
+void
+nsEventSource::DisconnectFromOwner()
+{
+  nsDOMEventTargetHelper::DisconnectFromOwner();
+  NS_DISCONNECT_EVENT_HANDLER(Open)
+  NS_DISCONNECT_EVENT_HANDLER(Message)
+  NS_DISCONNECT_EVENT_HANDLER(Error)
+}
+
 //-----------------------------------------------------------------------------
 // nsEventSource::nsIEventSource
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsEventSource::GetUrl(nsAString& aURL)
 {
   aURL = mOriginalURL;
@@ -246,19 +255,16 @@ nsEventSource::Close()
 
   while (mMessagesToDispatch.GetSize() != 0) {
     delete static_cast<Message*>(mMessagesToDispatch.PopFront());
   }
 
   mSrc = nsnull;
   mFrozen = false;
 
-  mScriptContext = nsnull;
-  mOwner = nsnull;
-
   mUnicodeDecoder = nsnull;
 
   mReadyState = nsIEventSource::CLOSED;
 
   return NS_OK;
 }
 
 /**
@@ -273,23 +279,22 @@ nsEventSource::Init(nsIPrincipal* aPrinc
 {
   NS_ENSURE_ARG(aPrincipal);
 
   if (mReadyState != nsIEventSource::CONNECTING || !PrefEnabled()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   mPrincipal = aPrincipal;
-  mScriptContext = aScriptContext;
   mWithCredentials = aWithCredentials;
   if (aOwnerWindow) {
-    mOwner = aOwnerWindow->IsOuterWindow() ?
-      aOwnerWindow->GetCurrentInnerWindow() : aOwnerWindow;
+    BindToOwner(aOwnerWindow->IsOuterWindow() ?
+      aOwnerWindow->GetCurrentInnerWindow() : aOwnerWindow);
   } else {
-    mOwner = nsnull;
+    BindToOwner(aOwnerWindow);
   }
 
   nsCOMPtr<nsIJSContextStack> stack =
     do_GetService("@mozilla.org/js/xpc/ContextStack;1");
   JSContext* cx = nsnull;
   if (stack && NS_SUCCEEDED(stack->Peek(&cx)) && cx) {
     const char *filename;
     if (nsJSUtils::GetCallingLocation(cx, &filename, &mScriptLine)) {
@@ -297,27 +302,29 @@ nsEventSource::Init(nsIPrincipal* aPrinc
     }
 
     mInnerWindowID = nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx);
   }
 
   // Get the load group for the page. When requesting we'll add ourselves to it.
   // This way any pending requests will be automatically aborted if the user
   // leaves the page.
-  if (mScriptContext) {
+  nsresult rv;
+  nsIScriptContext* sc = GetContextForEventHandlers(&rv);
+  if (sc) {
     nsCOMPtr<nsIDocument> doc =
-      nsContentUtils::GetDocumentFromScriptContext(mScriptContext);
+      nsContentUtils::GetDocumentFromScriptContext(sc);
     if (doc) {
       mLoadGroup = doc->GetDocumentLoadGroup();
     }
   }
 
   // get the src
   nsCOMPtr<nsIURI> baseURI;
-  nsresult rv = GetBaseURI(getter_AddRefs(baseURI));
+  rv = GetBaseURI(getter_AddRefs(baseURI));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIURI> srcURI;
   rv = NS_NewURI(getter_AddRefs(srcURI), aURL, nsnull, baseURI);
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_SYNTAX_ERR);
 
   // we observe when the window freezes and thaws
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
@@ -452,17 +459,17 @@ nsEventSource::Observe(nsISupports* aSub
                        const char* aTopic,
                        const PRUnichar* aData)
 {
   if (mReadyState == nsIEventSource::CLOSED) {
     return NS_OK;
   }
 
   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aSubject);
-  if (!mOwner || window != mOwner) {
+  if (!GetOwner() || window != GetOwner()) {
     return NS_OK;
   }
 
   nsresult rv;
   if (strcmp(aTopic, DOM_WINDOW_FROZEN_TOPIC) == 0) {
     rv = Freeze();
     NS_ASSERTION(rv, "Freeze() failed");
   } else if (strcmp(aTopic, DOM_WINDOW_THAWED_TOPIC) == 0) {
@@ -829,18 +836,18 @@ nsEventSource::GetInterface(const nsIID 
     nsCOMPtr<nsIPromptFactory> wwatch =
       do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Get the an auth prompter for our window so that the parenting
     // of the dialogs works as it should when using tabs.
 
     nsCOMPtr<nsIDOMWindow> window;
-    if (mOwner) {
-      window = mOwner->GetOuterWindow();
+    if (GetOwner()) {
+      window = GetOwner()->GetOuterWindow();
     }
 
     return wwatch->GetPrompt(window, aIID, aResult);
   }
 
   return QueryInterface(aIID, aResult);
 }
 
@@ -856,25 +863,27 @@ nsEventSource::GetBaseURI(nsIURI **aBase
 {
   NS_ENSURE_ARG_POINTER(aBaseURI);
 
   *aBaseURI = nsnull;
 
   nsCOMPtr<nsIURI> baseURI;
 
   // first we try from document->GetBaseURI()
+  nsresult rv;
+  nsIScriptContext* sc = GetContextForEventHandlers(&rv);
   nsCOMPtr<nsIDocument> doc =
-    nsContentUtils::GetDocumentFromScriptContext(mScriptContext);
+    nsContentUtils::GetDocumentFromScriptContext(sc);
   if (doc) {
     baseURI = doc->GetBaseURI();
   }
 
   // otherwise we get from the doc's principal
   if (!baseURI) {
-    nsresult rv = mPrincipal->GetURI(getter_AddRefs(baseURI));
+    rv = mPrincipal->GetURI(getter_AddRefs(baseURI));
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   NS_ENSURE_STATE(baseURI);
 
   baseURI.forget(aBaseURI);
   return NS_OK;
 }
@@ -1262,18 +1271,19 @@ nsEventSource::CheckCanRequestSrc(nsIURI
   nsresult rv = nsContentUtils::GetSecurityManager()->
     CheckLoadURIWithPrincipal(mPrincipal,
                               srcToTest,
                               aCheckURIFlags);
   isValidURI = NS_SUCCEEDED(rv);
 
   // After the security manager, the content-policy check
 
+  nsIScriptContext* sc = GetContextForEventHandlers(&rv);
   nsCOMPtr<nsIDocument> doc =
-    nsContentUtils::GetDocumentFromScriptContext(mScriptContext);
+    nsContentUtils::GetDocumentFromScriptContext(sc);
 
   // mScriptContext should be initialized because of GetBaseURI() above.
   // Still need to consider the case that doc is nsnull however.
   rv = CheckInnerWindowCorrectness();
   NS_ENSURE_SUCCESS(rv, false);
   PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
   rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_DATAREQUEST,
                                  srcToTest,
@@ -1413,17 +1423,17 @@ nsEventSource::DispatchAllMessageEvents(
   mGoingToDispatchAllMessages = false;
 
   nsresult rv = CheckInnerWindowCorrectness();
   if (NS_FAILED(rv)) {
     return;
   }
 
   // Let's play get the JSContext
-  nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(mOwner);
+  nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(GetOwner());
   NS_ENSURE_TRUE(sgo,);
 
   nsIScriptContext* scriptContext = sgo->GetContext();
   NS_ENSURE_TRUE(scriptContext,);
 
   JSContext* cx = scriptContext->GetNativeContext();
   NS_ENSURE_TRUE(cx,);
 
--- a/content/base/src/nsEventSource.h
+++ b/content/base/src/nsEventSource.h
@@ -97,16 +97,17 @@ public:
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSICHANNELEVENTSINK
   NS_DECL_NSIINTERFACEREQUESTOR
 
   // Determine if preferences allow EventSource
   static bool PrefEnabled();
 
+  virtual void DisconnectFromOwner();
 protected:
   nsresult GetBaseURI(nsIURI **aBaseURI);
 
   nsresult SetupHttpChannel();
   nsresult InitChannelAndRequestEventSource();
   nsresult ResetConnection();
   nsresult DispatchFailConnection();
   nsresult SetReconnectionTimeout();
--- a/content/base/src/nsWebSocket.cpp
+++ b/content/base/src/nsWebSocket.cpp
@@ -414,18 +414,19 @@ nsWebSocket::GetInterface(const nsIID &a
 
   if (mDisconnected)
     return NS_ERROR_FAILURE;
 
   if (aIID.Equals(NS_GET_IID(nsIAuthPrompt)) ||
       aIID.Equals(NS_GET_IID(nsIAuthPrompt2))) {
     nsresult rv;
 
+    nsIScriptContext* sc = GetContextForEventHandlers(&rv);
     nsCOMPtr<nsIDocument> doc =
-      nsContentUtils::GetDocumentFromScriptContext(mScriptContext);
+      nsContentUtils::GetDocumentFromScriptContext(sc);
     if (!doc)
       return NS_ERROR_NOT_AVAILABLE;
 
     nsCOMPtr<nsIPromptFactory> wwatch =
       do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsPIDOMWindow> outerWindow = doc->GetWindow();
@@ -530,16 +531,27 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_INTERFACE_MAP_ENTRY(nsIRequest)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebSocket)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(nsWebSocket, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(nsWebSocket, nsDOMEventTargetHelper)
 
+void
+nsWebSocket::DisconnectFromOwner()
+{
+  nsDOMEventTargetHelper::DisconnectFromOwner();
+  NS_DISCONNECT_EVENT_HANDLER(Open)
+  NS_DISCONNECT_EVENT_HANDLER(Message)
+  NS_DISCONNECT_EVENT_HANDLER(Close)
+  NS_DISCONNECT_EVENT_HANDLER(Error)
+  DontKeepAliveAnyMore();
+}
+
 //-----------------------------------------------------------------------------
 // nsWebSocket::nsIJSNativeInitializer methods:
 //-----------------------------------------------------------------------------
 
 /**
  * This Initialize method is called from XPConnect via nsIJSNativeInitializer.
  * It is used for constructing our nsWebSocket from JavaScript. It expects a URL
  * string parameter and an optional protocol parameter which may be a string or
@@ -785,17 +797,17 @@ nsWebSocket::CreateAndDispatchMessageEve
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
   nsresult rv;
 
   rv = CheckInnerWindowCorrectness();
   if (NS_FAILED(rv))
     return NS_OK;
 
   // Get the JSContext
-  nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(mOwner);
+  nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(GetOwner());
   NS_ENSURE_TRUE(sgo, NS_ERROR_FAILURE);
 
   nsIScriptContext* scriptContext = sgo->GetContext();
   NS_ENSURE_TRUE(scriptContext, NS_ERROR_FAILURE);
 
   JSContext* cx = scriptContext->GetNativeContext();
   NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE);
 
@@ -1520,22 +1532,21 @@ nsWebSocket::Init(nsIPrincipal* aPrincip
 
   NS_ENSURE_ARG(aPrincipal);
 
   if (!PrefEnabled()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   mPrincipal = aPrincipal;
-  mScriptContext = aScriptContext;
   if (aOwnerWindow) {
-    mOwner = aOwnerWindow->IsOuterWindow() ?
-      aOwnerWindow->GetCurrentInnerWindow() : aOwnerWindow;
+    BindToOwner(aOwnerWindow->IsOuterWindow() ?
+                aOwnerWindow->GetCurrentInnerWindow() : aOwnerWindow);
   } else {
-    mOwner = nsnull;
+    BindToOwner(aOwnerWindow);
   }
 
   // Attempt to kill "ghost" websocket: but usually too early for check to fail
   rv = CheckInnerWindowCorrectness();
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Shut down websocket if window is frozen or destroyed (only needed for
   // "ghost" websockets--see bug 696085)
@@ -1565,18 +1576,19 @@ nsWebSocket::Init(nsIPrincipal* aPrincip
 
     mInnerWindowID = nsJSUtils::GetCurrentlyRunningCodeInnerWindowID(cx);
   }
 
   // parses the url
   rv = ParseURL(PromiseFlatString(aURL));
   NS_ENSURE_SUCCESS(rv, rv);
 
+  nsIScriptContext* sc = GetContextForEventHandlers(&rv);
   nsCOMPtr<nsIDocument> originDoc =
-    nsContentUtils::GetDocumentFromScriptContext(mScriptContext);
+    nsContentUtils::GetDocumentFromScriptContext(sc);
 
   // Don't allow https:// to open ws://
   if (!mSecure &&
       !Preferences::GetBool("network.websocket.allowInsecureFromHTTPS",
                             false)) {
     // Confirmed we are opening plain ws:// and want to prevent this from a
     // secure context (e.g. https). Check the security context of the document
     // associated with this script, which is the same as associated with mOwner.
@@ -1631,17 +1643,17 @@ nsWebSocket::Observe(nsISupports* aSubje
                      const PRUnichar* aData)
 {
   if ((mReadyState == nsIWebSocket::CLOSING) ||
       (mReadyState == nsIWebSocket::CLOSED)) {
     return NS_OK;
   }
 
   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aSubject);
-  if (!mOwner || window != mOwner) {
+  if (!GetOwner() || window != GetOwner()) {
     return NS_OK;
   }
 
   if ((strcmp(aTopic, DOM_WINDOW_FROZEN_TOPIC) == 0) ||
       (strcmp(aTopic, DOM_WINDOW_DESTROYED_TOPIC) == 0))
   {
     FailConnectionQuietly();
   }
@@ -1700,18 +1712,20 @@ nsWebSocket::Resume()
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 nsWebSocket::GetLoadGroup(nsILoadGroup **aLoadGroup)
 {
   *aLoadGroup = nsnull;
 
+  nsresult rv;
+  nsIScriptContext* sc = GetContextForEventHandlers(&rv);
   nsCOMPtr<nsIDocument> doc =
-    nsContentUtils::GetDocumentFromScriptContext(mScriptContext);
+    nsContentUtils::GetDocumentFromScriptContext(sc);
 
   if (doc) {
     *aLoadGroup = doc->GetDocumentLoadGroup().get();  // already_AddRefed
   }
 
   return NS_OK;
 }
 
--- a/content/base/src/nsWebSocket.h
+++ b/content/base/src/nsWebSocket.h
@@ -107,16 +107,17 @@ public:
                               PRUint8 optional_argc);
   NS_IMETHOD RemoveEventListener(const nsAString& aType,
                                  nsIDOMEventListener* aListener,
                                  bool aUseCapture);
 
   // Determine if preferences allow WebSocket
   static bool PrefEnabled();
 
+  virtual void DisconnectFromOwner();
 protected:
   nsresult ParseURL(const nsString& aURL);
   nsresult EstablishConnection();
 
   // These methods when called can release the WebSocket object
   nsresult FailConnection(PRUint16 reasonCode,
                           const nsACString& aReasonString = EmptyCString());
   void     FailConnectionQuietly();
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -324,16 +324,29 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXHREventTarget)
   NS_INTERFACE_MAP_ENTRY(nsIXMLHttpRequestEventTarget)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(nsXHREventTarget, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(nsXHREventTarget, nsDOMEventTargetHelper)
 
+void
+nsXHREventTarget::DisconnectFromOwner()
+{
+  nsDOMEventTargetHelper::DisconnectFromOwner();
+  NS_DISCONNECT_EVENT_HANDLER(Load)
+  NS_DISCONNECT_EVENT_HANDLER(Error)
+  NS_DISCONNECT_EVENT_HANDLER(Abort)
+  NS_DISCONNECT_EVENT_HANDLER(Load)
+  NS_DISCONNECT_EVENT_HANDLER(Progress)
+  NS_DISCONNECT_EVENT_HANDLER(Loadend)
+  NS_DISCONNECT_EVENT_HANDLER(Timeout)
+}
+
 NS_IMETHODIMP
 nsXHREventTarget::GetOnload(nsIDOMEventListener** aOnLoad)
 {
   return GetInnerEventListener(mOnLoadListener, aOnLoad);
 }
 
 NS_IMETHODIMP
 nsXHREventTarget::SetOnload(nsIDOMEventListener* aOnLoad)
@@ -484,17 +497,17 @@ nsXMLHttpRequest::RootResultArrayBuffer(
 }
 
 /**
  * This Init method is called from the factory constructor.
  */
 nsresult
 nsXMLHttpRequest::Init()
 {
-  // Set the original mScriptContext and mPrincipal, if available.
+  // Set the original mPrincipal, if available.
   // Get JSContext from stack.
   nsCOMPtr<nsIJSContextStack> stack =
     do_GetService("@mozilla.org/js/xpc/ContextStack;1");
 
   if (!stack) {
     return NS_OK;
   }
 
@@ -510,76 +523,60 @@ nsXMLHttpRequest::Init()
     nsresult rv = secMan->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
     NS_ENSURE_SUCCESS(rv, rv);
   }
   NS_ENSURE_STATE(subjectPrincipal);
   mPrincipal = subjectPrincipal;
 
   nsIScriptContext* context = GetScriptContextFromJSContext(cx);
   if (context) {
-    mScriptContext = context;
     nsCOMPtr<nsPIDOMWindow> window =
       do_QueryInterface(context->GetGlobalObject());
-    if (window) {
-      mOwner = window->GetCurrentInnerWindow();
-    }
+    BindToOwner(window ? window->GetCurrentInnerWindow() : nsnull);
   }
 
   return NS_OK;
 }
 /**
  * This Init method should only be called by C++ consumers.
  */
 NS_IMETHODIMP
 nsXMLHttpRequest::Init(nsIPrincipal* aPrincipal,
                        nsIScriptContext* aScriptContext,
                        nsPIDOMWindow* aOwnerWindow,
                        nsIURI* aBaseURI)
 {
   NS_ENSURE_ARG_POINTER(aPrincipal);
 
-  // This object may have already been initialized in the other Init call above
-  // if JS was on the stack. Clear the old values for mScriptContext and mOwner
-  // if new ones are not supplied here.
-
   mPrincipal = aPrincipal;
-  mScriptContext = aScriptContext;
-  if (aOwnerWindow) {
-    mOwner = aOwnerWindow->GetCurrentInnerWindow();
-  }
-  else {
-    mOwner = nsnull;
-  }
+  BindToOwner(aOwnerWindow ? aOwnerWindow->GetCurrentInnerWindow() : nsnull);
   mBaseURI = aBaseURI;
 
   return NS_OK;
 }
 
 /**
  * This Initialize method is called from XPConnect via nsIJSNativeInitializer.
  */
 NS_IMETHODIMP
 nsXMLHttpRequest::Initialize(nsISupports* aOwner, JSContext* cx, JSObject* obj,
                              PRUint32 argc, jsval *argv)
 {
-  mOwner = do_QueryInterface(aOwner);
-  if (!mOwner) {
+  nsCOMPtr<nsPIDOMWindow> owner = do_QueryInterface(aOwner);
+  if (!owner) {
     NS_WARNING("Unexpected nsIJSNativeInitializer owner");
     return NS_OK;
   }
 
   // This XHR object is bound to a |window|,
   // so re-set principal and script context.
   nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal = do_QueryInterface(aOwner);
   NS_ENSURE_STATE(scriptPrincipal);
   mPrincipal = scriptPrincipal->GetPrincipal();
-  nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aOwner);
-  NS_ENSURE_STATE(sgo);
-  mScriptContext = sgo->GetContext();
-  NS_ENSURE_STATE(mScriptContext);
+  BindToOwner(owner);
   return NS_OK; 
 }
 
 void
 nsXMLHttpRequest::ResetResponse()
 {
   mResponseXML = nsnull;
   mResponseBody.Truncate();
@@ -700,16 +697,24 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
   NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
   NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(XMLHttpRequest)
 NS_INTERFACE_MAP_END_INHERITING(nsXHREventTarget)
 
 NS_IMPL_ADDREF_INHERITED(nsXMLHttpRequest, nsXHREventTarget)
 NS_IMPL_RELEASE_INHERITED(nsXMLHttpRequest, nsXHREventTarget)
 
+void
+nsXMLHttpRequest::DisconnectFromOwner()
+{
+  nsXHREventTarget::DisconnectFromOwner();
+  NS_DISCONNECT_EVENT_HANDLER(UploadProgress)
+  NS_DISCONNECT_EVENT_HANDLER(Readystatechange)
+}
+
 NS_IMETHODIMP
 nsXMLHttpRequest::GetOnreadystatechange(nsIDOMEventListener * *aOnreadystatechange)
 {
   return
     nsXHREventTarget::GetInnerEventListener(mOnReadystatechangeListener,
                                             aOnreadystatechange);
 }
 
@@ -772,21 +777,21 @@ nsXMLHttpRequest::GetResponseXML(nsIDOMD
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
   if ((XML_HTTP_REQUEST_DONE & mState) && mResponseXML) {
     *aResponseXML = mResponseXML;
     NS_ADDREF(*aResponseXML);
   }
   if (mWarnAboutMultipartHtml) {
     mWarnAboutMultipartHtml = false;
-    LogMessage("HTMLMultipartXHRWarning", mOwner);
+    LogMessage("HTMLMultipartXHRWarning", GetOwner());
   }
   if (mWarnAboutSyncHtml) {
     mWarnAboutSyncHtml = false;
-    LogMessage("HTMLSyncXHRWarning", mOwner);
+    LogMessage("HTMLSyncXHRWarning", GetOwner());
   }
   return NS_OK;
 }
 
 /*
  * This piece copied from nsXMLDocument, we try to get the charset
  * from HTTP headers.
  */
@@ -818,17 +823,17 @@ nsXMLHttpRequest::DetectCharset()
   if (NS_FAILED(rv) || mResponseCharset.IsEmpty()) {
     // MS documentation states UTF-8 is default for responseText
     mResponseCharset.AssignLiteral("UTF-8");
   }
 
   if (mResponseType == XML_HTTP_RESPONSE_TYPE_JSON &&
       !mResponseCharset.EqualsLiteral("UTF-8")) {
     // The XHR spec says only UTF-8 is supported for responseType == "json"
-    LogMessage("JSONCharsetWarning", mOwner);
+    LogMessage("JSONCharsetWarning", GetOwner());
     mResponseCharset.AssignLiteral("UTF-8");
   }
 
   nsCOMPtr<nsICharsetConverterManager> ccm =
     do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return ccm->GetUnicodeDecoderRaw(mResponseCharset.get(),
@@ -1039,19 +1044,19 @@ NS_IMETHODIMP nsXMLHttpRequest::SetRespo
 {
   // If the state is not OPENED or HEADERS_RECEIVED raise an
   // INVALID_STATE_ERR exception and terminate these steps.
   if (!(mState & (XML_HTTP_REQUEST_OPENED | XML_HTTP_REQUEST_SENT |
                   XML_HTTP_REQUEST_HEADERS_RECEIVED)))
     return NS_ERROR_DOM_INVALID_STATE_ERR;
 
   // sync request is not allowed setting responseType in window context
-  if (mOwner &&
+  if (HasOrHasHadOwner() &&
       !(mState & (XML_HTTP_REQUEST_UNSENT | XML_HTTP_REQUEST_ASYNC))) {
-    LogMessage("ResponseTypeSyncXHRWarning", mOwner);
+    LogMessage("ResponseTypeSyncXHRWarning", GetOwner());
     return NS_ERROR_DOM_INVALID_ACCESS_ERR;
   }
 
   // Set the responseType attribute's value to the given value.
   if (aResponseType.IsEmpty()) {
     mResponseType = XML_HTTP_RESPONSE_TYPE_DEFAULT;
   } else if (aResponseType.EqualsLiteral("arraybuffer")) {
     mResponseType = XML_HTTP_RESPONSE_TYPE_ARRAYBUFFER;
@@ -1474,22 +1479,25 @@ nsXMLHttpRequest::GetResponseHeader(cons
   }
 
   return rv;
 }
 
 already_AddRefed<nsILoadGroup>
 nsXMLHttpRequest::GetLoadGroup() const
 {
-  if (mState & XML_HTTP_REQUEST_BACKGROUND) {
+  if (mState & XML_HTTP_REQUEST_BACKGROUND) {                 
     return nsnull;
   }
 
+  nsresult rv = NS_ERROR_FAILURE;
+  nsIScriptContext* sc =
+    const_cast<nsXMLHttpRequest*>(this)->GetContextForEventHandlers(&rv);
   nsCOMPtr<nsIDocument> doc =
-    nsContentUtils::GetDocumentFromScriptContext(mScriptContext);
+    nsContentUtils::GetDocumentFromScriptContext(sc);
   if (doc) {
     return doc->GetDocumentLoadGroup();
   }
 
   return nsnull;
 }
 
 nsresult
@@ -1558,17 +1566,17 @@ nsXMLHttpRequest::DispatchProgressEvent(
     return;
   }
 
   progress->InitProgressEvent(aType, false, false, aLengthComputable,
                               aLoaded, (aTotal == LL_MAXUINT) ? 0 : aTotal);
 
   if (aUseLSEventWrapper) {
     nsCOMPtr<nsIDOMProgressEvent> xhrprogressEvent =
-      new nsXMLHttpProgressEvent(progress, aPosition, aTotalSize, mOwner);
+      new nsXMLHttpProgressEvent(progress, aPosition, aTotalSize, GetOwner());
     event = xhrprogressEvent;
   }
   aTarget->DispatchDOMEvent(nsnull, event, nsnull, nsnull);
   
   if (dispatchLoadend) {
     DispatchProgressEvent(aTarget, NS_LITERAL_STRING(LOADEND_STR),
                           aUseLSEventWrapper, aLengthComputable,
                           aLoaded, aTotal, aPosition, aTotalSize);
@@ -1661,28 +1669,28 @@ nsXMLHttpRequest::Open(const nsACString&
   // and MS IIS equivalent TRACK (see bug 381264)
   if (method.LowerCaseEqualsLiteral("trace") ||
       method.LowerCaseEqualsLiteral("track")) {
     return NS_ERROR_INVALID_ARG;
   }
 
   // sync request is not allowed using withCredential or responseType
   // in window context
-  if (!async && mOwner &&
+  if (!async && HasOrHasHadOwner() &&
       (mState & XML_HTTP_REQUEST_AC_WITH_CREDENTIALS ||
        mTimeoutMilliseconds ||
        mResponseType != XML_HTTP_RESPONSE_TYPE_DEFAULT)) {
     if (mState & XML_HTTP_REQUEST_AC_WITH_CREDENTIALS) {
-      LogMessage("WithCredentialsSyncXHRWarning", mOwner);
+      LogMessage("WithCredentialsSyncXHRWarning", GetOwner());
     }
     if (mTimeoutMilliseconds) {
-      LogMessage("TimeoutSyncXHRWarning", mOwner);
+      LogMessage("TimeoutSyncXHRWarning", GetOwner());
     }
     if (mResponseType != XML_HTTP_RESPONSE_TYPE_DEFAULT) {
-      LogMessage("ResponseTypeSyncXHRWarning", mOwner);
+      LogMessage("ResponseTypeSyncXHRWarning", GetOwner());
     }
     return NS_ERROR_DOM_INVALID_ACCESS_ERR;
   }
 
   nsresult rv;
   nsCOMPtr<nsIURI> uri;
 
   if (mState & (XML_HTTP_REQUEST_OPENED |
@@ -1706,32 +1714,32 @@ nsXMLHttpRequest::Open(const nsACString&
   if (async) {
     mState |= XML_HTTP_REQUEST_ASYNC;
   } else {
     mState &= ~XML_HTTP_REQUEST_ASYNC;
   }
 
   mState &= ~XML_HTTP_REQUEST_MPART_HEADERS;
 
+  nsIScriptContext* sc = GetContextForEventHandlers(&rv);
+  NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr<nsIDocument> doc =
-    nsContentUtils::GetDocumentFromScriptContext(mScriptContext);
+    nsContentUtils::GetDocumentFromScriptContext(sc);
   
   nsCOMPtr<nsIURI> baseURI;
   if (mBaseURI) {
     baseURI = mBaseURI;
   }
   else if (doc) {
     baseURI = doc->GetBaseURI();
   }
 
   rv = NS_NewURI(getter_AddRefs(uri), url, nsnull, baseURI);
   if (NS_FAILED(rv)) return rv;
 
-  // mScriptContext should be initialized because of GetBaseURI() above.
-  // Still need to consider the case that doc is nsnull however.
   rv = CheckInnerWindowCorrectness();
   NS_ENSURE_SUCCESS(rv, rv);
   PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
   rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_XMLHTTPREQUEST,
                                  uri,
                                  mPrincipal,
                                  doc,
                                  EmptyCString(), //mime guess
@@ -2118,30 +2126,32 @@ nsXMLHttpRequest::OnStartRequest(nsIRequ
     }
   } else {
     // The request failed, so we shouldn't be parsing anyway
     mState &= ~XML_HTTP_REQUEST_PARSEBODY;
   }
 
   if (mState & XML_HTTP_REQUEST_PARSEBODY) {
     nsCOMPtr<nsIURI> baseURI, docURI;
+    nsIScriptContext* sc = GetContextForEventHandlers(&rv);
+    NS_ENSURE_SUCCESS(rv, rv);
     nsCOMPtr<nsIDocument> doc =
-      nsContentUtils::GetDocumentFromScriptContext(mScriptContext);
+      nsContentUtils::GetDocumentFromScriptContext(sc);
 
     if (doc) {
       docURI = doc->GetDocumentURI();
       baseURI = doc->GetBaseURI();
     }
 
     // Create an empty document from it.  Here we have to cheat a little bit...
     // Setting the base URI to |baseURI| won't work if the document has a null
     // principal, so use mPrincipal when creating the document, then reset the
     // principal.
     const nsAString& emptyStr = EmptyString();
-    nsCOMPtr<nsIScriptGlobalObject> global = do_QueryInterface(mOwner);
+    nsCOMPtr<nsIScriptGlobalObject> global = do_QueryInterface(GetOwner());
     rv = nsContentUtils::CreateDocument(emptyStr, emptyStr, nsnull, docURI,
                                         baseURI, mPrincipal, global,
                                         mIsHtml ? DocumentFlavorHTML :
                                                   DocumentFlavorLegacyGuess,
                                         getter_AddRefs(mResponseXML));
     NS_ENSURE_SUCCESS(rv, rv);
     nsCOMPtr<nsIDocument> responseDoc = do_QueryInterface(mResponseXML);
     responseDoc->SetPrincipal(documentPrincipal);
@@ -2573,18 +2583,20 @@ nsXMLHttpRequest::Send(nsIVariant *aBody
       // If the document's original URI (before any push/replaceStates) matches
       // our principal, then we use the document's current URI (after
       // push/replaceStates).  Otherwise (if the document is, say, a data:
       // URI), we just use the principal's URI.
 
       nsCOMPtr<nsIURI> principalURI;
       mPrincipal->GetURI(getter_AddRefs(principalURI));
 
+      nsIScriptContext* sc = GetContextForEventHandlers(&rv);
+      NS_ENSURE_SUCCESS(rv, rv);
       nsCOMPtr<nsIDocument> doc =
-        nsContentUtils::GetDocumentFromScriptContext(mScriptContext);
+        nsContentUtils::GetDocumentFromScriptContext(sc);
 
       nsCOMPtr<nsIURI> docCurURI;
       nsCOMPtr<nsIURI> docOrigURI;
       if (doc) {
         docCurURI = doc->GetDocumentURI();
         docOrigURI = doc->GetOriginalURI();
       }
 
@@ -2831,19 +2843,19 @@ nsXMLHttpRequest::Send(nsIVariant *aBody
   mWaitingForOnStopRequest = true;
 
   // If we're synchronous, spin an event loop here and wait
   if (!(mState & XML_HTTP_REQUEST_ASYNC)) {
     mState |= XML_HTTP_REQUEST_SYNCLOOPING;
 
     nsCOMPtr<nsIDocument> suspendedDoc;
     nsCOMPtr<nsIRunnable> resumeTimeoutRunnable;
-    if (mOwner) {
+    if (GetOwner()) {
       nsCOMPtr<nsIDOMWindow> topWindow;
-      if (NS_SUCCEEDED(mOwner->GetTop(getter_AddRefs(topWindow)))) {
+      if (NS_SUCCEEDED(GetOwner()->GetTop(getter_AddRefs(topWindow)))) {
         nsCOMPtr<nsPIDOMWindow> suspendedWindow(do_QueryInterface(topWindow));
         if (suspendedWindow &&
             (suspendedWindow = suspendedWindow->GetCurrentInnerWindow())) {
           suspendedDoc = do_QueryInterface(suspendedWindow->GetExtantDocument());
           if (suspendedDoc) {
             suspendedDoc->SuppressEventHandling();
           }
           suspendedWindow->SuspendTimeouts(1, false);
@@ -3003,27 +3015,28 @@ NS_IMETHODIMP
 nsXMLHttpRequest::GetTimeout(PRUint32 *aTimeout)
 {
   *aTimeout = mTimeoutMilliseconds;
   return NS_OK;
 }
 NS_IMETHODIMP
 nsXMLHttpRequest::SetTimeout(PRUint32 aTimeout)
 {
-  if ((mState & (XML_HTTP_REQUEST_ASYNC | XML_HTTP_REQUEST_UNSENT)) || !mOwner) {
+  if ((mState & (XML_HTTP_REQUEST_ASYNC | XML_HTTP_REQUEST_UNSENT)) ||
+      !HasOrHasHadOwner()) {
     mTimeoutMilliseconds = aTimeout;
     if (mRequestSentTime) {
       StartTimeoutTimer();
     }
     return NS_OK;
   }
 
   /* Timeout is not supported for synchronous requests with an owning window,
      per XHR2 spec. */
-  LogMessage("TimeoutSyncXHRWarning", mOwner);
+  LogMessage("TimeoutSyncXHRWarning", GetOwner());
   return NS_ERROR_DOM_INVALID_ACCESS_ERR;
 }
 
 void
 nsXMLHttpRequest::StartTimeoutTimer()
 {
   NS_ABORT_IF_FALSE(mRequestSentTime,
                     "StartTimeoutTimer mustn't be called before the request was sent!");
@@ -3161,19 +3174,19 @@ NS_IMETHODIMP
 nsXMLHttpRequest::SetWithCredentials(bool aWithCredentials)
 {
   // Return error if we're already processing a request
   if (XML_HTTP_REQUEST_SENT & mState) {
     return NS_ERROR_FAILURE;
   }
 
   // sync request is not allowed setting withCredentials in window context
-  if (mOwner &&
+  if (HasOrHasHadOwner() &&
       !(mState & (XML_HTTP_REQUEST_UNSENT | XML_HTTP_REQUEST_ASYNC))) {
-    LogMessage("WithCredentialsSyncXHRWarning", mOwner);
+    LogMessage("WithCredentialsSyncXHRWarning", GetOwner());
     return NS_ERROR_DOM_INVALID_ACCESS_ERR;
   }
 
   if (aWithCredentials) {
     mState |= XML_HTTP_REQUEST_AC_WITH_CREDENTIALS;
   }
   else {
     mState &= ~XML_HTTP_REQUEST_AC_WITH_CREDENTIALS;
@@ -3514,18 +3527,18 @@ nsXMLHttpRequest::GetInterface(const nsI
     nsCOMPtr<nsIPromptFactory> wwatch =
       do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Get the an auth prompter for our window so that the parenting
     // of the dialogs works as it should when using tabs.
 
     nsCOMPtr<nsIDOMWindow> window;
-    if (mOwner) {
-      window = mOwner->GetOuterWindow();
+    if (GetOwner()) {
+      window = GetOwner()->GetOuterWindow();
     }
 
     return wwatch->GetPrompt(window, aIID,
                              reinterpret_cast<void**>(aResult));
 
   }
 
   return QueryInterface(aIID, aResult);
@@ -3536,17 +3549,17 @@ nsXMLHttpRequest::GetUpload(nsIXMLHttpRe
 {
   *aUpload = nsnull;
 
   nsresult rv;
   nsIScriptContext* scriptContext =
     GetContextForEventHandlers(&rv);
   NS_ENSURE_SUCCESS(rv, rv);
   if (!mUpload) {
-    mUpload = new nsXMLHttpRequestUpload(mOwner, scriptContext);
+    mUpload = new nsXMLHttpRequestUpload(this);
     NS_ENSURE_TRUE(mUpload, NS_ERROR_OUT_OF_MEMORY);
   }
   NS_ADDREF(*aUpload = mUpload);
   return NS_OK;
 }
 
 void
 nsXMLHttpRequest::HandleTimeoutCallback()
--- a/content/base/src/nsXMLHttpRequest.h
+++ b/content/base/src/nsXMLHttpRequest.h
@@ -78,36 +78,35 @@ class nsXHREventTarget : public nsDOMEve
 public:
   virtual ~nsXHREventTarget() {}
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXHREventTarget,
                                            nsDOMEventTargetHelper)
   NS_DECL_NSIXMLHTTPREQUESTEVENTTARGET
   NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
 
+  virtual void DisconnectFromOwner();
 protected:
   nsRefPtr<nsDOMEventListenerWrapper> mOnLoadListener;
   nsRefPtr<nsDOMEventListenerWrapper> mOnErrorListener;
   nsRefPtr<nsDOMEventListenerWrapper> mOnAbortListener;
   nsRefPtr<nsDOMEventListenerWrapper> mOnLoadStartListener;
   nsRefPtr<nsDOMEventListenerWrapper> mOnProgressListener;
   nsRefPtr<nsDOMEventListenerWrapper> mOnLoadendListener;
   nsRefPtr<nsDOMEventListenerWrapper> mOnTimeoutListener;
 };
 
 class nsXMLHttpRequestUpload : public nsXHREventTarget,
                                public nsIXMLHttpRequestUpload
 {
 public:
-  nsXMLHttpRequestUpload(nsPIDOMWindow* aOwner,
-                         nsIScriptContext* aScriptContext)
+  nsXMLHttpRequestUpload(nsDOMEventTargetHelper* aOwner)
   {
-    mOwner = aOwner;
-    mScriptContext = aScriptContext;
-  }
+    BindToOwner(aOwner);
+  }                                         
   NS_DECL_ISUPPORTS_INHERITED
   NS_FORWARD_NSIXMLHTTPREQUESTEVENTTARGET(nsXHREventTarget::)
   NS_FORWARD_NSIDOMEVENTTARGET(nsXHREventTarget::)
   NS_DECL_NSIXMLHTTPREQUESTUPLOAD
 
   bool HasListeners()
   {
     return mListenerManager && mListenerManager->HasListeners();
@@ -201,17 +200,18 @@ public:
   nsresult Init();
 
   void SetRequestObserver(nsIRequestObserver* aObserver);
 
   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED(nsXMLHttpRequest,
                                                                    nsXHREventTarget)
   bool AllowUploadProgress();
   void RootResultArrayBuffer();
-  
+
+  virtual void DisconnectFromOwner();
 protected:
   friend class nsMultipartProxyListener;
 
   nsresult DetectCharset();
   nsresult AppendToResponseText(const char * aBuffer, PRUint32 aBufferLen);
   static NS_METHOD StreamReaderFunc(nsIInputStream* in,
                 void* closure,
                 const char* fromRawSegment,
--- a/content/events/src/nsDOMEventTargetHelper.cpp
+++ b/content/events/src/nsDOMEventTargetHelper.cpp
@@ -39,16 +39,17 @@
 #include "nsDOMEventTargetHelper.h"
 #include "nsContentUtils.h"
 #include "nsEventDispatcher.h"
 #include "nsGUIEvent.h"
 #include "nsIDocument.h"
 #include "nsIJSContextStack.h"
 #include "nsDOMJSUtils.h"
 #include "prprf.h"
+#include "nsGlobalWindow.h"
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMEventListenerWrapper)
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMEventListenerWrapper)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
 NS_INTERFACE_MAP_END_AGGREGATED(mListener)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMEventListenerWrapper)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMEventListenerWrapper)
@@ -86,46 +87,89 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
                               name);
   } else {
     NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsDOMEventTargetHelper, tmp->mRefCnt.get())
   }
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mListenerManager,
                                                   nsEventListenerManager)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptContext)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOwner)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMEventTargetHelper)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mListenerManager)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mScriptContext)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOwner)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMEventTargetHelper)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMEventTargetHelper)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMEventTargetHelper)
 
 NS_IMPL_DOMTARGET_DEFAULTS(nsDOMEventTargetHelper);
 
 nsDOMEventTargetHelper::~nsDOMEventTargetHelper()
 {
+  if (mOwner) {
+    static_cast<nsGlobalWindow*>(mOwner)->RemoveEventTargetObject(this);
+  }
   if (mListenerManager) {
     mListenerManager->Disconnect();
   }
   nsContentUtils::ReleaseWrapper(this, this);
 }
 
+void
+nsDOMEventTargetHelper::BindToOwner(nsPIDOMWindow* aOwner)
+{
+  if (mOwner) {
+    static_cast<nsGlobalWindow*>(mOwner)->RemoveEventTargetObject(this);
+    mOwner = nsnull;
+    mHasOrHasHadOwner = false;
+  }
+  if (aOwner) {
+    mOwner = aOwner;
+    mHasOrHasHadOwner = true;
+    static_cast<nsGlobalWindow*>(mOwner)->AddEventTargetObject(this);
+  }
+}
+
+void
+nsDOMEventTargetHelper::BindToOwner(nsDOMEventTargetHelper* aOther)
+{
+  if (mOwner) {
+    static_cast<nsGlobalWindow*>(mOwner)->RemoveEventTargetObject(this);
+    mOwner = nsnull;
+    mHasOrHasHadOwner = false;
+  }
+  if (aOther) {
+    mHasOrHasHadOwner = aOther->HasOrHasHadOwner();
+    if (aOther->GetOwner()) {
+      mOwner = aOther->GetOwner();
+      mHasOrHasHadOwner = true;
+      static_cast<nsGlobalWindow*>(mOwner)->AddEventTargetObject(this);
+    }
+  }
+}
+
+void
+nsDOMEventTargetHelper::DisconnectFromOwner()
+{
+  mOwner = nsnull;
+  // Event listeners can't be handled anymore, so we can release them here.
+  if (mListenerManager) {
+    mListenerManager->Disconnect();
+    mListenerManager = nsnull;
+  }
+}
+
 NS_IMETHODIMP
 nsDOMEventTargetHelper::RemoveEventListener(const nsAString& aType,
                                             nsIDOMEventListener* aListener,
                                             bool aUseCapture)
 {
   nsEventListenerManager* elm = GetListenerManager(false);
   if (elm) {
     elm->RemoveEventListener(aType, aListener, aUseCapture);
@@ -267,36 +311,36 @@ nsDOMEventTargetHelper::GetListenerManag
 
 nsIScriptContext*
 nsDOMEventTargetHelper::GetContextForEventHandlers(nsresult* aRv)
 {
   *aRv = CheckInnerWindowCorrectness();
   if (NS_FAILED(*aRv)) {
     return nsnull;
   }
-  return mScriptContext;
+  return mOwner ? static_cast<nsGlobalWindow*>(mOwner)->GetContextInternal()
+                : nsnull;
 }
 
 void
 nsDOMEventTargetHelper::Init(JSContext* aCx)
 {
-  // Set the original mScriptContext and mPrincipal, if available
   JSContext* cx = aCx;
   if (!cx) {
     nsIJSContextStack* stack = nsContentUtils::ThreadJSContextStack();
 
     if (!stack)
       return;
 
     if (NS_FAILED(stack->Peek(&cx)) || !cx)
       return;
   }
 
   NS_ASSERTION(cx, "Should have returned earlier ...");
   nsIScriptContext* context = GetScriptContextFromJSContext(cx);
   if (context) {
-    mScriptContext = context;
     nsCOMPtr<nsPIDOMWindow> window =
       do_QueryInterface(context->GetGlobalObject());
-    if (window)
-      mOwner = window->GetCurrentInnerWindow();
+    if (window) {
+      BindToOwner(window->GetCurrentInnerWindow());
+    }
   }
 }
--- a/content/events/src/nsDOMEventTargetHelper.h
+++ b/content/events/src/nsDOMEventTargetHelper.h
@@ -57,25 +57,26 @@ public:
   : mListener(aListener) {}
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMEventListenerWrapper)
 
   NS_DECL_NSIDOMEVENTLISTENER
 
   nsIDOMEventListener* GetInner() { return mListener; }
+  void Disconnect() { mListener = nsnull; }
 protected:
   nsCOMPtr<nsIDOMEventListener> mListener;
 };
 
 class nsDOMEventTargetHelper : public nsIDOMEventTarget,
                                public nsWrapperCache
 {
 public:
-  nsDOMEventTargetHelper() {}
+  nsDOMEventTargetHelper() : mOwner(nsnull), mHasOrHasHadOwner(false) {}
   virtual ~nsDOMEventTargetHelper();
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsDOMEventTargetHelper)
 
   NS_DECL_NSIDOMEVENTTARGET
 
   void GetParentObject(nsIScriptGlobalObject **aParentObject)
   {
@@ -116,30 +117,38 @@ public:
                                   nsRefPtr<nsDOMEventListenerWrapper>& aCurrent,
                                   nsIDOMEventListener* aNew);
 
   nsresult GetInnerEventListener(nsRefPtr<nsDOMEventListenerWrapper>& aWrapper,
                                  nsIDOMEventListener** aListener);
 
   nsresult CheckInnerWindowCorrectness()
   {
+    NS_ENSURE_STATE(!mHasOrHasHadOwner || mOwner);
     if (mOwner) {
       NS_ASSERTION(mOwner->IsInnerWindow(), "Should have inner window here!\n");
       nsPIDOMWindow* outer = mOwner->GetOuterWindow();
       if (!outer || outer->GetCurrentInnerWindow() != mOwner) {
         return NS_ERROR_FAILURE;
       }
     }
     return NS_OK;
   }
+
+  void BindToOwner(nsPIDOMWindow* aOwner);
+  void BindToOwner(nsDOMEventTargetHelper* aOther);
+  virtual void DisconnectFromOwner();                   
+  nsPIDOMWindow* GetOwner() { return mOwner; }
+  bool HasOrHasHadOwner() { return mHasOrHasHadOwner; }
 protected:
   nsRefPtr<nsEventListenerManager> mListenerManager;
+private:
   // These may be null (native callers or xpcshell).
-  nsCOMPtr<nsIScriptContext> mScriptContext;
-  nsCOMPtr<nsPIDOMWindow>    mOwner; // Inner window.
+  nsPIDOMWindow*             mOwner; // Inner window.
+  bool                       mHasOrHasHadOwner;
 };
 
 #define NS_DECL_EVENT_HANDLER(_event)                                         \
   protected:                                                                  \
     nsRefPtr<nsDOMEventListenerWrapper> mOn##_event##Listener;                \
   public:
 
 #define NS_DECL_AND_IMPL_EVENT_HANDLER(_event)                                \
@@ -182,16 +191,19 @@ protected:
     }
 
 #define NS_CYCLE_COLLECTION_TRAVERSE_EVENT_HANDLER(_event)                    \
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOn##_event##Listener)
 
 #define NS_CYCLE_COLLECTION_UNLINK_EVENT_HANDLER(_event)                      \
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOn##_event##Listener)
 
+#define NS_DISCONNECT_EVENT_HANDLER(_event)                                   \
+  if (mOn##_event##Listener) { mOn##_event##Listener->Disconnect(); }
+
 #define NS_UNMARK_LISTENER_WRAPPER(_event)                       \
   if (tmp->mOn##_event##Listener) {                              \
     nsCOMPtr<nsIXPConnectWrappedJS> wjs =                        \
       do_QueryInterface(tmp->mOn##_event##Listener->GetInner()); \
     xpc_UnmarkGrayObject(wjs);                                   \
   }
 
 #endif // nsDOMEventTargetHelper_h_
--- a/dom/base/DOMRequest.cpp
+++ b/dom/base/DOMRequest.cpp
@@ -17,21 +17,18 @@ using mozilla::dom::DOMRequest;
 using mozilla::dom::DOMRequestService;
 
 DOMRequest::DOMRequest(nsIDOMWindow* aWindow)
   : mDone(false)
   , mResult(JSVAL_VOID)
   , mRooted(false)
 {
   nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow);
-  mOwner = window->IsInnerWindow() ? window.get() :
-                                     window->GetCurrentInnerWindow();
-
-  nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aWindow);
-  mScriptContext = sgo->GetContext();
+  BindToOwner(window->IsInnerWindow() ? window.get() :
+                                        window->GetCurrentInnerWindow());
 }
 
 DOMCI_DATA(DOMRequest, DOMRequest)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(DOMRequest)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(DOMRequest,
                                                   nsDOMEventTargetHelper)
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -917,47 +917,39 @@ NS_IMETHODIMP Navigator::GetMozNotificat
   *aRetVal = nsnull;
 
   if (mNotification) {
     NS_ADDREF(*aRetVal = mNotification);
     return NS_OK;
   }
 
   nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
-  nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(win));
-  NS_ENSURE_TRUE(sgo && win->GetDocShell(), NS_ERROR_FAILURE);
+  NS_ENSURE_TRUE(win && win->GetDocShell(), NS_ERROR_FAILURE);
 
-  nsIScriptContext* scx = sgo->GetContext();
-  NS_ENSURE_TRUE(scx, NS_ERROR_FAILURE);
-
-  mNotification = new nsDesktopNotificationCenter(win, scx);
+  mNotification = new nsDesktopNotificationCenter(win);
 
   NS_ADDREF(*aRetVal = mNotification);
   return NS_OK;
 }
 
 //*****************************************************************************
 //    Navigator::nsIDOMNavigatorBattery
 //*****************************************************************************
 
 NS_IMETHODIMP
 Navigator::GetMozBattery(nsIDOMMozBatteryManager** aBattery)
 {
   if (!mBatteryManager) {
     *aBattery = nsnull;
 
     nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mWindow));
-    nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(win));
-    NS_ENSURE_TRUE(sgo && win->GetDocShell(), NS_OK);
-
-    nsIScriptContext* scx = sgo->GetContext();
-    NS_ENSURE_TRUE(scx, NS_OK);
+    NS_ENSURE_TRUE(win->GetDocShell(), NS_OK);
 
     mBatteryManager = new battery::BatteryManager();
-    mBatteryManager->Init(win, scx);
+    mBatteryManager->Init(win);
   }
 
   NS_ADDREF(*aBattery = mBatteryManager);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -1078,24 +1070,18 @@ Navigator::GetMozSms(nsIDOMMozSmsManager
   if (!mSmsManager) {
     if (!IsSmsSupported() || !IsSmsAllowed()) {
       return NS_OK;
     }
 
     nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
     NS_ENSURE_TRUE(window && window->GetDocShell(), NS_OK);
 
-    nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(window);
-    NS_ENSURE_TRUE(sgo, NS_OK);
-
-    nsIScriptContext* scx = sgo->GetContext();
-    NS_ENSURE_TRUE(scx, NS_OK);
-
     mSmsManager = new sms::SmsManager();
-    mSmsManager->Init(window, scx);
+    mSmsManager->Init(window);
   }
 
   NS_ADDREF(*aSmsManager = mSmsManager);
 
   return NS_OK;
 }
 
 #ifdef MOZ_B2G_RIL
@@ -1134,24 +1120,18 @@ NS_IMETHODIMP
 Navigator::GetMozConnection(nsIDOMMozConnection** aConnection)
 {
   *aConnection = nsnull;
 
   if (!mConnection) {
     nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
     NS_ENSURE_TRUE(window && window->GetDocShell(), NS_OK);
 
-    nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(window);
-    NS_ENSURE_TRUE(sgo, NS_OK);
-
-    nsIScriptContext* scx = sgo->GetContext();
-    NS_ENSURE_TRUE(scx, NS_OK);
-
     mConnection = new network::Connection();
-    mConnection->Init(window, scx);
+    mConnection->Init(window);
   }
 
   NS_ADDREF(*aConnection = mConnection);
   return NS_OK;
 }
 
 #ifdef MOZ_B2G_BT
 //*****************************************************************************
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -248,16 +248,17 @@
 #include "mozilla/dom/StructuredCloneTags.h"
 
 #include "nsRefreshDriver.h"
 #include "mozAutoDocUpdate.h"
 
 #include "mozilla/Telemetry.h"
 #include "nsLocation.h"
 #include "nsWrapperCacheInlines.h"
+#include "nsDOMEventTargetHelper.h"
 
 #ifdef ANDROID
 #include <android/log.h>
 #endif
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gDOMLeakPRLog;
 #endif
@@ -962,16 +963,18 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalW
     PR_LOG(gDOMLeakPRLog, PR_LOG_DEBUG,
            ("DOMWINDOW %p created outer=%p", this, aOuterWindow));
 #endif
 
   NS_ASSERTION(sWindowsById, "Windows hash table must be created!");
   NS_ASSERTION(!sWindowsById->Get(mWindowID),
                "This window shouldn't be in the hash table yet!");
   sWindowsById->Put(mWindowID, this);
+
+  mEventTargetObjects.Init();
 }
 
 /* static */
 void
 nsGlobalWindow::Init()
 {
   CallGetService(NS_ENTROPYCOLLECTOR_CONTRACTID, &gEntropyCollector);
   NS_ASSERTION(gEntropyCollector,
@@ -988,18 +991,29 @@ nsGlobalWindow::Init()
   // should happen.
 #ifdef DEBUG
   NS_ASSERTION(sWindowsById->Init(), "Init() should not fail!");
 #else
   sWindowsById->Init();
 #endif
 }
 
+static PLDHashOperator
+DisconnectEventTargetObjects(nsPtrHashKey<nsDOMEventTargetHelper>* aKey,
+                             void* aClosure)
+{
+  aKey->GetKey()->DisconnectFromOwner();
+  return PL_DHASH_NEXT;
+}
+
 nsGlobalWindow::~nsGlobalWindow()
 {
+  mEventTargetObjects.EnumerateEntries(DisconnectEventTargetObjects, nsnull);
+  mEventTargetObjects.Clear();
+
   // We have to check if sWindowsById isn't null because ::Shutdown might have
   // been called.
   if (sWindowsById) {
     NS_ASSERTION(sWindowsById->Get(mWindowID),
                  "This window should be in the hash table");
     sWindowsById->Remove(mWindowID);
   }
 
@@ -1077,16 +1091,28 @@ nsGlobalWindow::~nsGlobalWindow()
   }
 
   DisableDeviceMotionUpdates();
   mHasDeviceMotion = false;
 
   nsLayoutStatics::Release();
 }
 
+void
+nsGlobalWindow::AddEventTargetObject(nsDOMEventTargetHelper* aObject)
+{
+  mEventTargetObjects.PutEntry(aObject);
+}
+
+void
+nsGlobalWindow::RemoveEventTargetObject(nsDOMEventTargetHelper* aObject)
+{
+  mEventTargetObjects.RemoveEntry(aObject);
+}
+
 // static
 void
 nsGlobalWindow::ShutDown()
 {
   if (gDumpFile && gDumpFile != stdout) {
     fclose(gDumpFile);
   }
   gDumpFile = nsnull;
@@ -1141,16 +1167,19 @@ nsGlobalWindow::CleanUp(bool aIgnoreModa
       return;
     }
   }
 
   // Guarantee idempotence.
   if (mCleanedUp)
     return;
   mCleanedUp = true;
+  
+  mEventTargetObjects.EnumerateEntries(DisconnectEventTargetObjects, nsnull);
+  mEventTargetObjects.Clear();
 
   if (mObserver) {
     nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
     if (os) {
       os->RemoveObserver(mObserver, NS_IOSERVICE_OFFLINE_STATUS_TOPIC);
       os->RemoveObserver(mObserver, "dom-storage2-changed");
       os->RemoveObserver(mObserver, "dom-storage-changed");
     }
@@ -3328,21 +3357,18 @@ nsGlobalWindow::GetApplicationCache(nsID
     nsCOMPtr<nsIURI> uri;
     nsresult rv = webNav->GetCurrentURI(getter_AddRefs(uri));
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument);
     nsCOMPtr<nsIURI> manifestURI;
     nsContentUtils::GetOfflineAppManifest(doc, getter_AddRefs(manifestURI));
 
-    nsIScriptContext* scriptContext = GetContext();
-    NS_ENSURE_STATE(scriptContext);
-
     nsRefPtr<nsDOMOfflineResourceList> applicationCache =
-      new nsDOMOfflineResourceList(manifestURI, uri, this, scriptContext);
+      new nsDOMOfflineResourceList(manifestURI, uri, this);
     NS_ENSURE_TRUE(applicationCache, NS_ERROR_OUT_OF_MEMORY);
 
     applicationCache->Init();
 
     mApplicationCache = applicationCache;
   }
 
   NS_IF_ADDREF(*aApplicationCache = mApplicationCache);
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -129,17 +129,17 @@ class nsHistory;
 class nsPerformance;
 class nsIDocShellLoadInfo;
 class WindowStateHolder;
 class nsGlobalWindowObserver;
 class nsGlobalWindow;
 class nsDummyJavaPluginOwner;
 class PostMessageEvent;
 class nsRunnable;
-
+class nsDOMEventTargetHelper;
 class nsDOMOfflineResourceList;
 class nsDOMMozURLProperty;
 
 #ifdef MOZ_DISABLE_DOMCRYPTO
 class nsIDOMCrypto;
 #endif
 
 class nsWindowSizes;
@@ -586,16 +586,19 @@ public:
 
   static WindowByIdTable* GetWindowsTable() {
     return sWindowsById;
   }
 
   void SizeOfIncludingThis(nsWindowSizes* aWindowSizes) const;
 
   void UnmarkGrayTimers();
+
+  void AddEventTargetObject(nsDOMEventTargetHelper* aObject);
+  void RemoveEventTargetObject(nsDOMEventTargetHelper* aObject);
 private:
   // Enable updates for the accelerometer.
   void EnableDeviceMotionUpdates();
 
   // Disables updates for the accelerometer.
   void DisableDeviceMotionUpdates();
 
   // Implements Get{Real,Scriptable}Top.
@@ -1006,16 +1009,18 @@ protected:
   // checkbox is shown. In the case of ShowModalDialog another Confirm
   // dialog will be shown, the result of the checkbox/confirm dialog
   // will be stored in mDialogDisabled variable.
   TimeStamp                     mLastDialogQuitTime;
   bool                          mDialogDisabled;
 
   nsRefPtr<nsDOMMozURLProperty> mURLProperty;
 
+  nsTHashtable<nsPtrHashKey<nsDOMEventTargetHelper> > mEventTargetObjects;
+
   friend class nsDOMScriptableHelper;
   friend class nsDOMWindowUtils;
   friend class PostMessageEvent;
 
   static WindowByIdTable* sWindowsById;
   static bool sWarnedAboutWindowInternal;
 };
 
--- a/dom/battery/BatteryManager.cpp
+++ b/dom/battery/BatteryManager.cpp
@@ -88,21 +88,19 @@ NS_IMPL_RELEASE_INHERITED(BatteryManager
 BatteryManager::BatteryManager()
   : mLevel(kDefaultLevel)
   , mCharging(kDefaultCharging)
   , mRemainingTime(kDefaultRemainingTime)
 {
 }
 
 void
-BatteryManager::Init(nsPIDOMWindow *aWindow, nsIScriptContext* aScriptContext)
+BatteryManager::Init(nsPIDOMWindow *aWindow)
 {
-  // Those vars come from nsDOMEventTargetHelper.
-  mOwner = aWindow;
-  mScriptContext = aScriptContext;
+  BindToOwner(aWindow);
 
   hal::RegisterBatteryObserver(this);
 
   hal::BatteryInformation batteryInfo;
   hal::GetCurrentBatteryInformation(&batteryInfo);
 
   UpdateFromBatteryInfo(batteryInfo);
 }
--- a/dom/battery/BatteryManager.h
+++ b/dom/battery/BatteryManager.h
@@ -63,17 +63,17 @@ class BatteryManager : public nsDOMEvent
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMMOZBATTERYMANAGER
   NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
 
   BatteryManager();
 
-  void Init(nsPIDOMWindow *aWindow, nsIScriptContext* aScriptContext);
+  void Init(nsPIDOMWindow *aWindow);
   void Shutdown();
 
   // For IObserver.
   void Notify(const hal::BatteryInformation& aBatteryInfo);
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(BatteryManager,
                                            nsDOMEventTargetHelper)
 
--- a/dom/indexedDB/IDBCursor.cpp
+++ b/dom/indexedDB/IDBCursor.cpp
@@ -257,18 +257,16 @@ IDBCursor::CreateCommon(IDBRequest* aReq
   NS_ASSERTION(aTransaction, "Null pointer!");
   NS_ASSERTION(aObjectStore, "Null pointer!");
   NS_ASSERTION(!aContinueQuery.IsEmpty(), "Empty query!");
   NS_ASSERTION(!aContinueToQuery.IsEmpty(), "Empty query!");
 
   nsRefPtr<IDBCursor> cursor = new IDBCursor();
 
   IDBDatabase* database = aTransaction->Database();
-  cursor->mScriptContext = database->GetScriptContext();
-  cursor->mOwner = database->GetOwner();
   cursor->mScriptOwner = database->GetScriptOwner();
 
   if (cursor->mScriptOwner) {
     if (NS_FAILED(NS_HOLD_JS_OBJECTS(cursor, IDBCursor))) {
       return nsnull;
     }
 
     cursor->mRooted = true;
@@ -371,18 +369,16 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(IDBCursor
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(IDBCursor)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mRequest,
                                                        nsIDOMEventTarget)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mTransaction,
                                                        nsIDOMEventTarget)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mObjectStore)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mIndex)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOwner)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptContext)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(IDBCursor)
   NS_ASSERTION(tmp->mHaveCachedKey || JSVAL_IS_VOID(tmp->mCachedKey),
                "Should have a cached key");
   NS_ASSERTION(tmp->mHaveCachedPrimaryKey ||
                JSVAL_IS_VOID(tmp->mCachedPrimaryKey),
                "Should have a cached primary key");
@@ -416,18 +412,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ID
     tmp->mCachedValue = JSVAL_VOID;
     tmp->mHaveCachedKey = false;
     tmp->mHaveCachedPrimaryKey = false;
     tmp->mHaveCachedValue = false;
     tmp->mRooted = false;
     tmp->mHaveValue = false;
   }
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mRequest)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOwner)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mScriptContext)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IDBCursor)
   NS_INTERFACE_MAP_ENTRY(nsIIDBCursor)
   NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIIDBCursorWithValue, mType != INDEXKEY)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(IDBCursorWithValue,
                                                    mType != INDEXKEY)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(IDBCursor,
--- a/dom/indexedDB/IDBCursor.h
+++ b/dom/indexedDB/IDBCursor.h
@@ -147,18 +147,16 @@ protected:
   ContinueInternal(const Key& aKey,
                    PRInt32 aCount);
 
   nsRefPtr<IDBRequest> mRequest;
   nsRefPtr<IDBTransaction> mTransaction;
   nsRefPtr<IDBObjectStore> mObjectStore;
   nsRefPtr<IDBIndex> mIndex;
 
-  nsCOMPtr<nsIScriptContext> mScriptContext;
-  nsCOMPtr<nsPIDOMWindow> mOwner;
   JSObject* mScriptOwner;
 
   Type mType;
   PRUint16 mDirection;
   nsCString mContinueQuery;
   nsCString mContinueToQuery;
 
   // These are cycle-collected!
--- a/dom/indexedDB/IDBDatabase.cpp
+++ b/dom/indexedDB/IDBDatabase.cpp
@@ -157,18 +157,17 @@ IDBDatabase::Create(IDBWrapperCache* aOw
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(!aASCIIOrigin.IsEmpty(), "Empty origin!");
 
   nsRefPtr<DatabaseInfo> databaseInfo(aDatabaseInfo);
   NS_ASSERTION(databaseInfo, "Null pointer!");
 
   nsRefPtr<IDBDatabase> db(new IDBDatabase());
 
-  db->mScriptContext = aOwnerCache->GetScriptContext();
-  db->mOwner = aOwnerCache->GetOwner();
+  db->BindToOwner(aOwnerCache);
   if (!db->SetScriptOwner(aOwnerCache->GetScriptOwner())) {
     return nsnull;
   }
 
   db->mDatabaseId = databaseInfo->id;
   db->mName = databaseInfo->name;
   db->mFilePath = databaseInfo->filePath;
   databaseInfo.swap(db->mDatabaseInfo);
@@ -676,31 +675,31 @@ IDBDatabase::Close()
   return NS_OK;
 }
 
 nsresult
 IDBDatabase::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
 {
   NS_ENSURE_TRUE(aVisitor.mDOMEvent, NS_ERROR_UNEXPECTED);
 
-  if (!mOwner) {
+  if (!GetOwner()) {
     return NS_OK;
   }
 
   if (aVisitor.mEventStatus != nsEventStatus_eConsumeNoDefault) {
     nsString type;
     nsresult rv = aVisitor.mDOMEvent->GetType(type);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (type.EqualsLiteral(ERROR_EVT_STR)) {
       nsRefPtr<nsDOMEvent> duplicateEvent =
         CreateGenericEvent(type, eDoesNotBubble, eNotCancelable);
       NS_ENSURE_STATE(duplicateEvent);
 
-      nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(mOwner));
+      nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(GetOwner()));
       NS_ASSERTION(target, "How can this happen?!");
 
       bool dummy;
       rv = target->DispatchEvent(duplicateEvent, &dummy);
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
--- a/dom/indexedDB/IDBDatabase.h
+++ b/dom/indexedDB/IDBDatabase.h
@@ -98,21 +98,22 @@ public:
 
   const nsString& FilePath()
   {
     return mFilePath;
   }
 
   already_AddRefed<nsIDocument> GetOwnerDocument()
   {
-    if (!mOwner) {
+    if (!GetOwner()) {
       return nsnull;
     }
 
-    nsCOMPtr<nsIDocument> doc = do_QueryInterface(mOwner->GetExtantDocument());
+    nsCOMPtr<nsIDocument> doc =
+      do_QueryInterface(GetOwner()->GetExtantDocument());
     return doc.forget();
   }
 
   nsCString& Origin()
   {
     return mASCIIOrigin;
   }
 
--- a/dom/indexedDB/IDBFactory.cpp
+++ b/dom/indexedDB/IDBFactory.cpp
@@ -463,39 +463,32 @@ IDBFactory::OpenCommon(const nsAString& 
     // we do not end up in a side thread that asks for the path (which
     // would make ContentChild try to send a message in a thread other
     // than the main one).
     ContentChild::GetSingleton()->GetIndexedDBPath();
   }
 
   nsCOMPtr<nsPIDOMWindow> window;
   nsCOMPtr<nsIScriptGlobalObject> sgo;
-  nsIScriptContext* context = nsnull;
   JSObject* scriptOwner = nsnull;
 
   if (mWindow) {
-    sgo = do_QueryInterface(mWindow);
-    NS_ENSURE_TRUE(sgo, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
-
-    context = sgo->GetContext();
-    NS_ENSURE_TRUE(context, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
-
     window = mWindow;
   }
   else {
     scriptOwner = mOwningObject;
   }
 
   nsCString origin;
   nsresult rv =
     IndexedDatabaseManager::GetASCIIOriginFromWindow(window, origin);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsRefPtr<IDBOpenDBRequest> request =
-    IDBOpenDBRequest::Create(context, window, scriptOwner);
+    IDBOpenDBRequest::Create(window, scriptOwner);
   NS_ENSURE_TRUE(request, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
   nsRefPtr<OpenDatabaseHelper> openHelper =
     new OpenDatabaseHelper(request, aName, origin, aVersion, aDeleting);
 
   rv = openHelper->Init();
   NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
 
--- a/dom/indexedDB/IDBRequest.cpp
+++ b/dom/indexedDB/IDBRequest.cpp
@@ -81,18 +81,17 @@ IDBRequest::Create(nsISupports* aSource,
                    IDBWrapperCache* aOwnerCache,
                    IDBTransaction* aTransaction)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   nsRefPtr<IDBRequest> request(new IDBRequest());
 
   request->mSource = aSource;
   request->mTransaction = aTransaction;
-  request->mScriptContext = aOwnerCache->GetScriptContext();
-  request->mOwner = aOwnerCache->GetOwner();
+  request->BindToOwner(aOwnerCache);
   if (!request->SetScriptOwner(aOwnerCache->GetScriptOwner())) {
     return nsnull;
   }
 
   return request.forget();
 }
 
 void
@@ -138,17 +137,19 @@ IDBRequest::NotifyHelperCompleted(Helper
     if (NS_FAILED(cxStack->GetSafeJSContext(&cx))) {
       NS_WARNING("Failed to get safe JSContext!");
       rv = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
       mErrorCode = NS_ERROR_GET_CODE(rv);
       return rv;
     }
   }
   else {
-    cx = mScriptContext->GetNativeContext();
+    nsIScriptContext* sc = GetContextForEventHandlers(&rv);
+    NS_ENSURE_STATE(sc);
+    cx = sc->GetNativeContext();
     NS_ASSERTION(cx, "Failed to get a context!");
   } 
 
   JSObject* global = GetParentObject();
   NS_ASSERTION(global, "This should never be null!");
 
   JSAutoRequest ar(cx);
   JSAutoEnterCompartment ac;
@@ -305,25 +306,23 @@ IDBOpenDBRequest::~IDBOpenDBRequest()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   UnrootResultVal();
 }
 
 // static
 already_AddRefed<IDBOpenDBRequest>
-IDBOpenDBRequest::Create(nsIScriptContext* aScriptContext,
-                         nsPIDOMWindow* aOwner,
+IDBOpenDBRequest::Create(nsPIDOMWindow* aOwner,
                          JSObject* aScriptOwner)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   nsRefPtr<IDBOpenDBRequest> request(new IDBOpenDBRequest());
 
-  request->mScriptContext = aScriptContext;
-  request->mOwner = aOwner;
+  request->BindToOwner(aOwner);
   if (!request->SetScriptOwner(aScriptOwner)) {
     return nsnull;
   }
 
   return request.forget();
 }
 
 void
--- a/dom/indexedDB/IDBRequest.h
+++ b/dom/indexedDB/IDBRequest.h
@@ -132,25 +132,24 @@ class IDBOpenDBRequest : public IDBReque
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_FORWARD_NSIIDBREQUEST(IDBRequest::)
   NS_DECL_NSIIDBOPENDBREQUEST
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IDBOpenDBRequest, IDBRequest)
 
   static
   already_AddRefed<IDBOpenDBRequest>
-  Create(nsIScriptContext* aScriptContext,
-         nsPIDOMWindow* aOwner,
+  Create(nsPIDOMWindow* aOwner,
          JSObject* aScriptOwner);
 
   static
   already_AddRefed<IDBOpenDBRequest>
   Create(IDBWrapperCache* aOwnerCache)
   {
-    return Create(aOwnerCache->GetScriptContext(), aOwnerCache->GetOwner(),
+    return Create(aOwnerCache->GetOwner(),
                   aOwnerCache->GetScriptOwner());
   }
 
   void SetTransaction(IDBTransaction* aTransaction);
 
 protected:
   ~IDBOpenDBRequest();
 
--- a/dom/indexedDB/IDBTransaction.cpp
+++ b/dom/indexedDB/IDBTransaction.cpp
@@ -112,18 +112,17 @@ IDBTransaction::Create(IDBDatabase* aDat
                        nsTArray<nsString>& aObjectStoreNames,
                        PRUint16 aMode,
                        bool aDispatchDelayed)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   nsRefPtr<IDBTransaction> transaction = new IDBTransaction();
 
-  transaction->mScriptContext = aDatabase->GetScriptContext();
-  transaction->mOwner = aDatabase->GetOwner();
+  transaction->BindToOwner(aDatabase);
   if (!transaction->SetScriptOwner(aDatabase->GetScriptOwner())) {
     return nsnull;
   }
 
   transaction->mDatabase = aDatabase;
   transaction->mMode = aMode;
   
   transaction->mDatabaseInfo = aDatabase->Info();
--- a/dom/indexedDB/IDBWrapperCache.h
+++ b/dom/indexedDB/IDBWrapperCache.h
@@ -22,26 +22,16 @@ public:
                                                    nsDOMEventTargetHelper)
 
   JSObject* GetScriptOwner() const
   {
     return mScriptOwner;
   }
   bool SetScriptOwner(JSObject* aScriptOwner);
 
-  nsIScriptContext* GetScriptContext() const
-  {
-    return mScriptContext;
-  }
-
-  nsPIDOMWindow* GetOwner() const
-  {
-    return mOwner;
-  }
-
   JSObject* GetParentObject()
   {
     if (mScriptOwner) {
       return mScriptOwner;
     }
 
     // Do what nsEventTargetSH::PreCreate does.
     nsCOMPtr<nsIScriptGlobalObject> parent;
--- a/dom/network/src/Connection.cpp
+++ b/dom/network/src/Connection.cpp
@@ -81,21 +81,19 @@ NS_IMPL_RELEASE_INHERITED(Connection, ns
 
 Connection::Connection()
   : mCanBeMetered(kDefaultCanBeMetered)
   , mBandwidth(kDefaultBandwidth)
 {
 }
 
 void
-Connection::Init(nsPIDOMWindow *aWindow, nsIScriptContext* aScriptContext)
+Connection::Init(nsPIDOMWindow* aWindow)
 {
-  // Those vars come from nsDOMEventTargetHelper.
-  mOwner = aWindow;
-  mScriptContext = aScriptContext;
+  BindToOwner(aWindow);
 
   hal::RegisterNetworkObserver(this);
 
   hal::NetworkInformation networkInfo;
   hal::GetCurrentNetworkInformation(&networkInfo);
 
   UpdateFromNetworkInfo(networkInfo);
 }
--- a/dom/network/src/Connection.h
+++ b/dom/network/src/Connection.h
@@ -60,17 +60,17 @@ class Connection : public nsDOMEventTarg
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMMOZCONNECTION
 
   NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
 
   Connection();
 
-  void Init(nsPIDOMWindow *aWindow, nsIScriptContext* aScriptContext);
+  void Init(nsPIDOMWindow *aWindow);
   void Shutdown();
 
   // For IObserver
   void Notify(const hal::NetworkInformation& aNetworkInfo);
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Connection,
                                            nsDOMEventTargetHelper)
 
--- a/dom/sms/interfaces/nsISmsRequestManager.idl
+++ b/dom/sms/interfaces/nsISmsRequestManager.idl
@@ -1,18 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface nsIDOMMozSmsMessage;
 interface nsIDOMMozSmsRequest;
-interface nsPIDOMWindow;
-interface nsIScriptContext;
+interface nsIDOMMozSmsManager;
 
 %{C++
 #define SMS_REQUEST_MANAGER_CID \
 { 0xa97a3129, 0x1e0b, 0x45da,    \
 { 0xa3, 0x85, 0xcf, 0xe5, 0xb0, 0xb1, 0xc4, 0x8f } }
 #define SMS_REQUEST_MANAGER_CONTRACTID "@mozilla.org/sms/smsrequestmanager;1"
 %}
 
@@ -31,18 +30,17 @@ interface nsISmsRequestManager : nsISupp
   const unsigned short UNKNOWN_ERROR    = 3;
   const unsigned short INTERNAL_ERROR   = 4;
 
   /**
    * Create a new request object.
    *
    * @return the request ID.
    */
-  long createRequest(in nsPIDOMWindow aWindow,
-                     in nsIScriptContext aScriptContext,
+  long createRequest(in nsIDOMMozSmsManager aManager,
                      out nsIDOMMozSmsRequest aRequest);
 
   /**
    * Track an already existing request object.
    *
    * @return the request ID.
    */
   long addRequest(in nsIDOMMozSmsRequest aRequest);
--- a/dom/sms/src/SmsManager.cpp
+++ b/dom/sms/src/SmsManager.cpp
@@ -87,21 +87,19 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMozSmsManager)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozSmsManager)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(SmsManager, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(SmsManager, nsDOMEventTargetHelper)
 
 void
-SmsManager::Init(nsPIDOMWindow *aWindow, nsIScriptContext* aScriptContext)
+SmsManager::Init(nsPIDOMWindow *aWindow)
 {
-  // Those vars come from nsDOMEventTargetHelper.
-  mOwner = aWindow;
-  mScriptContext = aScriptContext;
+  BindToOwner(aWindow);
 
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   // GetObserverService() can return null is some situations like shutdown.
   if (!obs) {
     return;
   }
 
   obs->AddObserver(this, kSmsReceivedObserverTopic, false);
@@ -144,18 +142,17 @@ SmsManager::Send(JSContext* aCx, JSObjec
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIDOMMozSmsRequest> request;
 
   nsCOMPtr<nsISmsRequestManager> requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID);
 
   PRInt32 requestId;
-  nsresult rv = requestManager->CreateRequest(mOwner, mScriptContext,
-                                              getter_AddRefs(request),
+  nsresult rv = requestManager->CreateRequest(this, getter_AddRefs(request),
                                               &requestId);
   if (NS_FAILED(rv)) {
     NS_ERROR("Failed to create the request!");
     return rv;
   }
 
   nsDependentJSString number;
   number.init(aCx, aNumber);
@@ -169,25 +166,28 @@ SmsManager::Send(JSContext* aCx, JSObjec
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 SmsManager::Send(const jsval& aNumber, const nsAString& aMessage, jsval* aReturn)
 {
-  JSContext* cx = mScriptContext->GetNativeContext();
+  nsresult rv;
+  nsIScriptContext* sc = GetContextForEventHandlers(&rv);
+  NS_ENSURE_STATE(sc);
+  JSContext* cx = sc->GetNativeContext();
   NS_ASSERTION(cx, "Failed to get a context!");
 
   if (!aNumber.isString() &&
       !(aNumber.isObject() && JS_IsArrayObject(cx, &aNumber.toObject()))) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  JSObject* global = mScriptContext->GetNativeGlobal();
+  JSObject* global = sc->GetNativeGlobal();
   NS_ASSERTION(global, "Failed to get global object!");
 
   JSAutoRequest ar(cx);
   JSAutoEnterCompartment ac;
   if (!ac.enter(cx, global)) {
     NS_ERROR("Failed to enter the js compartment!");
     return NS_ERROR_FAILURE;
   }
@@ -221,18 +221,17 @@ SmsManager::Send(const jsval& aNumber, c
 }
 
 NS_IMETHODIMP
 SmsManager::GetMessageMoz(PRInt32 aId, nsIDOMMozSmsRequest** aRequest)
 {
   nsCOMPtr<nsISmsRequestManager> requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID);
 
   PRInt32 requestId;
-  nsresult rv = requestManager->CreateRequest(mOwner, mScriptContext, aRequest,
-                                              &requestId);
+  nsresult rv = requestManager->CreateRequest(this, aRequest, &requestId);
   if (NS_FAILED(rv)) {
     NS_ERROR("Failed to create the request!");
     return rv;
   }
 
   nsCOMPtr<nsISmsDatabaseService> smsDBService =
     do_GetService(SMS_DATABASE_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(smsDBService, NS_ERROR_FAILURE);
@@ -243,18 +242,17 @@ SmsManager::GetMessageMoz(PRInt32 aId, n
 }
 
 nsresult
 SmsManager::Delete(PRInt32 aId, nsIDOMMozSmsRequest** aRequest)
 {
   nsCOMPtr<nsISmsRequestManager> requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID);
 
   PRInt32 requestId;
-  nsresult rv = requestManager->CreateRequest(mOwner, mScriptContext, aRequest,
-                                              &requestId);
+  nsresult rv = requestManager->CreateRequest(this, aRequest, &requestId);
   if (NS_FAILED(rv)) {
     NS_ERROR("Failed to create the request!");
     return rv;
   }
 
   nsCOMPtr<nsISmsDatabaseService> smsDBService =
     do_GetService(SMS_DATABASE_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(smsDBService, NS_ERROR_FAILURE);
@@ -270,19 +268,22 @@ SmsManager::Delete(const jsval& aParam, 
   if (aParam.isInt32()) {
     return Delete(aParam.toInt32(), aRequest);
   }
 
   if (!aParam.isObject()) {
     return NS_ERROR_INVALID_ARG;
   }
 
+  nsresult rv;
+  nsIScriptContext* sc = GetContextForEventHandlers(&rv);
+  NS_ENSURE_STATE(sc);
   nsCOMPtr<nsIDOMMozSmsMessage> message =
     do_QueryInterface(nsContentUtils::XPConnect()->GetNativeOfWrapper(
-          mScriptContext->GetNativeContext(), &aParam.toObject()));
+          sc->GetNativeContext(), &aParam.toObject()));
   NS_ENSURE_TRUE(message, NS_ERROR_INVALID_ARG);
 
   PRInt32 id;
   message->GetId(&id);
 
   return Delete(id, aRequest);
 }
 
@@ -294,17 +295,17 @@ SmsManager::GetMessages(nsIDOMMozSmsFilt
 
   if (!filter) {
     filter = new SmsFilter();
   }
 
   nsCOMPtr<nsISmsRequestManager> requestManager = do_GetService(SMS_REQUEST_MANAGER_CONTRACTID);
 
   PRInt32 requestId;
-  nsresult rv = requestManager->CreateRequest(mOwner, mScriptContext, aRequest,
+  nsresult rv = requestManager->CreateRequest(this, aRequest,
                                               &requestId);
   if (NS_FAILED(rv)) {
     NS_ERROR("Failed to create the request!");
     return rv;
   }
 
   nsCOMPtr<nsISmsDatabaseService> smsDBService =
     do_GetService(SMS_DATABASE_SERVICE_CONTRACTID);
--- a/dom/sms/src/SmsManager.h
+++ b/dom/sms/src/SmsManager.h
@@ -57,17 +57,17 @@ public:
   NS_DECL_NSIOBSERVER
   NS_DECL_NSIDOMMOZSMSMANAGER
 
   NS_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper::)
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SmsManager,
                                            nsDOMEventTargetHelper)
 
-  void Init(nsPIDOMWindow *aWindow, nsIScriptContext* aScriptContext);
+  void Init(nsPIDOMWindow *aWindow);
   void Shutdown();
 
 private:
   /**
    * Internal Send() method used to send one message.
    */
   nsresult Send(JSContext* aCx, JSObject* aGlobal, JSString* aNumber,
                 const nsAString& aMessage, jsval* aRequest);
--- a/dom/sms/src/SmsRequest.cpp
+++ b/dom/sms/src/SmsRequest.cpp
@@ -37,16 +37,17 @@
 
 #include "SmsRequest.h"
 #include "nsIDOMClassInfo.h"
 #include "nsDOMString.h"
 #include "nsContentUtils.h"
 #include "nsIDOMSmsMessage.h"
 #include "nsIDOMSmsCursor.h"
 #include "nsISmsRequestManager.h"
+#include "SmsManager.h"
 
 DOMCI_DATA(MozSmsRequest, mozilla::dom::sms::SmsRequest)
 
 namespace mozilla {
 namespace dom {
 namespace sms {
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(SmsRequest)
@@ -85,25 +86,23 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(SmsRequest, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(SmsRequest, nsDOMEventTargetHelper)
 
 NS_IMPL_EVENT_HANDLER(SmsRequest, success)
 NS_IMPL_EVENT_HANDLER(SmsRequest, error)
 
-SmsRequest::SmsRequest(nsPIDOMWindow* aWindow, nsIScriptContext* aScriptContext)
+SmsRequest::SmsRequest(SmsManager* aManager)
   : mResult(JSVAL_VOID)
   , mResultRooted(false)
   , mError(nsISmsRequestManager::SUCCESS_NO_ERROR)
   , mDone(false)
 {
-  // Those vars come from nsDOMEventTargetHelper.
-  mOwner = aWindow;
-  mScriptContext = aScriptContext;
+  BindToOwner(aManager);
 }
 
 SmsRequest::~SmsRequest()
 {
   if (mResultRooted) {
     UnrootResult();
   }
 }
@@ -176,20 +175,27 @@ SmsRequest::SetSuccess(nsIDOMMozSmsCurso
 bool
 SmsRequest::SetSuccessInternal(nsISupports* aObject)
 {
   NS_PRECONDITION(!mDone, "mDone shouldn't have been set to true already!");
   NS_PRECONDITION(mError == nsISmsRequestManager::SUCCESS_NO_ERROR,
                   "mError shouldn't have been set!");
   NS_PRECONDITION(mResult == JSVAL_VOID, "mResult shouldn't have been set!");
 
-  JSContext* cx = mScriptContext->GetNativeContext();
+  nsresult rv;
+  nsIScriptContext* sc = GetContextForEventHandlers(&rv);
+  if (!sc) {
+    SetError(nsISmsRequestManager::INTERNAL_ERROR);
+    return false;
+  }
+
+  JSContext* cx = sc->GetNativeContext();    
   NS_ASSERTION(cx, "Failed to get a context!");
 
-  JSObject* global = mScriptContext->GetNativeGlobal();
+  JSObject* global = sc->GetNativeGlobal();
   NS_ASSERTION(global, "Failed to get global object!");
 
   JSAutoRequest ar(cx);
   JSAutoEnterCompartment ac;
   if (!ac.enter(cx, global)) {
     SetError(nsISmsRequestManager::INTERNAL_ERROR);
     return false;
   }
--- a/dom/sms/src/SmsRequest.h
+++ b/dom/sms/src/SmsRequest.h
@@ -42,16 +42,17 @@
 #include "nsDOMEventTargetHelper.h"
 
 class nsIDOMMozSmsMessage;
 class nsIDOMMozSmsCursor;
 
 namespace mozilla {
 namespace dom {
 namespace sms {
+class SmsManager;
 
 class SmsRequest : public nsIDOMMozSmsRequest
                  , public nsDOMEventTargetHelper
 {
 public:
   friend class SmsRequestManager;
 
   NS_DECL_ISUPPORTS
@@ -62,17 +63,17 @@ public:
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(SmsRequest,
                                                          nsDOMEventTargetHelper)
 
   void Reset();
 
 private:
   SmsRequest() MOZ_DELETE;
 
-  SmsRequest(nsPIDOMWindow* aWindow, nsIScriptContext* aScriptContext);
+  SmsRequest(SmsManager* aManager);
   ~SmsRequest();
 
   /**
    * Root mResult (jsval) to prevent garbage collection.
    */
   void RootResult();
 
   /**
--- a/dom/sms/src/SmsRequestManager.cpp
+++ b/dom/sms/src/SmsRequestManager.cpp
@@ -34,16 +34,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "SmsRequestManager.h"
 #include "nsIDOMSmsMessage.h"
 #include "nsDOMEvent.h"
 #include "SmsCursor.h"
+#include "SmsManager.h"
 
 /**
  * We have to use macros here because our leak analysis tool things we are
  * leaking strings when we have |static const nsString|. Sad :(
  */
 #define SUCCESS_EVENT_NAME NS_LITERAL_STRING("success")
 #define ERROR_EVENT_NAME   NS_LITERAL_STRING("error")
 
@@ -73,23 +74,22 @@ SmsRequestManager::AddRequest(nsIDOMMozS
 
   mRequests.AppendObject(aRequest);
   *aRequestId = size;
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
-SmsRequestManager::CreateRequest(nsPIDOMWindow* aWindow,
-                                 nsIScriptContext* aScriptContext,
+SmsRequestManager::CreateRequest(nsIDOMMozSmsManager* aManager,
                                  nsIDOMMozSmsRequest** aRequest,
                                  PRInt32* aRequestId)
 {
   nsCOMPtr<nsIDOMMozSmsRequest> request =
-    new SmsRequest(aWindow, aScriptContext);
+    new SmsRequest(static_cast<SmsManager*>(aManager));
 
   PRInt32 size = mRequests.Count();
 
   // Look for empty slots.
   for (PRInt32 i=0; i<size; ++i) {
     if (mRequests[i]) {
       continue;
     }
--- a/dom/src/notification/nsDesktopNotification.cpp
+++ b/dom/src/notification/nsDesktopNotification.cpp
@@ -94,28 +94,25 @@ NS_INTERFACE_MAP_END_INHERITING(nsDOMEve
 
 NS_IMPL_ADDREF_INHERITED(nsDOMDesktopNotification, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(nsDOMDesktopNotification, nsDOMEventTargetHelper)
 
 nsDOMDesktopNotification::nsDOMDesktopNotification(const nsAString & title,
                                                    const nsAString & description,
                                                    const nsAString & iconURL,
                                                    nsPIDOMWindow *aWindow,
-                                                   nsIScriptContext* aScriptContext,
                                                    nsIURI* uri)
   : mTitle(title)
   , mDescription(description)
   , mIconURL(iconURL)
   , mURI(uri)
   , mAllow(false)
   , mShowHasBeenCalled(false)
 {
-  mOwner = aWindow;
-  mScriptContext = aScriptContext;
-
+  BindToOwner(aWindow);
   if (Preferences::GetBool("notification.disabled", false)) {
     return;
   }
 
   // If we are in testing mode (running mochitests, for example)
   // and we are suppose to allow requests, then just post an allow event.
   if (Preferences::GetBool("notification.prompt.testing", false) &&
       Preferences::GetBool("notification.prompt.testing.allow", true)) {
@@ -126,22 +123,22 @@ nsDOMDesktopNotification::nsDOMDesktopNo
   nsRefPtr<nsDesktopNotificationRequest> request = new nsDesktopNotificationRequest(this);
 
   // if we are in the content process, then remote it to the parent.
   if (XRE_GetProcessType() == GeckoProcessType_Content) {
 
     // if for some reason mOwner is null, just silently
     // bail.  The user will not see a notification, and that
     // is fine.
-    if (!mOwner)
+    if (!GetOwner())
       return;
 
     // because owner implements nsITabChild, we can assume that it is
     // the one and only TabChild for this docshell.
-    TabChild* child = GetTabChildFrom(mOwner->GetDocShell());
+    TabChild* child = GetTabChildFrom(GetOwner()->GetDocShell());
     
     // Retain a reference so the object isn't deleted without IPDL's knowledge.
     // Corresponding release occurs in DeallocPContentPermissionRequest.
     nsRefPtr<nsDesktopNotificationRequest> copy = request;
 
     nsCString type = NS_LITERAL_CSTRING("desktop-notification");
     child->SendPContentPermissionRequestConstructor(copy.forget().get(), type, IPC::URI(mURI));
     
@@ -258,21 +255,21 @@ NS_IMPL_ADDREF(nsDesktopNotificationCent
 NS_IMPL_RELEASE(nsDesktopNotificationCenter)
 
 NS_IMETHODIMP
 nsDesktopNotificationCenter::CreateNotification(const nsAString & title,
                                                 const nsAString & description,
                                                 const nsAString & iconURL,
                                                 nsIDOMDesktopNotification **aResult)
 {
+  NS_ENSURE_STATE(mOwner);
   nsRefPtr<nsIDOMDesktopNotification> notification = new nsDOMDesktopNotification(title, 
                                                                                   description,
                                                                                   iconURL,
                                                                                   mOwner,
-                                                                                  mScriptContext,
                                                                                   mURI);
   notification.forget(aResult);
   return NS_OK;
 }
 
 
 /* ------------------------------------------------------------------------ */
 /* nsDesktopNotificationRequest                                             */
@@ -293,17 +290,18 @@ nsDesktopNotificationRequest::GetUri(nsI
 }
 
 NS_IMETHODIMP
 nsDesktopNotificationRequest::GetWindow(nsIDOMWindow * *aRequestingWindow)
 {
   if (!mDesktopNotification)
     return NS_ERROR_NOT_INITIALIZED;
 
-  nsCOMPtr<nsIDOMWindow> window = do_QueryInterface(mDesktopNotification->mOwner);
+  nsCOMPtr<nsIDOMWindow> window =
+    do_QueryInterface(mDesktopNotification->GetOwner());
   NS_IF_ADDREF(*aRequestingWindow = window);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDesktopNotificationRequest::GetElement(nsIDOMElement * *aElement)
 {
   return NS_ERROR_FAILURE;
--- a/dom/src/notification/nsDesktopNotification.h
+++ b/dom/src/notification/nsDesktopNotification.h
@@ -67,41 +67,37 @@ class AlertServiceObserver;
  * Object hangs off of the navigator object and hands out nsDOMDesktopNotification objects
  */
 class nsDesktopNotificationCenter : public nsIDOMDesktopNotificationCenter
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMDESKTOPNOTIFICATIONCENTER
 
-  nsDesktopNotificationCenter(nsPIDOMWindow *aWindow,
-                              nsIScriptContext* aScriptContext)
+  nsDesktopNotificationCenter(nsPIDOMWindow *aWindow)
   {
     mOwner = aWindow;
-    mScriptContext = aScriptContext;
 
     // Grab the uri of the document
     nsCOMPtr<nsIDOMDocument> domdoc;
     mOwner->GetDocument(getter_AddRefs(domdoc));
     nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
     doc->NodePrincipal()->GetURI(getter_AddRefs(mURI));
   }
 
   virtual ~nsDesktopNotificationCenter()
   {
   }
 
   void Shutdown() {
     mOwner = nsnull;
-    mScriptContext = nsnull;
   }
 
 private:
   nsCOMPtr<nsPIDOMWindow> mOwner;
-  nsCOMPtr<nsIScriptContext> mScriptContext;
   nsCOMPtr<nsIURI> mURI;
 };
 
 
 class nsDOMDesktopNotification : public nsDOMEventTargetHelper,
                                  public nsIDOMDesktopNotification
 {
   friend class nsDesktopNotificationRequest;
@@ -110,17 +106,16 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMDesktopNotification,nsDOMEventTargetHelper)
   NS_DECL_NSIDOMDESKTOPNOTIFICATION
 
   nsDOMDesktopNotification(const nsAString & title,
                            const nsAString & description,
                            const nsAString & iconURL,
                            nsPIDOMWindow *aWindow,
-                           nsIScriptContext* aScriptContext,
                            nsIURI* uri);
 
   virtual ~nsDOMDesktopNotification();
 
   /*
    * PostDesktopNotification
    * Uses alert service to display a notification
    */
--- a/dom/src/offline/nsDOMOfflineResourceList.cpp
+++ b/dom/src/offline/nsDOMOfflineResourceList.cpp
@@ -133,28 +133,26 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(OfflineResourceList)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(nsDOMOfflineResourceList, nsDOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(nsDOMOfflineResourceList, nsDOMEventTargetHelper)
 
 nsDOMOfflineResourceList::nsDOMOfflineResourceList(nsIURI *aManifestURI,
                                                    nsIURI *aDocumentURI,
-                                                   nsPIDOMWindow *aWindow,
-                                                   nsIScriptContext* aScriptContext)
+                                                   nsPIDOMWindow *aWindow)
   : mInitialized(false)
   , mManifestURI(aManifestURI)
   , mDocumentURI(aDocumentURI)
   , mExposeCacheUpdateStatus(true)
   , mStatus(nsIDOMOfflineResourceList::IDLE)
   , mCachedKeys(nsnull)
   , mCachedKeysCount(0)
 {
-  mOwner = aWindow;
-  mScriptContext = aScriptContext;
+  BindToOwner(aWindow);
 }
 
 nsDOMOfflineResourceList::~nsDOMOfflineResourceList()
 {
   ClearCachedKeys();
 }
 
 nsresult
@@ -505,17 +503,17 @@ nsDOMOfflineResourceList::Update()
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
     do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIDOMWindow> window = 
-    do_QueryInterface(mOwner);
+    do_QueryInterface(GetOwner());
 
   nsCOMPtr<nsIOfflineCacheUpdate> update;
   rv = updateService->ScheduleUpdate(mManifestURI, mDocumentURI,
                                      window, getter_AddRefs(update));
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
@@ -685,21 +683,21 @@ nsDOMOfflineResourceList::FirePendingEve
   }
   mPendingEvents.Clear();
 }
 
 nsresult
 nsDOMOfflineResourceList::SendEvent(const nsAString &aEventName)
 {
   // Don't send events to closed windows
-  if (!mOwner) {
+  if (!GetOwner()) {
     return NS_OK;
   }
 
-  if (!mOwner->GetDocShell()) {
+  if (!GetOwner()->GetDocShell()) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIDOMEvent> event;
   nsresult rv = nsEventDispatcher::CreateEvent(nsnull, nsnull,
                                                NS_LITERAL_STRING("Events"),
                                                getter_AddRefs(event));
   NS_ENSURE_SUCCESS(rv, rv);
@@ -711,17 +709,17 @@ nsDOMOfflineResourceList::SendEvent(cons
 
   event->InitEvent(aEventName, false, true);
 
   // We assume anyone that managed to call SendEvent is trusted
   privevent->SetTrusted(true);
 
   // If the window is frozen or we're still catching up on events that were
   // queued while frozen, save the event for later.
-  if (mOwner->IsFrozen() || mPendingEvents.Count() > 0) {
+  if (GetOwner()->IsFrozen() || mPendingEvents.Count() > 0) {
     mPendingEvents.AppendObject(event);
     return NS_OK;
   }
 
   bool dummy;
   DispatchEvent(event, &dummy);
 
   return NS_OK;
@@ -848,17 +846,17 @@ nsDOMOfflineResourceList::UpdateAdded(ns
   mCacheUpdate->AddObserver(this, true);
 
   return NS_OK;
 }
 
 already_AddRefed<nsIApplicationCacheContainer>
 nsDOMOfflineResourceList::GetDocumentAppCacheContainer()
 {
-  nsCOMPtr<nsIWebNavigation> webnav = do_GetInterface(mOwner);
+  nsCOMPtr<nsIWebNavigation> webnav = do_GetInterface(GetOwner());
   if (!webnav) {
     return nsnull;
   }
 
   nsCOMPtr<nsIApplicationCacheContainer> appCacheContainer =
     do_GetInterface(webnav);
   return appCacheContainer.forget();
 }
--- a/dom/src/offline/nsDOMOfflineResourceList.h
+++ b/dom/src/offline/nsDOMOfflineResourceList.h
@@ -73,18 +73,17 @@ public:
   NS_DECL_NSIOBSERVER
   NS_DECL_NSIOFFLINECACHEUPDATEOBSERVER
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsDOMOfflineResourceList,
                                            nsDOMEventTargetHelper)
 
   nsDOMOfflineResourceList(nsIURI* aManifestURI,
                            nsIURI* aDocumentURI,
-                           nsPIDOMWindow* aWindow,
-                           nsIScriptContext* aScriptContext);
+                           nsPIDOMWindow* aWindow);
   virtual ~nsDOMOfflineResourceList();
 
   void FirePendingEvents();
   void Disconnect();
 
   nsresult Init();
 
 private: