diff --git a/docshell/base/SerializedLoadContext.cpp b/docshell/base/SerializedLoadContext.cpp index ec52b561935..b7f067c4c50 100644 --- a/docshell/base/SerializedLoadContext.cpp +++ b/docshell/base/SerializedLoadContext.cpp @@ -21,6 +21,20 @@ SerializedLoadContext::SerializedLoadContext(nsIChannel* aChannel) nsCOMPtr loadContext; NS_QueryNotificationCallbacks(aChannel, loadContext); Init(loadContext); + + if (!loadContext) { + // Attempt to retrieve the private bit from the channel if it has been + // overriden. + bool isPrivate = false; + bool isOverriden = false; + nsCOMPtr pbChannel = do_QueryInterface(aChannel); + if (pbChannel && + NS_SUCCEEDED(pbChannel->IsPrivateModeOverriden(&isPrivate, &isOverriden)) && + isOverriden) { + mUsePrivateBrowsing = isPrivate; + mIsPrivateBitValid = true; + } + } } SerializedLoadContext::SerializedLoadContext(nsIWebSocketChannel* aChannel) @@ -35,12 +49,14 @@ SerializedLoadContext::Init(nsILoadContext* aLoadContext) { if (aLoadContext) { mIsNotNull = true; + mIsPrivateBitValid = true; aLoadContext->GetIsContent(&mIsContent); aLoadContext->GetUsePrivateBrowsing(&mUsePrivateBrowsing); aLoadContext->GetAppId(&mAppId); aLoadContext->GetIsInBrowserElement(&mIsInBrowserElement); } else { mIsNotNull = false; + mIsPrivateBitValid = false; // none of below values really matter when mIsNotNull == false: // we won't be GetInterfaced to nsILoadContext mIsContent = true; diff --git a/docshell/base/SerializedLoadContext.h b/docshell/base/SerializedLoadContext.h index c2331ef244c..555d9eeccc8 100644 --- a/docshell/base/SerializedLoadContext.h +++ b/docshell/base/SerializedLoadContext.h @@ -36,13 +36,21 @@ public: void Init(nsILoadContext* aLoadContext); - bool IsNotNull() const + bool IsNotNull() const { return mIsNotNull; } + bool IsPrivateBitValid() const + { + return mIsPrivateBitValid; + } + // used to indicate if child-side LoadContext * was null. bool mIsNotNull; + // used to indicate if child-side mUsePrivateBrowsing flag is valid, even if + // mIsNotNull is false, i.e., child LoadContext was null. + bool mIsPrivateBitValid; bool mIsContent; bool mUsePrivateBrowsing; bool mIsInBrowserElement; diff --git a/netwerk/base/public/Makefile.in b/netwerk/base/public/Makefile.in index 93ce67c4759..013e8c942d9 100644 --- a/netwerk/base/public/Makefile.in +++ b/netwerk/base/public/Makefile.in @@ -58,6 +58,7 @@ XPIDLSRCS = \ nsINetworkLinkService.idl \ nsIPermission.idl \ nsIPermissionManager.idl \ + nsIPrivateBrowsingChannel.idl \ nsIPrivateBrowsingService.idl \ nsIProgressEventSink.idl \ nsIPrompt.idl \ diff --git a/netwerk/base/public/nsIPrivateBrowsingChannel.idl b/netwerk/base/public/nsIPrivateBrowsingChannel.idl new file mode 100644 index 00000000000..6d9afbd01af --- /dev/null +++ b/netwerk/base/public/nsIPrivateBrowsingChannel.idl @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsISupports.idl" + +/** + * This interface is implemented by channels which support overriding the + * privacy state of the channel. + * + * This interface must be used only from the XPCOM main thread. + */ +[scriptable, uuid(424b7efc-5d56-4717-9a71-8db9dcaaa618)] +interface nsIPrivateBrowsingChannel : nsISupports +{ + /** + * Determine whether the channel is tied to a private browsing window. + * + * This value can be set only before the channel is opened. Setting it + * after that does not have any effect. This value overrides the privacy + * state of the channel, which means that if you call this method, then + * the loadGroup and load context will no longer be consulted when we + * need to know the private mode status for a channel. + * + * Note that this value is only meant to be used when the channel's privacy + * status cannot be obtained from the loadGroup or load context (for + * example, when the channel is not associated with any loadGroup or load + * context.) Setting this value directly should be avoided if possible. + * + * Implementations must enforce the ordering semantics of this function by + * raising errors if setPrivate is called on a channel which has a loadGroup + * and/or callbacks that implement nsILoadContext, or if the loadGroup + * or notificationCallbacks are set after setPrivate has been called. + * + * @param aPrivate whether the channel should be opened in private mode. + */ + void setPrivate(in boolean aPrivate); + + /* + * This function is used to determine whether the channel's private mode + * has been overridden by a call to setPrivate. It is intended to be used + * by NS_UsePrivateBrowsing(), and you should not call it directly. + * + * @param aValue the overridden value. This will only be set if the function + * returns true. + */ + [noscript] boolean isPrivateModeOverriden(out boolean aValue); +}; diff --git a/netwerk/base/public/nsNetUtil.h b/netwerk/base/public/nsNetUtil.h index bf665cb31a4..aad4280c71d 100644 --- a/netwerk/base/public/nsNetUtil.h +++ b/netwerk/base/public/nsNetUtil.h @@ -76,6 +76,7 @@ #include "nsIMIMEHeaderParam.h" #include "nsILoadContext.h" #include "mozilla/Services.h" +#include "nsIPrivateBrowsingChannel.h" #ifdef MOZILLA_INTERNAL_API @@ -1325,6 +1326,14 @@ NS_QueryNotificationCallbacks(nsIInterfaceRequestor *callbacks, inline bool NS_UsePrivateBrowsing(nsIChannel *channel) { + bool isPrivate = false; + bool isOverriden = false; + nsCOMPtr pbChannel = do_QueryInterface(channel); + if (pbChannel && + NS_SUCCEEDED(pbChannel->IsPrivateModeOverriden(&isPrivate, &isOverriden)) && + isOverriden) { + return isPrivate; + } nsCOMPtr loadContext; NS_QueryNotificationCallbacks(channel, loadContext); return loadContext && loadContext->UsePrivateBrowsing(); diff --git a/netwerk/base/src/PrivateBrowsingChannel.h b/netwerk/base/src/PrivateBrowsingChannel.h new file mode 100644 index 00000000000..451915c4cc1 --- /dev/null +++ b/netwerk/base/src/PrivateBrowsingChannel.h @@ -0,0 +1,83 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:set ts=4 sts=4 sw=4 et cin: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_net_PrivateBrowsingChannel_h__ +#define mozilla_net_PrivateBrowsingChannel_h__ + +#include "nsIPrivateBrowsingChannel.h" +#include "nsCOMPtr.h" +#include "nsILoadGroup.h" +#include "nsILoadContext.h" + +namespace mozilla { +namespace net { + +template +class PrivateBrowsingChannel : public nsIPrivateBrowsingChannel +{ +public: + PrivateBrowsingChannel() : + mPrivateBrowsingOverriden(false), + mPrivateBrowsing(false) + { + } + + NS_IMETHOD SetPrivate(bool aPrivate) + { + // Make sure that we don't have a load group or a load context + // This is a fatal error in debug builds, and a runtime error in release + // builds. + nsILoadGroup* loadGroup = static_cast(this)->mLoadGroup; + nsCOMPtr loadContext; + if (!loadGroup) { + NS_QueryNotificationCallbacks(static_cast(this), loadContext); + } + MOZ_ASSERT(!loadGroup && !loadContext); + if (loadGroup || loadContext) { + return NS_ERROR_FAILURE; + } + + mPrivateBrowsingOverriden = true; + mPrivateBrowsing = aPrivate; + return NS_OK; + } + + NS_IMETHOD IsPrivateModeOverriden(bool* aValue, bool *aResult) + { + NS_ENSURE_ARG_POINTER(aValue); + NS_ENSURE_ARG_POINTER(aResult); + *aResult = mPrivateBrowsingOverriden; + if (mPrivateBrowsingOverriden) { + *aValue = mPrivateBrowsing; + } + return NS_OK; + } + + bool CanSetCallbacks() const + { + // Make sure that the private bit override flag is not set. + // This is a fatal error in debug builds, and a runtime error in release + // builds. + MOZ_ASSERT(!mPrivateBrowsingOverriden); + return !mPrivateBrowsingOverriden; + } + + bool CanSetLoadGroup() const + { + // We can set a load group whenever we can set a callback + return CanSetCallbacks(); + } + +protected: + bool mPrivateBrowsingOverriden; + bool mPrivateBrowsing; +}; + +} +} + +#endif + diff --git a/netwerk/protocol/ftp/FTPChannelChild.cpp b/netwerk/protocol/ftp/FTPChannelChild.cpp index d57bd9577e9..ae937356846 100644 --- a/netwerk/protocol/ftp/FTPChannelChild.cpp +++ b/netwerk/protocol/ftp/FTPChannelChild.cpp @@ -69,13 +69,14 @@ FTPChannelChild::ReleaseIPDLReference() // FTPChannelChild::nsISupports //----------------------------------------------------------------------------- -NS_IMPL_ISUPPORTS_INHERITED5(FTPChannelChild, +NS_IMPL_ISUPPORTS_INHERITED6(FTPChannelChild, nsBaseChannel, nsIFTPChannel, nsIUploadChannel, nsIResumableChannel, nsIProxiedChannel, - nsIChildChannel) + nsIChildChannel, + nsIPrivateBrowsingChannel) //----------------------------------------------------------------------------- @@ -546,6 +547,26 @@ FTPChannelChild::CompleteRedirectSetup(nsIStreamListener *listener, return NS_OK; } +NS_IMETHODIMP +FTPChannelChild::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks) +{ + if (!CanSetCallbacks()) { + return NS_ERROR_FAILURE; + } + + return nsBaseChannel::SetNotificationCallbacks(aCallbacks); +} + +NS_IMETHODIMP +FTPChannelChild::SetLoadGroup(nsILoadGroup * aLoadGroup) +{ + if (!CanSetLoadGroup()) { + return NS_ERROR_FAILURE; + } + + return nsBaseChannel::SetLoadGroup(aLoadGroup); +} + } // namespace net } // namespace mozilla diff --git a/netwerk/protocol/ftp/FTPChannelChild.h b/netwerk/protocol/ftp/FTPChannelChild.h index 65f01f4b88a..d02af96e6a2 100644 --- a/netwerk/protocol/ftp/FTPChannelChild.h +++ b/netwerk/protocol/ftp/FTPChannelChild.h @@ -18,6 +18,7 @@ #include "nsIChildChannel.h" #include "nsIStreamListener.h" +#include "PrivateBrowsingChannel.h" namespace mozilla { namespace net { @@ -34,6 +35,7 @@ class FTPChannelChild : public PFTPChannelChild , public nsIResumableChannel , public nsIProxiedChannel , public nsIChildChannel + , public mozilla::net::PrivateBrowsingChannel { public: typedef ::nsIStreamListener nsIStreamListener; @@ -92,11 +94,15 @@ protected: void DoFailedAsyncOpen(const nsresult& statusCode); void DoDeleteSelf(); + NS_IMETHOD SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks); + NS_IMETHOD SetLoadGroup(nsILoadGroup* aLoadGroup); + friend class FTPStartRequestEvent; friend class FTPDataAvailableEvent; friend class FTPStopRequestEvent; friend class FTPFailedAsyncOpenEvent; friend class FTPDeleteSelfEvent; + friend class mozilla::net::PrivateBrowsingChannel; private: // Called asynchronously from Resume: continues any pending calls into client. diff --git a/netwerk/protocol/ftp/FTPChannelParent.cpp b/netwerk/protocol/ftp/FTPChannelParent.cpp index 45cea07875c..c60bb75ab34 100644 --- a/netwerk/protocol/ftp/FTPChannelParent.cpp +++ b/netwerk/protocol/ftp/FTPChannelParent.cpp @@ -102,6 +102,11 @@ FTPChannelParent::RecvAsyncOpen(const URIParams& aURI, if (loadContext.IsNotNull()) mLoadContext = new LoadContext(loadContext); + else if (loadContext.IsPrivateBitValid()) { + nsCOMPtr pbChannel = do_QueryInterface(chan); + if (pbChannel) + pbChannel->SetPrivate(loadContext.mUsePrivateBrowsing); + } rv = mChannel->AsyncOpen(this, nullptr); if (NS_FAILED(rv)) diff --git a/netwerk/protocol/ftp/nsFTPChannel.cpp b/netwerk/protocol/ftp/nsFTPChannel.cpp index 82bf787fdaa..1496657bd1a 100644 --- a/netwerk/protocol/ftp/nsFTPChannel.cpp +++ b/netwerk/protocol/ftp/nsFTPChannel.cpp @@ -45,12 +45,13 @@ PRTimeToSeconds(PRTime t_usec) //----------------------------------------------------------------------------- -NS_IMPL_ISUPPORTS_INHERITED4(nsFtpChannel, +NS_IMPL_ISUPPORTS_INHERITED5(nsFtpChannel, nsBaseChannel, nsIUploadChannel, nsIResumableChannel, nsIFTPChannel, - nsIProxiedChannel) + nsIProxiedChannel, + nsIPrivateBrowsingChannel) //----------------------------------------------------------------------------- @@ -217,3 +218,23 @@ nsFtpChannel::GetFTPEventSink(nsCOMPtr &aResult) } aResult = mFTPEventSink; } + +NS_IMETHODIMP +nsFtpChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks) +{ + if (!CanSetCallbacks()) { + return NS_ERROR_FAILURE; + } + + return nsBaseChannel::SetNotificationCallbacks(aCallbacks); +} + +NS_IMETHODIMP +nsFtpChannel::SetLoadGroup(nsILoadGroup * aLoadGroup) +{ + if (!CanSetLoadGroup()) { + return NS_ERROR_FAILURE; + } + + return nsBaseChannel::SetLoadGroup(aLoadGroup); +} diff --git a/netwerk/protocol/ftp/nsFTPChannel.h b/netwerk/protocol/ftp/nsFTPChannel.h index aa512eb9797..bc93871388e 100644 --- a/netwerk/protocol/ftp/nsFTPChannel.h +++ b/netwerk/protocol/ftp/nsFTPChannel.h @@ -29,19 +29,21 @@ #include "nsHashPropertyBag.h" #include "nsFtpProtocolHandler.h" #include "nsNetUtil.h" +#include "PrivateBrowsingChannel.h" class nsFtpChannel : public nsBaseChannel, public nsIFTPChannel, public nsIUploadChannel, public nsIResumableChannel, - public nsIProxiedChannel + public nsIProxiedChannel, + public mozilla::net::PrivateBrowsingChannel { public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIUPLOADCHANNEL NS_DECL_NSIRESUMABLECHANNEL NS_DECL_NSIPROXIEDCHANNEL - + nsFtpChannel(nsIURI *uri, nsIProxyInfo *pi) : mProxyInfo(pi) , mStartPos(0) @@ -94,6 +96,11 @@ protected: virtual bool GetStatusArg(nsresult status, nsString &statusArg); virtual void OnCallbacksChanged(); + NS_IMETHOD SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks); + NS_IMETHOD SetLoadGroup(nsILoadGroup* aLoadGroup); + + friend class mozilla::net::PrivateBrowsingChannel; + private: nsCOMPtr mProxyInfo; nsCOMPtr mFTPEventSink; diff --git a/netwerk/protocol/http/HttpBaseChannel.cpp b/netwerk/protocol/http/HttpBaseChannel.cpp index c28ebc862e6..15622e5d306 100644 --- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -48,7 +48,6 @@ HttpBaseChannel::HttpBaseChannel() , mTracingEnabled(true) , mTimingEnabled(false) , mAllowSpdy(true) - , mPrivateBrowsing(false) , mSuspendCount(0) { LOG(("Creating HttpBaseChannel @%x\n", this)); @@ -138,7 +137,7 @@ HttpBaseChannel::Init(nsIURI *aURI, // HttpBaseChannel::nsISupports //----------------------------------------------------------------------------- -NS_IMPL_ISUPPORTS_INHERITED9( HttpBaseChannel, +NS_IMPL_ISUPPORTS_INHERITED10(HttpBaseChannel, nsHashPropertyBag, nsIRequest, nsIChannel, @@ -148,7 +147,8 @@ NS_IMPL_ISUPPORTS_INHERITED9( HttpBaseChannel, nsIUploadChannel, nsIUploadChannel2, nsISupportsPriority, - nsITraceableChannel) + nsITraceableChannel, + nsIPrivateBrowsingChannel) //----------------------------------------------------------------------------- // HttpBaseChannel::nsIRequest @@ -189,6 +189,10 @@ HttpBaseChannel::GetLoadGroup(nsILoadGroup **aLoadGroup) NS_IMETHODIMP HttpBaseChannel::SetLoadGroup(nsILoadGroup *aLoadGroup) { + if (!CanSetLoadGroup()) { + return NS_ERROR_FAILURE; + } + mLoadGroup = aLoadGroup; mProgressSink = nullptr; mPrivateBrowsing = NS_UsePrivateBrowsing(this); @@ -269,10 +273,13 @@ HttpBaseChannel::GetNotificationCallbacks(nsIInterfaceRequestor **aCallbacks) NS_IMETHODIMP HttpBaseChannel::SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks) { + if (!CanSetCallbacks()) { + return NS_ERROR_FAILURE; + } + mCallbacks = aCallbacks; mProgressSink = nullptr; - // Will never change unless SetNotificationCallbacks called again, so cache mPrivateBrowsing = NS_UsePrivateBrowsing(this); return NS_OK; } diff --git a/netwerk/protocol/http/HttpBaseChannel.h b/netwerk/protocol/http/HttpBaseChannel.h index 971958c122e..a1fa503bad0 100644 --- a/netwerk/protocol/http/HttpBaseChannel.h +++ b/netwerk/protocol/http/HttpBaseChannel.h @@ -30,6 +30,7 @@ #include "nsILoadContext.h" #include "mozilla/net/NeckoCommon.h" #include "nsThreadUtils.h" +#include "PrivateBrowsingChannel.h" namespace mozilla { namespace net { @@ -50,6 +51,7 @@ class HttpBaseChannel : public nsHashPropertyBag , public nsISupportsPriority , public nsIResumableChannel , public nsITraceableChannel + , public PrivateBrowsingChannel { public: NS_DECL_ISUPPORTS_INHERITED @@ -208,6 +210,8 @@ protected: getter_AddRefs(aResult)); } + friend class PrivateBrowsingChannel; + nsCOMPtr mURI; nsCOMPtr mOriginalURI; nsCOMPtr mDocumentURI; @@ -263,7 +267,6 @@ protected: // True if timing collection is enabled uint32_t mTimingEnabled : 1; uint32_t mAllowSpdy : 1; - uint32_t mPrivateBrowsing : 1; // Current suspension depth for this channel object uint32_t mSuspendCount; diff --git a/netwerk/protocol/http/HttpChannelParent.cpp b/netwerk/protocol/http/HttpChannelParent.cpp index 211353074b8..3bbec203f53 100644 --- a/netwerk/protocol/http/HttpChannelParent.cpp +++ b/netwerk/protocol/http/HttpChannelParent.cpp @@ -152,6 +152,10 @@ HttpChannelParent::RecvAsyncOpen(const URIParams& aURI, mLoadContext = new LoadContext(loadContext, mTabParent->GetOwnerElement()); else mLoadContext = new LoadContext(loadContext); + } else if (loadContext.IsPrivateBitValid()) { + nsCOMPtr pbChannel = do_QueryInterface(mChannel); + if (pbChannel) + pbChannel->SetPrivate(loadContext.mUsePrivateBrowsing); } nsHttpChannel *httpChan = static_cast(mChannel.get()); diff --git a/netwerk/protocol/websocket/WebSocketChannelParent.cpp b/netwerk/protocol/websocket/WebSocketChannelParent.cpp index ce1e6c76ef6..8a659c7e5c3 100644 --- a/netwerk/protocol/websocket/WebSocketChannelParent.cpp +++ b/netwerk/protocol/websocket/WebSocketChannelParent.cpp @@ -67,6 +67,11 @@ WebSocketChannelParent::RecvAsyncOpen(const URIParams& aURI, if (loadContext.IsNotNull()) mLoadContext = new LoadContext(loadContext); +#ifdef DEBUG + else + // websocket channels cannot have a private bit override + MOZ_ASSERT(!loadContext.IsPrivateBitValid()); +#endif rv = mChannel->SetNotificationCallbacks(this); if (NS_FAILED(rv)) diff --git a/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp b/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp index ca8caf09eec..0a8da5ed31d 100644 --- a/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp +++ b/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp @@ -21,10 +21,11 @@ using namespace mozilla::ipc; namespace mozilla { namespace net { -NS_IMPL_ISUPPORTS3(WyciwygChannelChild, +NS_IMPL_ISUPPORTS4(WyciwygChannelChild, nsIRequest, nsIChannel, - nsIWyciwygChannel) + nsIWyciwygChannel, + nsIPrivateBrowsingChannel) WyciwygChannelChild::WyciwygChannelChild() @@ -384,6 +385,10 @@ WyciwygChannelChild::GetLoadGroup(nsILoadGroup * *aLoadGroup) NS_IMETHODIMP WyciwygChannelChild::SetLoadGroup(nsILoadGroup * aLoadGroup) { + if (!CanSetLoadGroup()) { + return NS_ERROR_FAILURE; + } + mLoadGroup = aLoadGroup; NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, @@ -466,6 +471,10 @@ WyciwygChannelChild::GetNotificationCallbacks(nsIInterfaceRequestor * *aCallback NS_IMETHODIMP WyciwygChannelChild::SetNotificationCallbacks(nsIInterfaceRequestor * aCallbacks) { + if (!CanSetCallbacks()) { + return NS_ERROR_FAILURE; + } + mCallbacks = aCallbacks; NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, diff --git a/netwerk/protocol/wyciwyg/WyciwygChannelChild.h b/netwerk/protocol/wyciwyg/WyciwygChannelChild.h index e5f3712fae9..e654edd6a58 100644 --- a/netwerk/protocol/wyciwyg/WyciwygChannelChild.h +++ b/netwerk/protocol/wyciwyg/WyciwygChannelChild.h @@ -10,6 +10,7 @@ #include "nsIWyciwygChannel.h" #include "nsIChannel.h" #include "nsIProgressEventSink.h" +#include "PrivateBrowsingChannel.h" namespace mozilla { namespace net { @@ -34,6 +35,7 @@ enum WyciwygChannelChildState { // Header file contents class WyciwygChannelChild : public PWyciwygChannelChild , public nsIWyciwygChannel + , public PrivateBrowsingChannel { public: NS_DECL_ISUPPORTS @@ -72,6 +74,8 @@ protected: void OnStopRequest(const nsresult& statusCode); void CancelEarly(const nsresult& statusCode); + friend class PrivateBrowsingChannel; + private: nsresult mStatus; bool mIsPending; diff --git a/netwerk/protocol/wyciwyg/WyciwygChannelParent.cpp b/netwerk/protocol/wyciwyg/WyciwygChannelParent.cpp index c8a4b0e2cb2..e0057a154ed 100644 --- a/netwerk/protocol/wyciwyg/WyciwygChannelParent.cpp +++ b/netwerk/protocol/wyciwyg/WyciwygChannelParent.cpp @@ -109,6 +109,11 @@ WyciwygChannelParent::RecvAsyncOpen(const URIParams& aOriginal, if (loadContext.IsNotNull()) mLoadContext = new LoadContext(loadContext); + else if (loadContext.IsPrivateBitValid()) { + nsCOMPtr pbChannel = do_QueryInterface(mChannel); + if (pbChannel) + pbChannel->SetPrivate(loadContext.mUsePrivateBrowsing); + } rv = mChannel->AsyncOpen(this, nullptr); if (NS_FAILED(rv)) diff --git a/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp b/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp index b6988297911..f687eaea748 100644 --- a/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp +++ b/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp @@ -83,7 +83,6 @@ nsWyciwygChannel::nsWyciwygChannel() mIsPending(false), mCharsetAndSourceSet(false), mNeedToWriteCharset(false), - mPrivateBrowsing(false), mCharsetSource(kCharsetUninitialized), mContentLength(-1), mLoadFlags(LOAD_NORMAL) @@ -94,13 +93,14 @@ nsWyciwygChannel::~nsWyciwygChannel() { } -NS_IMPL_THREADSAFE_ISUPPORTS6(nsWyciwygChannel, +NS_IMPL_THREADSAFE_ISUPPORTS7(nsWyciwygChannel, nsIChannel, nsIRequest, nsIStreamListener, nsIRequestObserver, - nsICacheListener, - nsIWyciwygChannel) + nsICacheListener, + nsIWyciwygChannel, + nsIPrivateBrowsingChannel) nsresult nsWyciwygChannel::Init(nsIURI* uri) @@ -188,11 +188,16 @@ nsWyciwygChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup) NS_IMETHODIMP nsWyciwygChannel::SetLoadGroup(nsILoadGroup* aLoadGroup) { + if (!CanSetLoadGroup()) { + return NS_ERROR_FAILURE; + } + mLoadGroup = aLoadGroup; NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, NS_GET_IID(nsIProgressEventSink), getter_AddRefs(mProgressSink)); + mPrivateBrowsing = NS_UsePrivateBrowsing(this); return NS_OK; } @@ -266,13 +271,16 @@ nsWyciwygChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aCallbacks) NS_IMETHODIMP nsWyciwygChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks) { + if (!CanSetCallbacks()) { + return NS_ERROR_FAILURE; + } + mCallbacks = aNotificationCallbacks; NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, NS_GET_IID(nsIProgressEventSink), getter_AddRefs(mProgressSink)); - // Will never change unless SetNotificationCallbacks called again, so cache mPrivateBrowsing = NS_UsePrivateBrowsing(this); return NS_OK; diff --git a/netwerk/protocol/wyciwyg/nsWyciwygChannel.h b/netwerk/protocol/wyciwyg/nsWyciwygChannel.h index b91458ab990..e5894ad41fb 100644 --- a/netwerk/protocol/wyciwyg/nsWyciwygChannel.h +++ b/netwerk/protocol/wyciwyg/nsWyciwygChannel.h @@ -26,6 +26,7 @@ #include "nsIEventTarget.h" #include "nsILoadContext.h" #include "nsNetUtil.h" +#include "PrivateBrowsingChannel.h" extern PRLogModuleInfo * gWyciwygLog; @@ -33,7 +34,8 @@ extern PRLogModuleInfo * gWyciwygLog; class nsWyciwygChannel: public nsIWyciwygChannel, public nsIStreamListener, - public nsICacheListener + public nsICacheListener, + public mozilla::net::PrivateBrowsingChannel { public: NS_DECL_ISUPPORTS @@ -68,11 +70,12 @@ protected: void NotifyListener(); bool IsOnCacheIOThread(); + friend class mozilla::net::PrivateBrowsingChannel; + nsresult mStatus; bool mIsPending; bool mCharsetAndSourceSet; bool mNeedToWriteCharset; - bool mPrivateBrowsing; int32_t mCharsetSource; nsCString mCharset; int32_t mContentLength; diff --git a/netwerk/test/unit/head_cache.js b/netwerk/test/unit/head_cache.js index 5bd964fe764..95ecb4402e0 100644 --- a/netwerk/test/unit/head_cache.js +++ b/netwerk/test/unit/head_cache.js @@ -55,3 +55,25 @@ function syncWithCacheIOThread(callback) callback(); }); } + +function get_device_entry_count(device) { + var cs = get_cache_service(); + var entry_count = -1; + + var visitor = { + visitDevice: function (deviceID, deviceInfo) { + if (device == deviceID) + entry_count = deviceInfo.entryCount; + return false; + }, + visitEntry: function (deviceID, entryInfo) { + do_throw("nsICacheVisitor.visitEntry should not be called " + + "when checking the availability of devices"); + } + }; + + // get the device entry count + cs.visitEntries(visitor); + + return entry_count; +} diff --git a/netwerk/test/unit/test_bug248970_cache.js b/netwerk/test/unit/test_bug248970_cache.js index 83aef245bdb..4d4bc20a315 100644 --- a/netwerk/test/unit/test_bug248970_cache.js +++ b/netwerk/test/unit/test_bug248970_cache.js @@ -52,28 +52,6 @@ function check_devices_available(devices) { } } -function get_device_entry_count(device) { - var cs = get_cache_service(); - var entry_count = -1; - - var visitor = { - visitDevice: function (deviceID, deviceInfo) { - if (device == deviceID) - entry_count = deviceInfo.entryCount; - return false; - }, - visitEntry: function (deviceID, entryInfo) { - do_throw("nsICacheVisitor.visitEntry should not be called " + - "when checking the availability of devices"); - } - }; - - // get the device entry count - cs.visitEntries(visitor); - - return entry_count; -} - function make_input_stream_scriptable(input) { var wrapper = Cc["@mozilla.org/scriptableinputstream;1"]. createInstance(Ci.nsIScriptableInputStream); diff --git a/netwerk/test/unit/test_private_channel.js b/netwerk/test/unit/test_private_channel.js new file mode 100644 index 00000000000..81a53050c58 --- /dev/null +++ b/netwerk/test/unit/test_private_channel.js @@ -0,0 +1,50 @@ +// +// Private channel test +// + +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; +const Cr = Components.results; + +Cu.import("resource://testing-common/httpd.js"); + +var httpserver = new HttpServer(); +var testpath = "/simple"; + +function run_test() { + // Simulate a profile dir for xpcshell + do_get_profile(); + + // Start off with an empty cache + evict_cache_entries(); + + httpserver.registerPathHandler(testpath, serverHandler); + httpserver.start(4444); + + var channel = setupChannel(testpath); + + channel.QueryInterface(Ci.nsIPrivateBrowsingChannel); + channel.setPrivate(true); + + channel.asyncOpen(new ChannelListener(checkRequest, channel), null); + + do_test_pending(); +} + +function setupChannel(path) { + var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); + return chan = ios.newChannel("http://localhost:4444" + path, "", null) + .QueryInterface(Ci.nsIHttpChannel); +} + +function serverHandler(metadata, response) { + response.write("HTTP/1.0 200 OK\r\n\r\nfoobar"); + respose.finish(); +} + +function checkRequest(request, data, context) { + do_check_eq(get_device_entry_count("disk"), 0); + do_check_eq(get_device_entry_count("memory"), 1); + httpserver.stop(do_test_finished); +} diff --git a/netwerk/test/unit/xpcshell.ini b/netwerk/test/unit/xpcshell.ini index 138603db10c..91d2e39c873 100644 --- a/netwerk/test/unit/xpcshell.ini +++ b/netwerk/test/unit/xpcshell.ini @@ -155,6 +155,7 @@ skip-if = os == "win" [test_permmgr.js] [test_plaintext_sniff.js] [test_post.js] +[test_private_channel.js] [test_progress.js] [test_protocolproxyservice.js] [test_proxy-failover_canceled.js]