From 83c646ef2ff2fbada89b0a351f9840230271f642 Mon Sep 17 00:00:00 2001 From: Mark Smith Date: Tue, 16 Jun 2009 10:30:25 -0400 Subject: [PATCH] Bug 437174 - Disabling 3rd party cookies breaks sending cookies for channels with no docshell. r+sr=bzbarsky. Added forceAllowThirdPartyCookie to nsIHttpChannelInternal. Added LOAD_FLAGS_FORCE_ALLOW_COOKIES to nsIWebNavigation. Added PERSIST_FLAGS_FORCE_ALLOW_COOKIES to nsIWebBrowserPersist. --HG-- extra : rebase_source : 0ea11e1ed53d75152f57ffed74f44fc749a7a567 --- browser/base/content/nsContextMenu.js | 7 +++- docshell/base/nsDocShell.cpp | 12 +++++-- docshell/base/nsDocShell.h | 3 +- docshell/base/nsIDocShell.idl | 1 + docshell/base/nsIWebNavigation.idl | 6 ++++ .../public/nsIWebBrowserPersist.idl | 5 +++ .../src/nsWebBrowserPersist.cpp | 9 +++++ extensions/cookie/nsCookiePermission.cpp | 34 +++++++++++++++---- .../http/public/nsIHttpChannelInternal.idl | 7 +++- netwerk/protocol/http/src/nsHttpChannel.cpp | 15 ++++++++ netwerk/protocol/http/src/nsHttpChannel.h | 1 + toolkit/content/contentAreaUtils.js | 5 ++- 12 files changed, 93 insertions(+), 12 deletions(-) diff --git a/browser/base/content/nsContextMenu.js b/browser/base/content/nsContextMenu.js index d8525e42f810..a9c432bf907c 100644 --- a/browser/base/content/nsContextMenu.js +++ b/browser/base/content/nsContextMenu.js @@ -43,6 +43,8 @@ # Ehsan Akhgari # Dan Mosedale # Justin Dolske +# Kathleen Brade +# Mark Smith # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or @@ -946,8 +948,11 @@ nsContextMenu.prototype = { channel.notificationCallbacks = new callbacks(); channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE | Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS; - if (channel instanceof Ci.nsIHttpChannel) + if (channel instanceof Ci.nsIHttpChannel) { channel.referrer = doc.documentURIObject; + if (channel instanceof Ci.nsIHttpChannelInternal) + channel.forceAllowThirdPartyCookie = true; + } // fallback to the old way if we don't see the headers quickly var timeToWait = diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index fa0ab9b4a398..e7050db5a053 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -1336,6 +1336,9 @@ nsDocShell::LoadURI(nsIURI * aURI, if (aLoadFlags & LOAD_FLAGS_BYPASS_CLASSIFIER) flags |= INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER; + if (aLoadFlags & LOAD_FLAGS_FORCE_ALLOW_COOKIES) + flags |= INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES; + return InternalLoad(aURI, referrer, owner, @@ -8018,7 +8021,8 @@ nsDocShell::InternalLoad(nsIURI * aURI, owner, aTypeHint, aPostData, aHeadersData, aFirstParty, aDocShell, getter_AddRefs(req), (aFlags & INTERNAL_LOAD_FLAGS_FIRST_LOAD) != 0, - (aFlags & INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER) != 0); + (aFlags & INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER) != 0, + (aFlags & INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES) != 0); if (req && aRequest) NS_ADDREF(*aRequest = req); @@ -8105,7 +8109,8 @@ nsDocShell::DoURILoad(nsIURI * aURI, nsIDocShell ** aDocShell, nsIRequest ** aRequest, PRBool aIsNewWindowTarget, - PRBool aBypassClassifier) + PRBool aBypassClassifier, + PRBool aForceAllowCookies) { nsresult rv; nsCOMPtr uriLoader; @@ -8179,6 +8184,9 @@ nsDocShell::DoURILoad(nsIURI * aURI, nsCOMPtr httpChannel(do_QueryInterface(channel)); nsCOMPtr httpChannelInternal(do_QueryInterface(channel)); if (httpChannelInternal) { + if (aForceAllowCookies) { + httpChannelInternal->SetForceAllowThirdPartyCookie(PR_TRUE); + } if (aFirstParty) { httpChannelInternal->SetDocumentURI(aURI); } else { diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index 5ed2cccedd11..307eb31c38eb 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -347,7 +347,8 @@ protected: nsIDocShell ** aDocShell, nsIRequest ** aRequest, PRBool aIsNewWindowTarget, - PRBool aBypassClassifier); + PRBool aBypassClassifier, + PRBool aForceAllowCookies); NS_IMETHOD AddHeadersToChannel(nsIInputStream * aHeadersData, nsIChannel * aChannel); virtual nsresult DoChannelLoad(nsIChannel * aChannel, diff --git a/docshell/base/nsIDocShell.idl b/docshell/base/nsIDocShell.idl index 90eeb94fcb9e..252995fa76b4 100644 --- a/docshell/base/nsIDocShell.idl +++ b/docshell/base/nsIDocShell.idl @@ -131,6 +131,7 @@ interface nsIDocShell : nsISupports const long INTERNAL_LOAD_FLAGS_FIRST_LOAD = 0x8; const long INTERNAL_LOAD_FLAGS_BYPASS_CLASSIFIER = 0x10; + const long INTERNAL_LOAD_FLAGS_FORCE_ALLOW_COOKIES = 0x20; /** * Loads the given URI. This method is identical to loadURI(...) except diff --git a/docshell/base/nsIWebNavigation.idl b/docshell/base/nsIWebNavigation.idl index 44ebde7295ac..9aa390d4b472 100644 --- a/docshell/base/nsIWebNavigation.idl +++ b/docshell/base/nsIWebNavigation.idl @@ -210,6 +210,12 @@ interface nsIWebNavigation : nsISupports */ const unsigned long LOAD_FLAGS_BYPASS_CLASSIFIER = 0x10000; + /** + * Force relevant cookies to be sent with this load even if normally they + * wouldn't be. + */ + const unsigned long LOAD_FLAGS_FORCE_ALLOW_COOKIES = 0x20000; + /** * Loads a given URI. This will give priority to loading the requested URI * in the object implementing this interface. If it can't be loaded here diff --git a/embedding/components/webbrowserpersist/public/nsIWebBrowserPersist.idl b/embedding/components/webbrowserpersist/public/nsIWebBrowserPersist.idl index ef7e1e4b4884..7ac0f01f8d56 100644 --- a/embedding/components/webbrowserpersist/public/nsIWebBrowserPersist.idl +++ b/embedding/components/webbrowserpersist/public/nsIWebBrowserPersist.idl @@ -100,6 +100,11 @@ interface nsIWebBrowserPersist : nsICancelable */ const unsigned long PERSIST_FLAGS_APPEND_TO_FILE = 32768; + /** + * Force relevant cookies to be sent with this load even if normally they + * wouldn't be. + */ + const unsigned long PERSIST_FLAGS_FORCE_ALLOW_COOKIES = 65536; /** * Flags governing how data is fetched and saved from the network. diff --git a/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp b/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp index 19c7acb5fa45..682eff9f584f 100644 --- a/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp +++ b/embedding/components/webbrowserpersist/src/nsWebBrowserPersist.cpp @@ -52,6 +52,7 @@ #include "nsIStorageStream.h" #include "nsISeekableStream.h" #include "nsIHttpChannel.h" +#include "nsIHttpChannelInternal.h" #include "nsIEncodedChannel.h" #include "nsIUploadChannel.h" #include "nsICachingChannel.h" @@ -1262,6 +1263,14 @@ nsresult nsWebBrowserPersist::SaveURIInternal( } } + if (mPersistFlags & PERSIST_FLAGS_FORCE_ALLOW_COOKIES) + { + nsCOMPtr httpChannelInternal = + do_QueryInterface(inputChannel); + if (httpChannelInternal) + httpChannelInternal->SetForceAllowThirdPartyCookie(PR_TRUE); + } + // Set the referrer, post data and headers if any nsCOMPtr httpChannel(do_QueryInterface(inputChannel)); if (httpChannel) diff --git a/extensions/cookie/nsCookiePermission.cpp b/extensions/cookie/nsCookiePermission.cpp index acde217027ae..dcd236fc3a15 100644 --- a/extensions/cookie/nsCookiePermission.cpp +++ b/extensions/cookie/nsCookiePermission.cpp @@ -24,6 +24,8 @@ * Darin Fisher * Daniel Witte * Ehsan Akhgari + * Kathleen Brade + * Mark Smith * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -53,6 +55,7 @@ #include "nsIDocShell.h" #include "nsIWebNavigation.h" #include "nsIChannel.h" +#include "nsIHttpChannelInternal.h" #include "nsIDOMWindow.h" #include "nsIDOMDocument.h" #include "nsIPrincipal.h" @@ -428,17 +431,20 @@ nsCookiePermission::GetOriginatingURI(nsIChannel *aChannel, * * 1) no channel. * - * 2) a channel, but no window. this can occur when the consumer kicking + * 2) a channel with the "force allow third party cookies" option set. + * since we may not have a window, we return the channel URI in this case. + * + * 3) a channel, but no window. this can occur when the consumer kicking * off the load doesn't provide one to the channel, and should be limited * to loads of certain types of resources. * - * 3) a window equal to the top window of same type, with the channel its + * 4) a window equal to the top window of same type, with the channel its * document channel. this covers the case of a freshly kicked-off load * (e.g. the user typing something in the location bar, or clicking on a * bookmark), where the window's URI hasn't yet been set, and will be * bogus. we return the channel URI in this case. * - * 4) Anything else. this covers most cases for an ordinary page load from + * 5) Anything else. this covers most cases for an ordinary page load from * the location bar, and will catch nested frames within a page, image * loads, etc. we return the URI of the root window's document's principal * in this case. @@ -450,6 +456,22 @@ nsCookiePermission::GetOriginatingURI(nsIChannel *aChannel, if (!aChannel) return NS_ERROR_NULL_POINTER; + // case 2) + nsCOMPtr httpChannelInternal = do_QueryInterface(aChannel); + if (httpChannelInternal) + { + PRBool doForce = PR_FALSE; + if (NS_SUCCEEDED(httpChannelInternal->GetForceAllowThirdPartyCookie(&doForce)) && doForce) + { + // return the channel's URI (we may not have a window) + aChannel->GetURI(aURI); + if (!*aURI) + return NS_ERROR_NULL_POINTER; + + return NS_OK; + } + } + // find the associated window and its top window nsCOMPtr ctx; NS_QueryNotificationCallbacks(aChannel, ctx); @@ -459,11 +481,11 @@ nsCookiePermission::GetOriginatingURI(nsIChannel *aChannel, ctx->GetAssociatedWindow(getter_AddRefs(ourWin)); } - // case 2) + // case 3) if (!topWin) return NS_ERROR_INVALID_ARG; - // case 3) + // case 4) if (ourWin == topWin) { // Check whether this is the document channel for this window (representing // a load of a new page). This is a bit of a nasty hack, but we will @@ -481,7 +503,7 @@ nsCookiePermission::GetOriginatingURI(nsIChannel *aChannel, } } - // case 4) - get the originating URI from the top window's principal + // case 5) - get the originating URI from the top window's principal nsCOMPtr scriptObjPrin = do_QueryInterface(topWin); NS_ENSURE_TRUE(scriptObjPrin, NS_ERROR_UNEXPECTED); diff --git a/netwerk/protocol/http/public/nsIHttpChannelInternal.idl b/netwerk/protocol/http/public/nsIHttpChannelInternal.idl index ae8de636d1ad..ca73ddbf5bab 100644 --- a/netwerk/protocol/http/public/nsIHttpChannelInternal.idl +++ b/netwerk/protocol/http/public/nsIHttpChannelInternal.idl @@ -45,7 +45,7 @@ interface nsIProxyInfo; * using any feature exposed by this interface, be aware that this interface * will change and you will be broken. You have been warned. */ -[scriptable, uuid(3ce040fb-3933-462a-8d62-80b78fbd0809)] +[scriptable, uuid(0eb66361-faaa-4e52-8c7e-6c25f11f8e3c)] interface nsIHttpChannelInternal : nsISupports { /** @@ -78,4 +78,9 @@ interface nsIHttpChannelInternal : nsISupports */ void setupFallbackChannel(in string aFallbackKey); + /** + * Force relevant cookies to be sent with this load even if normally they + * wouldn't be. + */ + attribute boolean forceAllowThirdPartyCookie; }; diff --git a/netwerk/protocol/http/src/nsHttpChannel.cpp b/netwerk/protocol/http/src/nsHttpChannel.cpp index e2886ecb2422..08040a487c03 100644 --- a/netwerk/protocol/http/src/nsHttpChannel.cpp +++ b/netwerk/protocol/http/src/nsHttpChannel.cpp @@ -135,6 +135,7 @@ nsHttpChannel::nsHttpChannel() , mChooseApplicationCache(PR_FALSE) , mLoadedFromApplicationCache(PR_FALSE) , mTracingEnabled(PR_TRUE) + , mForceAllowThirdPartyCookie(PR_FALSE) { LOG(("Creating nsHttpChannel @%x\n", this)); @@ -4727,6 +4728,20 @@ nsHttpChannel::SetDocumentURI(nsIURI *aDocumentURI) return NS_OK; } +NS_IMETHODIMP +nsHttpChannel::GetForceAllowThirdPartyCookie(PRBool *aForceAllowThirdPartyCookie) +{ + *aForceAllowThirdPartyCookie = mForceAllowThirdPartyCookie; + return NS_OK; +} + +NS_IMETHODIMP +nsHttpChannel::SetForceAllowThirdPartyCookie(PRBool aForceAllowThirdPartyCookie) +{ + mForceAllowThirdPartyCookie = aForceAllowThirdPartyCookie; + return NS_OK; +} + NS_IMETHODIMP nsHttpChannel::GetRequestVersion(PRUint32 *major, PRUint32 *minor) { diff --git a/netwerk/protocol/http/src/nsHttpChannel.h b/netwerk/protocol/http/src/nsHttpChannel.h index 6bc0a9e19ac7..6b4a304663d3 100644 --- a/netwerk/protocol/http/src/nsHttpChannel.h +++ b/netwerk/protocol/http/src/nsHttpChannel.h @@ -343,6 +343,7 @@ private: PRUint32 mChooseApplicationCache : 1; PRUint32 mLoadedFromApplicationCache : 1; PRUint32 mTracingEnabled : 1; + PRUint32 mForceAllowThirdPartyCookie : 1; class nsContentEncodings : public nsIUTF8StringEnumerator { diff --git a/toolkit/content/contentAreaUtils.js b/toolkit/content/contentAreaUtils.js index 37cf3da87720..4262206c1938 100644 --- a/toolkit/content/contentAreaUtils.js +++ b/toolkit/content/contentAreaUtils.js @@ -24,6 +24,8 @@ # Fredrik Holmqvist # Asaf Romano # Ehsan Akhgari +# Kathleen Brade +# Mark Smith # # Alternatively, the contents of this file may be used under the terms of # either the GNU General Public License Version 2 or later (the "GPL"), or @@ -391,7 +393,8 @@ function internalPersist(persistArgs) // Calculate persist flags. const nsIWBP = Components.interfaces.nsIWebBrowserPersist; - const flags = nsIWBP.PERSIST_FLAGS_REPLACE_EXISTING_FILES; + const flags = nsIWBP.PERSIST_FLAGS_REPLACE_EXISTING_FILES | + nsIWBP.PERSIST_FLAGS_FORCE_ALLOW_COOKIES; if (persistArgs.bypassCache) persist.persistFlags = flags | nsIWBP.PERSIST_FLAGS_BYPASS_CACHE; else