michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsDNSPrefetch.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsString.h" michael@0: #include "nsThreadUtils.h" michael@0: michael@0: #include "nsIDNSListener.h" michael@0: #include "nsIDNSService.h" michael@0: #include "nsICancelable.h" michael@0: #include "nsIURI.h" michael@0: michael@0: static nsIDNSService *sDNSService = nullptr; michael@0: michael@0: nsresult michael@0: nsDNSPrefetch::Initialize(nsIDNSService *aDNSService) michael@0: { michael@0: NS_IF_RELEASE(sDNSService); michael@0: sDNSService = aDNSService; michael@0: NS_IF_ADDREF(sDNSService); michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: nsDNSPrefetch::Shutdown() michael@0: { michael@0: NS_IF_RELEASE(sDNSService); michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsDNSPrefetch::nsDNSPrefetch(nsIURI *aURI, michael@0: nsIDNSListener *aListener, michael@0: bool storeTiming) michael@0: : mStoreTiming(storeTiming) michael@0: , mListener(do_GetWeakReference(aListener)) michael@0: { michael@0: aURI->GetAsciiHost(mHostname); michael@0: } michael@0: michael@0: nsresult michael@0: nsDNSPrefetch::Prefetch(uint16_t flags) michael@0: { michael@0: if (mHostname.IsEmpty()) michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: michael@0: if (!sDNSService) michael@0: return NS_ERROR_NOT_AVAILABLE; michael@0: michael@0: nsCOMPtr tmpOutstanding; michael@0: michael@0: if (mStoreTiming) michael@0: mStartTimestamp = mozilla::TimeStamp::Now(); michael@0: // If AsyncResolve fails, for example because prefetching is disabled, michael@0: // then our timing will be useless. However, in such a case, michael@0: // mEndTimestamp will be a null timestamp and callers should check michael@0: // TimingsValid() before using the timing. michael@0: nsCOMPtr mainThread = do_GetMainThread(); michael@0: return sDNSService->AsyncResolve(mHostname, michael@0: flags | nsIDNSService::RESOLVE_SPECULATE, michael@0: this, mainThread, michael@0: getter_AddRefs(tmpOutstanding)); michael@0: } michael@0: michael@0: nsresult michael@0: nsDNSPrefetch::PrefetchLow(bool refreshDNS) michael@0: { michael@0: return Prefetch(nsIDNSService::RESOLVE_PRIORITY_LOW | michael@0: (refreshDNS ? nsIDNSService::RESOLVE_BYPASS_CACHE : 0)); michael@0: } michael@0: michael@0: nsresult michael@0: nsDNSPrefetch::PrefetchMedium(bool refreshDNS) michael@0: { michael@0: return Prefetch(nsIDNSService::RESOLVE_PRIORITY_MEDIUM | michael@0: (refreshDNS ? nsIDNSService::RESOLVE_BYPASS_CACHE : 0)); michael@0: } michael@0: michael@0: nsresult michael@0: nsDNSPrefetch::PrefetchHigh(bool refreshDNS) michael@0: { michael@0: return Prefetch(refreshDNS ? michael@0: nsIDNSService::RESOLVE_BYPASS_CACHE : 0); michael@0: } michael@0: michael@0: michael@0: NS_IMPL_ISUPPORTS(nsDNSPrefetch, nsIDNSListener) michael@0: michael@0: NS_IMETHODIMP michael@0: nsDNSPrefetch::OnLookupComplete(nsICancelable *request, michael@0: nsIDNSRecord *rec, michael@0: nsresult status) michael@0: { michael@0: MOZ_ASSERT(NS_IsMainThread(), "Expecting DNS callback on main thread."); michael@0: michael@0: if (mStoreTiming) { michael@0: mEndTimestamp = mozilla::TimeStamp::Now(); michael@0: } michael@0: nsCOMPtr listener = do_QueryReferent(mListener); michael@0: if (listener) { michael@0: listener->OnLookupComplete(request, rec, status); michael@0: } michael@0: return NS_OK; michael@0: }