Bug 1360480 - about:url-classifier: Cache information. r=francois

MozReview-Commit-ID: 4YXtb2KPgwL

--HG--
extra : rebase_source : ad9f897aa5772d6001a757e189730d427713f915
This commit is contained in:
DimiL 2017-05-17 10:32:33 +08:00
parent de5fa4f269
commit c632a44157
18 changed files with 651 additions and 35 deletions

View File

@ -886,6 +886,18 @@ Classifier::ApplyFullHashes(nsTArray<TableUpdate*>* aUpdates)
return NS_OK; return NS_OK;
} }
void
Classifier::GetCacheInfo(const nsACString& aTable,
nsIUrlClassifierCacheInfo** aCache)
{
LookupCache* lookupCache = GetLookupCache(aTable);
if (!lookupCache) {
return;
}
lookupCache->GetCacheInfo(aCache);
}
void void
Classifier::DropStores() Classifier::DropStores()
{ {

View File

@ -124,6 +124,9 @@ public:
LookupCache *GetLookupCache(const nsACString& aTable, LookupCache *GetLookupCache(const nsACString& aTable,
bool aForUpdate = false); bool aForUpdate = false);
void GetCacheInfo(const nsACString& aTable,
nsIUrlClassifierCacheInfo** aCache);
private: private:
void DropStores(); void DropStores();
void DeleteTables(nsIFile* aDirectory, const nsTArray<nsCString>& aTables); void DeleteTables(nsIFile* aDirectory, const nsTArray<nsCString>& aTables);

View File

@ -6,11 +6,13 @@
#include "LookupCache.h" #include "LookupCache.h"
#include "HashStore.h" #include "HashStore.h"
#include "nsISeekableStream.h" #include "nsISeekableStream.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Telemetry.h" #include "mozilla/Telemetry.h"
#include "mozilla/Logging.h" #include "mozilla/Logging.h"
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "prprf.h" #include "prprf.h"
#include "Classifier.h" #include "Classifier.h"
#include "nsUrlClassifierInfo.h"
// We act as the main entry point for all the real lookups, // We act as the main entry point for all the real lookups,
// so note that those are not done to the actual HashStore. // so note that those are not done to the actual HashStore.
@ -47,6 +49,22 @@ const int CacheResultV4::VER = CacheResult::V4;
const int LookupCacheV2::VER = 2; const int LookupCacheV2::VER = 2;
static
void CStringToHexString(const nsACString& aIn, nsACString& aOut)
{
static const char* const lut = "0123456789ABCDEF";
size_t len = aIn.Length();
MOZ_ASSERT(len <= COMPLETE_SIZE);
aOut.SetCapacity(2 * len);
for (size_t i = 0; i < aIn.Length(); ++i) {
const char c = static_cast<const char>(aIn[i]);
aOut.Append(lut[(c >> 4) & 0x0F]);
aOut.Append(lut[c & 15]);
}
}
LookupCache::LookupCache(const nsACString& aTableName, LookupCache::LookupCache(const nsACString& aTableName,
const nsACString& aProvider, const nsACString& aProvider,
nsIFile* aRootStoreDir) nsIFile* aRootStoreDir)
@ -213,6 +231,49 @@ LookupCache::ClearAll()
mPrimed = false; mPrimed = false;
} }
void
LookupCache::GetCacheInfo(nsIUrlClassifierCacheInfo** aCache)
{
MOZ_ASSERT(aCache);
RefPtr<nsUrlClassifierCacheInfo> info = new nsUrlClassifierCacheInfo;
info->table = mTableName;
for (auto iter = mCache.ConstIter(); !iter.Done(); iter.Next()) {
RefPtr<nsUrlClassifierCacheEntry> entry = new nsUrlClassifierCacheEntry;
// Set prefix of the cache entry.
nsAutoCString prefix(reinterpret_cast<const char*>(&iter.Key()), PREFIX_SIZE);
CStringToHexString(prefix, entry->prefix);
// Set expiry of the cache entry.
CachedFullHashResponse* response = iter.Data();
entry->expirySec = response->negativeCacheExpirySec;
// Set positive cache.
FullHashExpiryCache& fullHashes = response->fullHashes;
for (auto iter2 = fullHashes.ConstIter(); !iter2.Done(); iter2.Next()) {
RefPtr<nsUrlClassifierPositiveCacheEntry> match =
new nsUrlClassifierPositiveCacheEntry;
// Set fullhash of positive cache entry.
CStringToHexString(iter2.Key(), match->fullhash);
// Set expiry of positive cache entry.
match->expirySec = iter2.Data();
entry->matches.AppendElement(
static_cast<nsIUrlClassifierPositiveCacheEntry*>(match));
}
info->entries.AppendElement(static_cast<nsIUrlClassifierCacheEntry*>(entry));
}
NS_ADDREF(*aCache = info);
return;
}
/* static */ bool /* static */ bool
LookupCache::IsCanonicalizedIP(const nsACString& aHost) LookupCache::IsCanonicalizedIP(const nsACString& aHost)
{ {
@ -425,21 +486,6 @@ LookupCache::LoadPrefixSet()
} }
#if defined(DEBUG) #if defined(DEBUG)
static
void CStringToHexString(const nsACString& aIn, nsACString& aOut)
{
static const char* const lut = "0123456789ABCDEF";
// 32 bytes is the longest hash
size_t len = COMPLETE_SIZE;
aOut.SetCapacity(2 * len);
for (size_t i = 0; i < aIn.Length(); ++i) {
const char c = static_cast<const char>(aIn[i]);
aOut.Append(lut[(c >> 4) & 0x0F]);
aOut.Append(lut[c & 15]);
}
}
static static
nsCString GetFormattedTimeString(int64_t aCurTimeSec) nsCString GetFormattedTimeString(int64_t aCurTimeSec)
{ {
@ -461,16 +507,19 @@ LookupCache::DumpCache()
for (auto iter = mCache.ConstIter(); !iter.Done(); iter.Next()) { for (auto iter = mCache.ConstIter(); !iter.Done(); iter.Next()) {
CachedFullHashResponse* response = iter.Data(); CachedFullHashResponse* response = iter.Data();
LOG(("Caches prefix: %X, Expire time: %s",
iter.Key(), nsAutoCString prefix;
GetFormattedTimeString(response->negativeCacheExpirySec).get())); CStringToHexString(
nsCString(reinterpret_cast<const char*>(&iter.Key()), PREFIX_SIZE), prefix);
LOG(("Cache prefix(%s): %s, Expiry: %s", mTableName.get(), prefix.get(),
GetFormattedTimeString(response->negativeCacheExpirySec).get()));
FullHashExpiryCache& fullHashes = response->fullHashes; FullHashExpiryCache& fullHashes = response->fullHashes;
for (auto iter2 = fullHashes.ConstIter(); !iter2.Done(); iter2.Next()) { for (auto iter2 = fullHashes.ConstIter(); !iter2.Done(); iter2.Next()) {
nsAutoCString strFullhash; nsAutoCString fullhash;
CStringToHexString(iter2.Key(), strFullhash); CStringToHexString(iter2.Key(), fullhash);
LOG((" - %s, Expire time: %s", strFullhash.get(), LOG((" - %s, Expiry: %s", fullhash.get(),
GetFormattedTimeString(iter2.Data()).get())); GetFormattedTimeString(iter2.Data()).get()));
} }
} }
} }
@ -601,18 +650,14 @@ LookupCacheV2::AddGethashResultToCache(AddCompleteArray& aAddCompletes,
reinterpret_cast<const char*>(add.CompleteHash().buf), COMPLETE_SIZE); reinterpret_cast<const char*>(add.CompleteHash().buf), COMPLETE_SIZE);
CachedFullHashResponse* response = mCache.LookupOrAdd(add.ToUint32()); CachedFullHashResponse* response = mCache.LookupOrAdd(add.ToUint32());
// Set negative cache expiry to the same value as positive cache response->negativeCacheExpirySec = defaultExpirySec;
// expiry when the gethash request returns a complete match.
if (response->negativeCacheExpirySec == 0) {
response->negativeCacheExpirySec = defaultExpirySec;
}
FullHashExpiryCache& fullHashes = response->fullHashes; FullHashExpiryCache& fullHashes = response->fullHashes;
fullHashes.Put(fullhash, defaultExpirySec); fullHashes.Put(fullhash, defaultExpirySec);
} }
for (const Prefix& prefix : aMissPrefixes) { for (const Prefix& prefix : aMissPrefixes) {
CachedFullHashResponse* response = mCache.LookupOrAdd(prefix.ToUint32()); CachedFullHashResponse* response = mCache.LookupOrAdd(prefix.ToUint32());
response->negativeCacheExpirySec = defaultExpirySec; response->negativeCacheExpirySec = defaultExpirySec;
} }
} }

View File

@ -18,6 +18,7 @@
#include "VariableLengthPrefixSet.h" #include "VariableLengthPrefixSet.h"
#include "mozilla/Logging.h" #include "mozilla/Logging.h"
#include "mozilla/TypedEnumBits.h" #include "mozilla/TypedEnumBits.h"
#include "nsIUrlClassifierInfo.h"
namespace mozilla { namespace mozilla {
namespace safebrowsing { namespace safebrowsing {
@ -209,6 +210,8 @@ public:
void DumpCache(); void DumpCache();
#endif #endif
void GetCacheInfo(nsIUrlClassifierCacheInfo** aCache);
virtual nsresult Open(); virtual nsresult Open();
virtual nsresult Init() = 0; virtual nsresult Init() = 0;
virtual nsresult ClearPrefixes() = 0; virtual nsresult ClearPrefixes() = 0;

View File

@ -12,6 +12,7 @@ TEST_DIRS += ['tests']
XPIDL_SOURCES += [ XPIDL_SOURCES += [
'nsIUrlClassifierDBService.idl', 'nsIUrlClassifierDBService.idl',
'nsIUrlClassifierHashCompleter.idl', 'nsIUrlClassifierHashCompleter.idl',
'nsIUrlClassifierInfo.idl',
'nsIUrlClassifierPrefixSet.idl', 'nsIUrlClassifierPrefixSet.idl',
'nsIUrlClassifierStreamUpdater.idl', 'nsIUrlClassifierStreamUpdater.idl',
'nsIUrlClassifierUtils.idl', 'nsIUrlClassifierUtils.idl',
@ -30,6 +31,7 @@ UNIFIED_SOURCES += [
'LookupCacheV4.cpp', 'LookupCacheV4.cpp',
'nsCheckSummedOutputStream.cpp', 'nsCheckSummedOutputStream.cpp',
'nsUrlClassifierDBService.cpp', 'nsUrlClassifierDBService.cpp',
'nsUrlClassifierInfo.cpp',
'nsUrlClassifierProxies.cpp', 'nsUrlClassifierProxies.cpp',
'nsUrlClassifierUtils.cpp', 'nsUrlClassifierUtils.cpp',
'protobuf/safebrowsing.pb.cc', 'protobuf/safebrowsing.pb.cc',

View File

@ -201,6 +201,11 @@ interface nsIUrlClassifierDBService : nsISupports
* for use in tests. * for use in tests.
*/ */
void reloadDatabase(); void reloadDatabase();
/**
* Empty all the caches.
*/
void clearCache();
}; };
/** /**

View File

@ -0,0 +1,73 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "nsISupports.idl"
#include "nsIArray.idl"
/**
* nsIUrlClassifierPositiveCacheEntry Represents a positive cache entry.
*/
[scriptable, uuid(b3c27f8c-7db8-4f3f-97a5-5a94d781e565)]
interface nsIUrlClassifierPositiveCacheEntry : nsISupports {
/**
* Fullhash for the positive cache entry.
*/
readonly attribute ACString fullhash;
/**
* Positive cache expiry.
*/
readonly attribute long long expiry;
};
/**
* nsIUrlClassifierCacheEntry contains cache information for
* a given prefix.
*/
[scriptable, uuid(d6297907-8236-4126-adaf-c3aa239a0d40)]
interface nsIUrlClassifierCacheEntry : nsISupports {
/**
* Prefix for this cache entry.
*/
readonly attribute ACString prefix;
/**
* Negative cache expiry.
*/
readonly attribute long long expiry;
/**
* An array of nsIUrlClassifierPositiveCacheEntry, each item represents
* a positive cache entry with its fullhash and expiry.
*/
readonly attribute nsIArray matches;
};
/**
* Cache information for a given table.
*/
[scriptable, function, uuid(69384f24-d9c5-4462-b24e-351c69e3b46a)]
interface nsIUrlClassifierCacheInfo : nsISupports {
/**
* Table name.
*/
readonly attribute ACString table;
/*
* An array of nsIUrlClassifierCacheEntry.
*/
readonly attribute nsIArray entries;
};
/**
* Interface to query url-classifier information.
*/
[scriptable, function, uuid(411bbff4-1b88-4687-aa36-e2bbdd93f6e8)]
interface nsIUrlClassifierInfo : nsISupports {
/**
* A synchronous call to return cache information for the table.
*/
nsIUrlClassifierCacheInfo getCacheInfo(in ACString table);
};

View File

@ -734,6 +734,18 @@ nsUrlClassifierDBServiceWorker::ReloadDatabase()
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsUrlClassifierDBServiceWorker::ClearCache()
{
nsTArray<nsCString> tables;
nsresult rv = mClassifier->ActiveTables(tables);
NS_ENSURE_SUCCESS(rv, rv);
mClassifier->ResetTables(Classifier::Clear_Cache, tables);
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
nsUrlClassifierDBServiceWorker::CancelUpdate() nsUrlClassifierDBServiceWorker::CancelUpdate()
{ {
@ -944,6 +956,19 @@ nsUrlClassifierDBServiceWorker::ClearLastResults()
return NS_OK; return NS_OK;
} }
nsresult
nsUrlClassifierDBServiceWorker::GetCacheInfo(const nsACString& aTable,
nsIUrlClassifierCacheInfo** aCache)
{
MOZ_ASSERT(!NS_IsMainThread(), "Must be on the background thread");
if (!mClassifier) {
return NS_ERROR_NOT_AVAILABLE;
}
mClassifier->GetCacheInfo(aTable, aCache);
return NS_OK;
}
bool bool
nsUrlClassifierDBServiceWorker::IsSameAsLastResults(CacheResultArray& aResult) nsUrlClassifierDBServiceWorker::IsSameAsLastResults(CacheResultArray& aResult)
{ {
@ -1507,6 +1532,7 @@ NS_INTERFACE_MAP_BEGIN(nsUrlClassifierDBService)
// Only nsIURIClassifier is supported in the content process! // Only nsIURIClassifier is supported in the content process!
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIUrlClassifierDBService, XRE_IsParentProcess()) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIUrlClassifierDBService, XRE_IsParentProcess())
NS_INTERFACE_MAP_ENTRY(nsIURIClassifier) NS_INTERFACE_MAP_ENTRY(nsIURIClassifier)
NS_INTERFACE_MAP_ENTRY(nsIUrlClassifierInfo)
NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIObserver, XRE_IsParentProcess()) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIObserver, XRE_IsParentProcess())
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIURIClassifier) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIURIClassifier)
NS_INTERFACE_MAP_END NS_INTERFACE_MAP_END
@ -2198,6 +2224,24 @@ nsUrlClassifierDBService::ReloadDatabase()
return mWorkerProxy->ReloadDatabase(); return mWorkerProxy->ReloadDatabase();
} }
NS_IMETHODIMP
nsUrlClassifierDBService::ClearCache()
{
NS_ENSURE_TRUE(gDbBackgroundThread, NS_ERROR_NOT_INITIALIZED);
return mWorkerProxy->ClearCache();
}
NS_IMETHODIMP
nsUrlClassifierDBService::GetCacheInfo(const nsACString& aTable,
nsIUrlClassifierCacheInfo** aCache)
{
NS_ENSURE_TRUE(gDbBackgroundThread, NS_ERROR_NOT_INITIALIZED);
return mWorkerProxy->GetCacheInfo(aTable, aCache);
}
nsresult nsresult
nsUrlClassifierDBService::CacheCompletions(CacheResultArray *results) nsUrlClassifierDBService::CacheCompletions(CacheResultArray *results)
{ {

View File

@ -15,6 +15,7 @@
#include "nsIUrlClassifierHashCompleter.h" #include "nsIUrlClassifierHashCompleter.h"
#include "nsIUrlListManager.h" #include "nsIUrlListManager.h"
#include "nsIUrlClassifierDBService.h" #include "nsIUrlClassifierDBService.h"
#include "nsIUrlClassifierInfo.h"
#include "nsIURIClassifier.h" #include "nsIURIClassifier.h"
#include "nsToolkitCompsCID.h" #include "nsToolkitCompsCID.h"
#include "nsICryptoHMAC.h" #include "nsICryptoHMAC.h"
@ -83,6 +84,7 @@ TablesToResponse(const nsACString& tables);
// calls to the background thread. // calls to the background thread.
class nsUrlClassifierDBService final : public nsIUrlClassifierDBService, class nsUrlClassifierDBService final : public nsIUrlClassifierDBService,
public nsIURIClassifier, public nsIURIClassifier,
public nsIUrlClassifierInfo,
public nsIObserver public nsIObserver
{ {
public: public:
@ -98,6 +100,7 @@ public:
NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIURLCLASSIFIERDBSERVICE NS_DECL_NSIURLCLASSIFIERDBSERVICE
NS_DECL_NSIURICLASSIFIER NS_DECL_NSIURICLASSIFIER
NS_DECL_NSIURLCLASSIFIERINFO
NS_DECL_NSIOBSERVER NS_DECL_NSIOBSERVER
bool CanComplete(const nsACString &tableName); bool CanComplete(const nsACString &tableName);
@ -229,6 +232,10 @@ public:
// Should be called on the worker thread. // Should be called on the worker thread.
void FlushAndDisableAsyncUpdate(); void FlushAndDisableAsyncUpdate();
// A synchronous call to get cache information for the given table.
// This is only used by about:url-classifier now.
nsresult GetCacheInfo(const nsACString& aTable,
nsIUrlClassifierCacheInfo** aCache);
private: private:
// No subclassing // No subclassing
~nsUrlClassifierDBServiceWorker(); ~nsUrlClassifierDBServiceWorker();

View File

@ -0,0 +1,105 @@
/* This Source Code Form is subject to the terms of the Mozilla
* 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 "nsUrlClassifierInfo.h"
NS_IMPL_ISUPPORTS(nsUrlClassifierPositiveCacheEntry,
nsIUrlClassifierPositiveCacheEntry)
nsUrlClassifierPositiveCacheEntry::nsUrlClassifierPositiveCacheEntry()
{
}
NS_IMETHODIMP
nsUrlClassifierPositiveCacheEntry::GetExpiry(int64_t* aExpiry)
{
if (!aExpiry) {
return NS_ERROR_NULL_POINTER;
}
*aExpiry = expirySec;
return NS_OK;
}
NS_IMETHODIMP
nsUrlClassifierPositiveCacheEntry::GetFullhash(nsACString& aFullHash)
{
aFullHash = fullhash;
return NS_OK;
}
NS_IMPL_ISUPPORTS(nsUrlClassifierCacheEntry,
nsIUrlClassifierCacheEntry)
nsUrlClassifierCacheEntry::nsUrlClassifierCacheEntry()
{
}
NS_IMETHODIMP
nsUrlClassifierCacheEntry::GetPrefix(nsACString& aPrefix)
{
aPrefix = prefix;
return NS_OK;
}
NS_IMETHODIMP
nsUrlClassifierCacheEntry::GetExpiry(int64_t* aExpiry)
{
if (!aExpiry) {
return NS_ERROR_NULL_POINTER;
}
*aExpiry = expirySec;
return NS_OK;
}
NS_IMETHODIMP
nsUrlClassifierCacheEntry::GetMatches(nsIArray** aMatches)
{
if (!aMatches) {
return NS_ERROR_NULL_POINTER;
}
nsCOMPtr<nsIMutableArray> array(do_CreateInstance(NS_ARRAY_CONTRACTID));
for (uint32_t i = 0;i < matches.Length(); i++) {
array->AppendElement(matches[i], false);
}
NS_ADDREF(*aMatches = array);
return NS_OK;
}
NS_IMPL_ISUPPORTS(nsUrlClassifierCacheInfo,
nsIUrlClassifierCacheInfo)
nsUrlClassifierCacheInfo::nsUrlClassifierCacheInfo()
{
}
NS_IMETHODIMP
nsUrlClassifierCacheInfo::GetTable(nsACString& aTable)
{
aTable = table;
return NS_OK;
}
NS_IMETHODIMP
nsUrlClassifierCacheInfo::GetEntries(nsIArray** aEntries)
{
if (!aEntries) {
return NS_ERROR_NULL_POINTER;
}
nsCOMPtr<nsIMutableArray> array(do_CreateInstance(NS_ARRAY_CONTRACTID));
for (uint32_t i = 0;i < entries.Length(); i++) {
array->AppendElement(entries[i], false);
}
NS_ADDREF(*aEntries = array);
return NS_OK;
}

View File

@ -0,0 +1,64 @@
/* This Source Code Form is subject to the terms of the Mozilla
* 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 nsUrlClassifierInfo_h_
#define nsUrlClassifierInfo_h_
#include "nsIUrlClassifierInfo.h"
#include "nsString.h"
class nsUrlClassifierPositiveCacheEntry final : public nsIUrlClassifierPositiveCacheEntry
{
public:
nsUrlClassifierPositiveCacheEntry();
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIURLCLASSIFIERPOSITIVECACHEENTRY
private:
~nsUrlClassifierPositiveCacheEntry() {}
public:
nsCString fullhash;
int64_t expirySec;
};
class nsUrlClassifierCacheEntry final : public nsIUrlClassifierCacheEntry
{
public:
nsUrlClassifierCacheEntry();
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIURLCLASSIFIERCACHEENTRY
private:
~nsUrlClassifierCacheEntry() {}
public:
nsCString prefix;
int64_t expirySec;
nsTArray<nsCOMPtr<nsIUrlClassifierPositiveCacheEntry>> matches;
};
class nsUrlClassifierCacheInfo final : public nsIUrlClassifierCacheInfo
{
public:
nsUrlClassifierCacheInfo();
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIURLCLASSIFIERCACHEINFO
private:
~nsUrlClassifierCacheInfo() {}
public:
nsCString table;
nsTArray<nsCOMPtr<nsIUrlClassifierCacheEntry>> entries;
};
#endif // nsUrlClassifierInfo_h_

View File

@ -179,6 +179,15 @@ UrlClassifierDBServiceWorkerProxy::ReloadDatabase()
return DispatchToWorkerThread(r); return DispatchToWorkerThread(r);
} }
NS_IMETHODIMP
UrlClassifierDBServiceWorkerProxy::ClearCache()
{
nsCOMPtr<nsIRunnable> r =
NewRunnableMethod(mTarget,
&nsUrlClassifierDBServiceWorker::ClearCache);
return DispatchToWorkerThread(r);
}
nsresult nsresult
UrlClassifierDBServiceWorkerProxy::OpenDb() UrlClassifierDBServiceWorkerProxy::OpenDb()
{ {
@ -224,6 +233,29 @@ UrlClassifierDBServiceWorkerProxy::ClearLastResultsRunnable::Run()
return mTarget->ClearLastResults(); return mTarget->ClearLastResults();
} }
nsresult
UrlClassifierDBServiceWorkerProxy::GetCacheInfo(const nsACString& aTable,
nsIUrlClassifierCacheInfo** aCache)
{
nsCOMPtr<nsIRunnable> r = new GetCacheInfoRunnable(mTarget, aTable, aCache);
nsIThread* t = nsUrlClassifierDBService::BackgroundThread();
if (!t) {
return NS_ERROR_FAILURE;
}
// This blocks main thread but since 'GetCacheInfo' is only used by
// about:url-classifier so it should be fine.
mozilla::SyncRunnable::DispatchToThread(t, r);
return NS_OK;
}
NS_IMETHODIMP
UrlClassifierDBServiceWorkerProxy::GetCacheInfoRunnable::Run()
{
return mTarget->GetCacheInfo(mTable, mCache);
}
NS_IMPL_ISUPPORTS(UrlClassifierLookupCallbackProxy, NS_IMPL_ISUPPORTS(UrlClassifierLookupCallbackProxy,
nsIUrlClassifierLookupCallback) nsIUrlClassifierLookupCallback)

View File

@ -167,6 +167,24 @@ public:
RefPtr<nsUrlClassifierDBServiceWorker> mTarget; RefPtr<nsUrlClassifierDBServiceWorker> mTarget;
}; };
class GetCacheInfoRunnable: public mozilla::Runnable
{
public:
explicit GetCacheInfoRunnable(nsUrlClassifierDBServiceWorker* aTarget,
const nsACString& aTable,
nsIUrlClassifierCacheInfo** aCache)
: mTarget(aTarget),
mTable(aTable),
mCache(aCache)
{ }
NS_DECL_NSIRUNNABLE
private:
RefPtr<nsUrlClassifierDBServiceWorker> mTarget;
nsCString mTable;
nsIUrlClassifierCacheInfo** mCache;
};
public: public:
nsresult DoLocalLookup(const nsACString& spec, nsresult DoLocalLookup(const nsACString& spec,
const nsACString& tables, const nsACString& tables,
@ -177,6 +195,8 @@ public:
nsresult CacheCompletions(mozilla::safebrowsing::CacheResultArray * aEntries); nsresult CacheCompletions(mozilla::safebrowsing::CacheResultArray * aEntries);
nsresult GetCacheInfo(const nsACString& aTable,
nsIUrlClassifierCacheInfo** aCache);
private: private:
~UrlClassifierDBServiceWorkerProxy() {} ~UrlClassifierDBServiceWorkerProxy() {}

View File

@ -18,7 +18,8 @@ SetupCacheEntry(LookupCacheV2* aLookupCache,
MissPrefixArray misses; MissPrefixArray misses;
MissPrefixArray emptyMisses; MissPrefixArray emptyMisses;
nsCOMPtr<nsICryptoHash> cryptoHash = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID); nsCOMPtr<nsICryptoHash> cryptoHash =
do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID);
AddComplete* add = completes.AppendElement(fallible); AddComplete* add = completes.AppendElement(fallible);
add->complete.FromPlaintext(aCompletion, cryptoHash); add->complete.FromPlaintext(aCompletion, cryptoHash);
@ -26,11 +27,13 @@ SetupCacheEntry(LookupCacheV2* aLookupCache,
Prefix* prefix = misses.AppendElement(fallible); Prefix* prefix = misses.AppendElement(fallible);
prefix->FromPlaintext(aCompletion, cryptoHash); prefix->FromPlaintext(aCompletion, cryptoHash);
int64_t negExpirySec = aNegExpired ? EXPIRED_TIME_SEC : NOTEXPIRED_TIME_SEC; // Setup positive cache first otherwise negative cache expiry will be
aLookupCache->AddGethashResultToCache(emptyCompletes, misses, negExpirySec); // overwritten.
int64_t posExpirySec = aPosExpired ? EXPIRED_TIME_SEC : NOTEXPIRED_TIME_SEC; int64_t posExpirySec = aPosExpired ? EXPIRED_TIME_SEC : NOTEXPIRED_TIME_SEC;
aLookupCache->AddGethashResultToCache(completes, emptyMisses, posExpirySec); aLookupCache->AddGethashResultToCache(completes, emptyMisses, posExpirySec);
int64_t negExpirySec = aNegExpired ? EXPIRED_TIME_SEC : NOTEXPIRED_TIME_SEC;
aLookupCache->AddGethashResultToCache(emptyCompletes, misses, negExpirySec);
} }
static void static void
@ -42,12 +45,14 @@ SetupCacheEntry(LookupCacheV4* aLookupCache,
FullHashResponseMap map; FullHashResponseMap map;
Prefix prefix; Prefix prefix;
nsCOMPtr<nsICryptoHash> cryptoHash = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID); nsCOMPtr<nsICryptoHash> cryptoHash =
do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID);
prefix.FromPlaintext(aCompletion, cryptoHash); prefix.FromPlaintext(aCompletion, cryptoHash);
CachedFullHashResponse* response = map.LookupOrAdd(prefix.ToUint32()); CachedFullHashResponse* response = map.LookupOrAdd(prefix.ToUint32());
response->negativeCacheExpirySec = aNegExpired ? EXPIRED_TIME_SEC : NOTEXPIRED_TIME_SEC; response->negativeCacheExpirySec =
aNegExpired ? EXPIRED_TIME_SEC : NOTEXPIRED_TIME_SEC;
response->fullHashes.Put(GeneratePrefix(aCompletion, COMPLETE_SIZE), response->fullHashes.Put(GeneratePrefix(aCompletion, COMPLETE_SIZE),
aPosExpired ? EXPIRED_TIME_SEC : NOTEXPIRED_TIME_SEC); aPosExpired ? EXPIRED_TIME_SEC : NOTEXPIRED_TIME_SEC);

View File

@ -58,7 +58,11 @@ td {
text-align: center; text-align: center;
} }
#debug-table { #cache-table > tbody > tr > td:last-child {
text-align: center;
}
#debug-table, #cache-table {
margin-top: 20px; margin-top: 20px;
} }

View File

@ -21,6 +21,7 @@ function unLoad() {
window.removeEventListener("unload", unLoad); window.removeEventListener("unload", unLoad);
Provider.uninit(); Provider.uninit();
Cache.uninit();
Debug.uninit(); Debug.uninit();
} }
@ -29,6 +30,7 @@ function onLoad() {
window.addEventListener("unload", unLoad); window.addEventListener("unload", unLoad);
Provider.init(); Provider.init();
Cache.init();
Debug.init(); Debug.init();
} }
@ -179,6 +181,145 @@ var Provider = {
}; };
/*
* Cache
*/
var Cache = {
// Tables that show cahe entries.
showCacheEnties: null,
init() {
this.showCacheEnties = new Set();
this.register()
this.render();
},
uninit() {
Services.obs.removeObserver(this.refresh, UPDATE_FINISH);
},
register() {
this.refresh = this.refresh.bind(this);
Services.obs.addObserver(this.refresh, UPDATE_FINISH);
},
render() {
this.createCacheEntries();
let refreshBtn = document.getElementById("refresh-cache-btn");
refreshBtn.addEventListener("click", () => { this.refresh(); });
let clearBtn = document.getElementById("clear-cache-btn");
clearBtn.addEventListener("click", () => {
let dbservice = Cc["@mozilla.org/url-classifier/dbservice;1"]
.getService(Ci.nsIUrlClassifierDBService);
dbservice.clearCache();
// Since clearCache is async call, we just simply assume it will be
// updated in 100 milli-seconds.
setTimeout(() => { this.refresh(); }, 100);
});
},
refresh() {
this.clearCacheEntries();
this.createCacheEntries();
},
clearCacheEntries() {
let ctbody = document.getElementById("cache-table-body");
while (ctbody.firstChild) {
ctbody.firstChild.remove();
}
let cetbody = document.getElementById("cache-entries-table-body");
while (cetbody.firstChild) {
cetbody.firstChild.remove();
}
},
createCacheEntries() {
function createRow(tds, body, cols) {
let tr = document.createElement("tr");
tds.forEach(function(v, i, a) {
let td = document.createElement("td");
if (i == 0 && tds.length != cols) {
td.setAttribute("colspan", cols - tds.length + 1);
}
let elem = typeof v === "object" ? v : document.createTextNode(v);
td.appendChild(elem);
tr.appendChild(td);
})
body.appendChild(tr);
}
let dbservice = Cc["@mozilla.org/url-classifier/dbservice;1"]
.getService(Ci.nsIUrlClassifierInfo);
for (let provider of Provider.providers) {
let pref = "browser.safebrowsing.provider." + provider + ".lists";
let tables = Services.prefs.getCharPref(pref, "").split(",");
for (let table of tables) {
let cache = dbservice.getCacheInfo(table);
let entries = cache.entries;
if (entries.length === 0) {
this.showCacheEnties.delete(table);
continue;
}
let positiveCacheCount = 0;
for (let i = 0; i < entries.length ; i++) {
let entry = entries.queryElementAt(i, Ci.nsIUrlClassifierCacheEntry);
let matches = entry.matches;
positiveCacheCount += matches.length;
// If we don't have to show cache entries for this table then just
// skip the following code.
if (!this.showCacheEnties.has(table)) {
continue;
}
let tds = [table, entry.prefix, new Date(entry.expiry * 1000).toString()];
let j = 0;
do {
if (matches.length >= 1) {
let match =
matches.queryElementAt(j, Ci.nsIUrlClassifierPositiveCacheEntry);
let list = [match.fullhash, new Date(match.expiry * 1000).toString()];
tds = tds.concat(list);
} else {
tds = tds.concat([STR_NA, STR_NA])
}
createRow(tds, document.getElementById("cache-entries-table-body"), 5);
j++;
tds = [""];
} while (j < matches.length)
}
// Create cache information entries.
let chk = document.createElement("input");
chk.type = "checkbox";
chk.checked = this.showCacheEnties.has(table);
chk.addEventListener("click", () => {
if (chk.checked) {
this.showCacheEnties.add(table);
} else {
this.showCacheEnties.delete(table);
}
this.refresh();
});
let tds = [table, entries.length, positiveCacheCount, chk];
createRow(tds, document.getElementById("cache-table-body"), tds.length);
}
}
let entries_div = document.getElementById("cache-entries");
entries_div.style.display = this.showCacheEnties.size == 0 ? "none" : "block";
},
};
/* /*
* Debug * Debug
*/ */

View File

@ -37,6 +37,45 @@
</tbody> </tbody>
</table> </table>
</div> </div>
<div id="cache">
<h2 class="major-section">&aboutUrlClassifier.cacheTitle;</h2>
<div id="cache-modules" class="options">
<button id="refresh-cache-btn">&aboutUrlClassifier.cacheRefreshBtn;</button>
<button id="clear-cache-btn">&aboutUrlClassifier.cacheClearBtn;</button>
<br></br>
</div>
<table id="cache-table">
<thead>
<tr id="cache-head-row">
<th id="col-tablename">&aboutUrlClassifier.cacheTableName;</th>
<th id="col-negativeentries">&aboutUrlClassifier.cacheNCacheEntries;</th>
<th id="col-positiveentries">&aboutUrlClassifier.cachePCacheEntries;</th>
<th id="col-showentries">&aboutUrlClassifier.cacheShowEntries;</th>
</tr>
</thead>
<tbody id="cache-table-body">
<!-- data is generated in javascript -->
</tbody>
</table>
<br></br>
</div>
<div id="cache-entries">
<h2 class="major-section">&aboutUrlClassifier.cacheEntries;</h2>
<table id="cache-entries-table">
<thead>
<tr id="cache-entries-row">
<th id="col-table">&aboutUrlClassifier.cacheTableName;</th>
<th id="col-prefix">&aboutUrlClassifier.cachePrefix;</th>
<th id="col-n-expire">&aboutUrlClassifier.cacheNCacheExpiry;</th>
<th id="col-fullhash">&aboutUrlClassifier.cacheFullhash;</th>
<th id="col-p-expire">&aboutUrlClassifier.cachePCacheExpiry;</th>
</tr>
</thead>
<tbody id="cache-entries-table-body">
<!-- data is generated in javascript -->
</tbody>
</table>
</div>
<div id="debug"> <div id="debug">
<h2 class="major-section">&aboutUrlClassifier.debugTitle;</h2> <h2 class="major-section">&aboutUrlClassifier.debugTitle;</h2>
<div id="debug-modules" class="options"> <div id="debug-modules" class="options">

View File

@ -10,6 +10,18 @@
<!ENTITY aboutUrlClassifier.providerNextUpdateTime "Next update time"> <!ENTITY aboutUrlClassifier.providerNextUpdateTime "Next update time">
<!ENTITY aboutUrlClassifier.providerLastUpdateStatus "Last update status"> <!ENTITY aboutUrlClassifier.providerLastUpdateStatus "Last update status">
<!ENTITY aboutUrlClassifier.providerUpdateBtn "Update"> <!ENTITY aboutUrlClassifier.providerUpdateBtn "Update">
<!ENTITY aboutUrlClassifier.cacheTitle "Cache">
<!ENTITY aboutUrlClassifier.cacheRefreshBtn "Refresh">
<!ENTITY aboutUrlClassifier.cacheClearBtn "Clear">
<!ENTITY aboutUrlClassifier.cacheTableName "Table name">
<!ENTITY aboutUrlClassifier.cacheNCacheEntries "Number of negative cache entries">
<!ENTITY aboutUrlClassifier.cachePCacheEntries "Number of positive cache entries">
<!ENTITY aboutUrlClassifier.cacheShowEntries "Show entries">
<!ENTITY aboutUrlClassifier.cacheEntries "Cache Entries">
<!ENTITY aboutUrlClassifier.cachePrefix "Prefix">
<!ENTITY aboutUrlClassifier.cacheNCacheExpiry "Negative cache expiry">
<!ENTITY aboutUrlClassifier.cacheFullhash "Full hash">
<!ENTITY aboutUrlClassifier.cachePCacheExpiry "Positive cache expiry">
<!ENTITY aboutUrlClassifier.lookupTitle "Lookup"> <!ENTITY aboutUrlClassifier.lookupTitle "Lookup">
<!ENTITY aboutUrlClassifier.lookupUrl "Url"> <!ENTITY aboutUrlClassifier.lookupUrl "Url">
<!ENTITY aboutUrlClassifier.lookupMatch "Match"> <!ENTITY aboutUrlClassifier.lookupMatch "Match">