author | Arpit Bharti <arpitbharti73@gmail.com> |
Fri, 23 Aug 2019 10:56:59 +0000 | |
changeset 489846 | 03c9cce08d1126e337938b919852704cb3469358 |
parent 489845 | d9b024555ac15ecc7f9e9e6e01f92a752deb9040 |
child 489847 | e1a536d26d80db9fe9960e1d0c10bddc583f64f1 |
push id | 36491 |
push user | malexandru@mozilla.com |
push date | Mon, 26 Aug 2019 22:30:36 +0000 |
treeherder | mozilla-central@5c7635de0cb6 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | leplatrem, kmag |
bugs | 1563246 |
milestone | 70.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/netwerk/dns/nsEffectiveTLDService.cpp +++ b/netwerk/dns/nsEffectiveTLDService.cpp @@ -5,62 +5,103 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // This service reads a file of rules describing TLD-like domain names. For a // complete description of the expected file format and parsing rules, see // http://wiki.mozilla.org/Gecko:Effective_TLD_Service #include "mozilla/ArrayUtils.h" #include "mozilla/HashFunctions.h" -#include "mozilla/Maybe.h" #include "mozilla/MemoryReporting.h" +#include "mozilla/ResultExtensions.h" #include "MainThreadUtils.h" +#include "nsCRT.h" #include "nsEffectiveTLDService.h" +#include "nsIFile.h" #include "nsIIDNService.h" -#include "nsNetUtil.h" -#include "prnetdb.h" +#include "nsIObserverService.h" #include "nsIURI.h" #include "nsNetCID.h" +#include "nsNetUtil.h" #include "nsServiceManagerUtils.h" +#include "prnetdb.h" namespace etld_dafsa { // Generated file that includes kDafsa #include "etld_data.inc" } // namespace etld_dafsa using namespace mozilla; NS_IMPL_ISUPPORTS(nsEffectiveTLDService, nsIEffectiveTLDService, - nsIMemoryReporter) + nsIMemoryReporter, nsIObserver) // ---------------------------------------------------------------------- static nsEffectiveTLDService* gService = nullptr; nsEffectiveTLDService::nsEffectiveTLDService() - : mIDNService(), mGraph(etld_dafsa::kDafsa) {} + : mIDNService(), mGraphLock("nsEffectiveTLDService::mGraph") { + mGraph.emplace(etld_dafsa::kDafsa); +} nsresult nsEffectiveTLDService::Init() { + nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); + obs->AddObserver(this, "public-suffix-list-updated", false); + if (gService) { return NS_ERROR_ALREADY_INITIALIZED; } nsresult rv; mIDNService = do_GetService(NS_IDNSERVICE_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; gService = this; RegisterWeakMemoryReporter(this); return NS_OK; } +NS_IMETHODIMP nsEffectiveTLDService::Observe(nsISupports* aSubject, + const char* aTopic, + const char16_t* aData) { + /** + * Signal sent from netwerk/dns/PublicSuffixList.jsm + * aSubject is the nsIFile object for dafsa.bin + * aData is the absolute path to the dafsa.bin file (not used) + */ + if (aSubject && (nsCRT::strcmp(aTopic, "public-suffix-list-updated") == 0)) { + nsCOMPtr<nsIFile> mDafsaBinFile(do_QueryInterface(aSubject)); + NS_ENSURE_TRUE(mDafsaBinFile, NS_ERROR_ILLEGAL_VALUE); + + AutoWriteLock lock(mGraphLock); + // Reset mGraph with kDafsa in case reassigning to mDafsaMap fails + mGraph.reset(); + mGraph.emplace(etld_dafsa::kDafsa); + + mDafsaMap.reset(); + mMruTable.Clear(); + + MOZ_TRY(mDafsaMap.init(mDafsaBinFile)); + + size_t size = mDafsaMap.size(); + const uint8_t* remoteDafsaPtr = mDafsaMap.get<uint8_t>().get(); + + auto remoteDafsa = mozilla::MakeSpan(remoteDafsaPtr, size); + + mGraph.reset(); + mGraph.emplace(remoteDafsa); + } + return NS_OK; +} + nsEffectiveTLDService::~nsEffectiveTLDService() { UnregisterWeakMemoryReporter(this); if (mIDNService) { // Only clear gService if Init() finished successfully. gService = nullptr; } } @@ -249,31 +290,35 @@ nsresult nsEffectiveTLDService::GetBaseD // have multiple attributes (e.g. IsWild() and IsNormal()). const char* prevDomain = nullptr; const char* currDomain = aHostname.get(); const char* nextDot = strchr(currDomain, '.'); const char* end = currDomain + aHostname.Length(); // Default value of *eTLD is currDomain as set in the while loop below const char* eTLD = nullptr; while (true) { - // sanity check the string we're about to look up: it should not begin with - // a '.'; this would mean the hostname began with a '.' or had an + // sanity check the string we're about to look up: it should not begin + // with a '.'; this would mean the hostname began with a '.' or had an // embedded '..' sequence. if (*currDomain == '.') { // Update the MRU table if in use. if (entry) { entry->Set( TLDCacheEntry{aHostname, EmptyCString(), NS_ERROR_INVALID_ARG}); } return NS_ERROR_INVALID_ARG; } - // Perform the lookup. - const int result = mGraph.Lookup(Substring(currDomain, end)); + int result; + { + AutoReadLock lock(mGraphLock); + // Perform the lookup. + result = mGraph->Lookup(Substring(currDomain, end)); + } if (result != Dafsa::kKeyNotFound) { if (result == kWildcardRule && prevDomain) { // wildcard rules imply an eTLD one level inferior to the match. eTLD = prevDomain; break; } if ((result == kWildcardRule || result != kExceptionRule) || !nextDot) { // specific match, or we've hit the top domain level @@ -281,16 +326,17 @@ nsresult nsEffectiveTLDService::GetBaseD break; } if (result == kExceptionRule) { // exception rules imply an eTLD one level superior to the match. eTLD = nextDot + 1; break; } } + if (!nextDot) { // we've hit the top domain level; use it by default. eTLD = currDomain; break; } prevDomain = currDomain; currDomain = nextDot + 1;
--- a/netwerk/dns/nsEffectiveTLDService.h +++ b/netwerk/dns/nsEffectiveTLDService.h @@ -3,33 +3,40 @@ * 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 "mozilla/AutoMemMap.h" +#include "mozilla/Attributes.h" +#include "mozilla/Dafsa.h" +#include "mozilla/Maybe.h" +#include "mozilla/MemoryReporting.h" +#include "mozilla/MruCache.h" +#include "mozilla/RWLock.h" + +#include "nsCOMPtr.h" #include "nsHashKeys.h" #include "nsIMemoryReporter.h" +#include "nsIObserver.h" #include "nsString.h" -#include "nsCOMPtr.h" -#include "mozilla/Attributes.h" -#include "mozilla/Dafsa.h" -#include "mozilla/MemoryReporting.h" -#include "mozilla/MruCache.h" class nsIIDNService; class nsEffectiveTLDService final : public nsIEffectiveTLDService, + public nsIObserver, public nsIMemoryReporter { public: NS_DECL_ISUPPORTS NS_DECL_NSIEFFECTIVETLDSERVICE NS_DECL_NSIMEMORYREPORTER + NS_DECL_NSIOBSERVER nsEffectiveTLDService(); nsresult Init(); static nsEffectiveTLDService* GetInstance(); size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf); @@ -37,17 +44,23 @@ class nsEffectiveTLDService final : publ nsresult GetBaseDomainInternal(nsCString& aHostname, int32_t aAdditionalParts, nsACString& aBaseDomain); nsresult NormalizeHostname(nsCString& aHostname); ~nsEffectiveTLDService(); nsCOMPtr<nsIIDNService> mIDNService; // The DAFSA provides a compact encoding of the rather large eTLD list. - mozilla::Dafsa mGraph; + mozilla::Maybe<mozilla::Dafsa> mGraph; + + // Memory map used for a new updated dafsa + mozilla::loader::AutoMemMap mDafsaMap; + + // Lock for mGraph and mDafsaMap + mozilla::RWLock mGraphLock; // Note that the cache entries here can record entries that were cached // successfully or unsuccessfully. mResult must be checked before using an // entry. If it's a success error code, the cache entry is valid and can be // used. struct TLDCacheEntry { nsCString mHost; nsCString mBaseDomain;
new file mode 100644 --- /dev/null +++ b/netwerk/dns/tests/unit/test_nsEffectiveTLDService_Reload_DAFSA.js @@ -0,0 +1,31 @@ +"use strict"; + +const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); + +const SIGNAL = "public-suffix-list-updated"; + +add_task(async () => { + info("Before fake dafsa reload."); + + let suffix = Services.eTLD.getPublicSuffixFromHost("website.xpcshelltest"); + Assert.equal( + suffix, + "xpcshelltest", + "Fake Suffix does not exist in current PSL." + ); +}); + +add_task(async () => { + info("After fake dafsa reload."); + + // reload the PSL with fake data containing .xpcshelltest + const fakeDafsaFile = do_get_file("data/fake_remote_dafsa.bin"); + Services.obs.notifyObservers(fakeDafsaFile, SIGNAL, fakeDafsaFile.path); + + let suffix = Services.eTLD.getPublicSuffixFromHost("website.xpcshelltest"); + Assert.equal( + suffix, + "website.xpcshelltest", + "Fake Suffix now exists in PSL after DAFSA reload." + ); +});
--- a/netwerk/dns/tests/unit/xpcshell.ini +++ b/netwerk/dns/tests/unit/xpcshell.ini @@ -1,6 +1,7 @@ [DEFAULT] head = ../../../../services/common/tests/unit/head_global.js ../../../../services/common/tests/unit/head_helpers.js firefox-appdir = browser support-files = data/** [test_PublicSuffixList.js] +[test_nsEffectiveTLDService_Reload_DAFSA.js]