diff --git a/mozilla/caps/idl/nsIAggregatePrincipal.idl b/mozilla/caps/idl/nsIAggregatePrincipal.idl index f6f182aff97..c6755b43ee5 100644 --- a/mozilla/caps/idl/nsIAggregatePrincipal.idl +++ b/mozilla/caps/idl/nsIAggregatePrincipal.idl @@ -50,6 +50,7 @@ interface nsIAggregatePrincipal : nsISupports { attribute nsIPrincipal certificate; attribute nsIPrincipal codebase; + readonly attribute nsIPrincipal originalCodebase; readonly attribute nsIPrincipal primaryChild; void intersect(in nsIPrincipal other); diff --git a/mozilla/caps/include/nsAggregatePrincipal.h b/mozilla/caps/include/nsAggregatePrincipal.h index faafc80c78c..6c16648c8aa 100644 --- a/mozilla/caps/include/nsAggregatePrincipal.h +++ b/mozilla/caps/include/nsAggregatePrincipal.h @@ -108,6 +108,7 @@ public: protected: nsCOMPtr mCertificate; nsCOMPtr mCodebase; + nsCOMPtr mOriginalCodebase; }; #endif // _NS_AGGREGATE_PRINCIPAL_H_ diff --git a/mozilla/caps/src/nsAggregatePrincipal.cpp b/mozilla/caps/src/nsAggregatePrincipal.cpp index 696439906f2..d86ac2dcbf4 100644 --- a/mozilla/caps/src/nsAggregatePrincipal.cpp +++ b/mozilla/caps/src/nsAggregatePrincipal.cpp @@ -185,27 +185,41 @@ NS_IMETHODIMP nsAggregatePrincipal::SetCodebase(nsIPrincipal* aCodebase) { nsresult rv; - //-- Make sure this really is a codebase principal - if (aCodebase) + nsCOMPtr newCodebase(aCodebase); + + //-- If newCodebase is an aggregate, get its underlying codebase + nsCOMPtr agg = + do_QueryInterface(newCodebase, &rv); + if (NS_SUCCEEDED(rv)) { + rv = agg->GetCodebase(getter_AddRefs(newCodebase)); + if (NS_FAILED(rv)) return NS_ERROR_FAILURE; + } + else + { //-- Make sure this really is a codebase principal nsCOMPtr tempCodebase = - do_QueryInterface(aCodebase, &rv); + do_QueryInterface(newCodebase, &rv); if (NS_FAILED(rv)) return NS_ERROR_FAILURE; } - //-- If aCodebase is an aggregate, get its underlying codebase - nsCOMPtr agg = - do_QueryInterface(aCodebase, &rv); - if (NS_SUCCEEDED(rv)) - { - nsCOMPtr underlying; - rv = agg->GetCodebase(getter_AddRefs(underlying)); - if (NS_FAILED(rv)) return NS_ERROR_FAILURE; - mCodebase = underlying.get(); - } - else - mCodebase = aCodebase; + mCodebase = newCodebase; + + //-- If this is the first codebase set, remember it + if (!mOriginalCodebase) + mOriginalCodebase = newCodebase; + + return NS_OK; +} + +NS_IMETHODIMP +nsAggregatePrincipal::GetOriginalCodebase(nsIPrincipal** aOriginalCodebase) +{ + NS_ENSURE_ARG_POINTER(aOriginalCodebase); + + *aOriginalCodebase = mOriginalCodebase; + NS_IF_ADDREF(*aOriginalCodebase); + return NS_OK; } diff --git a/mozilla/content/html/document/src/nsHTMLContentSink.cpp b/mozilla/content/html/document/src/nsHTMLContentSink.cpp index 70fb85083c2..5623394aac2 100644 --- a/mozilla/content/html/document/src/nsHTMLContentSink.cpp +++ b/mozilla/content/html/document/src/nsHTMLContentSink.cpp @@ -116,6 +116,8 @@ #include "nsVoidArray.h" #include "nsIScriptSecurityManager.h" #include "nsIPrincipal.h" +#include "nsICodebasePrincipal.h" +#include "nsIAggregatePrincipal.h" #include "nsTextFragment.h" #include "nsIScriptGlobalObject.h" #include "nsIScriptGlobalObjectOwner.h" @@ -4547,11 +4549,31 @@ HTMLContentSink::ProcessHeaderData(nsIAtom* aHeader,const nsAString& aValue,nsIH if (NS_FAILED(rv)) return rv; nsCOMPtr cookieServ = do_GetService(NS_COOKIESERVICE_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; - - nsCOMPtr baseURI; - nsCOMPtr webNav = do_QueryInterface(docShell); - rv = webNav->GetCurrentURI(getter_AddRefs(baseURI)); + + // Get a URI from the document principal + // We use the original codebase in case the codebase was changed by SetDomain + nsCOMPtr docPrincipal; + rv = mDocument->GetPrincipal(getter_AddRefs(docPrincipal)); if (NS_FAILED(rv)) return rv; + if (!docPrincipal) return NS_OK; + + nsCOMPtr agg(do_QueryInterface(docPrincipal, &rv)); + // Document principal should always be an aggregate + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr originalPrincipal; + rv = agg->GetOriginalCodebase(getter_AddRefs(originalPrincipal)); + nsCOMPtr originalCodebase( + do_QueryInterface(originalPrincipal, &rv)); + if (NS_FAILED(rv)) { + // Document's principal is not a codebase (may be system), so can't set cookies + return NS_OK; + } + + nsCOMPtr codebaseURI; + rv = originalCodebase->GetURI(getter_AddRefs(codebaseURI)); + NS_ENSURE_SUCCESS(rv, rv); + char *cookie = ToNewUTF8String(aValue); nsCOMPtr globalObj; nsCOMPtr prompt; @@ -4571,7 +4593,7 @@ HTMLContentSink::ProcessHeaderData(nsIAtom* aHeader,const nsAString& aValue,nsIH } } - rv = cookieServ->SetCookieString(baseURI, prompt, cookie, httpChannel); + rv = cookieServ->SetCookieString(codebaseURI, prompt, cookie, httpChannel); nsCRT::free(cookie); if (NS_FAILED(rv)) return rv; } // END set-cookie diff --git a/mozilla/content/html/document/src/nsHTMLDocument.cpp b/mozilla/content/html/document/src/nsHTMLDocument.cpp index 675353bbc67..844ea88aa11 100644 --- a/mozilla/content/html/document/src/nsHTMLDocument.cpp +++ b/mozilla/content/html/document/src/nsHTMLDocument.cpp @@ -291,7 +291,8 @@ nsHTMLDocument::nsHTMLDocument() mBaseTarget(nsnull), mLastModified(nsnull), mReferrer(nsnull), - mIsWriting(0) + mIsWriting(0), + mDomainWasSet(PR_FALSE) { mImages = nsnull; mApplets = nsnull; @@ -322,7 +323,6 @@ nsHTMLDocument::nsHTMLDocument() //nsCOMPtr gRDF(do_GetService(kRDFServiceCID, //&rv)); } - mDomainWasSet = PR_FALSE; // Bug 13871: Frameset spoofing } nsHTMLDocument::~nsHTMLDocument() @@ -1950,8 +1950,9 @@ nsHTMLDocument::GetDomain(nsAString& aDomain) NS_IMETHODIMP nsHTMLDocument::SetDomain(const nsAString& aDomain) { - // Check new domain - + // Check new domain - must be a superdomain of the current host + // For example, a page from foo.bar.com may set domain to bar.com, + // but not to ar.com, baz.com, or fi.foo.bar.com. nsAutoString current; if (NS_FAILED(GetDomain(current))) return NS_ERROR_FAILURE; @@ -2228,11 +2229,30 @@ nsHTMLDocument::GetCookie(nsAString& aCookie) nsresult result = NS_OK; nsAutoString str; - nsCOMPtr service = do_GetService(kCookieServiceCID, &result); - if (NS_SUCCEEDED(result) && service && mDocumentURL) { + if (NS_SUCCEEDED(result) && service) { + + // Get a URI from the document principal + // We use the original codebase in case the codebase was changed by SetDomain + nsCOMPtr agg(do_QueryInterface(mPrincipal, &result)); + // Document principal should always be an aggregate + NS_ENSURE_SUCCESS(result, result); + + nsCOMPtr originalPrincipal; + result = agg->GetOriginalCodebase(getter_AddRefs(originalPrincipal)); + nsCOMPtr originalCodebase( + do_QueryInterface(originalPrincipal, &result)); + if (NS_FAILED(result)) { + // Document's principal is not a codebase, so can't get cookies + return NS_OK; + } + + nsCOMPtr codebaseURI; + result = originalCodebase->GetURI(getter_AddRefs(codebaseURI)); + NS_ENSURE_SUCCESS(result, result); + nsXPIDLCString cookie; - result = service->GetCookieString(mDocumentURL, getter_Copies(cookie)); + result = service->GetCookieString(codebaseURI, getter_Copies(cookie)); if (NS_SUCCEEDED(result) && cookie) CopyASCIItoUCS2(nsDependentCString(cookie), aCookie); } @@ -2265,10 +2285,30 @@ nsHTMLDocument::SetCookie(const nsAString& aCookie) window->GetPrompter(getter_AddRefs(prompt)); } } + + // Get a URI from the document principal + // We use the original codebase in case the codebase was changed by SetDomain + nsCOMPtr agg(do_QueryInterface(mPrincipal, &result)); + // Document principal should always be an aggregate + NS_ENSURE_SUCCESS(result, result); + + nsCOMPtr originalPrincipal; + result = agg->GetOriginalCodebase(getter_AddRefs(originalPrincipal)); + nsCOMPtr originalCodebase( + do_QueryInterface(originalPrincipal, &result)); + if (NS_FAILED(result)) { + // Document's principal is not a codebase, so can't set cookies + return NS_OK; + } + + nsCOMPtr codebaseURI; + result = originalCodebase->GetURI(getter_AddRefs(codebaseURI)); + NS_ENSURE_SUCCESS(result, result); + result = NS_ERROR_OUT_OF_MEMORY; char* cookie = ToNewCString(aCookie); if (cookie) { - result = service->SetCookieString(mDocumentURL, prompt, cookie, mHttpChannel); + result = service->SetCookieString(codebaseURI, prompt, cookie, mHttpChannel); nsCRT::free(cookie); } } diff --git a/mozilla/content/xml/document/src/nsXMLContentSink.cpp b/mozilla/content/xml/document/src/nsXMLContentSink.cpp index 98e71e26482..29b7d059de0 100644 --- a/mozilla/content/xml/document/src/nsXMLContentSink.cpp +++ b/mozilla/content/xml/document/src/nsXMLContentSink.cpp @@ -104,6 +104,9 @@ #include "nsIDOMWindowInternal.h" #include "nsIChannel.h" #include "nsIHttpChannel.h" +#include "nsIPrincipal.h" +#include "nsIAggregatePrincipal.h" +#include "nsICodebasePrincipal.h" // XXX misnamed header file, but oh well #include "nsHTMLTokens.h" @@ -953,10 +956,30 @@ nsXMLContentSink::ProcessHeaderData(nsIAtom* aHeader,const nsAString& aValue,nsI nsCOMPtr cookieServ = do_GetService(NS_COOKIESERVICE_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; - nsCOMPtr baseURI; - nsCOMPtr webNav = do_QueryInterface(docShell); - rv = webNav->GetCurrentURI(getter_AddRefs(baseURI)); + // Get a URI from the document principal + // We use the original codebase in case the codebase was changed by SetDomain + nsCOMPtr docPrincipal; + rv = mDocument->GetPrincipal(getter_AddRefs(docPrincipal)); if (NS_FAILED(rv)) return rv; + if (!docPrincipal) return NS_OK; + + nsCOMPtr agg(do_QueryInterface(docPrincipal, &rv)); + // Document principal should always be an aggregate + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr originalPrincipal; + rv = agg->GetOriginalCodebase(getter_AddRefs(originalPrincipal)); + nsCOMPtr originalCodebase( + do_QueryInterface(originalPrincipal, &rv)); + if (NS_FAILED(rv)) { + // Document's principal is not a codebase (may be system), so can't set cookies + return NS_OK; + } + + nsCOMPtr codebaseURI; + rv = originalCodebase->GetURI(getter_AddRefs(codebaseURI)); + NS_ENSURE_SUCCESS(rv, rv); + char *cookie = ToNewUTF8String(aValue); nsCOMPtr globalObj; nsCOMPtr prompt; @@ -976,7 +999,7 @@ nsXMLContentSink::ProcessHeaderData(nsIAtom* aHeader,const nsAString& aValue,nsI } } - rv = cookieServ->SetCookieString(baseURI, prompt, cookie, httpChannel); + rv = cookieServ->SetCookieString(codebaseURI, prompt, cookie, httpChannel); nsCRT::free(cookie); if (NS_FAILED(rv)) return rv; } // END set-cookie