Bug 403168, r=jonas, sr=jst, a=blocking1.9
authorOlli.Pettay@helsinki.fi
Wed, 12 Dec 2007 00:33:32 -0800
changeset 8947 fce062922614e8a31eddf68477219e823cc15d77
parent 8946 32375188195aa0cf74ea0a204bfd299a83923e26
child 8948 9eff567b8e73a6a11f182613c592dd087c85efb8
push idunknown
push userunknown
push dateunknown
reviewersjonas, jst, blocking1.9
bugs403168
milestone1.9b3pre
Bug 403168, r=jonas, sr=jst, a=blocking1.9
content/base/src/nsDOMParser.cpp
content/base/src/nsDOMParser.h
content/base/src/nsDocument.cpp
content/base/src/nsXMLHttpRequest.cpp
content/base/src/nsXMLHttpRequest.h
content/html/content/src/nsHTMLImageElement.cpp
content/html/content/src/nsHTMLOptionElement.cpp
content/xslt/src/xslt/txMozillaXSLTProcessor.cpp
content/xslt/src/xslt/txMozillaXSLTProcessor.h
dom/public/nsIJSNativeInitializer.h
dom/src/base/nsDOMClassInfo.cpp
layout/build/nsLayoutModule.cpp
--- a/content/base/src/nsDOMParser.cpp
+++ b/content/base/src/nsDOMParser.cpp
@@ -52,16 +52,18 @@
 #include "nsCRT.h"
 #include "nsLoadListenerProxy.h"
 #include "nsStreamUtils.h"
 #include "nsThreadUtils.h"
 #include "nsNetCID.h"
 #include "nsContentUtils.h"
 #include "nsDOMJSUtils.h"
 #include "nsDOMError.h"
+#include "nsIDOMWindow.h"
+#include "nsPIDOMWindow.h"
 
 // nsIDOMEventListener
 nsresult
 nsDOMParser::HandleEvent(nsIDOMEvent* aEvent)
 {
   return NS_OK;
 }
 
@@ -421,17 +423,17 @@ GetInitArgs(JSContext *cx, PRUint32 argc
 
   NS_IF_ADDREF(*aPrincipal = prin);
   NS_IF_ADDREF(*aDocumentURI = documentURI);
   NS_IF_ADDREF(*aBaseURI = baseURI);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMParser::Initialize(JSContext *cx, JSObject* obj,
+nsDOMParser::Initialize(nsISupports* aOwner, JSContext* cx, JSObject* obj,
                         PRUint32 argc, jsval *argv)
 {
   AttemptedInitMarker marker(&mAttemptedInit);
   nsCOMPtr<nsIPrincipal> prin;
   nsCOMPtr<nsIURI> documentURI;
   nsCOMPtr<nsIURI> baseURI;
   if (argc > 0) {
     nsresult rv = GetInitArgs(cx, argc, argv, getter_AddRefs(prin),
@@ -458,30 +460,34 @@ nsDOMParser::Initialize(JSContext *cx, J
     // Note that this is a behavior change as far as I can tell -- we're now
     // using the base URI and document URI of the window off of which the
     // DOMParser is created, not the window in which parse*() is called.
     // Does that matter?
 
     // Also note that |cx| matches what GetDocumentFromContext() would return,
     // while GetDocumentFromCaller() gives us the window that the DOMParser()
     // call was made on.
-    
-    nsCOMPtr<nsIDocument> doc =
-      do_QueryInterface(nsContentUtils::GetDocumentFromCaller());
+
+    nsCOMPtr<nsIDocument> doc;
+    nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aOwner);
+    if (aOwner) {
+      nsCOMPtr<nsIDOMDocument> domdoc = window->GetExtantDocument();
+      doc = do_QueryInterface(domdoc);
+    }
+
     if (!doc) {
       return NS_ERROR_UNEXPECTED;
     }
 
     baseURI = doc->GetBaseURI();
     documentURI = doc->GetDocumentURI();
   }
 
-  nsIScriptContext* scriptContext = GetScriptContextFromJSContext(cx);
-  return Init(prin, documentURI, baseURI,
-              scriptContext ? scriptContext->GetGlobalObject() : nsnull);
+  nsCOMPtr<nsIScriptGlobalObject> scriptglobal = do_QueryInterface(aOwner);
+  return Init(prin, documentURI, baseURI, scriptglobal);
 }
 
 NS_IMETHODIMP
 nsDOMParser::Init()
 {
   AttemptedInitMarker marker(&mAttemptedInit);
 
   nsCOMPtr<nsIXPCNativeCallContext> ncc;
--- a/content/base/src/nsDOMParser.h
+++ b/content/base/src/nsDOMParser.h
@@ -69,17 +69,17 @@ public:
   // nsIDOMLoadListener
   NS_IMETHOD Load(nsIDOMEvent* aEvent);
   NS_IMETHOD BeforeUnload(nsIDOMEvent* aEvent);
   NS_IMETHOD Unload(nsIDOMEvent* aEvent);
   NS_IMETHOD Abort(nsIDOMEvent* aEvent);
   NS_IMETHOD Error(nsIDOMEvent* aEvent);
 
   // nsIJSNativeInitializer
-  NS_IMETHOD Initialize(JSContext *cx, JSObject *obj, 
+  NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* cx, JSObject* obj,
                         PRUint32 argc, jsval *argv);
 
 private:
   class AttemptedInitMarker {
   public:
     AttemptedInitMarker(PRPackedBool* aAttemptedInit) :
       mAttemptedInit(aAttemptedInit)
     {}
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -2580,30 +2580,33 @@ nsDocument::GetScriptHandlingObject(PRBo
   if (mScriptGlobalObject) {
     return mScriptGlobalObject;
   }
 
   nsCOMPtr<nsIScriptGlobalObject> scriptHandlingObject =
     do_QueryReferent(mScriptObject);
   nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(scriptHandlingObject);
   if (win) {
+    NS_ASSERTION(win->IsInnerWindow(), "Should have inner window here!");
     nsPIDOMWindow* outer = win->GetOuterWindow();
     if (!outer || outer->GetCurrentInnerWindow() != win) {
       NS_WARNING("Wrong inner/outer window combination!");
       return nsnull;
     }
   }
   return scriptHandlingObject;
 }
 void
 nsDocument::SetScriptHandlingObject(nsIScriptGlobalObject* aScriptObject)
 {
   NS_ASSERTION(!mScriptGlobalObject ||
                mScriptGlobalObject == aScriptObject,
                "Wrong script object!");
+  nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(aScriptObject);
+  NS_ASSERTION(!win || win->IsInnerWindow(), "Should have inner window here!");
   mScriptObject = do_GetWeakReference(aScriptObject);
   if (aScriptObject) {
     mHasHadScriptHandlingObject = PR_TRUE;
   }
 }
 
 nsPIDOMWindow *
 nsDocument::GetWindow()
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -84,16 +84,17 @@
 #include "nsContentPolicyUtils.h"
 #include "nsContentErrors.h"
 #include "nsLayoutStatics.h"
 #include "nsCrossSiteListenerProxy.h"
 #include "nsDOMError.h"
 #include "nsIHTMLDocument.h"
 #include "nsWhitespaceTokenizer.h"
 #include "nsIMultiPartChannel.h"
+#include "nsIScriptObjectPrincipal.h"
 
 #define LOAD_STR "load"
 #define ERROR_STR "error"
 #define PROGRESS_STR "progress"
 #define UPLOADPROGRESS_STR "uploadprogress"
 #define READYSTATE_STR "readystatechange"
 
 // CIDs
@@ -333,37 +334,16 @@ nsACProxyListener::OnChannelRedirect(nsI
 }
 
 NS_IMETHODIMP
 nsACProxyListener::GetInterface(const nsIID & aIID, void **aResult)
 {
   return QueryInterface(aIID, aResult);
 }
 
-
-static nsIScriptContext *
-GetCurrentContext()
-{
-  // Get JSContext from stack.
-  nsCOMPtr<nsIJSContextStack> stack =
-    do_GetService("@mozilla.org/js/xpc/ContextStack;1");
-
-  if (!stack) {
-    return nsnull;
-  }
-
-  JSContext *cx;
-
-  if (NS_FAILED(stack->Peek(&cx)) || !cx) {
-    return nsnull;
-  }
-
-  return GetScriptContextFromJSContext(cx);
-}
-
 /**
  * Gets the nsIDocument given the script context. Will return nsnull on failure.
  *
  * @param aScriptContext the script context to get the document for; can be null
  *
  * @return the document associated with the script context
  */
 static already_AddRefed<nsIDocument>
@@ -407,16 +387,78 @@ nsXMLHttpRequest::~nsXMLHttpRequest()
   NS_ABORT_IF_FALSE(!(mState & XML_HTTP_REQUEST_SYNCLOOPING), "we rather crash than hang");
   mState &= ~XML_HTTP_REQUEST_SYNCLOOPING;
 
   // Needed to free the listener arrays.
   ClearEventListeners();
   nsLayoutStatics::Release();
 }
 
+nsresult
+nsXMLHttpRequest::Init()
+{
+  // Set the original mScriptContext and mPrincipal, if available.
+  // Get JSContext from stack.
+  nsCOMPtr<nsIJSContextStack> stack =
+    do_GetService("@mozilla.org/js/xpc/ContextStack;1");
+
+  if (!stack) {
+    return NS_OK;
+  }
+
+  JSContext *cx;
+
+  if (NS_FAILED(stack->Peek(&cx)) || !cx) {
+    return NS_OK;
+  }
+
+  nsIScriptContext* context = GetScriptContextFromJSContext(cx);
+  if (!context) {
+    return NS_OK;
+  }
+  nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
+  nsCOMPtr<nsIPrincipal> subjectPrincipal;
+  if (secMan) {
+    secMan->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
+  }
+  NS_ENSURE_STATE(subjectPrincipal);
+
+  mScriptContext = context;
+  mPrincipal = subjectPrincipal;
+  nsCOMPtr<nsPIDOMWindow> window =
+    do_QueryInterface(context->GetGlobalObject());
+  if (window) {
+    mOwner = window->GetCurrentInnerWindow();
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsXMLHttpRequest::Initialize(nsISupports* aOwner, JSContext* cx, JSObject* obj,
+                             PRUint32 argc, jsval *argv)
+{
+  mOwner = do_QueryInterface(aOwner);
+  if (!mOwner) {
+    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);
+  return NS_OK; 
+}
+
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLHttpRequest)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXMLHttpRequest)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChannel)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mReadRequest)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mLoadEventListeners)
@@ -431,16 +473,18 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnProgressListener)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnUploadProgressListener)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOnReadystatechangeListener)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mXMLParserStreamListener)
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChannelEventSink)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mProgressEventSink)
+
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOwner)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXMLHttpRequest)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContext)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChannel)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mReadRequest)
 
@@ -456,32 +500,35 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnProgressListener)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnUploadProgressListener)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnReadystatechangeListener)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mXMLParserStreamListener)
 
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChannelEventSink)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mProgressEventSink)
+
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOwner)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 
 // QueryInterface implementation for nsXMLHttpRequest
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXMLHttpRequest)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXMLHttpRequest)
   NS_INTERFACE_MAP_ENTRY(nsIXMLHttpRequest)
   NS_INTERFACE_MAP_ENTRY(nsIJSXMLHttpRequest)
   NS_INTERFACE_MAP_ENTRY(nsIDOMLoadListener)
   NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
   NS_INTERFACE_MAP_ENTRY(nsIRequestObserver)
   NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
   NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink)
   NS_INTERFACE_MAP_ENTRY(nsIProgressEventSink)
   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
+  NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(XMLHttpRequest)
 NS_INTERFACE_MAP_END
 
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsXMLHttpRequest, nsIXMLHttpRequest)
 NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsXMLHttpRequest, nsIXMLHttpRequest)
 
 
@@ -507,18 +554,16 @@ nsXMLHttpRequest::AddEventListener(const
   IMPL_ADD_LISTENER(UPLOADPROGRESS_STR, mUploadProgressEventListeners)
   IMPL_ADD_LISTENER(READYSTATE_STR, mReadystatechangeEventListeners)
   {
     return NS_ERROR_INVALID_ARG;
   }
 
   array->AppendObject(listener);
 
-  mScriptContext = GetCurrentContext();
-
 #undef IMPL_ADD_LISTENER
   
   return NS_OK;
 }
 
 /* void removeEventListener (in string type, in nsIDOMEventListener
    listener); */
 NS_IMETHODIMP
@@ -573,19 +618,16 @@ nsXMLHttpRequest::GetOnreadystatechange(
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXMLHttpRequest::SetOnreadystatechange(nsIDOMEventListener * aOnreadystatechange)
 {
   mOnReadystatechangeListener = aOnreadystatechange;
-
-  mScriptContext = GetCurrentContext();
-
   return NS_OK;
 }
 
 
 /* attribute nsIDOMEventListener onload; */
 NS_IMETHODIMP
 nsXMLHttpRequest::GetOnload(nsIDOMEventListener * *aOnLoad)
 {
@@ -595,19 +637,16 @@ nsXMLHttpRequest::GetOnload(nsIDOMEventL
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXMLHttpRequest::SetOnload(nsIDOMEventListener * aOnLoad)
 {
   mOnLoadListener = aOnLoad;
-
-  mScriptContext = GetCurrentContext();
-
   return NS_OK;
 }
 
 /* attribute nsIDOMEventListener onerror; */
 NS_IMETHODIMP
 nsXMLHttpRequest::GetOnerror(nsIDOMEventListener * *aOnerror)
 {
   NS_ENSURE_ARG_POINTER(aOnerror);
@@ -616,19 +655,16 @@ nsXMLHttpRequest::GetOnerror(nsIDOMEvent
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXMLHttpRequest::SetOnerror(nsIDOMEventListener * aOnerror)
 {
   mOnErrorListener = aOnerror;
-
-  mScriptContext = GetCurrentContext();
-
   return NS_OK;
 }
 
 /* attribute nsIDOMEventListener onprogress; */
 NS_IMETHODIMP
 nsXMLHttpRequest::GetOnprogress(nsIDOMEventListener * *aOnprogress)
 {
   NS_ENSURE_ARG_POINTER(aOnprogress);  
@@ -637,19 +673,16 @@ nsXMLHttpRequest::GetOnprogress(nsIDOMEv
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXMLHttpRequest::SetOnprogress(nsIDOMEventListener * aOnprogress)
 {
   mOnProgressListener = aOnprogress;
-
-  mScriptContext = GetCurrentContext();
-
   return NS_OK;
 }
 
 /* attribute nsIDOMEventListener onuploadprogress; */
 NS_IMETHODIMP
 nsXMLHttpRequest::GetOnuploadprogress(nsIDOMEventListener * *aOnuploadprogress)
 {
   NS_ENSURE_ARG_POINTER(aOnuploadprogress);  
@@ -658,19 +691,16 @@ nsXMLHttpRequest::GetOnuploadprogress(ns
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXMLHttpRequest::SetOnuploadprogress(nsIDOMEventListener * aOnuploadprogress)
 {
   mOnUploadProgressListener = aOnuploadprogress;
-
-  mScriptContext = GetCurrentContext();
-
   return NS_OK;
 }
 
 /* readonly attribute nsIChannel channel; */
 NS_IMETHODIMP
 nsXMLHttpRequest::GetChannel(nsIChannel **aChannel)
 {
   NS_ENSURE_ARG_POINTER(aChannel);
@@ -978,36 +1008,29 @@ nsXMLHttpRequest::GetResponseHeader(cons
 }
 
 nsresult
 nsXMLHttpRequest::GetLoadGroup(nsILoadGroup **aLoadGroup)
 {
   NS_ENSURE_ARG_POINTER(aLoadGroup);
   *aLoadGroup = nsnull;
 
-  if (!mScriptContext) {
-    mScriptContext = GetCurrentContext();
-  }
-
   nsCOMPtr<nsIDocument> doc = GetDocumentFromScriptContext(mScriptContext);
   if (doc) {
     *aLoadGroup = doc->GetDocumentLoadGroup().get();  // already_AddRefed
   }
 
   return NS_OK;
 }
 
 nsIURI *
 nsXMLHttpRequest::GetBaseURI()
 {
   if (!mScriptContext) {
-    mScriptContext = GetCurrentContext();
-    if (!mScriptContext) {
-      return nsnull;
-    }
+    return nsnull;
   }
 
   nsCOMPtr<nsIDocument> doc = GetDocumentFromScriptContext(mScriptContext);
   if (!doc) {
     return nsnull;
   }
 
   return doc->GetBaseURI();
@@ -1062,16 +1085,20 @@ nsXMLHttpRequest::NotifyEventListeners(c
   // XXXbz wouldn't it be easier to just have an actual nsEventListenerManager
   // to work with or something?  I feel like we're duplicating code here...
   if (!aEvent)
     return;
 
   nsCOMPtr<nsIJSContextStack> stack;
   JSContext *cx = nsnull;
 
+  if (NS_FAILED(CheckInnerWindowCorrectness())) {
+    return;
+  }
+
   if (mScriptContext) {
     stack = do_GetService("@mozilla.org/js/xpc/ContextStack;1");
 
     if (stack) {
       cx = (JSContext *)mScriptContext->GetNativeContext();
 
       if (cx) {
         stack->Push(cx);
@@ -1204,30 +1231,16 @@ nsXMLHttpRequest::OpenRequest(const nsAC
 
   // Disallow HTTP/1.1 TRACE method (see bug 302489)
   // and MS IIS equivalent TRACK (see bug 381264)
   if (method.LowerCaseEqualsLiteral("trace") ||
       method.LowerCaseEqualsLiteral("track")) {
     return NS_ERROR_INVALID_ARG;
   }
 
-  // Get the principal.
-  // XXX This should be done at construction time.
-  nsCOMPtr<nsIDocument> doc =
-    do_QueryInterface(nsContentUtils::GetDocumentFromCaller());
-  if (doc) {
-    mPrincipal = doc->NodePrincipal();
-  }
-  else {
-    nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
-    if (secMan) {
-      secMan->GetSubjectPrincipal(getter_AddRefs(mPrincipal));
-    }
-  }
-
   nsresult rv;
   nsCOMPtr<nsIURI> uri;
   PRBool authp = PR_FALSE;
 
   if (mState & (XML_HTTP_REQUEST_OPENED |
                 XML_HTTP_REQUEST_LOADED |
                 XML_HTTP_REQUEST_INTERACTIVE |
                 XML_HTTP_REQUEST_SENT |
@@ -1257,21 +1270,23 @@ nsXMLHttpRequest::OpenRequest(const nsAC
     mState &= ~XML_HTTP_REQUEST_ASYNC;
   }
 
   rv = NS_NewURI(getter_AddRefs(uri), url, nsnull, GetBaseURI());
   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.
-  doc = GetDocumentFromScriptContext(mScriptContext);
+  rv = CheckInnerWindowCorrectness();
+  NS_ENSURE_SUCCESS(rv, rv);
+  nsCOMPtr<nsIDocument> doc = GetDocumentFromScriptContext(mScriptContext);
   PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
   rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_XMLHTTPREQUEST,
                                  uri,
-                                 (doc ? doc->NodePrincipal() : nsnull),
+                                 mPrincipal,
                                  doc,
                                  EmptyCString(), //mime guess
                                  nsnull,         //extra
                                  &shouldLoad,
                                  nsContentUtils::GetContentPolicy(),
                                  nsContentUtils::GetSecurityManager());
   if (NS_FAILED(rv)) return rv;
   if (NS_CP_REJECTED(shouldLoad)) {
@@ -1547,18 +1562,17 @@ nsXMLHttpRequest::OnStartRequest(nsIRequ
   mContext = ctxt;
   mState |= XML_HTTP_REQUEST_PARSEBODY;
   ChangeState(XML_HTTP_REQUEST_LOADED);
 
   nsIURI* uri = GetBaseURI();
 
   // Create an empty document from it 
   const nsAString& emptyStr = EmptyString();
-  nsIScriptGlobalObject* global = mScriptContext ?
-    mScriptContext->GetGlobalObject() : nsnull;
+  nsCOMPtr<nsIScriptGlobalObject> global = do_QueryInterface(mOwner);
   nsresult rv = nsContentUtils::CreateDocument(emptyStr, emptyStr, nsnull, uri,
                                                uri, mPrincipal, global,
                                                getter_AddRefs(mDocument));
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (mState & XML_HTTP_REQUEST_USE_XSITE_AC) {
     nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(mDocument);
     if (htmlDoc) {
@@ -1819,17 +1833,18 @@ nsXMLHttpRequest::SendAsBinary(const nsA
 
   return Send(variant);
 }
 
 /* void send (in nsIVariant aBody); */
 NS_IMETHODIMP
 nsXMLHttpRequest::Send(nsIVariant *aBody)
 {
-  nsresult rv;
+  nsresult rv = CheckInnerWindowCorrectness();
+  NS_ENSURE_SUCCESS(rv, rv);
 
   // Return error if we're already processing a request
   if (XML_HTTP_REQUEST_SENT & mState) {
     return NS_ERROR_FAILURE;
   }
 
   // Make sure we've been opened
   if (!mChannel || !(XML_HTTP_REQUEST_OPENED & mState)) {
@@ -2011,21 +2026,16 @@ nsXMLHttpRequest::Send(nsIVariant *aBody
 
   // Reset responseXML
   mDocument = nsnull;
 
   if (!(mState & XML_HTTP_REQUEST_ASYNC)) {
     mState |= XML_HTTP_REQUEST_SYNCLOOPING;
   }
 
-  if (!mScriptContext) {
-    // We need a context to check if redirect (if any) is allowed
-    mScriptContext = GetCurrentContext();
-  }
-
   rv = CheckChannelForCrossSiteRequest();
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Hook us up to listen to redirects and the like
   mChannel->GetNotificationCallbacks(getter_AddRefs(mNotificationCallbacks));
   mChannel->SetNotificationCallbacks(this);
 
   // Create our listener
--- a/content/base/src/nsXMLHttpRequest.h
+++ b/content/base/src/nsXMLHttpRequest.h
@@ -55,30 +55,32 @@
 #include "nsIChannelEventSink.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIHttpHeaderVisitor.h"
 #include "nsIProgressEventSink.h"
 #include "nsCOMArray.h"
 #include "nsJSUtils.h"
 #include "nsTArray.h"
 #include "nsCycleCollectionParticipant.h"
-
+#include "nsIJSNativeInitializer.h"
+#include "nsPIDOMWindow.h"
 #include "nsIDOMLSProgressEvent.h"
 
 class nsILoadGroup;
 
 class nsXMLHttpRequest : public nsIXMLHttpRequest,
                          public nsIJSXMLHttpRequest,
                          public nsIDOMLoadListener,
                          public nsIDOMEventTarget,
                          public nsIStreamListener,
                          public nsIChannelEventSink,
                          public nsIProgressEventSink,
                          public nsIInterfaceRequestor,
-                         public nsSupportsWeakReference
+                         public nsSupportsWeakReference,
+                         public nsIJSNativeInitializer
 {
 public:
   nsXMLHttpRequest();
   virtual ~nsXMLHttpRequest();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   // nsIXMLHttpRequest
@@ -110,16 +112,23 @@ public:
   NS_DECL_NSICHANNELEVENTSINK
 
   // nsIProgressEventSink
   NS_DECL_NSIPROGRESSEVENTSINK
 
   // nsIInterfaceRequestor
   NS_DECL_NSIINTERFACEREQUESTOR
 
+  // nsIJSNativeInitializer
+  NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* cx, JSObject* obj,
+                       PRUint32 argc, jsval* argv);
+
+  // This is called by the factory constructor.
+  nsresult Init();
+
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXMLHttpRequest, nsIXMLHttpRequest)
 
 protected:
 
   nsresult DetectCharset(nsACString& aCharset);
   nsresult ConvertBodyToText(nsAString& aOutBuffer);
   static NS_METHOD StreamReaderFunc(nsIInputStream* in,
                 void* closure,
@@ -160,31 +169,44 @@ protected:
   /**
    * Check if mChannel is ok for a cross-site request by making sure no
    * inappropriate headers are set, and no username/password is set.
    *
    * Also updates the XML_HTTP_REQUEST_USE_XSITE_AC bit.
    */
   nsresult CheckChannelForCrossSiteRequest();
 
+  nsresult CheckInnerWindowCorrectness()
+  {
+    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;
+  }
+
   nsCOMPtr<nsISupports> mContext;
   nsCOMPtr<nsIPrincipal> mPrincipal;
   nsCOMPtr<nsIChannel> mChannel;
   // mReadRequest is different from mChannel for multipart requests
   nsCOMPtr<nsIRequest> mReadRequest;
   nsCOMPtr<nsIDOMDocument> mDocument;
   nsCOMPtr<nsIChannel> mACGetChannel;
 
   nsCOMArray<nsIDOMEventListener> mLoadEventListeners;
   nsCOMArray<nsIDOMEventListener> mErrorEventListeners;
   nsCOMArray<nsIDOMEventListener> mProgressEventListeners;
   nsCOMArray<nsIDOMEventListener> mUploadProgressEventListeners;
   nsCOMArray<nsIDOMEventListener> mReadystatechangeEventListeners;
   
   nsCOMPtr<nsIScriptContext> mScriptContext;
+  nsCOMPtr<nsPIDOMWindow>    mOwner; // Inner window.
 
   nsCOMPtr<nsIDOMEventListener> mOnLoadListener;
   nsCOMPtr<nsIDOMEventListener> mOnErrorListener;
   nsCOMPtr<nsIDOMEventListener> mOnProgressListener;
   nsCOMPtr<nsIDOMEventListener> mOnUploadProgressListener;
   nsCOMPtr<nsIDOMEventListener> mOnReadystatechangeListener;
 
   nsCOMPtr<nsIStreamListener> mXMLParserStreamListener;
--- a/content/html/content/src/nsHTMLImageElement.cpp
+++ b/content/html/content/src/nsHTMLImageElement.cpp
@@ -103,18 +103,18 @@ public:
 
   // nsIDOMHTMLImageElement
   NS_DECL_NSIDOMHTMLIMAGEELEMENT
 
   // nsIDOMNSHTMLImageElement
   NS_DECL_NSIDOMNSHTMLIMAGEELEMENT
 
   // nsIJSNativeInitializer
-  NS_IMETHOD Initialize(JSContext* aContext, JSObject *aObj,
-                        PRUint32 argc, jsval *argv);
+  NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* aContext,
+                        JSObject* aObj, PRUint32 argc, jsval* argv);
 
   // nsIContent
   virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult);
   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                               PRInt32 aModType) const;
@@ -537,18 +537,18 @@ nsHTMLImageElement::BindToTree(nsIDocume
 PRInt32
 nsHTMLImageElement::IntrinsicState() const
 {
   return nsGenericHTMLElement::IntrinsicState() |
     nsImageLoadingContent::ImageState();
 }
 
 NS_IMETHODIMP
-nsHTMLImageElement::Initialize(JSContext* aContext, JSObject *aObj,
-                               PRUint32 argc, jsval *argv)
+nsHTMLImageElement::Initialize(nsISupports* aOwner, JSContext* aContext,
+                               JSObject *aObj, PRUint32 argc, jsval *argv)
 {
   if (argc <= 0) {
     // Nothing to do here if we don't get any arguments.
 
     return NS_OK;
   }
 
   // The first (optional) argument is the width of the image
--- a/content/html/content/src/nsHTMLOptionElement.cpp
+++ b/content/html/content/src/nsHTMLOptionElement.cpp
@@ -97,18 +97,18 @@ public:
 
   // nsIDOMHTMLOptionElement
   NS_DECL_NSIDOMHTMLOPTIONELEMENT
 
   // nsIDOMNSHTMLOptionElement
   NS_IMETHOD SetText(const nsAString & aText); 
 
   // nsIJSNativeInitializer
-  NS_IMETHOD Initialize(JSContext* aContext, JSObject *aObj, 
-                        PRUint32 argc, jsval *argv);
+  NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* aContext,
+                        JSObject *aObj, PRUint32 argc, jsval *argv);
 
   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                               PRInt32 aModType) const;
 
   virtual nsresult BeforeSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
                                  const nsAString* aValue, PRBool aNotify);
   
   // nsIOptionElement
@@ -450,17 +450,18 @@ nsHTMLOptionElement::GetSelect()
       break;
     }
   }
   
   return nsnull;
 }
 
 NS_IMETHODIMP    
-nsHTMLOptionElement::Initialize(JSContext* aContext, 
+nsHTMLOptionElement::Initialize(nsISupports* aOwner,
+                                JSContext* aContext,
                                 JSObject *aObj,
                                 PRUint32 argc, 
                                 jsval *argv)
 {
   nsresult result = NS_OK;
 
   if (argc > 0) {
     // The first (optional) parameter is the text of the option
--- a/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp
+++ b/content/xslt/src/xslt/txMozillaXSLTProcessor.cpp
@@ -1253,18 +1253,18 @@ txMozillaXSLTProcessor::ContentRemoved(n
                                        nsIContent* aContainer,
                                        nsIContent* aChild,
                                        PRInt32 aIndexInContainer)
 {
     mStylesheet = nsnull;
 }
 
 NS_IMETHODIMP
-txMozillaXSLTProcessor::Initialize(JSContext* cx, JSObject* obj,
-                                   PRUint32 argc, jsval* argv)
+txMozillaXSLTProcessor::Initialize(nsISupports* aOwner, JSContext* cx,
+                                   JSObject* obj, PRUint32 argc, jsval* argv)
 {
     nsCOMPtr<nsIPrincipal> prin;
     nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
     NS_ENSURE_TRUE(secMan, NS_ERROR_UNEXPECTED);
 
     secMan->GetSubjectPrincipal(getter_AddRefs(prin));
     NS_ENSURE_TRUE(prin, NS_ERROR_UNEXPECTED);
 
--- a/content/xslt/src/xslt/txMozillaXSLTProcessor.h
+++ b/content/xslt/src/xslt/txMozillaXSLTProcessor.h
@@ -137,17 +137,17 @@ public:
                             nsIDOMDocument **aResult);
 
     PRBool IsLoadDisabled()
     {
         return (mFlags & DISABLE_ALL_LOADS) != 0;
     }
 
     // nsIJSNativeInitializer
-    NS_IMETHODIMP Initialize(JSContext *cx, JSObject *obj, 
+    NS_IMETHODIMP Initialize(nsISupports* aOwner, JSContext *cx, JSObject *obj,
                              PRUint32 argc, jsval *argv);
 
     static nsresult Startup();
     static void Shutdown();
 
 private:
     nsresult DoTransform();
     void notifyError();
--- a/dom/public/nsIJSNativeInitializer.h
+++ b/dom/public/nsIJSNativeInitializer.h
@@ -37,34 +37,34 @@
 
 #ifndef nsIJSNativeInitializer_h__
 #define nsIJSNativeInitializer_h__
 
 #include "nsISupports.h"
 #include "jsapi.h"
 
 #define NS_IJSNATIVEINITIALIZER_IID \
-{0xa6cf90f4, 0x15b3, 0x11d2,        \
- {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}}
+{ 0x536c5ad2, 0x1275, 0x4706,       \
+  { 0x99, 0xbd, 0x4a, 0xef, 0xb2, 0x4a, 0xb7, 0xf7 } }
 
 /**
  * A JavaScript specific interface used to initialize new
  * native objects, created as a result of calling a
  * JavaScript constructor. The arguments are passed in
  * their raw form as jsval's.
  */
 
 class nsIJSNativeInitializer : public nsISupports {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IJSNATIVEINITIALIZER_IID)
 
   /**
-   * Intialize a newly created native instance using the parameters
-   * passed into the JavaScript constructor.
+   * Initialize a newly created native instance using the owner of the
+   * constructor and the parameters passed into the JavaScript constructor.
    */
-  NS_IMETHOD Initialize(JSContext *cx, JSObject *obj, 
+  NS_IMETHOD Initialize(nsISupports* aOwner, JSContext *cx, JSObject *obj,
                         PRUint32 argc, jsval *argv) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIJSNativeInitializer,
                               NS_IJSNATIVEINITIALIZER_IID)
 
 #endif // nsIJSNativeInitializer_h__
--- a/dom/src/base/nsDOMClassInfo.cpp
+++ b/dom/src/base/nsDOMClassInfo.cpp
@@ -4729,17 +4729,18 @@ FindConstructorContractID(PRInt32 aDOMCl
     if (kConstructorMap[i].mDOMClassInfoID == aDOMClassInfoID) {
       return kConstructorMap[i].mContractID;
     }
   }
   return nsnull;
 }
 
 static nsresult
-BaseStubConstructor(const nsGlobalNameStruct *name_struct, JSContext *cx,
+BaseStubConstructor(nsIWeakReference* aWeakOwner,
+                    const nsGlobalNameStruct *name_struct, JSContext *cx,
                     JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
   nsresult rv;
   nsCOMPtr<nsISupports> native;
   if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
     const char *contractid =
       FindConstructorContractID(name_struct->mDOMClassInfoID);
     native = do_CreateInstance(contractid, &rv);
@@ -4752,17 +4753,19 @@ BaseStubConstructor(const nsGlobalNameSt
   }
   if (NS_FAILED(rv)) {
     NS_ERROR("Failed to create the object");
     return rv;
   }
 
   nsCOMPtr<nsIJSNativeInitializer> initializer(do_QueryInterface(native));
   if (initializer) {
-    rv = initializer->Initialize(cx, obj, argc, argv);
+    nsCOMPtr<nsISupports> owner = do_QueryReferent(aWeakOwner);
+    NS_ENSURE_STATE(owner);
+    rv = initializer->Initialize(owner, cx, obj, argc, argv);
     if (NS_FAILED(rv)) {
       return NS_ERROR_NOT_INITIALIZED;
     }
   }
 
   nsCOMPtr<nsIScriptObjectOwner> owner(do_QueryInterface(native));
   if (owner) {
     nsIScriptContext *context = nsJSUtils::GetStaticScriptContext(cx, obj);
@@ -4860,19 +4863,21 @@ DefineInterfaceConstants(JSContext *cx, 
 
   return NS_OK;
 }
 
 class nsDOMConstructor : public nsIDOMDOMConstructor
 {
 public:
   nsDOMConstructor(const PRUnichar *aName,
-                   const nsGlobalNameStruct *aNameStruct)
+                   const nsGlobalNameStruct *aNameStruct,
+                   nsISupports* aOwner)
     : mClassName(aName),
-      mConstructable(IsConstructable(aNameStruct))
+      mConstructable(IsConstructable(aNameStruct)),
+      mWeakOwner(do_GetWeakReference(aOwner))
   {
   }
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMDOMCONSTRUCTOR
 
   nsresult Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                      JSObject *obj, PRUint32 argc, jsval *argv,
@@ -4941,18 +4946,19 @@ private:
       (aNameStruct->mType == nsGlobalNameStruct::eTypeClassConstructor &&
        FindConstructorContractID(aNameStruct->mDOMClassInfoID)) ||
       (aNameStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfo &&
        aNameStruct->mData->mConstructorCID) ||
       aNameStruct->mType == nsGlobalNameStruct::eTypeExternalConstructor ||
       aNameStruct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias;
   }
 
-  const PRUnichar *mClassName;
+  const PRUnichar*   mClassName;
   const PRPackedBool mConstructable;
+  nsWeakPtr          mWeakOwner;
 };
 
 NS_IMPL_ADDREF(nsDOMConstructor)
 NS_IMPL_RELEASE(nsDOMConstructor)
 NS_INTERFACE_MAP_BEGIN(nsDOMConstructor)
   NS_INTERFACE_MAP_ENTRY(nsIDOMDOMConstructor)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   if (aIID.Equals(NS_GET_IID(nsIClassInfo))) {
@@ -4989,17 +4995,17 @@ nsDOMConstructor::Construct(nsIXPConnect
   const nsGlobalNameStruct *name_struct = GetNameStruct();
   NS_ENSURE_TRUE(name_struct, NS_ERROR_FAILURE);
 
   if (!IsConstructable(name_struct)) {
     // ignore return value, we return JS_FALSE anyway
     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
   }
 
-  return BaseStubConstructor(name_struct, cx, obj, argc, argv, vp);
+  return BaseStubConstructor(mWeakOwner, name_struct, cx, obj, argc, argv, vp);
 }
 
 nsresult
 nsDOMConstructor::HasInstance(nsIXPConnectWrappedNative *wrapper,
                               JSContext * cx, JSObject * obj,
                               jsval v, PRBool *bp, PRBool *_retval)
 
 {
@@ -5195,17 +5201,18 @@ nsWindowSH::GlobalResolve(nsGlobalWindow
 
   if (name_struct->mType == nsGlobalNameStruct::eTypeInterface) {
     // We're resolving a name of a DOM interface for which there is no
     // direct DOM class, create a constructor object...
 
     nsRefPtr<nsDOMConstructor> constructor =
       new nsDOMConstructor(reinterpret_cast<PRUnichar *>
                                            (::JS_GetStringChars(str)),
-                           name_struct);
+                           name_struct,
+                           static_cast<nsPIDOMWindow*>(aWin));
     if (!constructor) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     PRBool doSecurityCheckInAddProperty = sDoSecurityCheckInAddProperty;
     sDoSecurityCheckInAddProperty = PR_FALSE;
 
     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
@@ -5257,17 +5264,18 @@ nsWindowSH::GlobalResolve(nsGlobalWindow
       } else if (alias_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
         ci_data = alias_struct->mData;
       }
     }
 
     const PRUnichar *name = reinterpret_cast<PRUnichar *>
                                             (::JS_GetStringChars(str));
     nsRefPtr<nsDOMConstructor> constructor =
-      new nsDOMConstructor(name, name_struct);
+      new nsDOMConstructor(name, name_struct,
+                           static_cast<nsPIDOMWindow*>(aWin));
     if (!constructor) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     PRBool doSecurityCheckInAddProperty = sDoSecurityCheckInAddProperty;
     sDoSecurityCheckInAddProperty = PR_FALSE;
 
     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
@@ -5478,17 +5486,18 @@ nsWindowSH::GlobalResolve(nsGlobalWindow
 
     *did_resolve = PR_TRUE;
 
     return NS_OK;
   }
 
   if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructor) {
     nsRefPtr<nsDOMConstructor> constructor =
-      new nsDOMConstructor(class_name, name_struct);
+      new nsDOMConstructor(class_name, name_struct,
+                           static_cast<nsPIDOMWindow*>(aWin));
     if (!constructor) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     jsval val;
     nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
     rv = WrapNative(cx, obj, constructor, NS_GET_IID(nsIDOMDOMConstructor),
                     &val, getter_AddRefs(holder));
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -277,17 +277,17 @@ static void Shutdown();
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsXPath1SchemeProcessor)
 
 // Factory Constructor
 NS_GENERIC_FACTORY_CONSTRUCTOR(txMozillaXSLTProcessor)
 NS_GENERIC_AGGREGATED_CONSTRUCTOR_INIT(nsXPathEvaluator, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(txNodeSetAdaptor, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMSerializer)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsXMLHttpRequest)
+NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsXMLHttpRequest, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsDOMParser)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsDOMStorageManager,
                                          nsDOMStorageManager::GetInstance)
 
 //-----------------------------------------------------------------------------
 
 // Per bug 209804, it is necessary to observe the "xpcom-shutdown" event and
 // perform shutdown of the layout modules at that time instead of waiting for