Bug 416534: Clean up cross-site xmlhttprequest security checks. r/sr=peterv
authorjonas@sicking.cc
Tue, 26 Feb 2008 18:17:49 -0800
changeset 12315 896c4a5ed76ba7f66c324f5bdd40df4783e77f43
parent 12314 8aa1c834ef5143d6e307af69dd10c4c0abac549f
child 12316 4ddd1edf7adc72f972f534978580a1c261028567
push idunknown
push userunknown
push dateunknown
bugs416534
milestone1.9b4pre
Bug 416534: Clean up cross-site xmlhttprequest security checks. r/sr=peterv
caps/idl/nsIPrincipal.idl
caps/include/nsScriptSecurityManager.h
caps/src/nsNullPrincipal.cpp
caps/src/nsPrincipal.cpp
caps/src/nsScriptSecurityManager.cpp
caps/src/nsSystemPrincipal.cpp
content/base/public/nsISyncLoadDOMService.idl
content/base/src/nsContentSink.cpp
content/base/src/nsContentUtils.cpp
content/base/src/nsCrossSiteListenerProxy.cpp
content/base/src/nsCrossSiteListenerProxy.h
content/base/src/nsSyncLoadService.cpp
content/base/src/nsSyncLoadService.h
content/base/src/nsXMLHttpRequest.cpp
content/xml/document/src/nsXMLContentSink.cpp
content/xml/document/src/nsXMLDocument.cpp
content/xslt/src/xml/txXMLParser.cpp
content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp
content/xul/document/src/nsXULDocument.cpp
extensions/canvas3d/src/nsCanvasRenderingContextGL.cpp
--- a/caps/idl/nsIPrincipal.idl
+++ b/caps/idl/nsIPrincipal.idl
@@ -46,17 +46,17 @@ struct JSContext;
 struct JSPrincipals;
 %}
 
 interface nsIURI;
 
 [ptr] native JSContext(JSContext);
 [ptr] native JSPrincipals(JSPrincipals);
 
-[scriptable, uuid(635c413b-47c3-4ee1-87c8-e7919cc65f5a)]
+[scriptable, uuid(7292475e-2821-4602-9d00-228476696428)]
 interface nsIPrincipal : nsISerializable
 {
     /**
      * Values of capabilities for each principal. Order is
      * significant: if an operation is performed on a set
      * of capabilities, the minimum is computed.
      */
     const short ENABLE_DENIED                = 1;
@@ -199,16 +199,39 @@ interface nsIPrincipal : nsISerializable
      * Note for the future: Perhaps we should consider a certificate principal
      * for a given URI subsuming a codebase principal for the same URI?  Not
      * sure what the immediate benefit would be, but I think the setup could
      * make some code (e.g. MaybeDowngradeToCodebase) clearer.
      */
     [noscript] boolean subsumes(in nsIPrincipal other);
 
     /**
+     * Checks whether this principal is allowed to load the network resource
+     * located at the given URI under the same-origin policy. This means that
+     * codebase principals are only allowed to load resources from the same
+     * domain, the system principal is allowed to load anything, and null
+     * principals are not allowed to load anything.
+     *
+     * If the load is allowed this function does nothing. If the load is not
+     * allowed the function throws NS_ERROR_DOM_BAD_URI.
+     *
+     * NOTE: Other policies might override this, such as the Access-Control
+     *       specification.
+     * NOTE: The 'domain' attribute has no effect on the behaviour of this
+     *       function.
+     *
+     *
+     * @param uri    The URI about to be loaded.
+     * @param report If true, will report a warning to the console service
+     *               if the load is not allowed.
+     * @throws NS_ERROR_DOM_BAD_URI if the load is not allowed.
+     */
+    [noscript] void checkMayLoad(in nsIUri uri, in boolean report);
+
+    /**
      * The subject name for the certificate.  This actually identifies the
      * subject of the certificate.  This may well not be a string that would
      * mean much to a typical user on its own (e.g. it may have a number of
      * different names all concatenated together with some information on what
      * they mean in between).
      *
      * Throws if there is no certificate associated with this principal.
      */
--- a/caps/include/nsScriptSecurityManager.h
+++ b/caps/include/nsScriptSecurityManager.h
@@ -390,16 +390,28 @@ public:
 
     static nsSystemPrincipal*
     SystemPrincipalSingletonConstructor();
 
     JSContext* GetCurrentJSContext();
 
     JSContext* GetSafeJSContext();
 
+    /**
+     * Utility method for comparing two URIs.  For security purposes, two URIs
+     * are equivalent if their schemes, hosts, and ports (if any) match.  This
+     * method returns true if aSubjectURI and aObjectURI have the same origin,
+     * false otherwise.
+     */
+    static PRBool SecurityCompareURIs(nsIURI* aSourceURI, nsIURI* aTargetURI);
+
+    static nsresult 
+    ReportError(JSContext* cx, const nsAString& messageTag,
+                nsIURI* aSource, nsIURI* aTarget);
+
 private:
 
     // GetScriptSecurityManager is the only call that can make one
     nsScriptSecurityManager();
     virtual ~nsScriptSecurityManager();
 
     static JSBool JS_DLL_CALLBACK
     CheckObjectAccess(JSContext *cx, JSObject *obj,
@@ -415,20 +427,16 @@ private:
 #endif
                          );
 
     // Returns null if a principal cannot be found.  Note that rv can be NS_OK
     // when this happens -- this means that there was no JS running.
     nsIPrincipal*
     doGetSubjectPrincipal(nsresult* rv);
     
-    static nsresult 
-    ReportError(JSContext* cx, const nsAString& messageTag,
-                nsIURI* aSource, nsIURI* aTarget);
-
     nsresult
     CheckPropertyAccessImpl(PRUint32 aAction,
                             nsAXPCNativeCallContext* aCallContext,
                             JSContext* cx, JSObject* aJSObject,
                             nsISupports* aObj, nsIURI* aTargetURI,
                             nsIClassInfo* aClassInfo,
                             const char* aClassName, jsval aProperty,
                             void** aCachedClassPolicy);
@@ -535,26 +543,19 @@ private:
     InitDomainPolicy(JSContext* cx, const char* aPolicyName,
                      DomainPolicy* aDomainPolicy);
 
     nsresult
     InitPrincipals(PRUint32 prefCount, const char** prefNames,
                    nsISecurityPref* securityPref);
 
 
-    /**
-     * Utility method for comparing two URIs.  For security purposes, two URIs
-     * are equivalent if their schemes, hosts, and ports (if any) match.  This
-     * method returns true if aSubjectURI and aObjectURI have the same origin,
-     * false otherwise.
-     */
-    PRBool SecurityCompareURIs(nsIURI* aSourceURI, nsIURI* aTargetURI);
-
     /* encapsulate the file comparison rules */
-    PRBool SecurityCompareFileURIs(nsIURI* aSourceURI, nsIURI* aTargetURI);
+    static PRBool SecurityCompareFileURIs(nsIURI* aSourceURI,
+                                          nsIURI* aTargetURI);
 
 #ifdef XPC_IDISPATCH_SUPPORT
     // While this header is included outside of caps, this class isn't 
     // referenced so this should be fine.
     nsresult
     CheckComponentPermissions(JSContext *cx, const nsCID &aCID);
 #endif
 #ifdef DEBUG_CAPS_HACKER
@@ -585,17 +586,18 @@ private:
     PRPackedBool mIsJavaScriptEnabled;
     PRPackedBool mIsMailJavaScriptEnabled;
     PRPackedBool mIsWritingPrefs;
     PRPackedBool mPolicyPrefsChanged;
 #ifdef XPC_IDISPATCH_SUPPORT    
     PRPackedBool mXPCDefaultGrantAll;
     static const char sXPCDefaultGrantAllName[];
 #endif
-    PRInt32 mFileURIOriginPolicy;
+
+    static PRInt32 sFileURIOriginPolicy;
 
     static nsIIOService    *sIOService;
     static nsIXPConnect    *sXPConnect;
     static nsIStringBundle *sStrBundle;
     static JSRuntime       *sRuntime;
 };
 
 // Levels for file: URI same-origin policy:
--- a/caps/src/nsNullPrincipal.cpp
+++ b/caps/src/nsNullPrincipal.cpp
@@ -44,16 +44,18 @@
 
 #include "nsNullPrincipal.h"
 #include "nsMemory.h"
 #include "nsIUUIDGenerator.h"
 #include "nsID.h"
 #include "nsNetUtil.h"
 #include "nsIClassInfoImpl.h"
 #include "nsNetCID.h"
+#include "nsDOMError.h"
+#include "nsScriptSecurityManager.h"
 
 static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID);
 
 NS_IMPL_QUERY_INTERFACE2_CI(nsNullPrincipal,
                             nsIPrincipal,
                             nsISerializable)
 NS_IMPL_CI_INTERFACE_GETTER2(nsNullPrincipal,
                              nsIPrincipal,
@@ -311,16 +313,27 @@ nsNullPrincipal::Subsumes(nsIPrincipal *
 {
   // We don't subsume anything except ourselves.  Note that nsPrincipal::Equals
   // will return false for us, since we're not about:blank and not Equals to
   // reasonable nsPrincipals.
   *aResult = (aOther == this);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsNullPrincipal::CheckMayLoad(nsIURI* aURI, PRBool aReport)
+{
+  if (aReport) {
+    nsScriptSecurityManager::ReportError(
+      nsnull, NS_LITERAL_STRING("CheckSameOriginError"), mURI, aURI);
+  }
+
+  return NS_ERROR_DOM_BAD_URI;
+}
+
 NS_IMETHODIMP 
 nsNullPrincipal::GetSubjectName(nsACString& aName)
 {
     return NS_ERROR_NOT_AVAILABLE;
 }
 
 NS_IMETHODIMP
 nsNullPrincipal::GetCertificate(nsISupports** aCertificate)
--- a/caps/src/nsPrincipal.cpp
+++ b/caps/src/nsPrincipal.cpp
@@ -49,16 +49,17 @@
 #include "nsJSPrincipals.h"
 #include "nsVoidArray.h"
 #include "nsHashtable.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefService.h"
 #include "nsIClassInfoImpl.h"
+#include "nsDOMError.h"
 
 #include "nsPrincipal.h"
 
 static PRBool URIIsImmutable(nsIURI* aURI)
 {
   nsCOMPtr<nsIMutable> mutableObj(do_QueryInterface(aURI));
   PRBool isMutable;
   return
@@ -302,16 +303,31 @@ nsPrincipal::Equals(nsIPrincipal *aOther
 
 NS_IMETHODIMP
 nsPrincipal::Subsumes(nsIPrincipal *aOther, PRBool *aResult)
 {
   return Equals(aOther, aResult);
 }
 
 NS_IMETHODIMP
+nsPrincipal::CheckMayLoad(nsIURI* aURI, PRBool aReport)
+{
+  if (!nsScriptSecurityManager::SecurityCompareURIs(mCodebase, aURI)) {
+    if (aReport) {
+      nsScriptSecurityManager::ReportError(
+        nsnull, NS_LITERAL_STRING("CheckSameOriginError"), mCodebase, aURI);
+    }
+    
+    return NS_ERROR_DOM_BAD_URI;
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsPrincipal::CanEnableCapability(const char *capability, PRInt16 *result)
 {
   // If this principal is marked invalid, can't enable any capabilities
   if (mCapabilities) {
     nsCStringKey invalidKey(sInvalid);
     if (mCapabilities->Exists(&invalidKey)) {
       *result = nsIPrincipal::ENABLE_DENIED;
 
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -93,16 +93,17 @@
 #include "nsCDefaultURIFixup.h"
 
 static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
 
 nsIIOService    *nsScriptSecurityManager::sIOService = nsnull;
 nsIXPConnect    *nsScriptSecurityManager::sXPConnect = nsnull;
 nsIStringBundle *nsScriptSecurityManager::sStrBundle = nsnull;
 JSRuntime       *nsScriptSecurityManager::sRuntime   = 0;
+PRInt32 nsScriptSecurityManager::sFileURIOriginPolicy = FILEURI_SOP_SELF;
 
 // Info we need about the JSClasses used by XPConnects wrapped
 // natives, to avoid having to QI to nsIXPConnectWrappedNative all the
 // time when doing security checks.
 static const JSClass *sXPCWrappedNativeJSClass;
 static JSGetObjectOps sXPCWrappedNativeGetObjOps1;
 static JSGetObjectOps sXPCWrappedNativeGetObjOps2;
 
@@ -272,16 +273,17 @@ nsScriptSecurityManager::GetSafeJSContex
     }
 
     JSContext *cx;
     if (NS_FAILED(mJSContextStack->GetSafeJSContext(&cx)))
         return nsnull;
     return cx;
 }
 
+/* static */
 PRBool
 nsScriptSecurityManager::SecurityCompareURIs(nsIURI* aSourceURI,
                                              nsIURI* aTargetURI)
 {
     // Note that this is not an Equals() test on purpose -- for URIs that don't
     // support host/port, we want equality to basically be object identity, for
     // security purposes.  Otherwise, for example, two javascript: URIs that
     // are otherwise unrelated could end up "same origin", which would be
@@ -373,26 +375,26 @@ nsScriptSecurityManager::SecurityCompare
 }
 
 // helper function for SecurityCompareURIs
 PRBool
 nsScriptSecurityManager::SecurityCompareFileURIs(nsIURI* aSourceURI,
                                                  nsIURI* aTargetURI)
 {
     // in traditional unsafe behavior all files are the same origin
-    if (mFileURIOriginPolicy == FILEURI_SOP_TRADITIONAL)
+    if (sFileURIOriginPolicy == FILEURI_SOP_TRADITIONAL)
         return PR_TRUE;
 
 
     // Check simplest and default FILEURI_SOP_SELF case first:
     // If they're equal or if the policy says they must be, we're done
     PRBool filesAreEqual = PR_FALSE;
     if (NS_FAILED( aSourceURI->Equals(aTargetURI, &filesAreEqual) ))
         return PR_FALSE;
-    if (filesAreEqual || mFileURIOriginPolicy == FILEURI_SOP_SELF)
+    if (filesAreEqual || sFileURIOriginPolicy == FILEURI_SOP_SELF)
         return filesAreEqual;
 
 
     // disallow access to directory listings (bug 209234)
     PRBool targetIsDir = PR_TRUE;
     nsCOMPtr<nsIFile> targetFile;
     nsCOMPtr<nsIFileURL> targetFileURL( do_QueryInterface(aTargetURI) );
 
@@ -401,17 +403,17 @@ nsScriptSecurityManager::SecurityCompare
         NS_FAILED( targetFile->IsDirectory(&targetIsDir) ) ||
         targetIsDir)
     {
         return PR_FALSE;
     }
 
 
     // For policy ANYFILE we're done
-    if (mFileURIOriginPolicy == FILEURI_SOP_ANYFILE)
+    if (sFileURIOriginPolicy == FILEURI_SOP_ANYFILE)
         return PR_TRUE;
 
 
     // source parent directory is needed for remaining policies
     nsCOMPtr<nsIFile> sourceFile;
     nsCOMPtr<nsIFile> sourceParent;
     nsCOMPtr<nsIFileURL> sourceFileURL( do_QueryInterface(aSourceURI) );
 
@@ -420,28 +422,28 @@ nsScriptSecurityManager::SecurityCompare
         NS_FAILED( sourceFile->GetParent(getter_AddRefs(sourceParent)) ) ||
         !sourceParent)
     {
         // unexpected error
         return PR_FALSE;
     }
 
     // check remaining policies
-    if (mFileURIOriginPolicy == FILEURI_SOP_SAMEDIR)
+    if (sFileURIOriginPolicy == FILEURI_SOP_SAMEDIR)
     {
         // file: URIs in the same directory have the same origin
         PRBool sameParent = PR_FALSE;
         nsCOMPtr<nsIFile> targetParent;
         if (NS_FAILED( targetFile->GetParent(getter_AddRefs(targetParent)) ) ||
             NS_FAILED( sourceParent->Equals(targetParent, &sameParent) ))
             return PR_FALSE;
         return sameParent;
     }
 
-    if (mFileURIOriginPolicy == FILEURI_SOP_SUBDIR)
+    if (sFileURIOriginPolicy == FILEURI_SOP_SUBDIR)
     {
         // file: URIs can access files in the same or lower directories
         PRBool isChild = PR_FALSE;
         if (NS_FAILED( sourceParent->Contains(targetFile, PR_TRUE, &isChild) ))
             return PR_FALSE;
         return isChild;
     }
 
@@ -3254,21 +3256,20 @@ nsScriptSecurityManager::Observe(nsISupp
 /////////////////////////////////////////////
 nsScriptSecurityManager::nsScriptSecurityManager(void)
     : mOriginToPolicyMap(nsnull),
       mDefaultPolicy(nsnull),
       mCapabilities(nsnull),
       mIsJavaScriptEnabled(PR_FALSE),
       mIsMailJavaScriptEnabled(PR_FALSE),
       mIsWritingPrefs(PR_FALSE),
-      mPolicyPrefsChanged(PR_TRUE),
+      mPolicyPrefsChanged(PR_TRUE)
 #ifdef XPC_IDISPATCH_SUPPORT
-      mXPCDefaultGrantAll(PR_FALSE),
+      , mXPCDefaultGrantAll(PR_FALSE)
 #endif
-      mFileURIOriginPolicy(FILEURI_SOP_SELF)
 {
     NS_ASSERTION(sizeof(long) == sizeof(void*), "long and void* have different lengths on this platform. This may cause a security failure.");
     mPrincipals.Init(31);
 }
 
 
 nsresult nsScriptSecurityManager::Init()
 {
@@ -3872,17 +3873,17 @@ nsScriptSecurityManager::ScriptSecurityP
     mIsJavaScriptEnabled = NS_FAILED(rv) || temp;
 
     rv = mSecurityPref->SecurityGetBoolPref(sJSMailEnabledPrefName, &temp);
     // JavaScript in Mail defaults to disabled in failure cases.
     mIsMailJavaScriptEnabled = NS_SUCCEEDED(rv) && temp;
 
     PRInt32 policy;
     rv = mSecurityPref->SecurityGetIntPref(sFileOriginPolicyPrefName, &policy);
-    mFileURIOriginPolicy = NS_SUCCEEDED(rv) ? policy : FILEURI_SOP_SELF;
+    sFileURIOriginPolicy = NS_SUCCEEDED(rv) ? policy : FILEURI_SOP_SELF;
 
 #ifdef XPC_IDISPATCH_SUPPORT
     rv = mSecurityPref->SecurityGetBoolPref(sXPCDefaultGrantAllName, &temp);
     // Granting XPC Priveleges defaults to disabled in failure cases.
     mXPCDefaultGrantAll = NS_SUCCEEDED(rv) && temp;
 #endif
 }
 
--- a/caps/src/nsSystemPrincipal.cpp
+++ b/caps/src/nsSystemPrincipal.cpp
@@ -111,16 +111,22 @@ nsSystemPrincipal::Equals(nsIPrincipal *
 NS_IMETHODIMP
 nsSystemPrincipal::Subsumes(nsIPrincipal *other, PRBool *result)
 {
     *result = PR_TRUE;
     return NS_OK;
 }
 
 NS_IMETHODIMP
+nsSystemPrincipal::CheckMayLoad(nsIURI* uri, PRBool aReport)
+{
+    return NS_OK;
+}
+
+NS_IMETHODIMP
 nsSystemPrincipal::GetHashValue(PRUint32 *result)
 {
     *result = NS_PTR_TO_INT32(this);
     return NS_OK;
 }
 
 NS_IMETHODIMP 
 nsSystemPrincipal::CanEnableCapability(const char *capability, 
--- a/content/base/public/nsISyncLoadDOMService.idl
+++ b/content/base/public/nsISyncLoadDOMService.idl
@@ -34,60 +34,66 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 
 interface nsIURI;
+interface nsIPrincipal;
 interface nsIDOMDocument;
 interface nsIChannel;
 
 /*************************************************************************
  *                                                                       *
  *                          **** NOTICE ****                             *
  *                                                                       *
- *    nsISyncLoadDOMService defines synchronous methods to download      *
- *    data from the network.  Any delays from the server will            *
- *    appear as a hang in the mozilla UI.  Therefore, this interface     *
- *    should be avoided as much as possible.                             *
+ *                                                                       *
+ *    This interface is DEPRECATED!                                      *
+ *    You should instead use XMLHttpRequest which now works both from    *
+ *    Javascript and C++.                                                *
+ *                                                                       *
+ *    Additionally, synchronous network loads are evil.  Any delays      *
+ *    from the server will appear as a hang in the mozilla UI.           *
+ *    Therefore, they should be avoided as much as possible.             *
  *                                                                       *
  *    Don't make me come over there!!                                    *
  *                                                                       *
  *                                                                       *
  ************************************************************************/
 
 /**
  * The nsISyncDOMLoadService interface can be used to synchronously load
  * a document.
  */
 
-[scriptable, uuid(2ae03836-0704-45c9-a545-4169548c0669)]
+[scriptable, uuid(8095998d-ae1c-4cfa-9b43-0973e5d77eb0)]
 interface nsISyncLoadDOMService : nsISupports
 {
     /**
      * Synchronously load the document from the specified channel.
      *
      * @param aChannel   The channel to load the document from.
-     * @param aLoaderURI URI of loading document. For security checks
-     *                   null if no securitychecks should be done
+     * @param aLoaderPrincipal Principal of loading document. For security
+     *                         checks null if no securitychecks should be done
      *
      * @returns The document loaded from the URI.
      */
-    nsIDOMDocument loadDocument(in nsIChannel aChannel, in nsIURI aLoaderURI);
+    nsIDOMDocument loadDocument(in nsIChannel aChannel,
+                                in nsIPrincipal aLoaderPrincipal);
 
     nsIDOMDocument loadDocumentAsXML(in nsIChannel aChannel,
-                                     in nsIURI aLoaderURI);
+                                     in nsIPrincipal aLoaderPrincipal);
 
     /**
      * Synchronously load an XML document from the specified
      * channel. The channel must be possible to open synchronously.
      *
      * @param aChannel   The channel to load the document from.
-     * @param aLoaderURI URI of loading document. For security checks
-     *                   null if no securitychecks should be done
+     * @param aLoaderPrincipal Principal of loading document. For security
+     *                         checks null if no securitychecks should be done
      *
      * @returns The document loaded from the URI.
      */
     nsIDOMDocument loadLocalDocument(in nsIChannel aChannel,
-                                     in nsIURI aLoaderURI);
+                                     in nsIPrincipal aLoaderPrincipal);
 };
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -861,18 +861,17 @@ nsContentSink::ProcessOfflineManifest(ns
   nsContentUtils::NewURIWithDocumentCharset(getter_AddRefs(manifestURI),
                                             manifestSpec, mDocument,
                                             mDocumentURI);
   if (!manifestURI) {
     return;
   }
 
   // Documents must list a manifest from the same origin
-  nsresult rv = nsContentUtils::GetSecurityManager()->
-                   CheckSameOriginURI(manifestURI, mDocumentURI, PR_TRUE);
+  nsresult rv = mDocument->NodePrincipal()->CheckMayLoad(manifestURI, PR_TRUE);
   if (NS_FAILED(rv)) {
     return;
   }
 
   // Start the update
   nsCOMPtr<nsIDOMDocument> domdoc = do_QueryInterface(mDocument);
   nsCOMPtr<nsIOfflineCacheUpdateService> updateService =
     do_GetService(NS_OFFLINECACHEUPDATESERVICE_CONTRACTID);
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -3829,20 +3829,17 @@ nsContentUtils::CheckSecurityBeforeLoad(
 
   // Same Origin
   if ((aAllowData && SchemeIs(aURIToLoad, "data")) ||
       ((aCheckLoadFlags & nsIScriptSecurityManager::ALLOW_CHROME) &&
        SchemeIs(aURIToLoad, "chrome"))) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsIURI> loadingURI;
-  rv = aLoadingPrincipal->GetURI(getter_AddRefs(loadingURI));
-  NS_ENSURE_SUCCESS(rv, rv);
-  return sSecurityManager->CheckSameOriginURI(loadingURI, aURIToLoad, PR_TRUE);
+  return aLoadingPrincipal->CheckMayLoad(aURIToLoad, PR_TRUE);
 }
 
 /* static */
 void
 nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext,
                             nsIURI *aLinkURI, const nsString &aTargetSpec,
                             PRBool aClick, PRBool aIsUserTriggered)
 {
--- a/content/base/src/nsCrossSiteListenerProxy.cpp
+++ b/content/base/src/nsCrossSiteListenerProxy.cpp
@@ -46,28 +46,39 @@
 #include "nsParserCIID.h"
 #include "nsICharsetAlias.h"
 #include "nsMimeTypes.h"
 #include "nsIStreamConverterService.h"
 #include "nsStringStream.h"
 #include "nsParserUtils.h"
 #include "nsGkAtoms.h"
 #include "nsWhitespaceTokenizer.h"
+#include "nsIChannelEventSink.h"
 
 static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
 
-NS_IMPL_ISUPPORTS5(nsCrossSiteListenerProxy, nsIStreamListener,
+NS_IMPL_ISUPPORTS7(nsCrossSiteListenerProxy, nsIStreamListener,
                    nsIRequestObserver, nsIContentSink, nsIXMLContentSink,
-                   nsIExpatSink)
+                   nsIExpatSink, nsIChannelEventSink, nsIInterfaceRequestor)
 
 nsCrossSiteListenerProxy::nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
-                                                   nsIPrincipal* aRequestingPrincipal)
-  : mOuter(aOuter), mAcceptState(eNotSet), mHasForwardedRequest(PR_FALSE)
+                                                   nsIPrincipal* aRequestingPrincipal,
+                                                   nsIChannel* aChannel,
+                                                   nsresult* aResult)
+  : mOuterListener(aOuter),
+    mRequestingPrincipal(aRequestingPrincipal),
+    mAcceptState(eNotSet),
+    mHasForwardedRequest(PR_FALSE),
+    mHasBeenCrossSite(PR_FALSE)
 {
   aRequestingPrincipal->GetURI(getter_AddRefs(mRequestingURI));
+  aChannel->GetNotificationCallbacks(getter_AddRefs(mOuterNotificationCallbacks));
+  aChannel->SetNotificationCallbacks(this);
+
+  *aResult = UpdateChannel(aChannel);
 }
 
 nsresult
 nsCrossSiteListenerProxy::ForwardRequest(PRBool aFromStop)
 {
   if (mHasForwardedRequest) {
     return NS_OK;
   }
@@ -78,41 +89,42 @@ nsCrossSiteListenerProxy::ForwardRequest
     mParser->Terminate();
     mParser = nsnull;
     mParserListener = nsnull;
   }
 
   if (mAcceptState != eAccept) {
     mAcceptState = eDeny;
     mOuterRequest->Cancel(NS_ERROR_DOM_BAD_URI);
-    mOuter->OnStartRequest(mOuterRequest, mOuterContext);
+    mOuterListener->OnStartRequest(mOuterRequest, mOuterContext);
 
     // Only call OnStopRequest here if we were called from OnStopRequest.
     // Otherwise the call to Cancel will make us get an OnStopRequest later
     // so we'll forward OnStopRequest then.
     if (aFromStop) {
-      mOuter->OnStopRequest(mOuterRequest, mOuterContext, NS_ERROR_DOM_BAD_URI);
+      mOuterListener->OnStopRequest(mOuterRequest, mOuterContext,
+                                    NS_ERROR_DOM_BAD_URI);
     }
 
     // Clear this data just in case since it should never be forwarded.
     mStoredData.Truncate();
 
     return NS_ERROR_DOM_BAD_URI;
   }
 
-  nsresult rv = mOuter->OnStartRequest(mOuterRequest, mOuterContext);
+  nsresult rv = mOuterListener->OnStartRequest(mOuterRequest, mOuterContext);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!mStoredData.IsEmpty()) {
     nsCOMPtr<nsIInputStream> stream;
     rv = NS_NewCStringInputStream(getter_AddRefs(stream), mStoredData);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    rv = mOuter->OnDataAvailable(mOuterRequest, mOuterContext, stream, 0,
-                                 mStoredData.Length());
+    rv = mOuterListener->OnDataAvailable(mOuterRequest, mOuterContext, stream,
+                                         0, mStoredData.Length());
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsCrossSiteListenerProxy::OnStartRequest(nsIRequest* aRequest,
@@ -132,19 +144,18 @@ nsCrossSiteListenerProxy::OnStartRequest
 
   // Check if this was actually a cross domain request
   nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
   if (!channel) {
     return NS_ERROR_DOM_BAD_URI;
   }
   nsCOMPtr<nsIURI> finalURI;
   channel->GetURI(getter_AddRefs(finalURI));
-  rv = nsContentUtils::GetSecurityManager()->
-    CheckSameOriginURI(mRequestingURI, finalURI, PR_FALSE);
-  if (NS_SUCCEEDED(rv)) {
+
+  if (!mHasBeenCrossSite) {
     mAcceptState = eAccept;
     return ForwardRequest(PR_FALSE);
   }
 
   nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(channel);
   if (http) {
     PRBool succeeded;
     rv = http->GetRequestSucceeded(&succeeded);
@@ -242,17 +253,17 @@ nsCrossSiteListenerProxy::OnStartRequest
 }
 
 NS_IMETHODIMP
 nsCrossSiteListenerProxy::OnStopRequest(nsIRequest* aRequest,
                                         nsISupports* aContext,
                                         nsresult aStatusCode)
 {
   if (mHasForwardedRequest) {
-    return mOuter->OnStopRequest(aRequest, aContext, aStatusCode);
+    return mOuterListener->OnStopRequest(aRequest, aContext, aStatusCode);
   }
 
   mAcceptState = eDeny;
   return ForwardRequest(PR_TRUE);
 }
 
 NS_METHOD
 StringSegmentWriter(nsIInputStream *aInStream,
@@ -276,18 +287,18 @@ nsCrossSiteListenerProxy::OnDataAvailabl
                                           nsIInputStream* aInputStream,
                                           PRUint32 aOffset,
                                           PRUint32 aCount)
 {
   if (mHasForwardedRequest) {
     if (mAcceptState != eAccept) {
       return NS_ERROR_DOM_BAD_URI;
     }
-    return mOuter->OnDataAvailable(aRequest, aContext, aInputStream, aOffset,
-                                   aCount);
+    return mOuterListener->OnDataAvailable(aRequest, aContext, aInputStream,
+                                           aOffset, aCount);
   }
 
   NS_ASSERTION(mStoredData.Length() == aOffset,
                "Stored wrong amount of data");
 
   PRUint32 read;
   nsresult rv = aInputStream->ReadSegments(StringSegmentWriter, &mStoredData,
                                            aCount, &read);
@@ -861,47 +872,98 @@ nsCrossSiteListenerProxy::VerifyAndMatch
 
   // Only matches if we've matched all of pattern and, if there is a wildcard, there
   // is at least one more entry in mReqSubdomains.
   
   return patternPos == 0 &&
          (!patternHasWild || reqPos >= 1);
 }
 
-/* static */
-nsresult
-nsCrossSiteListenerProxy::AddRequestHeaders(nsIChannel* aChannel,
-                                            nsIPrincipal* aRequestingPrincipal)
+NS_IMETHODIMP
+nsCrossSiteListenerProxy::GetInterface(const nsIID & aIID, void **aResult)
 {
-  // Once bug 386823 is fixed this could just be an assertion.
-  NS_ENSURE_TRUE(aRequestingPrincipal, NS_ERROR_FAILURE);
+  if (aIID.Equals(NS_GET_IID(nsIChannelEventSink))) {
+    *aResult = static_cast<nsIChannelEventSink*>(this);
+    NS_ADDREF_THIS();
+
+    return NS_OK;
+  }
+
+  return mOuterNotificationCallbacks ?
+    mOuterNotificationCallbacks->GetInterface(aIID, aResult) :
+    NS_ERROR_NO_INTERFACE;
+}
 
-  // Work out the requesting URI
+NS_IMETHODIMP
+nsCrossSiteListenerProxy::OnChannelRedirect(nsIChannel *aOldChannel,
+                                            nsIChannel *aNewChannel,
+                                            PRUint32    aFlags)
+{
+  nsresult rv;
+  nsCOMPtr<nsIChannelEventSink> outer =
+    do_GetInterface(mOuterNotificationCallbacks);
+  if (outer) {
+    rv = outer->OnChannelRedirect(aOldChannel, aNewChannel, aFlags);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  return UpdateChannel(aNewChannel);
+}
+
+nsresult
+nsCrossSiteListenerProxy::UpdateChannel(nsIChannel* aChannel)
+{
   nsCOMPtr<nsIURI> uri;
-  nsresult rv = aRequestingPrincipal->GetURI(getter_AddRefs(uri));
+  nsresult rv = aChannel->GetURI(getter_AddRefs(uri));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCString scheme, host;
-  rv = uri->GetScheme(scheme);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = uri->GetAsciiHost(host);
+  // Check that the uri is ok to load
+  rv = nsContentUtils::GetSecurityManager()->
+    CheckLoadURIWithPrincipal(mRequestingPrincipal, uri,
+                              nsIScriptSecurityManager::STANDARD);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCString root = scheme + NS_LITERAL_CSTRING("://") + host;
-  // Append the port
-  PRInt32 port;
-  uri->GetPort(&port);
-  if (port != -1) {
-    PRInt32 defaultPort = NS_GetDefaultPort(scheme.get());
-    if (port != defaultPort) {
-      root.Append(":");
-      root.AppendInt(port);
+  if (!mHasBeenCrossSite &&
+      NS_SUCCEEDED(mRequestingPrincipal->CheckMayLoad(uri, PR_FALSE))) {
+    return NS_OK;
+  }
+
+  nsCString userpass;
+  uri->GetUserPass(userpass);
+  NS_ENSURE_TRUE(userpass.IsEmpty(), NS_ERROR_DOM_BAD_URI);
+
+  // It's a cross site load
+  mHasBeenCrossSite = PR_TRUE;
+
+  // Work out the Referer-Root header
+  nsCString root, host;
+  rv = mRequestingURI->GetAsciiHost(host);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (!host.IsEmpty()) {
+    nsCString scheme;
+    rv = mRequestingURI->GetScheme(scheme);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    root = scheme + NS_LITERAL_CSTRING("://") + host;
+
+    // If needed, append the port
+    PRInt32 port;
+    mRequestingURI->GetPort(&port);
+    if (port != -1) {
+      PRInt32 defaultPort = NS_GetDefaultPort(scheme.get());
+      if (port != defaultPort) {
+        root.Append(":");
+        root.AppendInt(port);
+      }
     }
   }
+  else {
+    root.AssignLiteral("null");
+  }
 
   // Now add the access-control-origin header
   nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(aChannel);
   NS_ENSURE_TRUE(http, NS_ERROR_FAILURE);
 
   return http->SetRequestHeader(NS_LITERAL_CSTRING("Access-Control-Origin"),
     root, PR_FALSE);
 }
--- a/content/base/src/nsCrossSiteListenerProxy.h
+++ b/content/base/src/nsCrossSiteListenerProxy.h
@@ -39,62 +39,71 @@
 #include "nsIInterfaceRequestor.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsIURI.h"
 #include "nsTArray.h"
 #include "nsIContentSink.h"
 #include "nsIXMLContentSink.h"
 #include "nsIExpatSink.h"
+#include "nsIInterfaceRequestor.h"
+#include "nsIChannelEventSink.h"
 
 class nsIURI;
 class nsIParser;
 class nsIPrincipal;
 
 class nsCrossSiteListenerProxy : public nsIStreamListener,
                                  public nsIXMLContentSink,
-                                 public nsIExpatSink
+                                 public nsIExpatSink,
+                                 public nsIInterfaceRequestor,
+                                 public nsIChannelEventSink
 {
 public:
   nsCrossSiteListenerProxy(nsIStreamListener* aOuter,
-                           nsIPrincipal* aRequestingPrincipal);
-  
+                           nsIPrincipal* aRequestingPrincipal,
+                           nsIChannel* aChannel,
+                           nsresult* aResult);
+
   NS_DECL_ISUPPORTS
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_NSIEXPATSINK
-
-  static nsresult AddRequestHeaders(nsIChannel* aChannel,
-                                    nsIPrincipal* aRequestingPrincipal);
+  NS_DECL_NSIINTERFACEREQUESTOR
+  NS_DECL_NSICHANNELEVENTSINK
 
   // nsIContentSink
   NS_IMETHOD WillTokenize(void) { return NS_OK; }
   NS_IMETHOD WillBuildModel(void);
   NS_IMETHOD DidBuildModel()  { return NS_OK; }
   NS_IMETHOD WillInterrupt(void) { return NS_OK; }
   NS_IMETHOD WillResume(void) { return NS_OK; }
   NS_IMETHOD SetParser(nsIParser* aParser) { return NS_OK; }
   virtual void FlushPendingNotifications(mozFlushType aType) { }
   NS_IMETHOD SetDocumentCharset(nsACString& aCharset) { return NS_OK; }
   virtual nsISupports *GetTarget() { return nsnull; }
 
 private:
+  nsresult UpdateChannel(nsIChannel* aChannel);
 
   nsresult ForwardRequest(PRBool aCallStop);
   PRBool MatchPatternList(const char*& aIter, const char* aEnd);
   void CheckHeader(const nsCString& aHeader);
   PRBool VerifyAndMatchDomainPattern(const nsACString& aDomainPattern);
 
-  nsCOMPtr<nsIStreamListener> mOuter;
+  nsCOMPtr<nsIStreamListener> mOuterListener;
   nsCOMPtr<nsIRequest> mOuterRequest;
   nsCOMPtr<nsISupports> mOuterContext;
   nsCOMPtr<nsIStreamListener> mParserListener;
   nsCOMPtr<nsIParser> mParser;
   nsCOMPtr<nsIURI> mRequestingURI;
+  nsCOMPtr<nsIPrincipal> mRequestingPrincipal;
+  nsCOMPtr<nsIInterfaceRequestor> mOuterNotificationCallbacks;
   nsTArray<nsCString> mReqSubdomains;
   nsCString mStoredData;
   enum {
     eAccept,
     eDeny,
     eNotSet
   } mAcceptState;
   PRBool mHasForwardedRequest;
+  PRBool mHasBeenCrossSite;
 };
--- a/content/base/src/nsSyncLoadService.cpp
+++ b/content/base/src/nsSyncLoadService.cpp
@@ -54,32 +54,33 @@
 #include "nsIPrivateDOMImplementation.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsContentUtils.h"
 #include "nsThreadUtils.h"
 #include "nsNetUtil.h"
 #include "nsAutoPtr.h"
 #include "nsLoadListenerProxy.h"
 #include "nsStreamUtils.h"
+#include "nsCrossSiteListenerProxy.h"
 
 /**
  * This class manages loading a single XML document
  */
 
 class nsSyncLoader : public nsIDOMLoadListener,
                      public nsIChannelEventSink,
                      public nsIInterfaceRequestor,
                      public nsSupportsWeakReference
 {
 public:
     virtual ~nsSyncLoader();
 
     NS_DECL_ISUPPORTS
 
-    nsresult LoadDocument(nsIChannel* aChannel, nsIURI *aLoaderURI,
+    nsresult LoadDocument(nsIChannel* aChannel, nsIPrincipal *aLoaderPrincipal,
                           PRBool aChannelIsSync, PRBool aForceToXML,
                           nsIDOMDocument** aResult);
 
     NS_DECL_NSIDOMEVENTLISTENER
 
     // nsIDOMLoadListener
     NS_IMETHOD Load(nsIDOMEvent* aEvent);
     NS_IMETHOD BeforeUnload(nsIDOMEvent* aEvent);
@@ -157,51 +158,45 @@ nsSyncLoader::~nsSyncLoader()
 NS_IMPL_ISUPPORTS4(nsSyncLoader,
                    nsIDOMLoadListener,
                    nsIChannelEventSink,
                    nsIInterfaceRequestor,
                    nsISupportsWeakReference)
 
 nsresult
 nsSyncLoader::LoadDocument(nsIChannel* aChannel,
-                           nsIURI *aLoaderURI,
+                           nsIPrincipal *aLoaderPrincipal,
                            PRBool aChannelIsSync,
                            PRBool aForceToXML,
                            nsIDOMDocument **aResult)
 {
     NS_ENSURE_ARG_POINTER(aResult);
     *aResult = nsnull;
     nsresult rv = NS_OK;
 
+    nsCOMPtr<nsIURI> loaderUri;
+    if (aLoaderPrincipal) {
+        aLoaderPrincipal->GetURI(getter_AddRefs(loaderUri));
+    }
+
     mChannel = aChannel;
     nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(mChannel);
     if (http) {
         http->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),     
                                NS_LITERAL_CSTRING("text/xml,application/xml,application/xhtml+xml,*/*;q=0.1"),
                                PR_FALSE);
-        if (aLoaderURI) {
-            http->SetReferrer(aLoaderURI);
+        if (loaderUri) {
+            http->SetReferrer(loaderUri);
         }
     }
 
-    if (aLoaderURI) {
-        nsCOMPtr<nsIURI> docURI;
-        rv = aChannel->GetOriginalURI(getter_AddRefs(docURI));
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        nsIScriptSecurityManager *securityManager =
-            nsContentUtils::GetSecurityManager();
-
-        rv = securityManager->CheckLoadURI(aLoaderURI, docURI,
-                                           nsIScriptSecurityManager::STANDARD);
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        rv = securityManager->CheckSameOriginURI(aLoaderURI, docURI, PR_TRUE);
-        NS_ENSURE_SUCCESS(rv, rv);
-    }
+    // Hook us up to listen to redirects and the like.
+    // Do this before setting up the cross-site proxy since
+    // that installs its own proxies.
+    mChannel->SetNotificationCallbacks(this);
 
     // Get the loadgroup of the channel
     nsCOMPtr<nsILoadGroup> loadGroup;
     rv = aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Create document
     nsCOMPtr<nsIDocument> document;
@@ -218,16 +213,23 @@ nsSyncLoader::LoadDocument(nsIChannel* a
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (aForceToXML) {
         nsCOMPtr<nsIStreamListener> forceListener =
             new nsForceXMLListener(listener);
         listener.swap(forceListener);
     }
 
+    if (aLoaderPrincipal) {
+        listener = new nsCrossSiteListenerProxy(listener, aLoaderPrincipal,
+                                                mChannel, &rv);
+        NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
+        NS_ENSURE_SUCCESS(rv, rv);
+    }
+
     // Register as a load listener on the document
     nsCOMPtr<nsPIDOMEventTarget> target = do_QueryInterface(document);
     NS_ENSURE_TRUE(target, NS_ERROR_FAILURE);
 
     nsWeakPtr requestWeak = do_GetWeakReference(static_cast<nsIDOMLoadListener*>(this));
     nsLoadListenerProxy* proxy = new nsLoadListenerProxy(requestWeak);
     NS_ENSURE_TRUE(proxy, NS_ERROR_OUT_OF_MEMORY);
 
@@ -265,19 +267,16 @@ nsSyncLoader::LoadDocument(nsIChannel* a
     NS_ENSURE_TRUE(document->GetRootContent(), NS_ERROR_FAILURE);
 
     return CallQueryInterface(document, aResult);
 }
 
 nsresult
 nsSyncLoader::PushAsyncStream(nsIStreamListener* aListener)
 {
-    // Hook us up to listen to redirects and the like
-    mChannel->SetNotificationCallbacks(this);
-
     // Start reading from the channel
     nsresult rv = mChannel->AsyncOpen(aListener, nsnull);
 
     if (NS_SUCCEEDED(rv)) {
         // process events until we're finished.
         mLoading = PR_TRUE;
         nsIThread *thread = NS_GetCurrentThread();
         while (mLoading && NS_SUCCEEDED(rv)) {
@@ -362,82 +361,75 @@ nsSyncLoader::Error(nsIDOMEvent* aEvent)
 
 NS_IMETHODIMP
 nsSyncLoader::OnChannelRedirect(nsIChannel *aOldChannel,
                                 nsIChannel *aNewChannel,
                                 PRUint32    aFlags)
 {
     NS_PRECONDITION(aNewChannel, "Redirecting to null channel?");
 
-    nsCOMPtr<nsIURI> oldURI;
-    nsresult rv = aOldChannel->GetURI(getter_AddRefs(oldURI)); // The original URI
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    nsCOMPtr<nsIURI> newURI;
-    rv = aNewChannel->GetURI(getter_AddRefs(newURI)); // The new URI
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    nsIScriptSecurityManager *securityManager =
-        nsContentUtils::GetSecurityManager();
-
-    rv = securityManager->CheckSameOriginURI(oldURI, newURI, PR_TRUE);
-    NS_ENSURE_SUCCESS(rv, rv);
-
     mChannel = aNewChannel;
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsSyncLoader::GetInterface(const nsIID & aIID,
                            void **aResult)
 {
     return QueryInterface(aIID, aResult);
 }
 
 NS_IMPL_ISUPPORTS1(nsSyncLoadService,
                    nsISyncLoadDOMService)
 
 static nsresult
-LoadFromChannel(nsIChannel* aChannel, nsIURI *aLoaderURI, PRBool aChannelIsSync,
-                PRBool aForceToXML, nsIDOMDocument** aResult)
+LoadFromChannel(nsIChannel* aChannel, nsIPrincipal *aLoaderPrincipal,
+                PRBool aChannelIsSync, PRBool aForceToXML,
+                nsIDOMDocument** aResult)
 {
     nsRefPtr<nsSyncLoader> loader = new nsSyncLoader();
     if (!loader) {
         return NS_ERROR_OUT_OF_MEMORY;
     }
 
-    return loader->LoadDocument(aChannel, aLoaderURI, aChannelIsSync,
+    return loader->LoadDocument(aChannel, aLoaderPrincipal, aChannelIsSync,
                                 aForceToXML, aResult);
 }
 
 NS_IMETHODIMP
-nsSyncLoadService::LoadDocument(nsIChannel* aChannel, nsIURI* aLoaderURI,
+nsSyncLoadService::LoadDocument(nsIChannel* aChannel,
+                                nsIPrincipal* aLoaderPrincipal,
                                 nsIDOMDocument** aResult)
 {
-    return LoadFromChannel(aChannel, aLoaderURI, PR_FALSE, PR_FALSE, aResult);
+    return LoadFromChannel(aChannel, aLoaderPrincipal, PR_FALSE, PR_FALSE,
+                           aResult);
 }
 
 NS_IMETHODIMP
-nsSyncLoadService::LoadDocumentAsXML(nsIChannel* aChannel, nsIURI* aLoaderURI,
+nsSyncLoadService::LoadDocumentAsXML(nsIChannel* aChannel,
+                                     nsIPrincipal* aLoaderPrincipal,
                                      nsIDOMDocument** aResult)
 {
-    return LoadFromChannel(aChannel, aLoaderURI, PR_FALSE, PR_TRUE, aResult);
+    return LoadFromChannel(aChannel, aLoaderPrincipal, PR_FALSE, PR_TRUE,
+                           aResult);
 }
 
 NS_IMETHODIMP
-nsSyncLoadService::LoadLocalDocument(nsIChannel* aChannel, nsIURI* aLoaderURI,
+nsSyncLoadService::LoadLocalDocument(nsIChannel* aChannel,
+                                     nsIPrincipal* aLoaderPrincipal,
                                      nsIDOMDocument** aResult)
 {
-    return LoadFromChannel(aChannel, aLoaderURI, PR_TRUE, PR_TRUE, aResult);
+    return LoadFromChannel(aChannel, aLoaderPrincipal, PR_TRUE, PR_TRUE,
+                           aResult);
 }
 
 /* static */
 nsresult
-nsSyncLoadService::LoadDocument(nsIURI *aURI, nsIURI *aLoaderURI,
+nsSyncLoadService::LoadDocument(nsIURI *aURI, nsIPrincipal *aLoaderPrincipal,
                                 nsILoadGroup *aLoadGroup, PRBool aForceToXML,
                                 nsIDOMDocument** aResult)
 {
     nsCOMPtr<nsIChannel> channel;
     nsresult rv = NS_NewChannel(getter_AddRefs(channel), aURI, nsnull,
                                 aLoadGroup);
     NS_ENSURE_SUCCESS(rv, rv);
 
@@ -446,17 +438,18 @@ nsSyncLoadService::LoadDocument(nsIURI *
     }
 
     PRBool isChrome = PR_FALSE, isResource = PR_FALSE;
     PRBool isSync = (NS_SUCCEEDED(aURI->SchemeIs("chrome", &isChrome)) &&
                      isChrome) ||
                     (NS_SUCCEEDED(aURI->SchemeIs("resource", &isResource)) &&
                      isResource);
 
-    return LoadFromChannel(channel, aLoaderURI, isSync, aForceToXML, aResult);
+    return LoadFromChannel(channel, aLoaderPrincipal, isSync, aForceToXML,
+                           aResult);
 }
 
 /* static */
 nsresult
 nsSyncLoadService::PushSyncStreamToListener(nsIInputStream* aIn,
                                             nsIStreamListener* aListener,
                                             nsIChannel* aChannel)
 {
--- a/content/base/src/nsSyncLoadService.h
+++ b/content/base/src/nsSyncLoadService.h
@@ -55,25 +55,25 @@ class nsSyncLoadService : public nsISync
 public:
     NS_DECL_ISUPPORTS
     NS_DECL_NSISYNCLOADDOMSERVICE
 
     /**
      * Synchronously load the document from the specified URI.
      *
      * @param aURI URI to load the document from.
-     * @param aLoaderURI URI of loading document. For security checks and
-     *                   referrer header. May be null if no security checks
-     *                   should be done.
+     * @param aLoaderPrincipal Principal of loading document. For security
+     *                         checks and referrer header. May be null if no
+     *                         security checks should be done.
      * @param aLoadGroup The loadgroup to use for loading the document.
      * @param aForceToXML Whether to parse the document as XML, regardless of
      *                    content type.
      * @param aResult [out] The document loaded from the URI.
      */
-    static nsresult LoadDocument(nsIURI *aURI, nsIURI *aLoaderURI,
+    static nsresult LoadDocument(nsIURI *aURI, nsIPrincipal *aLoaderPrincipal,
                                  nsILoadGroup *aLoadGroup, PRBool aForceToXML,
                                  nsIDOMDocument** aResult);
 
     /**
      * Read input stream aIn in chunks and deliver synchronously to aListener.
      *
      * @param aIn The stream to be read.
      * @param aListener The listener that will receive
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -1411,37 +1411,27 @@ nsXMLHttpRequest::CheckChannelForCrossSi
     return NS_OK;
   }
 
   // This is a cross-site request
 
   // The request is now cross-site, so update flag.
   mState |= XML_HTTP_REQUEST_USE_XSITE_AC;
 
-  // Remove dangerous headers and set XMLHttpRequest-Security-Check
+  // Remove dangerous headers
   nsCOMPtr<nsIHttpChannel> http = do_QueryInterface(mChannel);
   if (http) {
     PRUint32 i;
     for (i = 0; i < mExtraRequestHeaders.Length(); ++i) {
       http->SetRequestHeader(mExtraRequestHeaders[i], EmptyCString(), PR_FALSE);
     }
     mExtraRequestHeaders.Clear();
   }
 
-  // Cancel if username/password is supplied to avoid brute-force password
-  // hacking
-  nsCOMPtr<nsIURI> channelURI;
-  nsresult rv = mChannel->GetURI(getter_AddRefs(channelURI));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsCString userpass;
-  channelURI->GetUserPass(userpass);
-  NS_ENSURE_TRUE(userpass.IsEmpty(), NS_ERROR_DOM_BAD_URI);
-  
-  return nsCrossSiteListenerProxy::AddRequestHeaders(mChannel, mPrincipal);
+  return NS_OK;
 }
 
 /* noscript void openRequest (in AUTF8String method, in AUTF8String url, in boolean async, in AString user, in AString password); */
 NS_IMETHODIMP
 nsXMLHttpRequest::OpenRequest(const nsACString& method,
                               const nsACString& url,
                               PRBool async,
                               const nsAString& user,
@@ -1585,18 +1575,16 @@ nsXMLHttpRequest::OpenRequest(const nsAC
 
     if (expiration <= PR_Now()) {
       // Either it wasn't cached or the cached result has expired. Build a
       // channel for the OPTIONS request.
       rv = NS_NewChannel(getter_AddRefs(mACGetChannel), uri, nsnull, loadGroup,
                          nsnull, loadFlags);
       NS_ENSURE_SUCCESS(rv, rv);
 
-      rv = nsCrossSiteListenerProxy::AddRequestHeaders(mACGetChannel, mPrincipal);
-
       nsCOMPtr<nsIHttpChannel> acHttp = do_QueryInterface(mACGetChannel);
       NS_ASSERTION(acHttp, "Failed to QI to nsIHttpChannel!");
 
       rv = acHttp->SetRequestMethod(NS_LITERAL_CSTRING("OPTIONS"));
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
@@ -2285,18 +2273,20 @@ nsXMLHttpRequest::Send(nsIVariant *aBody
     if (!listener) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
   if (!(mState & XML_HTTP_REQUEST_XSITEENABLED)) {
     // Always create a nsCrossSiteListenerProxy here even if it's
     // a same-origin request right now, since it could be redirected.
-    listener = new nsCrossSiteListenerProxy(listener, mPrincipal);
+    listener = new nsCrossSiteListenerProxy(listener, mPrincipal, mChannel,
+                                            &rv);
     NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
+    NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // Bypass the network cache in cases where it makes no sense:
   // 1) Multipart responses are very large and would likely be doomed by the
   //    cache once they grow too large, so they are not worth caching.
   // 2) POST responses are always unique, and we provide no API that would
   //    allow our consumers to specify a "cache key" to access old POST
   //    responses, so they are not worth caching.
@@ -2323,18 +2313,20 @@ nsXMLHttpRequest::Send(nsIVariant *aBody
 
   // If we're doing a cross-site non-GET request we need to first do
   // a GET request to the same URI. Set that up if needed
   if (mACGetChannel) {
     nsCOMPtr<nsIStreamListener> acListener =
       new nsACProxyListener(mChannel, listener, nsnull, mPrincipal, method);
     NS_ENSURE_TRUE(acListener, NS_ERROR_OUT_OF_MEMORY);
 
-    listener = new nsCrossSiteListenerProxy(acListener, mPrincipal);
+    listener = new nsCrossSiteListenerProxy(acListener, mPrincipal,
+                                            mACGetChannel, &rv);
     NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
+    NS_ENSURE_SUCCESS(rv, rv);
 
     rv = mACGetChannel->AsyncOpen(listener, nsnull);
   }
   else {
     // Start reading from the channel
     rv = mChannel->AsyncOpen(listener, nsnull);
   }
 
--- a/content/xml/document/src/nsXMLContentSink.cpp
+++ b/content/xml/document/src/nsXMLContentSink.cpp
@@ -766,19 +766,16 @@ nsXMLContentSink::ProcessStyleLink(nsICo
 
     // Do security check
     nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
     rv = secMan->
       CheckLoadURIWithPrincipal(mDocument->NodePrincipal(), url,
                                 nsIScriptSecurityManager::ALLOW_CHROME);
     NS_ENSURE_SUCCESS(rv, NS_OK);
 
-    rv = secMan->CheckSameOriginURI(mDocumentURI, url, PR_TRUE);
-    NS_ENSURE_SUCCESS(rv, NS_OK);
-
     // Do content policy check
     PRInt16 decision = nsIContentPolicy::ACCEPT;
     rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET,
                                    url,
                                    mDocument->NodePrincipal(),
                                    aElement,
                                    type,
                                    nsnull,
--- a/content/xml/document/src/nsXMLDocument.cpp
+++ b/content/xml/document/src/nsXMLDocument.cpp
@@ -373,16 +373,19 @@ nsXMLDocument::Load(const nsAString& aUr
 
   // Get security manager, check to see whether the current document
   // is allowed to load this URI. It's important to use the current
   // document's principal for this check so that we don't end up in a
   // case where code with elevated privileges is calling us and
   // changing the principal of this document.
   nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
 
+  // Enforce same-origin even for chrome loaders to avoid someone accidentally
+  // using a document that content has a reference to and turn that into a
+  // chrome document.
   if (codebase) {
     rv = secMan->CheckSameOriginURI(codebase, uri, PR_FALSE);
 
     if (NS_FAILED(rv)) {
       return rv;
     }
   } else {
     // We're called from chrome, check to make sure the URI we're
--- a/content/xslt/src/xml/txXMLParser.cpp
+++ b/content/xslt/src/xml/txXMLParser.cpp
@@ -95,28 +95,25 @@ txParseDocumentFromURI(const nsAString& 
     nsCOMPtr<nsIURI> documentURI;
     nsresult rv = NS_NewURI(getter_AddRefs(documentURI), aHref);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsIDocument* loaderDocument = txXPathNativeNode::getDocument(aLoader);
 
     nsCOMPtr<nsILoadGroup> loadGroup = loaderDocument->GetDocumentLoadGroup();
 
-    nsCOMPtr<nsIURI> loaderUri;
-    rv = loaderDocument->NodePrincipal()->GetURI(getter_AddRefs(loaderUri));
-    NS_ENSURE_SUCCESS(rv, rv);
-
     // For the system principal loaderUri will be null here, which is good
     // since that means that chrome documents can load any uri.
 
     // Raw pointer, we want the resulting txXPathNode to hold a reference to
     // the document.
     nsIDOMDocument* theDocument = nsnull;
-    rv = nsSyncLoadService::LoadDocument(documentURI, loaderUri, loadGroup,
-                                         PR_TRUE, &theDocument);
+    rv = nsSyncLoadService::LoadDocument(documentURI,
+                                         loaderDocument->NodePrincipal(),
+                                         loadGroup, PR_TRUE, &theDocument);
 
     if (NS_FAILED(rv)) {
         aErrMsg.Append(NS_LITERAL_STRING("Document load of ") + 
                        aHref + NS_LITERAL_STRING(" failed."));
         return NS_FAILED(rv) ? rv : NS_ERROR_FAILURE;
     }
 
     *aResult = txXPathNativeNode::createXPathNode(theDocument);
--- a/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp
+++ b/content/xslt/src/xslt/txMozillaStylesheetCompiler.cpp
@@ -65,16 +65,18 @@
 #include "txAtoms.h"
 #include "txLog.h"
 #include "txMozillaXSLTProcessor.h"
 #include "txStylesheetCompiler.h"
 #include "txXMLUtils.h"
 #include "nsAttrName.h"
 #include "nsIScriptError.h"
 #include "nsIURL.h"
+#include "nsCrossSiteListenerProxy.h"
+#include "nsDOMError.h"
 
 static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
 
 static void
 getSpec(nsIChannel* aChannel, nsAString& aSpec)
 {
     if (!aChannel) {
         return;
@@ -89,27 +91,25 @@ getSpec(nsIChannel* aChannel, nsAString&
     nsCAutoString spec;
     uri->GetSpec(spec);
     AppendUTF8toUTF16(spec, aSpec);
 }
 
 class txStylesheetSink : public nsIXMLContentSink,
                          public nsIExpatSink,
                          public nsIStreamListener,
-                         public nsIChannelEventSink,
                          public nsIInterfaceRequestor
 {
 public:
     txStylesheetSink(txStylesheetCompiler* aCompiler, nsIParser* aParser);
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIEXPATSINK
     NS_DECL_NSISTREAMLISTENER
     NS_DECL_NSIREQUESTOBSERVER
-    NS_DECL_NSICHANNELEVENTSINK
     NS_DECL_NSIINTERFACEREQUESTOR
 
     // nsIContentSink
     NS_IMETHOD WillTokenize(void) { return NS_OK; }
     NS_IMETHOD WillBuildModel(void) { return NS_OK; }
     NS_IMETHOD DidBuildModel();
     NS_IMETHOD WillInterrupt(void) { return NS_OK; }
     NS_IMETHOD WillResume(void) { return NS_OK; }
@@ -131,23 +131,22 @@ protected:
 txStylesheetSink::txStylesheetSink(txStylesheetCompiler* aCompiler,
                                    nsIParser* aParser)
     : mCompiler(aCompiler),
       mCheckedForXML(PR_FALSE)
 {
     mListener = do_QueryInterface(aParser);
 }
 
-NS_IMPL_ISUPPORTS7(txStylesheetSink,
+NS_IMPL_ISUPPORTS6(txStylesheetSink,
                    nsIXMLContentSink,
                    nsIContentSink,
                    nsIExpatSink,
                    nsIStreamListener,
                    nsIRequestObserver,
-                   nsIChannelEventSink,
                    nsIInterfaceRequestor)
 
 NS_IMETHODIMP
 txStylesheetSink::HandleStartElement(const PRUnichar *aName,
                                      const PRUnichar **aAtts,
                                      PRUint32 aAttsCount,
                                      PRInt32 aIndex,
                                      PRUint32 aLineNumber)
@@ -370,39 +369,16 @@ txStylesheetSink::OnStopRequest(nsIReque
     }
 
     nsresult rv = mListener->OnStopRequest(aRequest, aContext, aStatusCode);
     mListener = nsnull;
     return rv;
 }
 
 NS_IMETHODIMP
-txStylesheetSink::OnChannelRedirect(nsIChannel *aOldChannel,
-                                    nsIChannel *aNewChannel,
-                                    PRUint32    aFlags)
-{
-    NS_PRECONDITION(aNewChannel, "Redirect without a channel?");
-
-    nsresult rv;
-    nsCOMPtr<nsIScriptSecurityManager> secMan =
-        do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    nsCOMPtr<nsIURI> oldURI;
-    rv = aOldChannel->GetURI(getter_AddRefs(oldURI)); // The original URI
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    nsCOMPtr<nsIURI> newURI;
-    rv = aNewChannel->GetURI(getter_AddRefs(newURI)); // The new URI
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    return secMan->CheckSameOriginURI(oldURI, newURI, PR_TRUE);
-}
-
-NS_IMETHODIMP
 txStylesheetSink::GetInterface(const nsIID& aIID, void** aResult)
 {
     if (aIID.Equals(NS_GET_IID(nsIAuthPrompt))) {
         NS_ENSURE_ARG(aResult);
         *aResult = nsnull;
 
         nsresult rv;
         nsCOMPtr<nsIWindowWatcher> wwatcher =
@@ -415,17 +391,17 @@ txStylesheetSink::GetInterface(const nsI
 
         nsIAuthPrompt* rawPtr = nsnull;
         prompt.swap(rawPtr);
         *aResult = rawPtr;
 
         return NS_OK;
     }
 
-    return QueryInterface(aIID, aResult);
+    return NS_ERROR_NO_INTERFACE;
 }
 
 class txCompileObserver : public txACompileObserver
 {
 public:
     txCompileObserver(txMozillaXSLTProcessor* aProcessor,
                       nsILoadGroup* aLoadGroup);
 
@@ -488,23 +464,29 @@ txCompileObserver::loadURI(const nsAStri
     rv = NS_NewURI(getter_AddRefs(referrerUri), aReferrerUri);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIPrincipal> referrerPrincipal;
     rv = nsContentUtils::GetSecurityManager()->
       GetCodebasePrincipal(referrerUri, getter_AddRefs(referrerPrincipal));
     NS_ENSURE_SUCCESS(rv, rv);
 
-    // Do security check.
-    rv = nsContentUtils::
-      CheckSecurityBeforeLoad(uri, referrerPrincipal,
-                              nsIScriptSecurityManager::STANDARD, PR_FALSE,
-                              nsIContentPolicy::TYPE_STYLESHEET,
-                              nsnull, NS_LITERAL_CSTRING("application/xml"));
+    // Content Policy
+    PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
+    rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET,
+                                   uri,
+                                   referrerPrincipal,
+                                   nsnull,
+                                   NS_LITERAL_CSTRING("application/xml"),
+                                   nsnull,
+                                   &shouldLoad);
     NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_CP_REJECTED(shouldLoad)) {
+        return NS_ERROR_DOM_BAD_URI;
+    }
 
     return startLoad(uri, aCompiler, referrerPrincipal);
 }
 
 void
 txCompileObserver::onDoneCompiling(txStylesheetCompiler* aCompiler,
                                    nsresult aResult,
                                    const PRUnichar *aErrorText,
@@ -550,35 +532,47 @@ txCompileObserver::startLoad(nsIURI* aUr
     NS_ENSURE_TRUE(sink, NS_ERROR_OUT_OF_MEMORY);
 
     channel->SetNotificationCallbacks(sink);
 
     parser->SetCommand(kLoadAsData);
     parser->SetContentSink(sink);
     parser->Parse(aUri);
 
+    // Always install in case of redirects
+    nsCOMPtr<nsIStreamListener> listener =
+        new nsCrossSiteListenerProxy(sink, aReferrerPrincipal, channel, &rv);
+    NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY);
+    NS_ENSURE_SUCCESS(rv, rv);
+
     return channel->AsyncOpen(sink, parser);
 }
 
 nsresult
 TX_LoadSheet(nsIURI* aUri, txMozillaXSLTProcessor* aProcessor,
              nsILoadGroup* aLoadGroup, nsIPrincipal* aCallerPrincipal)
 {
     nsCAutoString spec;
     aUri->GetSpec(spec);
     PR_LOG(txLog::xslt, PR_LOG_ALWAYS, ("TX_LoadSheet: %s\n", spec.get()));
 
-    // Pass source document as the context
-    nsresult rv = nsContentUtils::
-      CheckSecurityBeforeLoad(aUri, aCallerPrincipal,
-                              nsIScriptSecurityManager::STANDARD, PR_FALSE,
-                              nsIContentPolicy::TYPE_STYLESHEET,
-                              aProcessor->GetSourceContentModel(),
-                              NS_LITERAL_CSTRING("application/xml"));
+    // Content Policy
+    PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
+    nsresult rv =
+        NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET,
+                                  aUri,
+                                  aCallerPrincipal,
+                                  aProcessor->GetSourceContentModel(),
+                                  NS_LITERAL_CSTRING("application/xml"),
+                                  nsnull,
+                                  &shouldLoad);
     NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_CP_REJECTED(shouldLoad)) {
+        return NS_ERROR_DOM_BAD_URI;
+    }
 
     nsRefPtr<txCompileObserver> observer =
         new txCompileObserver(aProcessor, aLoadGroup);
     NS_ENSURE_TRUE(observer, NS_ERROR_OUT_OF_MEMORY);
 
     nsRefPtr<txStylesheetCompiler> compiler =
         new txStylesheetCompiler(NS_ConvertUTF8toUTF16(spec), observer);
     NS_ENSURE_TRUE(compiler, NS_ERROR_OUT_OF_MEMORY);
@@ -710,28 +704,35 @@ txSyncCompileObserver::loadURI(const nsA
     rv = NS_NewURI(getter_AddRefs(referrerUri), aReferrerUri);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIPrincipal> referrerPrincipal;
     rv = nsContentUtils::GetSecurityManager()->
       GetCodebasePrincipal(referrerUri, getter_AddRefs(referrerPrincipal));
     NS_ENSURE_SUCCESS(rv, rv);
 
-    rv = nsContentUtils::
-      CheckSecurityBeforeLoad(uri, referrerPrincipal,
-                              nsIScriptSecurityManager::STANDARD,
-                              PR_FALSE, nsIContentPolicy::TYPE_STYLESHEET,
-                              nsnull, NS_LITERAL_CSTRING("application/xml"));
+    // Content Policy
+    PRInt16 shouldLoad = nsIContentPolicy::ACCEPT;
+    rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_STYLESHEET,
+                                   uri,
+                                   referrerPrincipal,
+                                   nsnull,
+                                   NS_LITERAL_CSTRING("application/xml"),
+                                   nsnull,
+                                   &shouldLoad);
     NS_ENSURE_SUCCESS(rv, rv);
+    if (NS_CP_REJECTED(shouldLoad)) {
+        return NS_ERROR_DOM_BAD_URI;
+    }
 
     // This is probably called by js, a loadGroup for the channel doesn't
     // make sense.
     nsCOMPtr<nsIDOMDocument> document;
-    rv = nsSyncLoadService::LoadDocument(uri, referrerUri, nsnull, PR_FALSE,
-                                         getter_AddRefs(document));
+    rv = nsSyncLoadService::LoadDocument(uri, referrerPrincipal, nsnull,
+                                         PR_FALSE, getter_AddRefs(document));
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsCOMPtr<nsIDocument> doc = do_QueryInterface(document);
     rv = handleNode(doc, aCompiler);
     if (NS_FAILED(rv)) {
         nsCAutoString spec;
         uri->GetSpec(spec);
         aCompiler->cancel(rv, nsnull, NS_ConvertUTF8toUTF16(spec).get());
--- a/content/xul/document/src/nsXULDocument.cpp
+++ b/content/xul/document/src/nsXULDocument.cpp
@@ -2600,26 +2600,23 @@ nsXULDocument::LoadOverlayInternal(nsIUR
         PR_LOG(gXULLog, PR_LOG_DEBUG,
                 ("xul: loading overlay %s", urlspec.get()));
     }
 #endif
 
     if (aIsDynamic)
         mResolutionPhase = nsForwardReference::eStart;
 
-    nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
-    NS_ENSURE_TRUE(secMan, NS_ERROR_NOT_AVAILABLE);
-
     // Chrome documents are allowed to load overlays from anywhere.
     // In all other cases, the overlay is only allowed to load if
     // the master document and prototype document have the same origin.
 
     if (!IsChromeURI(mDocumentURI)) {
         // Make sure we're allowed to load this overlay.
-        rv = secMan->CheckSameOriginURI(mDocumentURI, aURI, PR_TRUE);
+        rv = NodePrincipal()->CheckMayLoad(aURI, PR_TRUE);
         if (NS_FAILED(rv)) {
             *aFailureFromContent = PR_TRUE;
             return rv;
         }
     }
 
     // Look in the prototype cache for the prototype document with
     // the specified overlay URI.
--- a/extensions/canvas3d/src/nsCanvasRenderingContextGL.cpp
+++ b/extensions/canvas3d/src/nsCanvasRenderingContextGL.cpp
@@ -708,40 +708,26 @@ nsCanvasRenderingContextGLPrivate::DoDra
 
     fprintf (stderr, "DoDrawImageSecuritycheck this 3: %p\n", this);
     if (forceWriteOnly) {
         mCanvasElement->SetWriteOnly();
         return;
     }
 
     fprintf (stderr, "DoDrawImageSecuritycheck this 4: %p\n", this);
-    nsCOMPtr<nsIScriptSecurityManager> ssm =
-        do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
-    if (!ssm) {
-        mCanvasElement->SetWriteOnly();
-        return;
-    }
-
-    fprintf (stderr, "DoDrawImageSecuritycheck this 5: %p\n", this);
     nsCOMPtr<nsINode> elem = do_QueryInterface(mCanvasElement);
-    if (elem && ssm) {
-        nsCOMPtr<nsIPrincipal> uriPrincipal;
-        ssm->GetCodebasePrincipal(aURI, getter_AddRefs(uriPrincipal));
-
-        if (uriPrincipal) {
-            nsresult rv = ssm->CheckSameOriginPrincipal(elem->NodePrincipal(),
-                                                        uriPrincipal);
-            if (NS_SUCCEEDED(rv)) {
-                // Same origin
-                return;
-            }
+    if (elem) {
+        rv = elem->NodePrincipal()->CheckMayLoad(aURI);
+        if (NS_SUCCEEDED(rv)) {
+            // Same origin
+            return;
         }
     }
 
-    fprintf (stderr, "DoDrawImageSecuritycheck this 6: %p\n", this); fflush(stderr);
+    fprintf (stderr, "DoDrawImageSecuritycheck this 5: %p\n", this); fflush(stderr);
     mCanvasElement->SetWriteOnly();
 #endif
 }
 
 
 nsCanvasRenderingContextGLPrivate::nsCanvasRenderingContextGLPrivate()
     : mGLPbuffer(nsnull), mWidth(0), mHeight(0), mCanvasElement(nsnull)
 {