Bug 1616014 - Get rid off nsMainThreadPtrHandle in DNSListenerProxy r=valentin

Differential Revision: https://phabricator.services.mozilla.com/D75485
This commit is contained in:
Kershaw Chang 2020-05-19 13:54:48 +00:00
Родитель 4060dae1b1
Коммит 9f9eb50d04
6 изменённых файлов: 62 добавлений и 83 удалений

Просмотреть файл

@ -10,6 +10,7 @@
#include "nsIXPConnect.h" #include "nsIXPConnect.h"
#include "nsIProtocolProxyService.h" #include "nsIProtocolProxyService.h"
#include "nsNetCID.h" #include "nsNetCID.h"
#include "nsQueryObject.h"
#include "mozilla/ClearOnShutdown.h" #include "mozilla/ClearOnShutdown.h"
#include "mozilla/StaticPtr.h" #include "mozilla/StaticPtr.h"
#include "mozilla/net/NeckoChild.h" #include "mozilla/net/NeckoChild.h"
@ -61,7 +62,7 @@ ChildDNSService::ChildDNSService()
void ChildDNSService::GetDNSRecordHashKey( void ChildDNSService::GetDNSRecordHashKey(
const nsACString& aHost, const nsACString& aTrrServer, uint16_t aType, const nsACString& aHost, const nsACString& aTrrServer, uint16_t aType,
const OriginAttributes& aOriginAttributes, uint32_t aFlags, const OriginAttributes& aOriginAttributes, uint32_t aFlags,
nsIDNSListener* aListener, nsACString& aHashKey) { uintptr_t aListenerAddr, nsACString& aHashKey) {
aHashKey.Assign(aHost); aHashKey.Assign(aHost);
aHashKey.Assign(aTrrServer); aHashKey.Assign(aTrrServer);
aHashKey.AppendInt(aType); aHashKey.AppendInt(aType);
@ -71,7 +72,7 @@ void ChildDNSService::GetDNSRecordHashKey(
aHashKey.Append(originSuffix); aHashKey.Append(originSuffix);
aHashKey.AppendInt(aFlags); aHashKey.AppendInt(aFlags);
aHashKey.AppendPrintf("%p", aListener); aHashKey.AppendPrintf("0x%" PRIxPTR, aListenerAddr);
} }
nsresult ChildDNSService::AsyncResolveInternal( nsresult ChildDNSService::AsyncResolveInternal(
@ -92,7 +93,7 @@ nsresult ChildDNSService::AsyncResolveInternal(
} }
// We need original listener for the pending requests hash. // We need original listener for the pending requests hash.
nsIDNSListener* originalListener = listener; uintptr_t originalListenerAddr = reinterpret_cast<uintptr_t>(listener);
// make sure JS callers get notification on the main thread // make sure JS callers get notification on the main thread
nsCOMPtr<nsIEventTarget> target = target_; nsCOMPtr<nsIEventTarget> target = target_;
@ -119,7 +120,7 @@ nsresult ChildDNSService::AsyncResolveInternal(
MutexAutoLock lock(mPendingRequestsLock); MutexAutoLock lock(mPendingRequestsLock);
nsCString key; nsCString key;
GetDNSRecordHashKey(hostname, aTrrServer, type, aOriginAttributes, flags, GetDNSRecordHashKey(hostname, aTrrServer, type, aOriginAttributes, flags,
originalListener, key); originalListenerAddr, key);
auto entry = mPendingRequests.LookupForAdd(key); auto entry = mPendingRequests.LookupForAdd(key);
if (entry) { if (entry) {
entry.Data()->AppendElement(sender); entry.Data()->AppendElement(sender);
@ -149,8 +150,9 @@ nsresult ChildDNSService::CancelAsyncResolveInternal(
MutexAutoLock lock(mPendingRequestsLock); MutexAutoLock lock(mPendingRequestsLock);
nsTArray<RefPtr<DNSRequestSender>>* hashEntry; nsTArray<RefPtr<DNSRequestSender>>* hashEntry;
nsCString key; nsCString key;
uintptr_t listenerAddr = reinterpret_cast<uintptr_t>(aListener);
GetDNSRecordHashKey(aHostname, aTrrServer, aType, aOriginAttributes, aFlags, GetDNSRecordHashKey(aHostname, aTrrServer, aType, aOriginAttributes, aFlags,
aListener, key); listenerAddr, key);
if (mPendingRequests.Get(key, &hashEntry)) { if (mPendingRequests.Get(key, &hashEntry)) {
// We cancel just one. // We cancel just one.
hashEntry->ElementAt(0)->Cancel(aReason); hashEntry->ElementAt(0)->Cancel(aReason);
@ -417,14 +419,11 @@ ChildDNSService::GetMyHostName(nsACString& result) {
void ChildDNSService::NotifyRequestDone(DNSRequestSender* aDnsRequest) { void ChildDNSService::NotifyRequestDone(DNSRequestSender* aDnsRequest) {
// We need the original flags and listener for the pending requests hash. // We need the original flags and listener for the pending requests hash.
uint32_t originalFlags = aDnsRequest->mFlags & ~RESOLVE_OFFLINE; uint32_t originalFlags = aDnsRequest->mFlags & ~RESOLVE_OFFLINE;
nsCOMPtr<nsIDNSListener> originalListener = aDnsRequest->mListener; uintptr_t originalListenerAddr =
nsCOMPtr<nsIDNSListenerProxy> wrapper = do_QueryInterface(originalListener); reinterpret_cast<uintptr_t>(aDnsRequest->mListener.get());
RefPtr<DNSListenerProxy> wrapper = do_QueryObject(aDnsRequest->mListener);
if (wrapper) { if (wrapper) {
wrapper->GetOriginalListener(getter_AddRefs(originalListener)); originalListenerAddr = wrapper->GetOriginalListenerAddress();
if (NS_WARN_IF(!originalListener)) {
MOZ_ASSERT(originalListener);
return;
}
} }
MutexAutoLock lock(mPendingRequestsLock); MutexAutoLock lock(mPendingRequestsLock);
@ -432,7 +431,7 @@ void ChildDNSService::NotifyRequestDone(DNSRequestSender* aDnsRequest) {
nsCString key; nsCString key;
GetDNSRecordHashKey(aDnsRequest->mHost, aDnsRequest->mTrrServer, GetDNSRecordHashKey(aDnsRequest->mHost, aDnsRequest->mTrrServer,
aDnsRequest->mType, aDnsRequest->mOriginAttributes, aDnsRequest->mType, aDnsRequest->mOriginAttributes,
originalFlags, originalListener, key); originalFlags, originalListenerAddr, key);
nsTArray<RefPtr<DNSRequestSender>>* hashEntry; nsTArray<RefPtr<DNSRequestSender>>* hashEntry;

Просмотреть файл

@ -41,7 +41,7 @@ class ChildDNSService final : public nsPIDNSService, public nsIObserver {
void MOZ_ALWAYS_INLINE GetDNSRecordHashKey( void MOZ_ALWAYS_INLINE GetDNSRecordHashKey(
const nsACString& aHost, const nsACString& aTrrServer, uint16_t aType, const nsACString& aHost, const nsACString& aTrrServer, uint16_t aType,
const OriginAttributes& aOriginAttributes, uint32_t aFlags, const OriginAttributes& aOriginAttributes, uint32_t aFlags,
nsIDNSListener* aListener, nsACString& aHashKey); uintptr_t aListenerAddr, nsACString& aHashKey);
nsresult AsyncResolveInternal(const nsACString& hostname, nsresult AsyncResolveInternal(const nsACString& hostname,
const nsACString& aTrrServer, uint16_t type, const nsACString& aTrrServer, uint16_t type,
uint32_t flags, nsIDNSListener* listener, uint32_t flags, nsIDNSListener* listener,

Просмотреть файл

@ -10,26 +10,27 @@
namespace mozilla { namespace mozilla {
namespace net { namespace net {
NS_IMPL_ISUPPORTS(DNSListenerProxy, nsIDNSListener, nsIDNSListenerProxy) NS_IMPL_ADDREF(DNSListenerProxy)
NS_IMPL_RELEASE(DNSListenerProxy)
NS_INTERFACE_MAP_BEGIN(DNSListenerProxy)
NS_INTERFACE_MAP_ENTRY(nsIDNSListener)
NS_INTERFACE_MAP_ENTRY_CONCRETE(DNSListenerProxy)
NS_INTERFACE_MAP_END
NS_IMETHODIMP NS_IMETHODIMP
DNSListenerProxy::OnLookupComplete(nsICancelable* aRequest, DNSListenerProxy::OnLookupComplete(nsICancelable* aRequest,
nsIDNSRecord* aRecord, nsresult aStatus) { nsIDNSRecord* aRecord, nsresult aStatus) {
RefPtr<OnLookupCompleteRunnable> r = RefPtr<DNSListenerProxy> self = this;
new OnLookupCompleteRunnable(mListener, aRequest, aRecord, aStatus); nsCOMPtr<nsICancelable> request = aRequest;
return mTargetThread->Dispatch(r, NS_DISPATCH_NORMAL); nsCOMPtr<nsIDNSRecord> record = aRecord;
} return mTargetThread->Dispatch(
NS_NewRunnableFunction("DNSListenerProxy::OnLookupComplete",
NS_IMETHODIMP [self, request, record, aStatus]() {
DNSListenerProxy::OnLookupCompleteRunnable::Run() { Unused << self->mListener->OnLookupComplete(
mListener->OnLookupComplete(mRequest, mRecord, mStatus); request, record, aStatus);
return NS_OK; self->mListener = nullptr;
} }),
NS_DISPATCH_NORMAL);
NS_IMETHODIMP
DNSListenerProxy::GetOriginalListener(nsIDNSListener** aOriginalListener) {
NS_IF_ADDREF(*aOriginalListener = mListener);
return NS_OK;
} }
} // namespace net } // namespace net

Просмотреть файл

@ -18,50 +18,44 @@ class nsICancelable;
namespace mozilla { namespace mozilla {
namespace net { namespace net {
class DNSListenerProxy final : public nsIDNSListener, #define DNS_LISTENER_PROXY_IID \
public nsIDNSListenerProxy { { \
0x8f172ca3, 0x7a7f, 0x4941, { \
0xa7, 0x0b, 0xbc, 0x72, 0x80, 0x2e, 0x9d, 0x9b \
} \
}
class DNSListenerProxy final : public nsIDNSListener {
public: public:
DNSListenerProxy(nsIDNSListener* aListener, nsIEventTarget* aTargetThread) DNSListenerProxy(nsIDNSListener* aListener, nsIEventTarget* aTargetThread)
// Sometimes aListener is a main-thread only object like XPCWrappedJS, and // We want to make sure that |aListener| is only accessed on the target
// sometimes it's a threadsafe object like nsSOCKSSocketInfo. Use a main- // thread.
// thread pointer holder, but disable strict enforcement of thread : mListener(aListener),
// invariants. The AddRef implementation of XPCWrappedJS will assert if we mTargetThread(aTargetThread),
// go wrong here. mListenerAddress(reinterpret_cast<uintptr_t>(aListener)) {
: mListener(new nsMainThreadPtrHolder<nsIDNSListener>( MOZ_ASSERT(mListener);
"DNSListenerProxy::mListener", aListener, false)), MOZ_ASSERT(mTargetThread);
mTargetThread(aTargetThread) {} }
NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIDNSLISTENER NS_DECL_NSIDNSLISTENER
NS_DECL_NSIDNSLISTENERPROXY NS_DECLARE_STATIC_IID_ACCESSOR(DNS_LISTENER_PROXY_IID)
class OnLookupCompleteRunnable : public Runnable { uintptr_t GetOriginalListenerAddress() const { return mListenerAddress; }
public:
OnLookupCompleteRunnable(
const nsMainThreadPtrHandle<nsIDNSListener>& aListener,
nsICancelable* aRequest, nsIDNSRecord* aRecord, nsresult aStatus)
: Runnable("DNSListenerProxy::OnLookupCompleteRunnable"),
mListener(aListener),
mRequest(aRequest),
mRecord(aRecord),
mStatus(aStatus) {}
NS_DECL_NSIRUNNABLE
private:
nsMainThreadPtrHandle<nsIDNSListener> mListener;
nsCOMPtr<nsICancelable> mRequest;
nsCOMPtr<nsIDNSRecord> mRecord;
nsresult mStatus;
};
private: private:
~DNSListenerProxy() {} ~DNSListenerProxy() {
NS_ProxyRelease("DNSListenerProxy::mListener", mTargetThread,
mListener.forget());
}
nsMainThreadPtrHandle<nsIDNSListener> mListener; nsCOMPtr<nsIDNSListener> mListener;
nsCOMPtr<nsIEventTarget> mTargetThread; nsCOMPtr<nsIEventTarget> mTargetThread;
uintptr_t mListenerAddress;
}; };
NS_DEFINE_STATIC_IID_ACCESSOR(DNSListenerProxy, DNS_LISTENER_PROXY_IID)
} // namespace net } // namespace net
} // namespace mozilla } // namespace mozilla

Просмотреть файл

@ -437,13 +437,14 @@ void nsDNSAsyncRequest::OnResolveHostComplete(nsHostResolver* resolver,
} }
bool nsDNSAsyncRequest::EqualsAsyncListener(nsIDNSListener* aListener) { bool nsDNSAsyncRequest::EqualsAsyncListener(nsIDNSListener* aListener) {
nsCOMPtr<nsIDNSListenerProxy> wrapper = do_QueryInterface(mListener); uintptr_t originalListenerAddr = reinterpret_cast<uintptr_t>(mListener.get());
RefPtr<DNSListenerProxy> wrapper = do_QueryObject(mListener);
if (wrapper) { if (wrapper) {
nsCOMPtr<nsIDNSListener> originalListener; originalListenerAddr = wrapper->GetOriginalListenerAddress();
wrapper->GetOriginalListener(getter_AddRefs(originalListener));
return aListener == originalListener;
} }
return (aListener == mListener);
uintptr_t listenerAddr = reinterpret_cast<uintptr_t>(aListener);
return (listenerAddr == originalListenerAddr);
} }
size_t nsDNSAsyncRequest::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const { size_t nsDNSAsyncRequest::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const {

Просмотреть файл

@ -29,19 +29,3 @@ interface nsIDNSListener : nsISupports
in nsIDNSRecord aRecord, in nsIDNSRecord aRecord,
in nsresult aStatus); in nsresult aStatus);
}; };
/**
* nsIDNSListenerProxy:
*
* Must be implemented by classes that wrap the original listener passed to
* nsIDNSService.AsyncResolve, so we have access to original listener for
* comparison purposes.
*/
[uuid(60eff0e4-6f7c-493c-add9-1cbea59063ad)]
interface nsIDNSListenerProxy : nsISupports
{
/*
* The original nsIDNSListener which requested hostname resolution.
*/
readonly attribute nsIDNSListener originalListener;
};