Bug 1515286 - Introduce nsIURIClassifier.getFeatureByName() and nsIURIClassifier.createFeatureWithTables(), r=dimi

This commit is contained in:
Andrea Marchesini 2019-01-05 09:10:45 +01:00
Родитель ce5a0b424d
Коммит 7872e64c7c
21 изменённых файлов: 406 добавлений и 22 удалений

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

@ -154,9 +154,16 @@ var TrackingProtection = {
if (this.trackingTable == this.trackingAnnotationTable) {
return true;
}
let feature = classifierService.getFeatureByName("tracking-protection");
if (!feature) {
return false;
}
return new Promise(resolve => {
classifierService.asyncClassifyLocalWithTables(uri, this.trackingTable, [], [],
(code, list) => resolve(!!list));
classifierService.asyncClassifyLocalWithFeatures(uri, [feature],
Ci.nsIUrlClassifierFeature.blacklist,
list => resolve(!!list.length));
});
},

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

@ -0,0 +1,103 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 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 "UrlClassifierFeatureCustomTables.h"
namespace mozilla {
NS_INTERFACE_MAP_BEGIN(UrlClassifierFeatureCustomTables)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIUrlClassifierFeature)
NS_INTERFACE_MAP_ENTRY(nsIUrlClassifierFeature)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(UrlClassifierFeatureCustomTables)
NS_IMPL_RELEASE(UrlClassifierFeatureCustomTables)
UrlClassifierFeatureCustomTables::UrlClassifierFeatureCustomTables(
const nsACString& aName, const nsTArray<nsCString>& aBlacklistTables,
const nsTArray<nsCString>& aWhitelistTables)
: mName(aName),
mBlacklistTables(aBlacklistTables),
mWhitelistTables(aWhitelistTables) {}
UrlClassifierFeatureCustomTables::~UrlClassifierFeatureCustomTables() = default;
NS_IMETHODIMP
UrlClassifierFeatureCustomTables::GetName(nsACString& aName) {
aName = mName;
return NS_OK;
}
NS_IMETHODIMP
UrlClassifierFeatureCustomTables::GetTables(
nsIUrlClassifierFeature::listType aListType, nsTArray<nsCString>& aTables) {
if (aListType == nsIUrlClassifierFeature::blacklist) {
aTables = mBlacklistTables;
return NS_OK;
}
if (aListType == nsIUrlClassifierFeature::whitelist) {
aTables = mWhitelistTables;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
UrlClassifierFeatureCustomTables::HasTable(
const nsACString& aTable, nsIUrlClassifierFeature::listType aListType,
bool* aResult) {
NS_ENSURE_ARG_POINTER(aResult);
if (aListType == nsIUrlClassifierFeature::blacklist) {
*aResult = mBlacklistTables.Contains(aTable);
return NS_OK;
}
if (aListType == nsIUrlClassifierFeature::whitelist) {
*aResult = mWhitelistTables.Contains(aTable);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
UrlClassifierFeatureCustomTables::HasHostInPreferences(
const nsACString& aHost, nsIUrlClassifierFeature::listType aListType,
nsACString& aPrefTableName, bool* aResult) {
NS_ENSURE_ARG_POINTER(aResult);
*aResult = false;
return NS_OK;
}
NS_IMETHODIMP
UrlClassifierFeatureCustomTables::GetSkipHostList(nsACString& aList) {
return NS_OK;
}
NS_IMETHODIMP
UrlClassifierFeatureCustomTables::ProcessChannel(nsIChannel* aChannel,
const nsACString& aList,
bool* aShouldContinue) {
NS_ENSURE_ARG_POINTER(aChannel);
NS_ENSURE_ARG_POINTER(aShouldContinue);
// This is not a blocking feature.
*aShouldContinue = true;
return NS_OK;
}
NS_IMETHODIMP
UrlClassifierFeatureCustomTables::GetURIByListType(
nsIChannel* aChannel, nsIUrlClassifierFeature::listType aListType,
nsIURI** aURI) {
return NS_ERROR_NOT_IMPLEMENTED;
}
} // namespace mozilla

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

@ -0,0 +1,35 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 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_UrlClassifierFeatureCustomTables_h
#define mozilla_UrlClassifierFeatureCustomTables_h
#include "nsIUrlClassifierFeature.h"
#include "nsTArray.h"
#include "nsString.h"
namespace mozilla {
class UrlClassifierFeatureCustomTables : public nsIUrlClassifierFeature {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIURLCLASSIFIERFEATURE
explicit UrlClassifierFeatureCustomTables(
const nsACString& aName, const nsTArray<nsCString>& aBlacklistTables,
const nsTArray<nsCString>& aWhitelistTables);
private:
virtual ~UrlClassifierFeatureCustomTables();
nsCString mName;
nsTArray<nsCString> mBlacklistTables;
nsTArray<nsCString> mWhitelistTables;
};
} // namespace mozilla
#endif // mozilla_UrlClassifierFeatureCustomTables_h

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

@ -11,6 +11,7 @@
#include "UrlClassifierFeatureLoginReputation.h"
#include "UrlClassifierFeatureTrackingProtection.h"
#include "UrlClassifierFeatureTrackingAnnotation.h"
#include "UrlClassifierFeatureCustomTables.h"
#include "nsAppRunner.h"
@ -77,5 +78,46 @@ UrlClassifierFeatureFactory::GetFeatureLoginReputation() {
return UrlClassifierFeatureLoginReputation::MaybeGetOrCreate();
}
/* static */ already_AddRefed<nsIUrlClassifierFeature>
UrlClassifierFeatureFactory::GetFeatureByName(const nsACString& aName) {
nsCOMPtr<nsIUrlClassifierFeature> feature;
// Tracking Protection
feature = UrlClassifierFeatureTrackingProtection::GetIfNameMatches(aName);
if (feature) {
return feature.forget();
}
// Tracking Annotation
feature = UrlClassifierFeatureTrackingAnnotation::GetIfNameMatches(aName);
if (feature) {
return feature.forget();
}
// Login reputation
feature = UrlClassifierFeatureLoginReputation::GetIfNameMatches(aName);
if (feature) {
return feature.forget();
}
// We use Flash feature just for document loading.
feature = UrlClassifierFeatureFlash::GetIfNameMatches(aName);
if (feature) {
return feature.forget();
}
return nullptr;
}
/* static */ already_AddRefed<nsIUrlClassifierFeature>
UrlClassifierFeatureFactory::CreateFeatureWithTables(
const nsACString& aName, const nsTArray<nsCString>& aBlacklistTables,
const nsTArray<nsCString>& aWhitelistTables) {
nsCOMPtr<nsIUrlClassifierFeature> feature =
new UrlClassifierFeatureCustomTables(aName, aBlacklistTables,
aWhitelistTables);
return feature.forget();
}
} // namespace net
} // namespace mozilla

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

@ -27,6 +27,13 @@ class UrlClassifierFeatureFactory final {
nsTArray<nsCOMPtr<nsIUrlClassifierFeature>>& aFeatures);
static nsIUrlClassifierFeature* GetFeatureLoginReputation();
static already_AddRefed<nsIUrlClassifierFeature> GetFeatureByName(
const nsACString& aFeatureName);
static already_AddRefed<nsIUrlClassifierFeature> CreateFeatureWithTables(
const nsACString& aName, const nsTArray<nsCString>& aBlacklistTables,
const nsTArray<nsCString>& aWhitelistTables);
};
} // namespace net

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

@ -111,6 +111,22 @@ UrlClassifierFeatureFlash::UrlClassifierFeatureFlash(uint32_t aId)
}
}
/* static */ already_AddRefed<nsIUrlClassifierFeature>
UrlClassifierFeatureFlash::GetIfNameMatches(const nsACString& aName) {
uint32_t numFeatures =
(sizeof(sFlashFeaturesMap) / sizeof(sFlashFeaturesMap[0]));
for (uint32_t i = 0; i < numFeatures; ++i) {
MOZ_ASSERT(sFlashFeaturesMap[i].mFeature);
if (aName.Equals(sFlashFeaturesMap[i].mName)) {
nsCOMPtr<nsIUrlClassifierFeature> self =
sFlashFeaturesMap[i].mFeature.get();
return self.forget();
}
}
return nullptr;
}
NS_IMETHODIMP
UrlClassifierFeatureFlash::ProcessChannel(nsIChannel* aChannel,
const nsACString& aList,

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

@ -21,6 +21,9 @@ class UrlClassifierFeatureFlash final : public UrlClassifierFeatureBase {
nsIChannel* aChannel,
nsTArray<nsCOMPtr<nsIUrlClassifierFeature>>& aFeatures);
static already_AddRefed<nsIUrlClassifierFeature> GetIfNameMatches(
const nsACString& aName);
NS_IMETHOD
ProcessChannel(nsIChannel* aChannel, const nsACString& aList,
bool* aShouldContinue) override;

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

@ -13,6 +13,8 @@ namespace net {
namespace {
#define LOGIN_REPUTATION_FEATURE_NAME "login-reputation"
#define PREF_PASSWORD_ALLOW_TABLE "urlclassifier.passwordAllowTable"
StaticRefPtr<UrlClassifierFeatureLoginReputation> gFeatureLoginReputation;
@ -20,14 +22,15 @@ StaticRefPtr<UrlClassifierFeatureLoginReputation> gFeatureLoginReputation;
} // namespace
UrlClassifierFeatureLoginReputation::UrlClassifierFeatureLoginReputation()
: UrlClassifierFeatureBase(NS_LITERAL_CSTRING("login-reputation"),
EmptyCString(), // blacklist tables
NS_LITERAL_CSTRING(PREF_PASSWORD_ALLOW_TABLE),
EmptyCString(), // blacklist pref
EmptyCString(), // whitelist pref
EmptyCString(), // blacklist pref table name
EmptyCString(), // whitelist pref table name
EmptyCString()) // skip host pref
: UrlClassifierFeatureBase(
NS_LITERAL_CSTRING(LOGIN_REPUTATION_FEATURE_NAME),
EmptyCString(), // blacklist tables
NS_LITERAL_CSTRING(PREF_PASSWORD_ALLOW_TABLE),
EmptyCString(), // blacklist pref
EmptyCString(), // whitelist pref
EmptyCString(), // blacklist pref table name
EmptyCString(), // whitelist pref table name
EmptyCString()) // skip host pref
{}
/* static */ void UrlClassifierFeatureLoginReputation::MaybeShutdown() {
@ -53,6 +56,16 @@ UrlClassifierFeatureLoginReputation::MaybeGetOrCreate() {
return gFeatureLoginReputation;
}
/* static */ already_AddRefed<nsIUrlClassifierFeature>
UrlClassifierFeatureLoginReputation::GetIfNameMatches(const nsACString& aName) {
if (!aName.EqualsLiteral(LOGIN_REPUTATION_FEATURE_NAME)) {
return nullptr;
}
nsCOMPtr<nsIUrlClassifierFeature> self = MaybeGetOrCreate();
return self.forget();
}
NS_IMETHODIMP
UrlClassifierFeatureLoginReputation::ProcessChannel(nsIChannel* aChannel,
const nsACString& aList,

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

@ -21,6 +21,9 @@ class UrlClassifierFeatureLoginReputation final
static nsIUrlClassifierFeature* MaybeGetOrCreate();
static already_AddRefed<nsIUrlClassifierFeature> GetIfNameMatches(
const nsACString& aName);
NS_IMETHOD
GetTables(nsIUrlClassifierFeature::listType aListType,
nsTArray<nsCString>& aResult) override;

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

@ -21,6 +21,8 @@ namespace net {
namespace {
#define TRACKING_ANNOTATION_FEATURE_NAME "tracking-annotation"
#define URLCLASSIFIER_ANNOTATION_BLACKLIST \
"urlclassifier.trackingAnnotationTable"
#define URLCLASSIFIER_ANNOTATION_BLACKLIST_TEST_ENTRIES \
@ -109,7 +111,7 @@ static void LowerPriorityHelper(nsIChannel* aChannel) {
UrlClassifierFeatureTrackingAnnotation::UrlClassifierFeatureTrackingAnnotation()
: UrlClassifierFeatureBase(
NS_LITERAL_CSTRING("tracking-annotation"),
NS_LITERAL_CSTRING(TRACKING_ANNOTATION_FEATURE_NAME),
NS_LITERAL_CSTRING(URLCLASSIFIER_ANNOTATION_BLACKLIST),
NS_LITERAL_CSTRING(URLCLASSIFIER_ANNOTATION_WHITELIST),
NS_LITERAL_CSTRING(URLCLASSIFIER_ANNOTATION_BLACKLIST_TEST_ENTRIES),
@ -156,6 +158,20 @@ UrlClassifierFeatureTrackingAnnotation::MaybeCreate(nsIChannel* aChannel) {
return self.forget();
}
/* static */ already_AddRefed<nsIUrlClassifierFeature>
UrlClassifierFeatureTrackingAnnotation::GetIfNameMatches(
const nsACString& aName) {
MOZ_ASSERT(gFeatureTrackingAnnotation);
if (!aName.EqualsLiteral(TRACKING_ANNOTATION_FEATURE_NAME)) {
return nullptr;
}
RefPtr<UrlClassifierFeatureTrackingAnnotation> self =
gFeatureTrackingAnnotation;
return self.forget();
}
NS_IMETHODIMP
UrlClassifierFeatureTrackingAnnotation::ProcessChannel(nsIChannel* aChannel,
const nsACString& aList,

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

@ -24,6 +24,9 @@ class UrlClassifierFeatureTrackingAnnotation final
static already_AddRefed<UrlClassifierFeatureTrackingAnnotation> MaybeCreate(
nsIChannel* aChannel);
static already_AddRefed<nsIUrlClassifierFeature> GetIfNameMatches(
const nsACString& aName);
NS_IMETHOD ProcessChannel(nsIChannel* aChannel, const nsACString& aList,
bool* aShouldContinue) override;

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

@ -17,6 +17,8 @@ namespace net {
namespace {
#define TRACKING_PROTECTION_FEATURE_NAME "tracking-protection"
#define URLCLASSIFIER_TRACKING_BLACKLIST "urlclassifier.trackingTable"
#define URLCLASSIFIER_TRACKING_BLACKLIST_TEST_ENTRIES \
"urlclassifier.trackingTable.testEntries"
@ -32,7 +34,7 @@ StaticRefPtr<UrlClassifierFeatureTrackingProtection> gFeatureTrackingProtection;
UrlClassifierFeatureTrackingProtection::UrlClassifierFeatureTrackingProtection()
: UrlClassifierFeatureBase(
NS_LITERAL_CSTRING("tracking-protection"),
NS_LITERAL_CSTRING(TRACKING_PROTECTION_FEATURE_NAME),
NS_LITERAL_CSTRING(URLCLASSIFIER_TRACKING_BLACKLIST),
NS_LITERAL_CSTRING(URLCLASSIFIER_TRACKING_WHITELIST),
NS_LITERAL_CSTRING(URLCLASSIFIER_TRACKING_BLACKLIST_TEST_ENTRIES),
@ -103,6 +105,20 @@ UrlClassifierFeatureTrackingProtection::MaybeCreate(nsIChannel* aChannel) {
return self.forget();
}
/* static */ already_AddRefed<nsIUrlClassifierFeature>
UrlClassifierFeatureTrackingProtection::GetIfNameMatches(
const nsACString& aName) {
MOZ_ASSERT(gFeatureTrackingProtection);
if (!aName.EqualsLiteral(TRACKING_PROTECTION_FEATURE_NAME)) {
return nullptr;
}
RefPtr<UrlClassifierFeatureTrackingProtection> self =
gFeatureTrackingProtection;
return self.forget();
}
NS_IMETHODIMP
UrlClassifierFeatureTrackingProtection::ProcessChannel(nsIChannel* aChannel,
const nsACString& aList,

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

@ -24,6 +24,9 @@ class UrlClassifierFeatureTrackingProtection final
static already_AddRefed<UrlClassifierFeatureTrackingProtection> MaybeCreate(
nsIChannel* aChannel);
static already_AddRefed<nsIUrlClassifierFeature> GetIfNameMatches(
const nsACString& aName);
NS_IMETHOD ProcessChannel(nsIChannel* aChannel, const nsACString& aList,
bool* aShouldContinue) override;

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

@ -22,6 +22,7 @@ UNIFIED_SOURCES += [
'nsChannelClassifier.cpp',
'UrlClassifierCommon.cpp',
'UrlClassifierFeatureBase.cpp',
'UrlClassifierFeatureCustomTables.cpp',
'UrlClassifierFeatureFactory.cpp',
'UrlClassifierFeatureFlash.cpp',
'UrlClassifierFeatureLoginReputation.cpp',

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

@ -104,6 +104,19 @@ interface nsIURIClassifier : nsISupports
in nsIUrlClassifierFeature_listType aListType,
in nsIUrlClassifierFeatureCallback aCallback);
/**
* Returns a feature named aFeatureName.
*/
nsIUrlClassifierFeature getFeatureByName(in ACString aFeatureName);
/**
* Create a new feature with a list of tables. This method is just for
* testing! Don't use it elsewhere.
*/
nsIUrlClassifierFeature createFeatureWithTables(in ACString aName,
in Array<ACString> aBlacklistTables,
in Array<ACString> aWhitelistTables);
/**
* Report to the provider that a Safe Browsing warning was shown.
*

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

@ -2245,19 +2245,21 @@ SpecialPowersAPI.prototype = {
let classifierService =
Cc["@mozilla.org/url-classifier/dbservice;1"].getService(Ci.nsIURIClassifier);
let wrapCallback = (...args) => {
let wrapCallback = results => {
Services.tm.dispatchToMainThread(() => {
if (typeof callback == "function") {
callback(...args);
callback(wrapIfUnwrapped(results));
} else {
callback.onClassifyComplete.call(undefined, ...args);
callback.onClassifyComplete.call(undefined, wrapIfUnwrapped(results));
}
});
};
return classifierService.asyncClassifyLocalWithTables(unwrapIfWrapped(uri),
tables, [], [],
wrapCallback);
let feature = classifierService.createFeatureWithTables("test", tables.split(","), []);
return classifierService.asyncClassifyLocalWithFeatures(unwrapIfWrapped(uri),
[feature],
Ci.nsIUrlClassifierFeature.blacklist,
wrapCallback);
},
EARLY_BETA_OR_EARLIER: AppConstants.EARLY_BETA_OR_EARLIER,

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

@ -7,6 +7,7 @@
#define UrlClassifierTelemetryUtils_h__
#include "mozilla/TypedEnumBits.h"
#include "nsISupportsImpl.h"
namespace mozilla {
namespace safebrowsing {

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

@ -47,6 +47,7 @@
#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/PermissionMessageUtils.h"
#include "mozilla/dom/URLClassifierChild.h"
#include "mozilla/net/UrlClassifierFeatureFactory.h"
#include "mozilla/net/UrlClassifierFeatureResult.h"
#include "mozilla/ipc/URIUtils.h"
#include "mozilla/SyncRunnable.h"
@ -2852,3 +2853,34 @@ bool nsUrlClassifierDBService::AsyncClassifyLocalWithFeaturesUsingPreferences(
NS_DispatchToMainThread(cbRunnable);
return true;
}
NS_IMETHODIMP
nsUrlClassifierDBService::GetFeatureByName(const nsACString& aFeatureName,
nsIUrlClassifierFeature** aFeature) {
NS_ENSURE_ARG_POINTER(aFeature);
nsCOMPtr<nsIUrlClassifierFeature> feature =
mozilla::net::UrlClassifierFeatureFactory::GetFeatureByName(aFeatureName);
if (NS_WARN_IF(!feature)) {
return NS_ERROR_FAILURE;
}
feature.forget(aFeature);
return NS_OK;
}
NS_IMETHODIMP
nsUrlClassifierDBService::CreateFeatureWithTables(
const nsACString& aName, const nsTArray<nsCString>& aBlacklistTables,
const nsTArray<nsCString>& aWhitelistTables,
nsIUrlClassifierFeature** aFeature) {
NS_ENSURE_ARG_POINTER(aFeature);
nsCOMPtr<nsIUrlClassifierFeature> feature =
mozilla::net::UrlClassifierFeatureFactory::CreateFeatureWithTables(
aName, aBlacklistTables, aWhitelistTables);
if (NS_WARN_IF(!feature)) {
return NS_ERROR_FAILURE;
}
feature.forget(aFeature);
return NS_OK;
}

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

@ -147,9 +147,15 @@ function testService() {
SpecialPowers.doUrlClassify(prin, null, test.trackingProtection, function(errorCode) {
is(errorCode, test.result,
`Successful asynchronous classification of ${test.url} with TP=${test.trackingProtection}`);
SpecialPowers.doUrlClassifyLocal(uri, tables, function(errorCode1, tables1) {
is(tables1, test.table,
`Successful asynchronous local classification of ${test.url} with TP=${test.trackingProtection}`);
SpecialPowers.doUrlClassifyLocal(uri, tables, function(results) {
if (results.length == 0) {
is(test.table, "",
`Successful asynchronous local classification of ${test.url} with TP=${test.trackingProtection}`);
} else {
let result = results[0].QueryInterface(Ci.nsIUrlClassifierFeatureResult);
is(result.list, test.table,
`Successful asynchronous local classification of ${test.url} with TP=${test.trackingProtection}`);
}
runNextTest();
});

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

@ -0,0 +1,61 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
*/
"use strict";
add_test(async _ => {
Services.prefs.setBoolPref("browser.safebrowsing.passwords.enabled", true);
let classifier = Cc["@mozilla.org/url-classifier/dbservice;1"]
.getService(Ci.nsIURIClassifier);
ok(!!classifier, "We have the URI-Classifier");
var tests = [
{ name: "a", expectedResult: false },
{ name: "tracking-annotation", expectedResult: true },
{ name: "tracking-protection", expectedResult: true },
{ name: "login-reputation", expectedResult: true },
];
tests.forEach(test => {
let feature;
try {
feature = classifier.getFeatureByName(test.name);
} catch (e) {
}
equal(!!feature, test.expectedResult, "Exceptected result for: " + test.name);
if (feature) {
equal(feature.name, test.name, "Feature name matches");
}
});
let uri = Services.io.newURI("https://example.com");
let feature = classifier.getFeatureByName("tracking-protection");
let results = await new Promise(resolve => {
classifier.asyncClassifyLocalWithFeatures(uri, [feature],
Ci.nsIUrlClassifierFeature.blacklist,
r => { resolve(r); });
});
equal(results.length, 0, "No tracker");
Services.prefs.setCharPref("urlclassifier.trackingTable.testEntries", "example.com");
feature = classifier.getFeatureByName("tracking-protection");
results = await new Promise(resolve => {
classifier.asyncClassifyLocalWithFeatures(uri, [feature],
Ci.nsIUrlClassifierFeature.blacklist,
r => { resolve(r); });
});
equal(results.length, 1, "Tracker");
let result = results[0];
equal(result.feature.name, "tracking-protection", "Correct feature");
equal(result.list, "tracking-blacklist-pref", "Correct list");
Services.prefs.clearUserPref("browser.safebrowsing.password.enabled");
run_next_test();
});

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

@ -23,4 +23,5 @@ support-files =
[test_pref.js]
[test_malwaretable_pref.js]
[test_safebrowsing_protobuf.js]
[test_platform_specific_threats.js]
[test_platform_specific_threats.js]
[test_features.js]