Bug 1531354 - P5. Safe Browsing test entries are directly stored in LookupCache. r=gcp
authordlee <dlee@mozilla.com>
Sat, 29 Jun 2019 19:05:41 +0000
changeset 543539 cc7cce83765a90aa1b25b566917b42e9450532fe
parent 543538 7417be59b320f4ba945e3c4f6c0a47b0c19d8df2
child 543540 93c33782f57deb40cd05a08bf0c72092bddb327e
push id2131
push userffxbld-merge
push dateMon, 26 Aug 2019 18:30:20 +0000
treeherdermozilla-release@b19ffb3ca153 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgcp
bugs1531354
milestone69.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
Bug 1531354 - P5. Safe Browsing test entries are directly stored in LookupCache. r=gcp Create test entries via update introduces performance overhead. We can store them directly in LookupCache and do not save test entries to disk. Differential Revision: https://phabricator.services.mozilla.com/D34576
browser/components/safebrowsing/content/test/head.js
mobile/android/app/mobile.js
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/ContentBlocking.java
mobile/android/tests/browser/robocop/testTrackingProtection.js
mobile/android/tests/browser/robocop/tracking_bad.html
modules/libpref/init/all.js
testing/firefox-ui/tests/functional/safebrowsing/test_initial_download.py
toolkit/components/url-classifier/Classifier.cpp
toolkit/components/url-classifier/Classifier.h
toolkit/components/url-classifier/LookupCache.cpp
toolkit/components/url-classifier/LookupCache.h
toolkit/components/url-classifier/LookupCacheV4.cpp
toolkit/components/url-classifier/LookupCacheV4.h
toolkit/components/url-classifier/SafeBrowsing.jsm
toolkit/components/url-classifier/UrlClassifierListManager.jsm
toolkit/components/url-classifier/nsIUrlListManager.idl
toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
toolkit/components/url-classifier/nsUrlClassifierUtils.cpp
toolkit/components/url-classifier/nsUrlClassifierUtils.h
toolkit/components/url-classifier/tests/browser/classifierHelper.js
toolkit/components/url-classifier/tests/gtest/TestFailUpdate.cpp
toolkit/components/url-classifier/tests/gtest/TestFindFullHash.cpp
toolkit/components/url-classifier/tests/mochitest/classifierCommon.js
toolkit/components/url-classifier/tests/mochitest/test_allowlisted_annotations.html
toolkit/components/url-classifier/tests/mochitest/test_bug1254766.html
toolkit/components/url-classifier/tests/mochitest/test_cachemiss.html
toolkit/components/url-classifier/tests/mochitest/test_classified_annotations.html
toolkit/components/url-classifier/tests/mochitest/test_classifier.html
toolkit/components/url-classifier/tests/mochitest/test_classifier_worker.html
toolkit/components/url-classifier/tests/mochitest/test_classify_ping.html
toolkit/components/url-classifier/tests/mochitest/test_gethash.html
toolkit/components/url-classifier/tests/mochitest/test_safebrowsing_bug1272239.html
toolkit/components/url-classifier/tests/mochitest/test_trackingprotection_bug1157081.html
toolkit/components/url-classifier/tests/unit/head_urlclassifier.js
toolkit/components/url-classifier/tests/unit/test_threat_type_conversion.js
--- a/browser/components/safebrowsing/content/test/head.js
+++ b/browser/components/safebrowsing/content/test/head.js
@@ -1,13 +1,13 @@
 var {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 
 // This url must sync with the table, url in SafeBrowsing.jsm addMozEntries
-const PHISH_TABLE = "test-phish-simple";
+const PHISH_TABLE = "moztest-phish-simple";
 const PHISH_URL = "https://www.itisatrap.org/firefox/its-a-trap.html";
 
 /**
  * Waits for a load (or custom) event to finish in a given tab. If provided
  * load an uri into the tab.
  *
  * @param tab
  *        The tab to load into.
@@ -81,12 +81,12 @@ function waitForDBInit(callback) {
   dbService.lookup(principal, PHISH_TABLE, value => {
     if (value === PHISH_TABLE) {
       ok(true, "DB lookup success!");
       callbackOnce();
     }
   });
 }
 
-Services.prefs.setCharPref("urlclassifier.malwareTable", "test-malware-simple,test-unwanted-simple,test-harmful.simple");
-Services.prefs.setCharPref("urlclassifier.phishTable", "test-phish-simple");
-Services.prefs.setCharPref("urlclassifier.blockedTable", "test-block-simple");
+Services.prefs.setCharPref("urlclassifier.malwareTable", "moztest-malware-simple,moztest-unwanted-simple,moztest-harmful-simple");
+Services.prefs.setCharPref("urlclassifier.phishTable", "moztest-phish-simple");
+Services.prefs.setCharPref("urlclassifier.blockedTable", "moztest-block-simple");
 SafeBrowsing.init();
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -585,17 +585,17 @@ pref("image.downscale-during-decode.enab
 // The download protection UI is not implemented yet (bug 1239094).
 pref("browser.safebrowsing.downloads.enabled", false);
 
 // The application reputation lists are not available on Android.
 pref("urlclassifier.downloadAllowTable", "");
 pref("urlclassifier.downloadBlockTable", "");
 
 // The Potentially Harmful Apps list replaces the malware one on Android.
-pref("urlclassifier.malwareTable", "goog-harmful-proto,goog-unwanted-proto,test-harmful-simple,test-malware-simple,test-unwanted-simple");
+pref("urlclassifier.malwareTable", "goog-harmful-proto,goog-unwanted-proto,moztest-harmful-simple,moztest-malware-simple,moztest-unwanted-simple");
 
 // True if you always want dump() to work
 //
 // On Android, you also need to do the following for the output
 // to show up in logcat:
 //
 // $ adb shell stop
 // $ adb shell setprop log.redirect-stdio true
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/ContentBlocking.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/ContentBlocking.java
@@ -427,17 +427,17 @@ public class ContentBlocking {
         * @param event The {@link BlockEvent} details.
         */
         @UiThread
         default void onContentBlocked(@NonNull GeckoSession session,
                                       @NonNull BlockEvent event) {}
     }
 
 
-    private static final String TEST = "test-track-simple";
+    private static final String TEST = "moztest-track-simple";
     private static final String AD = "ads-track-digest256";
     private static final String ANALYTIC = "analytics-track-digest256";
     private static final String SOCIAL = "social-track-digest256";
     private static final String CONTENT = "content-track-digest256";
     private static final String CRYPTOMINING =
         "base-cryptomining-track-digest256";
     private static final String FINGERPRINTING =
         "base-fingerprinting-track-digest256";
--- a/mobile/android/tests/browser/robocop/testTrackingProtection.js
+++ b/mobile/android/tests/browser/robocop/testTrackingProtection.js
@@ -35,72 +35,35 @@ function promiseLoadEvent(browser, url, 
       browser.loadURI(url);
     }
   });
 }
 
 // Test that the Tracking Protection is active and has the correct state when
 // tracking content is blocked (Bug 1063831 + Bug 1520520)
 
-// Code is mostly stolen from:
-// http://dxr.mozilla.org/mozilla-central/source/browser/base/content/test/general/browser_trackingUI.js
-
 var TABLE = "urlclassifier.trackingTable";
 
-// Update tracking database
-function doUpdate() {
-  // Add some URLs to the tracking database (to be blocked)
-  var testData = "tracking.example.com/";
-  var testUpdate =
-    "n:1000\ni:test-track-simple\nad:1\n" +
-    "a:524:32:" + testData.length + "\n" +
-    testData;
-
-  let dbService = Cc["@mozilla.org/url-classifier/dbservice;1"].getService(Ci.nsIUrlClassifierDBService);
-
-  return new Promise((resolve, reject) => {
-    let listener = {
-      QueryInterface: ChromeUtils.generateQI([Ci.nsIUrlClassifierUpdateObserver]),
-      updateUrlRequested: function(url) { },
-      streamFinished: function(status) { },
-      updateError: function(errorCode) {
-        ok(false, "Couldn't update classifier.");
-        resolve();
-      },
-      updateSuccess: function(requestedTimeout) {
-        resolve();
-      },
-    };
-
-    dbService.beginUpdate(listener, "test-track-simple", "");
-    dbService.beginStream("", "");
-    dbService.updateStream(testUpdate);
-    dbService.finishStream();
-    dbService.finishUpdate();
-  });
-}
-
 var BrowserApp = Services.wm.getMostRecentWindow("navigator:browser").BrowserApp;
 
 // Tests the tracking protection UI in private browsing. By default, tracking protection is
 // enabled in private browsing ("privacy.trackingprotection.pbmode.enabled").
 add_task(async function test_tracking_pb() {
   Services.prefs.setBoolPref(DTSCBN_PREF, true);
 
   // Load a blank page
   let browser = BrowserApp.addTab("about:blank", { selected: true, parentId: BrowserApp.selectedTab.id, isPrivate: true }).browser;
   await new Promise((resolve, reject) => {
     browser.addEventListener("load", function(event) {
       Services.tm.dispatchToMainThread(resolve);
     }, {capture: true, once: true});
   });
 
   // Populate and use 'test-track-simple' for tracking protection lookups
-  Services.prefs.setCharPref(TABLE, "test-track-simple");
-  await doUpdate();
+  Services.prefs.setCharPref(TABLE, "moztest-track-simple");
 
   // Point tab to a test page NOT containing tracking elements
   await promiseLoadEvent(browser, "http://tracking.example.org/tests/robocop/tracking_good.html");
   EventDispatcher.instance.sendRequest({ type: "Test:Expected", expected: "unknown" });
 
   // Point tab to a test page containing tracking elements
   await promiseLoadEvent(browser, "http://tracking.example.org/tests/robocop/tracking_bad.html");
   EventDispatcher.instance.sendRequest({ type: "Test:Expected", expected: "tracking_content_blocked" });
--- a/mobile/android/tests/browser/robocop/tracking_bad.html
+++ b/mobile/android/tests/browser/robocop/tracking_bad.html
@@ -2,11 +2,11 @@
 <!-- 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/. -->
 <html dir="ltr" xml:lang="en-US" lang="en-US">
   <head>
     <meta charset="utf8">
   </head>
   <body>
-    <iframe src="http://tracking.example.com/"></iframe>
+    <iframe src="http://itisatracker.org/"></iframe>
   </body>
 </html>
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -5195,37 +5195,37 @@ pref("captivedetect.canonicalContent", "
 pref("captivedetect.maxWaitingTime", 5000);
 pref("captivedetect.pollingTime", 3000);
 pref("captivedetect.maxRetryCount", 5);
 
 // Enable mapped array buffer by default.
 pref("dom.mapped_arraybuffer.enabled", true);
 
 // The tables used for Safebrowsing phishing and malware checks
-pref("urlclassifier.malwareTable", "goog-malware-proto,goog-unwanted-proto,test-harmful-simple,test-malware-simple,test-unwanted-simple");
+pref("urlclassifier.malwareTable", "goog-malware-proto,goog-unwanted-proto,moztest-harmful-simple,moztest-malware-simple,moztest-unwanted-simple");
 #ifdef MOZILLA_OFFICIAL
 // In official builds, we are allowed to use Google's private phishing
 // list (see bug 1288840).
-pref("urlclassifier.phishTable", "goog-phish-proto,test-phish-simple");
+pref("urlclassifier.phishTable", "goog-phish-proto,moztest-phish-simple");
 #else
-pref("urlclassifier.phishTable", "googpub-phish-proto,test-phish-simple");
+pref("urlclassifier.phishTable", "googpub-phish-proto,moztest-phish-simple");
 #endif
 
 // Tables for application reputation
 pref("urlclassifier.downloadAllowTable", "goog-downloadwhite-proto");
 pref("urlclassifier.downloadBlockTable", "goog-badbinurl-proto");
 
 // Tables for login reputation
 pref("urlclassifier.passwordAllowTable", "goog-passwordwhite-proto");
 
 // Tables for anti-tracking features
-pref("urlclassifier.trackingAnnotationTable", "test-track-simple,ads-track-digest256,social-track-digest256,analytics-track-digest256,content-track-digest256");
-pref("urlclassifier.trackingAnnotationWhitelistTable", "test-trackwhite-simple,mozstd-trackwhite-digest256");
-pref("urlclassifier.trackingTable", "test-track-simple,base-track-digest256");
-pref("urlclassifier.trackingWhitelistTable", "test-trackwhite-simple,mozstd-trackwhite-digest256");
+pref("urlclassifier.trackingAnnotationTable", "moztest-track-simple,ads-track-digest256,social-track-digest256,analytics-track-digest256,content-track-digest256");
+pref("urlclassifier.trackingAnnotationWhitelistTable", "moztest-trackwhite-simple,mozstd-trackwhite-digest256");
+pref("urlclassifier.trackingTable", "moztest-track-simple,base-track-digest256");
+pref("urlclassifier.trackingWhitelistTable", "moztest-trackwhite-simple,mozstd-trackwhite-digest256");
 
 pref("urlclassifier.features.fingerprinting.blacklistTables", "base-fingerprinting-track-digest256");
 pref("urlclassifier.features.fingerprinting.whitelistTables", "mozstd-trackwhite-digest256");
 pref("urlclassifier.features.cryptomining.blacklistTables", "base-cryptomining-track-digest256");
 pref("urlclassifier.features.cryptomining.whitelistTables", "mozstd-trackwhite-digest256");
 
 // These tables will never trigger a gethash call.
 pref("urlclassifier.disallow_completions", "goog-downloadwhite-digest256,base-track-digest256,mozstd-trackwhite-digest256,content-track-digest256,mozplugin-block-digest256,mozplugin2-block-digest256,block-flash-digest256,except-flash-digest256,allow-flashallow-digest256,except-flashallow-digest256,block-flashsubdoc-digest256,except-flashsubdoc-digest256,goog-passwordwhite-proto,ads-track-digest256,social-track-digest256,analytics-track-digest256,base-fingerprinting-track-digest256,content-fingerprinting-track-digest256,base-cryptomining-track-digest256,content-cryptomining-track-digest256,fanboyannoyance-ads-digest256,fanboysocial-ads-digest256,easylist-ads-digest256,easyprivacy-ads-digest256,adguard-ads-digest256");
@@ -5304,17 +5304,17 @@ pref("browser.safebrowsing.provider.mozi
 // Set to a date in the past to force immediate download in new profiles.
 pref("browser.safebrowsing.provider.mozilla.nextupdatetime", "1");
 // Block lists for tracking protection. The name values will be used as the keys
 // to lookup the localized name in preferences.properties.
 pref("browser.safebrowsing.provider.mozilla.lists.base", "moz-std");
 pref("browser.safebrowsing.provider.mozilla.lists.content", "moz-full");
 
 // The table and global pref for blocking plugin content
-pref("urlclassifier.blockedTable", "test-block-simple,mozplugin-block-digest256");
+pref("urlclassifier.blockedTable", "moztest-block-simple,mozplugin-block-digest256");
 
 // Flash blocking tables
 pref("urlclassifier.flashAllowTable", "allow-flashallow-digest256");
 pref("urlclassifier.flashAllowExceptTable", "except-flashallow-digest256");
 pref("urlclassifier.flashTable", "block-flash-digest256");
 pref("urlclassifier.flashExceptTable", "except-flash-digest256");
 pref("urlclassifier.flashSubDocTable", "block-flashsubdoc-digest256");
 pref("urlclassifier.flashSubDocExceptTable", "except-flashsubdoc-digest256");
--- a/testing/firefox-ui/tests/functional/safebrowsing/test_initial_download.py
+++ b/testing/firefox-ui/tests/functional/safebrowsing/test_initial_download.py
@@ -7,17 +7,17 @@ import os
 from firefox_puppeteer import PuppeteerMixin
 from marionette_driver import Wait
 from marionette_harness import MarionetteTestCase
 
 
 class TestSafeBrowsingInitialDownload(PuppeteerMixin, MarionetteTestCase):
 
     v2_file_extensions = [
-        'pset',
+        'vlpset',
         'sbstore',
     ]
 
     v4_file_extensions = [
         'vlpset',
         'metadata',
     ]
 
@@ -51,16 +51,20 @@ class TestSafeBrowsingInitialDownload(Pu
 
         if is_v4:
             my_file_extensions = self.v4_file_extensions
         else:  # v2
             my_file_extensions = self.v2_file_extensions
 
         for pref_name in self.prefs_download_lists:
             base_names = self.marionette.get_pref(pref_name).split(',')
+
+            # moztest- lists are not saved to disk
+            base_names = filter(lambda x: not x.startswith('moztest-'), base_names)
+
             for ext in my_file_extensions:
                 files.extend(['{name}.{ext}'.format(name=f, ext=ext)
                               for f in base_names if f and f.endswith('-proto') == is_v4])
 
         return set(sorted(files))
 
     def setUp(self):
         super(TestSafeBrowsingInitialDownload, self).setUp()
--- a/toolkit/components/url-classifier/Classifier.cpp
+++ b/toolkit/components/url-classifier/Classifier.cpp
@@ -855,20 +855,25 @@ void Classifier::DropStores() {
 
 nsresult Classifier::RegenActiveTables() {
   if (ShouldAbort()) {
     return NS_OK;  // nothing to do, the classifier is done
   }
 
   mActiveTablesCache.Clear();
 
+  // Create
   nsTArray<nsCString> foundTables;
   nsresult rv = ScanStoreDir(mRootStoreDirectory, foundTables);
   Unused << NS_WARN_IF(NS_FAILED(rv));
 
+  // We don't have test tables on disk, add Moz built-in entries here
+  rv = AddMozEntries(foundTables);
+  Unused << NS_WARN_IF(NS_FAILED(rv));
+
   for (const auto& table : foundTables) {
     RefPtr<const LookupCache> lookupCache = GetLookupCache(table);
     if (!lookupCache) {
       LOG(("Inactive table (no cache): %s", table.get()));
       continue;
     }
 
     if (!lookupCache->IsPrimed()) {
@@ -881,16 +886,40 @@ nsresult Classifier::RegenActiveTables()
          table.get()));
 
     mActiveTablesCache.AppendElement(table);
   }
 
   return NS_OK;
 }
 
+nsresult Classifier::AddMozEntries(nsTArray<nsCString>& aTables) {
+  nsTArray<nsLiteralCString> tables = {
+      NS_LITERAL_CSTRING("moztest-phish-simple"),
+      NS_LITERAL_CSTRING("moztest-malware-simple"),
+      NS_LITERAL_CSTRING("moztest-unwanted-simple"),
+      NS_LITERAL_CSTRING("moztest-harmful-simple"),
+      NS_LITERAL_CSTRING("moztest-track-simple"),
+      NS_LITERAL_CSTRING("moztest-trackwhite-simple"),
+      NS_LITERAL_CSTRING("moztest-block-simple"),
+  };
+
+  for (const auto& table : tables) {
+    RefPtr<LookupCache> c = GetLookupCache(table, false);
+    RefPtr<LookupCacheV2> lookupCache = LookupCache::Cast<LookupCacheV2>(c);
+    if (!lookupCache || lookupCache->IsPrimed()) {
+      continue;
+    }
+
+    aTables.AppendElement(table);
+  }
+
+  return NS_OK;
+}
+
 nsresult Classifier::ScanStoreDir(nsIFile* aDirectory,
                                   nsTArray<nsCString>& aTables) {
   nsCOMPtr<nsIDirectoryEnumerator> entries;
   nsresult rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIFile> file;
   while (NS_SUCCEEDED(rv = entries->GetNextFile(getter_AddRefs(file))) &&
@@ -1171,16 +1200,22 @@ nsCString Classifier::GetProvider(const 
 nsresult Classifier::UpdateHashStore(TableUpdateArray& aUpdates,
                                      const nsACString& aTable) {
   if (ShouldAbort()) {
     return NS_ERROR_UC_UPDATE_SHUTDOWNING;
   }
 
   LOG(("Classifier::UpdateHashStore(%s)", PromiseFlatCString(aTable).get()));
 
+  // moztest- tables don't support update because they are directly created
+  // in LookupCache. To test updates, use tables begin with "test-" instead.
+  // Also, recommend using 'test-' tables while writing testcases because
+  // it is more like the real world scenario.
+  MOZ_ASSERT(!nsUrlClassifierUtils::IsMozTestTable(aTable));
+
   HashStore store(aTable, GetProvider(aTable), mUpdatingDirectory);
 
   if (!CheckValidUpdate(aUpdates, store.TableName())) {
     return NS_OK;
   }
 
   nsresult rv = store.Open();
   NS_ENSURE_SUCCESS(rv, rv);
@@ -1272,16 +1307,19 @@ nsresult Classifier::UpdateHashStore(Tab
 nsresult Classifier::UpdateTableV4(TableUpdateArray& aUpdates,
                                    const nsACString& aTable) {
   MOZ_ASSERT(!NS_IsMainThread(),
              "UpdateTableV4 must be called on the classifier worker thread.");
   if (ShouldAbort()) {
     return NS_ERROR_UC_UPDATE_SHUTDOWNING;
   }
 
+  // moztest- tables don't support update, see comment in UpdateHashStore.
+  MOZ_ASSERT(!nsUrlClassifierUtils::IsMozTestTable(aTable));
+
   LOG(("Classifier::UpdateTableV4(%s)", PromiseFlatCString(aTable).get()));
 
   if (!CheckValidUpdate(aUpdates, aTable)) {
     return NS_OK;
   }
 
   RefPtr<LookupCacheV4> lookupCacheV4;
   {
--- a/toolkit/components/url-classifier/Classifier.h
+++ b/toolkit/components/url-classifier/Classifier.h
@@ -194,16 +194,18 @@ class Classifier {
    * |aBackgroundRv| will be returned to forward the background update result.
    */
   nsresult ApplyUpdatesForeground(nsresult aBackgroundRv,
                                   const nsACString& aFailedTableName);
 
   // Used by worker thread and update thread to abort current operation.
   bool ShouldAbort() const;
 
+  nsresult AddMozEntries(nsTArray<nsCString>& aTables);
+
   // Root dir of the Local profile.
   nsCOMPtr<nsIFile> mCacheDirectory;
   // Main directory where to store the databases.
   nsCOMPtr<nsIFile> mRootStoreDirectory;
   // Used for atomically updating the other dirs.
   nsCOMPtr<nsIFile> mBackupDirectory;
   nsCOMPtr<nsIFile> mUpdatingDirectory;  // For update only.
   nsCOMPtr<nsIFile> mToDeleteDirectory;
--- a/toolkit/components/url-classifier/LookupCache.cpp
+++ b/toolkit/components/url-classifier/LookupCache.cpp
@@ -172,20 +172,28 @@ LookupCache::LookupCache(const nsACStrin
       mTableName(aTableName),
       mProvider(aProvider),
       mRootStoreDirectory(aRootStoreDir) {
   UpdateRootDirHandle(mRootStoreDirectory);
 }
 
 nsresult LookupCache::Open() {
   LOG(("Loading PrefixSet for %s", mTableName.get()));
-  nsresult rv = LoadPrefixSet();
-  NS_ENSURE_SUCCESS(rv, rv);
+  nsresult rv;
+  if (nsUrlClassifierUtils::IsMozTestTable(mTableName)) {
+    // For built-in test table, we don't load it from disk,
+    // test entries are directly added in memory.
+    rv = LoadMozEntries();
+  } else {
+    rv = LoadPrefixSet();
+  }
 
-  return NS_OK;
+  Unused << NS_WARN_IF(NS_FAILED(rv));
+
+  return rv;
 }
 
 nsresult LookupCache::Init() {
   mVLPrefixSet = new VariableLengthPrefixSet();
   nsresult rv = mVLPrefixSet->Init(mTableName);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
@@ -858,10 +866,66 @@ nsresult LookupCacheV2::SanityCheck(cons
 nsresult LookupCacheV2::LoadLegacyFile() { return NS_ERROR_NOT_IMPLEMENTED; }
 
 nsresult LookupCacheV2::ClearLegacyFile() { return NS_ERROR_NOT_IMPLEMENTED; }
 
 nsCString LookupCacheV2::GetPrefixSetSuffix() const {
   return NS_LITERAL_CSTRING(".vlpset");
 }
 
+// Support creating built-in entries for phsihing, malware, unwanted, harmful,
+// tracking/tracking whitelist and flash block tables.
+//
+nsresult LookupCacheV2::LoadMozEntries() {
+  // We already have the entries, return
+  if (!IsEmpty() || IsPrimed()) {
+    return NS_OK;
+  }
+
+  nsTArray<nsLiteralCString> entries;
+
+  if (mTableName.EqualsLiteral("moztest-phish-simple")) {
+    // Entries for phishing table
+    entries.AppendElement(
+        NS_LITERAL_CSTRING("itisatrap.org/firefox/its-a-trap.html"));
+  } else if (mTableName.EqualsLiteral("moztest-malware-simple")) {
+    // Entries for malware table
+    entries.AppendElement(
+        NS_LITERAL_CSTRING("itisatrap.org/firefox/its-an-attack.html"));
+  } else if (mTableName.EqualsLiteral("moztest-unwanted-simple")) {
+    // Entries for unwanted table
+    entries.AppendElement(
+        NS_LITERAL_CSTRING("itisatrap.org/firefox/unwanted.html"));
+  } else if (mTableName.EqualsLiteral("moztest-harmful-simple")) {
+    // Entries for harmfule tables
+    entries.AppendElement(
+        NS_LITERAL_CSTRING("itisatrap.org/firefox/harmful.html"));
+  } else if (mTableName.EqualsLiteral("moztest-track-simple")) {
+    // Entries for tracking table
+    entries.AppendElement(NS_LITERAL_CSTRING("trackertest.org/"));
+    entries.AppendElement(NS_LITERAL_CSTRING("itisatracker.org/"));
+  } else if (mTableName.EqualsLiteral("moztest-trackwhite-simple")) {
+    // Entries for tracking whitelist table
+    entries.AppendElement(
+        NS_LITERAL_CSTRING("itisatrap.org/?resource=itisatracker.org"));
+  } else if (mTableName.EqualsLiteral("moztest-block-simple")) {
+    // Entries for flash block table
+    entries.AppendElement(
+        NS_LITERAL_CSTRING("itisatrap.org/firefox/blocked.html"));
+  } else {
+    MOZ_ASSERT_UNREACHABLE();
+  }
+
+  AddPrefixArray prefix;
+  AddCompleteArray completes;
+  for (const auto& entry : entries) {
+    AddComplete add;
+    if (NS_FAILED(add.complete.FromPlaintext(entry))) {
+      continue;
+    }
+    completes.AppendElement(add, fallible);
+  }
+
+  return Build(prefix, completes);
+}
+
 }  // namespace safebrowsing
 }  // namespace mozilla
--- a/toolkit/components/url-classifier/LookupCache.h
+++ b/toolkit/components/url-classifier/LookupCache.h
@@ -235,16 +235,18 @@ class LookupCache {
 
   virtual nsresult StoreToFile(nsCOMPtr<nsIFile>& aFile);
   virtual nsresult LoadFromFile(nsCOMPtr<nsIFile>& aFile);
 
   virtual bool IsEmpty() const;
 
   virtual void ClearAll();
 
+  virtual nsresult LoadMozEntries() = 0;
+
   template <typename T>
   static T* Cast(LookupCache* aThat) {
     return ((aThat && T::VER == aThat->Ver()) ? reinterpret_cast<T*>(aThat)
                                               : nullptr);
   }
   template <typename T>
   static const T* Cast(const LookupCache* aThat) {
     return ((aThat && T::VER == aThat->Ver())
@@ -310,16 +312,18 @@ class LookupCacheV2 final : public Looku
                        FallibleTArray<nsCString>& aAddCompletes);
 
   // This will Clear() the passed arrays when done.
   // 'aExpirySec' is used by testcase to config an expired time.
   void AddGethashResultToCache(const AddCompleteArray& aAddCompletes,
                                const MissPrefixArray& aMissPrefixes,
                                int64_t aExpirySec = 0);
 
+  virtual nsresult LoadMozEntries() override;
+
   static const int VER;
   static const uint32_t VLPSET_MAGIC;
   static const uint32_t VLPSET_VERSION;
 
  protected:
   virtual nsCString GetPrefixSetSuffix() const override;
 
  private:
--- a/toolkit/components/url-classifier/LookupCacheV4.cpp
+++ b/toolkit/components/url-classifier/LookupCacheV4.cpp
@@ -565,10 +565,12 @@ bool VLPrefixSet::GetSmallestPrefix(nsAC
 
   if (pick) {
     pick->next();
   }
 
   return pick != nullptr;
 }
 
+nsresult LookupCacheV4::LoadMozEntries() { return NS_ERROR_NOT_IMPLEMENTED; }
+
 }  // namespace safebrowsing
 }  // namespace mozilla
--- a/toolkit/components/url-classifier/LookupCacheV4.h
+++ b/toolkit/components/url-classifier/LookupCacheV4.h
@@ -34,16 +34,18 @@ class LookupCacheV4 final : public Looku
   nsresult ApplyUpdate(RefPtr<TableUpdateV4> aTableUpdate,
                        PrefixStringMap& aInputMap, PrefixStringMap& aOutputMap);
 
   nsresult AddFullHashResponseToCache(const FullHashResponseMap& aResponseMap);
 
   nsresult WriteMetadata(RefPtr<const TableUpdateV4> aTableUpdate);
   nsresult LoadMetadata(nsACString& aState, nsACString& aChecksum);
 
+  virtual nsresult LoadMozEntries() override;
+
   static const int VER;
   static const uint32_t MAX_METADATA_VALUE_LENGTH;
   static const uint32_t VLPSET_MAGIC;
   static const uint32_t VLPSET_VERSION;
 
  protected:
   virtual nsCString GetPrefixSetSuffix() const override;
   nsCString GetMetadataSuffix() const;
--- a/toolkit/components/url-classifier/SafeBrowsing.jsm
+++ b/toolkit/components/url-classifier/SafeBrowsing.jsm
@@ -167,17 +167,16 @@ var SafeBrowsing = {
     }
 
     Services.prefs.addObserver("browser.safebrowsing", this);
     Services.prefs.addObserver("privacy.trackingprotection", this);
     Services.prefs.addObserver("urlclassifier", this);
     Services.prefs.addObserver("plugins.flashBlock.enabled", this);
 
     this.readPrefs();
-    this.addMozEntries();
 
     this.controlUpdateChecking();
     this.initialized = true;
 
     log("init() finished");
   },
 
   registerTableWithURLs(listname) {
@@ -419,93 +418,9 @@ var SafeBrowsing = {
         feature.list.forEach(table => {
           listManager.enableUpdate(table);
         });
       }
     });
 
     listManager.maybeToggleUpdateChecking();
   },
-
-
-  addMozEntries() {
-    // Add test entries to the DB.
-    // XXX bug 779008 - this could be done by DB itself?
-    const phishURL    = "itisatrap.org/firefox/its-a-trap.html";
-    const malwareURL  = "itisatrap.org/firefox/its-an-attack.html";
-    const unwantedURL = "itisatrap.org/firefox/unwanted.html";
-    const harmfulURL  = "itisatrap.org/firefox/harmful.html";
-    const trackerURLs = [
-      "trackertest.org/",
-      "itisatracker.org/",
-    ];
-    const whitelistURL  = "itisatrap.org/?resource=itisatracker.org";
-    const blockedURL    = "itisatrap.org/firefox/blocked.html";
-
-    let update = "n:1000\ni:test-malware-simple\nad:1\n" +
-                 "a:1:32:" + malwareURL.length + "\n" +
-                 malwareURL + "\n";
-    update += "n:1000\ni:test-phish-simple\nad:1\n" +
-              "a:1:32:" + phishURL.length + "\n" +
-              phishURL + "\n";
-    update += "n:1000\ni:test-unwanted-simple\nad:1\n" +
-              "a:1:32:" + unwantedURL.length + "\n" +
-              unwantedURL + "\n";
-    update += "n:1000\ni:test-harmful-simple\nad:1\n" +
-              "a:1:32:" + harmfulURL.length + "\n" +
-              harmfulURL + "\n";
-    update += "n:1000\ni:test-track-simple\n" +
-              "ad:" + trackerURLs.length + "\n";
-    trackerURLs.forEach((trackerURL, i) => {
-      update += "a:" + (i + 1) + ":32:" + trackerURL.length + "\n" +
-                trackerURL + "\n";
-    });
-    update += "n:1000\ni:test-trackwhite-simple\nad:1\n" +
-              "a:1:32:" + whitelistURL.length + "\n" +
-              whitelistURL;
-    update += "n:1000\ni:test-block-simple\nad:1\n" +
-              "a:1:32:" + blockedURL.length + "\n" +
-              blockedURL;
-    log("addMozEntries:", update);
-
-    let db = Cc["@mozilla.org/url-classifier/dbservice;1"].
-             getService(Ci.nsIUrlClassifierDBService);
-
-    // nsIUrlClassifierUpdateObserver
-    let dummyListener = {
-      updateUrlRequested() { },
-      streamFinished() { },
-      // We notify observers when we're done in order to be able to make perf
-      // test results more consistent
-      updateError() {
-        Services.obs.notifyObservers(db, "mozentries-update-finished", "error");
-      },
-      updateSuccess() {
-        Services.obs.notifyObservers(db, "mozentries-update-finished", "success");
-      },
-    };
-
-    try {
-      let tables = "test-malware-simple,test-phish-simple,test-unwanted-simple,test-harmful-simple,test-track-simple,test-trackwhite-simple,test-block-simple";
-      db.beginUpdate(dummyListener, tables, "");
-      db.beginStream("", "");
-      db.updateStream(update);
-      db.finishStream();
-      db.finishUpdate();
-    } catch (ex) {
-      // beginUpdate will throw harmlessly if there's an existing update in progress, ignore failures.
-      log("addMozEntries failed!", ex);
-      Services.obs.notifyObservers(db, "mozentries-update-finished", "exception");
-    }
-  },
-
-  addMozEntriesFinishedPromise: new Promise(resolve => {
-    let finished = (subject, topic, data) => {
-      Services.obs.removeObserver(finished, "mozentries-update-finished");
-      if (data == "error") {
-        Cu.reportError("addMozEntries failed to update the db!");
-      }
-      resolve();
-    };
-    Services.obs.addObserver(finished, "mozentries-update-finished");
-  }),
-
 };
--- a/toolkit/components/url-classifier/UrlClassifierListManager.jsm
+++ b/toolkit/components/url-classifier/UrlClassifierListManager.jsm
@@ -58,16 +58,20 @@ this.PROT_ListManager = function PROT_Li
   this.needsUpdate_ = {};
 
   // A map of updateUrls to single-use nsITimer. An entry exists if and only if
   // there is at least one table with updates enabled for that url. nsITimers
   // are reset when enabling/disabling updates or on update callbacks (update
   // success, update failure, download error).
   this.updateCheckers_ = {};
   this.requestBackoffs_ = {};
+
+  // This is only used by testcases to ensure SafeBrowsing.jsm is inited
+  this.registered = false;
+
   this.dbService_ = Cc["@mozilla.org/url-classifier/dbservice;1"]
                    .getService(Ci.nsIUrlClassifierDBService);
 
   Services.obs.addObserver(this, "quit-application");
   Services.prefs.addObserver(PREF_DEBUG_ENABLED, this);
 };
 
 /**
@@ -76,16 +80,18 @@ this.PROT_ListManager = function PROT_Li
  * @param updateUrl - the url for updating the table
  * @param gethashUrl - the url for fetching hash completions
  * @returns true if the table could be created; false otherwise
  */
 PROT_ListManager.prototype.registerTable = function(tableName,
                                                     providerName,
                                                     updateUrl,
                                                     gethashUrl) {
+  this.registered = true;
+
   this.tablesData[tableName] = {};
   if (!updateUrl) {
     log("Can't register table " + tableName + " without updateUrl");
     return false;
   }
   log("registering " + tableName + " with " + updateUrl);
   this.tablesData[tableName].updateUrl = updateUrl;
   this.tablesData[tableName].gethashUrl = gethashUrl;
@@ -173,16 +179,20 @@ PROT_ListManager.prototype.getUpdateUrl 
 PROT_ListManager.prototype.enableUpdate = function(tableName) {
   var table = this.tablesData[tableName];
   if (table) {
     log("Enabling table updates for " + tableName);
     this.needsUpdate_[table.updateUrl][tableName] = true;
   }
 };
 
+PROT_ListManager.prototype.isRegistered = function() {
+  return this.registered;
+};
+
 /**
  * Returns true if any table associated with the updateUrl requires updates.
  * @param updateUrl - the updateUrl
  */
 PROT_ListManager.prototype.updatesNeeded_ = function(updateUrl) {
   let updatesNeeded = false;
   for (var tableName in this.needsUpdate_[updateUrl]) {
     if (this.needsUpdate_[updateUrl][tableName]) {
--- a/toolkit/components/url-classifier/nsIUrlListManager.idl
+++ b/toolkit/components/url-classifier/nsIUrlListManager.idl
@@ -80,9 +80,15 @@ interface nsIUrlListManager : nsISupport
     boolean forceUpdates(in ACString tableNames);
 
     /**
      * This is currently used by about:url-classifier to get back-off time
      * (in millisecond since epoch) for the given provider. Return 0 if we
      * are not in back-off mode.
      */
     uint64_t getBackOffTime(in ACString provider);
+
+    /**
+     * Return true if someone registers a table, this is used by testcase
+     * to figure out it SafeBrowsing.jsm is initialized.
+     */
+    boolean isRegistered();
 };
--- a/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierDBService.cpp
@@ -1223,17 +1223,17 @@ nsUrlClassifierLookupCallback::LookupCom
       NS_ENSURE_SUCCESS(rv, rv);
       LOG(("The match from %s needs to be completed at %s",
            result->mTableName.get(), gethashUrl.get()));
       // gethashUrls may be empty in 2 cases: test tables, and on startup where
       // we may have found a prefix in an existing table before the listmanager
       // has registered the table. In the second case we should not call
       // complete.
       if ((!gethashUrl.IsEmpty() ||
-           StringBeginsWith(result->mTableName, NS_LITERAL_CSTRING("test"))) &&
+           nsUrlClassifierUtils::IsTestTable(result->mTableName)) &&
           mDBService->GetCompleter(result->mTableName,
                                    getter_AddRefs(completer))) {
         // Bug 1323953 - Send the first 4 bytes for completion no matter how
         // long we matched the prefix.
         nsresult rv = completer->Complete(result->PartialHash(), gethashUrl,
                                           result->mTableName, this);
         if (NS_SUCCEEDED(rv)) {
           mPendingCompletions++;
--- a/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp
+++ b/toolkit/components/url-classifier/nsUrlClassifierUtils.cpp
@@ -301,19 +301,22 @@ static const struct {
     // For application reputation
     {"goog-badbinurl-proto", MALICIOUS_BINARY},            // 7
     {"goog-downloadwhite-proto", CSD_DOWNLOAD_WHITELIST},  // 9
 
     // For login reputation
     {"goog-passwordwhite-proto", CSD_WHITELIST},  // 8
 
     // For testing purpose.
-    {"test-phish-proto", SOCIAL_ENGINEERING_PUBLIC},  // 2
-    {"test-unwanted-proto", UNWANTED_SOFTWARE},       // 3
-    {"test-passwordwhite-proto", CSD_WHITELIST},      // 8
+    {"moztest-phish-proto", SOCIAL_ENGINEERING_PUBLIC},  // 2
+    {"test-phish-proto", SOCIAL_ENGINEERING_PUBLIC},     // 2
+    {"moztest-unwanted-proto", UNWANTED_SOFTWARE},       // 3
+    {"test-unwanted-proto", UNWANTED_SOFTWARE},          // 3
+    {"moztest-passwordwhite-proto", CSD_WHITELIST},      // 8
+    {"test-passwordwhite-proto", CSD_WHITELIST},         // 8
 };
 
 NS_IMETHODIMP
 nsUrlClassifierUtils::ConvertThreatTypeToListNames(uint32_t aThreatType,
                                                    nsACString& aListNames) {
   for (uint32_t i = 0; i < ArrayLength(THREAT_TYPE_CONV_TABLE); i++) {
     if (aThreatType == THREAT_TYPE_CONV_TABLE[i].mThreatType) {
       if (!aListNames.IsEmpty()) {
@@ -339,17 +342,18 @@ nsUrlClassifierUtils::ConvertListNameToT
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsUrlClassifierUtils::GetProvider(const nsACString& aTableName,
                                   nsACString& aProvider) {
   MutexAutoLock lock(mProviderDictLock);
   nsCString* provider = nullptr;
-  if (StringBeginsWith(aTableName, NS_LITERAL_CSTRING("test"))) {
+
+  if (IsTestTable(aTableName)) {
     aProvider = NS_LITERAL_CSTRING(TESTING_TABLE_PROVIDER_NAME);
   } else if (mProviderDict.Get(aTableName, &provider)) {
     aProvider = provider ? *provider : EmptyCString();
   } else {
     aProvider = EmptyCString();
   }
   return NS_OK;
 }
@@ -1082,8 +1086,23 @@ bool nsUrlClassifierUtils::SpecialEncode
     curChar++;
   }
   return changed;
 }
 
 bool nsUrlClassifierUtils::ShouldURLEscape(const unsigned char c) const {
   return c <= 32 || c == '%' || c >= 127;
 }
+
+// moztest- tables are built-in created in LookupCache, they contain hardcoded
+// url entries in it. moztest tables don't support updates.
+// static
+bool nsUrlClassifierUtils::IsMozTestTable(const nsACString& aTableName) {
+  return StringBeginsWith(aTableName, NS_LITERAL_CSTRING("moztest-"));
+}
+
+// test- tables are used by testcases and can add custom test entries
+// through update API.
+// static
+bool nsUrlClassifierUtils::IsTestTable(const nsACString& aTableName) {
+  return IsMozTestTable(aTableName) ||
+         StringBeginsWith(aTableName, NS_LITERAL_CSTRING("test"));
+}
--- a/toolkit/components/url-classifier/nsUrlClassifierUtils.h
+++ b/toolkit/components/url-classifier/nsUrlClassifierUtils.h
@@ -37,16 +37,20 @@ class nsUrlClassifierUtils final : publi
   // ret != url.
   bool SpecialEncode(const nsACString& url, bool foldSlashes,
                      nsACString& _retval);
 
   void ParseIPAddress(const nsACString& host, nsACString& _retval);
   void CanonicalNum(const nsACString& num, uint32_t bytes, bool allowOctal,
                     nsACString& _retval);
 
+  static bool IsMozTestTable(const nsACString& aTableName);
+
+  static bool IsTestTable(const nsACString& aTableName);
+
  private:
   nsUrlClassifierUtils();
   ~nsUrlClassifierUtils();
 
   nsresult Init();
 
   // Disallow copy constructor
   nsUrlClassifierUtils(const nsUrlClassifierUtils&);
--- a/toolkit/components/url-classifier/tests/browser/classifierHelper.js
+++ b/toolkit/components/url-classifier/tests/browser/classifierHelper.js
@@ -4,16 +4,18 @@
 
 // Created from toolkit/components/url-classifier/tests/mochitest/classifierHelper.js
 // Unfortunately, browser tests cannot load that script as it is too reliant on
 // being loaded in the content process.
 
 
 let dbService = Cc["@mozilla.org/url-classifier/dbservice;1"]
                 .getService(Ci.nsIUrlClassifierDBService);
+let listmanager = Cc["@mozilla.org/url-classifier/listmanager;1"].
+                    getService(Ci.nsIUrlListManager);
 
 if (typeof(classifierHelper) == "undefined") {
   var classifierHelper = {};
 }
 
 const HASHLEN = 32;
 
 const PREFS = {
@@ -29,37 +31,26 @@ classifierHelper._curAddChunkNum = 1;
 classifierHelper._updatesToCleanup = [];
 
 // This function returns a Promise resolved when SafeBrowsing.jsm is initialized.
 // SafeBrowsing.jsm is initialized after mozEntries are added. Add observer
 // to receive "finished" event. For the case when this function is called
 // after the event had already been notified, we lookup entries to see if
 // they are already added to database.
 classifierHelper.waitForInit = function() {
-  // This url must sync with the table, url in SafeBrowsing.jsm addMozEntries
-  const table = "test-phish-simple";
-  const url = "http://itisatrap.org/firefox/its-a-trap.html";
-  let principal = Services.scriptSecurityManager.createCodebasePrincipal(
-    Services.io.newURI(url), {});
-
   return new Promise(function(resolve, reject) {
-    Services.obs.addObserver(function() {
-      resolve();
-    }, "mozentries-update-finished");
+    function checkForInit() {
+      if (listmanager.isRegistered()) {
+        resolve();
+      } else {
+        setTimeout(() => { checkForInit(); }, 1000);
+      }
+    }
 
-    let listener = {
-      QueryInterface: ChromeUtils.generateQI(["nsIUrlClassifierUpdateObserver"]),
-
-      handleEvent(value) {
-        if (value === table) {
-          resolve();
-        }
-      },
-    };
-    dbService.lookup(principal, table, listener);
+    checkForInit();
   });
 };
 
 // This function is used to allow completion for specific "list",
 // some lists like "test-malware-simple" is default disabled to ask for complete.
 // "list" is the db we would like to allow it
 // "url" is the completion server
 classifierHelper.allowCompletion = function(lists, url) {
--- a/toolkit/components/url-classifier/tests/gtest/TestFailUpdate.cpp
+++ b/toolkit/components/url-classifier/tests/gtest/TestFailUpdate.cpp
@@ -2,17 +2,17 @@
 #include "nsPrintfCString.h"
 #include "string.h"
 #include "gtest/gtest.h"
 #include "mozilla/Unused.h"
 
 using namespace mozilla;
 using namespace mozilla::safebrowsing;
 
-static const char* kFilesInV2[] = {".pset", ".sbstore"};
+static const char* kFilesInV2[] = {".vlpset", ".sbstore"};
 static const char* kFilesInV4[] = {".vlpset", ".metadata"};
 
 #define V2_TABLE "gtest-malware-simple"
 #define V4_TABLE1 "goog-malware-proto"
 #define V4_TABLE2 "goog-phish-proto"
 
 #define ROOT_DIR NS_LITERAL_STRING("safebrowsing")
 #define SB_FILE(x, y) NS_ConvertUTF8toUTF16(nsPrintfCString("%s%s", x, y))
@@ -40,17 +40,17 @@ TEST(UrlClassifierFailUpdate, CheckTable
   // Apply V2 update
   {
     RefPtr<TableUpdateV2> update =
         new TableUpdateV2(NS_LITERAL_CSTRING(V2_TABLE));
     Unused << update->NewAddChunk(1);
 
     ApplyUpdate(update);
 
-    // A successful V2 update should create .pset & .sbstore files
+    // A successful V2 update should create .vlpset & .sbstore files
     CheckFileExist(V2_TABLE, kFilesInV2, true);
   }
 
   // Helper function to generate table update data
   auto func = [](RefPtr<TableUpdateV4> update, bool full, const char* str) {
     update->SetFullUpdate(full);
     nsCString prefix(str);
     update->NewPrefixes(prefix.Length(), prefix);
--- a/toolkit/components/url-classifier/tests/gtest/TestFindFullHash.cpp
+++ b/toolkit/components/url-classifier/tests/gtest/TestFindFullHash.cpp
@@ -12,18 +12,18 @@ void ToBase64EncodedStringArray(nsCStrin
                                 nsTArray<nsCString>& aEncodedArray);
 }  // end of unnamed namespace.
 
 TEST(UrlClassifierFindFullHash, Request)
 {
   nsUrlClassifierUtils* urlUtil = nsUrlClassifierUtils::GetInstance();
 
   nsTArray<nsCString> listNames;
-  listNames.AppendElement("test-phish-proto");
-  listNames.AppendElement("test-unwanted-proto");
+  listNames.AppendElement("moztest-phish-proto");
+  listNames.AppendElement("moztest-unwanted-proto");
 
   nsCString listStates[] = {nsCString("sta\x00te1", 7),
                             nsCString("sta\x00te2", 7)};
   nsTArray<nsCString> listStateArray;
   ToBase64EncodedStringArray(listStates, listStateArray);
 
   nsCString prefixes[] = {nsCString("\x00\x00\x00\x01", 4),
                           nsCString("\x00\x00\x00\x00\x01", 5),
--- a/toolkit/components/url-classifier/tests/mochitest/classifierCommon.js
+++ b/toolkit/components/url-classifier/tests/mochitest/classifierCommon.js
@@ -2,16 +2,18 @@
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /* eslint-env mozilla/frame-script */
 
 const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 var dbService = Cc["@mozilla.org/url-classifier/dbservice;1"]
                 .getService(Ci.nsIUrlClassifierDBService);
+var listmanager = Cc["@mozilla.org/url-classifier/listmanager;1"].
+                    getService(Ci.nsIUrlListManager);
 
 var timer;
 function setTimeout(callback, delay) {
   timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
   timer.initWithCallback({ notify: callback },
                            delay,
                            Ci.nsITimer.TYPE_ONE_SHOT);
 }
@@ -51,37 +53,21 @@ function doReload() {
   }
 }
 
 // SafeBrowsing.jsm is initialized after mozEntries are added. Add observer
 // to receive "finished" event. For the case when this function is called
 // after the event had already been notified, we lookup entries to see if
 // they are already added to database.
 function waitForInit() {
-  Services.obs.addObserver(function() {
+  if (listmanager.isRegistered()) {
     sendAsyncMessage("safeBrowsingInited");
-  }, "mozentries-update-finished");
-
-  // This url must sync with the table, url in SafeBrowsing.jsm addMozEntries
-  const table = "test-phish-simple";
-  const url = "http://itisatrap.org/firefox/its-a-trap.html";
-
-  let principal = Services.scriptSecurityManager.createCodebasePrincipal(
-    Services.io.newURI(url), {});
-
-  let listener = {
-    QueryInterface: ChromeUtils.generateQI(["nsIUrlClassifierUpdateObserver"]),
-
-    handleEvent(value) {
-      if (value === table) {
-        sendAsyncMessage("safeBrowsingInited");
-      }
-    },
-  };
-  dbService.lookup(principal, table, listener);
+  } else {
+    setTimeout(() => { waitForInit(); }, 1000);
+  }
 }
 
 addMessageListener("doUpdate", ({ testUpdate }) => {
   doUpdate(testUpdate);
 });
 
 addMessageListener("doReload", () => {
   doReload();
--- a/toolkit/components/url-classifier/tests/mochitest/test_allowlisted_annotations.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_allowlisted_annotations.html
@@ -28,17 +28,17 @@ function clearPermissions() {
   SpecialPowers.removePermission("trackingprotection",
                                  { url: "https://allowlisted.example.com" });
   ok(!SpecialPowers.testPermission("trackingprotection",
                                    Ci.nsIPermissionManager.ALLOW_ACTION,
                                    { url: "https://allowlisted.example.com" }));
 }
 
 SpecialPowers.pushPrefEnv(
-  {"set": [["urlclassifier.trackingTable", "test-track-simple"],
+  {"set": [["urlclassifier.trackingTable", "moztest-track-simple"],
            ["privacy.trackingprotection.enabled", true],
            ["channelclassifier.allowlist_example", true]]},
   test);
 
 function test() {
   SimpleTest.registerCleanupFunction(UrlClassifierTestUtils.cleanupTestTrackers);
   UrlClassifierTestUtils.addTestTrackers().then(() => {
     document.getElementById("testFrame").src = "allowlistAnnotatedFrame.html";
--- a/toolkit/components/url-classifier/tests/mochitest/test_bug1254766.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_bug1254766.html
@@ -10,21 +10,21 @@
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 
 <script src="head.js"></script>
 <script class="testbody" type="text/javascript">
-const MALWARE_LIST = "test-malware-simple";
+const MALWARE_LIST = "mochi-malware-simple";
 const MALWARE_HOST1 = "malware.example.com/";
 const MALWARE_HOST2 = "test1.example.com/";
 
-const UNWANTED_LIST = "test-unwanted-simple";
+const UNWANTED_LIST = "mochi-unwanted-simple";
 const UNWANTED_HOST1 = "unwanted.example.com/";
 const UNWANTED_HOST2 = "test2.example.com/";
 
 
 const UNUSED_MALWARE_HOST = "unused.malware.com/";
 const UNUSED_UNWANTED_HOST = "unused.unwanted.com/";
 
 const GETHASH_URL =
@@ -243,16 +243,17 @@ function runTest() {
 
 SimpleTest.waitForExplicitFinish();
 
 // 'network.predictor.enabled' is disabled because if other testcase load
 // evil.js, evil.css ...etc resources, it may cause we load them from cache
 // directly and bypass classifier check
 SpecialPowers.pushPrefEnv({"set": [
   ["browser.safebrowsing.malware.enabled", true],
+  ["urlclassifier.malwareTable", "mochi-malware-simple,mochi-unwanted-simple"],
   ["network.predictor.enabled", false],
   ["urlclassifier.gethash.timeout_ms", 30000],
 ]}, runTest);
 
 </script>
 </pre>
 </body>
 </html>
--- a/toolkit/components/url-classifier/tests/mochitest/test_cachemiss.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_cachemiss.html
@@ -149,16 +149,17 @@ function runTest() {
 
 SimpleTest.waitForExplicitFinish();
 
 // 'network.predictor.enabled' is disabled because if other testcase load
 // evil.js, evil.css ...etc resources, it may cause we load them from cache
 // directly and bypass classifier check
 SpecialPowers.pushPrefEnv({"set": [
   ["browser.safebrowsing.malware.enabled", true],
+  ["urlclassifier.malwareTable", "test-malware-simple,test-unwanted-simple"],
   ["network.predictor.enabled", false],
   ["urlclassifier.gethash.timeout_ms", 30000],
 ]}, runTest);
 
 </script>
 </pre>
 </body>
 </html>
--- a/toolkit/components/url-classifier/tests/mochitest/test_classified_annotations.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_classified_annotations.html
@@ -131,17 +131,17 @@ function checkLoads(aWindow, aData) {
 function cleanup() {
   SpecialPowers.clearUserPref("privacy.trackingprotection.enabled");
   SpecialPowers.clearUserPref("channelclassifier.allowlist_example");
 
   UrlClassifierTestUtils.cleanupTestTrackers();
 }
 
 SpecialPowers.pushPrefEnv(
-  {"set": [["urlclassifier.trackingTable", "test-track-simple"]]},
+  {"set": [["urlclassifier.trackingTable", "moztest-track-simple"]]},
   test);
 
 async function test() {
   SimpleTest.registerCleanupFunction(cleanup);
   await UrlClassifierTestUtils.addTestTrackers();
 
   await SpecialPowers.setBoolPref("privacy.trackingprotection.enabled", true);
   // Make sure chrome:// URIs are processed. This does not white-list
--- a/toolkit/components/url-classifier/tests/mochitest/test_classifier.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_classifier.html
@@ -48,17 +48,17 @@ var testURLs = [
     table: "test-malware-simple",
     result: Cr.NS_ERROR_MALWARE_URI,
   },
   { url: "http://unwanted.example.com",
     table: "test-unwanted-simple",
     result: Cr.NS_ERROR_UNWANTED_URI,
   },
   { url: "http://itisatrap.org/firefox/its-a-trap.html",
-    table: "test-phish-simple",
+    table: "moztest-phish-simple",
     result: Cr.NS_ERROR_PHISHING_URI,
   },
   { url: "http://harmful.example.com",
     table: "test-harmful-simple",
     result: Cr.NS_ERROR_HARMFUL_URI,
   },
   { url: "http://blocked.example.com",
     table: "test-block-simple",
@@ -87,17 +87,17 @@ function updateError(errorCode) {
 function testService() {
   return new Promise(resolve => {
     function runNextTest() {
       if (!testURLs.length) {
         resolve();
         return;
       }
       let test = testURLs.shift();
-      let tables = "test-malware-simple,test-unwanted-simple,test-phish-simple,test-block-simple,test-harmful-simple";
+      let tables = "test-malware-simple,test-unwanted-simple,moztest-phish-simple,test-block-simple,test-harmful-simple";
       let uri = SpecialPowers.Services.io.newURI(test.url);
       let prin = SpecialPowers.Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
       SpecialPowers.doUrlClassify(prin, null, function(errorCode) {
         is(errorCode, test.result,
            `Successful asynchronous classification of ${test.url}`);
         SpecialPowers.doUrlClassifyLocal(uri, tables, function(results) {
           if (results.length == 0) {
             is(test.table, "",
@@ -112,18 +112,17 @@ function testService() {
       });
     }
     runNextTest(resolve);
   });
 }
 
 SpecialPowers.pushPrefEnv(
   {"set": [["urlclassifier.malwareTable", "test-malware-simple,test-unwanted-simple,test-harmful-simple"],
-           ["urlclassifier.phishTable", "test-phish-simple"],
-           ["urlclassifier.downloadBlockTable", "test-block-simple"],
+           ["urlclassifier.blockedTable", "test-block-simple"],
            ["browser.safebrowsing.debug", true]]},
   function() {
     classifierHelper.waitForInit()
       .then(() => classifierHelper.addUrlToDB(testData))
       .then(updateSuccess)
       .catch(err => {
         updateError(err);
       })
--- a/toolkit/components/url-classifier/tests/mochitest/test_classifier_worker.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_classifier_worker.html
@@ -46,18 +46,17 @@ function updateSuccess() {
 
 function updateError(errorCode) {
   ok(false, "Couldn't update classifier. Error code: " + errorCode);
   // Abort test.
   SimpleTest.finish();
 }
 
 SpecialPowers.pushPrefEnv(
-  {"set": [["urlclassifier.malwareTable", "test-malware-simple,test-unwanted-simple"],
-           ["urlclassifier.phishTable", "test-phish-simple"]]},
+  {"set": [["urlclassifier.malwareTable", "test-malware-simple,test-unwanted-simple"]]},
   function() {
     classifierHelper.waitForInit()
       .then(() => classifierHelper.addUrlToDB(testData))
       .then(updateSuccess)
       .catch(err => {
         updateError(err);
       });
   });
--- a/toolkit/components/url-classifier/tests/mochitest/test_classify_ping.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_classify_ping.html
@@ -18,22 +18,16 @@
 
   const timeout = 200;
   const host_nottrack = "http://not-tracking.example.com/";
   const host_track = "http://trackertest.org/";
   const path_ping = "tests/toolkit/components/url-classifier/tests/mochitest/ping.sjs";
   const TP_ENABLE_PREF = "privacy.trackingprotection.enabled";
   const RETRY_TIMEOUT_MS = 200;
 
-  var testData = [
-    { url: "trackertest.org/",
-      db: "test-track-simple",
-    },
-  ];
-
   function testPingNonBlacklist() {
     SpecialPowers.setBoolPref(TP_ENABLE_PREF, true);
 
     var msg = "ping should reach page not in blacklist";
     var expectPing = true;
     var id = "1111";
     ping(id, host_nottrack);
 
@@ -109,31 +103,29 @@
   }
 
   function cleanup() {
     SpecialPowers.clearUserPref(TP_ENABLE_PREF);
   }
 
   function runTest() {
     classifierHelper.waitForInit()
-      .then(() => classifierHelper.addUrlToDB(testData))
       .then(testPingNonBlacklist)
       .then(testPingBlacklistSafebrowsingOff)
       .then(testPingBlacklistSafebrowsingOn)
       .then(function() {
         SimpleTest.finish();
       }).catch(function(e) {
         ok(false, "Some test failed with error " + e);
         SimpleTest.finish();
       });
   }
 
   SimpleTest.waitForExplicitFinish();
   SimpleTest.registerCleanupFunction(cleanup);
   SpecialPowers.pushPrefEnv({"set": [
     ["browser.send_pings", true],
-    ["urlclassifier.trackingTable", "test-track-simple"],
   ]}, runTest);
 
 </script>
 </pre>
 </body>
 </html>
--- a/toolkit/components/url-classifier/tests/mochitest/test_gethash.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_gethash.html
@@ -102,16 +102,17 @@ function runTest() {
 
 SimpleTest.waitForExplicitFinish();
 
 // 'network.predictor.enabled' is disabled because if other testcase load
 // evil.js, evil.css ...etc resources, it may cause we load them from cache
 // directly and bypass classifier check
 SpecialPowers.pushPrefEnv({"set": [
   ["browser.safebrowsing.malware.enabled", true],
+  ["urlclassifier.malwareTable", "test-malware-simple,test-unwanted-simple"],
   ["network.predictor.enabled", false],
   ["urlclassifier.gethash.timeout_ms", 30000],
 ]}, runTest);
 
 </script>
 </pre>
 </body>
 </html>
--- a/toolkit/components/url-classifier/tests/mochitest/test_safebrowsing_bug1272239.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_safebrowsing_bug1272239.html
@@ -62,17 +62,17 @@ var listmanager = Cc["@mozilla.org/url-c
 
 let googleKey = SpecialPowers.Services.urlFormatter.formatURL("%GOOGLE_SAFEBROWSING_API_KEY%").trim();
 
 for (let list of lists) {
   if (!list)
     continue;
 
   // For lists having a provider, it should have a correct gethash url
-  // For lists without a provider, for example, test-malware-simple, it should not
+  // For lists without a provider, for example, moztest-malware-simple, it should not
   // have a gethash url.
   var url = listmanager.getGethashUrl(list);
   var index = listsWithProvider.indexOf(list);
   if (index >= 0) {
     let provider = listsToProvider[index];
     let pref = "browser.safebrowsing.provider." + provider + ".gethashURL";
     if ((provider == "google" || provider == "google4") &&
         (!googleKey || googleKey == "no-google-safebrowsing-api-key")) {
--- a/toolkit/components/url-classifier/tests/mochitest/test_trackingprotection_bug1157081.html
+++ b/toolkit/components/url-classifier/tests/mochitest/test_trackingprotection_bug1157081.html
@@ -56,17 +56,17 @@ var badids = [
 ];
 
 function checkLoads(aWindow, aBlocked) {
   var win = aWindow.content;
   is(win.document.getElementById("badscript").dataset.touched, aBlocked ? "no" : "yes", "Should not load tracking javascript");
 }
 
 SpecialPowers.pushPrefEnv(
-  {"set": [["urlclassifier.trackingTable", "test-track-simple"],
+  {"set": [["urlclassifier.trackingTable", "moztest-track-simple"],
            ["privacy.trackingprotection.enabled", true],
            ["browser.safebrowsing.malware.enabled", false],
            ["browser.safebrowsing.phishing.enabled", false],
            ["channelclassifier.allowlist_example", true]]},
   test);
 
 function test() {
   SimpleTest.registerCleanupFunction(UrlClassifierTestUtils.cleanupTestTrackers);
--- a/toolkit/components/url-classifier/tests/unit/head_urlclassifier.js
+++ b/toolkit/components/url-classifier/tests/unit/head_urlclassifier.js
@@ -18,16 +18,23 @@ Cc["@mozilla.org/psm;1"].getService(Ci.n
 Services.prefs.setIntPref("urlclassifier.gethashnoise", 0);
 
 // Enable malware/phishing checking for tests
 Services.prefs.setBoolPref("browser.safebrowsing.malware.enabled", true);
 Services.prefs.setBoolPref("browser.safebrowsing.blockedURIs.enabled", true);
 Services.prefs.setBoolPref("browser.safebrowsing.phishing.enabled", true);
 Services.prefs.setBoolPref("browser.safebrowsing.provider.test.disableBackoff", true);
 
+// Add testing tables, we don't use moztest-* here because it doesn't support update
+Services.prefs.setCharPref("urlclassifier.phishTable", "test-phish-simple");
+Services.prefs.setCharPref("urlclassifier.malwareTable", "test-harmful-simple,test-malware-simple,test-unwanted-simple");
+Services.prefs.setCharPref("urlclassifier.blockedTable", "test-block-simple");
+Services.prefs.setCharPref("urlclassifier.trackingTable", "test-track-simple");
+Services.prefs.setCharPref("urlclassifier.trackingWhitelistTable", "test-trackwhite-simple");
+
 // Enable all completions for tests
 Services.prefs.setCharPref("urlclassifier.disallow_completions", "");
 
 // Hash completion timeout
 Services.prefs.setIntPref("urlclassifier.gethash.timeout_ms", 5000);
 
 function delFile(name) {
   try {
--- a/toolkit/components/url-classifier/tests/unit/test_threat_type_conversion.js
+++ b/toolkit/components/url-classifier/tests/unit/test_threat_type_conversion.js
@@ -4,33 +4,39 @@ function run_test() {
 
   // Test list name to threat type conversion.
 
   equal(urlUtils.convertListNameToThreatType("goog-malware-proto"), 1);
   equal(urlUtils.convertListNameToThreatType("googpub-phish-proto"), 2);
   equal(urlUtils.convertListNameToThreatType("goog-unwanted-proto"), 3);
   equal(urlUtils.convertListNameToThreatType("goog-harmful-proto"), 4);
   equal(urlUtils.convertListNameToThreatType("goog-phish-proto"), 5);
+  equal(urlUtils.convertListNameToThreatType("goog-badbinurl-proto"), 7);
+  equal(urlUtils.convertListNameToThreatType("goog-passwordwhite-proto"), 8);
+  equal(urlUtils.convertListNameToThreatType("goog-downloadwhite-proto"), 9);
 
   try {
     urlUtils.convertListNameToThreatType("bad-list-name");
     ok(false, "Bad list name should lead to exception.");
   } catch (e) {}
 
   try {
     urlUtils.convertListNameToThreatType("bad-list-name");
     ok(false, "Bad list name should lead to exception.");
   } catch (e) {}
 
   // Test threat type to list name conversion.
   equal(urlUtils.convertThreatTypeToListNames(1), "goog-malware-proto");
-  equal(urlUtils.convertThreatTypeToListNames(2), "googpub-phish-proto,test-phish-proto");
-  equal(urlUtils.convertThreatTypeToListNames(3), "goog-unwanted-proto,test-unwanted-proto");
+  equal(urlUtils.convertThreatTypeToListNames(2), "googpub-phish-proto,moztest-phish-proto,test-phish-proto");
+  equal(urlUtils.convertThreatTypeToListNames(3), "goog-unwanted-proto,moztest-unwanted-proto,test-unwanted-proto");
   equal(urlUtils.convertThreatTypeToListNames(4), "goog-harmful-proto");
   equal(urlUtils.convertThreatTypeToListNames(5), "goog-phish-proto");
+  equal(urlUtils.convertThreatTypeToListNames(7), "goog-badbinurl-proto");
+  equal(urlUtils.convertThreatTypeToListNames(8), "goog-passwordwhite-proto,moztest-passwordwhite-proto,test-passwordwhite-proto");
+  equal(urlUtils.convertThreatTypeToListNames(9), "goog-downloadwhite-proto");
 
   try {
     urlUtils.convertThreatTypeToListNames(0);
     ok(false, "Bad threat type should lead to exception.");
   } catch (e) {}
 
   try {
     urlUtils.convertThreatTypeToListNames(100);