Bug 945066: remote nsIDNSService to child. r=jdm

* * *
bug 945066. Fix windows bustage.  r=jduell
This commit is contained in:
Jason Duell 2013-12-11 11:03:51 -08:00
Родитель a00e00a3cc
Коммит 0c4425831b
26 изменённых файлов: 1084 добавлений и 72 удалений

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

@ -1,4 +1,5 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* 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/. */
@ -57,8 +58,9 @@ NS_HIDDEN_(ContentSnifferCache*) gDataSniffers = nullptr;
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIOService, nsIOService::GetInstance)
#include "nsDNSService2.h"
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsDNSService, Init)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIDNSService,
nsDNSService::GetXPCOMSingleton)
#include "nsProtocolProxyService.h"
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsProtocolProxyService, Init)
@ -825,7 +827,7 @@ static const mozilla::Module::CIDEntry kNeckoCIDs[] = {
{ &kNS_SERVERSOCKET_CID, false, nullptr, nsServerSocketConstructor },
{ &kNS_UDPSOCKET_CID, false, nullptr, nsUDPSocketConstructor },
{ &kNS_SOCKETPROVIDERSERVICE_CID, false, nullptr, nsSocketProviderService::Create },
{ &kNS_DNSSERVICE_CID, false, nullptr, nsDNSServiceConstructor },
{ &kNS_DNSSERVICE_CID, false, nullptr, nsIDNSServiceConstructor },
{ &kNS_IDNSERVICE_CID, false, nullptr, nsIDNServiceConstructor },
{ &kNS_EFFECTIVETLDSERVICE_CID, false, nullptr, nsEffectiveTLDServiceConstructor },
{ &kNS_SIMPLEURI_CID, false, nullptr, nsSimpleURIConstructor },

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

@ -0,0 +1,231 @@
/* 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 "mozilla/net/ChildDNSService.h"
#include "nsIDNSListener.h"
#include "nsNetUtil.h"
#include "nsIThread.h"
#include "nsThreadUtils.h"
#include "nsIXPConnect.h"
#include "nsIPrefService.h"
#include "nsIProtocolProxyService.h"
#include "mozilla/net/NeckoChild.h"
#include "mozilla/net/DNSRequestChild.h"
#include "mozilla/net/DNSListenerProxy.h"
namespace mozilla {
namespace net {
//-----------------------------------------------------------------------------
// ChildDNSService
//-----------------------------------------------------------------------------
static ChildDNSService *gChildDNSService;
static const char kPrefNameDisablePrefetch[] = "network.dns.disablePrefetch";
ChildDNSService* ChildDNSService::GetSingleton()
{
MOZ_ASSERT(IsNeckoChild());
if (!gChildDNSService) {
gChildDNSService = new ChildDNSService();
}
NS_ADDREF(gChildDNSService);
return gChildDNSService;
}
NS_IMPL_ISUPPORTS3(ChildDNSService,
nsIDNSService,
nsPIDNSService,
nsIObserver)
ChildDNSService::ChildDNSService()
: mFirstTime(true)
, mOffline(false)
{
MOZ_ASSERT(IsNeckoChild());
}
ChildDNSService::~ChildDNSService()
{
}
//-----------------------------------------------------------------------------
// ChildDNSService::nsIDNSService
//-----------------------------------------------------------------------------
NS_IMETHODIMP
ChildDNSService::AsyncResolve(const nsACString &hostname,
uint32_t flags,
nsIDNSListener *listener,
nsIEventTarget *target_,
nsICancelable **result)
{
NS_ENSURE_TRUE(gNeckoChild != nullptr, NS_ERROR_FAILURE);
if (mDisablePrefetch && (flags & RESOLVE_SPECULATE)) {
return NS_ERROR_DNS_LOOKUP_QUEUE_FULL;
}
// Support apps being 'offline' even if parent is not: avoids DNS traffic by
// apps that have been told they are offline.
if (mOffline) {
flags |= RESOLVE_OFFLINE;
}
// make sure JS callers get notification on the main thread
nsCOMPtr<nsIEventTarget> target = target_;
nsCOMPtr<nsIXPConnectWrappedJS> wrappedListener = do_QueryInterface(listener);
if (wrappedListener && !target) {
nsCOMPtr<nsIThread> mainThread;
NS_GetMainThread(getter_AddRefs(mainThread));
target = do_QueryInterface(mainThread);
}
if (target) {
// Guarantee listener freed on main thread. Not sure we need this in child
// (or in parent in nsDNSService.cpp) but doesn't hurt.
listener = new DNSListenerProxy(listener, target);
}
nsRefPtr<DNSRequestChild> childReq =
new DNSRequestChild(nsCString(hostname), flags, listener, target);
childReq->StartRequest();
childReq.forget(result);
return NS_OK;
}
NS_IMETHODIMP
ChildDNSService::CancelAsyncResolve(const nsACString &aHostname,
uint32_t aFlags,
nsIDNSListener *aListener,
nsresult aReason)
{
if (mDisablePrefetch && (aFlags & RESOLVE_SPECULATE)) {
return NS_ERROR_DNS_LOOKUP_QUEUE_FULL;
}
// TODO: keep a hashtable of pending requests, so we can obey cancel semantics
// (call OnLookupComplete with aReason). Also possible we could send IPDL to
// parent to cancel.
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
ChildDNSService::Resolve(const nsACString &hostname,
uint32_t flags,
nsIDNSRecord **result)
{
// not planning to ever support this, since sync IPDL is evil.
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
ChildDNSService::GetDNSCacheEntries(nsTArray<mozilla::net::DNSCacheEntries> *args)
{
// Only used by networking dashboard, so may not ever need this in child.
// (and would provide a way to spy on what hosts other apps are connecting to,
// unless we start keeping per-app DNS caches).
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
ChildDNSService::GetMyHostName(nsACString &result)
{
// TODO: get value from parent during PNecko construction?
return NS_ERROR_NOT_AVAILABLE;
}
//-----------------------------------------------------------------------------
// ChildDNSService::nsPIDNSService
//-----------------------------------------------------------------------------
nsresult
ChildDNSService::Init()
{
// Disable prefetching either by explicit preference or if a manual proxy
// is configured
bool disablePrefetch = false;
int proxyType = nsIProtocolProxyService::PROXYCONFIG_DIRECT;
nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
prefs->GetBoolPref(kPrefNameDisablePrefetch, &disablePrefetch);
if (prefs) {
prefs->GetIntPref("network.proxy.type", &proxyType);
prefs->GetBoolPref(kPrefNameDisablePrefetch, &disablePrefetch);
}
if (mFirstTime) {
mFirstTime = false;
if (prefs) {
prefs->AddObserver(kPrefNameDisablePrefetch, this, false);
// Monitor these to see if there is a change in proxy configuration
// If a manual proxy is in use, disable prefetch implicitly
prefs->AddObserver("network.proxy.type", this, false);
}
}
mDisablePrefetch = disablePrefetch ||
(proxyType == nsIProtocolProxyService::PROXYCONFIG_MANUAL);
return NS_OK;
}
nsresult
ChildDNSService::Shutdown()
{
return NS_OK;
}
NS_IMETHODIMP
ChildDNSService::GetPrefetchEnabled(bool *outVal)
{
*outVal = !mDisablePrefetch;
return NS_OK;
}
NS_IMETHODIMP
ChildDNSService::SetPrefetchEnabled(bool inVal)
{
mDisablePrefetch = !inVal;
return NS_OK;
}
NS_IMETHODIMP
ChildDNSService::GetOffline(bool* aResult)
{
*aResult = mOffline;
return NS_OK;
}
NS_IMETHODIMP
ChildDNSService::SetOffline(bool value)
{
mOffline = value;
return NS_OK;
}
//-----------------------------------------------------------------------------
// ChildDNSService::nsIObserver
//-----------------------------------------------------------------------------
NS_IMETHODIMP
ChildDNSService::Observe(nsISupports *subject, const char *topic,
const PRUnichar *data)
{
// we are only getting called if a preference has changed.
NS_ASSERTION(strcmp(topic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0,
"unexpected observe call");
// Reread prefs
Init();
return NS_OK;
}
} // namespace net
} // namespace mozilla

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

@ -0,0 +1,42 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* 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_ChildDNSService_h
#define mozilla_net_ChildDNSService_h
#include "nsPIDNSService.h"
#include "nsIObserver.h"
#include "mozilla/Attributes.h"
namespace mozilla {
namespace net {
class ChildDNSService MOZ_FINAL
: public nsPIDNSService
, public nsIObserver
{
public:
// AsyncResolve (and CancelAsyncResolve) can be called off-main
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSPIDNSSERVICE
NS_DECL_NSIDNSSERVICE
NS_DECL_NSIOBSERVER
ChildDNSService();
virtual ~ChildDNSService();
static ChildDNSService* GetSingleton();
private:
bool mFirstTime;
bool mOffline;
bool mDisablePrefetch;
};
} // namespace net
} // namespace mozilla
#endif // mozilla_net_ChildDNSService_h

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

@ -6,6 +6,7 @@
#include "mozilla/Assertions.h"
#include "mozilla/mozalloc.h"
#include "mozilla/ArrayUtils.h"
#include <string.h>
#ifdef XP_WIN
@ -203,6 +204,31 @@ bool IsIPAddrLocal(const NetAddr *addr)
return false;
}
bool
NetAddr::operator == (const NetAddr& other) const
{
if (this->raw.family != other.raw.family) {
return false;
} else if (this->raw.family == AF_INET) {
return (this->inet.port == other.inet.port) &&
(this->inet.ip == other.inet.ip);
} else if (this->raw.family == AF_INET6) {
return (this->inet6.port == other.inet6.port) &&
(this->inet6.flowinfo == other.inet6.flowinfo) &&
(memcmp(&this->inet6.ip, &other.inet6.ip,
sizeof(this->inet6.ip)) == 0) &&
(this->inet6.scope_id == other.inet6.scope_id);
#if defined(XP_UNIX) || defined(XP_OS2)
} else if (this->raw.family == AF_LOCAL) {
return PL_strncmp(this->local.path, other.local.path,
ArrayLength(this->local.path));
#endif
}
return false;
}
NetAddrElement::NetAddrElement(const PRNetAddr *prNetAddr)
{
PRNetAddrToNetAddr(prNetAddr, &mAddress);

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

@ -10,6 +10,7 @@
#include "nscore.h"
#include "prio.h"
#include "prnetdb.h"
#include "plstr.h"
#include "mozilla/LinkedList.h"
#include "mozilla/MemoryReporting.h"
@ -112,6 +113,8 @@ union NetAddr {
#endif
} local;
#endif
// introduced to support nsTArray<NetAddr> (for DNSRequestParent.cpp)
bool operator == (const NetAddr& other) const;
};
// This class wraps a NetAddr union to provide C++ linked list

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

@ -0,0 +1,36 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* 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 "mozilla/net/DNSListenerProxy.h"
#include "nsICancelable.h"
#include "nsIEventTarget.h"
namespace mozilla {
namespace net {
NS_IMPL_ISUPPORTS1(DNSListenerProxy, nsIDNSListener)
NS_IMETHODIMP
DNSListenerProxy::OnLookupComplete(nsICancelable* aRequest,
nsIDNSRecord* aRecord,
nsresult aStatus)
{
nsRefPtr<OnLookupCompleteRunnable> r =
new OnLookupCompleteRunnable(mListener, aRequest, aRecord, aStatus);
return mTargetThread->Dispatch(r, NS_DISPATCH_NORMAL);
}
NS_IMETHODIMP
DNSListenerProxy::OnLookupCompleteRunnable::Run()
{
mListener->OnLookupComplete(mRequest, mRecord, mStatus);
return NS_OK;
}
} // namespace net
} // namespace mozilla

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

@ -0,0 +1,66 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* 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 DNSListenerProxy_h__
#define DNSListenerProxy_h__
#include "nsIDNSListener.h"
#include "nsIDNSRecord.h"
#include "nsProxyRelease.h"
#include "nsThreadUtils.h"
class nsIEventTarget;
class nsICancelable;
namespace mozilla {
namespace net {
class DNSListenerProxy MOZ_FINAL : public nsIDNSListener
{
public:
DNSListenerProxy(nsIDNSListener* aListener, nsIEventTarget* aTargetThread)
// Sometimes aListener is a main-thread only object like XPCWrappedJS, and
// sometimes it's a threadsafe object like nsSOCKSSocketInfo. Use a main-
// thread pointer holder, but disable strict enforcement of thread invariants.
// The AddRef implementation of XPCWrappedJS will assert if we go wrong here.
: mListener(new nsMainThreadPtrHolder<nsIDNSListener>(aListener, false))
, mTargetThread(aTargetThread)
{ }
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIDNSLISTENER
class OnLookupCompleteRunnable : public nsRunnable
{
public:
OnLookupCompleteRunnable(const nsMainThreadPtrHandle<nsIDNSListener>& aListener,
nsICancelable* aRequest,
nsIDNSRecord* aRecord,
nsresult aStatus)
: mListener(aListener)
, mRequest(aRequest)
, mRecord(aRecord)
, mStatus(aStatus)
{ }
NS_DECL_NSIRUNNABLE
private:
nsMainThreadPtrHandle<nsIDNSListener> mListener;
nsCOMPtr<nsICancelable> mRequest;
nsCOMPtr<nsIDNSRecord> mRecord;
nsresult mStatus;
};
private:
nsMainThreadPtrHandle<nsIDNSListener> mListener;
nsCOMPtr<nsIEventTarget> mTargetThread;
};
} // namespace net
} // namespace mozilla
#endif // DNSListenerProxy_h__

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

@ -0,0 +1,247 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* 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 "mozilla/net/DNSRequestChild.h"
#include "mozilla/net/NeckoChild.h"
#include "nsIDNSRecord.h"
#include "nsHostResolver.h"
#include "nsTArray.h"
#include "nsNetAddr.h"
#include "nsIThread.h"
#include "nsThreadUtils.h"
using namespace mozilla::ipc;
namespace mozilla {
namespace net {
//-----------------------------------------------------------------------------
// ChildDNSRecord:
// A simple class to provide nsIDNSRecord on the child
//-----------------------------------------------------------------------------
class ChildDNSRecord : public nsIDNSRecord
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIDNSRECORD
ChildDNSRecord(const DNSRecord& reply, uint16_t flags);
virtual ~ChildDNSRecord();
private:
nsCString mCanonicalName;
nsTArray<NetAddr> mAddresses;
uint32_t mCurrent; // addr iterator
uint32_t mLength; // number of addrs
uint16_t mFlags;
};
NS_IMPL_ISUPPORTS1(ChildDNSRecord, nsIDNSRecord)
ChildDNSRecord::ChildDNSRecord(const DNSRecord& reply, uint16_t flags)
: mCurrent(0)
, mFlags(flags)
{
mCanonicalName = reply.canonicalName();
// A shame IPDL gives us no way to grab ownership of array: so copy it.
const nsTArray<NetAddr>& addrs = reply.addrs();
uint32_t i = 0;
mLength = addrs.Length();
for (; i < mLength; i++) {
mAddresses.AppendElement(addrs[i]);
}
}
ChildDNSRecord::~ChildDNSRecord()
{
}
//-----------------------------------------------------------------------------
// ChildDNSRecord::nsIDNSRecord
//-----------------------------------------------------------------------------
NS_IMETHODIMP
ChildDNSRecord::GetCanonicalName(nsACString &result)
{
if (!(mFlags & nsHostResolver::RES_CANON_NAME)) {
return NS_ERROR_NOT_AVAILABLE;
}
result = mCanonicalName;
return NS_OK;
}
NS_IMETHODIMP
ChildDNSRecord::GetNextAddr(uint16_t port, NetAddr *addr)
{
if (mCurrent >= mLength) {
return NS_ERROR_NOT_AVAILABLE;
}
memcpy(addr, &mAddresses[mCurrent++], sizeof(NetAddr));
// both Ipv4/6 use same bits for port, so safe to just use ipv4's field
addr->inet.port = port;
return NS_OK;
}
// shamelessly copied from nsDNSRecord
NS_IMETHODIMP
ChildDNSRecord::GetScriptableNextAddr(uint16_t port, nsINetAddr **result)
{
NetAddr addr;
nsresult rv = GetNextAddr(port, &addr);
if (NS_FAILED(rv)) return rv;
NS_ADDREF(*result = new nsNetAddr(&addr));
return NS_OK;
}
// also copied from nsDNSRecord
NS_IMETHODIMP
ChildDNSRecord::GetNextAddrAsString(nsACString &result)
{
NetAddr addr;
nsresult rv = GetNextAddr(0, &addr);
if (NS_FAILED(rv)) {
return rv;
}
char buf[kIPv6CStrBufSize];
if (NetAddrToString(&addr, buf, sizeof(buf))) {
result.Assign(buf);
return NS_OK;
}
NS_ERROR("NetAddrToString failed unexpectedly");
return NS_ERROR_FAILURE; // conversion failed for some reason
}
NS_IMETHODIMP
ChildDNSRecord::HasMore(bool *result)
{
*result = mCurrent < mLength;
return NS_OK;
}
NS_IMETHODIMP
ChildDNSRecord::Rewind()
{
mCurrent = 0;
return NS_OK;
}
NS_IMETHODIMP
ChildDNSRecord::ReportUnusable(uint16_t aPort)
{
// "We thank you for your feedback" == >/dev/null
// TODO: we could send info back to parent.
return NS_OK;
}
//-----------------------------------------------------------------------------
// DNSRequestChild
//-----------------------------------------------------------------------------
DNSRequestChild::DNSRequestChild(const nsCString& aHost,
const uint32_t& aFlags,
nsIDNSListener *aListener,
nsIEventTarget *target)
: mListener(aListener)
, mTarget(target)
, mResultStatus(NS_OK)
, mHost(aHost)
, mFlags(aFlags)
{
}
void
DNSRequestChild::StartRequest()
{
// we can only do IPDL on the main thread
if (!NS_IsMainThread()) {
NS_DispatchToMainThread(
NS_NewRunnableMethod(this, &DNSRequestChild::StartRequest));
return;
}
// Send request to Parent process.
gNeckoChild->SendPDNSRequestConstructor(this, mHost, mFlags);
// IPDL holds a reference until IPDL channel gets destroyed
AddIPDLReference();
}
void
DNSRequestChild::CallOnLookupComplete()
{
MOZ_ASSERT(mListener);
mListener->OnLookupComplete(this, mResultRecord, mResultStatus);
}
bool
DNSRequestChild::Recv__delete__(const DNSRequestResponse& reply)
{
MOZ_ASSERT(mListener);
switch (reply.type()) {
case DNSRequestResponse::TDNSRecord: {
mResultRecord = new ChildDNSRecord(reply.get_DNSRecord(), mFlags);
break;
}
case DNSRequestResponse::Tnsresult: {
mResultStatus = reply.get_nsresult();
break;
}
default:
NS_NOTREACHED("unknown type");
return false;
}
MOZ_ASSERT(NS_IsMainThread());
bool targetIsMain = false;
if (!mTarget) {
targetIsMain = true;
} else {
mTarget->IsOnCurrentThread(&targetIsMain);
}
if (targetIsMain) {
CallOnLookupComplete();
} else {
nsCOMPtr<nsIRunnable> event =
NS_NewRunnableMethod(this, &DNSRequestChild::CallOnLookupComplete);
mTarget->Dispatch(event, NS_DISPATCH_NORMAL);
}
return true;
}
//-----------------------------------------------------------------------------
// DNSRequestChild::nsISupports
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS1(DNSRequestChild,
nsICancelable)
//-----------------------------------------------------------------------------
// DNSRequestChild::nsICancelable
//-----------------------------------------------------------------------------
NS_IMETHODIMP
DNSRequestChild::Cancel(nsresult reason)
{
// for now Cancel is a no-op
return NS_OK;
}
//------------------------------------------------------------------------------
}} // mozilla::net

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

@ -0,0 +1,58 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* 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_DNSRequestChild_h
#define mozilla_net_DNSRequestChild_h
#include "mozilla/net/PDNSRequestChild.h"
#include "nsICancelable.h"
#include "nsIDNSRecord.h"
#include "nsIDNSListener.h"
#include "nsIEventTarget.h"
namespace mozilla {
namespace net {
class DNSRequestChild
: public PDNSRequestChild
, public nsICancelable
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSICANCELABLE
DNSRequestChild(const nsCString& aHost, const uint32_t& aFlags,
nsIDNSListener *aListener, nsIEventTarget *target);
virtual ~DNSRequestChild() {}
void AddIPDLReference() {
AddRef();
}
void ReleaseIPDLReference() {
// we don't need an 'mIPCOpen' variable until/unless we add calls that might
// try to send IPDL msgs to parent after ReleaseIPDLReference is called
// (when IPDL channel torn down).
Release();
}
// Sends IPDL request to parent
void StartRequest();
void CallOnLookupComplete();
private:
virtual bool Recv__delete__(const DNSRequestResponse& reply) MOZ_OVERRIDE;
nsCOMPtr<nsIDNSListener> mListener;
nsCOMPtr<nsIEventTarget> mTarget;
nsCOMPtr<nsIDNSRecord> mResultRecord;
nsresult mResultStatus;
nsCString mHost;
uint16_t mFlags;
};
} // namespace net
} // namespace mozilla
#endif // mozilla_net_DNSRequestChild_h

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

@ -0,0 +1,105 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* 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 "mozilla/net/DNSRequestParent.h"
#include "nsIDNSService.h"
#include "nsNetCID.h"
#include "nsThreadUtils.h"
#include "nsIServiceManager.h"
#include "nsICancelable.h"
#include "nsIDNSRecord.h"
#include "nsHostResolver.h"
#include "mozilla/unused.h"
using namespace mozilla::ipc;
namespace mozilla {
namespace net {
DNSRequestParent::DNSRequestParent()
: mIPCClosed(false)
{
}
DNSRequestParent::~DNSRequestParent()
{
}
void
DNSRequestParent::DoAsyncResolve(const nsACString &hostname, uint32_t flags)
{
nsresult rv;
mFlags = flags;
nsCOMPtr<nsIDNSService> dns = do_GetService(NS_DNSSERVICE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIThread> mainThread = do_GetMainThread();
nsCOMPtr<nsICancelable> unused;
rv = dns->AsyncResolve(hostname, flags, this, mainThread,
getter_AddRefs(unused));
}
if (NS_FAILED(rv) && !mIPCClosed) {
unused << Send__delete__(this, DNSRequestResponse(rv));
}
}
void
DNSRequestParent::ActorDestroy(ActorDestroyReason why)
{
// We may still have refcount>0 if DNS hasn't called our OnLookupComplete
// yet, but child process has crashed. We must not send any more msgs
// to child, or IPDL will kill chrome process, too.
mIPCClosed = true;
}
//-----------------------------------------------------------------------------
// DNSRequestParent::nsISupports
//-----------------------------------------------------------------------------
NS_IMPL_ISUPPORTS1(DNSRequestParent,
nsIDNSListener)
//-----------------------------------------------------------------------------
// nsIDNSListener functions
//-----------------------------------------------------------------------------
NS_IMETHODIMP
DNSRequestParent::OnLookupComplete(nsICancelable *request,
nsIDNSRecord *rec,
nsresult status)
{
if (mIPCClosed) {
// nothing to do: child probably crashed
return NS_OK;
}
if (NS_SUCCEEDED(status)) {
MOZ_ASSERT(rec);
nsAutoCString cname;
if (mFlags & nsHostResolver::RES_CANON_NAME) {
rec->GetCanonicalName(cname);
}
// Get IP addresses for hostname (use port 80 as dummy value for NetAddr)
NetAddrArray array;
NetAddr addr;
while (NS_SUCCEEDED(rec->GetNextAddr(80, &addr))) {
array.AppendElement(addr);
}
unused << Send__delete__(this, DNSRequestResponse(DNSRecord(cname, array)));
} else {
unused << Send__delete__(this, DNSRequestResponse(status));
}
return NS_OK;
}
}} // mozilla::net

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

@ -0,0 +1,39 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* 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_DNSRequestParent_h
#define mozilla_net_DNSRequestParent_h
#include "mozilla/net/PDNSRequestParent.h"
#include "nsIDNSService.h"
#include "nsIDNSListener.h"
namespace mozilla {
namespace net {
class DNSRequestParent
: public PDNSRequestParent
, public nsIDNSListener
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIDNSLISTENER
DNSRequestParent();
virtual ~DNSRequestParent();
void DoAsyncResolve(const nsACString &hostname, uint32_t flags);
protected:
virtual void ActorDestroy(ActorDestroyReason why);
private:
uint32_t mFlags;
bool mIPCClosed; // true if IPDL channel has been closed (child crash)
};
} // namespace net
} // namespace mozilla
#endif // mozilla_net_DNSRequestParent_h

23
netwerk/dns/PDNSParams.h Normal file
Просмотреть файл

@ -0,0 +1,23 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 ft=c: */
/* 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 PDNSParams_h
#define PDNSParams_h
#include "DNS.h"
#include "nsTArray.h"
namespace mozilla {
namespace net {
// Need to define typedef in .h file--can't seem to in ipdl.h file?
typedef nsTArray<NetAddr> NetAddrArray;
} // namespace net
} // namespace mozilla
#endif // PDNSParams_h

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

@ -0,0 +1,31 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
/* 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 protocol PNecko;
include PDNSRequestParams;
include "mozilla/net/NeckoMessageUtils.h";
namespace mozilla {
namespace net {
async protocol PDNSRequest
{
manager PNecko;
//parent:
// constructor in PNecko takes AsyncResolve args that initialize request
child:
__delete__(DNSRequestResponse reply);
};
} //namespace net
} //namespace mozilla

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

@ -0,0 +1,31 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
/* 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/. */
using NetAddrArray from "mozilla/net/PDNSParams.h";
namespace mozilla {
namespace net {
//-----------------------------------------------------------------------------
// DNS IPDL structs
//-----------------------------------------------------------------------------
struct DNSRecord
{
nsCString canonicalName;
NetAddrArray addrs;
};
union DNSRequestResponse
{
DNSRecord;
nsresult; // if error
};
} // namespace ipc
} // namespace mozilla

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

@ -16,7 +16,12 @@ XPIDL_SOURCES += [
XPIDL_MODULE = 'necko_dns'
EXPORTS.mozilla.net += [
'ChildDNSService.h',
'DNS.h',
'DNSListenerProxy.h',
'DNSRequestChild.h',
'DNSRequestParent.h',
'PDNSParams.h',
]
SOURCES += [
@ -25,7 +30,11 @@ SOURCES += [
]
UNIFIED_SOURCES += [
'ChildDNSService.cpp',
'DNS.cpp',
'DNSListenerProxy.cpp',
'DNSRequestChild.cpp',
'DNSRequestParent.cpp',
'nameprep.c',
'nsDNSService2.cpp',
'nsIDNService.cpp',
@ -33,10 +42,17 @@ UNIFIED_SOURCES += [
'race.c',
]
IPDL_SOURCES = [
'PDNSRequest.ipdl',
'PDNSRequestParams.ipdlh',
]
FAIL_ON_WARNINGS = True
MSVC_ENABLE_PGO = True
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'necko'
GENERATED_FILES = [

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

@ -1,4 +1,5 @@
/* vim:set ts=4 sw=4 sts=4 et cin: */
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* 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/. */
@ -33,6 +34,9 @@
#include "mozilla/Attributes.h"
#include "mozilla/VisualEventTracer.h"
#include "mozilla/net/NeckoCommon.h"
#include "mozilla/net/ChildDNSService.h"
#include "mozilla/net/DNSListenerProxy.h"
using namespace mozilla;
using namespace mozilla::net;
@ -410,6 +414,43 @@ nsDNSService::~nsDNSService()
NS_IMPL_ISUPPORTS_INHERITED3(nsDNSService, MemoryUniReporter, nsIDNSService,
nsPIDNSService, nsIObserver)
/******************************************************************************
* nsDNSService impl:
* singleton instance ctor/dtor methods
******************************************************************************/
static nsDNSService *gDNSService;
nsIDNSService*
nsDNSService::GetXPCOMSingleton()
{
if (IsNeckoChild()) {
return ChildDNSService::GetSingleton();
}
return GetSingleton();
}
nsDNSService*
nsDNSService::GetSingleton()
{
NS_ASSERTION(!IsNeckoChild(), "not a parent process");
if (gDNSService) {
NS_ADDREF(gDNSService);
return gDNSService;
}
gDNSService = new nsDNSService();
if (gDNSService) {
NS_ADDREF(gDNSService);
if (NS_FAILED(gDNSService->Init())) {
NS_RELEASE(gDNSService);
}
}
return gDNSService;
}
NS_IMETHODIMP
nsDNSService::Init()
{
@ -563,70 +604,6 @@ nsDNSService::SetPrefetchEnabled(bool inVal)
return NS_OK;
}
namespace {
class DNSListenerProxy MOZ_FINAL : public nsIDNSListener
{
public:
DNSListenerProxy(nsIDNSListener* aListener, nsIEventTarget* aTargetThread)
// Sometimes aListener is a main-thread only object like XPCWrappedJS, and
// sometimes it's a threadsafe object like nsSOCKSSocketInfo. Use a main-
// thread pointer holder, but disable strict enforcement of thread invariants.
// The AddRef implementation of XPCWrappedJS will assert if we go wrong here.
: mListener(new nsMainThreadPtrHolder<nsIDNSListener>(aListener, false))
, mTargetThread(aTargetThread)
{ }
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIDNSLISTENER
class OnLookupCompleteRunnable : public nsRunnable
{
public:
OnLookupCompleteRunnable(const nsMainThreadPtrHandle<nsIDNSListener>& aListener,
nsICancelable* aRequest,
nsIDNSRecord* aRecord,
nsresult aStatus)
: mListener(aListener)
, mRequest(aRequest)
, mRecord(aRecord)
, mStatus(aStatus)
{ }
NS_DECL_NSIRUNNABLE
private:
nsMainThreadPtrHandle<nsIDNSListener> mListener;
nsCOMPtr<nsICancelable> mRequest;
nsCOMPtr<nsIDNSRecord> mRecord;
nsresult mStatus;
};
private:
nsMainThreadPtrHandle<nsIDNSListener> mListener;
nsCOMPtr<nsIEventTarget> mTargetThread;
};
NS_IMPL_ISUPPORTS1(DNSListenerProxy, nsIDNSListener)
NS_IMETHODIMP
DNSListenerProxy::OnLookupComplete(nsICancelable* aRequest,
nsIDNSRecord* aRecord,
nsresult aStatus)
{
nsRefPtr<OnLookupCompleteRunnable> r =
new OnLookupCompleteRunnable(mListener, aRequest, aRecord, aStatus);
return mTargetThread->Dispatch(r, NS_DISPATCH_NORMAL);
}
NS_IMETHODIMP
DNSListenerProxy::OnLookupCompleteRunnable::Run()
{
mListener->OnLookupComplete(mRequest, mRecord, mStatus);
return NS_OK;
}
} // anonymous namespace
NS_IMETHODIMP
nsDNSService::AsyncResolve(const nsACString &hostname,
@ -670,6 +647,7 @@ nsDNSService::AsyncResolve(const nsACString &hostname,
hostPtr = &hostACE;
}
// make sure JS callers get notification on the main thread
nsCOMPtr<nsIXPConnectWrappedJS> wrappedListener = do_QueryInterface(listener);
if (wrappedListener && !target) {
nsCOMPtr<nsIThread> mainThread;

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

@ -1,3 +1,5 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* vim: set sw=4 ts=8 et tw=80 : */
/* 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/. */
@ -30,6 +32,8 @@ public:
nsDNSService();
~nsDNSService();
static nsIDNSService* GetXPCOMSingleton();
int64_t Amount() MOZ_OVERRIDE
{
return SizeOfIncludingThis(MallocSizeOf);
@ -37,6 +41,8 @@ public:
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
private:
static nsDNSService* GetSingleton();
uint16_t GetAFForLookup(const nsACString &host, uint32_t flags);
nsRefPtr<nsHostResolver> mResolver;

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

@ -3,6 +3,9 @@
* 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 EffectiveTLDService_h
#define EffectiveTLDService_h
#include "nsIEffectiveTLDService.h"
#include "nsIMemoryReporter.h"
@ -124,3 +127,5 @@ private:
nsTHashtable<nsDomainEntry> mHash;
nsCOMPtr<nsIIDNService> mIDNService;
};
#endif // EffectiveTLDService_h

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

@ -878,9 +878,9 @@ nsHostResolver::ConditionallyCreateThread(nsHostRecord *rec)
#include "windns.h"
#include "windows.h"
typedef DNS_STATUS (__stdcall * DnsQueryFunc) (PCTSTR lpstrName, WORD wType,
typedef DNS_STATUS (__stdcall * DnsQueryFunc) (LPCSTR lpstrName, WORD wType,
DWORD Options, PVOID pExtra,
PDNS_RECORD *ppQueryResultsSet,
PDNS_RECORDA *ppQueryResultsSet,
PVOID *pReserved);
class ExperimentFinishedRunner : public nsRunnable
@ -1055,7 +1055,7 @@ public:
}
if (srvStatus == DNS_RCODE_NOERROR) {
DNS_SRV_DATA *srvData = &srvResults->Data.Srv;
DNS_SRV_DATAA *srvData = &srvResults->Data.Srv;
if (_stricmp(srvData->pNameTarget, "success.http2test.mozilla.org") ||
srvData->wPort != 443 ||
srvData->wPriority != 100 ||

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

@ -14,6 +14,7 @@
#include "mozilla/net/WyciwygChannelChild.h"
#include "mozilla/net/FTPChannelChild.h"
#include "mozilla/net/WebSocketChannelChild.h"
#include "mozilla/net/DNSRequestChild.h"
#include "mozilla/net/RemoteOpenFileChild.h"
#include "mozilla/dom/network/TCPSocketChild.h"
#include "mozilla/dom/network/TCPServerSocketChild.h"
@ -230,6 +231,24 @@ NeckoChild::DeallocPUDPSocketChild(PUDPSocketChild* child)
return true;
}
PDNSRequestChild*
NeckoChild::AllocPDNSRequestChild(const nsCString& aHost,
const uint32_t& aFlags)
{
// We don't allocate here: instead we always use IPDL constructor that takes
// an existing object
NS_NOTREACHED("AllocPDNSRequestChild should not be called on child");
return nullptr;
}
bool
NeckoChild::DeallocPDNSRequestChild(PDNSRequestChild* aChild)
{
DNSRequestChild *p = static_cast<DNSRequestChild*>(aChild);
p->ReleaseIPDLReference();
return true;
}
PRemoteOpenFileChild*
NeckoChild::AllocPRemoteOpenFileChild(const URIParams&, const OptionalURIParams&)
{

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

@ -51,6 +51,9 @@ protected:
const uint16_t& aPort,
const nsCString& aFilter);
virtual bool DeallocPUDPSocketChild(PUDPSocketChild*);
virtual PDNSRequestChild* AllocPDNSRequestChild(const nsCString& aHost,
const uint32_t& aFlags);
virtual bool DeallocPDNSRequestChild(PDNSRequestChild*);
virtual PRemoteOpenFileChild* AllocPRemoteOpenFileChild(const URIParams&,
const OptionalURIParams&);
virtual bool DeallocPRemoteOpenFileChild(PRemoteOpenFileChild*);

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

@ -16,6 +16,7 @@
#ifdef NECKO_PROTOCOL_rtsp
#include "mozilla/net/RtspControllerParent.h"
#endif
#include "mozilla/net/DNSRequestParent.h"
#include "mozilla/net/RemoteOpenFileParent.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/TabParent.h"
@ -428,6 +429,32 @@ NeckoParent::DeallocPUDPSocketParent(PUDPSocketParent* actor)
return true;
}
PDNSRequestParent*
NeckoParent::AllocPDNSRequestParent(const nsCString& aHost,
const uint32_t& aFlags)
{
DNSRequestParent *p = new DNSRequestParent();
p->AddRef();
return p;
}
bool
NeckoParent::RecvPDNSRequestConstructor(PDNSRequestParent* aActor,
const nsCString& aHost,
const uint32_t& aFlags)
{
static_cast<DNSRequestParent*>(aActor)->DoAsyncResolve(aHost, aFlags);
return true;
}
bool
NeckoParent::DeallocPDNSRequestParent(PDNSRequestParent* aParent)
{
DNSRequestParent *p = static_cast<DNSRequestParent*>(aParent);
p->Release();
return true;
}
PRemoteOpenFileParent*
NeckoParent::AllocPRemoteOpenFileParent(const URIParams& aURI,
const OptionalURIParams& aAppURI)

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

@ -124,6 +124,12 @@ protected:
const uint16_t& aPort,
const nsCString& aFilter);
virtual bool DeallocPUDPSocketParent(PUDPSocketParent*);
virtual PDNSRequestParent* AllocPDNSRequestParent(const nsCString& aHost,
const uint32_t& aFlags);
virtual bool RecvPDNSRequestConstructor(PDNSRequestParent* actor,
const nsCString& hostName,
const uint32_t& flags);
virtual bool DeallocPDNSRequestParent(PDNSRequestParent*);
virtual bool RecvHTMLDNSPrefetch(const nsString& hostname,
const uint16_t& flags);
virtual bool RecvCancelHTMLDNSPrefetch(const nsString& hostname,

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

@ -16,6 +16,7 @@ include protocol PTCPSocket;
include protocol PTCPServerSocket;
include protocol PUDPSocket;
include protocol PRemoteOpenFile;
include protocol PDNSRequest;
include protocol PBlob; //FIXME: bug #792908
include protocol PRtspController;
@ -41,6 +42,7 @@ sync protocol PNecko
manages PTCPSocket;
manages PTCPServerSocket;
manages PUDPSocket;
manages PDNSRequest;
manages PRemoteOpenFile;
manages PRtspController;
@ -59,6 +61,8 @@ parent:
PTCPServerSocket(uint16_t localPort, uint16_t backlog, nsString binaryType);
PUDPSocket(nsCString host, uint16_t port, nsCString filter);
PDNSRequest(nsCString hostName, uint32_t flags);
PRemoteOpenFile(URIParams fileuri, OptionalURIParams appuri);
HTMLDNSPrefetch(nsString hostname, uint16_t flags);

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

@ -0,0 +1,7 @@
//
// Run test script in content process instead of chrome (xpcshell's default)
//
function run_test() {
run_test_in_child("../unit/test_dns_service.js");
}

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

@ -9,6 +9,7 @@ support-files = disabled_test_bug528292_wrap.js
[test_channel_close_wrap.js]
[test_cookie_header_wrap.js]
[test_cookiejars_wrap.js]
[test_dns_service_wrap.js]
[test_duplicate_headers_wrap.js]
[test_event_sink_wrap.js]
[test_head_wrap.js]