author | Ehsan Akhgari <ehsan@mozilla.com> |
Tue, 04 Sep 2012 20:37:45 -0400 | |
changeset 107260 | 83a7ea5398a988ff151d06f65b4fc852328e30e8 |
parent 107259 | 7096242b4edde22375d8511d2386d745a429f1ea |
child 107261 | 4dc194e18570657487241780d77fcdd5b4be7dce |
push id | 14941 |
push user | eakhgari@mozilla.com |
push date | Mon, 17 Sep 2012 18:42:43 +0000 |
treeherder | mozilla-inbound@89027f6e7662 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jduell |
bugs | 741059 |
milestone | 18.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/docshell/base/SerializedLoadContext.cpp +++ b/docshell/base/SerializedLoadContext.cpp @@ -16,36 +16,52 @@ SerializedLoadContext::SerializedLoadCon Init(aLoadContext); } SerializedLoadContext::SerializedLoadContext(nsIChannel* aChannel) { nsCOMPtr<nsILoadContext> 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<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(aChannel); + if (pbChannel && + NS_SUCCEEDED(pbChannel->IsPrivateModeOverriden(&isPrivate, &isOverriden)) && + isOverriden) { + mUsePrivateBrowsing = isPrivate; + mIsPrivateBitValid = true; + } + } } SerializedLoadContext::SerializedLoadContext(nsIWebSocketChannel* aChannel) { nsCOMPtr<nsILoadContext> loadContext; NS_QueryNotificationCallbacks(aChannel, loadContext); Init(loadContext); } void 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; mUsePrivateBrowsing = false; mAppId = 0; mIsInBrowserElement = false; } }
--- a/docshell/base/SerializedLoadContext.h +++ b/docshell/base/SerializedLoadContext.h @@ -31,23 +31,31 @@ public: } SerializedLoadContext(nsILoadContext* aLoadContext); SerializedLoadContext(nsIChannel* aChannel); SerializedLoadContext(nsIWebSocketChannel* aChannel); 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; uint32_t mAppId; }; // Function to serialize over IPDL template<>
--- a/netwerk/base/public/Makefile.in +++ b/netwerk/base/public/Makefile.in @@ -53,16 +53,17 @@ XPIDLSRCS = \ nsIInputStreamPump.idl \ nsIInputStreamChannel.idl \ nsIIOService2.idl \ nsIMIMEInputStream.idl \ nsINetAddr.idl \ nsINetworkLinkService.idl \ nsIPermission.idl \ nsIPermissionManager.idl \ + nsIPrivateBrowsingChannel.idl \ nsIPrivateBrowsingService.idl \ nsIProgressEventSink.idl \ nsIPrompt.idl \ nsIProtocolProxyService.idl \ nsIProtocolProxyService2.idl \ nsIProtocolProxyFilter.idl \ nsIProtocolProxyCallback.idl \ nsIProxiedProtocolHandler.idl \
new file mode 100644 --- /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); +};
--- a/netwerk/base/public/nsNetUtil.h +++ b/netwerk/base/public/nsNetUtil.h @@ -71,16 +71,17 @@ #include "nsIChannelEventSink.h" #include "nsIChannelPolicy.h" #include "nsISocketProviderService.h" #include "nsISocketProvider.h" #include "nsIRedirectChannelRegistrar.h" #include "nsIMIMEHeaderParam.h" #include "nsILoadContext.h" #include "mozilla/Services.h" +#include "nsIPrivateBrowsingChannel.h" #ifdef MOZILLA_INTERNAL_API inline already_AddRefed<nsIIOService> do_GetIOService(nsresult* error = 0) { already_AddRefed<nsIIOService> ret = mozilla::services::GetIOService(); if (error) @@ -1320,16 +1321,24 @@ NS_QueryNotificationCallbacks(nsIInterfa /** * Returns true if channel is using Private Browsing, or false if not. * Returns false if channel's callbacks don't implement nsILoadContext. */ inline bool NS_UsePrivateBrowsing(nsIChannel *channel) { + bool isPrivate = false; + bool isOverriden = false; + nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(channel); + if (pbChannel && + NS_SUCCEEDED(pbChannel->IsPrivateModeOverriden(&isPrivate, &isOverriden)) && + isOverriden) { + return isPrivate; + } nsCOMPtr<nsILoadContext> loadContext; NS_QueryNotificationCallbacks(channel, loadContext); return loadContext && loadContext->UsePrivateBrowsing(); } /** * Gets AppId and isInBrowserElement from channel's nsILoadContext. * Returns false if error or channel's callbacks don't implement nsILoadContext.
new file mode 100644 --- /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 Channel> +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<Channel*>(this)->mLoadGroup; + nsCOMPtr<nsILoadContext> loadContext; + if (!loadGroup) { + NS_QueryNotificationCallbacks(static_cast<Channel*>(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 +
--- a/netwerk/protocol/ftp/FTPChannelChild.cpp +++ b/netwerk/protocol/ftp/FTPChannelChild.cpp @@ -64,23 +64,24 @@ FTPChannelChild::ReleaseIPDLReference() mIPCOpen = false; Release(); } //----------------------------------------------------------------------------- // FTPChannelChild::nsISupports //----------------------------------------------------------------------------- -NS_IMPL_ISUPPORTS_INHERITED5(FTPChannelChild, +NS_IMPL_ISUPPORTS_INHERITED6(FTPChannelChild, nsBaseChannel, nsIFTPChannel, nsIUploadChannel, nsIResumableChannel, nsIProxiedChannel, - nsIChildChannel) + nsIChildChannel, + nsIPrivateBrowsingChannel) //----------------------------------------------------------------------------- NS_IMETHODIMP FTPChannelChild::GetLastModifiedTime(PRTime* lastModifiedTime) { *lastModifiedTime = mLastModifiedTime; return NS_OK; @@ -541,11 +542,31 @@ FTPChannelChild::CompleteRedirectSetup(n mLoadGroup->AddRequest(this, nullptr); // We already have an open IPDL connection to the parent. If on-modify-request // listeners or load group observers canceled us, let the parent handle it // and send it back to us naturally. 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
--- a/netwerk/protocol/ftp/FTPChannelChild.h +++ b/netwerk/protocol/ftp/FTPChannelChild.h @@ -13,32 +13,34 @@ #include "nsBaseChannel.h" #include "nsIFTPChannel.h" #include "nsIUploadChannel.h" #include "nsIProxiedChannel.h" #include "nsIResumableChannel.h" #include "nsIChildChannel.h" #include "nsIStreamListener.h" +#include "PrivateBrowsingChannel.h" namespace mozilla { namespace net { // This class inherits logic from nsBaseChannel that is not needed for an // e10s child channel, but it works. At some point we could slice up // nsBaseChannel and have a new class that has only the common logic for // nsFTPChannel/FTPChannelChild. class FTPChannelChild : public PFTPChannelChild , public nsBaseChannel , public nsIFTPChannel , public nsIUploadChannel , public nsIResumableChannel , public nsIProxiedChannel , public nsIChildChannel + , public mozilla::net::PrivateBrowsingChannel<FTPChannelChild> { public: typedef ::nsIStreamListener nsIStreamListener; NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIFTPCHANNEL NS_DECL_NSIUPLOADCHANNEL NS_DECL_NSIRESUMABLECHANNEL @@ -87,21 +89,25 @@ protected: const URIParams& aURI); void DoOnDataAvailable(const nsCString& data, const uint64_t& offset, const uint32_t& count); void DoOnStopRequest(const nsresult& statusCode); 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<FTPChannelChild>; private: // Called asynchronously from Resume: continues any pending calls into client. void CompleteResume(); nsresult AsyncCall(void (FTPChannelChild::*funcPtr)(), nsRunnableMethod<FTPChannelChild> **retval = nullptr); nsCOMPtr<nsIInputStream> mUploadStream;
--- a/netwerk/protocol/ftp/FTPChannelParent.cpp +++ b/netwerk/protocol/ftp/FTPChannelParent.cpp @@ -97,16 +97,21 @@ FTPChannelParent::RecvAsyncOpen(const UR } rv = mChannel->ResumeAt(aStartPos, aEntityID); if (NS_FAILED(rv)) return SendFailedAsyncOpen(rv); if (loadContext.IsNotNull()) mLoadContext = new LoadContext(loadContext); + else if (loadContext.IsPrivateBitValid()) { + nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(chan); + if (pbChannel) + pbChannel->SetPrivate(loadContext.mUsePrivateBrowsing); + } rv = mChannel->AsyncOpen(this, nullptr); if (NS_FAILED(rv)) return SendFailedAsyncOpen(rv); return true; }
--- a/netwerk/protocol/ftp/nsFTPChannel.cpp +++ b/netwerk/protocol/ftp/nsFTPChannel.cpp @@ -40,22 +40,23 @@ PRTimeToSeconds(PRTime t_usec) // the other for the data channel. The command channel is the first // connection made and is used to negotiate the second, data, channel. // The data channel is driven by the command channel and is either // initiated by the server (PORT command) or by the client (PASV command). // Client initiation is the most common case and is attempted first. //----------------------------------------------------------------------------- -NS_IMPL_ISUPPORTS_INHERITED4(nsFtpChannel, +NS_IMPL_ISUPPORTS_INHERITED5(nsFtpChannel, nsBaseChannel, nsIUploadChannel, nsIResumableChannel, nsIFTPChannel, - nsIProxiedChannel) + nsIProxiedChannel, + nsIPrivateBrowsingChannel) //----------------------------------------------------------------------------- NS_IMETHODIMP nsFtpChannel::SetUploadStream(nsIInputStream *stream, const nsACString &contentType, int32_t contentLength) { @@ -212,8 +213,28 @@ nsFtpChannel::GetFTPEventSink(nsCOMPtr<n nsCOMPtr<nsIFTPEventSink> ftpSink; GetCallback(ftpSink); if (ftpSink) { mFTPEventSink = new FTPEventSinkProxy(ftpSink); } } 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); +}
--- a/netwerk/protocol/ftp/nsFTPChannel.h +++ b/netwerk/protocol/ftp/nsFTPChannel.h @@ -24,29 +24,31 @@ #include "nsIFTPChannel.h" #include "nsIUploadChannel.h" #include "nsIProxyInfo.h" #include "nsIProxiedChannel.h" #include "nsIResumableChannel.h" #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<nsFtpChannel> { public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIUPLOADCHANNEL NS_DECL_NSIRESUMABLECHANNEL NS_DECL_NSIPROXIEDCHANNEL - + nsFtpChannel(nsIURI *uri, nsIProxyInfo *pi) : mProxyInfo(pi) , mStartPos(0) , mResumeRequested(false) , mLastModifiedTime(0) { SetURI(uri); } @@ -89,16 +91,21 @@ public: protected: virtual ~nsFtpChannel() {} virtual nsresult OpenContentStream(bool async, nsIInputStream **result, nsIChannel** channel); 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<nsFtpChannel>; + private: nsCOMPtr<nsIProxyInfo> mProxyInfo; nsCOMPtr<nsIFTPEventSink> mFTPEventSink; nsCOMPtr<nsIInputStream> mUploadStream; uint64_t mStartPos; nsCString mEntityID; bool mResumeRequested; PRTime mLastModifiedTime;
--- a/netwerk/protocol/http/HttpBaseChannel.cpp +++ b/netwerk/protocol/http/HttpBaseChannel.cpp @@ -43,17 +43,16 @@ HttpBaseChannel::HttpBaseChannel() , mUploadStreamHasHeaders(false) , mInheritApplicationCache(true) , mChooseApplicationCache(false) , mLoadedFromApplicationCache(false) , mChannelIsForDownload(false) , mTracingEnabled(true) , mTimingEnabled(false) , mAllowSpdy(true) - , mPrivateBrowsing(false) , mSuspendCount(0) { LOG(("Creating HttpBaseChannel @%x\n", this)); // grab a reference to the handler to ensure that it doesn't go away. NS_ADDREF(gHttpHandler); // Subfields of unions cannot be targeted in an initializer list @@ -133,27 +132,28 @@ HttpBaseChannel::Init(nsIURI *aURI, return rv; } //----------------------------------------------------------------------------- // HttpBaseChannel::nsISupports //----------------------------------------------------------------------------- -NS_IMPL_ISUPPORTS_INHERITED9( HttpBaseChannel, +NS_IMPL_ISUPPORTS_INHERITED10(HttpBaseChannel, nsHashPropertyBag, nsIRequest, nsIChannel, nsIEncodedChannel, nsIHttpChannel, nsIHttpChannelInternal, nsIUploadChannel, nsIUploadChannel2, nsISupportsPriority, - nsITraceableChannel) + nsITraceableChannel, + nsIPrivateBrowsingChannel) //----------------------------------------------------------------------------- // HttpBaseChannel::nsIRequest //----------------------------------------------------------------------------- NS_IMETHODIMP HttpBaseChannel::GetName(nsACString& aName) { @@ -184,16 +184,20 @@ HttpBaseChannel::GetLoadGroup(nsILoadGro *aLoadGroup = mLoadGroup; NS_IF_ADDREF(*aLoadGroup); return NS_OK; } NS_IMETHODIMP HttpBaseChannel::SetLoadGroup(nsILoadGroup *aLoadGroup) { + if (!CanSetLoadGroup()) { + return NS_ERROR_FAILURE; + } + mLoadGroup = aLoadGroup; mProgressSink = nullptr; mPrivateBrowsing = NS_UsePrivateBrowsing(this); return NS_OK; } NS_IMETHODIMP HttpBaseChannel::GetLoadFlags(nsLoadFlags *aLoadFlags) @@ -264,20 +268,23 @@ HttpBaseChannel::GetNotificationCallback *aCallbacks = mCallbacks; NS_IF_ADDREF(*aCallbacks); return NS_OK; } 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; } NS_IMETHODIMP HttpBaseChannel::GetContentType(nsACString& aContentType) { if (!mResponseHead) {
--- a/netwerk/protocol/http/HttpBaseChannel.h +++ b/netwerk/protocol/http/HttpBaseChannel.h @@ -25,16 +25,17 @@ #include "nsIStringEnumerator.h" #include "nsISupportsPriority.h" #include "nsIApplicationCache.h" #include "nsIResumableChannel.h" #include "nsITraceableChannel.h" #include "nsILoadContext.h" #include "mozilla/net/NeckoCommon.h" #include "nsThreadUtils.h" +#include "PrivateBrowsingChannel.h" namespace mozilla { namespace net { /* * This class is a partial implementation of nsIHttpChannel. It contains code * shared by nsHttpChannel and HttpChannelChild. * - Note that this class has nothing to do with nsBaseChannel, which is an @@ -45,16 +46,17 @@ class HttpBaseChannel : public nsHashPro , public nsIEncodedChannel , public nsIHttpChannel , public nsIHttpChannelInternal , public nsIUploadChannel , public nsIUploadChannel2 , public nsISupportsPriority , public nsIResumableChannel , public nsITraceableChannel + , public PrivateBrowsingChannel<HttpBaseChannel> { public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIUPLOADCHANNEL NS_DECL_NSIUPLOADCHANNEL2 NS_DECL_NSITRACEABLECHANNEL HttpBaseChannel(); @@ -203,16 +205,18 @@ protected: template <class T> void GetCallback(nsCOMPtr<T> &aResult) { NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, NS_GET_TEMPLATE_IID(T), getter_AddRefs(aResult)); } + friend class PrivateBrowsingChannel<HttpBaseChannel>; + nsCOMPtr<nsIURI> mURI; nsCOMPtr<nsIURI> mOriginalURI; nsCOMPtr<nsIURI> mDocumentURI; nsCOMPtr<nsIStreamListener> mListener; nsCOMPtr<nsISupports> mListenerContext; nsCOMPtr<nsILoadGroup> mLoadGroup; nsCOMPtr<nsISupports> mOwner; nsCOMPtr<nsIInterfaceRequestor> mCallbacks; @@ -258,17 +262,16 @@ protected: uint32_t mInheritApplicationCache : 1; uint32_t mChooseApplicationCache : 1; uint32_t mLoadedFromApplicationCache : 1; uint32_t mChannelIsForDownload : 1; uint32_t mTracingEnabled : 1; // 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; nsAutoPtr<nsTArray<nsCString> > mRedirectedCachekeys; }; // Share some code while working around C++'s absurd inability to handle casting
--- a/netwerk/protocol/http/HttpChannelParent.cpp +++ b/netwerk/protocol/http/HttpChannelParent.cpp @@ -147,16 +147,20 @@ HttpChannelParent::RecvAsyncOpen(const U if (NS_FAILED(rv)) return SendFailedAsyncOpen(rv); if (loadContext.IsNotNull()) { if (mTabParent) mLoadContext = new LoadContext(loadContext, mTabParent->GetOwnerElement()); else mLoadContext = new LoadContext(loadContext); + } else if (loadContext.IsPrivateBitValid()) { + nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(mChannel); + if (pbChannel) + pbChannel->SetPrivate(loadContext.mUsePrivateBrowsing); } nsHttpChannel *httpChan = static_cast<nsHttpChannel *>(mChannel.get()); if (doResumeAt) httpChan->ResumeAt(startPos, entityID); if (originalUri)
--- a/netwerk/protocol/websocket/WebSocketChannelParent.cpp +++ b/netwerk/protocol/websocket/WebSocketChannelParent.cpp @@ -62,16 +62,21 @@ WebSocketChannelParent::RecvAsyncOpen(co mChannel = do_CreateInstance("@mozilla.org/network/protocol;1?name=ws", &rv); } if (NS_FAILED(rv)) goto fail; 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)) goto fail; rv = mChannel->SetProtocol(aProtocol); if (NS_FAILED(rv)) goto fail;
--- a/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp +++ b/netwerk/protocol/wyciwyg/WyciwygChannelChild.cpp @@ -16,20 +16,21 @@ #include "nsILoadContext.h" #include "mozilla/ipc/URIUtils.h" using namespace mozilla::ipc; namespace mozilla { namespace net { -NS_IMPL_ISUPPORTS3(WyciwygChannelChild, +NS_IMPL_ISUPPORTS4(WyciwygChannelChild, nsIRequest, nsIChannel, - nsIWyciwygChannel) + nsIWyciwygChannel, + nsIPrivateBrowsingChannel) WyciwygChannelChild::WyciwygChannelChild() : mStatus(NS_OK) , mIsPending(false) , mCanceled(false) , mLoadFlags(LOAD_NORMAL) , mContentLength(-1) @@ -379,16 +380,20 @@ WyciwygChannelChild::GetLoadGroup(nsILoa { *aLoadGroup = mLoadGroup; NS_IF_ADDREF(*aLoadGroup); return NS_OK; } NS_IMETHODIMP WyciwygChannelChild::SetLoadGroup(nsILoadGroup * aLoadGroup) { + if (!CanSetLoadGroup()) { + return NS_ERROR_FAILURE; + } + mLoadGroup = aLoadGroup; NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, NS_GET_IID(nsIProgressEventSink), getter_AddRefs(mProgressSink)); return NS_OK; } @@ -461,16 +466,20 @@ WyciwygChannelChild::GetNotificationCall { *aCallbacks = mCallbacks; NS_IF_ADDREF(*aCallbacks); return NS_OK; } NS_IMETHODIMP WyciwygChannelChild::SetNotificationCallbacks(nsIInterfaceRequestor * aCallbacks) { + if (!CanSetCallbacks()) { + return NS_ERROR_FAILURE; + } + mCallbacks = aCallbacks; NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, NS_GET_IID(nsIProgressEventSink), getter_AddRefs(mProgressSink)); return NS_OK; }
--- a/netwerk/protocol/wyciwyg/WyciwygChannelChild.h +++ b/netwerk/protocol/wyciwyg/WyciwygChannelChild.h @@ -5,16 +5,17 @@ #ifndef mozilla_net_WyciwygChannelChild_h #define mozilla_net_WyciwygChannelChild_h #include "mozilla/net/PWyciwygChannelChild.h" #include "mozilla/net/ChannelEventQueue.h" #include "nsIWyciwygChannel.h" #include "nsIChannel.h" #include "nsIProgressEventSink.h" +#include "PrivateBrowsingChannel.h" namespace mozilla { namespace net { // TODO: replace with IPDL states enum WyciwygChannelChildState { WCC_NEW, WCC_INIT, @@ -29,16 +30,17 @@ enum WyciwygChannelChildState { WCC_ONWRITE, WCC_ONCLOSED }; // Header file contents class WyciwygChannelChild : public PWyciwygChannelChild , public nsIWyciwygChannel + , public PrivateBrowsingChannel<WyciwygChannelChild> { public: NS_DECL_ISUPPORTS NS_DECL_NSIREQUEST NS_DECL_NSICHANNEL NS_DECL_NSIWYCIWYGCHANNEL WyciwygChannelChild(); @@ -67,16 +69,18 @@ protected: const int32_t& source, const nsCString& charset, const nsCString& securityInfo); void OnDataAvailable(const nsCString& data, const uint64_t& offset); void OnStopRequest(const nsresult& statusCode); void CancelEarly(const nsresult& statusCode); + friend class PrivateBrowsingChannel<WyciwygChannelChild>; + private: nsresult mStatus; bool mIsPending; bool mCanceled; uint32_t mLoadFlags; int32_t mContentLength; int32_t mCharsetSource; nsCString mCharset;
--- a/netwerk/protocol/wyciwyg/WyciwygChannelParent.cpp +++ b/netwerk/protocol/wyciwyg/WyciwygChannelParent.cpp @@ -104,16 +104,21 @@ WyciwygChannelParent::RecvAsyncOpen(cons return SendCancelEarly(rv); rv = mChannel->SetLoadFlags(aLoadFlags); if (NS_FAILED(rv)) return SendCancelEarly(rv); if (loadContext.IsNotNull()) mLoadContext = new LoadContext(loadContext); + else if (loadContext.IsPrivateBitValid()) { + nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(mChannel); + if (pbChannel) + pbChannel->SetPrivate(loadContext.mUsePrivateBrowsing); + } rv = mChannel->AsyncOpen(this, nullptr); if (NS_FAILED(rv)) return SendCancelEarly(rv); return true; }
--- a/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp +++ b/netwerk/protocol/wyciwyg/nsWyciwygChannel.cpp @@ -78,34 +78,34 @@ private: // nsWyciwygChannel methods nsWyciwygChannel::nsWyciwygChannel() : mStatus(NS_OK), mIsPending(false), mCharsetAndSourceSet(false), mNeedToWriteCharset(false), - mPrivateBrowsing(false), mCharsetSource(kCharsetUninitialized), mContentLength(-1), mLoadFlags(LOAD_NORMAL) { } 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) { NS_ENSURE_ARG_POINTER(uri); nsresult rv; @@ -183,21 +183,26 @@ nsWyciwygChannel::GetLoadGroup(nsILoadGr *aLoadGroup = mLoadGroup; NS_IF_ADDREF(*aLoadGroup); return NS_OK; } 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; } NS_IMETHODIMP nsWyciwygChannel::SetLoadFlags(uint32_t aLoadFlags) { mLoadFlags = aLoadFlags; return NS_OK; @@ -261,23 +266,26 @@ nsWyciwygChannel::GetNotificationCallbac *aCallbacks = mCallbacks.get(); NS_IF_ADDREF(*aCallbacks); return NS_OK; } 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; } NS_IMETHODIMP nsWyciwygChannel::GetSecurityInfo(nsISupports * *aSecurityInfo) {
--- a/netwerk/protocol/wyciwyg/nsWyciwygChannel.h +++ b/netwerk/protocol/wyciwyg/nsWyciwygChannel.h @@ -21,24 +21,26 @@ #include "nsIProgressEventSink.h" #include "nsIStreamListener.h" #include "nsICacheListener.h" #include "nsICacheEntryDescriptor.h" #include "nsIURI.h" #include "nsIEventTarget.h" #include "nsILoadContext.h" #include "nsNetUtil.h" +#include "PrivateBrowsingChannel.h" extern PRLogModuleInfo * gWyciwygLog; //----------------------------------------------------------------------------- class nsWyciwygChannel: public nsIWyciwygChannel, public nsIStreamListener, - public nsICacheListener + public nsICacheListener, + public mozilla::net::PrivateBrowsingChannel<nsWyciwygChannel> { public: NS_DECL_ISUPPORTS NS_DECL_NSIREQUEST NS_DECL_NSICHANNEL NS_DECL_NSIWYCIWYGCHANNEL NS_DECL_NSIREQUESTOBSERVER NS_DECL_NSISTREAMLISTENER @@ -63,21 +65,22 @@ protected: nsresult OpenCacheEntry(const nsACString & aCacheKey, nsCacheAccessMode aWriteAccess); void WriteCharsetAndSourceToCache(int32_t aSource, const nsCString& aCharset); void NotifyListener(); bool IsOnCacheIOThread(); + friend class mozilla::net::PrivateBrowsingChannel<nsWyciwygChannel>; + nsresult mStatus; bool mIsPending; bool mCharsetAndSourceSet; bool mNeedToWriteCharset; - bool mPrivateBrowsing; int32_t mCharsetSource; nsCString mCharset; int32_t mContentLength; uint32_t mLoadFlags; nsCOMPtr<nsIURI> mURI; nsCOMPtr<nsIURI> mOriginalURI; nsCOMPtr<nsISupports> mOwner; nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
--- a/netwerk/test/unit/head_cache.js +++ b/netwerk/test/unit/head_cache.js @@ -50,8 +50,30 @@ function syncWithCacheIOThread(callback) "HTTP", Components.interfaces.nsICache.STORE_ANYWHERE, Components.interfaces.nsICache.ACCESS_READ, function(status, entry) { do_check_eq(status, Components.results.NS_ERROR_CACHE_KEY_NOT_FOUND); 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; +}
--- a/netwerk/test/unit/test_bug248970_cache.js +++ b/netwerk/test/unit/test_bug248970_cache.js @@ -47,38 +47,16 @@ function check_devices_available(devices // see if any extra devices have been found if (found_devices.length > devices.length) { do_throw("Expected to find these devices: [" + devices.join(", ") + "], but instead got: [" + found_devices.join(", ") + "]"); } } -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); wrapper.init(input); return wrapper; } const entries = [
new file mode 100644 --- /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); +}
--- a/netwerk/test/unit/xpcshell.ini +++ b/netwerk/test/unit/xpcshell.ini @@ -150,16 +150,17 @@ skip-if = os == "android" # Bug 732363: test fails on windows for unknown reasons. skip-if = os == "win" [test_nojsredir.js] [test_offline_status.js] [test_parse_content_type.js] [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] [test_proxy-failover_passing.js] [test_proxy-replace_canceled.js] [test_proxy-replace_passing.js] [test_psl.js] [test_range_requests.js]