Bug 804655 - Part 2: Wrap up interface aggregator callbacks with a target thread on which they should be released. r=mayhemer

This commit is contained in:
Josh Matthews 2012-11-14 16:00:44 +00:00
parent e822f81d3d
commit 5faa109e12
24 changed files with 119 additions and 121 deletions

View File

@ -498,12 +498,12 @@
var connector = var connector =
Services.io.QueryInterface(Components.interfaces.nsISpeculativeConnect); Services.io.QueryInterface(Components.interfaces.nsISpeculativeConnect);
var searchURI = engine.getSubmission("dummy").uri; var searchURI = engine.getSubmission("dummy").uri;
connector.speculativeConnect(searchURI, null, null); connector.speculativeConnect(searchURI, null);
if (engine.supportsResponseType(SUGGEST_TYPE)) { if (engine.supportsResponseType(SUGGEST_TYPE)) {
var suggestURI = engine.getSubmission("dummy", SUGGEST_TYPE).uri; var suggestURI = engine.getSubmission("dummy", SUGGEST_TYPE).uri;
if (suggestURI.prePath != searchURI.prePath) if (suggestURI.prePath != searchURI.prePath)
connector.speculativeConnect(suggestURI, null, null); connector.speculativeConnect(suggestURI, null);
} }
]]></handler> ]]></handler>
</handlers> </handlers>

View File

@ -3802,7 +3802,7 @@ var BrowserEventHandler = {
if (closest) { if (closest) {
let uri = this._getLinkURI(closest); let uri = this._getLinkURI(closest);
if (uri) { if (uri) {
Services.io.QueryInterface(Ci.nsISpeculativeConnect).speculativeConnect(uri, null, null); Services.io.QueryInterface(Ci.nsISpeculativeConnect).speculativeConnect(uri, null);
} }
this._doTapHighlight(closest); this._doTapHighlight(closest);
} }

View File

@ -7,9 +7,8 @@
interface nsIURI; interface nsIURI;
interface nsIInterfaceRequestor; interface nsIInterfaceRequestor;
interface nsIEventTarget;
[scriptable, uuid(b3c53863-1313-480a-90a2-5b0da651ee5e)] [scriptable, uuid(fa580a8d-f4a4-47c5-8ade-4f9786e8d1de)]
interface nsISpeculativeConnect : nsISupports interface nsISpeculativeConnect : nsISupports
{ {
/** /**
@ -24,13 +23,10 @@ interface nsISpeculativeConnect : nsISupports
* @param aURI the URI of the hinted transaction * @param aURI the URI of the hinted transaction
* @param aCallbacks any security callbacks for use with SSL for interfaces * @param aCallbacks any security callbacks for use with SSL for interfaces
* such as nsIBadCertListener. May be null. * such as nsIBadCertListener. May be null.
* @param aTarget the thread on which the release of the callbacks will
* occur. May be null for "any thread".
* *
*/ */
void speculativeConnect(in nsIURI aURI, void speculativeConnect(in nsIURI aURI,
in nsIInterfaceRequestor aCallbacks, in nsIInterfaceRequestor aCallbacks);
in nsIEventTarget aTarget);
}; };

View File

@ -1504,12 +1504,21 @@ NS_QueryNotificationCallbacks(const nsCOMPtr<nsIChannel> &aChannel,
inline nsresult inline nsresult
NS_NewNotificationCallbacksAggregation(nsIInterfaceRequestor *callbacks, NS_NewNotificationCallbacksAggregation(nsIInterfaceRequestor *callbacks,
nsILoadGroup *loadGroup, nsILoadGroup *loadGroup,
nsIEventTarget *target,
nsIInterfaceRequestor **result) nsIInterfaceRequestor **result)
{ {
nsCOMPtr<nsIInterfaceRequestor> cbs; nsCOMPtr<nsIInterfaceRequestor> cbs;
if (loadGroup) if (loadGroup)
loadGroup->GetNotificationCallbacks(getter_AddRefs(cbs)); loadGroup->GetNotificationCallbacks(getter_AddRefs(cbs));
return NS_NewInterfaceRequestorAggregation(callbacks, cbs, result); return NS_NewInterfaceRequestorAggregation(callbacks, cbs, target, result);
}
inline nsresult
NS_NewNotificationCallbacksAggregation(nsIInterfaceRequestor *callbacks,
nsILoadGroup *loadGroup,
nsIInterfaceRequestor **result)
{
return NS_NewNotificationCallbacksAggregation(callbacks, loadGroup, nullptr, result);
} }
/** /**

View File

@ -1178,16 +1178,13 @@ public:
NS_DECL_NSIPROTOCOLPROXYCALLBACK NS_DECL_NSIPROTOCOLPROXYCALLBACK
IOServiceProxyCallback(nsIInterfaceRequestor *aCallbacks, IOServiceProxyCallback(nsIInterfaceRequestor *aCallbacks,
nsIEventTarget *aTarget,
nsIOService *aIOService) nsIOService *aIOService)
: mCallbacks(aCallbacks) : mCallbacks(aCallbacks)
, mTarget(aTarget)
, mIOService(aIOService) , mIOService(aIOService)
{ } { }
private: private:
nsRefPtr<nsIInterfaceRequestor> mCallbacks; nsRefPtr<nsIInterfaceRequestor> mCallbacks;
nsRefPtr<nsIEventTarget> mTarget;
nsRefPtr<nsIOService> mIOService; nsRefPtr<nsIOService> mIOService;
}; };
@ -1223,15 +1220,13 @@ IOServiceProxyCallback::OnProxyAvailable(nsICancelable *request, nsIURI *aURI,
return NS_OK; return NS_OK;
speculativeHandler->SpeculativeConnect(aURI, speculativeHandler->SpeculativeConnect(aURI,
mCallbacks, mCallbacks);
mTarget);
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsIOService::SpeculativeConnect(nsIURI *aURI, nsIOService::SpeculativeConnect(nsIURI *aURI,
nsIInterfaceRequestor *aCallbacks, nsIInterfaceRequestor *aCallbacks)
nsIEventTarget *aTarget)
{ {
// Check for proxy information. If there is a proxy configured then a // Check for proxy information. If there is a proxy configured then a
// speculative connect should not be performed because the potential // speculative connect should not be performed because the potential
@ -1244,6 +1239,6 @@ nsIOService::SpeculativeConnect(nsIURI *aURI,
nsCOMPtr<nsICancelable> cancelable; nsCOMPtr<nsICancelable> cancelable;
nsRefPtr<IOServiceProxyCallback> callback = nsRefPtr<IOServiceProxyCallback> callback =
new IOServiceProxyCallback(aCallbacks, aTarget, this); new IOServiceProxyCallback(aCallbacks, this);
return pps->AsyncResolve(aURI, 0, callback, getter_AddRefs(cancelable)); return pps->AsyncResolve(aURI, 0, callback, getter_AddRefs(cancelable));
} }

View File

@ -16,12 +16,10 @@ NS_IMPL_THREADSAFE_ISUPPORTS0(NullHttpTransaction)
NullHttpTransaction::NullHttpTransaction(nsHttpConnectionInfo *ci, NullHttpTransaction::NullHttpTransaction(nsHttpConnectionInfo *ci,
nsIInterfaceRequestor *callbacks, nsIInterfaceRequestor *callbacks,
nsIEventTarget *target,
uint8_t caps) uint8_t caps)
: mStatus(NS_OK) : mStatus(NS_OK)
, mCaps(caps | NS_HTTP_ALLOW_KEEPALIVE) , mCaps(caps | NS_HTTP_ALLOW_KEEPALIVE)
, mCallbacks(callbacks) , mCallbacks(callbacks)
, mEventTarget(target)
, mConnectionInfo(ci) , mConnectionInfo(ci)
, mRequestHead(nullptr) , mRequestHead(nullptr)
, mIsDone(false) , mIsDone(false)
@ -30,11 +28,7 @@ NullHttpTransaction::NullHttpTransaction(nsHttpConnectionInfo *ci,
NullHttpTransaction::~NullHttpTransaction() NullHttpTransaction::~NullHttpTransaction()
{ {
if (mCallbacks) { mCallbacks = nullptr;
nsIInterfaceRequestor *cbs = nullptr;
mCallbacks.swap(cbs);
NS_ProxyRelease(mEventTarget, cbs);
}
delete mRequestHead; delete mRequestHead;
} }
@ -51,18 +45,11 @@ NullHttpTransaction::Connection()
} }
void void
NullHttpTransaction::GetSecurityCallbacks(nsIInterfaceRequestor **outCB, NullHttpTransaction::GetSecurityCallbacks(nsIInterfaceRequestor **outCB)
nsIEventTarget **outTarget)
{ {
nsCOMPtr<nsIInterfaceRequestor> copyCB(mCallbacks); nsCOMPtr<nsIInterfaceRequestor> copyCB(mCallbacks);
*outCB = copyCB; *outCB = copyCB;
copyCB.forget(); copyCB.forget();
if (outTarget) {
nsCOMPtr<nsIEventTarget> copyET(mEventTarget);
*outTarget = copyET;
copyET.forget();
}
} }
void void

View File

@ -10,7 +10,6 @@
#include "nsAHttpTransaction.h" #include "nsAHttpTransaction.h"
#include "nsAHttpConnection.h" #include "nsAHttpConnection.h"
#include "nsIInterfaceRequestor.h" #include "nsIInterfaceRequestor.h"
#include "nsIEventTarget.h"
#include "nsHttpConnectionInfo.h" #include "nsHttpConnectionInfo.h"
#include "nsHttpRequestHead.h" #include "nsHttpRequestHead.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
@ -30,7 +29,6 @@ public:
NullHttpTransaction(nsHttpConnectionInfo *ci, NullHttpTransaction(nsHttpConnectionInfo *ci,
nsIInterfaceRequestor *callbacks, nsIInterfaceRequestor *callbacks,
nsIEventTarget *target,
uint8_t caps); uint8_t caps);
~NullHttpTransaction(); ~NullHttpTransaction();
@ -45,7 +43,6 @@ private:
uint8_t mCaps; uint8_t mCaps;
nsRefPtr<nsAHttpConnection> mConnection; nsRefPtr<nsAHttpConnection> mConnection;
nsCOMPtr<nsIInterfaceRequestor> mCallbacks; nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
nsCOMPtr<nsIEventTarget> mEventTarget;
nsRefPtr<nsHttpConnectionInfo> mConnectionInfo; nsRefPtr<nsHttpConnectionInfo> mConnectionInfo;
nsHttpRequestHead *mRequestHead; nsHttpRequestHead *mRequestHead;
bool mIsDone; bool mIsDone;

View File

@ -2119,8 +2119,7 @@ SpdySession2::SetConnection(nsAHttpConnection *)
} }
void void
SpdySession2::GetSecurityCallbacks(nsIInterfaceRequestor **, SpdySession2::GetSecurityCallbacks(nsIInterfaceRequestor **)
nsIEventTarget **)
{ {
// This is unexpected // This is unexpected
NS_ABORT_IF_FALSE(false, "SpdySession2::GetSecurityCallbacks()"); NS_ABORT_IF_FALSE(false, "SpdySession2::GetSecurityCallbacks()");

View File

@ -2178,8 +2178,7 @@ SpdySession3::SetConnection(nsAHttpConnection *)
} }
void void
SpdySession3::GetSecurityCallbacks(nsIInterfaceRequestor **, SpdySession3::GetSecurityCallbacks(nsIInterfaceRequestor **)
nsIEventTarget **)
{ {
// This is unexpected // This is unexpected
NS_ABORT_IF_FALSE(false, "SpdySession3::GetSecurityCallbacks()"); NS_ABORT_IF_FALSE(false, "SpdySession3::GetSecurityCallbacks()");

View File

@ -127,8 +127,7 @@ public:
// Update the callbacks used to provide security info. May be called on // Update the callbacks used to provide security info. May be called on
// any thread. // any thread.
virtual void SetSecurityCallbacks(nsIInterfaceRequestor* aCallbacks, virtual void SetSecurityCallbacks(nsIInterfaceRequestor* aCallbacks) = 0;
nsIEventTarget* aCallbackTarget) = 0;
}; };
#define NS_DECL_NSAHTTPCONNECTION(fwdObject) \ #define NS_DECL_NSAHTTPCONNECTION(fwdObject) \
@ -201,10 +200,9 @@ public:
} \ } \
int64_t BytesWritten() \ int64_t BytesWritten() \
{ return fwdObject ? (fwdObject)->BytesWritten() : 0; } \ { return fwdObject ? (fwdObject)->BytesWritten() : 0; } \
void SetSecurityCallbacks(nsIInterfaceRequestor* aCallbacks, \ void SetSecurityCallbacks(nsIInterfaceRequestor* aCallbacks) \
nsIEventTarget* aCallbackTarget) \
{ \ { \
(fwdObject)->SetSecurityCallbacks(aCallbacks, aCallbackTarget); \ (fwdObject)->SetSecurityCallbacks(aCallbacks); \
} }
#endif // nsAHttpConnection_h__ #endif // nsAHttpConnection_h__

View File

@ -37,8 +37,7 @@ public:
// called by the connection to get security callbacks to set on the // called by the connection to get security callbacks to set on the
// socket transport. // socket transport.
virtual void GetSecurityCallbacks(nsIInterfaceRequestor **, virtual void GetSecurityCallbacks(nsIInterfaceRequestor **) = 0;
nsIEventTarget **) = 0;
// called to report socket status (see nsITransportEventSink) // called to report socket status (see nsITransportEventSink)
virtual void OnTransportStatus(nsITransport* transport, virtual void OnTransportStatus(nsITransport* transport,
@ -138,8 +137,7 @@ public:
#define NS_DECL_NSAHTTPTRANSACTION \ #define NS_DECL_NSAHTTPTRANSACTION \
void SetConnection(nsAHttpConnection *); \ void SetConnection(nsAHttpConnection *); \
nsAHttpConnection *Connection(); \ nsAHttpConnection *Connection(); \
void GetSecurityCallbacks(nsIInterfaceRequestor **, \ void GetSecurityCallbacks(nsIInterfaceRequestor **); \
nsIEventTarget **); \
void OnTransportStatus(nsITransport* transport, \ void OnTransportStatus(nsITransport* transport, \
nsresult status, uint64_t progress); \ nsresult status, uint64_t progress); \
bool IsDone(); \ bool IsDone(); \

View File

@ -537,7 +537,7 @@ nsHttpChannel::SpeculativeConnect()
mConnectionInfo->SetAnonymous((mLoadFlags & LOAD_ANONYMOUS) != 0); mConnectionInfo->SetAnonymous((mLoadFlags & LOAD_ANONYMOUS) != 0);
mConnectionInfo->SetPrivate(mPrivateBrowsing); mConnectionInfo->SetPrivate(mPrivateBrowsing);
gHttpHandler->SpeculativeConnect(mConnectionInfo, gHttpHandler->SpeculativeConnect(mConnectionInfo,
callbacks, NS_GetCurrentThread()); callbacks);
} }
void void
@ -5933,8 +5933,9 @@ nsHttpChannel::UpdateAggregateCallbacks()
} }
nsCOMPtr<nsIInterfaceRequestor> callbacks; nsCOMPtr<nsIInterfaceRequestor> callbacks;
NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup, NS_NewNotificationCallbacksAggregation(mCallbacks, mLoadGroup,
NS_GetCurrentThread(),
getter_AddRefs(callbacks)); getter_AddRefs(callbacks));
mTransaction->SetSecurityCallbacks(callbacks, NS_GetCurrentThread()); mTransaction->SetSecurityCallbacks(callbacks);
} }
NS_IMETHODIMP NS_IMETHODIMP

View File

@ -78,12 +78,6 @@ nsHttpConnection::~nsHttpConnection()
{ {
LOG(("Destroying nsHttpConnection @%x\n", this)); LOG(("Destroying nsHttpConnection @%x\n", this));
if (mCallbacks) {
nsIInterfaceRequestor *cbs = nullptr;
mCallbacks.swap(cbs);
NS_ProxyRelease(mCallbackTarget, cbs);
}
// release our reference to the handler // release our reference to the handler
nsHttpHandler *handler = gHttpHandler; nsHttpHandler *handler = gHttpHandler;
NS_RELEASE(handler); NS_RELEASE(handler);
@ -113,7 +107,6 @@ nsHttpConnection::Init(nsHttpConnectionInfo *info,
nsIAsyncInputStream *instream, nsIAsyncInputStream *instream,
nsIAsyncOutputStream *outstream, nsIAsyncOutputStream *outstream,
nsIInterfaceRequestor *callbacks, nsIInterfaceRequestor *callbacks,
nsIEventTarget *callbackTarget,
PRIntervalTime rtt) PRIntervalTime rtt)
{ {
NS_ABORT_IF_FALSE(transport && instream && outstream, NS_ABORT_IF_FALSE(transport && instream && outstream,
@ -140,7 +133,6 @@ nsHttpConnection::Init(nsHttpConnectionInfo *info,
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
mCallbacks = callbacks; mCallbacks = callbacks;
mCallbackTarget = callbackTarget;
rv = mSocketTransport->SetSecurityCallbacks(this); rv = mSocketTransport->SetSecurityCallbacks(this);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -325,10 +317,8 @@ nsHttpConnection::Activate(nsAHttpTransaction *trans, uint8_t caps, int32_t pri)
// Update security callbacks // Update security callbacks
nsCOMPtr<nsIInterfaceRequestor> callbacks; nsCOMPtr<nsIInterfaceRequestor> callbacks;
nsCOMPtr<nsIEventTarget> callbackTarget; trans->GetSecurityCallbacks(getter_AddRefs(callbacks));
trans->GetSecurityCallbacks(getter_AddRefs(callbacks), SetSecurityCallbacks(callbacks);
getter_AddRefs(callbackTarget));
SetSecurityCallbacks(callbacks, callbackTarget);
SetupNPN(caps); // only for spdy SetupNPN(caps); // only for spdy
@ -1038,19 +1028,10 @@ nsHttpConnection::GetSecurityInfo(nsISupports **secinfo)
} }
void void
nsHttpConnection::SetSecurityCallbacks(nsIInterfaceRequestor* aCallbacks, nsHttpConnection::SetSecurityCallbacks(nsIInterfaceRequestor* aCallbacks)
nsIEventTarget* aCallbackTarget)
{ {
nsCOMPtr<nsIInterfaceRequestor> callbacks = aCallbacks;
MutexAutoLock lock(mCallbacksLock); MutexAutoLock lock(mCallbacksLock);
if (aCallbacks == mCallbacks) mCallbacks = aCallbacks;
return;
mCallbacks.swap(callbacks);
if (callbacks)
NS_ProxyRelease(mCallbackTarget, callbacks);
mCallbackTarget = aCallbackTarget;
} }
nsresult nsresult
@ -1168,11 +1149,7 @@ nsHttpConnection::CloseTransaction(nsAHttpTransaction *trans, nsresult reason)
{ {
MutexAutoLock lock(mCallbacksLock); MutexAutoLock lock(mCallbacksLock);
if (mCallbacks) { mCallbacks = nullptr;
nsIInterfaceRequestor *cbs = nullptr;
mCallbacks.swap(cbs);
NS_ProxyRelease(mCallbackTarget, cbs);
}
} }
if (NS_FAILED(reason)) if (NS_FAILED(reason))

View File

@ -21,7 +21,6 @@
#include "nsIAsyncInputStream.h" #include "nsIAsyncInputStream.h"
#include "nsIAsyncOutputStream.h" #include "nsIAsyncOutputStream.h"
#include "nsIInterfaceRequestor.h" #include "nsIInterfaceRequestor.h"
#include "nsIEventTarget.h"
class nsHttpRequestHead; class nsHttpRequestHead;
class nsHttpResponseHead; class nsHttpResponseHead;
@ -60,7 +59,7 @@ public:
nsresult Init(nsHttpConnectionInfo *info, uint16_t maxHangTime, nsresult Init(nsHttpConnectionInfo *info, uint16_t maxHangTime,
nsISocketTransport *, nsIAsyncInputStream *, nsISocketTransport *, nsIAsyncInputStream *,
nsIAsyncOutputStream *, nsIInterfaceRequestor *, nsIAsyncOutputStream *, nsIInterfaceRequestor *,
nsIEventTarget *, PRIntervalTime); PRIntervalTime);
// Activate causes the given transaction to be processed on this // Activate causes the given transaction to be processed on this
// connection. It fails if there is already an existing transaction unless // connection. It fails if there is already an existing transaction unless
@ -151,8 +150,7 @@ public:
int64_t BytesWritten() { return mTotalBytesWritten; } int64_t BytesWritten() { return mTotalBytesWritten; }
void SetSecurityCallbacks(nsIInterfaceRequestor* aCallbacks, void SetSecurityCallbacks(nsIInterfaceRequestor* aCallbacks);
nsIEventTarget* aCallbackTarget);
void PrintDiagnostics(nsCString &log); void PrintDiagnostics(nsCString &log);
private: private:
@ -201,7 +199,6 @@ private:
mozilla::Mutex mCallbacksLock; mozilla::Mutex mCallbacksLock;
nsCOMPtr<nsIInterfaceRequestor> mCallbacks; nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
nsCOMPtr<nsIEventTarget> mCallbackTarget;
nsRefPtr<nsHttpConnectionInfo> mConnInfo; nsRefPtr<nsHttpConnectionInfo> mConnInfo;

View File

@ -313,15 +313,19 @@ nsHttpConnectionMgr::ClosePersistentConnections()
nsresult nsresult
nsHttpConnectionMgr::SpeculativeConnect(nsHttpConnectionInfo *ci, nsHttpConnectionMgr::SpeculativeConnect(nsHttpConnectionInfo *ci,
nsIInterfaceRequestor *callbacks, nsIInterfaceRequestor *callbacks)
nsIEventTarget *target)
{ {
LOG(("nsHttpConnectionMgr::SpeculativeConnect [ci=%s]\n", LOG(("nsHttpConnectionMgr::SpeculativeConnect [ci=%s]\n",
ci->HashKey().get())); ci->HashKey().get()));
// Wrap up the callbacks and the target to ensure they're released on the target
// thread properly.
nsCOMPtr<nsIInterfaceRequestor> wrappedCallbacks;
NS_NewInterfaceRequestorAggregation(callbacks, nullptr, getter_AddRefs(wrappedCallbacks));
uint8_t caps = ci->GetAnonymous() ? NS_HTTP_LOAD_ANONYMOUS : 0; uint8_t caps = ci->GetAnonymous() ? NS_HTTP_LOAD_ANONYMOUS : 0;
nsRefPtr<NullHttpTransaction> trans = nsRefPtr<NullHttpTransaction> trans =
new NullHttpTransaction(ci, callbacks, target, caps); new NullHttpTransaction(ci, wrappedCallbacks, caps);
nsresult rv = nsresult rv =
PostEvent(&nsHttpConnectionMgr::OnMsgSpeculativeConnect, 0, trans); PostEvent(&nsHttpConnectionMgr::OnMsgSpeculativeConnect, 0, trans);
@ -2652,15 +2656,13 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out)
"Created new nshttpconnection %p\n", conn.get())); "Created new nshttpconnection %p\n", conn.get()));
nsCOMPtr<nsIInterfaceRequestor> callbacks; nsCOMPtr<nsIInterfaceRequestor> callbacks;
nsCOMPtr<nsIEventTarget> callbackTarget; mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks));
mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks),
getter_AddRefs(callbackTarget));
if (out == mStreamOut) { if (out == mStreamOut) {
TimeDuration rtt = TimeStamp::Now() - mPrimarySynStarted; TimeDuration rtt = TimeStamp::Now() - mPrimarySynStarted;
rv = conn->Init(mEnt->mConnInfo, rv = conn->Init(mEnt->mConnInfo,
gHttpHandler->ConnMgr()->mMaxRequestDelay, gHttpHandler->ConnMgr()->mMaxRequestDelay,
mSocketTransport, mStreamIn, mStreamOut, mSocketTransport, mStreamIn, mStreamOut,
callbacks, callbackTarget, callbacks,
PR_MillisecondsToInterval(rtt.ToMilliseconds())); PR_MillisecondsToInterval(rtt.ToMilliseconds()));
// The nsHttpConnection object now owns these streams and sockets // The nsHttpConnection object now owns these streams and sockets
@ -2673,7 +2675,7 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out)
rv = conn->Init(mEnt->mConnInfo, rv = conn->Init(mEnt->mConnInfo,
gHttpHandler->ConnMgr()->mMaxRequestDelay, gHttpHandler->ConnMgr()->mMaxRequestDelay,
mBackupTransport, mBackupStreamIn, mBackupStreamOut, mBackupTransport, mBackupStreamIn, mBackupStreamOut,
callbacks, callbackTarget, callbacks,
PR_MillisecondsToInterval(rtt.ToMilliseconds())); PR_MillisecondsToInterval(rtt.ToMilliseconds()));
// The nsHttpConnection object now owns these streams and sockets // The nsHttpConnection object now owns these streams and sockets
@ -2730,7 +2732,7 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out)
"be used to finish SSL handshake on conn %p\n", conn.get())); "be used to finish SSL handshake on conn %p\n", conn.get()));
nsRefPtr<NullHttpTransaction> trans = nsRefPtr<NullHttpTransaction> trans =
new NullHttpTransaction(mEnt->mConnInfo, new NullHttpTransaction(mEnt->mConnInfo,
callbacks, callbackTarget, callbacks,
mCaps & ~NS_HTTP_ALLOW_PIPELINING); mCaps & ~NS_HTTP_ALLOW_PIPELINING);
gHttpHandler->ConnMgr()->AddActiveConn(conn, mEnt); gHttpHandler->ConnMgr()->AddActiveConn(conn, mEnt);
@ -2836,7 +2838,7 @@ nsHttpConnectionMgr::nsHalfOpenSocket::GetInterface(const nsIID &iid,
{ {
if (mTransaction) { if (mTransaction) {
nsCOMPtr<nsIInterfaceRequestor> callbacks; nsCOMPtr<nsIInterfaceRequestor> callbacks;
mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks), nullptr); mTransaction->GetSecurityCallbacks(getter_AddRefs(callbacks));
if (callbacks) if (callbacks)
return callbacks->GetInterface(iid, result); return callbacks->GetInterface(iid, result);
} }

View File

@ -105,8 +105,7 @@ public:
// connection manager, nor is the submitter obligated to actually submit a // connection manager, nor is the submitter obligated to actually submit a
// real transaction for this connectionInfo. // real transaction for this connectionInfo.
nsresult SpeculativeConnect(nsHttpConnectionInfo *, nsresult SpeculativeConnect(nsHttpConnectionInfo *,
nsIInterfaceRequestor *, nsIInterfaceRequestor *);
nsIEventTarget *);
// called when a connection is done processing a transaction. if the // called when a connection is done processing a transaction. if the
// connection can be reused then it will be added to the idle list, else // connection can be reused then it will be added to the idle list, else

View File

@ -1613,8 +1613,7 @@ nsHttpHandler::Observe(nsISupports *subject,
NS_IMETHODIMP NS_IMETHODIMP
nsHttpHandler::SpeculativeConnect(nsIURI *aURI, nsHttpHandler::SpeculativeConnect(nsIURI *aURI,
nsIInterfaceRequestor *aCallbacks, nsIInterfaceRequestor *aCallbacks)
nsIEventTarget *aTarget)
{ {
nsIStrictTransportSecurityService* stss = gHttpHandler->GetSTSService(); nsIStrictTransportSecurityService* stss = gHttpHandler->GetSTSService();
bool isStsHost = false; bool isStsHost = false;
@ -1665,7 +1664,7 @@ nsHttpHandler::SpeculativeConnect(nsIURI *aURI,
nsHttpConnectionInfo *ci = nsHttpConnectionInfo *ci =
new nsHttpConnectionInfo(host, port, nullptr, usingSSL); new nsHttpConnectionInfo(host, port, nullptr, usingSSL);
return SpeculativeConnect(ci, aCallbacks, aTarget); return SpeculativeConnect(ci, aCallbacks);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -160,10 +160,9 @@ public:
} }
nsresult SpeculativeConnect(nsHttpConnectionInfo *ci, nsresult SpeculativeConnect(nsHttpConnectionInfo *ci,
nsIInterfaceRequestor *callbacks, nsIInterfaceRequestor *callbacks)
nsIEventTarget *target)
{ {
return mConnMgr->SpeculativeConnect(ci, callbacks, target); return mConnMgr->SpeculativeConnect(ci, callbacks);
} }
// //

View File

@ -422,8 +422,7 @@ nsHttpPipeline::Connection()
} }
void void
nsHttpPipeline::GetSecurityCallbacks(nsIInterfaceRequestor **result, nsHttpPipeline::GetSecurityCallbacks(nsIInterfaceRequestor **result)
nsIEventTarget **target)
{ {
NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread"); NS_ASSERTION(PR_GetCurrentThread() == gSocketThread, "wrong thread");
@ -435,11 +434,9 @@ nsHttpPipeline::GetSecurityCallbacks(nsIInterfaceRequestor **result,
if (!trans) if (!trans)
trans = Response(0); trans = Response(0);
if (trans) if (trans)
trans->GetSecurityCallbacks(result, target); trans->GetSecurityCallbacks(result);
else { else {
*result = nullptr; *result = nullptr;
if (target)
*target = nullptr;
} }
} }

View File

@ -120,6 +120,9 @@ nsHttpTransaction::~nsHttpTransaction()
{ {
LOG(("Destroying nsHttpTransaction @%x\n", this)); LOG(("Destroying nsHttpTransaction @%x\n", this));
// Force the callbacks to be released right now
mCallbacks = nullptr;
NS_IF_RELEASE(mConnection); NS_IF_RELEASE(mConnection);
NS_IF_RELEASE(mConnInfo); NS_IF_RELEASE(mConnInfo);
@ -389,26 +392,21 @@ nsHttpTransaction::SetConnection(nsAHttpConnection *conn)
} }
void void
nsHttpTransaction::GetSecurityCallbacks(nsIInterfaceRequestor **cb, nsHttpTransaction::GetSecurityCallbacks(nsIInterfaceRequestor **cb)
nsIEventTarget **target)
{ {
MutexAutoLock lock(mCallbacksLock); MutexAutoLock lock(mCallbacksLock);
NS_IF_ADDREF(*cb = mCallbacks); NS_IF_ADDREF(*cb = mCallbacks);
if (target)
NS_IF_ADDREF(*target = mConsumerTarget);
} }
void void
nsHttpTransaction::SetSecurityCallbacks(nsIInterfaceRequestor* aCallbacks, nsHttpTransaction::SetSecurityCallbacks(nsIInterfaceRequestor* aCallbacks)
nsIEventTarget* aCallbackTarget)
{ {
{ {
MutexAutoLock lock(mCallbacksLock); MutexAutoLock lock(mCallbacksLock);
mCallbacks = aCallbacks; mCallbacks = aCallbacks;
mConsumerTarget = aCallbackTarget;
} }
if (mConnection) { if (mConnection) {
mConnection->SetSecurityCallbacks(aCallbacks, mConsumerTarget); mConnection->SetSecurityCallbacks(aCallbacks);
} }
} }

View File

@ -86,8 +86,7 @@ public:
nsIEventTarget *ConsumerTarget() { return mConsumerTarget; } nsIEventTarget *ConsumerTarget() { return mConsumerTarget; }
void SetSecurityCallbacks(nsIInterfaceRequestor* aCallbacks, void SetSecurityCallbacks(nsIInterfaceRequestor* aCallbacks);
nsIEventTarget* aCallbackTarget);
// Called to take ownership of the response headers; the transaction // Called to take ownership of the response headers; the transaction
// will drop any reference to the response headers after this call. // will drop any reference to the response headers after this call.

View File

@ -36,7 +36,7 @@ function run_test() {
serv = new TestServer(); serv = new TestServer();
URI = ios.newURI("http://localhost:4444/just/a/test", null, null); URI = ios.newURI("http://localhost:4444/just/a/test", null, null);
ios.QueryInterface(Components.interfaces.nsISpeculativeConnect) ios.QueryInterface(Components.interfaces.nsISpeculativeConnect)
.speculativeConnect(URI, null, null); .speculativeConnect(URI, null);
do_test_pending(); do_test_pending();
} }

View File

@ -5,6 +5,8 @@
#include "nsInterfaceRequestorAgg.h" #include "nsInterfaceRequestorAgg.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "nsThreadUtils.h"
#include "nsProxyRelease.h"
class nsInterfaceRequestorAgg MOZ_FINAL : public nsIInterfaceRequestor class nsInterfaceRequestorAgg MOZ_FINAL : public nsIInterfaceRequestor
{ {
@ -13,11 +15,21 @@ public:
NS_DECL_NSIINTERFACEREQUESTOR NS_DECL_NSIINTERFACEREQUESTOR
nsInterfaceRequestorAgg(nsIInterfaceRequestor *aFirst, nsInterfaceRequestorAgg(nsIInterfaceRequestor *aFirst,
nsIInterfaceRequestor *aSecond) nsIInterfaceRequestor *aSecond,
nsIEventTarget *aConsumerTarget = nullptr)
: mFirst(aFirst) : mFirst(aFirst)
, mSecond(aSecond) {} , mSecond(aSecond)
, mConsumerTarget(aConsumerTarget)
{
if (!mConsumerTarget) {
mConsumerTarget = NS_GetCurrentThread();
}
}
~nsInterfaceRequestorAgg();
private:
nsCOMPtr<nsIInterfaceRequestor> mFirst, mSecond; nsCOMPtr<nsIInterfaceRequestor> mFirst, mSecond;
nsCOMPtr<nsIEventTarget> mConsumerTarget;
}; };
// XXX This needs to support threadsafe refcounting until we fix bug 243591. // XXX This needs to support threadsafe refcounting until we fix bug 243591.
@ -34,6 +46,20 @@ nsInterfaceRequestorAgg::GetInterface(const nsIID &aIID, void **aResult)
return rv; return rv;
} }
nsInterfaceRequestorAgg::~nsInterfaceRequestorAgg()
{
nsIInterfaceRequestor* iir = nullptr;
mFirst.swap(iir);
if (iir) {
NS_ProxyRelease(mConsumerTarget, iir);
}
iir = nullptr;
mSecond.swap(iir);
if (iir) {
NS_ProxyRelease(mConsumerTarget, iir);
}
}
nsresult nsresult
NS_NewInterfaceRequestorAggregation(nsIInterfaceRequestor *aFirst, NS_NewInterfaceRequestorAggregation(nsIInterfaceRequestor *aFirst,
nsIInterfaceRequestor *aSecond, nsIInterfaceRequestor *aSecond,
@ -45,3 +71,16 @@ NS_NewInterfaceRequestorAggregation(nsIInterfaceRequestor *aFirst,
NS_ADDREF(*aResult); NS_ADDREF(*aResult);
return NS_OK; return NS_OK;
} }
nsresult
NS_NewInterfaceRequestorAggregation(nsIInterfaceRequestor *aFirst,
nsIInterfaceRequestor *aSecond,
nsIEventTarget* aTarget,
nsIInterfaceRequestor **aResult)
{
*aResult = new nsInterfaceRequestorAgg(aFirst, aSecond, aTarget);
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}

View File

@ -7,16 +7,29 @@
#include "nsIInterfaceRequestor.h" #include "nsIInterfaceRequestor.h"
class nsIEventTarget;
/** /**
* This function returns an instance of nsIInterfaceRequestor that aggregates * This function returns an instance of nsIInterfaceRequestor that aggregates
* two nsIInterfaceRequestor instances. Its GetInterface method queries * two nsIInterfaceRequestor instances. Its GetInterface method queries
* aFirst for the requested interface and will query aSecond only if aFirst * aFirst for the requested interface and will query aSecond only if aFirst
* failed to supply the requested interface. Both aFirst and aSecond may * failed to supply the requested interface. Both aFirst and aSecond may
* be null. * be null, and will be released on the main thread when the aggregator is
* destroyed.
*/ */
extern nsresult extern nsresult
NS_NewInterfaceRequestorAggregation(nsIInterfaceRequestor *aFirst, NS_NewInterfaceRequestorAggregation(nsIInterfaceRequestor *aFirst,
nsIInterfaceRequestor *aSecond, nsIInterfaceRequestor *aSecond,
nsIInterfaceRequestor **aResult); nsIInterfaceRequestor **aResult);
/**
* Like the previous method, but aFirst and aSecond will be released on the
* provided target thread.
*/
extern nsresult
NS_NewInterfaceRequestorAggregation(nsIInterfaceRequestor *aFirst,
nsIInterfaceRequestor *aSecond,
nsIEventTarget *aTarget,
nsIInterfaceRequestor **aResult);
#endif // !defined( nsInterfaceRequestorAgg_h__ ) #endif // !defined( nsInterfaceRequestorAgg_h__ )