Bug 1511436 - Cleanup URL-Classifier code - part 2 - nsUrlClassifierDBService::AsyncClassifyLocalWithFeatures, r=dimi

This commit is contained in:
Andrea Marchesini
2018-12-14 12:40:17 +01:00
parent a5aa66ee92
commit e247fa8583
16 changed files with 611 additions and 205 deletions

View File

@@ -3191,7 +3191,7 @@ bool ContentChild::DeallocPURLClassifierChild(PURLClassifierChild* aActor) {
}
PURLClassifierLocalChild* ContentChild::AllocPURLClassifierLocalChild(
const URIParams& aUri, const nsCString& aTables) {
const URIParams& aUri, const nsTArray<IPCURLClassifierFeature>& aFeatures) {
return new URLClassifierLocalChild();
}

View File

@@ -644,7 +644,8 @@ class ContentChild final : public PContentChild,
// PURLClassifierLocalChild
virtual PURLClassifierLocalChild* AllocPURLClassifierLocalChild(
const URIParams& aUri, const nsCString& aTables) override;
const URIParams& aUri,
const nsTArray<IPCURLClassifierFeature>& aFeatures) override;
virtual bool DeallocPURLClassifierLocalChild(
PURLClassifierLocalChild* aActor) override;

View File

@@ -5353,7 +5353,7 @@ bool ContentParent::DeallocPURLClassifierParent(PURLClassifierParent* aActor) {
// PURLClassifierLocalParent
PURLClassifierLocalParent* ContentParent::AllocPURLClassifierLocalParent(
const URIParams& aURI, const nsCString& aTables) {
const URIParams& aURI, const nsTArray<IPCURLClassifierFeature>& aFeatures) {
MOZ_ASSERT(NS_IsMainThread());
RefPtr<URLClassifierLocalParent> actor = new URLClassifierLocalParent();
@@ -5362,10 +5362,12 @@ PURLClassifierLocalParent* ContentParent::AllocPURLClassifierLocalParent(
mozilla::ipc::IPCResult ContentParent::RecvPURLClassifierLocalConstructor(
PURLClassifierLocalParent* aActor, const URIParams& aURI,
const nsCString& aTables) {
nsTArray<IPCURLClassifierFeature>&& aFeatures) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aActor);
nsTArray<IPCURLClassifierFeature> features = std::move(aFeatures);
nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
if (!uri) {
NS_WARNING("Failed to DeserializeURI");
@@ -5373,7 +5375,7 @@ mozilla::ipc::IPCResult ContentParent::RecvPURLClassifierLocalConstructor(
}
auto* actor = static_cast<URLClassifierLocalParent*>(aActor);
return actor->StartClassify(uri, aTables);
return actor->StartClassify(uri, features);
}
bool ContentParent::DeallocPURLClassifierLocalParent(

View File

@@ -560,10 +560,12 @@ class ContentParent final : public PContentParent,
// PURLClassifierLocalParent.
virtual PURLClassifierLocalParent* AllocPURLClassifierLocalParent(
const URIParams& aURI, const nsCString& aTables) override;
const URIParams& aURI,
const nsTArray<IPCURLClassifierFeature>& aFeatures) override;
virtual mozilla::ipc::IPCResult RecvPURLClassifierLocalConstructor(
PURLClassifierLocalParent* aActor, const URIParams& aURI,
const nsCString& aTables) override;
nsTArray<IPCURLClassifierFeature>&& aFeatures) override;
virtual PLoginReputationParent* AllocPLoginReputationParent(
const URIParams& aURI) override;

View File

@@ -297,6 +297,13 @@ struct StringBundleDescriptor
uint32_t mapSize;
};
struct IPCURLClassifierFeature
{
nsCString featureName;
nsCString[] tables;
nsCString skipHostList;
};
/**
* The PContent protocol is a top-level protocol between the UI process
* and a content process. There is exactly one PContentParent/PContentChild pair
@@ -803,10 +810,12 @@ parent:
sync PURLClassifier(Principal principal, bool useTrackingProtection)
returns (bool success);
sync ClassifyLocal(URIParams uri, nsCString tables)
returns (nsresult rv, nsCString[] results);
// The async version of ClassifyLocal.
async PURLClassifierLocal(URIParams uri, nsCString tables);
async PURLClassifierLocal(URIParams uri, IPCURLClassifierFeature[] features);
async PLoginReputation(URIParams formURI);

View File

@@ -11,12 +11,18 @@ include PURLClassifierInfo;
namespace mozilla {
namespace dom {
struct URLClassifierLocalResult
{
nsCString featureName;
nsCString matchingList;
};
protocol PURLClassifierLocal
{
manager PContent;
child:
async __delete__(MaybeInfo info, nsresult errorCode);
async __delete__(URLClassifierLocalResult[] results);
};
} // namespace dom

View File

@@ -9,16 +9,15 @@
#include "mozilla/dom/PURLClassifierChild.h"
#include "mozilla/dom/PURLClassifierLocalChild.h"
#include "mozilla/net/UrlClassifierFeatureResult.h"
#include "nsIURIClassifier.h"
#include "nsIUrlClassifierFeature.h"
namespace mozilla {
namespace dom {
template <typename BaseProtocol>
class URLClassifierChildBase : public BaseProtocol {
class URLClassifierChild : public PURLClassifierChild {
public:
URLClassifierChildBase() = default;
void SetCallback(nsIURIClassifierCallback* aCallback) {
mCallback = aCallback;
}
@@ -35,14 +34,50 @@ class URLClassifierChildBase : public BaseProtocol {
}
private:
~URLClassifierChildBase() = default;
nsCOMPtr<nsIURIClassifierCallback> mCallback;
};
using URLClassifierChild = URLClassifierChildBase<PURLClassifierChild>;
using URLClassifierLocalChild =
URLClassifierChildBase<PURLClassifierLocalChild>;
class URLClassifierLocalChild : public PURLClassifierLocalChild {
public:
void SetFeaturesAndCallback(
const nsTArray<RefPtr<nsIUrlClassifierFeature>>& aFeatures,
nsIUrlClassifierFeatureCallback* aCallback) {
mCallback = aCallback;
mFeatures = aFeatures;
}
mozilla::ipc::IPCResult Recv__delete__(
nsTArray<URLClassifierLocalResult>&& aResults) override {
nsTArray<RefPtr<nsIUrlClassifierFeatureResult>> finalResults;
nsTArray<URLClassifierLocalResult> results = std::move(aResults);
for (URLClassifierLocalResult& result : results) {
for (nsIUrlClassifierFeature* feature : mFeatures) {
nsAutoCString name;
nsresult rv = feature->GetName(name);
if (NS_WARN_IF(NS_FAILED(rv))) {
continue;
}
if (result.featureName() != name) {
continue;
}
RefPtr<net::UrlClassifierFeatureResult> r =
new net::UrlClassifierFeatureResult(feature, result.matchingList());
finalResults.AppendElement(r);
break;
}
}
mCallback->OnClassifyComplete(finalResults);
return IPC_OK();
}
private:
nsCOMPtr<nsIUrlClassifierFeatureCallback> mCallback;
nsTArray<RefPtr<nsIUrlClassifierFeature>> mFeatures;
};
} // namespace dom
} // namespace mozilla

View File

@@ -6,6 +6,7 @@
#include "URLClassifierParent.h"
#include "nsComponentManagerUtils.h"
#include "mozilla/net/UrlClassifierFeatureResult.h"
#include "mozilla/Unused.h"
using namespace mozilla;
@@ -41,37 +42,112 @@ mozilla::ipc::IPCResult URLClassifierParent::StartClassify(
return IPC_OK();
}
void URLClassifierParent::ActorDestroy(ActorDestroyReason aWhy) {
mIPCOpen = false;
}
/////////////////////////////////////////////////////////////////////
// URLClassifierLocalParent.
NS_IMPL_ISUPPORTS(URLClassifierLocalParent, nsIURIClassifierCallback)
namespace {
// This class implements a nsIUrlClassifierFeature on the parent side, starting
// from an IPC data struct.
class IPCFeature final : public nsIUrlClassifierFeature {
public:
NS_DECL_ISUPPORTS
explicit IPCFeature(const IPCURLClassifierFeature& aFeature)
: mIPCFeature(aFeature) {}
NS_IMETHOD
GetName(nsACString& aName) override {
aName = mIPCFeature.featureName();
return NS_OK;
}
NS_IMETHOD
GetTables(nsIUrlClassifierFeature::listType,
nsTArray<nsCString>& aTables) override {
aTables.AppendElements(mIPCFeature.tables());
return NS_OK;
}
NS_IMETHOD
HasTable(const nsACString& aTable, nsIUrlClassifierFeature::listType,
bool* aResult) override {
NS_ENSURE_ARG_POINTER(aResult);
*aResult = mIPCFeature.tables().Contains(aTable);
return NS_OK;
}
NS_IMETHOD
HasHostInPreferences(const nsACString& aHost,
nsIUrlClassifierFeature::listType,
nsACString& aTableName, bool* aResult) override {
NS_ENSURE_ARG_POINTER(aResult);
*aResult = false;
return NS_OK;
}
NS_IMETHOD
GetSkipHostList(nsACString& aList) override {
aList = mIPCFeature.skipHostList();
return NS_OK;
}
private:
~IPCFeature() = default;
IPCURLClassifierFeature mIPCFeature;
};
NS_IMPL_ISUPPORTS(IPCFeature, nsIUrlClassifierFeature)
} // namespace
NS_IMPL_ISUPPORTS(URLClassifierLocalParent, nsIUrlClassifierFeatureCallback)
mozilla::ipc::IPCResult URLClassifierLocalParent::StartClassify(
nsIURI* aURI, const nsACString& aTables) {
nsIURI* aURI, const nsTArray<IPCURLClassifierFeature>& aFeatures) {
MOZ_ASSERT(aURI);
nsresult rv = NS_OK;
// Note that in safe mode, the URL classifier service isn't available, so we
// should handle the service not being present gracefully.
nsCOMPtr<nsIURIClassifier> uriClassifier =
do_GetService(NS_URICLASSIFIERSERVICE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv)) {
MOZ_ASSERT(aURI);
rv = uriClassifier->AsyncClassifyLocalWithTables(
aURI, aTables, nsTArray<nsCString>(), nsTArray<nsCString>(), this);
if (NS_WARN_IF(NS_FAILED(rv))) {
OnClassifyComplete(nsTArray<RefPtr<nsIUrlClassifierFeatureResult>>());
return IPC_OK();
}
if (NS_FAILED(rv)) {
// Cannot do ClassificationFailed() because the child side
// is expecting a callback. Only the second parameter will
// be used, which is the "matched list". We treat "unable
// to classify" as "not on any list".
OnClassifyComplete(NS_OK, EmptyCString(), EmptyCString(), EmptyCString());
nsTArray<RefPtr<nsIUrlClassifierFeature>> features;
for (const IPCURLClassifierFeature& feature : aFeatures) {
features.AppendElement(new IPCFeature(feature));
}
// Doesn't matter if we pass blacklist, whitelist or any other list.
// IPCFeature returns always the same values.
rv = uriClassifier->AsyncClassifyLocalWithFeatures(
aURI, features, nsIUrlClassifierFeature::blacklist, this);
if (NS_WARN_IF(NS_FAILED(rv))) {
OnClassifyComplete(nsTArray<RefPtr<nsIUrlClassifierFeatureResult>>());
return IPC_OK();
}
return IPC_OK();
}
void URLClassifierLocalParent::ActorDestroy(ActorDestroyReason aWhy) {
mIPCOpen = false;
NS_IMETHODIMP
URLClassifierLocalParent::OnClassifyComplete(
const nsTArray<RefPtr<nsIUrlClassifierFeatureResult>>& aResults) {
nsTArray<URLClassifierLocalResult> ipcResults;
for (nsIUrlClassifierFeatureResult* result : aResults) {
URLClassifierLocalResult* ipcResult = ipcResults.AppendElement();
net::UrlClassifierFeatureResult* r =
static_cast<net::UrlClassifierFeatureResult*>(result);
r->Feature()->GetName(ipcResult->featureName());
ipcResult->matchingList() = r->List();
}
Unused << Send__delete__(this, ipcResults);
return NS_OK;
}

View File

@@ -10,43 +10,16 @@
#include "mozilla/dom/PURLClassifierParent.h"
#include "mozilla/dom/PURLClassifierLocalParent.h"
#include "nsIURIClassifier.h"
#include "nsIUrlClassifierFeature.h"
namespace mozilla {
namespace dom {
template <typename BaseProtocol>
class URLClassifierParentBase : public nsIURIClassifierCallback,
public BaseProtocol {
public:
// nsIURIClassifierCallback.
NS_IMETHOD OnClassifyComplete(nsresult aErrorCode, const nsACString& aList,
const nsACString& aProvider,
const nsACString& aFullHash) override {
if (mIPCOpen) {
ClassifierInfo info = ClassifierInfo(
nsCString(aList), nsCString(aProvider), nsCString(aFullHash));
Unused << BaseProtocol::Send__delete__(this, info, aErrorCode);
}
return NS_OK;
}
// Custom.
void ClassificationFailed() {
if (mIPCOpen) {
Unused << BaseProtocol::Send__delete__(this, void_t(), NS_ERROR_FAILURE);
}
}
protected:
~URLClassifierParentBase() = default;
bool mIPCOpen = true;
};
//////////////////////////////////////////////////////////////
// URLClassifierParent
class URLClassifierParent
: public URLClassifierParentBase<PURLClassifierParent> {
class URLClassifierParent : public nsIURIClassifierCallback,
public PURLClassifierParent {
public:
NS_DECL_THREADSAFE_ISUPPORTS
@@ -54,30 +27,58 @@ class URLClassifierParent
bool aUseTrackingProtection,
bool* aSuccess);
// nsIURIClassifierCallback.
NS_IMETHOD OnClassifyComplete(nsresult aErrorCode, const nsACString& aList,
const nsACString& aProvider,
const nsACString& aFullHash) override {
if (mIPCOpen) {
ClassifierInfo info = ClassifierInfo(
nsCString(aList), nsCString(aProvider), nsCString(aFullHash));
Unused << Send__delete__(this, info, aErrorCode);
}
return NS_OK;
}
// Custom.
void ClassificationFailed() {
if (mIPCOpen) {
Unused << Send__delete__(this, void_t(), NS_ERROR_FAILURE);
}
}
private:
~URLClassifierParent() = default;
// Override PURLClassifierParent::ActorDestroy. We seem to unable to
// override from the base template class.
void ActorDestroy(ActorDestroyReason aWhy) override;
void ActorDestroy(ActorDestroyReason aWhy) override { mIPCOpen = false; }
bool mIPCOpen = true;
};
//////////////////////////////////////////////////////////////
// URLClassifierLocalParent
class URLClassifierLocalParent
: public URLClassifierParentBase<PURLClassifierLocalParent> {
class URLClassifierLocalParent : public nsIUrlClassifierFeatureCallback,
public PURLClassifierLocalParent {
public:
NS_DECL_THREADSAFE_ISUPPORTS
mozilla::ipc::IPCResult StartClassify(nsIURI* aURI,
const nsACString& aTables);
mozilla::ipc::IPCResult StartClassify(
nsIURI* aURI, const nsTArray<IPCURLClassifierFeature>& aFeatureNames);
// nsIUrlClassifierFeatureCallback.
NS_IMETHOD
OnClassifyComplete(
const nsTArray<RefPtr<nsIUrlClassifierFeatureResult>>& aResults) override;
private:
~URLClassifierLocalParent() = default;
// Override PURLClassifierParent::ActorDestroy.
void ActorDestroy(ActorDestroyReason aWhy) override;
// Override PURLClassifierLocalParent::ActorDestroy.
void ActorDestroy(ActorDestroyReason aWhy) override { mIPCOpen = false; }
bool mIPCOpen = true;
};
} // namespace dom

View File

@@ -22,6 +22,7 @@ UNIFIED_SOURCES += [
'UrlClassifierCommon.cpp',
'UrlClassifierFeatureBase.cpp',
'UrlClassifierFeatureFactory.cpp',
'UrlClassifierFeatureResult.cpp',
'UrlClassifierFeatureTrackingAnnotation.cpp',
'UrlClassifierFeatureTrackingProtection.cpp',
]
@@ -29,6 +30,7 @@ UNIFIED_SOURCES += [
EXPORTS.mozilla.net += [
'UrlClassifierCommon.h',
'UrlClassifierFeatureFactory.h',
'UrlClassifierFeatureResult.h',
]
LOCAL_INCLUDES += [

View File

@@ -406,7 +406,8 @@ void Classifier::TableRequest(nsACString& aResult) {
mIsTableRequestResultOutdated = false;
}
nsresult Classifier::Check(const nsACString& aSpec, const nsACString& aTables,
nsresult Classifier::Check(const nsACString& aSpec,
const nsTArray<nsCString>& aTables,
LookupResultArray& aResults) {
Telemetry::AutoTimer<Telemetry::URLCLASSIFIER_CL_CHECK_TIME> timer;
@@ -417,13 +418,10 @@ nsresult Classifier::Check(const nsACString& aSpec, const nsACString& aTables,
nsresult rv = LookupCache::GetLookupFragments(aSpec, &fragments);
NS_ENSURE_SUCCESS(rv, rv);
nsTArray<nsCString> activeTables;
SplitTables(aTables, activeTables);
LookupCacheArray cacheArray;
for (uint32_t i = 0; i < activeTables.Length(); i++) {
LOG(("Checking table %s", activeTables[i].get()));
RefPtr<LookupCache> cache = GetLookupCache(activeTables[i]);
for (const nsCString& table : aTables) {
LOG(("Checking table %s", table.get()));
RefPtr<LookupCache> cache = GetLookupCache(table);
if (cache) {
cacheArray.AppendElement(cache);
} else {

View File

@@ -59,7 +59,7 @@ class Classifier {
/**
* Check a URL against the specified tables.
*/
nsresult Check(const nsACString& aSpec, const nsACString& tables,
nsresult Check(const nsACString& aSpec, const nsTArray<nsCString>& tables,
LookupResultArray& aResults);
/**

View File

@@ -47,6 +47,7 @@
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/PermissionMessageUtils.h"
#include "mozilla/dom/URLClassifierChild.h"
#include "mozilla/net/UrlClassifierFeatureResult.h"
#include "mozilla/ipc/URIUtils.h"
#include "nsProxyRelease.h"
#include "UrlClassifierTelemetryUtils.h"
@@ -94,6 +95,200 @@ nsresult TablesToResponse(const nsACString& tables) {
} // namespace safebrowsing
} // namespace mozilla
namespace {
// This class holds a list of features, their tables, and it stores the lookup
// results.
class FeatureHolder final {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FeatureHolder);
struct FeatureData {
RefPtr<nsIUrlClassifierFeature> mFeature;
nsTArray<nsCString> mTables;
LookupResultArray mResults;
};
static already_AddRefed<FeatureHolder> Create(
const nsTArray<RefPtr<nsIUrlClassifierFeature>>& aFeatures,
nsIUrlClassifierFeature::listType aListType) {
MOZ_ASSERT(NS_IsMainThread());
RefPtr<FeatureHolder> holder = new FeatureHolder();
for (nsIUrlClassifierFeature* feature : aFeatures) {
FeatureData* data = holder->mData.AppendElement();
MOZ_ASSERT(data);
data->mFeature = feature;
nsresult rv = feature->GetTables(aListType, data->mTables);
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
}
return holder.forget();
}
nsresult DoLocalLookup(const nsACString& aSpec,
nsUrlClassifierDBServiceWorker* aWorker) {
MOZ_ASSERT(!NS_IsMainThread());
MOZ_ASSERT(aWorker);
for (FeatureData& data : mData) {
nsresult rv = aWorker->DoLocalLookup(aSpec, data.mTables, data.mResults);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}
return NS_OK;
}
void GetResults(nsTArray<RefPtr<nsIUrlClassifierFeatureResult>>& aResults) {
MOZ_ASSERT(NS_IsMainThread());
for (FeatureData& data : mData) {
if (data.mResults.IsEmpty()) {
continue;
}
nsAutoCString list;
for (uint32_t i = 0; i < data.mResults.Length(); ++i) {
if (!list.IsEmpty()) {
list.AppendLiteral(",");
}
list.Append(data.mResults[i]->mTableName);
}
RefPtr<mozilla::net::UrlClassifierFeatureResult> result =
new mozilla::net::UrlClassifierFeatureResult(data.mFeature, list);
aResults.AppendElement(result);
}
}
private:
FeatureHolder() { MOZ_ASSERT(NS_IsMainThread()); }
~FeatureHolder() {
for (FeatureData& data : mData) {
NS_ReleaseOnMainThreadSystemGroup("FeatureHolder:mData",
data.mFeature.forget());
}
}
nsTArray<FeatureData> mData;
};
// Simple feature which wraps preferences and tables received by
// AsyncClassifyLocalWithTables() as arguments.
class DummyFeature final : public nsIUrlClassifierFeature {
public:
NS_DECL_ISUPPORTS
enum Type { ePreference, eTable };
explicit DummyFeature(const nsACString& aName)
: mType(eTable), mName(aName) {}
explicit DummyFeature(const nsACString& aPreference,
nsTArray<nsCString>& aHostsFromPreference)
: mType(ePreference),
mName(aPreference),
mHostsFromPreference(aHostsFromPreference) {}
NS_IMETHOD
GetName(nsACString& aName) override {
aName = mName;
return NS_OK;
}
NS_IMETHOD
GetTables(nsIUrlClassifierFeature::listType,
nsTArray<nsCString>& aTables) override {
if (mType == eTable) {
aTables.AppendElement(mName);
}
return NS_OK;
}
NS_IMETHOD
HasTable(const nsACString& aTable, nsIUrlClassifierFeature::listType,
bool* aResult) override {
NS_ENSURE_ARG_POINTER(aResult);
*aResult = mType == eTable && aTable == mName;
return NS_OK;
}
NS_IMETHOD
HasHostInPreferences(const nsACString& aHost,
nsIUrlClassifierFeature::listType,
nsACString& aPrefTableName, bool* aResult) override {
NS_ENSURE_ARG_POINTER(aResult);
*aResult = mHostsFromPreference.Contains(aHost);
aPrefTableName = mName;
return NS_OK;
}
NS_IMETHOD
GetSkipHostList(nsACString& aList) override {
// Nothing to do here.
return NS_OK;
}
private:
~DummyFeature() = default;
Type mType;
nsCString mName;
nsTArray<nsCString> mHostsFromPreference;
};
NS_IMPL_ISUPPORTS(DummyFeature, nsIUrlClassifierFeature)
// This class is a proxy from nsIUrlClassifierFeatureCallback to
// nsIUrlClassifierCallback.
class CallbackWrapper final : public nsIUrlClassifierFeatureCallback {
public:
NS_DECL_ISUPPORTS
explicit CallbackWrapper(nsIURIClassifierCallback* aCallback)
: mCallback(aCallback) {
MOZ_ASSERT(aCallback);
}
NS_IMETHOD
OnClassifyComplete(const nsTArray<RefPtr<nsIUrlClassifierFeatureResult>>&
aResults) override {
nsAutoCString finalList;
for (nsIUrlClassifierFeatureResult* result : aResults) {
const nsCString& list =
static_cast<mozilla::net::UrlClassifierFeatureResult*>(result)
->List();
MOZ_ASSERT(!list.IsEmpty());
if (!finalList.IsEmpty()) {
finalList.AppendLiteral(",");
}
finalList.Append(list);
}
mCallback->OnClassifyComplete(NS_OK, finalList, EmptyCString(),
EmptyCString());
return NS_OK;
}
private:
~CallbackWrapper() = default;
nsCOMPtr<nsIURIClassifierCallback> mCallback;
};
NS_IMPL_ISUPPORTS(CallbackWrapper, nsIUrlClassifierFeatureCallback)
} // namespace
using namespace mozilla;
using namespace mozilla::safebrowsing;
@@ -168,7 +363,7 @@ nsresult nsUrlClassifierDBServiceWorker::QueueLookup(
}
nsresult nsUrlClassifierDBServiceWorker::DoLocalLookup(
const nsACString& spec, const nsACString& tables,
const nsACString& spec, const nsTArray<nsCString>& tables,
LookupResultArray& results) {
if (gShuttingDownThread) {
return NS_ERROR_ABORT;
@@ -232,7 +427,10 @@ nsresult nsUrlClassifierDBServiceWorker::DoLookup(
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult rv = DoLocalLookup(spec, tables, *results);
nsTArray<nsCString> tableArray;
Classifier::SplitTables(tables, tableArray);
nsresult rv = DoLocalLookup(spec, tableArray, *results);
if (NS_FAILED(rv)) {
MOZ_ASSERT(results->IsEmpty(),
"DoLocalLookup() should not return any results if it fails.");
@@ -1740,136 +1938,38 @@ nsUrlClassifierDBService::AsyncClassifyLocalWithTables(
"AsyncClassifyLocalWithTables must be called "
"on main thread");
nsresult rv;
// We do this check no matter what process we are in to return
// error as early as possible.
nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI);
NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
if (aExtraTablesByPrefs.Length() != aExtraEntriesByPrefs.Length()) {
return NS_ERROR_FAILURE;
}
// Let's see if we have special entries set by prefs.
if (!aExtraEntriesByPrefs.IsEmpty()) {
nsAutoCString host;
rv = uri->GetHost(host);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoCString tables;
for (uint32_t i = 0; i < aExtraEntriesByPrefs.Length(); ++i) {
nsTArray<nsCString> entries;
Classifier::SplitTables(aExtraEntriesByPrefs[i], entries);
if (entries.Contains(host)) {
if (!tables.IsEmpty()) {
tables.AppendLiteral(",");
}
tables.Append(aExtraTablesByPrefs[i]);
}
}
if (!tables.IsEmpty()) {
nsCOMPtr<nsIURIClassifierCallback> callback(aCallback);
nsCOMPtr<nsIRunnable> cbRunnable = NS_NewRunnableFunction(
"nsUrlClassifierDBService::AsyncClassifyLocalWithTables",
[callback, tables]() -> void {
callback->OnClassifyComplete(
NS_OK, // Not used.
tables,
EmptyCString(), // provider. (Not used)
EmptyCString()); // prefix. (Not used)
});
NS_DispatchToMainThread(cbRunnable);
return NS_OK;
}
}
nsAutoCString key;
// Canonicalize the url
nsCOMPtr<nsIUrlClassifierUtils> utilsService =
do_GetService(NS_URLCLASSIFIERUTILS_CONTRACTID);
rv = utilsService->GetKeyForURI(uri, key);
NS_ENSURE_SUCCESS(rv, rv);
if (XRE_IsContentProcess()) {
using namespace mozilla::dom;
using namespace mozilla::ipc;
ContentChild* content = ContentChild::GetSingleton();
if (NS_WARN_IF(!content || content->IsShuttingDown())) {
return NS_ERROR_FAILURE;
}
auto actor = new URLClassifierLocalChild();
// TODO: Bug 1353701 - Supports custom event target for labelling.
nsCOMPtr<nsIEventTarget> systemGroupEventTarget =
mozilla::SystemGroup::EventTargetFor(mozilla::TaskCategory::Other);
content->SetEventTargetForActor(actor, systemGroupEventTarget);
URIParams uri;
SerializeURI(aURI, uri);
nsAutoCString tables(aTables);
if (!content->SendPURLClassifierLocalConstructor(actor, uri, tables)) {
return NS_ERROR_FAILURE;
}
actor->SetCallback(aCallback);
return NS_OK;
}
if (gShuttingDownThread) {
return NS_ERROR_ABORT;
}
using namespace mozilla::Telemetry;
auto startTime = TimeStamp::Now(); // For telemetry.
// Let's convert the current params in a list of features.
nsTArray<RefPtr<nsIUrlClassifierFeature>> features;
auto worker = mWorker;
nsCString tables(aTables);
for (uint32_t i = 0; i < aExtraTablesByPrefs.Length(); ++i) {
nsTArray<nsCString> hosts;
Classifier::SplitTables(aExtraEntriesByPrefs[i], hosts);
RefPtr<DummyFeature> feature =
new DummyFeature(aExtraTablesByPrefs[i], hosts);
features.AppendElement(feature);
}
// Since aCallback will be passed around threads...
nsMainThreadPtrHandle<nsIURIClassifierCallback> callback(
new nsMainThreadPtrHolder<nsIURIClassifierCallback>(
"nsIURIClassifierCallback", aCallback));
nsTArray<nsCString> tables;
Classifier::SplitTables(aTables, tables);
for (uint32_t i = 0; i < tables.Length(); ++i) {
RefPtr<DummyFeature> feature = new DummyFeature(tables[i]);
features.AppendElement(feature);
}
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
"nsUrlClassifierDBService::AsyncClassifyLocalWithTables",
[worker, key, tables, callback, startTime]() -> void {
nsCString matchedLists;
LookupResultArray results;
nsresult rv = worker->DoLocalLookup(key, tables, results);
if (NS_SUCCEEDED(rv)) {
for (uint32_t i = 0; i < results.Length(); i++) {
if (i > 0) {
matchedLists.AppendLiteral(",");
}
matchedLists.Append(results[i]->mTableName);
}
}
RefPtr<CallbackWrapper> callback = new CallbackWrapper(aCallback);
nsCOMPtr<nsIRunnable> cbRunnable = NS_NewRunnableFunction(
"nsUrlClassifierDBService::AsyncClassifyLocalWithTables",
[callback, matchedLists, startTime]() -> void {
// Measure the time diff between calling and callback.
AccumulateTimeDelta(
Telemetry::URLCLASSIFIER_ASYNC_CLASSIFYLOCAL_TIME, startTime);
// |callback| is captured as const value so ...
auto cb = const_cast<nsIURIClassifierCallback*>(callback.get());
cb->OnClassifyComplete(NS_OK, // Not used.
matchedLists,
EmptyCString(), // provider. (Not used)
EmptyCString()); // prefix. (Not used)
});
NS_DispatchToMainThread(cbRunnable);
});
return gDbBackgroundThread->Dispatch(r, NS_DISPATCH_NORMAL);
// Doesn't really matter if we pass blacklist, whitelist or any other list
// here because the DummyFeature returns always the same values.
return AsyncClassifyLocalWithFeatures(
aURI, features, nsIUrlClassifierFeature::blacklist, callback);
}
NS_IMETHODIMP
@@ -2564,6 +2664,164 @@ nsUrlClassifierDBService::AsyncClassifyLocalWithFeatures(
nsIURI* aURI, const nsTArray<RefPtr<nsIUrlClassifierFeature>>& aFeatures,
nsIUrlClassifierFeature::listType aListType,
nsIUrlClassifierFeatureCallback* aCallback) {
// TODO
return NS_OK;
MOZ_ASSERT(NS_IsMainThread());
if (gShuttingDownThread) {
return NS_ERROR_ABORT;
}
nsCOMPtr<nsIURI> uri = NS_GetInnermostURI(aURI);
NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE);
// Let's try to use the preferences.
if (AsyncClassifyLocalWithFeaturesUsingPreferences(uri, aFeatures, aListType,
aCallback)) {
return NS_OK;
}
nsAutoCString key;
// Canonicalize the url
nsCOMPtr<nsIUrlClassifierUtils> utilsService =
do_GetService(NS_URLCLASSIFIERUTILS_CONTRACTID);
nsresult rv = utilsService->GetKeyForURI(uri, key);
NS_ENSURE_SUCCESS(rv, rv);
if (XRE_IsContentProcess()) {
using namespace mozilla::dom;
using namespace mozilla::ipc;
ContentChild* content = ContentChild::GetSingleton();
if (NS_WARN_IF(!content || content->IsShuttingDown())) {
return NS_ERROR_FAILURE;
}
auto actor = new URLClassifierLocalChild();
// TODO: Bug 1353701 - Supports custom event target for labelling.
nsCOMPtr<nsIEventTarget> systemGroupEventTarget =
mozilla::SystemGroup::EventTargetFor(mozilla::TaskCategory::Other);
content->SetEventTargetForActor(actor, systemGroupEventTarget);
URIParams uri;
SerializeURI(aURI, uri);
nsTArray<IPCURLClassifierFeature> ipcFeatures;
for (nsIUrlClassifierFeature* feature : aFeatures) {
nsAutoCString name;
rv = feature->GetName(name);
if (NS_WARN_IF(NS_FAILED(rv))) {
continue;
}
nsTArray<nsCString> tables;
rv = feature->GetTables(aListType, tables);
if (NS_WARN_IF(NS_FAILED(rv))) {
continue;
}
nsAutoCString skipHostList;
rv = feature->GetSkipHostList(skipHostList);
if (NS_WARN_IF(NS_FAILED(rv))) {
continue;
}
ipcFeatures.AppendElement(
IPCURLClassifierFeature(name, tables, skipHostList));
}
if (!content->SendPURLClassifierLocalConstructor(actor, uri, ipcFeatures)) {
return NS_ERROR_FAILURE;
}
actor->SetFeaturesAndCallback(aFeatures, aCallback);
return NS_OK;
}
using namespace mozilla::Telemetry;
auto startTime = TimeStamp::Now(); // For telemetry.
// Let's keep the features alive and release them on the correct thread.
RefPtr<FeatureHolder> holder = FeatureHolder::Create(aFeatures, aListType);
if (NS_WARN_IF(!holder)) {
return NS_ERROR_FAILURE;
}
auto worker = mWorker;
// Since aCallback will be passed around threads...
nsMainThreadPtrHandle<nsIUrlClassifierFeatureCallback> callback(
new nsMainThreadPtrHolder<nsIUrlClassifierFeatureCallback>(
"nsIURIClassifierFeatureCallback", aCallback));
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(
"nsUrlClassifierDBService::AsyncClassifyLocalWithFeatures",
[worker, key, holder, callback, startTime]() -> void {
holder->DoLocalLookup(key, worker);
nsCOMPtr<nsIRunnable> cbRunnable = NS_NewRunnableFunction(
"nsUrlClassifierDBService::AsyncClassifyLocalWithFeatures",
[callback, holder, startTime]() -> void {
// Measure the time diff between calling and callback.
AccumulateTimeDelta(
Telemetry::URLCLASSIFIER_ASYNC_CLASSIFYLOCAL_TIME, startTime);
nsTArray<RefPtr<nsIUrlClassifierFeatureResult>> results;
holder->GetResults(results);
// |callback| is captured as const value so ...
auto cb =
const_cast<nsIUrlClassifierFeatureCallback*>(callback.get());
cb->OnClassifyComplete(results);
});
NS_DispatchToMainThread(cbRunnable);
});
return gDbBackgroundThread->Dispatch(r, NS_DISPATCH_NORMAL);
}
bool nsUrlClassifierDBService::AsyncClassifyLocalWithFeaturesUsingPreferences(
nsIURI* aURI, const nsTArray<RefPtr<nsIUrlClassifierFeature>>& aFeatures,
nsIUrlClassifierFeature::listType aListType,
nsIUrlClassifierFeatureCallback* aCallback) {
MOZ_ASSERT(NS_IsMainThread());
nsAutoCString host;
nsresult rv = aURI->GetHost(host);
if (NS_WARN_IF(NS_FAILED(rv))) {
return false;
}
nsTArray<RefPtr<nsIUrlClassifierFeatureResult>> results;
// Let's see if we have special entries set by prefs.
for (nsIUrlClassifierFeature* feature : aFeatures) {
bool found = false;
nsAutoCString tableName;
rv = feature->HasHostInPreferences(host, aListType, tableName, &found);
NS_ENSURE_SUCCESS(rv, false);
if (found) {
MOZ_ASSERT(!tableName.IsEmpty());
LOG(("URI found in preferences. Table: %s", tableName.get()));
RefPtr<mozilla::net::UrlClassifierFeatureResult> result =
new mozilla::net::UrlClassifierFeatureResult(feature, tableName);
results.AppendElement(result);
}
}
if (results.IsEmpty()) {
return false;
}
// If we have some match using the preferences, we don't need to continue.
nsCOMPtr<nsIUrlClassifierFeatureCallback> callback(aCallback);
nsCOMPtr<nsIRunnable> cbRunnable = NS_NewRunnableFunction(
"nsUrlClassifierDBService::AsyncClassifyLocalWithFeatures",
[callback, results]() { callback->OnClassifyComplete(results); });
NS_DispatchToMainThread(cbRunnable);
return true;
}

View File

@@ -153,6 +153,13 @@ class nsUrlClassifierDBService final : public nsIUrlClassifierDBService,
nsresult ReadTablesFromPrefs();
// This method checks if the classification can be done just using
// preferences. It returns true if the operation has been completed.
bool AsyncClassifyLocalWithFeaturesUsingPreferences(
nsIURI* aURI, const nsTArray<RefPtr<nsIUrlClassifierFeature>>& aFeatures,
nsIUrlClassifierFeature::listType aListType,
nsIUrlClassifierFeatureCallback* aCallback);
RefPtr<nsUrlClassifierDBServiceWorker> mWorker;
RefPtr<UrlClassifierDBServiceWorkerProxy> mWorkerProxy;
@@ -216,7 +223,8 @@ class nsUrlClassifierDBServiceWorker final : public nsIUrlClassifierDBService {
// Perform a blocking classifier lookup for a given url. Can be called on
// either the main thread or the worker thread.
nsresult DoLocalLookup(const nsACString& spec, const nsACString& tables,
nsresult DoLocalLookup(const nsACString& spec,
const nsTArray<nsCString>& tables,
LookupResultArray& results);
// Open the DB connection

View File

@@ -6,7 +6,11 @@
#define nsUrlClassifierInfo_h_
#include "nsIUrlClassifierInfo.h"
#include "nsComponentManagerUtils.h"
#include "nsCOMPtr.h"
#include "nsIMutableArray.h"
#include "nsString.h"
#include "nsTArray.h"
class nsUrlClassifierPositiveCacheEntry final
: public nsIUrlClassifierPositiveCacheEntry {

View File

@@ -7,6 +7,7 @@
#include "nsUrlClassifierDBService.h"
#include "mozilla/SyncRunnable.h"
#include "Classifier.h"
using namespace mozilla;
using namespace mozilla::safebrowsing;
@@ -103,7 +104,10 @@ UrlClassifierDBServiceWorkerProxy::FinishStream() {
NS_IMETHODIMP
UrlClassifierDBServiceWorkerProxy::DoLocalLookupRunnable::Run() {
mTarget->DoLocalLookup(mSpec, mTables, mResults);
nsTArray<nsCString> tables;
Classifier::SplitTables(mTables, tables);
mTarget->DoLocalLookup(mSpec, tables, mResults);
return NS_OK;
}