commit d8e36b11e0b149a0d44dada9b3978f766e26c40a Author: Mike Perry mikeperry-git@fscked.org Date: Wed Aug 1 14:24:30 2012 -0700
Add patches for #5477 and #5472. --- ...0-Add-a-redirect-API-for-HTTPS-Everywhere.patch | 346 ++++++++ ...solate-the-Image-Cache-per-url-bar-domain.patch | 904 ++++++++++++++++++++ 2 files changed, 1250 insertions(+), 0 deletions(-)
diff --git a/src/current-patches/firefox/alpha/0020-Add-a-redirect-API-for-HTTPS-Everywhere.patch b/src/current-patches/firefox/alpha/0020-Add-a-redirect-API-for-HTTPS-Everywhere.patch new file mode 100644 index 0000000..dd15f05 --- /dev/null +++ b/src/current-patches/firefox/alpha/0020-Add-a-redirect-API-for-HTTPS-Everywhere.patch @@ -0,0 +1,346 @@ +From 046d49340c963f140c618866a4ddd47cc75f576f Mon Sep 17 00:00:00 2001 +From: Mike Perry mikeperry-git@torproject.org +Date: Thu, 26 Jul 2012 15:13:44 -0700 +Subject: [PATCH 20/21] Add a redirect API for HTTPS-Everywhere. + +--- + netwerk/protocol/http/HttpChannelChild.cpp | 15 ++++- + netwerk/protocol/http/HttpChannelChild.h | 4 + + netwerk/protocol/http/HttpChannelParent.cpp | 4 + + netwerk/protocol/http/HttpChannelParent.h | 1 + + netwerk/protocol/http/PHttpChannel.ipdl | 1 + + netwerk/protocol/http/nsHttpChannel.cpp | 67 +++++++++++++++++--- + netwerk/protocol/http/nsHttpChannel.h | 13 +++- + netwerk/protocol/http/nsIHttpChannel.idl | 12 ++++ + .../protocol/viewsource/nsViewSourceChannel.cpp | 13 ++++- + 9 files changed, 118 insertions(+), 12 deletions(-) + +diff --git a/netwerk/protocol/http/HttpChannelChild.cpp b/netwerk/protocol/http/HttpChannelChild.cpp +index 777dfb6..a563438 100644 +--- a/netwerk/protocol/http/HttpChannelChild.cpp ++++ b/netwerk/protocol/http/HttpChannelChild.cpp +@@ -1070,7 +1070,8 @@ HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext) + gNeckoChild->SendPHttpChannelConstructor(this, tabChild); + + SendAsyncOpen(IPC::URI(mURI), IPC::URI(mOriginalURI), +- IPC::URI(mDocumentURI), IPC::URI(mReferrer), mLoadFlags, ++ IPC::URI(mDocumentURI), IPC::URI(mReferrer), ++ IPC::URI(mInternalRedirectURI), mLoadFlags, + mClientSetRequestHeaders, mRequestHead.Method(), + IPC::InputStream(mUploadStream), mUploadStreamHasHeaders, + mPriority, mRedirectionLimit, mAllowPipelining, +@@ -1114,6 +1115,18 @@ HttpChannelChild::SetupFallbackChannel(const char *aFallbackKey) + DROP_DEAD(); + } + ++NS_IMETHODIMP ++HttpChannelChild::RedirectTo(nsIURI *uri) ++{ ++ // We can only redirect unopened channels ++ NS_ENSURE_TRUE(!mIPCOpen, NS_ERROR_ALREADY_OPENED); ++ ++ // The redirect is stored internally for use in AsyncOpen ++ mInternalRedirectURI = uri; ++ ++ return NS_OK; ++} ++ + // The next four _should_ be implemented, but we need to figure out how + // to transfer the data from the chrome process first. + +diff --git a/netwerk/protocol/http/HttpChannelChild.h b/netwerk/protocol/http/HttpChannelChild.h +index 43617ef..f595c4d 100644 +--- a/netwerk/protocol/http/HttpChannelChild.h ++++ b/netwerk/protocol/http/HttpChannelChild.h +@@ -110,6 +110,9 @@ public: + NS_IMETHOD GetLocalPort(PRInt32* port); + NS_IMETHOD GetRemoteAddress(nsACString& addr); + NS_IMETHOD GetRemotePort(PRInt32* port); ++ ++ NS_IMETHOD RedirectTo(nsIURI *uri); ++ + // nsISupportsPriority + NS_IMETHOD SetPriority(PRInt32 value); + // nsIResumableChannel +@@ -160,6 +163,7 @@ private: + RequestHeaderTuples mClientSetRequestHeaders; + nsCOMPtr<nsIChildChannel> mRedirectChannelChild; + nsCOMPtr<nsISupports> mSecurityInfo; ++ nsCOMPtr<nsIURI> mInternalRedirectURI; + + bool mIsFromCache; + bool mCacheEntryAvailable; +diff --git a/netwerk/protocol/http/HttpChannelParent.cpp b/netwerk/protocol/http/HttpChannelParent.cpp +index 464cbe7..3ce94b8 100644 +--- a/netwerk/protocol/http/HttpChannelParent.cpp ++++ b/netwerk/protocol/http/HttpChannelParent.cpp +@@ -132,6 +132,7 @@ HttpChannelParent::RecvAsyncOpen(const IPC::URI& aURI, + const IPC::URI& aOriginalURI, + const IPC::URI& aDocURI, + const IPC::URI& aReferrerURI, ++ const IPC::URI& aInternalRedirectURI, + const PRUint32& loadFlags, + const RequestHeaderTuples& requestHeaders, + const nsHttpAtom& requestMethod, +@@ -152,6 +153,7 @@ HttpChannelParent::RecvAsyncOpen(const IPC::URI& aURI, + nsCOMPtr<nsIURI> originalUri(aOriginalURI); + nsCOMPtr<nsIURI> docUri(aDocURI); + nsCOMPtr<nsIURI> referrerUri(aReferrerURI); ++ nsCOMPtr<nsIURI> internalRedirectUri(aInternalRedirectURI); + + nsCString uriSpec; + uri->GetSpec(uriSpec); +@@ -179,6 +181,8 @@ HttpChannelParent::RecvAsyncOpen(const IPC::URI& aURI, + httpChan->SetDocumentURI(docUri); + if (referrerUri) + httpChan->SetReferrerInternal(referrerUri); ++ if (internalRedirectUri) ++ httpChan->SetInternalRedirectURI(internalRedirectUri); + if (loadFlags != nsIRequest::LOAD_NORMAL) + httpChan->SetLoadFlags(loadFlags); + +diff --git a/netwerk/protocol/http/HttpChannelParent.h b/netwerk/protocol/http/HttpChannelParent.h +index 6cfc3a6..a4b410a 100644 +--- a/netwerk/protocol/http/HttpChannelParent.h ++++ b/netwerk/protocol/http/HttpChannelParent.h +@@ -82,6 +82,7 @@ protected: + const IPC::URI& originalUri, + const IPC::URI& docUri, + const IPC::URI& referrerUri, ++ const IPC::URI& internalRedirectUri, + const PRUint32& loadFlags, + const RequestHeaderTuples& requestHeaders, + const nsHttpAtom& requestMethod, +diff --git a/netwerk/protocol/http/PHttpChannel.ipdl b/netwerk/protocol/http/PHttpChannel.ipdl +index 252a6ee..23a912e 100644 +--- a/netwerk/protocol/http/PHttpChannel.ipdl ++++ b/netwerk/protocol/http/PHttpChannel.ipdl +@@ -69,6 +69,7 @@ parent: + URI original, + URI doc, + URI referrer, ++ URI internalRedirect, + PRUint32 loadFlags, + RequestHeaderTuples requestHeaders, + nsHttpAtom requestMethod, +diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp +index 23edc3c..c55fe4d 100644 +--- a/netwerk/protocol/http/nsHttpChannel.cpp ++++ b/netwerk/protocol/http/nsHttpChannel.cpp +@@ -1403,18 +1403,17 @@ nsHttpChannel::HandleAsyncRedirectChannelToHttps() + return; + } + +- nsresult rv = AsyncRedirectChannelToHttps(); ++ nsresult rv = InternalRedirectChannelToHttps(); + if (NS_FAILED(rv)) +- ContinueAsyncRedirectChannelToHttps(rv); ++ ContinueInternalRedirectChannelToURI(rv); + } + + nsresult +-nsHttpChannel::AsyncRedirectChannelToHttps() ++nsHttpChannel::InternalRedirectChannelToHttps() + { + nsresult rv = NS_OK; + LOG(("nsHttpChannel::HandleAsyncRedirectChannelToHttps() [STS]\n")); + +- nsCOMPtr<nsIChannel> newChannel; + nsCOMPtr<nsIURI> upgradedURI; + + rv = mURI->Clone(getter_AddRefs(upgradedURI)); +@@ -1436,6 +1435,48 @@ nsHttpChannel::AsyncRedirectChannelToHttps() + else + upgradedURI->SetPort(oldPort); + ++ return InternalRedirectChannelToURI(upgradedURI); ++} ++ ++NS_IMETHODIMP ++nsHttpChannel::RedirectTo(nsIURI *newURI) ++{ ++ // We can only redirect unopened channels ++ NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED); ++ ++ // The redirect is stored internally for use in AsyncOpen ++ mInternalRedirectURI = newURI; ++ ++ return NS_OK; ++} ++ ++void ++nsHttpChannel::HandleAsyncInternalRedirect() ++{ ++ NS_PRECONDITION(!mCallOnResume, "How did that happen?"); ++ NS_PRECONDITION(mInternalRedirectURI, "How did that happen?"); ++ ++ if (mSuspendCount) { ++ LOG(("Waiting until resume to do async API redirect [this=%p]\n", this)); ++ mCallOnResume = &nsHttpChannel::HandleAsyncInternalRedirect; ++ return; ++ } ++ ++ nsresult rv = InternalRedirectChannelToURI(mInternalRedirectURI); ++ if (NS_FAILED(rv)) ++ ContinueInternalRedirectChannelToURI(rv); ++ ++ return; ++} ++ ++nsresult ++nsHttpChannel::InternalRedirectChannelToURI(nsIURI *upgradedURI) ++{ ++ nsresult rv = NS_OK; ++ LOG(("nsHttpChannel::InternalRedirectChannelToURI()\n")); ++ ++ nsCOMPtr<nsIChannel> newChannel; ++ + nsCOMPtr<nsIIOService> ioService; + rv = gHttpHandler->GetIOService(getter_AddRefs(ioService)); + NS_ENSURE_SUCCESS(rv, rv); +@@ -1451,7 +1492,7 @@ nsHttpChannel::AsyncRedirectChannelToHttps() + PRUint32 flags = nsIChannelEventSink::REDIRECT_PERMANENT; + + PushRedirectAsyncFunc( +- &nsHttpChannel::ContinueAsyncRedirectChannelToHttps); ++ &nsHttpChannel::ContinueInternalRedirectChannelToURI); + rv = gHttpHandler->AsyncOnChannelRedirect(this, newChannel, flags); + + if (NS_SUCCEEDED(rv)) +@@ -1460,14 +1501,18 @@ nsHttpChannel::AsyncRedirectChannelToHttps() + if (NS_FAILED(rv)) { + AutoRedirectVetoNotifier notifier(this); + PopRedirectAsyncFunc( +- &nsHttpChannel::ContinueAsyncRedirectChannelToHttps); ++ &nsHttpChannel::ContinueInternalRedirectChannelToURI); ++ ++ // If we've failed so far, cancel the current channel, too, ++ // as both HSTS and the redirectTo codepaths prefer ++ // request failure to insecurity. ++ Cancel(rv); + } + + return rv; + } +- + nsresult +-nsHttpChannel::ContinueAsyncRedirectChannelToHttps(nsresult rv) ++nsHttpChannel::ContinueInternalRedirectChannelToURI(nsresult rv) + { + AutoRedirectVetoNotifier notifier(this); + +@@ -3929,6 +3974,12 @@ nsHttpChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *context) + if (mLoadGroup) + mLoadGroup->AddRequest(this, nsnull); + ++ // Check to see if we should redirect this channel elsewhere by ++ // nsIHttpChannel.redirectTo API request ++ if (mInternalRedirectURI) { ++ return AsyncCall(&nsHttpChannel::HandleAsyncInternalRedirect); ++ } ++ + // Collect mAsyncOpenTime after we have called all obsrevers like + // "http-on-modify-request" and load group observers that may set + // mTimingEnabled flag. +diff --git a/netwerk/protocol/http/nsHttpChannel.h b/netwerk/protocol/http/nsHttpChannel.h +index 5a61e21..d156c28 100644 +--- a/netwerk/protocol/http/nsHttpChannel.h ++++ b/netwerk/protocol/http/nsHttpChannel.h +@@ -138,6 +138,8 @@ public: + // nsIChannel + NS_IMETHOD GetSecurityInfo(nsISupports **aSecurityInfo); + NS_IMETHOD AsyncOpen(nsIStreamListener *listener, nsISupports *aContext); ++ // nsIHttpChannel ++ NS_IMETHOD RedirectTo(nsIURI *newURI); + // nsIHttpChannelInternal + NS_IMETHOD SetupFallbackChannel(const char *aFallbackKey); + // nsISupportsPriority +@@ -152,6 +154,9 @@ public: /* internal necko use only */ + void SetUploadStreamHasHeaders(bool hasHeaders) + { mUploadStreamHasHeaders = hasHeaders; } + ++ void SetInternalRedirectURI(nsIURI *redirectTo) ++ { mInternalRedirectURI = redirectTo; } ++ + nsresult SetReferrerInternal(nsIURI *referrer) { + nsCAutoString spec; + nsresult rv = referrer->GetAsciiSpec(spec); +@@ -190,11 +195,14 @@ private: + + // redirection specific methods + void HandleAsyncRedirect(); ++ void HandleAsyncInternalRedirect(); + nsresult ContinueHandleAsyncRedirect(nsresult); + void HandleAsyncNotModified(); + void HandleAsyncFallback(); + nsresult ContinueHandleAsyncFallback(nsresult); + nsresult PromptTempRedirect(); ++ nsresult InternalRedirectChannelToURI(nsIURI *); ++ + virtual nsresult SetupReplacementChannel(nsIURI *, nsIChannel *, + bool preserveMethod, + bool forProxy); +@@ -256,8 +264,8 @@ private: + bool MustValidateBasedOnQueryUrl(); + + void HandleAsyncRedirectChannelToHttps(); +- nsresult AsyncRedirectChannelToHttps(); +- nsresult ContinueAsyncRedirectChannelToHttps(nsresult rv); ++ nsresult InternalRedirectChannelToHttps(); ++ nsresult ContinueInternalRedirectChannelToURI(nsresult rv); + + /** + * A function that takes care of reading STS headers and enforcing STS +@@ -327,6 +335,7 @@ private: + friend class AutoRedirectVetoNotifier; + friend class HttpAsyncAborter<nsHttpChannel>; + nsCOMPtr<nsIURI> mRedirectURI; ++ nsCOMPtr<nsIURI> mInternalRedirectURI; + nsCOMPtr<nsIChannel> mRedirectChannel; + PRUint32 mRedirectType; + +diff --git a/netwerk/protocol/http/nsIHttpChannel.idl b/netwerk/protocol/http/nsIHttpChannel.idl +index 2d3f01a..39b2ee5 100644 +--- a/netwerk/protocol/http/nsIHttpChannel.idl ++++ b/netwerk/protocol/http/nsIHttpChannel.idl +@@ -291,4 +291,16 @@ interface nsIHttpChannel : nsIChannel + * has been received (before onStartRequest). + */ + boolean isNoCacheResponse(); ++ ++ /** ++ * Instructs the channel to immediately redirect to a new destination. ++ * Can only be called on channels not yet opened. ++ * ++ * This method provides no explicit conflict resolution. The last ++ * caller to call it wins. ++ * ++ * @throws NS_ERROR_ALREADY_OPENED if called after the channel ++ * has been opened. ++ */ ++ void redirectTo(in nsIURI aNewURI); + }; +diff --git a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp +index 919c3f7..e286b8f 100644 +--- a/netwerk/protocol/viewsource/nsViewSourceChannel.cpp ++++ b/netwerk/protocol/viewsource/nsViewSourceChannel.cpp +@@ -703,4 +703,15 @@ nsViewSourceChannel::IsNoCacheResponse(bool *_retval) + { + return !mHttpChannel ? NS_ERROR_NULL_POINTER : + mHttpChannel->IsNoCacheResponse(_retval); +-} ++} ++ ++// XXX: Is this the right thing to do here? Or should we have ++// made an nsIHTTPChannelRedirect that only nsHttpChannel implements? ++// Also, will this mean that some ViewSource requests may be non-https? ++// Or will the mHttpChannel take care of that for us? ++NS_IMETHODIMP ++nsViewSourceChannel::RedirectTo(nsIURI *uri) ++{ ++ return NS_ERROR_NOT_IMPLEMENTED; ++} ++ +-- +1.7.5.4 + diff --git a/src/current-patches/firefox/alpha/0021-Isolate-the-Image-Cache-per-url-bar-domain.patch b/src/current-patches/firefox/alpha/0021-Isolate-the-Image-Cache-per-url-bar-domain.patch new file mode 100644 index 0000000..2478af8 --- /dev/null +++ b/src/current-patches/firefox/alpha/0021-Isolate-the-Image-Cache-per-url-bar-domain.patch @@ -0,0 +1,904 @@ +From 0b3b4970954c9dd7d85929491b887e45abe9c194 Mon Sep 17 00:00:00 2001 +From: Mike Perry mikeperry-git@torproject.org +Date: Mon, 30 Jul 2012 18:37:36 -0700 +Subject: [PATCH 21/21] Isolate the Image Cache per url bar domain. + +Also adds a new API to mozIThirdPartyUtil to allow you to get the url bar URI +for a channel or nsIDocument. +--- + content/base/src/ThirdPartyUtil.cpp | 52 +++++ + content/base/src/ThirdPartyUtil.h | 2 + + content/base/src/nsContentUtils.cpp | 13 +- + embedding/browser/webBrowser/nsContextMenuInfo.cpp | 29 ++- + extensions/cookie/nsCookiePermission.cpp | 3 + + image/public/imgILoader.idl | 4 +- + image/src/imgLoader.cpp | 202 ++++++++++++-------- + image/src/imgLoader.h | 13 +- + image/src/imgRequest.cpp | 9 +- + image/src/imgRequest.h | 3 + + layout/generic/nsImageFrame.cpp | 11 +- + netwerk/base/public/mozIThirdPartyUtil.idl | 21 ++ + netwerk/cookie/nsICookiePermission.idl | 1 + + toolkit/system/gnome/nsAlertsIconListener.cpp | 3 +- + widget/cocoa/nsMenuItemIconX.mm | 8 +- + 15 files changed, 272 insertions(+), 102 deletions(-) + +diff --git a/content/base/src/ThirdPartyUtil.cpp b/content/base/src/ThirdPartyUtil.cpp +index 6a415e9..abf2eed 100644 +--- a/content/base/src/ThirdPartyUtil.cpp ++++ b/content/base/src/ThirdPartyUtil.cpp +@@ -39,7 +39,10 @@ + #include "nsNetUtil.h" + #include "nsIServiceManager.h" + #include "nsIHttpChannelInternal.h" ++#include "nsICookiePermission.h" + #include "nsIDOMWindow.h" ++#include "nsIDOMDocument.h" ++#include "nsIDocument.h" + #include "nsILoadContext.h" + #include "nsIPrincipal.h" + #include "nsIScriptObjectPrincipal.h" +@@ -54,6 +57,7 @@ ThirdPartyUtil::Init() + + nsresult rv; + mTLDService = do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID, &rv); ++ mCookiePermissions = do_GetService(NS_COOKIEPERMISSION_CONTRACTID); + return rv; + } + +@@ -315,3 +319,51 @@ ThirdPartyUtil::GetBaseDomain(nsIURI* aHostURI, + + return NS_OK; + } ++ ++NS_IMETHODIMP ++ThirdPartyUtil::GetFirstPartyURI(nsIChannel *aChannel, ++ nsIDocument *aDoc, ++ nsIURI **aOutput) ++{ ++ nsresult rv = NS_ERROR_NULL_POINTER; ++ ++ if (!aChannel && aDoc) { ++ aChannel = aDoc->GetChannel(); ++ } ++ ++ // If aChannel is specified or available, use the official route ++ // for sure ++ if (aChannel) { ++ rv = mCookiePermissions->GetOriginatingURI(aChannel, aOutput); ++ } ++ ++ // If the channel was missing, closed or broken, try the ++ // window hierarchy directly. ++ // ++ // This might fail to work for first-party loads themselves, but ++ // we don't need this codepath for that case. ++ if (NS_FAILED(rv) && aDoc) { ++ nsCOMPtr<nsIDOMWindow> top; ++ nsCOMPtr<nsIDOMDocument> topDDoc; ++ ++ aDoc->GetWindow()->GetTop(getter_AddRefs(top)); ++ top->GetDocument(getter_AddRefs(topDDoc)); ++ ++ nsCOMPtr<nsIDocument> topDoc(do_QueryInterface(topDDoc)); ++ *aOutput = topDoc->GetOriginalURI(); ++ ++ if (*aOutput) ++ rv = NS_OK; ++ } ++ ++ // TODO: We could provide a route through the loadgroup + notification ++ // callbacks too, but either channel or document was always available ++ // in the cases where this function was originally needed (the image cache). ++ // The notification callbacks also appear to suffers from the same limitation ++ // as the document path. See nsICookiePermissions.GetOriginatingURI() for ++ // details. ++ ++ return rv; ++} ++ ++ +diff --git a/content/base/src/ThirdPartyUtil.h b/content/base/src/ThirdPartyUtil.h +index 58ddb15..ba70162 100644 +--- a/content/base/src/ThirdPartyUtil.h ++++ b/content/base/src/ThirdPartyUtil.h +@@ -46,6 +46,7 @@ + class nsIURI; + class nsIChannel; + class nsIDOMWindow; ++class nsICookiePermission; + + class ThirdPartyUtil : public mozIThirdPartyUtil + { +@@ -61,6 +62,7 @@ private: + static already_AddRefed<nsIURI> GetURIFromWindow(nsIDOMWindow* aWin); + + nsCOMPtr<nsIEffectiveTLDService> mTLDService; ++ nsCOMPtr<nsICookiePermission> mCookiePermissions; + }; + + #endif +diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp +index 5c85697..4368609 100644 +--- a/content/base/src/nsContentUtils.cpp ++++ b/content/base/src/nsContentUtils.cpp +@@ -179,6 +179,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID); + #include "nsIDOMHTMLInputElement.h" + #include "nsParserConstants.h" + #include "nsIWebNavigation.h" ++#include "mozIThirdPartyUtil.h" + + #ifdef IBMBIDI + #include "nsIBidiKeyboard.h" +@@ -2629,8 +2630,6 @@ nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument, + nsCOMPtr<nsILoadGroup> loadGroup = aLoadingDocument->GetDocumentLoadGroup(); + NS_ASSERTION(loadGroup, "Could not get loadgroup; onload may fire too early"); + +- nsIURI *documentURI = aLoadingDocument->GetDocumentURI(); +- + // check for a Content Security Policy to pass down to the channel that + // will get created to load the image + nsCOMPtr<nsIChannelPolicy> channelPolicy; +@@ -2647,11 +2646,15 @@ nsContentUtils::LoadImage(nsIURI* aURI, nsIDocument* aLoadingDocument, + + // Make the URI immutable so people won't change it under us + NS_TryToSetImmutable(aURI); ++ ++ nsCOMPtr<nsIURI> firstPartyURI; ++ nsCOMPtr<mozIThirdPartyUtil> thirdPartySvc ++ = do_GetService(THIRDPARTYUTIL_CONTRACTID); ++ thirdPartySvc->GetFirstPartyURI(nsnull, aLoadingDocument, ++ getter_AddRefs(firstPartyURI)); + +- // XXXbz using "documentURI" for the initialDocumentURI is not quite +- // right, but the best we can do here... + return imgLoader->LoadImage(aURI, /* uri to load */ +- documentURI, /* initialDocumentURI */ ++ firstPartyURI, /* firstPartyURI */ + aReferrer, /* referrer */ + aLoadingPrincipal, /* loading principal */ + loadGroup, /* loadgroup */ +diff --git a/embedding/browser/webBrowser/nsContextMenuInfo.cpp b/embedding/browser/webBrowser/nsContextMenuInfo.cpp +index 045482a..78f5fc4 100644 +--- a/embedding/browser/webBrowser/nsContextMenuInfo.cpp ++++ b/embedding/browser/webBrowser/nsContextMenuInfo.cpp +@@ -62,6 +62,7 @@ + #include "nsIChannelPolicy.h" + #include "nsIContentSecurityPolicy.h" + #include "nsIContentPolicy.h" ++#include "mozIThirdPartyUtil.h" + + //***************************************************************************** + // class nsContextMenuInfo +@@ -305,15 +306,15 @@ nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode *aDOMNode, imgIR + nsCOMPtr<nsIPrincipal> principal; + nsCOMPtr<nsIChannelPolicy> channelPolicy; + nsCOMPtr<nsIContentSecurityPolicy> csp; +- if (doc) { +- principal = doc->NodePrincipal(); +- nsresult rv = principal->GetCsp(getter_AddRefs(csp)); +- NS_ENSURE_SUCCESS(rv, rv); +- if (csp) { +- channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1"); +- channelPolicy->SetContentSecurityPolicy(csp); +- channelPolicy->SetLoadType(nsIContentPolicy::TYPE_IMAGE); +- } ++ NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE); ++ ++ principal = doc->NodePrincipal(); ++ nsresult rv = principal->GetCsp(getter_AddRefs(csp)); ++ NS_ENSURE_SUCCESS(rv, rv); ++ if (csp) { ++ channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1"); ++ channelPolicy->SetContentSecurityPolicy(csp); ++ channelPolicy->SetLoadType(nsIContentPolicy::TYPE_IMAGE); + } + + while (true) { +@@ -340,8 +341,14 @@ nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode *aDOMNode, imgIR + nsCOMPtr<imgILoader> il(do_GetService( + "@mozilla.org/image/loader;1")); + NS_ENSURE_TRUE(il, NS_ERROR_FAILURE); +- +- return il->LoadImage(bgUri, nsnull, nsnull, principal, nsnull, ++ ++ nsCOMPtr<nsIURI> firstPartyURI; ++ nsCOMPtr<mozIThirdPartyUtil> thirdPartySvc ++ = do_GetService(THIRDPARTYUTIL_CONTRACTID); ++ thirdPartySvc->GetFirstPartyURI(nsnull, doc, ++ getter_AddRefs(firstPartyURI)); ++ ++ return il->LoadImage(bgUri, firstPartyURI, nsnull, principal, nsnull, + nsnull, nsnull, nsIRequest::LOAD_NORMAL, nsnull, + nsnull, channelPolicy, aRequest); + } +diff --git a/extensions/cookie/nsCookiePermission.cpp b/extensions/cookie/nsCookiePermission.cpp +index 577ee7e..c15ddc9 100644 +--- a/extensions/cookie/nsCookiePermission.cpp ++++ b/extensions/cookie/nsCookiePermission.cpp +@@ -445,6 +445,9 @@ nsCookiePermission::GetOriginatingURI(nsIChannel *aChannel, + + return NS_OK; + } ++ ++ // TODO: Why don't we just use this here: ++ // httpChannelInternal->GetDocumentURI(aURI); + } + + // find the associated window and its top window +diff --git a/image/public/imgILoader.idl b/image/public/imgILoader.idl +index 611b939..db9320b 100644 +--- a/image/public/imgILoader.idl ++++ b/image/public/imgILoader.idl +@@ -71,7 +71,7 @@ interface imgILoader : nsISupports + /** + * Start the load and decode of an image. + * @param aURI the URI to load +- * @param aInitialDocumentURI the URI that 'initiated' the load -- used for 3rd party cookie blocking ++ * @param aFirstPartyURI the urlbar URI that 'initiated' the load -- used for 3rd party blocking + * @param aReferrerURI the 'referring' URI + * @param aLoadingPrincipal the principal of the loading document + * @param aLoadGroup Loadgroup to put the image load into +@@ -90,7 +90,7 @@ interface imgILoader : nsISupports + * goes away. + */ + imgIRequest loadImage(in nsIURI aURI, +- in nsIURI aInitialDocumentURL, ++ in nsIURI aFirstPartyURI, + in nsIURI aReferrerURI, + in nsIPrincipal aLoadingPrincipal, + in nsILoadGroup aLoadGroup, +diff --git a/image/src/imgLoader.cpp b/image/src/imgLoader.cpp +index 36c8e6a..8ed12dc 100644 +--- a/image/src/imgLoader.cpp ++++ b/image/src/imgLoader.cpp +@@ -92,6 +92,7 @@ + #include "nsIHttpChannelInternal.h" + #include "nsIContentSecurityPolicy.h" + #include "nsIChannelPolicy.h" ++#include "mozIThirdPartyUtil.h" + + #include "nsContentUtils.h" + +@@ -504,7 +505,7 @@ static nsresult NewImageChannel(nsIChannel **aResult, + // aLoadingPrincipal and false otherwise. + bool *aForcePrincipalCheckForCacheEntry, + nsIURI *aURI, +- nsIURI *aInitialDocumentURI, ++ nsIURI *aFirstPartyURI, + nsIURI *aReferringURI, + nsILoadGroup *aLoadGroup, + const nsCString& aAcceptHeader, +@@ -556,7 +557,7 @@ static nsresult NewImageChannel(nsIChannel **aResult, + + nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal = do_QueryInterface(newHttpChannel); + NS_ENSURE_TRUE(httpChannelInternal, NS_ERROR_UNEXPECTED); +- httpChannelInternal->SetDocumentURI(aInitialDocumentURI); ++ httpChannelInternal->SetDocumentURI(aFirstPartyURI); + newHttpChannel->SetReferrer(aReferringURI); + } + +@@ -999,34 +1000,61 @@ NS_IMETHODIMP imgLoader::ClearCache(bool chrome) + /* void removeEntry(in nsIURI uri); */ + NS_IMETHODIMP imgLoader::RemoveEntry(nsIURI *uri) + { +- if (RemoveFromCache(uri)) ++ if (RemoveMatchingUrlsFromCache(uri)) + return NS_OK; + + return NS_ERROR_NOT_AVAILABLE; + } + ++static PLDHashOperator EnumAllEntries(const nsACString&, ++ nsRefPtr<imgCacheEntry> &aData, ++ void *data) ++{ ++ nsTArray<nsRefPtr<imgCacheEntry> > *entries = ++ reinterpret_cast<nsTArray<nsRefPtr<imgCacheEntry> > *>(data); ++ ++ entries->AppendElement(aData); ++ ++ return PL_DHASH_NEXT; ++} ++ + /* imgIRequest findEntry(in nsIURI uri); */ + NS_IMETHODIMP imgLoader::FindEntryProperties(nsIURI *uri, nsIProperties **_retval) + { + nsRefPtr<imgCacheEntry> entry; +- nsCAutoString spec; + imgCacheTable &cache = GetCache(uri); +- +- uri->GetSpec(spec); + *_retval = nsnull; + +- if (cache.Get(spec, getter_AddRefs(entry)) && entry) { +- if (gCacheTracker && entry->HasNoProxies()) +- gCacheTracker->MarkUsed(entry); ++ // We must traverse the whole cache in O(N) looking for the first ++ // matching URI. ++ // ++ // TODO: For now, it's ok to pick at random here. The images should be ++ // identical unless there is a cache-tracking attack. And even if they ++ // are not identical due to attack, this code is only used for save ++ // dialogs at this point, so no differentiating info is leaked to ++ // content. ++ nsTArray<nsRefPtr<imgCacheEntry> > entries; ++ cache.Enumerate(EnumAllEntries, &entries); ++ ++ for (PRUint32 i = 0; i < entries.Length(); ++i) { ++ bool isEqual = false; + +- nsRefPtr<imgRequest> request = getter_AddRefs(entry->GetRequest()); ++ nsRefPtr<imgRequest> request = getter_AddRefs(entries[i]->GetRequest()); + if (request) { +- *_retval = request->Properties(); +- NS_ADDREF(*_retval); ++ request->mURI->Equals(uri, &isEqual); ++ if (isEqual) { ++ if (gCacheTracker && entries[i]->HasNoProxies()) ++ gCacheTracker->MarkUsed(entries[i]); ++ ++ *_retval = request->Properties(); ++ } + } + } + +- return NS_OK; ++ if (*_retval) ++ return NS_OK; ++ ++ return NS_ERROR_NOT_AVAILABLE; + } + + void imgLoader::Shutdown() +@@ -1054,20 +1082,18 @@ void imgLoader::MinimizeCaches() + EvictEntries(sChromeCacheQueue); + } + +-bool imgLoader::PutIntoCache(nsIURI *key, imgCacheEntry *entry) ++bool imgLoader::PutIntoCache(nsCAutoString key, ++ imgCacheEntry *entry) + { +- imgCacheTable &cache = GetCache(key); +- +- nsCAutoString spec; +- key->GetSpec(spec); +- +- LOG_STATIC_FUNC_WITH_PARAM(gImgLog, "imgLoader::PutIntoCache", "uri", spec.get()); ++ LOG_STATIC_FUNC_WITH_PARAM(gImgLog, "imgLoader::PutIntoCache", "uri", key.get()); ++ imgCacheTable &cache = GetCache(entry->mRequest->mURI); ++ imgCacheQueue &queue = GetCacheQueue(entry->mRequest->mURI); + + // Check to see if this request already exists in the cache and is being + // loaded on a different thread. If so, don't allow this entry to be added to + // the cache. + nsRefPtr<imgCacheEntry> tmpCacheEntry; +- if (cache.Get(spec, getter_AddRefs(tmpCacheEntry)) && tmpCacheEntry) { ++ if (cache.Get(key, getter_AddRefs(tmpCacheEntry)) && tmpCacheEntry) { + PR_LOG(gImgLog, PR_LOG_DEBUG, + ("[this=%p] imgLoader::PutIntoCache -- Element already in the cache", nsnull)); + nsRefPtr<imgRequest> tmpRequest = getter_AddRefs(tmpCacheEntry->GetRequest()); +@@ -1077,13 +1103,13 @@ bool imgLoader::PutIntoCache(nsIURI *key, imgCacheEntry *entry) + PR_LOG(gImgLog, PR_LOG_DEBUG, + ("[this=%p] imgLoader::PutIntoCache -- Replacing cached element", nsnull)); + +- RemoveFromCache(key); ++ RemoveKeyFromCache(cache, queue, key); + } else { + PR_LOG(gImgLog, PR_LOG_DEBUG, + ("[this=%p] imgLoader::PutIntoCache -- Element NOT already in the cache", nsnull)); + } + +- if (!cache.Put(spec, entry)) ++ if (!cache.Put(key, entry)) + return false; + + // We can be called to resurrect an evicted entry. +@@ -1099,7 +1125,6 @@ bool imgLoader::PutIntoCache(nsIURI *key, imgCacheEntry *entry) + addrv = gCacheTracker->AddObject(entry); + + if (NS_SUCCEEDED(addrv)) { +- imgCacheQueue &queue = GetCacheQueue(key); + queue.Push(entry); + } + } +@@ -1205,7 +1230,7 @@ void imgLoader::CheckCacheLimits(imgCacheTable &cache, imgCacheQueue &queue) + + bool imgLoader::ValidateRequestWithNewChannel(imgRequest *request, + nsIURI *aURI, +- nsIURI *aInitialDocumentURI, ++ nsIURI *aFirstPartyURI, + nsIURI *aReferrerURI, + nsILoadGroup *aLoadGroup, + imgIDecoderObserver *aObserver, +@@ -1257,7 +1282,7 @@ bool imgLoader::ValidateRequestWithNewChannel(imgRequest *request, + rv = NewImageChannel(getter_AddRefs(newChannel), + &forcePrincipalCheck, + aURI, +- aInitialDocumentURI, ++ aFirstPartyURI, + aReferrerURI, + aLoadGroup, + mAcceptHeader, +@@ -1326,7 +1351,7 @@ bool imgLoader::ValidateRequestWithNewChannel(imgRequest *request, + + bool imgLoader::ValidateEntry(imgCacheEntry *aEntry, + nsIURI *aURI, +- nsIURI *aInitialDocumentURI, ++ nsIURI *aFirstPartyURI, + nsIURI *aReferrerURI, + nsILoadGroup *aLoadGroup, + imgIDecoderObserver *aObserver, +@@ -1432,7 +1457,7 @@ bool imgLoader::ValidateEntry(imgCacheEntry *aEntry, + if (validateRequest && aCanMakeNewChannel) { + LOG_SCOPE(gImgLog, "imgLoader::ValidateRequest |cache hit| must validate"); + +- return ValidateRequestWithNewChannel(request, aURI, aInitialDocumentURI, ++ return ValidateRequestWithNewChannel(request, aURI, aFirstPartyURI, + aReferrerURI, aLoadGroup, aObserver, + aCX, aLoadFlags, aExistingRequest, + aProxyRequest, aPolicy, +@@ -1442,16 +1467,32 @@ bool imgLoader::ValidateEntry(imgCacheEntry *aEntry, + return !validateRequest; + } + +- +-bool imgLoader::RemoveFromCache(nsIURI *aKey) ++bool imgLoader::RemoveMatchingUrlsFromCache(nsIURI *aKey) + { +- if (!aKey) return false; +- ++ bool rv = true; + imgCacheTable &cache = GetCache(aKey); +- imgCacheQueue &queue = GetCacheQueue(aKey); + +- nsCAutoString spec; +- aKey->GetSpec(spec); ++ // We have to make a temporary, since RemoveFromCache removes the element ++ // from the queue, invalidating iterators. ++ nsTArray<nsRefPtr<imgCacheEntry> > entries; ++ cache.Enumerate(EnumAllEntries, &entries); ++ ++ for (PRUint32 i = 0; i < entries.Length(); ++i) { ++ bool isEqual = false; ++ ++ entries[i]->mRequest->mURI->Equals(aKey, &isEqual); ++ if (isEqual && !RemoveFromCache(entries[i])) ++ rv = false; ++ } ++ ++ return rv; ++} ++ ++bool imgLoader::RemoveKeyFromCache(imgCacheTable &cache, ++ imgCacheQueue &queue, ++ nsCAutoString spec) ++{ ++ if (spec.IsEmpty()) return false; + + LOG_STATIC_FUNC_WITH_PARAM(gImgLog, "imgLoader::RemoveFromCache", "uri", spec.get()); + +@@ -1485,12 +1526,13 @@ bool imgLoader::RemoveFromCache(imgCacheEntry *entry) + + nsRefPtr<imgRequest> request(getter_AddRefs(entry->GetRequest())); + if (request) { +- nsCOMPtr<nsIURI> key; +- if (NS_SUCCEEDED(request->GetURI(getter_AddRefs(key))) && key) { +- imgCacheTable &cache = GetCache(key); +- imgCacheQueue &queue = GetCacheQueue(key); +- nsCAutoString spec; +- key->GetSpec(spec); ++ nsCOMPtr<nsIURI> imgURI = request->mURI; ++ nsCOMPtr<nsIURI> firstPartyURI = request->mFirstPartyURI; ++ ++ if (imgURI && firstPartyURI) { ++ imgCacheTable &cache = GetCache(imgURI); ++ imgCacheQueue &queue = GetCacheQueue(imgURI); ++ nsCAutoString spec = GetCacheKey(firstPartyURI, imgURI); + + LOG_STATIC_FUNC_WITH_PARAM(gImgLog, "imgLoader::RemoveFromCache", "entry's uri", spec.get()); + +@@ -1513,18 +1555,6 @@ bool imgLoader::RemoveFromCache(imgCacheEntry *entry) + return false; + } + +-static PLDHashOperator EnumEvictEntries(const nsACString&, +- nsRefPtr<imgCacheEntry> &aData, +- void *data) +-{ +- nsTArray<nsRefPtr<imgCacheEntry> > *entries = +- reinterpret_cast<nsTArray<nsRefPtr<imgCacheEntry> > *>(data); +- +- entries->AppendElement(aData); +- +- return PL_DHASH_NEXT; +-} +- + nsresult imgLoader::EvictEntries(imgCacheTable &aCacheToClear) + { + LOG_STATIC_FUNC(gImgLog, "imgLoader::EvictEntries table"); +@@ -1532,7 +1562,7 @@ nsresult imgLoader::EvictEntries(imgCacheTable &aCacheToClear) + // We have to make a temporary, since RemoveFromCache removes the element + // from the queue, invalidating iterators. + nsTArray<nsRefPtr<imgCacheEntry> > entries; +- aCacheToClear.Enumerate(EnumEvictEntries, &entries); ++ aCacheToClear.Enumerate(EnumAllEntries, &entries); + + for (PRUint32 i = 0; i < entries.Length(); ++i) + if (!RemoveFromCache(entries[i])) +@@ -1565,11 +1595,10 @@ nsresult imgLoader::EvictEntries(imgCacheQueue &aQueueToClear) + nsIRequest::VALIDATE_NEVER | \ + nsIRequest::VALIDATE_ONCE_PER_SESSION) + +- +-/* imgIRequest loadImage (in nsIURI aURI, in nsIURI initialDocumentURI, in nsIPrincipal loadingPrincipal, in nsILoadGroup aLoadGroup, in imgIDecoderObserver aObserver, in nsISupports aCX, in nsLoadFlags aLoadFlags, in nsISupports cacheKey, in imgIRequest aRequest); */ ++/* imgIRequest loadImage (in nsIURI aURI, in nsIURI aUrlBarURI, in nsIPrincipal loadingPrincipal, in nsILoadGroup aLoadGroup, in imgIDecoderObserver aObserver, in nsISupports aCX, in nsLoadFlags aLoadFlags, in nsISupports cacheKey, in imgIRequest aRequest); */ + + NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI, +- nsIURI *aInitialDocumentURI, ++ nsIURI *aFirstPartyURI, + nsIURI *aReferrerURI, + nsIPrincipal* aLoadingPrincipal, + nsILoadGroup *aLoadGroup, +@@ -1588,8 +1617,8 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI, + if (!aURI) + return NS_ERROR_NULL_POINTER; + +- nsCAutoString spec; +- aURI->GetSpec(spec); ++ nsCAutoString spec = GetCacheKey(aFirstPartyURI, aURI); ++ + LOG_SCOPE_WITH_PARAM(gImgLog, "imgLoader::LoadImage", "aURI", spec.get()); + + *_retval = nsnull; +@@ -1641,7 +1670,7 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI, + imgCacheTable &cache = GetCache(aURI); + + if (cache.Get(spec, getter_AddRefs(entry)) && entry) { +- if (ValidateEntry(entry, aURI, aInitialDocumentURI, aReferrerURI, ++ if (ValidateEntry(entry, aURI, aFirstPartyURI, aReferrerURI, + aLoadGroup, aObserver, aCX, requestFlags, true, + aRequest, _retval, aPolicy, aLoadingPrincipal, corsmode)) { + request = getter_AddRefs(entry->GetRequest()); +@@ -1680,7 +1709,7 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI, + rv = NewImageChannel(getter_AddRefs(newChannel), + &forcePrincipalCheck, + aURI, +- aInitialDocumentURI, ++ aFirstPartyURI, + aReferrerURI, + aLoadGroup, + mAcceptHeader, +@@ -1702,8 +1731,8 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI, + do_CreateInstance(NS_LOADGROUP_CONTRACTID); + newChannel->SetLoadGroup(loadGroup); + +- request->Init(aURI, aURI, loadGroup, newChannel, entry, aCX, +- aLoadingPrincipal, corsmode); ++ request->Init(aURI, aURI, aFirstPartyURI, loadGroup, newChannel, entry, ++ aCX, aLoadingPrincipal, corsmode); + + // Pass the inner window ID of the loading document, if possible. + nsCOMPtr<nsIDocument> doc = do_QueryInterface(aCX); +@@ -1751,7 +1780,7 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI, + } + + // Try to add the new request into the cache. +- PutIntoCache(aURI, entry); ++ PutIntoCache(spec, entry); + } else { + LOG_MSG_WITH_PARAM(gImgLog, + "imgLoader::LoadImage |cache hit|", "request", request); +@@ -1811,6 +1840,21 @@ NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI, + return NS_OK; + } + ++nsCAutoString imgLoader::GetCacheKey(nsIURI *firstPartyURI, nsIURI *imgURI) ++{ ++ nsCAutoString spec, hostKey; ++ imgURI->GetSpec(spec); ++ ++ // FIXME: Should we use mozIThirdPartyUtil to get a domain from this? ++ firstPartyURI->GetHost(hostKey); ++ ++ // Make a new key using host ++ // FIXME: This might involve a couple more copies than necessary.. ++ // But man, 18 string types? Who knows which one I need to use to do ++ // this cheaply.. ++ return hostKey + nsCAutoString("&") + spec; ++} ++ + /* imgIRequest loadImageWithChannel(in nsIChannel channel, in imgIDecoderObserver aObserver, in nsISupports cx, out nsIStreamListener); */ + NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderObserver *aObserver, nsISupports *aCX, nsIStreamListener **listener, imgIRequest **_retval) + { +@@ -1821,22 +1865,27 @@ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderOb + nsCOMPtr<nsIURI> uri; + channel->GetURI(getter_AddRefs(uri)); + ++ nsCOMPtr<nsIURI> firstPartyURI; ++ nsCOMPtr<mozIThirdPartyUtil> thirdPartySvc ++ = do_GetService(THIRDPARTYUTIL_CONTRACTID); ++ thirdPartySvc->GetFirstPartyURI(channel, nsnull, ++ getter_AddRefs(firstPartyURI)); ++ + nsLoadFlags requestFlags = nsIRequest::LOAD_NORMAL; + channel->GetLoadFlags(&requestFlags); + + nsRefPtr<imgCacheEntry> entry; ++ imgCacheTable &cache = GetCache(uri); ++ nsCAutoString spec = GetCacheKey(firstPartyURI, uri); + + if (requestFlags & nsIRequest::LOAD_BYPASS_CACHE) { +- RemoveFromCache(uri); ++ imgCacheQueue &queue = GetCacheQueue(uri); ++ RemoveKeyFromCache(cache, queue, spec); + } else { + // Look in the cache for our URI, and then validate it. + // XXX For now ignore aCacheKey. We will need it in the future + // for correctly dealing with image load requests that are a result +- // of post data. +- imgCacheTable &cache = GetCache(uri); +- nsCAutoString spec; +- +- uri->GetSpec(spec); ++ // of post data + + if (cache.Get(spec, getter_AddRefs(entry)) && entry) { + // We don't want to kick off another network load. So we ask +@@ -1908,7 +1957,7 @@ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderOb + channel->GetOriginalURI(getter_AddRefs(originalURI)); + + // No principal specified here, because we're not passed one. +- request->Init(originalURI, uri, channel, channel, entry, ++ request->Init(originalURI, uri, firstPartyURI, channel, channel, entry, + aCX, nsnull, imgIRequest::CORS_NONE); + + ProxyListener *pl = new ProxyListener(static_cast<nsIStreamListener *>(request.get())); +@@ -1920,7 +1969,7 @@ NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderOb + NS_RELEASE(pl); + + // Try to add the new request into the cache. +- PutIntoCache(originalURI, entry); ++ PutIntoCache(GetCacheKey(originalURI, firstPartyURI), entry); + + rv = CreateNewProxyForRequest(request, loadGroup, aObserver, + requestFlags, nsnull, _retval); +@@ -2207,6 +2256,7 @@ NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupport + + PRInt32 corsmode = mRequest->GetCORSMode(); + nsCOMPtr<nsIPrincipal> loadingPrincipal = mRequest->GetLoadingPrincipal(); ++ nsCOMPtr<nsIURI> firstPartyURI = mRequest->mFirstPartyURI; + + // Doom the old request's cache entry + mRequest->RemoveFromCache(); +@@ -2217,16 +2267,16 @@ NS_IMETHODIMP imgCacheValidator::OnStartRequest(nsIRequest *aRequest, nsISupport + // We use originalURI here to fulfil the imgIRequest contract on GetURI. + nsCOMPtr<nsIURI> originalURI; + channel->GetOriginalURI(getter_AddRefs(originalURI)); +- mNewRequest->Init(originalURI, uri, aRequest, channel, mNewEntry, +- mContext, loadingPrincipal, +- corsmode); ++ mNewRequest->Init(originalURI, uri, firstPartyURI, aRequest, channel, ++ mNewEntry, mContext, loadingPrincipal, corsmode); + + mDestListener = new ProxyListener(mNewRequest); + + // Try to add the new request into the cache. Note that the entry must be in + // the cache before the proxies' ownership changes, because adding a proxy + // changes the caching behaviour for imgRequests. +- sImgLoader.PutIntoCache(originalURI, mNewEntry); ++ sImgLoader.PutIntoCache(imgLoader::GetCacheKey(firstPartyURI, originalURI), ++ mNewEntry); + + PRUint32 count = mProxies.Count(); + for (PRInt32 i = count-1; i>=0; i--) { +diff --git a/image/src/imgLoader.h b/image/src/imgLoader.h +index c0ba1d4..22671b3 100644 +--- a/image/src/imgLoader.h ++++ b/image/src/imgLoader.h +@@ -261,10 +261,11 @@ public: + + static nsresult InitCache(); + +- static bool RemoveFromCache(nsIURI *aKey); ++ static nsCAutoString GetCacheKey(nsIURI *firstPartyURI, ++ nsIURI *imgURI); + static bool RemoveFromCache(imgCacheEntry *entry); +- +- static bool PutIntoCache(nsIURI *key, imgCacheEntry *entry); ++ static bool PutIntoCache(nsCAutoString key, imgCacheEntry *entry); ++ static bool RemoveMatchingUrlsFromCache(nsIURI *aKey); + + // Returns true if we should prefer evicting cache entry |two| over cache + // entry |one|. +@@ -349,9 +350,15 @@ private: // methods + static void CacheEntriesChanged(nsIURI *aURI, PRInt32 sizediff = 0); + static void CheckCacheLimits(imgCacheTable &cache, imgCacheQueue &queue); + ++ static bool RemoveKeyFromCache(imgCacheTable &cache, ++ imgCacheQueue &queue, ++ nsCAutoString key); ++ ++ + private: // data + friend class imgCacheEntry; + friend class imgMemoryReporter; ++ friend class imgRequest; + + static imgCacheTable sCache; + static imgCacheQueue sCacheQueue; +diff --git a/image/src/imgRequest.cpp b/image/src/imgRequest.cpp +index 85ec2fa..cc40e86 100644 +--- a/image/src/imgRequest.cpp ++++ b/image/src/imgRequest.cpp +@@ -137,6 +137,7 @@ imgRequest::~imgRequest() + + nsresult imgRequest::Init(nsIURI *aURI, + nsIURI *aCurrentURI, ++ nsIURI *aFirstPartyURI, + nsIRequest *aRequest, + nsIChannel *aChannel, + imgCacheEntry *aCacheEntry, +@@ -158,6 +159,7 @@ nsresult imgRequest::Init(nsIURI *aURI, + + mURI = aURI; + mCurrentURI = aCurrentURI; ++ mFirstPartyURI = aFirstPartyURI; + mRequest = aRequest; + mChannel = aChannel; + mTimedChannel = do_QueryInterface(mChannel); +@@ -351,8 +353,11 @@ void imgRequest::RemoveFromCache() + // mCacheEntry is nulled out when we have no more observers. + if (mCacheEntry) + imgLoader::RemoveFromCache(mCacheEntry); +- else +- imgLoader::RemoveFromCache(mURI); ++ else { ++ imgLoader::RemoveKeyFromCache(imgLoader::GetCache(mURI), ++ imgLoader::GetCacheQueue(mURI), ++ imgLoader::GetCacheKey(mFirstPartyURI, mURI)); ++ } + } + + mCacheEntry = nsnull; +diff --git a/image/src/imgRequest.h b/image/src/imgRequest.h +index 7b200df..6ae7ae7 100644 +--- a/image/src/imgRequest.h ++++ b/image/src/imgRequest.h +@@ -91,6 +91,7 @@ public: + + nsresult Init(nsIURI *aURI, + nsIURI *aCurrentURI, ++ nsIURI *aFirstPartyURI, + nsIRequest *aRequest, + nsIChannel *aChannel, + imgCacheEntry *aCacheEntry, +@@ -221,6 +222,8 @@ private: + nsCOMPtr<nsIURI> mURI; + // The URI of the resource we ended up loading after all redirects, etc. + nsCOMPtr<nsIURI> mCurrentURI; ++ // The first party that triggered the load -- for cookie + cache isolation ++ nsCOMPtr<nsIURI> mFirstPartyURI; + // The principal of the document which loaded this image. Used when validating for CORS. + nsCOMPtr<nsIPrincipal> mLoadingPrincipal; + // The principal of this image. +diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp +index 807aa6c..7bb866b 100644 +--- a/layout/generic/nsImageFrame.cpp ++++ b/layout/generic/nsImageFrame.cpp +@@ -96,6 +96,7 @@ + #include "nsLayoutErrors.h" + #include "nsBidiUtils.h" + #include "nsBidiPresUtils.h" ++#include "mozIThirdPartyUtil.h" + + #include "gfxRect.h" + #include "ImageLayers.h" +@@ -1760,9 +1761,17 @@ nsImageFrame::LoadIcon(const nsAString& aSpec, + + // For icon loads, we don't need to merge with the loadgroup flags + nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL; ++ ++ nsCOMPtr<nsIURI> firstPartyURI; ++ nsCOMPtr<mozIThirdPartyUtil> thirdPartySvc ++ = do_GetService(THIRDPARTYUTIL_CONTRACTID); ++ // XXX: Should we pass the loadgroup, too? Is document ever likely ++ // to be unset? ++ thirdPartySvc->GetFirstPartyURI(nsnull, aPresContext->Document(), ++ getter_AddRefs(firstPartyURI)); + + return il->LoadImage(realURI, /* icon URI */ +- nsnull, /* initial document URI; this is only ++ firstPartyURI, /* initial document URI; this is only + relevant for cookies, so does not + apply to icons. */ + nsnull, /* referrer (not relevant for icons) */ +diff --git a/netwerk/base/public/mozIThirdPartyUtil.idl b/netwerk/base/public/mozIThirdPartyUtil.idl +index ad41985..fd2cb38 100644 +--- a/netwerk/base/public/mozIThirdPartyUtil.idl ++++ b/netwerk/base/public/mozIThirdPartyUtil.idl +@@ -40,6 +40,7 @@ + interface nsIURI; + interface nsIDOMWindow; + interface nsIChannel; ++interface nsIDocument; + + /** + * Utility functions for determining whether a given URI, channel, or window +@@ -173,6 +174,26 @@ interface mozIThirdPartyUtil : nsISupports + * @return the base domain. + */ + AUTF8String getBaseDomain(in nsIURI aHostURI); ++ ++ ++ /** ++ * getFirstPartyURI ++ * ++ * Obtain the top-level url bar URI for either a channel or a document. ++ * Either parameter may be null (but not both). ++ * ++ * @param aChannel ++ * An arbitrary channel for some content element of a first party ++ * load. Can be null. ++ * ++ * @param aDoc ++ * An arbitrary third party document. Can be null. ++ * ++ * @return the first party url bar URI for the load. ++ */ ++ nsIURI getFirstPartyURI(in nsIChannel aChannel, ++ in nsIDocument aDoc); ++ + }; + + %{ C++ +diff --git a/netwerk/cookie/nsICookiePermission.idl b/netwerk/cookie/nsICookiePermission.idl +index c7f765b..d81e2e6 100644 +--- a/netwerk/cookie/nsICookiePermission.idl ++++ b/netwerk/cookie/nsICookiePermission.idl +@@ -40,6 +40,7 @@ + interface nsICookie2; + interface nsIURI; + interface nsIChannel; ++interface nsIDocument; + + typedef long nsCookieAccess; + +diff --git a/toolkit/system/gnome/nsAlertsIconListener.cpp b/toolkit/system/gnome/nsAlertsIconListener.cpp +index 250e4fb..614e70f 100644 +--- a/toolkit/system/gnome/nsAlertsIconListener.cpp ++++ b/toolkit/system/gnome/nsAlertsIconListener.cpp +@@ -271,7 +271,8 @@ nsAlertsIconListener::StartRequest(const nsAString & aImageUrl) + if (!il) + return ShowAlert(NULL); + +- return il->LoadImage(imageUri, nsnull, nsnull, nsnull, nsnull, this, ++ // XXX: Hrmm.... Bypass cache, or isolate to imageUrl? ++ return il->LoadImage(imageUri, imageUri, nsnull, nsnull, nsnull, this, + nsnull, nsIRequest::LOAD_NORMAL, nsnull, nsnull, + nsnull, getter_AddRefs(mIconRequest)); + } +diff --git a/widget/cocoa/nsMenuItemIconX.mm b/widget/cocoa/nsMenuItemIconX.mm +index 9505ea2..8739c67 100644 +--- a/widget/cocoa/nsMenuItemIconX.mm ++++ b/widget/cocoa/nsMenuItemIconX.mm +@@ -338,9 +338,15 @@ nsMenuItemIconX::LoadIcon(nsIURI* aIconURI) + [mNativeMenuItem setImage:sPlaceholderIconImage]; + } + ++ nsCOMPtr<nsIURI> firstPartyURI; ++ nsCOMPtr<mozIThirdPartyUtil> thirdPartySvc ++ = do_GetService(THIRDPARTYUTIL_CONTRACTID); ++ thirdPartySvc->GetFirstPartyURI(nsnull, document, ++ getter_AddRefs(firstPartyURI)); ++ + // Passing in null for channelPolicy here since nsMenuItemIconX::LoadIcon is + // not exposed to web content +- rv = loader->LoadImage(aIconURI, nsnull, nsnull, nsnull, loadGroup, this, ++ rv = loader->LoadImage(aIconURI, firstPartyURI, nsnull, nsnull, loadGroup, this, + nsnull, nsIRequest::LOAD_NORMAL, nsnull, nsnull, + nsnull, getter_AddRefs(mIconRequest)); + if (NS_FAILED(rv)) return rv; +-- +1.7.5.4 +
tor-commits@lists.torproject.org